编译器
0.8.23+commit.f704f362
文件 1 的 27:AccessControl.sol
pragma solidity ^0.8.20;
import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {ERC165} from "../utils/introspection/ERC165.sol";
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
mapping(bytes32 role => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
return _roles[role].hasRole[account];
}
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
return _roles[role].adminRole;
}
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
if (!hasRole(role, account)) {
_roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
if (hasRole(role, account)) {
_roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}
}
文件 2 的 27:Address.sol
pragma solidity ^0.8.20;
library Address {
error AddressInsufficientBalance(address account);
error AddressEmptyCode(address target);
error FailedInnerCall();
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
function _revert(bytes memory returndata) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}
文件 3 的 27:Constants.sol
pragma solidity ^0.8.23;
library Constants {
address internal constant CRVUSD_ADDRESS = 0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E;
address internal constant USDC_ADDRESS = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
address internal constant USDT_ADDRESS = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
address internal constant DAI_ADDRESS = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address internal constant FRX_ETH_ADDRESS = 0x5E8422345238F34275888049021821E8E08CAa1f;
address internal constant WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address internal constant CVX_ADDRESS = 0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B;
address internal constant CRV_ADDRESS = 0xD533a949740bb3306d119CC777fa900bA034cd52;
address internal constant FXS_ADDRESS = 0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0;
address internal constant SPELL_ADDRESS = 0x090185f2135308BaD17527004364eBcC2D37e5F6;
address internal constant SDT_ADDRESS = 0x73968b9a57c6E53d41345FD57a6E6ae27d6CDB2F;
address internal constant SFRXETH_ADDRESS = 0xac3E018457B222d93114458476f3E3416Abbe38F;
address internal constant ZUNUSD_ADDRESS = 0x8C0D76C9B18779665475F3E212D9Ca1Ed6A1A0e6;
address internal constant zunUSD_CONTROLLER_ADDRESS =
0x618eee502CDF6b46A2199C21D1411f3F6065c940;
address internal constant zunETH_ADDRESS = 0xc2e660C62F72c2ad35AcE6DB78a616215E2F2222;
address internal constant zunETH_CONTROLLER_ADDRESS =
0x54A00DA65c79DDCe24E7fe4691737FD70F7797DF;
address public constant CHAINLINK_FEED_REGISTRY_ETH_ADDRESS =
0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
address internal constant CRV_3POOL_ADDRESS = 0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7;
address internal constant CRV_3POOL_LP_ADDRESS = 0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490;
address internal constant CRV_TRICRYPTO2_ADDRESS = 0xD51a44d3FaE010294C616388b506AcdA1bfAAE46;
address internal constant ETH_frxETH_ADDRESS = 0xa1F8A6807c402E4A15ef4EBa36528A3FED24E577;
address internal constant ETH_frxETH_LP_ADDRESS = 0xf43211935C781D5ca1a41d2041F397B8A7366C7A;
address internal constant WETH_frxETH_ADDRESS = 0x9c3B46C0Ceb5B9e304FCd6D88Fc50f7DD24B31Bc;
address internal constant WETH_frxETH_LP_ADDRESS = 0x9c3B46C0Ceb5B9e304FCd6D88Fc50f7DD24B31Bc;
address internal constant CRV_FRAX_USDC_POOL_ADDRESS =
0xDcEF968d416a41Cdac0ED8702fAC8128A64241A2;
address internal constant CRV_FRAX_USDC_POOL_LP_ADDRESS =
0x3175Df0976dFA876431C2E9eE6Bc45b65d3473CC;
address internal constant SDT_CRVUSD_USDT_VAULT_ADDRESS =
0x37b24ac19504C0c6FC1ADc8deb5D24f5C4F6A2f2;
address internal constant CRV_CRVUSD_USDT_LP_ADDRESS =
0x390f3595bCa2Df7d23783dFd126427CCeb997BF4;
address internal constant CRV_CRVUSD_USDT_ADDRESS = 0x390f3595bCa2Df7d23783dFd126427CCeb997BF4;
address internal constant SDT_CRVUSD_USDC_VAULT_ADDRESS =
0xb618EA40cb1F5b08839Ba228C8dd58AC3DCA12F3;
address internal constant CRV_CRVUSD_USDC_LP_ADDRESS =
0x4DEcE678ceceb27446b35C672dC7d61F30bAD69E;
address internal constant CRV_CRVUSD_USDC_ADDRESS = 0x4DEcE678ceceb27446b35C672dC7d61F30bAD69E;
address internal constant CRV_BOOSTER_ADDRESS = 0xF403C135812408BFbE8713b5A23a04b3D48AAE31;
address internal constant CRV_STAKING_BOOSTER_ADDRESS = 0xD8Bd5Cdd145ed2197CB16ddB172DF954e3F28659;
address internal constant CRV_ETH_stETH_ADDRESS = 0x21E27a5E5513D6e65C4f830167390997aA84843a;
address internal constant CRV_ETH_stETH_LP_ADDRESS = 0x21E27a5E5513D6e65C4f830167390997aA84843a;
address internal constant CVX_ETH_stETH_REWARDS_ADDRESS =
0x6B27D7BC63F1999D14fF9bA900069ee516669ee8;
uint256 internal constant CVX_ETH_stETH_PID = 177;
address internal constant SDT_zunUSD_crvUSD_VAULT_ADDRESS = 0x5962E74338FEA24051e039A6106a68082AB58375;
address internal constant CRV_zunUSD_crvUSD_ADDRESS =
0x8C24b3213FD851db80245FCCc42c40B94Ac9a745;
address internal constant CRV_zunUSD_crvUSD_LP_ADDRESS =
0x8C24b3213FD851db80245FCCc42c40B94Ac9a745;
address internal constant CVX_zunUSD_crvUSD_REWARDS_ADDRESS =
0xB0408d1477554268Ece9b0a40290C345196fBf1B;
uint256 internal constant CVX_zunUSD_crvUSD_PID = 309;
address internal constant CRV_USDT_crvUSD_ADDRESS = 0x390f3595bCa2Df7d23783dFd126427CCeb997BF4;
address internal constant LLAMALEND_CRV_ADDRESS = 0xCeA18a8752bb7e7817F9AE7565328FE415C0f2cA;
address internal constant SDT_LLAMALEND_CRV_VAULT_ADDRESS =
0xfa6D40573082D797CB3cC378c0837fB90eB043e5;
address internal constant CVX_LLAMALEND_CRV_REWARDS_ADDRESS =
0x4bf2d8484474170bff8a8c34475be3d87dFF28cA;
uint256 internal constant CVX_LLAMALEND_CRV_PID = 325;
address internal constant LLAMALEND_WETH_ADDRESS = 0x5AE28c9197a4a6570216fC7e53E7e0221D7A0FEF;
address internal constant SDT_LLAMALEND_WETH_CRVUSD_VAULT_ADDRESS =
0xADde9073d897743E7004115Fa2452cC959FBF28a;
address internal constant CRV_zunETH_frxETH_ADDRESS =
0x3A65cbaebBFecbeA5D0CB523ab56fDbda7fF9aAA;
address internal constant CRV_zunETH_frxETH_LP_ADDRESS =
0x3A65cbaebBFecbeA5D0CB523ab56fDbda7fF9aAA;
address internal constant CVX_zunETH_frxETH_REWARDS_ADDRESS =
0x756d67A10974Fa0e0cE63F82AF4E7ef0d46d452D;
uint256 internal constant CVX_zunETH_frxETH_PID = 330;
uint256 internal constant CVX_STAKING_zunETH_frxETH_PID = 75;
address internal constant SDT_zunETH_frxETH_VAULT_ADDRESS =
0xAaE1Ae12d4C8b811DDa1188b01be23b4ab7C62D2;
address internal constant SDT_PXETH_WETH_VAULT_ADDRESS = 0x062AdE4F4583fF6b21f6f2c2Ed04eD7037E8B282;
address internal constant CRV_PXETH_WETH_ADDRESS = 0xC8Eb2Cf2f792F77AF0Cd9e203305a585E588179D;
address internal constant CRV_PXETH_WETH_LP_ADDRESS = 0xC8Eb2Cf2f792F77AF0Cd9e203305a585E588179D;
address internal constant CRV_zunUSD_crvFRAX_ADDRESS = address(0);
address internal constant CRV_zunUSD_crvFRAX_LP_ADDRESS = address(0);
address internal constant CVX_zunUSD_crvFRAX_REWARDS_ADDRESS = address(0);
uint256 internal constant CVX_zunUSD_crvFRAX_PID = 0;
}
文件 4 的 27:Context.sol
pragma solidity ^0.8.20;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
文件 5 的 27:CrvUsdApsStakeDaoCurveStratBase.sol
pragma solidity ^0.8.23;
import '../../../../../utils/Constants.sol';
import '../../../../../interfaces/IController.sol';
import '../../../../../interfaces/ITokenConverter.sol';
import '../EmergencyAdminStakeDaoCurveNStratBase.sol';
import '../../../../../interfaces/ICurvePool2.sol';
contract CrvUsdApsStakeDaoCurveStratBase is EmergencyAdminStakeDaoCurveNStratBase {
using SafeERC20 for IERC20;
uint256 public constant ZUNAMI_ZUNUSD_TOKEN_ID = 0;
uint128 public constant CRVUSD_TOKEN_POOL_CRVUSD_ID = 0;
int128 public constant CRVUSD_TOKEN_POOL_CRVUSD_ID_INT = int128(CRVUSD_TOKEN_POOL_CRVUSD_ID);
uint128 public constant CRVUSD_TOKEN_POOL_TOKEN_ID = 1;
int128 public constant CRVUSD_TOKEN_POOL_TOKEN_ID_INT = int128(CRVUSD_TOKEN_POOL_TOKEN_ID);
IController public immutable zunamiController;
IERC20 public immutable zunamiStable;
uint256 constant ZUNAMI_USDC_TOKEN_ID = 1;
uint128 public constant CRVUSD_USDC_POOL_USDC_ID = 0;
int128 public constant CRVUSD_USDC_POOL_USDC_ID_INT = int128(CRVUSD_USDC_POOL_USDC_ID);
uint128 public constant CRVUSD_USDC_POOL_CRVUSD_ID = 1;
int128 public constant CRVUSD_USDC_POOL_CRVUSD_ID_INT = int128(CRVUSD_USDC_POOL_CRVUSD_ID);
ICurvePool2 public immutable crvUsdUsdcPool = ICurvePool2(Constants.CRV_CRVUSD_USDC_ADDRESS);
ITokenConverter public converter;
event SetTokenConverter(address tokenConverter);
constructor(
IERC20[POOL_ASSETS] memory _tokens,
uint256[POOL_ASSETS] memory _tokenDecimalsMultipliers,
address _vaultAddr,
address _poolAddr,
address _poolTokenAddr,
address _zunamiControllerAddr,
address _zunamiStableAddr
)
EmergencyAdminStakeDaoCurveNStratBase(
_tokens,
_tokenDecimalsMultipliers,
_vaultAddr,
_poolAddr,
_poolTokenAddr
)
{
if (_zunamiControllerAddr == address(0)) revert ZeroAddress();
zunamiController = IController(_zunamiControllerAddr);
if (_zunamiStableAddr == address(0)) revert ZeroAddress();
zunamiStable = IERC20(_zunamiStableAddr);
}
function setTokenConverter(address converterAddr) external onlyRole(DEFAULT_ADMIN_ROLE) {
if (address(converterAddr) == address(0)) revert ZeroAddress();
converter = ITokenConverter(converterAddr);
emit SetTokenConverter(converterAddr);
}
function convertCurvePoolTokenAmounts(
uint256[POOL_ASSETS] memory amounts
) internal pure override returns (uint256[] memory) {
uint256[] memory amountsN = new uint256[](CURVENG_MAX_COINS);
amountsN[CRVUSD_TOKEN_POOL_TOKEN_ID] = amounts[ZUNAMI_ZUNUSD_TOKEN_ID];
return amountsN;
}
function convertAndApproveTokens(
address pool,
uint256[POOL_ASSETS] memory amounts
) internal override returns (uint256[] memory) {
uint256[] memory amountsN = new uint256[](CURVENG_MAX_COINS);
amountsN[CRVUSD_TOKEN_POOL_TOKEN_ID] = amounts[ZUNAMI_ZUNUSD_TOKEN_ID];
zunamiStable.safeIncreaseAllowance(pool, amountsN[CRVUSD_TOKEN_POOL_TOKEN_ID]);
return amountsN;
}
function getCurveRemovingTokenIndex() internal pure override returns (int128) {
return CRVUSD_TOKEN_POOL_TOKEN_ID_INT;
}
function getZunamiRemovingTokenIndex() internal pure override returns (uint256) {
return ZUNAMI_ZUNUSD_TOKEN_ID;
}
function _inflate(uint256 ratioOfCrvLps, uint256 minInflatedAmount) internal override {
uint256 removingCrvLps = getLiquidityAmountByRatio(ratioOfCrvLps);
depositedLiquidity -= removingCrvLps;
vault.withdraw(removingCrvLps);
uint256 crvUsdAmount = pool.remove_liquidity_one_coin(
removingCrvLps,
CRVUSD_TOKEN_POOL_CRVUSD_ID_INT,
0
);
IERC20 crvUsd = IERC20(Constants.CRVUSD_ADDRESS);
crvUsd.safeIncreaseAllowance(address(crvUsdUsdcPool), crvUsdAmount);
uint256 usdcAmount = crvUsdUsdcPool.exchange(
CRVUSD_USDC_POOL_CRVUSD_ID_INT,
CRVUSD_USDC_POOL_USDC_ID_INT,
crvUsdAmount,
minInflatedAmount
);
IERC20 usdc = IERC20(Constants.USDC_ADDRESS);
usdc.safeIncreaseAllowance(address(zunamiController), usdcAmount);
uint256 zunStableAmount = zunamiController.deposit([0, usdcAmount, 0, 0, 0], address(this));
uint256[] memory amountsN = new uint256[](CURVENG_MAX_COINS);
amountsN[CRVUSD_TOKEN_POOL_TOKEN_ID] = zunStableAmount;
zunamiStable.safeIncreaseAllowance(address(pool), zunStableAmount);
uint256 poolTokenAmount = depositCurve(amountsN);
depositedLiquidity += poolTokenAmount;
depositBooster(poolTokenAmount);
}
function _deflate(uint256 ratioOfCrvLps, uint256 minDeflateAmount) internal override {
uint256 removingCrvLps = getLiquidityAmountByRatio(ratioOfCrvLps);
depositedLiquidity -= removingCrvLps;
vault.withdraw(removingCrvLps);
uint256 tokenAmount = pool.remove_liquidity_one_coin(
removingCrvLps,
CRVUSD_TOKEN_POOL_TOKEN_ID_INT,
0
);
zunamiStable.safeIncreaseAllowance(address(zunamiController), tokenAmount);
zunamiController.withdraw(tokenAmount, [uint256(0), 0, 0, 0, 0], address(this));
IERC20 dai = IERC20(Constants.DAI_ADDRESS);
IERC20 usdc = IERC20(Constants.USDC_ADDRESS);
IERC20 usdt = IERC20(Constants.USDT_ADDRESS);
convertToken(dai, usdc, dai.balanceOf(address(this)));
convertToken(usdt, usdc, usdt.balanceOf(address(this)));
uint256 usdcAmount = usdc.balanceOf(address(this));
usdc.safeIncreaseAllowance(address(crvUsdUsdcPool), usdcAmount);
uint256 crvUsdAmount = crvUsdUsdcPool.exchange(
CRVUSD_USDC_POOL_USDC_ID_INT,
CRVUSD_USDC_POOL_CRVUSD_ID_INT,
usdcAmount,
minDeflateAmount
);
IERC20 crvUsd = IERC20(Constants.CRVUSD_ADDRESS);
uint256[] memory amountsN = new uint256[](CURVENG_MAX_COINS);
amountsN[CRVUSD_TOKEN_POOL_CRVUSD_ID] = crvUsdAmount;
crvUsd.safeIncreaseAllowance(address(pool), crvUsdAmount);
uint256 poolTokenAmount = depositCurve(amountsN);
depositedLiquidity += poolTokenAmount;
depositBooster(poolTokenAmount);
}
function convertToken(IERC20 fromToken, IERC20 toToken, uint256 fromAmount) internal {
if (address(fromToken) == address(toToken)) return;
fromToken.safeTransfer(address(converter), fromAmount);
converter.handle(address(fromToken), address(toToken), fromAmount, 0);
}
}
文件 6 的 27:CurveNStratBase.sol
pragma solidity ^0.8.23;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import '../../interfaces/ICurvePoolN.sol';
import '../ZunamiStratBase.sol';
abstract contract CurveNStratBase is ZunamiStratBase {
using SafeERC20 for IERC20;
uint256 public constant CURVENG_MAX_COINS = 8;
ICurvePoolN public immutable pool;
IERC20 public immutable poolToken;
constructor(
IERC20[POOL_ASSETS] memory tokens_,
uint256[POOL_ASSETS] memory tokenDecimalsMultipliers_,
address poolAddr,
address poolTokenAddr
) ZunamiStratBase(tokens_, tokenDecimalsMultipliers_) {
if (poolAddr == address(0)) revert ZeroAddress();
pool = ICurvePoolN(poolAddr);
if (poolTokenAddr == address(0)) revert ZeroAddress();
poolToken = IERC20(poolTokenAddr);
}
function convertCurvePoolTokenAmounts(
uint256[POOL_ASSETS] memory amounts
) internal view virtual returns (uint256[] memory);
function depositLiquidity(
uint256[POOL_ASSETS] memory amounts
) internal override returns (uint256 poolTokenAmount) {
uint256[] memory amountsN = convertAndApproveTokens(address(pool), amounts);
poolTokenAmount = depositCurve(amountsN);
depositBooster(poolTokenAmount);
}
function convertAndApproveTokens(
address pool,
uint256[POOL_ASSETS] memory amounts
) internal virtual returns (uint256[] memory amountsN);
function depositCurve(uint256[] memory amountsN) internal virtual returns (uint256 deposited) {
return pool.add_liquidity(amountsN, 0);
}
function depositBooster(uint256 amount) internal virtual;
function getLiquidityTokenPrice() internal view virtual override returns (uint256) {
return getTokenPrice(address(poolToken));
}
function calcTokenAmount(
uint256[POOL_ASSETS] memory tokenAmounts,
bool isDeposit
) public view override returns (uint256 sharesAmount) {
return pool.calc_token_amount(convertCurvePoolTokenAmounts(tokenAmounts), isDeposit);
}
function getCurveRemovingTokenIndex() internal view virtual returns (int128);
function getZunamiRemovingTokenIndex() internal view virtual returns (uint256);
function removeLiquidity(
uint256 amount,
uint256[POOL_ASSETS] memory minTokenAmounts,
bool
) internal virtual override {
int128 curveTokenIndex = getCurveRemovingTokenIndex();
uint256 removedAmount = pool.remove_liquidity_one_coin(
amount,
curveTokenIndex,
minTokenAmounts[getZunamiRemovingTokenIndex()]
);
convertRemovedAmount(removedAmount);
}
function convertRemovedAmount(uint256 receivedAmount) internal virtual {}
}
文件 7 的 27:ERC165.sol
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 8 的 27:EmergencyAdminStakeDaoCurveNStratBase.sol
pragma solidity ^0.8.23;
import '../StakeDaoCurveNStratBase.sol';
abstract contract EmergencyAdminStakeDaoCurveNStratBase is StakeDaoCurveNStratBase {
bytes32 public constant EMERGENCY_ADMIN_ROLE = keccak256('EMERGENCY_ADMIN_ROLE');
constructor(
IERC20[POOL_ASSETS] memory _tokens,
uint256[POOL_ASSETS] memory _tokenDecimalsMultipliers,
address _vaultAddr,
address _poolAddr,
address _poolTokenAddr
)
StakeDaoCurveNStratBase(
_tokens,
_tokenDecimalsMultipliers,
_vaultAddr,
_poolAddr,
_poolTokenAddr
)
{
_grantRole(EMERGENCY_ADMIN_ROLE, msg.sender);
}
function inflate(
uint256 ratioOfCrvLps,
uint256 minInflatedAmount
) external onlyRole(EMERGENCY_ADMIN_ROLE) {
_inflate(ratioOfCrvLps, minInflatedAmount);
}
function _inflate(uint256 ratioOfCrvLps, uint256 minInflatedAmount) internal virtual;
function deflate(
uint256 ratioOfCrvLps,
uint256 minDeflateAmount
) external onlyRole(EMERGENCY_ADMIN_ROLE) {
_deflate(ratioOfCrvLps, minDeflateAmount);
}
function _deflate(uint256 ratioOfCrvLps, uint256 minDeflateAmount) internal virtual;
}
文件 9 的 27:IAccessControl.sol
pragma solidity ^0.8.20;
interface IAccessControl {
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
error AccessControlBadConfirmation();
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address callerConfirmation) external;
}
文件 10 的 27:IController.sol
pragma solidity ^0.8.23;
interface IController {
function deposit(uint256[5] memory amounts, address receiver) external returns (uint256 shares);
function withdraw(uint256 shares, uint256[5] memory minTokenAmounts, address receiver) external;
}
文件 11 的 27:ICurvePool2.sol
pragma solidity ^0.8.23;
import './ICurvePoolPricable.sol';
interface ICurvePool2 is ICurvePoolPricable {
function coins(uint256 i) external view returns (address);
function add_liquidity(
uint256[2] memory amounts,
uint256 min_mint_amount
) external returns (uint256);
function remove_liquidity(
uint256 burn_amount,
uint256[2] memory min_amounts
) external returns (uint256[2] memory);
function remove_liquidity_imbalance(
uint256[2] memory amounts,
uint256 max_burn_amount
) external returns (uint256);
function remove_liquidity_one_coin(
uint256 burn_amount,
int128 i,
uint256 min_received
) external returns (uint256);
function exchange(
int128 i,
int128 j,
uint256 input,
uint256 min_output
) external returns (uint256);
function exchange_underlying(int128 i, int128 j, uint256 input, uint256 min_output) external;
function calc_token_amount(
uint256[2] memory amounts,
bool is_deposit
) external view returns (uint256);
function calc_token_amount(
uint256[2] memory amounts,
bool is_deposit,
bool previous
) external view returns (uint256);
function calc_withdraw_one_coin(uint256 burn_amount, int128 i) external view returns (uint256);
function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256);
}
文件 12 的 27:ICurvePoolN.sol
pragma solidity ^0.8.23;
import './ICurvePoolPricable.sol';
interface ICurvePoolN is ICurvePoolPricable {
function coins(uint256 i) external view returns (address);
function add_liquidity(
uint256[] memory amounts,
uint256 min_mint_amount
) external returns (uint256);
function remove_liquidity(
uint256 burn_amount,
uint256[] memory min_amounts
) external returns (uint256[] memory);
function remove_liquidity_imbalance(
uint256[] memory amounts,
uint256 max_burn_amount
) external returns (uint256);
function remove_liquidity_one_coin(
uint256 burn_amount,
int128 i,
uint256 min_received
) external returns (uint256);
function exchange(
int128 i,
int128 j,
uint256 input,
uint256 min_output
) external returns (uint256);
function exchange_underlying(int128 i, int128 j, uint256 input, uint256 min_output) external;
function calc_token_amount(
uint256[] memory amounts,
bool is_deposit
) external view returns (uint256);
function calc_token_amount(
uint256[] memory amounts,
bool is_deposit,
bool previous
) external view returns (uint256);
function calc_withdraw_one_coin(uint256 burn_amount, int128 i) external view returns (uint256);
function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256);
}
文件 13 的 27:ICurvePoolPricable.sol
pragma solidity ^0.8.23;
interface ICurvePoolPricable {
function get_virtual_price() external view returns (uint256);
}
文件 14 的 27:IERC165.sol
pragma solidity ^0.8.20;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 15 的 27:IERC20.sol
pragma solidity ^0.8.20;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
文件 16 的 27:IERC20Permit.sol
pragma solidity ^0.8.20;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 17 的 27:IOracle.sol
pragma solidity ^0.8.23;
interface IOracle {
error ZeroAddress();
error UnsupportedToken();
function getUSDPrice(address token) external view returns (uint256);
function isTokenSupported(address token) external view returns (bool);
}
文件 18 的 27:IPool.sol
pragma solidity ^0.8.23;
import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import { IStrategy } from './IStrategy.sol';
interface IPool is IERC20 {
error WrongDeposit(uint256 sid, uint256[5] amounts);
error AbsentStrategy(uint256 sid);
error NotStartedStrategy(uint256 sid);
error DisabledStrategy(uint256 sid);
error WrongAmount();
error WrongWithdrawParams(uint256 sid);
error WrongRatio();
error ZeroAddress();
error DuplicatedStrategy();
error IncorrectArguments();
error WrongWithdrawPercent();
error WrongReceiver();
error IncorrectSid();
error WrongTokens();
error WrongDecimalMultipliers();
struct StrategyInfo {
IStrategy strategy;
uint256 startTime;
uint256 minted;
bool enabled;
}
event Deposited(
address indexed depositor,
uint256 deposited,
uint256[5] amounts,
uint256 indexed sid
);
event Withdrawn(address indexed withdrawer, uint256 withdrawn, uint256 indexed sid);
event FailedWithdrawal(address indexed withdrawer, uint256[5] amounts, uint256 withdrawn);
event AddedStrategy(uint256 indexed sid, address indexed strategyAddr, uint256 startTime);
event ClaimedRewards(address indexed receiver, IERC20[] rewardTokens);
event ClaimedExtraGains(address indexed receiver, uint256 amount);
event EnabledStrategy(address indexed pool);
event DisableStrategy(address indexed pool);
event UpdatedToken(
uint256 indexed tid,
address indexed token,
uint256 tokenDecimalMultiplier,
address tokenOld
);
function tokens() external view returns (IERC20[5] memory);
function token(uint256 tid) external view returns (IERC20);
function tokenDecimalsMultipliers() external view returns (uint256[5] memory);
function strategyInfo(uint256 sid) external view returns (StrategyInfo memory);
function claimRewards(address receiver, IERC20[] memory rewardTokens) external;
function totalHoldings() external view returns (uint256);
function strategyCount() external view returns (uint256);
function deposit(
uint256 sid,
uint256[5] memory amounts,
address receiver
) external returns (uint256);
function depositStrategy(uint256 sid, uint256[5] memory amounts) external returns (uint256);
function withdraw(
uint256 sid,
uint256 stableAmount,
uint256[5] memory minTokenAmounts,
address receiver
) external;
function mintAndClaimExtraGains(address receiver) external;
}
文件 19 的 27:IStakeDaoGauge.sol
pragma solidity ^0.8.23;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
interface IStakeDaoGauge is IERC20 {
function claimable_reward(address _user, address _reward_token) external view returns (uint256);
function claim_rewards() external;
function withdraw(uint256 _value, address _addr, bool _claim_rewards) external;
function reward_tokens(uint256 id) external view returns (address);
function reward_count() external view returns (uint256);
}
文件 20 的 27:IStakeDaoVault.sol
pragma solidity ^0.8.23;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import './IStakeDaoGauge.sol';
interface IStakeDaoVault is IERC20 {
function liquidityGauge() external view returns (IStakeDaoGauge);
function withdraw(uint256 amount) external;
function deposit(address staker, uint256 amount, bool earn) external;
}
文件 21 的 27:IStrategy.sol
pragma solidity ^0.8.23;
import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
interface IStrategy {
function deposit(uint256[5] memory amounts) external returns (uint256);
function withdraw(
address receiver,
uint256 userDepositRatio,
uint256[5] memory minTokenAmounts
) external returns (bool);
function withdrawAll(uint256[5] memory minTokenAmounts) external;
function totalHoldings() external view returns (uint256);
function claimRewards(address receiver, IERC20[] memory rewardTokens) external;
function calcTokenAmount(
uint256[5] memory tokenAmounts,
bool isDeposit
) external view returns (uint256 sharesAmount);
}
文件 22 的 27:ITokenConverter.sol
pragma solidity ^0.8.23;
interface ITokenConverter {
function handle(
address tokenIn,
address tokenOut,
uint256 amount,
uint256 minAmountOut
) external returns (uint256);
function valuate(
address tokenIn_,
address tokenOut_,
uint256 amountIn_
) external view returns (uint256);
}
文件 23 的 27:SafeERC20.sol
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
error SafeERC20FailedOperation(address token);
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}
文件 24 的 27:StakeDaoCurveNStratBase.sol
pragma solidity ^0.8.23;
import '../CurveNStratBase.sol';
import '../../../interfaces/IStakeDaoVault.sol';
abstract contract StakeDaoCurveNStratBase is CurveNStratBase {
using SafeERC20 for IERC20;
IStakeDaoVault public immutable vault;
constructor(
IERC20[POOL_ASSETS] memory _tokens,
uint256[POOL_ASSETS] memory _tokenDecimalsMultipliers,
address _vaultAddr,
address _poolAddr,
address _poolTokenAddr
) CurveNStratBase(_tokens, _tokenDecimalsMultipliers, _poolAddr, _poolTokenAddr) {
if (_vaultAddr == address(0)) revert ZeroAddress();
vault = IStakeDaoVault(_vaultAddr);
}
function depositBooster(uint256 amount) internal override {
poolToken.safeIncreaseAllowance(address(vault), amount);
vault.deposit(address(this), amount, true);
}
function removeLiquidity(
uint256 amount,
uint256[POOL_ASSETS] memory minTokenAmounts,
bool removeAll
) internal virtual override {
vault.withdraw(amount);
super.removeLiquidity(amount, minTokenAmounts, removeAll);
}
function claimCollectedRewards() internal virtual override {
vault.liquidityGauge().claim_rewards();
}
}
文件 25 的 27:ZunUsdCrvUsdApsStakeDaoCurveStrat.sol
pragma solidity ^0.8.23;
import '../../../../../utils/Constants.sol';
import './CrvUsdApsStakeDaoCurveStratBase.sol';
contract ZunUsdCrvUsdApsStakeDaoCurveStrat is CrvUsdApsStakeDaoCurveStratBase {
constructor()
CrvUsdApsStakeDaoCurveStratBase(
[
IERC20(Constants.ZUNUSD_ADDRESS),
IERC20(address(0)),
IERC20(address(0)),
IERC20(address(0)),
IERC20(address(0))
],
[uint256(1), 0, 0, 0, 0],
Constants.SDT_zunUSD_crvUSD_VAULT_ADDRESS,
Constants.CRV_zunUSD_crvUSD_ADDRESS,
Constants.CRV_zunUSD_crvUSD_LP_ADDRESS,
Constants.zunUSD_CONTROLLER_ADDRESS,
Constants.ZUNUSD_ADDRESS
)
{}
}
文件 26 的 27:ZunamiPoolAccessControl.sol
pragma solidity ^0.8.23;
import '@openzeppelin/contracts/access/AccessControl.sol';
import '../interfaces/IPool.sol';
contract ZunamiPoolAccessControl is AccessControl {
error MustBeCalledByZunamiPool();
error ZeroAddress();
error ZeroValue();
error MustHaveOwner();
IPool public zunamiPool;
event ZunamiPoolSet(address zunamiPoolAddr);
modifier onlyZunamiPool() {
if (msg.sender != address(zunamiPool)) revert MustBeCalledByZunamiPool();
_;
}
constructor() {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
function setZunamiPool(address zunamiAddr) external onlyRole(DEFAULT_ADMIN_ROLE) {
if (zunamiAddr == address(0)) revert ZeroAddress();
zunamiPool = IPool(zunamiAddr);
emit ZunamiPoolSet(zunamiAddr);
}
}
文件 27 的 27:ZunamiStratBase.sol
pragma solidity ^0.8.23;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import '../lib/Oracle/interfaces/IOracle.sol';
import '../interfaces/IStrategy.sol';
import './ZunamiPoolAccessControl.sol';
abstract contract ZunamiStratBase is IStrategy, ZunamiPoolAccessControl {
using SafeERC20 for IERC20;
error WrongTokens();
error WrongDecimalMultipliers();
error DepositLiquidityValueTooLow();
uint8 public constant POOL_ASSETS = 5;
uint256 public constant RATIO_MULTIPLIER = 1e18;
uint256 public constant PRICE_DENOMINATOR = 1e18;
uint256 public constant SLIPPAGE_DENOMINATOR = 10000;
uint256 public slippage = 50;
IERC20[POOL_ASSETS] public tokens;
uint256[POOL_ASSETS] public tokenDecimalsMultipliers;
IOracle public oracle;
uint256 public depositedLiquidity;
event SlippageSet(uint256 oldSlippage, uint256 newSlippage);
event PriceOracleSet(address oracleAddr);
error WrongSlippage();
error WrongRatio();
constructor(
IERC20[POOL_ASSETS] memory tokens_,
uint256[POOL_ASSETS] memory tokenDecimalsMultipliers_
) {
bool otherZeros = false;
for (uint256 i = 0; i < POOL_ASSETS; ++i) {
if (otherZeros && address(tokens_[i]) != address(0)) revert WrongTokens();
if (address(tokens_[i]) == address(0)) otherZeros = true;
if (
(address(tokens_[i]) != address(0) && tokenDecimalsMultipliers_[i] == 0) ||
(address(tokens_[i]) == address(0) && tokenDecimalsMultipliers_[i] != 0)
) revert WrongDecimalMultipliers();
}
tokens = tokens_;
tokenDecimalsMultipliers = tokenDecimalsMultipliers_;
}
function setPriceOracle(address oracleAddr) public onlyRole(DEFAULT_ADMIN_ROLE) {
if (oracleAddr == address(0)) revert ZeroAddress();
oracle = IOracle(oracleAddr);
emit PriceOracleSet(oracleAddr);
}
function setSlippage(uint256 _slippage) external onlyRole(DEFAULT_ADMIN_ROLE) {
if (!(_slippage > 0 && _slippage <= SLIPPAGE_DENOMINATOR)) revert WrongSlippage();
emit SlippageSet(slippage, _slippage);
slippage = _slippage;
}
function applySlippageDifferentPrice(
uint256 amount,
address tokenIn,
address tokenOut
) internal view returns (uint256) {
return
(amount * getTokenPrice(tokenIn) * (SLIPPAGE_DENOMINATOR - slippage)) /
SLIPPAGE_DENOMINATOR /
getTokenPrice(tokenOut);
}
function applySlippage(uint256 amount) internal view returns (uint256) {
return (amount * (SLIPPAGE_DENOMINATOR - slippage)) / SLIPPAGE_DENOMINATOR;
}
function calcTokenAmount(
uint256[POOL_ASSETS] memory tokenAmounts,
bool isDeposit
) public view virtual returns (uint256 sharesAmount);
function calcLiquidityValue(uint256 tokenAmount) internal view returns (uint256) {
return (tokenAmount * getLiquidityTokenPrice()) / PRICE_DENOMINATOR;
}
function getLiquidityTokenPrice() internal view virtual returns (uint256);
function getTokenPrice(address token) internal view virtual returns (uint256) {
return oracle.getUSDPrice(token);
}
function totalHoldings() public view virtual returns (uint256) {
return calcLiquidityValue(getLiquidityBalance());
}
function getLiquidityBalance() internal view virtual returns (uint256) {
return depositedLiquidity;
}
function deposit(
uint256[POOL_ASSETS] memory amounts
) external onlyZunamiPool returns (uint256 liquidityValue) {
uint256 depositValue = valuateDeposit(amounts);
uint256 liquidity = depositLiquidity(amounts);
depositedLiquidity += liquidity;
liquidityValue = calcLiquidityValue(liquidity);
if (liquidityValue < applySlippage(depositValue)) revert DepositLiquidityValueTooLow();
}
function valuateDeposit(
uint256[POOL_ASSETS] memory amounts
) internal view virtual returns (uint256 value) {
for (uint256 i = 0; i < POOL_ASSETS; ++i) {
address token = address(tokens[i]);
if (token == address(0)) break;
value +=
(getTokenPrice(address(tokens[i])) * amounts[i] * tokenDecimalsMultipliers[i]) /
PRICE_DENOMINATOR;
}
return value;
}
function depositLiquidity(
uint256[POOL_ASSETS] memory amounts
) internal virtual returns (uint256);
function getLiquidityAmountByRatio(
uint256 poolTokenRatio
) internal view returns (uint256) {
require(poolTokenRatio > 0 && poolTokenRatio <= RATIO_MULTIPLIER, 'Wrong PoolToken Ratio');
if (!(poolTokenRatio > 0 && poolTokenRatio <= RATIO_MULTIPLIER)) revert WrongRatio();
return (getLiquidityBalance() * poolTokenRatio) / RATIO_MULTIPLIER;
}
function withdraw(
address receiver,
uint256 poolTokenRatio,
uint256[POOL_ASSETS] memory tokenAmounts
) external virtual onlyZunamiPool returns (bool) {
uint256 liquidityAmount = getLiquidityAmountByRatio(poolTokenRatio);
if (liquidityAmount < calcTokenAmount(tokenAmounts, false)) {
return false;
}
uint256[] memory prevBalances = new uint256[](POOL_ASSETS);
for (uint256 i = 0; i < POOL_ASSETS; ++i) {
if (address(tokens[i]) == address(0)) break;
prevBalances[i] = tokens[i].balanceOf(address(this));
}
depositedLiquidity -= liquidityAmount;
removeLiquidity(liquidityAmount, tokenAmounts, false);
transferTokensOut(convertTokensToDynamic(tokens), receiver, prevBalances);
return true;
}
function removeLiquidity(
uint256 amount,
uint256[POOL_ASSETS] memory minTokenAmounts,
bool removeAll
) internal virtual;
function claimRewards(
address receiver,
IERC20[] memory rewardTokens
) public virtual onlyZunamiPool {
claimCollectedRewards();
transferTokensOut(rewardTokens, receiver, fillArrayN(0, rewardTokens.length));
}
function claimCollectedRewards() internal virtual {}
function withdrawAll(
uint256[POOL_ASSETS] memory minTokenAmounts
) external virtual onlyZunamiPool {
removeLiquidity(depositedLiquidity, minTokenAmounts, true);
depositedLiquidity = 0;
transferTokensOut(convertTokensToDynamic(tokens), msg.sender, fillArrayN(0, POOL_ASSETS));
}
function transferTokensOut(
IERC20[] memory transferringTokens,
address receiver,
uint256[] memory prevBalances
) internal {
uint256 transferAmount;
IERC20 token_;
for (uint256 i = 0; i < transferringTokens.length; ++i) {
token_ = transferringTokens[i];
if (address(token_) == address(0)) break;
transferAmount = token_.balanceOf(address(this)) - prevBalances[i];
if (transferAmount > 0) {
token_.safeTransfer(receiver, transferAmount);
}
}
}
function convertTokensToDynamic(
IERC20[POOL_ASSETS] memory _tokens
) internal pure returns (IERC20[] memory tokesDynamic) {
tokesDynamic = new IERC20[](POOL_ASSETS);
for (uint256 i = 0; i < _tokens.length; ++i) {
tokesDynamic[i] = _tokens[i];
}
}
function fillArrayN(
uint256 _value,
uint256 _count
) internal pure returns (uint256[] memory values) {
values = new uint256[](_count);
for (uint256 i = 0; i < _count; ++i) {
values[i] = _value;
}
}
function withdrawEmergency(IERC20 _token) external onlyRole(DEFAULT_ADMIN_ROLE) {
uint256 tokenBalance = _token.balanceOf(address(this));
if (tokenBalance > 0) {
_token.safeTransfer(msg.sender, tokenBalance);
}
}
}
{
"compilationTarget": {
"contracts/strategies/curve/stakeDao/aps/crvUSD/ZunUsdCrvUsdApsStakeDaoCurveStrat.sol": "ZunUsdCrvUsdApsStakeDaoCurveStrat"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"DepositLiquidityValueTooLow","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"MustBeCalledByZunamiPool","type":"error"},{"inputs":[],"name":"MustHaveOwner","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"WrongDecimalMultipliers","type":"error"},{"inputs":[],"name":"WrongRatio","type":"error"},{"inputs":[],"name":"WrongSlippage","type":"error"},{"inputs":[],"name":"WrongTokens","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroValue","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oracleAddr","type":"address"}],"name":"PriceOracleSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"tokenConverter","type":"address"}],"name":"SetTokenConverter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldSlippage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newSlippage","type":"uint256"}],"name":"SlippageSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"zunamiPoolAddr","type":"address"}],"name":"ZunamiPoolSet","type":"event"},{"inputs":[],"name":"CRVUSD_TOKEN_POOL_CRVUSD_ID","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CRVUSD_TOKEN_POOL_CRVUSD_ID_INT","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CRVUSD_TOKEN_POOL_TOKEN_ID","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CRVUSD_TOKEN_POOL_TOKEN_ID_INT","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CRVUSD_USDC_POOL_CRVUSD_ID","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CRVUSD_USDC_POOL_CRVUSD_ID_INT","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CRVUSD_USDC_POOL_USDC_ID","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CRVUSD_USDC_POOL_USDC_ID_INT","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CURVENG_MAX_COINS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMERGENCY_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL_ASSETS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RATIO_MULTIPLIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SLIPPAGE_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ZUNAMI_ZUNUSD_TOKEN_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[5]","name":"tokenAmounts","type":"uint256[5]"},{"internalType":"bool","name":"isDeposit","type":"bool"}],"name":"calcTokenAmount","outputs":[{"internalType":"uint256","name":"sharesAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"contract IERC20[]","name":"rewardTokens","type":"address[]"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"converter","outputs":[{"internalType":"contract ITokenConverter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"crvUsdUsdcPool","outputs":[{"internalType":"contract ICurvePool2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ratioOfCrvLps","type":"uint256"},{"internalType":"uint256","name":"minDeflateAmount","type":"uint256"}],"name":"deflate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[5]","name":"amounts","type":"uint256[5]"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"liquidityValue","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositedLiquidity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ratioOfCrvLps","type":"uint256"},{"internalType":"uint256","name":"minInflatedAmount","type":"uint256"}],"name":"inflate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract IOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"contract ICurvePoolN","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"oracleAddr","type":"address"}],"name":"setPriceOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_slippage","type":"uint256"}],"name":"setSlippage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"converterAddr","type":"address"}],"name":"setTokenConverter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"zunamiAddr","type":"address"}],"name":"setZunamiPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slippage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenDecimalsMultipliers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokens","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalHoldings","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract IStakeDaoVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"poolTokenRatio","type":"uint256"},{"internalType":"uint256[5]","name":"tokenAmounts","type":"uint256[5]"}],"name":"withdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[5]","name":"minTokenAmounts","type":"uint256[5]"}],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"}],"name":"withdrawEmergency","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"zunamiController","outputs":[{"internalType":"contract IController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"zunamiPool","outputs":[{"internalType":"contract IPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"zunamiStable","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"}]