CurveLPPessimisticFeed

Description:

ERC20 token contract with Mintable, Burnable, Factory, Oracle capabilities. Standard implementation for fungible tokens on Ethereum.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "src/feeds/CurveLPPessimisticFeed.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import {ICurvePool} from "src/interfaces/ICurvePool.sol";
import {IChainlinkBasePriceFeed} from "src/interfaces/IChainlinkFeed.sol";
import {IERC20} from "src/interfaces/IERC20.sol";

contract CurveLPPessimisticFeed {
    ICurvePool public immutable curvePool;

    IChainlinkBasePriceFeed public immutable coin1Feed;
    IChainlinkBasePriceFeed public immutable coin2Feed;

    string public description;

    constructor(
        address _curvePool,
        address _coin1Feed,
        address _coin2Feed,
        bool _oldCurveImpl
    ) {
        curvePool = ICurvePool(_curvePool);
        coin1Feed = IChainlinkBasePriceFeed(_coin1Feed);
        coin2Feed = IChainlinkBasePriceFeed(_coin2Feed);
        require(
            coin1Feed.decimals() == coin2Feed.decimals() &&
                coin1Feed.decimals() == 18,
            "CurveLPPessimisticFeed: DECIMALS_MISMATCH"
        );
        if (_oldCurveImpl)
            description = string(
                abi.encodePacked(
                    IERC20(curvePool.lp_token()).symbol(),
                    " / USD"
                )
            );
        else
            description = string(
                abi.encodePacked(curvePool.symbol(), " / USD")
            );
    }

    /**
     * @return roundId The round ID of the Chainlink price feed
     * @return minLpUsdprice The latest LP token price in USD
     * @return startedAt The timestamp when the latest round of Chainlink price feed started
     * @return updatedAt The timestamp when the latest round of Chainlink price feed was updated
     * @return answeredInRound The round ID in which the answer was computed
     */
    function latestRoundData()
        public
        view
        returns (uint80, int256, uint256, uint256, uint80)
    {
        (
            uint80 roundId,
            int256 usdPriceCoin1,
            uint startedAt,
            uint updatedAt,
            uint80 answeredInRound
        ) = coin1Feed.latestRoundData();

        (
            uint80 roundIdCoin2,
            int256 usdPriceCoin2,
            uint startedAtCoin2,
            uint updatedAtCoin2,
            uint80 answeredInRoundCoin2
        ) = coin2Feed.latestRoundData();

        int256 minLpUsdPrice;

        // If coin1 price is lower than coin2 price, use coin1 price
        if (usdPriceCoin1 < usdPriceCoin2) {
            minLpUsdPrice =
                (usdPriceCoin1 * int256(curvePool.get_virtual_price())) /
                int256(10 ** decimals());
        } else {
            minLpUsdPrice =
                (usdPriceCoin2 * int(curvePool.get_virtual_price())) /
                int256(10 ** decimals());
        }
        if (updatedAtCoin2 < updatedAt) {
            roundId = roundIdCoin2;
            startedAt = startedAtCoin2;
            updatedAt = updatedAtCoin2;
            answeredInRound = answeredInRoundCoin2;
        }
        return (roundId, minLpUsdPrice, startedAt, updatedAt, answeredInRound);
    }

    /** 
    @notice Retrieves the latest price for LP token
    @return price The latest price for LP token
    */
    function latestAnswer() external view returns (int256) {
        (, int256 price, , , ) = latestRoundData();
        return price;
    }

    /**
     * @notice Retrieves number of decimals for the LP token price feed
     * @return decimals The number of decimals for the LP token price feed
     */
    function decimals() public pure returns (uint8) {
        return 18;
    }
}
"
    },
    "src/interfaces/ICurvePool.sol": {
      "content": "pragma solidity ^0.8.13;

interface ICurvePool {
    function price_oracle(uint256 k) external view returns (uint256);

    function get_virtual_price() external view returns (uint256);

    function price_oracle() external view returns (uint256);

    function add_liquidity(
        uint256[2] memory _amounts,
        uint256 _min_mint_amount,
        address _receiver
    ) external returns (uint256);

    function add_liquidity(
        uint256[] memory _amounts,
        uint256 _min_mint_amount,
        address _receiver
    ) external returns (uint256);

    function add_liquidity(
        uint256[2] memory _amounts,
        uint256 _min_mint_amount
    ) external returns (uint256);

    function add_liquidity(
        uint256[] memory _amounts,
        uint256 _min_mint_amount
    ) external returns (uint256);

    function add_liquidity(
        uint256[3] memory _amounts,
        uint256 _min_mint_amount,
        address _receiver
    ) external returns (uint256);

    function add_liquidity(
        uint256[3] memory _amounts,
        uint256 _min_mint_amount
    ) external returns (uint256);

    function remove_liquidity_one_coin(
        uint256 _burn_amount,
        int128 i,
        uint256 _min_received,
        address _receiver
    ) external returns (uint256);

    function coins(uint index) external view returns (address);

    function exchange(
        uint i,
        uint j,
        uint dx,
        uint min_dy,
        bool use_eth,
        address receiver
    ) external payable returns (uint);

    function calc_token_amount(
        uint256[2] memory _amounts,
        bool _is_deposit
    ) external view returns (uint256);
    function calc_token_amount(
        uint256[] memory _amounts,
        bool _is_deposit
    ) external view returns (uint256);

    function calc_withdraw_one_coin(
        uint256 _burn_amount,
        int128 i
    ) external view returns (uint256);

    function symbol() external view returns (string memory);

    function lp_token() external view returns (address);

    function decimals() external view returns (uint256);
}
"
    },
    "src/interfaces/IChainlinkFeed.sol": {
      "content": "pragma solidity ^0.8.13;

interface IChainlinkFeed {
    function aggregator() external view returns (address aggregator);

    function decimals() external view returns (uint8 decimals);

    function latestRoundData()
        external
        view
        returns (
            uint80 roundId,
            int256 crvUsdPrice,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        );

    function latestAnswer() external view returns (int256 price);

    function description() external view returns (string memory description);
}

interface IChainlinkBasePriceFeed is IChainlinkFeed {
    function assetToUsd() external view returns (IChainlinkFeed);

    function assetToUsdFallback() external view returns (IChainlinkFeed);

    function assetToUsdHeartbeat() external view returns (uint256 heartbeat);
}
"
    },
    "src/interfaces/IERC20.sol": {
      "content": "pragma solidity ^0.8.13;

interface IERC20 {
    function approve(address, uint) external;

    function transfer(address, uint) external returns (bool);

    function transferFrom(address, address, uint) external returns (bool);

    function balanceOf(address) external view returns (uint);

    function allowance(address from, address to) external view returns (uint);

    function symbol() external view returns (string memory);
}

interface IMintable is IERC20 {
    function mint(address, uint) external;

    function burn(uint) external;

    function addMinter(address minter) external;
}

interface IDelegateableERC20 is IERC20 {
    function delegate(address delegatee) external;

    function delegates(
        address delegator
    ) external view returns (address delegatee);
}
"
    }
  },
  "settings": {
    "remappings": [
      "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
      "ds-test/=lib/forge-std/lib/ds-test/src/",
      "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
      "forge-std/=lib/forge-std/src/",
      "openzeppelin-contracts/=lib/openzeppelin-contracts/",
      "solmate/=lib/solmate/src/",
      "bytes-utils/=lib/bytes-utils/contracts/",
      "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/"
    ],
    "optimizer": {
      "enabled": true,
      "runs": 10000
    },
    "metadata": {
      "useLiteralContent": false,
      "bytecodeHash": "ipfs",
      "appendCBOR": true
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "evmVersion": "shanghai",
    "viaIR": false
  }
}}

Tags:
ERC20, Token, Mintable, Burnable, Factory, Oracle|addr:0xf35bc9e56c3089a5b391fc6052f77ad956ba9e4d|verified:true|block:23447215|tx:0xedf47d0635c1771377de1ba36433c5179ae7b46d4f6d3945763219594dcbfe38|first_check:1758890356

Submitted on: 2025-09-26 14:39:18

Comments

Log in to comment.

No comments yet.