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
}
}}
Submitted on: 2025-09-26 14:39:18
Comments
Log in to comment.
No comments yet.