编译器
0.8.19+commit.7dd6d404
文件 1 的 28: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 的 28: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;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
文件 3 的 28:FixedPoint96.sol
pragma solidity >=0.4.0;
library FixedPoint96 {
uint8 internal constant RESOLUTION = 96;
uint256 internal constant Q96 = 0x1000000000000000000000000;
}
文件 4 的 28:IAlgebraSwapCallback.sol
pragma solidity >=0.5.0;
interface IAlgebraSwapCallback {
function algebraSwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata data
) external;
}
文件 5 的 28:ICamelotRouter.sol
pragma solidity >=0.6.2;
interface ICamelotRouter {
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
address referrer,
uint deadline
) external;
}
文件 6 的 28:ICurvePool.sol
pragma solidity ^0.8.19;
interface ICurvePool {
function coins(uint256 _idx) external returns (address);
function exchange(
int128 i,
int128 j,
uint256 dx,
uint256 minDy,
address receiver
) external returns (uint256);
}
文件 7 的 28:IDecentralizedIndex.sol
pragma solidity ^0.8.19;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
interface IDecentralizedIndex is IERC20 {
enum IndexType {
WEIGHTED,
UNWEIGHTED
}
struct Config {
address partner;
bool hasTransferTax;
bool blacklistTKNpTKNPoolV2;
}
struct Fees {
uint16 burn;
uint16 bond;
uint16 debond;
uint16 buy;
uint16 sell;
uint16 partner;
}
struct IndexAssetInfo {
address token;
uint256 weighting;
uint256 basePriceUSDX96;
address c1;
uint256 q1;
}
event Create(address indexed newIdx, address indexed wallet);
event Initialize(address indexed wallet, address v2Pool);
event Bond(
address indexed wallet,
address indexed token,
uint256 amountTokensBonded,
uint256 amountTokensMinted
);
event Debond(address indexed wallet, uint256 amountDebonded);
event AddLiquidity(
address indexed wallet,
uint256 amountTokens,
uint256 amountDAI
);
event RemoveLiquidity(address indexed wallet, uint256 amountLiquidity);
event SetPartner(address indexed wallet, address newPartner);
event SetPartnerFee(address indexed wallet, uint16 newFee);
function BOND_FEE() external view returns (uint16);
function DEBOND_FEE() external view returns (uint16);
function FLASH_FEE_AMOUNT_DAI() external view returns (uint256);
function PAIRED_LP_TOKEN() external view returns (address);
function indexType() external view returns (IndexType);
function created() external view returns (uint256);
function lpStakingPool() external view returns (address);
function lpRewardsToken() external view returns (address);
function partner() external view returns (address);
function getIdxPriceUSDX96() external view returns (uint256, uint256);
function isAsset(address token) external view returns (bool);
function getAllAssets() external view returns (IndexAssetInfo[] memory);
function getInitialAmount(
address sToken,
uint256 sAmount,
address tToken
) external view returns (uint256);
function getTokenPriceUSDX96(address token) external view returns (uint256);
function processPreSwapFeesAndSwap() external;
function bond(address token, uint256 amount, uint256 amountMintMin) external;
function debond(
uint256 amount,
address[] memory token,
uint8[] memory percentage
) external;
function addLiquidityV2(
uint256 idxTokens,
uint256 daiTokens,
uint256 slippage,
uint256 deadline
) external;
function removeLiquidityV2(
uint256 lpTokens,
uint256 minTokens,
uint256 minDAI,
uint256 deadline
) external;
function flash(
address recipient,
address token,
uint256 amount,
bytes calldata data
) external;
}
文件 8 的 28: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);
}
文件 9 的 28:IERC20Metadata.sol
pragma solidity ^0.8.19;
interface IERC20Metadata {
function decimals() external view returns (uint8);
}
文件 10 的 28: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);
}
文件 11 的 28:IERC4626.sol
pragma solidity ^0.8.19;
interface IERC4626 {
function deposit(
uint256 assets,
address receiver
) external returns (uint256 shares);
function withdraw(
uint256 assets,
address receiver,
address owner
) external returns (uint256 shares);
function redeem(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
}
文件 12 的 28:IPeripheryImmutableState.sol
pragma solidity >=0.5.0;
interface IPeripheryImmutableState {
function factory() external view returns (address);
function WETH9() external view returns (address);
}
文件 13 的 28:IStakingPoolToken.sol
pragma solidity ^0.8.19;
interface IStakingPoolToken {
event Stake(address indexed executor, address indexed user, uint256 amount);
event Unstake(address indexed user, uint256 amount);
function indexFund() external view returns (address);
function stakingToken() external view returns (address);
function poolRewards() external view returns (address);
function stakeUserRestriction() external view returns (address);
function stake(address user, uint256 amount) external;
function unstake(uint256 amount) external;
}
文件 14 的 28:ISwapRouter.sol
pragma solidity >=0.7.5;
pragma abicoder v2;
import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';
interface ISwapRouter is IUniswapV3SwapCallback {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}
文件 15 的 28:ISwapRouterAlgebra.sol
pragma solidity >=0.7.5;
pragma abicoder v2;
import './IAlgebraSwapCallback.sol';
interface ISwapRouterAlgebra is IAlgebraSwapCallback {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 limitSqrtPrice;
}
function exactInputSingle(
ExactInputSingleParams calldata params
) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
function exactInput(
ExactInputParams calldata params
) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 limitSqrtPrice;
}
function exactOutputSingle(
ExactOutputSingleParams calldata params
) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
function exactOutput(
ExactOutputParams calldata params
) external payable returns (uint256 amountIn);
function exactInputSingleSupportingFeeOnTransferTokens(
ExactInputSingleParams calldata params
) external returns (uint256 amountOut);
}
文件 16 的 28:ITokenRewards.sol
pragma solidity ^0.8.19;
interface ITokenRewards {
event AddShares(address indexed wallet, uint256 amount);
event RemoveShares(address indexed wallet, uint256 amount);
event ClaimReward(address indexed wallet);
event DistributeReward(
address indexed wallet,
address indexed token,
uint256 amount
);
event DepositRewards(
address indexed wallet,
address indexed token,
uint256 amount
);
function totalShares() external view returns (uint256);
function totalStakers() external view returns (uint256);
function rewardsToken() external view returns (address);
function trackingToken() external view returns (address);
function depositFromPairedLpToken(
uint256 amount,
uint256 slippageOverride
) external;
function depositRewards(address token, uint256 amount) external;
function claimReward(address wallet) external;
function setShares(
address wallet,
uint256 amount,
bool sharesRemoving
) external;
}
文件 17 的 28:IUniswapV2Factory.sol
pragma solidity ^0.8.19;
interface IUniswapV2Factory {
function createPair(
address tokenA,
address tokenB
) external returns (address pair);
function getPair(
address tokenA,
address tokenB
) external view returns (address pair);
}
文件 18 的 28:IUniswapV2Pair.sol
pragma solidity ^0.8.19;
interface IUniswapV2Pair {
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves()
external
view
returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
}
文件 19 的 28:IUniswapV2Router02.sol
pragma solidity ^0.8.19;
interface IUniswapV2Router02 {
function factory() external view returns (address);
function WETH() external view returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function swapETHForExactTokens(
uint256 amountOut,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
文件 20 的 28:IUniswapV3Pool.sol
pragma solidity ^0.8.19;
interface IUniswapV3Pool {
function token0() external view returns (address);
function token1() external view returns (address);
function fee() external view returns (uint24);
function observe(
uint32[] calldata secondsAgos
)
external
view
returns (
int56[] memory tickCumulatives,
uint160[] memory secondsPerLiquidityCumulativeX128s
);
function slot0()
external
view
returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
uint8 feeProtocol,
bool unlocked
);
}
文件 21 的 28:IUniswapV3SwapCallback.sol
pragma solidity >=0.5.0;
interface IUniswapV3SwapCallback {
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata data
) external;
}
文件 22 的 28:IV3TwapUtilities.sol
pragma solidity ^0.8.19;
interface IV3TwapUtilities {
function getV3Pool(
address v3Factory,
address token0,
address token1
) external view returns (address);
function getV3Pool(
address v3Factory,
address token0,
address token1,
uint24 poolFee
) external view returns (address);
function getPoolPriceUSDX96(
address pricePool,
address nativeStablePool,
address WETH9
) external view returns (uint256);
function sqrtPriceX96FromPoolAndInterval(
address pool
) external view returns (uint160);
function priceX96FromSqrtPriceX96(
uint160 sqrtPriceX96
) external pure returns (uint256);
}
文件 23 的 28:IWETH.sol
pragma solidity ^0.8.19;
interface IWETH {
function deposit() external payable;
function withdraw(uint256 _amount) external;
}
文件 24 的 28:IZapper.sol
pragma solidity ^0.8.19;
interface IZapper {
enum PoolType {
CURVE,
V2,
V3
}
struct Pools {
PoolType poolType;
address pool1;
address pool2;
}
}
文件 25 的 28:IndexUtils.sol
pragma solidity ^0.8.19;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';
import '@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol';
import '@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol';
import './interfaces/IDecentralizedIndex.sol';
import './interfaces/IERC20Metadata.sol';
import './interfaces/IStakingPoolToken.sol';
import './interfaces/ITokenRewards.sol';
import './interfaces/IUniswapV2Factory.sol';
import './interfaces/IUniswapV3Pool.sol';
import './interfaces/IUniswapV2Router02.sol';
import './interfaces/IWETH.sol';
import './Zapper.sol';
contract IndexUtils is Context, Zapper {
using SafeERC20 for IERC20;
constructor(
address _v2Router,
IV3TwapUtilities _v3TwapUtilities
) Zapper(_v2Router, _v3TwapUtilities) {}
function bond(
IDecentralizedIndex _indexFund,
address _token,
uint256 _amount,
uint256 _amountMintMin
) external {
IDecentralizedIndex.IndexAssetInfo[] memory _assets = _indexFund
.getAllAssets();
uint256[] memory _balsBefore = new uint256[](_assets.length);
uint256 _tokenCurSupply = IERC20(_token).balanceOf(address(_indexFund));
uint256 _tokenAmtSupplyRatioX96 = _indexFund.totalSupply() == 0
? FixedPoint96.Q96
: (_amount * FixedPoint96.Q96) / _tokenCurSupply;
uint256 _al = _assets.length;
for (uint256 _i; _i < _al; _i++) {
uint256 _amountNeeded = _indexFund.totalSupply() == 0
? _indexFund.getInitialAmount(_token, _amount, _assets[_i].token)
: (IERC20(_assets[_i].token).balanceOf(address(_indexFund)) *
_tokenAmtSupplyRatioX96) / FixedPoint96.Q96;
_balsBefore[_i] = IERC20(_assets[_i].token).balanceOf(address(this));
IERC20(_assets[_i].token).safeTransferFrom(
_msgSender(),
address(this),
_amountNeeded
);
IERC20(_assets[_i].token).safeIncreaseAllowance(
address(_indexFund),
_amountNeeded
);
}
uint256 _idxBalBefore = IERC20(_indexFund).balanceOf(address(this));
_indexFund.bond(_token, _amount, _amountMintMin);
IERC20(_indexFund).safeTransfer(
_msgSender(),
IERC20(_indexFund).balanceOf(address(this)) - _idxBalBefore
);
for (uint256 _i; _i < _al; _i++) {
_checkAndRefundERC20(_msgSender(), _assets[_i].token, _balsBefore[_i]);
}
}
function bondWeightedFromNative(
IDecentralizedIndex _indexFund,
uint256 _assetIdx,
uint256 _amountTokensForAssetIdx,
uint256 _amountMintMin,
uint256 _amountPairedLpTokenMin,
uint256 _slippage,
uint256 _deadline,
bool _stakeAsWell
) external payable {
require(msg.value > 0, 'NATIVE');
uint256 _ethBalBefore = address(this).balance - msg.value;
IDecentralizedIndex.IndexAssetInfo[] memory _assets = _indexFund
.getAllAssets();
(
uint256[] memory _balancesBefore,
uint256[] memory _amountsReceived
) = _swapNativeForTokensWeightedV2(
_indexFund,
_stakeAsWell ? msg.value / 2 : msg.value,
_assets,
_assetIdx,
_amountTokensForAssetIdx
);
for (uint256 _i; _i < _assets.length; _i++) {
if (_i == _assetIdx) {
continue;
}
IERC20(_assets[_i].token).safeIncreaseAllowance(
address(_indexFund),
_amountsReceived[_i]
);
}
uint256 _idxTokensGained = _bondToRecipient(
_indexFund,
_assets[_assetIdx].token,
_amountsReceived[_assetIdx],
_amountMintMin,
_stakeAsWell ? address(this) : _msgSender()
);
if (_stakeAsWell) {
_zapIndexTokensAndNative(
_msgSender(),
_indexFund,
_idxTokensGained,
msg.value / 2,
_amountPairedLpTokenMin,
_slippage,
_deadline
);
}
for (uint256 _i; _i < _assets.length; _i++) {
_checkAndRefundERC20(
_msgSender(),
_assets[_i].token,
_balancesBefore[_i]
);
}
if (address(this).balance > _ethBalBefore) {
(bool _s, ) = payable(_msgSender()).call{
value: address(this).balance - _ethBalBefore
}('');
require(_s, 'ETHREFUND');
}
}
function addLPAndStake(
IDecentralizedIndex _indexFund,
uint256 _amountIdxTokens,
address _pairedLpTokenProvided,
uint256 _amtPairedLpTokenProvided,
uint256 _amountPairedLpTokenMin,
uint256 _slippage,
uint256 _deadline
) external payable {
address _v2Pool = IUniswapV2Factory(V2_FACTORY).getPair(
address(_indexFund),
_indexFund.PAIRED_LP_TOKEN()
);
uint256 _idxTokensBefore = IERC20(address(_indexFund)).balanceOf(
address(this)
);
uint256 _pairedLpTokenBefore = IERC20(_indexFund.PAIRED_LP_TOKEN())
.balanceOf(address(this));
uint256 _ethBefore = address(this).balance - msg.value;
uint256 _v2PoolBefore = IERC20(_v2Pool).balanceOf(address(this));
IERC20(address(_indexFund)).safeTransferFrom(
_msgSender(),
address(this),
_amountIdxTokens
);
if (_pairedLpTokenProvided == address(0)) {
require(msg.value > 0, 'NEEDETH');
_amtPairedLpTokenProvided = msg.value;
} else {
IERC20(_pairedLpTokenProvided).safeTransferFrom(
_msgSender(),
address(this),
_amtPairedLpTokenProvided
);
}
if (_pairedLpTokenProvided != _indexFund.PAIRED_LP_TOKEN()) {
_zap(
_pairedLpTokenProvided,
_indexFund.PAIRED_LP_TOKEN(),
_amtPairedLpTokenProvided,
_amountPairedLpTokenMin
);
}
IERC20(_indexFund.PAIRED_LP_TOKEN()).safeIncreaseAllowance(
address(_indexFund),
IERC20(_indexFund.PAIRED_LP_TOKEN()).balanceOf(address(this)) -
_pairedLpTokenBefore
);
_indexFund.addLiquidityV2(
IERC20(address(_indexFund)).balanceOf(address(this)) - _idxTokensBefore,
IERC20(_indexFund.PAIRED_LP_TOKEN()).balanceOf(address(this)) -
_pairedLpTokenBefore,
_slippage,
_deadline
);
IERC20(_v2Pool).safeIncreaseAllowance(
_indexFund.lpStakingPool(),
IERC20(_v2Pool).balanceOf(address(this)) - _v2PoolBefore
);
IStakingPoolToken(_indexFund.lpStakingPool()).stake(
_msgSender(),
IERC20(_v2Pool).balanceOf(address(this)) - _v2PoolBefore
);
if (address(this).balance > _ethBefore) {
(bool _s, ) = payable(_msgSender()).call{
value: address(this).balance - _ethBefore
}('');
require(_s && address(this).balance >= _ethBefore, 'TOOMUCH');
}
_checkAndRefundERC20(_msgSender(), address(_indexFund), _idxTokensBefore);
_checkAndRefundERC20(
_msgSender(),
_indexFund.PAIRED_LP_TOKEN(),
_pairedLpTokenBefore
);
}
function unstakeAndRemoveLP(
IDecentralizedIndex _indexFund,
uint256 _amountStakedTokens,
uint256 _minLPTokens,
uint256 _minPairedLpToken,
uint256 _deadline
) external {
address _stakingPool = _indexFund.lpStakingPool();
address _pairedLpToken = _indexFund.PAIRED_LP_TOKEN();
uint256 _stakingBalBefore = IERC20(_stakingPool).balanceOf(address(this));
uint256 _pairedLpTokenBefore = IERC20(_pairedLpToken).balanceOf(
address(this)
);
IERC20(_stakingPool).safeTransferFrom(
_msgSender(),
address(this),
_amountStakedTokens
);
uint256 _indexBalBefore = _unstakeAndRemoveLP(
_indexFund,
_stakingPool,
IERC20(_stakingPool).balanceOf(address(this)) - _stakingBalBefore,
_minLPTokens,
_minPairedLpToken,
_deadline
);
if (
IERC20(address(_indexFund)).balanceOf(address(this)) > _indexBalBefore
) {
IERC20(address(_indexFund)).safeTransfer(
_msgSender(),
IERC20(address(_indexFund)).balanceOf(address(this)) - _indexBalBefore
);
}
if (
IERC20(_pairedLpToken).balanceOf(address(this)) > _pairedLpTokenBefore
) {
IERC20(_pairedLpToken).safeTransfer(
_msgSender(),
IERC20(_pairedLpToken).balanceOf(address(this)) - _pairedLpTokenBefore
);
}
}
function claimRewardsMulti(address[] memory _rewards) external {
uint256 _rl = _rewards.length;
for (uint256 _i; _i < _rl; _i++) {
ITokenRewards(_rewards[_i]).claimReward(_msgSender());
}
}
function _swapNativeForTokensWeightedV2(
IDecentralizedIndex _indexFund,
uint256 _amountNative,
IDecentralizedIndex.IndexAssetInfo[] memory _assets,
uint256 _poolIdx,
uint256 _amountForPoolIdx
) internal returns (uint256[] memory, uint256[] memory) {
uint256[] memory _amountBefore = new uint256[](_assets.length);
uint256[] memory _amountReceived = new uint256[](_assets.length);
uint256 _tokenCurSupply = IERC20(_assets[_poolIdx].token).balanceOf(
address(_indexFund)
);
uint256 _tokenAmtSupplyRatioX96 = _indexFund.totalSupply() == 0
? FixedPoint96.Q96
: (_amountForPoolIdx * FixedPoint96.Q96) / _tokenCurSupply;
uint256 _nativeLeft = _amountNative;
uint256 _al = _assets.length;
for (uint256 _i; _i < _al; _i++) {
(_nativeLeft, _amountBefore[_i], _amountReceived[_i]) = _swapForIdxToken(
_indexFund,
_assets[_poolIdx].token,
_amountForPoolIdx,
_assets[_i].token,
_tokenAmtSupplyRatioX96,
_nativeLeft
);
}
return (_amountBefore, _amountReceived);
}
function _swapForIdxToken(
IDecentralizedIndex _indexFund,
address _initToken,
uint256 _initTokenAmount,
address _outToken,
uint256 _tokenAmtSupplyRatioX96,
uint256 _nativeLeft
)
internal
returns (
uint256 _newNativeLeft,
uint256 _amountBefore,
uint256 _amountReceived
)
{
uint256 _nativeBefore = address(this).balance;
_amountBefore = IERC20(_outToken).balanceOf(address(this));
uint256 _amountOut = _indexFund.totalSupply() == 0
? _indexFund.getInitialAmount(_initToken, _initTokenAmount, _outToken)
: (IERC20(_outToken).balanceOf(address(_indexFund)) *
_tokenAmtSupplyRatioX96) / FixedPoint96.Q96;
address[] memory _path = new address[](2);
_path[0] = IUniswapV2Router02(V2_ROUTER).WETH();
_path[1] = _outToken;
IUniswapV2Router02(V2_ROUTER).swapETHForExactTokens{ value: _nativeLeft }(
_amountOut,
_path,
address(this),
block.timestamp
);
_newNativeLeft = _nativeLeft - (_nativeBefore - address(this).balance);
_amountReceived =
IERC20(_outToken).balanceOf(address(this)) -
_amountBefore;
}
function _unstakeAndRemoveLP(
IDecentralizedIndex _indexFund,
address _stakingPool,
uint256 _unstakeAmount,
uint256 _minLPTokens,
uint256 _minPairedLpTokens,
uint256 _deadline
) internal returns (uint256 _fundTokensBefore) {
address _pairedLpToken = _indexFund.PAIRED_LP_TOKEN();
address _v2Pool = IUniswapV2Factory(V2_FACTORY).getPair(
address(_indexFund),
_pairedLpToken
);
uint256 _v2TokensBefore = IERC20(_v2Pool).balanceOf(address(this));
IStakingPoolToken(_stakingPool).unstake(_unstakeAmount);
_fundTokensBefore = _indexFund.balanceOf(address(this));
IERC20(_v2Pool).safeIncreaseAllowance(
address(_indexFund),
IERC20(_v2Pool).balanceOf(address(this)) - _v2TokensBefore
);
_indexFund.removeLiquidityV2(
IERC20(_v2Pool).balanceOf(address(this)) - _v2TokensBefore,
_minLPTokens,
_minPairedLpTokens,
_deadline
);
}
function _bondToRecipient(
IDecentralizedIndex _indexFund,
address _indexToken,
uint256 _bondTokens,
uint256 _amountMintMin,
address _recipient
) internal returns (uint256) {
uint256 _idxTokensBefore = IERC20(address(_indexFund)).balanceOf(
address(this)
);
IERC20(_indexToken).safeIncreaseAllowance(address(_indexFund), _bondTokens);
_indexFund.bond(_indexToken, _bondTokens, _amountMintMin);
uint256 _idxTokensGained = IERC20(address(_indexFund)).balanceOf(
address(this)
) - _idxTokensBefore;
if (_recipient != address(this)) {
IERC20(address(_indexFund)).safeTransfer(_recipient, _idxTokensGained);
}
return _idxTokensGained;
}
function _zapIndexTokensAndNative(
address _user,
IDecentralizedIndex _indexFund,
uint256 _amountTokens,
uint256 _amountETH,
uint256 _amtPairedLpTokenMin,
uint256 _slippage,
uint256 _deadline
) internal {
address _pairedLpToken = _indexFund.PAIRED_LP_TOKEN();
uint256 _tokensBefore = IERC20(address(_indexFund)).balanceOf(
address(this)
) - _amountTokens;
uint256 _pairedLpTokenBefore = IERC20(_pairedLpToken).balanceOf(
address(this)
);
address _stakingPool = _indexFund.lpStakingPool();
_zap(address(0), _pairedLpToken, _amountETH, _amtPairedLpTokenMin);
address _v2Pool = IUniswapV2Factory(V2_FACTORY).getPair(
address(_indexFund),
_pairedLpToken
);
uint256 _lpTokensBefore = IERC20(_v2Pool).balanceOf(address(this));
IERC20(_pairedLpToken).safeIncreaseAllowance(
address(_indexFund),
IERC20(_pairedLpToken).balanceOf(address(this)) - _pairedLpTokenBefore
);
_indexFund.addLiquidityV2(
_amountTokens,
IERC20(_pairedLpToken).balanceOf(address(this)) - _pairedLpTokenBefore,
_slippage,
_deadline
);
IERC20(_v2Pool).safeIncreaseAllowance(
_stakingPool,
IERC20(_v2Pool).balanceOf(address(this)) - _lpTokensBefore
);
IStakingPoolToken(_stakingPool).stake(
_user,
IERC20(_v2Pool).balanceOf(address(this)) - _lpTokensBefore
);
if (IERC20(address(_indexFund)).balanceOf(address(this)) > _tokensBefore) {
IERC20(address(_indexFund)).safeTransfer(
_user,
IERC20(address(_indexFund)).balanceOf(address(this)) - _tokensBefore
);
}
if (
IERC20(_pairedLpToken).balanceOf(address(this)) > _pairedLpTokenBefore
) {
IERC20(_pairedLpToken).safeTransfer(
_user,
IERC20(_pairedLpToken).balanceOf(address(this)) - _pairedLpTokenBefore
);
}
}
function _checkAndRefundERC20(
address _user,
address _asset,
uint256 _beforeBal
) internal {
uint256 _curBal = IERC20(_asset).balanceOf(address(this));
if (_curBal > _beforeBal) {
IERC20(_asset).safeTransfer(_user, _curBal - _beforeBal);
}
}
}
文件 26 的 28:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/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);
}
}
文件 27 的 28:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/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));
}
}
文件 28 的 28:Zapper.sol
pragma solidity ^0.8.19;
import '@openzeppelin/contracts/access/Ownable.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';
import '@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol';
import '@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol';
import './interfaces/ICurvePool.sol';
import './interfaces/IDecentralizedIndex.sol';
import './interfaces/IERC4626.sol';
import './interfaces/ICamelotRouter.sol';
import './interfaces/ISwapRouterAlgebra.sol';
import './interfaces/IUniswapV2Pair.sol';
import './interfaces/IUniswapV3Pool.sol';
import './interfaces/IUniswapV2Router02.sol';
import './interfaces/IV3TwapUtilities.sol';
import './interfaces/IWETH.sol';
import './interfaces/IZapper.sol';
contract Zapper is IZapper, Context, Ownable {
using SafeERC20 for IERC20;
address constant STYETH = 0x583019fF0f430721aDa9cfb4fac8F06cA104d0B4;
address constant YETH = 0x1BED97CBC3c24A4fb5C069C6E311a967386131f7;
address constant WETH_YETH_POOL = 0x69ACcb968B19a53790f43e57558F5E443A91aF22;
address constant V3_ROUTER = 0x1F721E2E82F6676FCE4eA07A5958cF098D339e18;
address immutable V2_ROUTER;
address immutable V2_FACTORY;
address immutable WETH;
IV3TwapUtilities immutable V3_TWAP_UTILS;
uint256 _slippage = 30;
address public OHM = 0x64aa3364F17a4D01c6f1751Fd97C2BD3D7e7f1D5;
address public pOHM;
mapping(address => mapping(address => Pools)) public zapMap;
mapping(address => mapping(address => int128)) public curveTokenIdx;
constructor(address _v2Router, IV3TwapUtilities _v3TwapUtilities) {
V2_ROUTER = _v2Router;
V2_FACTORY = IUniswapV2Router02(_v2Router).factory();
V3_TWAP_UTILS = _v3TwapUtilities;
WETH = IUniswapV2Router02(_v2Router).WETH();
if (block.chainid == 1) {
_setZapMapFromPoolSingle(
PoolType.CURVE,
0x69ACcb968B19a53790f43e57558F5E443A91aF22
);
_setZapMapFromPoolSingle(
PoolType.V3,
0x60594a405d53811d3BC4766596EFD80fd545A270
);
_setZapMapFromPoolSingle(
PoolType.V3,
0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640
);
_setZapMapFromPoolSingle(
PoolType.V3,
0x88051B0eea095007D3bEf21aB287Be961f3d8598
);
_setZapMapFromPoolSingle(
PoolType.V3,
0x893f503FaC2Ee1e5B78665db23F9c94017Aae97D
);
}
}
function _zap(
address _in,
address _out,
uint256 _amountIn,
uint256 _amountOutMin
) internal returns (uint256 _amountOut) {
if (_in == address(0)) {
_amountIn = _ethToWETH(_amountIn);
_in = WETH;
if (_out == WETH) {
return _amountIn;
}
}
bool _isOutPOHM;
if (pOHM == _out) {
_isOutPOHM = true;
_out = OHM;
}
if (_out == YETH || _out == STYETH) {
require(_in == WETH, 'YETHIN');
return _wethToYeth(_amountIn, _amountOutMin, _out == STYETH);
} else if (_in == YETH || _in == STYETH) {
require(_out == WETH, 'YETHOUT');
return _styethToWeth(_amountIn, _amountOutMin, _in == YETH);
}
Pools memory _poolInfo = zapMap[_in][_out];
if (_poolInfo.pool1 == address(0)) {
address[] memory _path = new address[](2);
_path[0] = _in;
_path[1] = _out;
_amountOut = _swapV2(_path, _amountIn, _amountOutMin);
} else {
bool _twoHops = _poolInfo.pool2 != address(0);
if (_poolInfo.poolType == PoolType.CURVE) {
_amountOut = _swapCurve(
_poolInfo.pool1,
curveTokenIdx[_poolInfo.pool1][_in],
curveTokenIdx[_poolInfo.pool1][_out],
_amountIn,
_amountOutMin
);
} else if (_poolInfo.poolType == PoolType.V2) {
address _token0 = IUniswapV2Pair(_poolInfo.pool1).token0();
address[] memory _path = new address[](_twoHops ? 3 : 2);
_path[0] = _in;
_path[1] = !_twoHops ? _out : _token0 == _in
? IUniswapV2Pair(_poolInfo.pool1).token1()
: _token0;
if (_twoHops) {
_path[2] = _out;
}
_amountOut = _swapV2(_path, _amountIn, _amountOutMin);
} else {
if (_twoHops) {
address _t0 = IUniswapV3Pool(_poolInfo.pool1).token0();
_amountOut = _swapV3Multi(
_in,
block.chainid == 42161 ? 0 : IUniswapV3Pool(_poolInfo.pool1).fee(),
_t0 == _in ? IUniswapV3Pool(_poolInfo.pool1).token1() : _t0,
block.chainid == 42161 ? 0 : IUniswapV3Pool(_poolInfo.pool2).fee(),
_out,
_amountIn,
_amountOutMin
);
} else {
_amountOut = _swapV3Single(
_in,
block.chainid == 42161 ? 0 : IUniswapV3Pool(_poolInfo.pool1).fee(),
_out,
_amountIn,
_amountOutMin
);
}
}
}
if (!_isOutPOHM) {
return _amountOut;
}
uint256 _pOHMBefore = IERC20(pOHM).balanceOf(address(this));
IERC20(OHM).safeIncreaseAllowance(pOHM, _amountOut);
IDecentralizedIndex(pOHM).bond(OHM, _amountOut, 0);
return IERC20(pOHM).balanceOf(address(this)) - _pOHMBefore;
}
function _ethToWETH(uint256 _amountETH) internal returns (uint256) {
uint256 _wethBal = IERC20(WETH).balanceOf(address(this));
IWETH(WETH).deposit{ value: _amountETH }();
return IERC20(WETH).balanceOf(address(this)) - _wethBal;
}
function _swapV3Single(
address _in,
uint24 _fee,
address _out,
uint256 _amountIn,
uint256 _amountOutMin
) internal returns (uint256) {
if (_amountOutMin == 0) {
address _v3Pool;
try
V3_TWAP_UTILS.getV3Pool(
IPeripheryImmutableState(V3_ROUTER).factory(),
_in,
_out,
_fee
)
returns (address __v3Pool) {
_v3Pool = __v3Pool;
} catch {
_v3Pool = V3_TWAP_UTILS.getV3Pool(
IPeripheryImmutableState(V3_ROUTER).factory(),
_in,
_out
);
}
address _token0 = _in < _out ? _in : _out;
uint256 _poolPriceX96 = V3_TWAP_UTILS.priceX96FromSqrtPriceX96(
V3_TWAP_UTILS.sqrtPriceX96FromPoolAndInterval(_v3Pool)
);
_amountOutMin = _in == _token0
? (_poolPriceX96 * _amountIn) / FixedPoint96.Q96
: (_amountIn * FixedPoint96.Q96) / _poolPriceX96;
}
uint256 _outBefore = IERC20(_out).balanceOf(address(this));
IERC20(_in).safeIncreaseAllowance(V3_ROUTER, _amountIn);
if (block.chainid == 42161) {
ISwapRouterAlgebra(V3_ROUTER).exactInputSingle(
ISwapRouterAlgebra.ExactInputSingleParams({
tokenIn: _in,
tokenOut: _out,
recipient: address(this),
deadline: block.timestamp,
amountIn: _amountIn,
amountOutMinimum: (_amountOutMin * (1000 - _slippage)) / 1000,
limitSqrtPrice: 0
})
);
} else {
ISwapRouter(V3_ROUTER).exactInputSingle(
ISwapRouter.ExactInputSingleParams({
tokenIn: _in,
tokenOut: _out,
fee: _fee,
recipient: address(this),
deadline: block.timestamp,
amountIn: _amountIn,
amountOutMinimum: (_amountOutMin * (1000 - _slippage)) / 1000,
sqrtPriceLimitX96: 0
})
);
}
return IERC20(_out).balanceOf(address(this)) - _outBefore;
}
function _swapV3Multi(
address _in,
uint24 _fee1,
address _in2,
uint24 _fee2,
address _out,
uint256 _amountIn,
uint256 _amountOutMin
) internal returns (uint256) {
uint256 _outBefore = IERC20(_out).balanceOf(address(this));
IERC20(_in).safeIncreaseAllowance(V3_ROUTER, _amountIn);
bytes memory _path = abi.encodePacked(_in, _fee1, _in2, _fee2, _out);
ISwapRouter(V3_ROUTER).exactInput(
ISwapRouter.ExactInputParams({
path: _path,
recipient: address(this),
deadline: block.timestamp,
amountIn: _amountIn,
amountOutMinimum: _amountOutMin
})
);
return IERC20(_out).balanceOf(address(this)) - _outBefore;
}
function _swapV2(
address[] memory _path,
uint256 _amountIn,
uint256 _amountOutMin
) internal returns (uint256) {
address _out = _path.length == 3 ? _path[2] : _path[1];
uint256 _outBefore = IERC20(_out).balanceOf(address(this));
IERC20(_path[0]).safeIncreaseAllowance(V2_ROUTER, _amountIn);
if (block.chainid == 42161) {
ICamelotRouter(V2_ROUTER)
.swapExactTokensForTokensSupportingFeeOnTransferTokens(
_amountIn,
_amountOutMin,
_path,
address(this),
Ownable(address(V3_TWAP_UTILS)).owner(),
block.timestamp
);
} else {
IUniswapV2Router02(V2_ROUTER)
.swapExactTokensForTokensSupportingFeeOnTransferTokens(
_amountIn,
_amountOutMin,
_path,
address(this),
block.timestamp
);
}
return IERC20(_out).balanceOf(address(this)) - _outBefore;
}
function _swapCurve(
address _pool,
int128 _i,
int128 _j,
uint256 _amountIn,
uint256 _amountOutMin
) internal returns (uint256) {
IERC20(ICurvePool(_pool).coins(uint128(_i))).safeIncreaseAllowance(
_pool,
_amountIn
);
return
ICurvePool(_pool).exchange(
_i,
_j,
_amountIn,
_amountOutMin,
address(this)
);
}
function _wethToYeth(
uint256 _ethAmount,
uint256 _minYethAmount,
bool _stakeToStyeth
) internal returns (uint256) {
uint256 _boughtYeth = _swapCurve(
WETH_YETH_POOL,
0,
1,
_ethAmount,
_minYethAmount
);
if (_stakeToStyeth) {
IERC20(YETH).safeIncreaseAllowance(STYETH, _boughtYeth);
return IERC4626(STYETH).deposit(_boughtYeth, address(this));
}
return _boughtYeth;
}
function _styethToWeth(
uint256 _stYethAmount,
uint256 _minWethAmount,
bool _isYethOnly
) internal returns (uint256) {
uint256 _yethAmount;
if (_isYethOnly) {
_yethAmount = _stYethAmount;
} else {
_yethAmount = IERC4626(STYETH).redeem(
_stYethAmount,
address(this),
address(this)
);
}
return _swapCurve(WETH_YETH_POOL, 1, 0, _yethAmount, _minWethAmount);
}
function _setZapMapFromPoolSingle(PoolType _type, address _pool) internal {
address _t0;
address _t1;
if (_type == PoolType.CURVE) {
_t0 = ICurvePool(_pool).coins(0);
_t1 = ICurvePool(_pool).coins(1);
curveTokenIdx[_pool][_t0] = 0;
curveTokenIdx[_pool][_t1] = 1;
} else {
_t0 = IUniswapV3Pool(_pool).token0();
_t1 = IUniswapV3Pool(_pool).token1();
}
Pools memory _poolConf = Pools({
poolType: _type,
pool1: _pool,
pool2: address(0)
});
zapMap[_t0][_t1] = _poolConf;
zapMap[_t1][_t0] = _poolConf;
}
function setOHM(address _OHM, address _pOHM) external onlyOwner {
OHM = _OHM == address(0) ? OHM : _OHM;
pOHM = _pOHM == address(0) ? pOHM : _pOHM;
}
function setSlippage(uint256 _slip) external onlyOwner {
require(_slip >= 0 && _slip <= 1000, 'BOUNDS');
_slippage = _slip;
}
function setZapMap(
address _in,
address _out,
Pools memory _pools
) external onlyOwner {
zapMap[_in][_out] = _pools;
}
function setZapMapFromPoolSingle(
PoolType _type,
address _pool
) external onlyOwner {
_setZapMapFromPoolSingle(_type, _pool);
}
function rescueETH() external onlyOwner {
(bool _sent, ) = payable(owner()).call{ value: address(this).balance }('');
require(_sent);
}
function rescueERC20(IERC20 _token) external onlyOwner {
require(_token.balanceOf(address(this)) > 0);
_token.safeTransfer(owner(), _token.balanceOf(address(this)));
}
receive() external payable {}
}
{
"compilationTarget": {
"contracts/IndexUtils.sol": "IndexUtils"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "none"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_v2Router","type":"address"},{"internalType":"contract IV3TwapUtilities","name":"_v3TwapUtilities","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"OHM","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IDecentralizedIndex","name":"_indexFund","type":"address"},{"internalType":"uint256","name":"_amountIdxTokens","type":"uint256"},{"internalType":"address","name":"_pairedLpTokenProvided","type":"address"},{"internalType":"uint256","name":"_amtPairedLpTokenProvided","type":"uint256"},{"internalType":"uint256","name":"_amountPairedLpTokenMin","type":"uint256"},{"internalType":"uint256","name":"_slippage","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"}],"name":"addLPAndStake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IDecentralizedIndex","name":"_indexFund","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_amountMintMin","type":"uint256"}],"name":"bond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IDecentralizedIndex","name":"_indexFund","type":"address"},{"internalType":"uint256","name":"_assetIdx","type":"uint256"},{"internalType":"uint256","name":"_amountTokensForAssetIdx","type":"uint256"},{"internalType":"uint256","name":"_amountMintMin","type":"uint256"},{"internalType":"uint256","name":"_amountPairedLpTokenMin","type":"uint256"},{"internalType":"uint256","name":"_slippage","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"bool","name":"_stakeAsWell","type":"bool"}],"name":"bondWeightedFromNative","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_rewards","type":"address[]"}],"name":"claimRewardsMulti","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"curveTokenIdx","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pOHM","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"}],"name":"rescueERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rescueETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_OHM","type":"address"},{"internalType":"address","name":"_pOHM","type":"address"}],"name":"setOHM","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_slip","type":"uint256"}],"name":"setSlippage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_in","type":"address"},{"internalType":"address","name":"_out","type":"address"},{"components":[{"internalType":"enum IZapper.PoolType","name":"poolType","type":"uint8"},{"internalType":"address","name":"pool1","type":"address"},{"internalType":"address","name":"pool2","type":"address"}],"internalType":"struct IZapper.Pools","name":"_pools","type":"tuple"}],"name":"setZapMap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum IZapper.PoolType","name":"_type","type":"uint8"},{"internalType":"address","name":"_pool","type":"address"}],"name":"setZapMapFromPoolSingle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IDecentralizedIndex","name":"_indexFund","type":"address"},{"internalType":"uint256","name":"_amountStakedTokens","type":"uint256"},{"internalType":"uint256","name":"_minLPTokens","type":"uint256"},{"internalType":"uint256","name":"_minPairedLpToken","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"}],"name":"unstakeAndRemoveLP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"zapMap","outputs":[{"internalType":"enum IZapper.PoolType","name":"poolType","type":"uint8"},{"internalType":"address","name":"pool1","type":"address"},{"internalType":"address","name":"pool2","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]