编译器
0.8.23+commit.f704f362
文件 1 的 10: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();
}
}
}
文件 2 的 10: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_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 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_CRVUSD_ADDRESS = 0xCeA18a8752bb7e7817F9AE7565328FE415C0f2cA;
address internal constant CVX_LLAMALEND_CRVUSD_REWARDS_ADDRESS =
0x4bf2d8484474170bff8a8c34475be3d87dFF28cA;
uint256 internal constant CVX_LLAMALEND_CRVUSD_PID = 325;
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;
address internal constant SDT_zunETH_frxETH_VAULT_ADDRESS =
0xAaE1Ae12d4C8b811DDa1188b01be23b4ab7C62D2;
address internal constant SDT_LLAMALEND_CRVUSD_VAULT_ADDRESS =
0xfa6D40573082D797CB3cC378c0837fB90eB043e5;
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;
}
文件 3 的 10: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);
}
文件 4 的 10: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);
}
文件 5 的 10: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;
}
文件 6 的 10:IPoolController.sol
pragma solidity ^0.8.23;
import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import './IPool.sol';
interface IPoolController is IERC20 {
function pool() external view returns (IPool);
function deposit(uint256[5] memory amounts, address receiver) external returns (uint256);
function withdraw(
uint256 stableAmount,
uint256[5] memory minTokenAmounts,
address receiver
) external;
}
文件 7 的 10: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);
}
文件 8 的 10: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);
}
文件 9 的 10: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;
}
}
文件 10 的 10:ZunamiDepositZap2.sol
pragma solidity ^0.8.23;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import '../interfaces/IPoolController.sol';
import '../interfaces/ITokenConverter.sol';
import '../utils/Constants.sol';
contract ZunamiDepositZap2 {
using SafeERC20 for IERC20;
error ZeroAddress();
error SameAddress();
uint8 public constant POOL_ASSETS = 5;
uint256 constant ZUNAMI_CRVUSD_TOKEN_ID = 3;
uint256 public constant MIN_AMOUNT_DENOMINATOR = 10000;
uint256 public constant MIN_AMOUNT = 9950;
IPool public immutable zunamiPool;
IPoolController public immutable apsController;
ITokenConverter public immutable converter;
constructor(address zunamiPoolAddr, address apsControllerAddr, address tokenConverterAddr) {
if (
zunamiPoolAddr == address(0) ||
apsControllerAddr == address(0) ||
tokenConverterAddr == address(0)
) revert ZeroAddress();
zunamiPool = IPool(zunamiPoolAddr);
apsController = IPoolController(apsControllerAddr);
converter = ITokenConverter(tokenConverterAddr);
}
function deposit(
uint256[POOL_ASSETS] memory amounts,
address receiver
) external returns (uint256 shares) {
if (receiver == address(0)) {
receiver = msg.sender;
}
IERC20[POOL_ASSETS] memory tokens = zunamiPool.tokens();
uint256[POOL_ASSETS] memory tokenDecimalsMultipliers = zunamiPool
.tokenDecimalsMultipliers();
for (uint256 i = 0; i < amounts.length; i++) {
uint256 amount = amounts[i];
IERC20 token = tokens[i];
uint256 tokenDecimalsMultiplier = tokenDecimalsMultipliers[i];
if (i == ZUNAMI_CRVUSD_TOKEN_ID) {
token = IERC20(Constants.CRVUSD_ADDRESS);
tokenDecimalsMultiplier = 1;
}
if (address(token) != address(0) && amount > 0) {
token.safeTransferFrom(msg.sender, address(this), amount);
token.safeTransfer(address(converter), amount);
converter.handle(
address(token),
address(zunamiPool),
amount,
(amount * tokenDecimalsMultiplier * MIN_AMOUNT) / MIN_AMOUNT_DENOMINATOR
);
}
}
uint256 zunStableBalance = zunamiPool.balanceOf(address(this));
IERC20(address(zunamiPool)).safeIncreaseAllowance(address(apsController), zunStableBalance);
return apsController.deposit([zunStableBalance, 0, 0, 0, 0], receiver);
}
}
{
"compilationTarget": {
"contracts/utils/ZunamiDepositZap2.sol": "ZunamiDepositZap2"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"zunamiPoolAddr","type":"address"},{"internalType":"address","name":"apsControllerAddr","type":"address"},{"internalType":"address","name":"tokenConverterAddr","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"SameAddress","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"MIN_AMOUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_AMOUNT_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL_ASSETS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"apsController","outputs":[{"internalType":"contract IPoolController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"converter","outputs":[{"internalType":"contract ITokenConverter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[5]","name":"amounts","type":"uint256[5]"},{"internalType":"address","name":"receiver","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"zunamiPool","outputs":[{"internalType":"contract IPool","name":"","type":"address"}],"stateMutability":"view","type":"function"}]