编译器
0.8.19+commit.7dd6d404
文件 1 的 8:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 8:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 3 的 8:CurveDepositZap.sol
pragma solidity 0.8.19;
import "Ownable.sol";
import "SafeERC20.sol";
import "IVault.sol";
interface ICurveToken {
function minter() external view returns (address);
}
interface ICurvePool {
function remove_liquidity_one_coin(
uint256 _burn_amount,
int128 i,
uint256 _min_received
) external returns (uint256);
function calc_withdraw_one_coin(uint256 _burn_amount, int128 i) external view returns (uint256);
function coins(uint256 arg0) external view returns (address);
function balances(uint256 i) external view returns (uint256);
}
interface ICurvePoolV2 {
function remove_liquidity_one_coin(
uint256 _burn_amount,
uint256 i,
uint256 _min_received
) external returns (uint256);
function gamma() external view returns (uint256);
function calc_token_amount(uint256[2] calldata amounts) external view returns (uint256);
function calc_withdraw_one_coin(uint256 _burn_amount, uint256 i) external view returns (uint256);
}
interface ICurvePool2 is ICurvePool {
function add_liquidity(uint256[2] calldata _amounts, uint256 _min_mint_amount) external returns (uint256);
function remove_liquidity(uint256 _burn_amount, uint256[2] calldata _min_amounts) external;
function calc_token_amount(uint256[2] calldata _amounts, bool _is_deposit) external view returns (uint256);
}
interface ICurvePool3 is ICurvePool {
function add_liquidity(uint256[3] calldata _amounts, uint256 _min_mint_amount) external returns (uint256);
function remove_liquidity(uint256 _burn_amount, uint256[3] calldata _min_amounts) external;
function calc_token_amount(uint256[3] calldata _amounts, bool _is_deposit) external view returns (uint256);
}
interface ICurvePool4 is ICurvePool {
function add_liquidity(uint256[4] calldata _amounts, uint256 _min_mint_amount) external returns (uint256);
function remove_liquidity(uint256 _burn_amount, uint256[4] calldata _min_amounts) external;
function calc_token_amount(uint256[4] calldata _amounts, bool _is_deposit) external view returns (uint256);
}
interface ICurvePoolNg {
function N_COINS() external view returns (uint256);
function add_liquidity(uint256[] calldata amounts, uint256 min_mint_amount) external returns (uint256);
function remove_liquidity(uint256 burn_amount, uint256[] calldata min_amounts) external;
function calc_token_amount(uint256[] calldata amounts, bool is_deposit) external view returns (uint256);
}
interface IDepositToken {
function emissionId() external view returns (uint256);
function lpToken() external view returns (address);
function deposit(address receiver, uint256 amount) external returns (bool);
function withdraw(address receiver, uint256 amount) external returns (bool);
}
contract CurveDepositZap is Ownable {
using SafeERC20 for IERC20;
struct CurvePool {
address pool;
bool isMetapool;
bool isCryptoswap;
bool isStableNg;
address[] coins;
}
IPrismaVault public immutable vault;
mapping(address lpToken => CurvePool) poolData;
mapping(address depositToken => address lpToken) depositTokenToLpToken;
event PoolAdded(address pool, address lpToken, bool isMetapool, bool isCryptoswap, address[] coins);
event DepositTokenRegistered(address depositToken, address pool);
constructor(IPrismaVault _vault, address[2][] memory _basePools) {
vault = _vault;
for (uint i = 0; i < _basePools.length; i++) {
addCurvePool(_basePools[i][0], _basePools[i][1]);
}
}
function getCoins(address depositToken) public view returns (address[] memory coins) {
(, CurvePool memory pool) = _getDepositTokenData(depositToken);
if (!pool.isMetapool) {
return pool.coins;
}
CurvePool memory basePool = poolData[pool.coins[1]];
coins = new address[](basePool.coins.length + 1);
coins[0] = pool.coins[0];
for (uint i = 1; i < coins.length; i++) {
coins[i] = basePool.coins[i - 1];
}
return coins;
}
function getAddLiquidityReceived(address depositToken, uint256[] memory amounts) external view returns (uint256) {
(, CurvePool memory pool) = _getDepositTokenData(depositToken);
if (pool.isMetapool) {
CurvePool memory basePool = poolData[pool.coins[1]];
require(amounts.length == basePool.coins.length + 1, "Incorrect amounts.length");
bool isBaseDeposit;
for (uint i = 1; i < amounts.length; i++) {
if (amounts[i] > 0) {
isBaseDeposit = true;
break;
}
}
if (isBaseDeposit) {
amounts[1] = _calcTokenAmount(basePool, 1, amounts);
} else {
amounts[1] = 0;
}
} else {
require(amounts.length == pool.coins.length, "Incorrect amounts.length");
}
return _calcTokenAmount(pool, 0, amounts);
}
function _calcTokenAmount(
CurvePool memory pool,
uint256 i,
uint256[] memory amounts
) internal view returns (uint256) {
uint256 numCoins = pool.coins.length;
if (pool.isStableNg) {
return ICurvePoolNg(pool.pool).calc_token_amount(amounts, true);
}
if (numCoins == 2) {
if (pool.isCryptoswap) {
return ICurvePoolV2(pool.pool).calc_token_amount([amounts[i], amounts[i + 1]]);
} else {
return ICurvePool2(pool.pool).calc_token_amount([amounts[i], amounts[i + 1]], true);
}
}
if (numCoins == 3) {
return ICurvePool3(pool.pool).calc_token_amount([amounts[i], amounts[i + 1], amounts[i + 2]], true);
}
if (numCoins == 4) {
return
ICurvePool4(pool.pool).calc_token_amount(
[amounts[i], amounts[i + 1], amounts[i + 2], amounts[i + 3]],
true
);
}
revert();
}
function getRemoveLiquidityReceived(
address depositToken,
uint256 burnAmount
) external view returns (uint256[] memory received) {
(address lpToken, CurvePool memory pool) = _getDepositTokenData(depositToken);
if (pool.isMetapool) {
CurvePool memory basePool = poolData[pool.coins[1]];
uint256 length = basePool.coins.length;
received = new uint256[](length + 1);
uint256 supply = IERC20(lpToken).totalSupply();
received[0] = (ICurvePool(pool.pool).balances(0) * burnAmount) / supply;
burnAmount = (ICurvePool(pool.pool).balances(1) * burnAmount) / supply;
supply = IERC20(pool.coins[1]).totalSupply();
for (uint i = 0; i < length; i++) {
received[i + 1] = (ICurvePool(basePool.pool).balances(i) * burnAmount) / supply;
}
return received;
} else {
uint256 length = pool.coins.length;
received = new uint256[](length);
uint256 supply = IERC20(lpToken).totalSupply();
for (uint i = 0; i < length; i++) {
received[i] = (ICurvePool(pool.pool).balances(i) * burnAmount) / supply;
}
return received;
}
}
function getRemoveLiquidityOneCoinReceived(
address depositToken,
uint256 burnAmount,
uint256 index
) external view returns (uint256) {
(, CurvePool memory pool) = _getDepositTokenData(depositToken);
if (index != 0 && pool.isMetapool) {
if (pool.isCryptoswap) {
burnAmount = ICurvePoolV2(pool.pool).calc_withdraw_one_coin(burnAmount, 1);
} else {
burnAmount = ICurvePool(pool.pool).calc_withdraw_one_coin(burnAmount, 1);
}
pool = poolData[pool.coins[1]];
index -= 1;
}
if (pool.isCryptoswap) {
return ICurvePoolV2(pool.pool).calc_withdraw_one_coin(burnAmount, index);
} else {
return ICurvePool(pool.pool).calc_withdraw_one_coin(burnAmount, int128(int256(index)));
}
}
function recoverERC20(IERC20 token, uint256 amount) external onlyOwner {
token.safeTransfer(msg.sender, amount);
}
function addCurvePool(address pool, address lpToken) public onlyOwner {
_addPoolData(pool, lpToken);
}
function registerDepositToken(address depositToken) external {
require(depositTokenToLpToken[depositToken] == address(0), "Already registered");
_getDepositTokenDataWrite(depositToken);
}
function _getDepositTokenData(address depositToken) internal view returns (address lpToken, CurvePool memory pd) {
lpToken = IDepositToken(depositToken).lpToken();
address pool = _getPoolFromLpToken(lpToken);
return (lpToken, _getPoolData(pool));
}
function _getDepositTokenDataWrite(address depositToken) internal returns (CurvePool memory pd) {
address lpToken = depositTokenToLpToken[depositToken];
if (lpToken != address(0)) return poolData[lpToken];
lpToken = IDepositToken(depositToken).lpToken();
depositTokenToLpToken[depositToken] = lpToken;
pd = poolData[lpToken];
if (pd.pool == address(0)) {
uint256 id = IDepositToken(depositToken).emissionId();
(address receiver, ) = vault.idToReceiver(id);
require(receiver == depositToken, "receiver != depositToken");
pd = _addPoolData(_getPoolFromLpToken(lpToken), lpToken);
}
IERC20(lpToken).safeApprove(depositToken, type(uint256).max);
emit DepositTokenRegistered(depositToken, pd.pool);
return pd;
}
function _addPoolData(address pool, address lpToken) internal returns (CurvePool memory pd) {
pd = _getPoolData(pool);
for (uint i = 0; i < pd.coins.length; i++) {
IERC20(pd.coins[i]).safeApprove(pd.pool, type(uint256).max);
}
poolData[lpToken] = pd;
emit PoolAdded(pd.pool, lpToken, pd.isMetapool, pd.isCryptoswap, pd.coins);
return pd;
}
function _getPoolData(address pool) internal view returns (CurvePool memory pd) {
pd.pool = pool;
address[] memory coins = new address[](4);
uint256 i;
for (; i < 4; i++) {
try ICurvePool(pool).coins(i) returns (address _coin) {
coins[i] = _coin;
} catch {
assembly {
mstore(coins, i)
}
break;
}
}
pd.coins = coins;
address lastCoin = coins[i - 1];
address basePool = poolData[lastCoin].pool;
if (basePool != address(0)) pd.isMetapool = true;
try ICurvePoolV2(pool).gamma() returns (uint256) {
pd.isCryptoswap = true;
} catch {
try ICurvePoolNg(pool).N_COINS() returns (uint256) {
pd.isStableNg = true;
} catch {}
}
return pd;
}
function _getPoolFromLpToken(address lpToken) internal view returns (address pool) {
try ICurveToken(lpToken).minter() returns (address _pool) {
pool = _pool;
} catch {
pool = lpToken;
}
return pool;
}
function addLiquidity(
address depositToken,
uint256[] memory amounts,
uint256 minReceived,
address receiver
) external returns (uint256 lpTokenAmount) {
CurvePool memory pool = _getDepositTokenDataWrite(depositToken);
if (amounts[0] > 0) IERC20(pool.coins[0]).safeTransferFrom(msg.sender, address(this), amounts[0]);
if (pool.isMetapool) {
CurvePool memory basePool = poolData[pool.coins[1]];
uint256 length = basePool.coins.length + 1;
require(amounts.length == length, "Incorrect amounts.length");
bool isBaseDeposit;
for (uint i = 1; i < length; i++) {
if (amounts[i] > 0) {
isBaseDeposit = true;
IERC20(basePool.coins[i - 1]).safeTransferFrom(msg.sender, address(this), amounts[i]);
}
}
if (isBaseDeposit) {
amounts[1] = _addLiquidity(basePool, length - 1, 1, amounts, 0);
} else {
amounts[1] = 0;
}
} else {
uint256 length = pool.coins.length;
require(amounts.length == length, "Incorrect amounts.length");
for (uint i = 1; i < length; i++) {
if (amounts[i] > 0) {
IERC20(pool.coins[i]).safeTransferFrom(msg.sender, address(this), amounts[i]);
}
}
}
lpTokenAmount = _addLiquidity(pool, pool.coins.length, 0, amounts, minReceived);
IDepositToken(depositToken).deposit(receiver, lpTokenAmount);
return lpTokenAmount;
}
function _addLiquidity(
CurvePool memory pool,
uint256 numCoins,
uint256 i,
uint256[] memory amounts,
uint256 minReceived
) internal returns (uint256) {
if (pool.isStableNg) {
return ICurvePoolNg(pool.pool).add_liquidity(amounts, minReceived);
}
if (numCoins == 2) {
return ICurvePool2(pool.pool).add_liquidity([amounts[i], amounts[i + 1]], minReceived);
}
if (numCoins == 3) {
return ICurvePool3(pool.pool).add_liquidity([amounts[i], amounts[i + 1], amounts[i + 2]], minReceived);
}
if (numCoins == 4) {
return
ICurvePool4(pool.pool).add_liquidity(
[amounts[i], amounts[i + 1], amounts[i + 2], amounts[i + 3]],
minReceived
);
}
revert();
}
function removeLiquidity(
address depositToken,
uint256 burnAmount,
uint256[] calldata minReceived,
address receiver
) external returns (uint256[] memory received) {
CurvePool memory pool = _getDepositTokenDataWrite(depositToken);
IERC20(depositToken).transferFrom(msg.sender, address(this), burnAmount);
IDepositToken(depositToken).withdraw(address(this), burnAmount);
if (pool.isMetapool) return _removeLiquidityMeta(pool, burnAmount, minReceived, receiver);
else return _removeLiquidityPlain(pool, burnAmount, minReceived, receiver);
}
function _removeLiquidityMeta(
CurvePool memory pool,
uint256 burnAmount,
uint256[] calldata minReceived,
address receiver
) internal returns (uint256[] memory) {
CurvePool memory basePool = poolData[pool.coins[1]];
uint256 length = basePool.coins.length;
require(minReceived.length == length + 1, "Incorrect minReceived.length");
uint256[] memory received = new uint256[](length + 1);
_removeLiquidity(pool, 2, burnAmount);
IERC20 coin = IERC20(pool.coins[0]);
uint256 amount = coin.balanceOf(address(this));
require(amount >= minReceived[0], "Slippage");
coin.safeTransfer(receiver, amount);
received[0] = amount;
burnAmount = IERC20(pool.coins[1]).balanceOf(address(this));
_removeLiquidity(basePool, length, burnAmount);
for (uint i = 0; i < length; i++) {
coin = IERC20(basePool.coins[i]);
amount = coin.balanceOf(address(this));
require(amount >= minReceived[i + 1], "Slippage");
coin.safeTransfer(receiver, amount);
received[i + 1] = amount;
}
return received;
}
function _removeLiquidityPlain(
CurvePool memory pool,
uint256 burnAmount,
uint256[] calldata minReceived,
address receiver
) internal returns (uint256[] memory) {
uint length = pool.coins.length;
require(minReceived.length == length, "Incorrect minReceived.length");
uint256[] memory received = new uint256[](length);
_removeLiquidity(pool, length, burnAmount);
for (uint i = 0; i < length; i++) {
IERC20 coin = IERC20(pool.coins[i]);
uint256 amount = coin.balanceOf(address(this));
require(amount >= minReceived[i], "Slippage");
coin.safeTransfer(receiver, amount);
received[i] = amount;
}
return received;
}
function _removeLiquidity(CurvePool memory pool, uint256 numCoins, uint256 burnAmount) internal {
if (pool.isStableNg) {
ICurvePoolNg(pool.pool).remove_liquidity(burnAmount, new uint256[](numCoins));
} else if (numCoins == 2) {
ICurvePool2(pool.pool).remove_liquidity(burnAmount, [uint256(0), uint256(0)]);
} else if (numCoins == 3) {
ICurvePool3(pool.pool).remove_liquidity(burnAmount, [uint256(0), uint256(0), uint256(0)]);
} else if (numCoins == 4) {
ICurvePool4(pool.pool).remove_liquidity(burnAmount, [uint256(0), uint256(0), uint256(0), uint256(0)]);
}
}
function removeLiquidityOneCoin(
address depositToken,
uint256 burnAmount,
uint256 index,
uint256 minReceived,
address receiver
) external returns (uint256) {
CurvePool memory pool = _getDepositTokenDataWrite(depositToken);
IERC20(depositToken).transferFrom(msg.sender, address(this), burnAmount);
IDepositToken(depositToken).withdraw(address(this), burnAmount);
if (index != 0 && pool.isMetapool) {
if (pool.isCryptoswap) {
burnAmount = ICurvePoolV2(pool.pool).remove_liquidity_one_coin(burnAmount, 1, 0);
} else {
burnAmount = ICurvePool(pool.pool).remove_liquidity_one_coin(burnAmount, 1, 0);
}
pool = poolData[pool.coins[1]];
index -= 1;
}
uint256 amount;
if (pool.isCryptoswap) {
amount = ICurvePoolV2(pool.pool).remove_liquidity_one_coin(burnAmount, index, minReceived);
} else {
amount = ICurvePool(pool.pool).remove_liquidity_one_coin(burnAmount, int128(int256(index)), minReceived);
}
IERC20(pool.coins[index]).safeTransfer(receiver, amount);
return amount;
}
function zapBetweenCurveConvex(
address srcToken,
address destToken,
uint256 amount,
address receiver
) external returns (bool) {
address srcPool = _getDepositTokenDataWrite(srcToken).pool;
address destPool = _getDepositTokenDataWrite(destToken).pool;
require(srcPool == destPool, "Pools use different LP tokens");
IERC20(srcToken).transferFrom(msg.sender, address(this), amount);
IDepositToken(srcToken).withdraw(address(this), amount);
IDepositToken(destToken).deposit(receiver, amount);
return true;
}
}
文件 4 的 8:IERC20.sol
pragma solidity ^0.8.0;
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 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
文件 5 的 8:IERC20Permit.sol
pragma solidity ^0.8.0;
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);
}
文件 6 的 8:IVault.sol
pragma solidity ^0.8.0;
interface IPrismaVault {
struct InitialAllowance {
address receiver;
uint256 amount;
}
event BoostCalculatorSet(address boostCalculator);
event BoostDelegationSet(address indexed boostDelegate, bool isEnabled, uint256 feePct, address callback);
event EmissionScheduleSet(address emissionScheduler);
event IncreasedAllocation(address indexed receiver, uint256 increasedAmount);
event NewReceiverRegistered(address receiver, uint256 id);
event ReceiverIsActiveStatusModified(uint256 indexed id, bool isActive);
event UnallocatedSupplyIncreased(uint256 increasedAmount, uint256 unallocatedTotal);
event UnallocatedSupplyReduced(uint256 reducedAmount, uint256 unallocatedTotal);
function allocateNewEmissions(uint256 id) external returns (uint256);
function batchClaimRewards(
address receiver,
address boostDelegate,
address[] calldata rewardContracts,
uint256 maxFeePct
) external returns (bool);
function increaseUnallocatedSupply(uint256 amount) external returns (bool);
function registerReceiver(address receiver, uint256 count) external returns (bool);
function setBoostCalculator(address _boostCalculator) external returns (bool);
function setBoostDelegationParams(bool isEnabled, uint256 feePct, address callback) external returns (bool);
function setEmissionSchedule(address _emissionSchedule) external returns (bool);
function setInitialParameters(
address _emissionSchedule,
address _boostCalculator,
uint256 totalSupply,
uint64 initialLockWeeks,
uint128[] calldata _fixedInitialAmounts,
InitialAllowance[] calldata initialAllowances
) external;
function setReceiverIsActive(uint256 id, bool isActive) external returns (bool);
function transferAllocatedTokens(address claimant, address receiver, uint256 amount) external returns (bool);
function transferTokens(address token, address receiver, uint256 amount) external returns (bool);
function PRISMA_CORE() external view returns (address);
function allocated(address) external view returns (uint256);
function boostCalculator() external view returns (address);
function boostDelegation(address) external view returns (bool isEnabled, uint16 feePct, address callback);
function claimableRewardAfterBoost(
address account,
address receiver,
address boostDelegate,
address rewardContract
) external view returns (uint256 adjustedAmount, uint256 feeToDelegate);
function emissionSchedule() external view returns (address);
function getClaimableWithBoost(address claimant) external view returns (uint256 maxBoosted, uint256 boosted);
function getWeek() external view returns (uint256 week);
function guardian() external view returns (address);
function idToReceiver(uint256) external view returns (address account, bool isActive);
function lockWeeks() external view returns (uint64);
function locker() external view returns (address);
function owner() external view returns (address);
function claimableBoostDelegationFees(address claimant) external view returns (uint256 amount);
function prismaToken() external view returns (address);
function receiverUpdatedWeek(uint256) external view returns (uint16);
function totalUpdateWeek() external view returns (uint64);
function unallocatedTotal() external view returns (uint128);
function voter() external view returns (address);
function weeklyEmissions(uint256) external view returns (uint128);
}
文件 7 的 8:Ownable.sol
pragma solidity ^0.8.0;
import "Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 8 的 8:SafeERC20.sol
pragma solidity ^0.8.0;
import "IERC20.sol";
import "IERC20Permit.sol";
import "Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
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.isContract(address(token));
}
}
{
"compilationTarget": {
"CurveDepositZap.sol": "CurveDepositZap"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IPrismaVault","name":"_vault","type":"address"},{"internalType":"address[2][]","name":"_basePools","type":"address[2][]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"depositToken","type":"address"},{"indexed":false,"internalType":"address","name":"pool","type":"address"}],"name":"DepositTokenRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"address","name":"lpToken","type":"address"},{"indexed":false,"internalType":"bool","name":"isMetapool","type":"bool"},{"indexed":false,"internalType":"bool","name":"isCryptoswap","type":"bool"},{"indexed":false,"internalType":"address[]","name":"coins","type":"address[]"}],"name":"PoolAdded","type":"event"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"lpToken","type":"address"}],"name":"addCurvePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"depositToken","type":"address"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256","name":"minReceived","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"lpTokenAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"depositToken","type":"address"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"getAddLiquidityReceived","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"depositToken","type":"address"}],"name":"getCoins","outputs":[{"internalType":"address[]","name":"coins","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"depositToken","type":"address"},{"internalType":"uint256","name":"burnAmount","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRemoveLiquidityOneCoinReceived","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"depositToken","type":"address"},{"internalType":"uint256","name":"burnAmount","type":"uint256"}],"name":"getRemoveLiquidityReceived","outputs":[{"internalType":"uint256[]","name":"received","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"depositToken","type":"address"}],"name":"registerDepositToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"depositToken","type":"address"},{"internalType":"uint256","name":"burnAmount","type":"uint256"},{"internalType":"uint256[]","name":"minReceived","type":"uint256[]"},{"internalType":"address","name":"receiver","type":"address"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256[]","name":"received","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"depositToken","type":"address"},{"internalType":"uint256","name":"burnAmount","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"minReceived","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"removeLiquidityOneCoin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract IPrismaVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"zapBetweenCurveConvex","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]