Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
IndexUtils
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.28;
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/IDexAdapter.sol";
import "./interfaces/IIndexUtils.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, IIndexUtils, Zapper {
using SafeERC20 for IERC20;
constructor(IV3TwapUtilities _v3TwapUtilities, IDexAdapter _dexAdapter) Zapper(_v3TwapUtilities, _dexAdapter) {}
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 = _indexFund.totalAssets(_token);
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)
: (_indexFund.totalAssets(_assets[_i].token) * _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);
// refund any excess tokens to user we didn't use to bond
for (uint256 _i; _i < _al; _i++) {
_checkAndRefundERC20(_msgSender(), _assets[_i].token, _balsBefore[_i]);
}
}
function addLPAndStake(
IDecentralizedIndex _indexFund,
uint256 _amountIdxTokens,
address _pairedLpTokenProvided,
uint256 _amtPairedLpTokenProvided,
uint256 _amountPairedLpTokenMin,
uint256 _slippage,
uint256 _deadline
) external payable override returns (uint256 _amountOut) {
address _indexFundAddy = address(_indexFund);
address _pairedLpToken = _indexFund.PAIRED_LP_TOKEN();
uint256 _idxTokensBefore = IERC20(_indexFundAddy).balanceOf(address(this));
uint256 _pairedLpTokenBefore = IERC20(_pairedLpToken).balanceOf(address(this));
uint256 _ethBefore = address(this).balance - msg.value;
IERC20(_indexFundAddy).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 != _pairedLpToken) {
_zap(_pairedLpTokenProvided, _pairedLpToken, _amtPairedLpTokenProvided, _amountPairedLpTokenMin);
}
IERC20(_pairedLpToken).safeIncreaseAllowance(
_indexFundAddy, IERC20(_pairedLpToken).balanceOf(address(this)) - _pairedLpTokenBefore
);
// keeping 1 wei of each asset on the CA reduces transfer gas cost due to non-zero storage
// so worth it to keep 1 wei in the CA if there's not any here already
_amountOut = _indexFund.addLiquidityV2(
IERC20(_indexFundAddy).balanceOf(address(this)) - (_idxTokensBefore == 0 ? 1 : _idxTokensBefore),
IERC20(_pairedLpToken).balanceOf(address(this)) - (_pairedLpTokenBefore == 0 ? 1 : _pairedLpTokenBefore),
_slippage,
_deadline
);
require(_amountOut > 0, "LPM");
IERC20(DEX_ADAPTER.getV2Pool(_indexFundAddy, _pairedLpToken)).safeIncreaseAllowance(
_indexFund.lpStakingPool(), _amountOut
);
_amountOut = _stakeLPForUserHandlingLeftoverCheck(_indexFund.lpStakingPool(), _msgSender(), _amountOut);
// refunds if needed for index tokens and pairedLpToken
if (address(this).balance > _ethBefore) {
(bool _s,) = payable(_msgSender()).call{value: address(this).balance - _ethBefore}("");
require(_s && address(this).balance >= _ethBefore, "TOOMUCH");
}
_checkAndRefundERC20(_msgSender(), _indexFundAddy, _idxTokensBefore == 0 ? 1 : _idxTokensBefore);
_checkAndRefundERC20(_msgSender(), _pairedLpToken, _pairedLpTokenBefore == 0 ? 1 : _pairedLpTokenBefore);
}
function unstakeAndRemoveLP(
IDecentralizedIndex _indexFund,
uint256 _amountStakedTokens,
uint256 _minLPTokens,
uint256 _minPairedLpToken,
uint256 _deadline
) external override {
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());
}
}
/// @dev the ERC20 approval for the input token to stake has already been approved
function _stakeLPForUserHandlingLeftoverCheck(address _stakingPool, address _receiver, uint256 _stakeAmount)
internal
returns (uint256 _finalAmountOut)
{
_finalAmountOut = _stakeAmount;
if (IERC20(_stakingPool).balanceOf(address(this)) > 0) {
IStakingPoolToken(_stakingPool).stake(_receiver, _stakeAmount);
return _finalAmountOut;
}
IStakingPoolToken(_stakingPool).stake(address(this), _stakeAmount);
// leave 1 wei in the CA for future gas savings
_finalAmountOut = IERC20(_stakingPool).balanceOf(address(this)) - 1;
IERC20(_stakingPool).safeTransfer(_receiver, _finalAmountOut);
}
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 = DEX_ADAPTER.getV2Pool(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 _checkAndRefundERC20(address _user, address _asset, uint256 _beforeBal) internal {
uint256 _curBal = IERC20(_asset).balanceOf(address(this));
if (_curBal > _beforeBal) {
IERC20(_asset).safeTransfer(_user, _curBal - _beforeBal);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
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);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
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);
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.4.0;
/// @title FixedPoint96
/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)
/// @dev Used in SqrtPriceMath.sol
library FixedPoint96 {
uint8 internal constant RESOLUTION = 96;
uint256 internal constant Q96 = 0x1000000000000000000000000;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Immutable state
/// @notice Functions that return immutable state of the router
interface IPeripheryImmutableState {
/// @return Returns the address of the Uniswap V3 factory
function factory() external view returns (address);
/// @return Returns the address of WETH9
function WETH9() external view returns (address);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;
import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';
/// @title Router token swapping functionality
/// @notice Functions for swapping tokens via Uniswap V3
interface ISwapRouter is IUniswapV3SwapCallback {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another token
/// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata
/// @return amountOut The amount of the received token
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
/// @return amountOut The amount of the received token
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;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another token
/// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata
/// @return amountIn The amount of the input token
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
/// @return amountIn The amount of the input token
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./IDexAdapter.sol";
interface IDecentralizedIndex is IERC20 {
enum IndexType {
WEIGHTED,
UNWEIGHTED
}
struct Config {
address partner;
uint256 debondCooldown;
bool hasTransferTax;
bool blacklistTKNpTKNPoolV2;
}
// all fees: 1 == 0.01%, 10 == 0.1%, 100 == 1%
struct Fees {
uint16 burn;
uint16 bond;
uint16 debond;
uint16 buy;
uint16 sell;
uint16 partner;
}
struct IndexAssetInfo {
address token;
uint256 weighting;
uint256 basePriceUSDX96;
address c1; // arbitrary contract/address field we can use for an index
uint256 q1; // arbitrary quantity/number field we can use for an index
}
/// @notice The ```Create``` event fires when a new decentralized index has been created
/// @param newIdx The CA of the new index contract
/// @param wallet The creator of the new index
event Create(address indexed newIdx, address indexed wallet);
/// @notice The ```Initialize``` event fires when the new pod has been initialized,
/// @notice which is at creation on some and in another txn for others (gas limits)
/// @param wallet The wallet that initialized
/// @param v2Pool The new UniV2 derivative pool that was created at initialization
event Initialize(address indexed wallet, address v2Pool);
/// @notice The ```Bond``` event fires when someone wraps into the pod which mints new pod tokens
/// @param wallet The wallet that wrapped
/// @param token The token that was used as a ref to wrap into, representing an underlying tkn
/// @param amountTokensBonded Amount of underlying tkns used to wrap/bond
/// @param amountTokensMinted Amount of new pod tokens (pTKN) minted
event Bond(address indexed wallet, address indexed token, uint256 amountTokensBonded, uint256 amountTokensMinted);
/// @notice The ```Debond``` event fires when someone unwraps from a pod and redeems underlying tkn(s)
/// @param wallet The wallet that unwrapped/debond
/// @param amountDebonded Amount of pTKNs burned/unwrapped
event Debond(address indexed wallet, uint256 amountDebonded);
/// @notice The ```AddLiquidity``` event fires when new liquidity (LP) for a pod is added
/// @param wallet The wallet that added LP
/// @param amountTokens Amount of pTKNs used for LP
/// @param amountDAI Amount of pairedLpAsset used for LP
event AddLiquidity(address indexed wallet, uint256 amountTokens, uint256 amountDAI);
/// @notice The ```RemoveLiquidity``` event fires when LP is removed for a pod
/// @param wallet The wallet that removed LP
/// @param amountLiquidity Amount of liquidity removed
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 DEX_HANDLER() external view returns (IDexAdapter);
function FLASH_FEE_AMOUNT_DAI() external view returns (uint256);
function PAIRED_LP_TOKEN() external view returns (address);
function config() external view returns (Config calldata);
function fees() external view returns (Fees calldata);
function unlocked() external view returns (uint8);
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 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 processPreSwapFeesAndSwap() external;
function totalAssets() external view returns (uint256 totalManagedAssets);
function totalAssets(address asset) external view returns (uint256 totalManagedAssets);
function convertToShares(uint256 assets) external view returns (uint256 shares);
function convertToAssets(uint256 shares) external view returns (uint256 assets);
function setup() 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
returns (uint256);
function removeLiquidityV2(uint256 lpTokens, uint256 minTokens, uint256 minDAI, uint256 deadline) external;
function flash(address recipient, address token, uint256 amount, bytes calldata data) external;
function flashMint(address recipient, uint256 amount, bytes calldata data) external;
function setLpStakingPool(address lpStakingPool) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
interface IDexAdapter {
function ASYNC_INITIALIZE() external view returns (bool);
function V2_ROUTER() external view returns (address);
function V3_ROUTER() external view returns (address);
function WETH() external view returns (address);
function getV3Pool(address _token0, address _token1, int24 _tickSpacing) external view returns (address _pool);
function getV3Pool(address _token0, address _token1, uint24 _poolFee) external view returns (address _pool);
function getV2Pool(address _token0, address _token1) external view returns (address _pool);
function createV2Pool(address _token0, address _token1) external returns (address _pool);
function getReserves(address _pool) external view returns (uint112, uint112);
function swapV2Single(
address _tokenIn,
address _tokenOut,
uint256 _amountIn,
uint256 _amountOutMin,
address _recipient
) external returns (uint256 _amountOut);
function swapV2SingleExactOut(
address _tokenIn,
address _tokenOut,
uint256 _amountInMax,
uint256 _amountOut,
address _recipient
) external returns (uint256 _amountInUsed);
function swapV3Single(
address _tokenIn,
address _tokenOut,
uint24 _fee,
uint256 _amountIn,
uint256 _amountOutMin,
address _recipient
) external returns (uint256 _amountOut);
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external;
function removeLiquidity(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import "./IDecentralizedIndex.sol";
interface IIndexUtils {
function addLPAndStake(
IDecentralizedIndex indexFund,
uint256 amountIdxTokens,
address pairedLpTokenProvided,
uint256 amtPairedLpTokenProvided,
uint256 amountPairedLpTokenMin,
uint256 slippage,
uint256 deadline
) external payable returns (uint256 amountOut);
function unstakeAndRemoveLP(
IDecentralizedIndex indexFund,
uint256 amountStakedTokens,
uint256 minLPTokens,
uint256 minPairedLpToken,
uint256 deadline
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
interface IStakingPoolToken {
event Stake(address indexed executor, address indexed user, uint256 amount);
event Unstake(address indexed user, uint256 amount);
function INDEX_FUND() external view returns (address);
function POOL_REWARDS() external view returns (address);
function stakingToken() external view returns (address);
function stakeUserRestriction() external view returns (address);
function stake(address user, uint256 amount) external;
function unstake(uint256 amount) external;
function setPoolRewards(address poolRewards) external;
function setStakingToken(address stakingToken) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
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);
event RewardSwapError(uint256 amountIn);
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) external;
function depositRewards(address token, uint256 amount) external;
function depositRewardsNoTransfer(address token, uint256 amount) external;
function claimReward(address wallet) external;
function getAllRewardsTokens() external view returns (address[] memory);
function setShares(address wallet, uint256 amount, bool sharesRemoving) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
interface IUniswapV2Factory {
function createPair(address tokenA, address tokenB) external returns (address pair);
function getPair(address tokenA, address tokenB) external view returns (address pair);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
interface IUniswapV3Pool {
/// @notice The first of the two tokens of the pool, sorted by address
/// @return The token contract address
function token0() external view returns (address);
/// @notice The second of the two tokens of the pool, sorted by address
/// @return The token contract address
function token1() external view returns (address);
/// @notice The pool's fee in hundredths of a bip, i.e. 1e-6
/// @return The fee
function fee() external view returns (uint24);
/// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp
/// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing
/// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,
/// you must call it with secondsAgos = [3600, 0].
/// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in
/// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.
/// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned
/// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp
/// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block
/// timestamp
function observe(uint32[] calldata secondsAgos)
external
view
returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);
/// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas
/// when accessed externally.
/// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value
/// tick The current tick of the pool, i.e. according to the last tick transition that was run.
/// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick
/// boundary.
/// observationIndex The index of the last oracle observation that was written,
/// observationCardinality The current maximum number of observations stored in the pool,
/// observationCardinalityNext The next maximum number of observations, to be updated when the observation.
/// feeProtocol The protocol fee for both tokens of the pool.
/// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0
/// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.
/// unlocked Whether the pool is currently locked to reentrancy
function slot0()
external
view
returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
uint8 feeProtocol,
bool unlocked
);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
interface IUniswapV2Router02 {
function factory() external view returns (address);
function WETH() external view returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB, uint256 liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB);
function swapETHForExactTokens(uint256 amountOut, address[] calldata path, address to, uint256 deadline)
external
payable
returns (uint256[] memory amounts);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
interface IWETH {
function deposit() external payable;
function withdraw(uint256 _amount) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.28;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/interfaces/IERC4626.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/IDexAdapter.sol";
import "./interfaces/IUniswapV2Pair.sol";
import "./interfaces/IUniswapV3Pool.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 = 0xE592427A0AEce92De3Edee1F18E0157C05861564;
address immutable V2_ROUTER;
address immutable WETH;
IV3TwapUtilities immutable V3_TWAP_UTILS;
IDexAdapter immutable DEX_ADAPTER;
// pool => slippage (1 == 0.1%, 1000 == 100%)
mapping(address => uint256) _slippage;
uint256 _defaultSlippage = 30; // 3%
address public OHM = 0x64aa3364F17a4D01c6f1751Fd97C2BD3D7e7f1D5;
address public pOHM;
// token in => token out => swap pool(s)
mapping(address => mapping(address => Pools)) public zapMap;
// curve pool => token => idx
mapping(address => mapping(address => int128)) public curveTokenIdx;
constructor(IV3TwapUtilities _v3TwapUtilities, IDexAdapter _dexAdapter) Ownable(_msgSender()) {
V2_ROUTER = _dexAdapter.V2_ROUTER();
V3_TWAP_UTILS = _v3TwapUtilities;
DEX_ADAPTER = _dexAdapter;
WETH = _dexAdapter.WETH();
if (block.chainid == 1) {
// WETH/YETH
_setZapMapFromPoolSingle(PoolType.CURVE, 0x69ACcb968B19a53790f43e57558F5E443A91aF22);
// WETH/DAI
_setZapMapFromPoolSingle(PoolType.V3, 0x60594a405d53811d3BC4766596EFD80fd545A270);
// WETH/USDC
_setZapMapFromPoolSingle(PoolType.V3, 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640);
// WETH/OHM
_setZapMapFromPoolSingle(PoolType.V3, 0x88051B0eea095007D3bEf21aB287Be961f3d8598);
// USDC/OHM
_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;
}
}
// handle pOHM separately through pod, modularize later
bool _isOutPOHM;
if (pOHM == _out) {
_isOutPOHM = true;
_out = OHM;
}
// handle yETH and st-yETH special through curve pool, modularize later
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];
// no pool so just try to swap over one path univ2
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) {
// curve
_amountOut = _swapCurve(
_poolInfo.pool1,
curveTokenIdx[_poolInfo.pool1][_in],
curveTokenIdx[_poolInfo.pool1][_out],
_amountIn,
_amountOutMin
);
} else if (_poolInfo.poolType == PoolType.V2) {
// univ2
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 {
// univ3
if (_twoHops) {
address _t0 = IUniswapV3Pool(_poolInfo.pool1).token0();
_amountOut = _swapV3Multi(
_in,
_getPoolFee(_poolInfo.pool1),
_t0 == _in ? IUniswapV3Pool(_poolInfo.pool1).token1() : _t0,
_getPoolFee(_poolInfo.pool2),
_out,
_amountIn,
_amountOutMin
);
} else {
_amountOut = _swapV3Single(_in, _getPoolFee(_poolInfo.pool1), _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 _getPoolFee(address _pool) internal view returns (uint24) {
return block.chainid == 42161 ? 0 : IUniswapV3Pool(_pool).fee();
}
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)
{
address _v3Pool;
try DEX_ADAPTER.getV3Pool(_in, _out, uint24(10000)) returns (address __v3Pool) {
_v3Pool = __v3Pool;
} catch {
_v3Pool = DEX_ADAPTER.getV3Pool(_in, _out, int24(200));
}
if (_amountOutMin == 0) {
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));
uint256 _finalSlip = _slippage[_v3Pool] > 0 ? _slippage[_v3Pool] : _defaultSlippage;
IERC20(_in).safeIncreaseAllowance(address(DEX_ADAPTER), _amountIn);
DEX_ADAPTER.swapV3Single(
_in, _out, _fee, _amountIn, (_amountOutMin * (1000 - _finalSlip)) / 1000, address(this)
);
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) {
bool _twoHops = _path.length == 3;
address _out = _twoHops ? _path[2] : _path[1];
uint256 _outBefore = IERC20(_out).balanceOf(address(this));
IERC20(_path[0]).safeIncreaseAllowance(address(DEX_ADAPTER), _amountIn);
DEX_ADAPTER.swapV2Single(_path[0], _path[1], _amountIn, _twoHops ? 0 : _amountOutMin, address(this));
if (_twoHops) {
uint256 _intermediateBal = IERC20(_path[1]).balanceOf(address(this));
IERC20(_path[1]).safeIncreaseAllowance(address(DEX_ADAPTER), _intermediateBal);
DEX_ADAPTER.swapV2Single(_path[1], _path[2], _intermediateBal, _amountOutMin, address(this));
}
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 setPoolSlippage(address _pool, uint256 _slip) external onlyOwner {
require(_slip >= 0 && _slip <= 1000, "B");
_slippage[_pool] = _slip;
}
function setDefaultSlippage(uint256 _slip) external onlyOwner {
require(_slip >= 0 && _slip <= 1000, "B");
_defaultSlippage = _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 {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Callback for IUniswapV3PoolActions#swap
/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface
interface IUniswapV3SwapCallback {
/// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.
/// @dev In the implementation you must pay the pool tokens owed for the swap.
/// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.
/// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.
/// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token0 to the pool.
/// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token1 to the pool.
/// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC4626.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";
import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";
/**
* @dev Interface of the ERC-4626 "Tokenized Vault Standard", as defined in
* https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
*/
interface IERC4626 is IERC20, IERC20Metadata {
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed sender,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
/**
* @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
*
* - MUST be an ERC-20 token contract.
* - MUST NOT revert.
*/
function asset() external view returns (address assetTokenAddress);
/**
* @dev Returns the total amount of the underlying asset that is “managed” by Vault.
*
* - SHOULD include any compounding that occurs from yield.
* - MUST be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT revert.
*/
function totalAssets() external view returns (uint256 totalManagedAssets);
/**
* @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToShares(uint256 assets) external view returns (uint256 shares);
/**
* @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
* through a deposit call.
*
* - MUST return a limited value if receiver is subject to some deposit limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
* - MUST NOT revert.
*/
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
* call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
* in the same transaction.
* - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
* deposit would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewDeposit(uint256 assets) external view returns (uint256 shares);
/**
* @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* deposit execution, and are accounted for during deposit.
* - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
* - MUST return a limited value if receiver is subject to some mint limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
* - MUST NOT revert.
*/
function maxMint(address receiver) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
* in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
* same transaction.
* - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
* would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by minting.
*/
function previewMint(uint256 shares) external view returns (uint256 assets);
/**
* @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
* execution, and are accounted for during mint.
* - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
* Vault, through a withdraw call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
* call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
* called
* in the same transaction.
* - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
* the withdrawal would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
/**
* @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* withdraw execution, and are accounted for during withdraw.
* - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
* through a redeem call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxRedeem(address owner) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
* in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
* same transaction.
* - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
* redemption would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by redeeming.
*/
function previewRedeem(uint256 shares) external view returns (uint256 assets);
/**
* @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* redeem execution, and are accounted for during redeem.
* - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
interface ICurvePool {
function coins(uint256 _idx) external returns (address);
function exchange(int128 i, int128 j, uint256 dx, uint256 minDy, address receiver) external returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
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);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
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 getV3Pool(address v3Factory, address token0, address token1, int24 tickSpacing)
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 sqrtPriceX96FromPoolAndPassedInterval(address pool, uint32 interval) external view returns (uint160);
function priceX96FromSqrtPriceX96(uint160 sqrtPriceX96) external pure returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
interface IZapper {
enum PoolType {
CURVE,
V2,
V3
}
struct Pools {
PoolType poolType; // assume same for both pool1 and pool2
address pool1;
address pool2;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
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;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC-20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}{
"remappings": [
"@chainlink/=node_modules/@chainlink/",
"@fraxlend/=test/invariant/modules/fraxlend/",
"fuzzlib/=lib/fuzzlib/src/",
"swap-router/=test/invariant/modules/v3-periphery/swapRouter/",
"v3-core/=test/invariant/modules/v3-core/",
"v3-periphery/=test/invariant/modules/v3-periphery/",
"v2-core/=test/invariant/modules/uniswap-v2/v2-core/contracts/",
"v2-periphery/=test/invariant/modules/uniswap-v2/v2-periphery/contracts/",
"uniswap-v2/=test/invariant/modules/uniswap-v2/",
"solidity-bytes-utils/contracts/=test/invariant/modules/fraxlend/libraries/",
"@rari-capital/solmate/=node_modules/solmate/",
"@arbitrum/=node_modules/@arbitrum/",
"@ensdomains/=node_modules/@ensdomains/",
"@eth-optimism/=node_modules/@eth-optimism/",
"@ethereum-waffle/=node_modules/@ethereum-waffle/",
"@mean-finance/=node_modules/@mean-finance/",
"@offchainlabs/=node_modules/@offchainlabs/",
"@openzeppelin/=node_modules/@openzeppelin/",
"@scroll-tech/=node_modules/@scroll-tech/",
"@uniswap/=node_modules/@uniswap/",
"@zksync/=node_modules/@zksync/",
"base64-sol/=node_modules/base64-sol/",
"ds-test/=lib/fuzzlib/lib/forge-std/lib/ds-test/src/",
"erc721a/=node_modules/erc721a/",
"eth-gas-reporter/=node_modules/eth-gas-reporter/",
"forge-std/=lib/forge-std/src/",
"hardhat/=node_modules/hardhat/",
"solidity-code-metrics/=node_modules/solidity-code-metrics/",
"solmate/=node_modules/solmate/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IV3TwapUtilities","name":"_v3TwapUtilities","type":"address"},{"internalType":"contract IDexAdapter","name":"_dexAdapter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"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":[{"internalType":"uint256","name":"_amountOut","type":"uint256"}],"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":"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":"uint256","name":"_slip","type":"uint256"}],"name":"setDefaultSlippage","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":"address","name":"_pool","type":"address"},{"internalType":"uint256","name":"_slip","type":"uint256"}],"name":"setPoolSlippage","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"}]Contract Creation Code
610100604052601e600255600380546001600160a01b0319167364aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d517905534801561003c57600080fd5b50604051614bed380380614bed83398101604081905261005b916105de565b8181338061008357604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61008c81610221565b50806001600160a01b0316638ada032e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ef9190610618565b6001600160a01b0390811660805282811660c052811660e0819052604080516315ab88c960e31b8152905163ad5c4648916004808201926020929091908290030181865afa158015610145573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101699190610618565b6001600160a01b031660a052466001036102185761019c60007369accb968b19a53790f43e57558f5e443a91af22610271565b6101bb60027360594a405d53811d3bc4766596efd80fd545a270610271565b6101da60027388e6a0c2ddd26feeb64f039a2c41296fcb3f5640610271565b6101f960027388051b0eea095007d3bef21ab287be961f3d8598610271565b610218600273893f503fac2ee1e5b78665db23f9c94017aae97d610271565b50505050610652565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080808460028111156102875761028761063c565b036103b55760405163c661065760e01b8152600060048201526001600160a01b0384169063c6610657906024016020604051808303816000875af11580156102d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102f79190610618565b60405163c661065760e01b8152600160048201529092506001600160a01b0384169063c6610657906024016020604051808303816000875af1158015610341573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103659190610618565b6001600160a01b038481166000908152600660209081526040808320878516845290915280822080546001600160801b03199081169091559284168252902080549091166001179055905061047e565b826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104179190610618565b9150826001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610457573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047b9190610618565b90505b6000604051806060016040528086600281111561049d5761049d61063c565b81526001600160a01b0380871660208084019190915260006040938401819052878316815260058252838120928716815291905220815181549293508392829060ff191660018360028111156104f5576104f561063c565b02179055506020828101518254610100600160a81b0319166101006001600160a01b0392831602178355604093840151600193840180546001600160a01b0319169183169190911790558581166000908152600583528481209188168152915291909120825181548493839160ff1916908360028111156105785761057861063c565b021790555060208201518154610100600160a81b0319166101006001600160a01b0392831602178255604090920151600190910180546001600160a01b031916919092161790555050505050565b6001600160a01b03811681146105db57600080fd5b50565b600080604083850312156105f157600080fd5b82516105fc816105c6565b602084015190925061060d816105c6565b809150509250929050565b60006020828403121561062a57600080fd5b8151610635816105c6565b9392505050565b634e487b7160e01b600052602160045260246000fd5b60805160a05160c05160e0516144fc6106f160003960008181610ee0015281816119d701528181613181015281816131d60152818161336201528181613397015281816138c20152818161395701528181613c0d0152613c3c01526000613a1c01526000818161211e01528181612141015281816121f7015281816122df01528181612da601528181612e150152612e9c0152600050506144fc6000f3fe60806040526004361061010d5760003560e01c80638da5cb5b11610095578063ae7eb64611610064578063ae7eb646146102eb578063ccec37161461030b578063d71f11fb1461032b578063e42f53431461034b578063f2fde38b146103b057600080fd5b80638da5cb5b1461025957806394d994591461028b578063a1879d90146102ab578063a6c41fec146102cb57600080fd5b806344bd1afd116100dc57806344bd1afd1461019057806353eedc67146101b0578063715018a6146101d0578063816846c8146101e557806384614e1a1461023857600080fd5b80631fd8ecd914610119578063205b7d031461013b57806320800a001461015b57806338e781111461017057600080fd5b3661011457005b600080fd5b34801561012557600080fd5b50610139610134366004613e86565b6103d0565b005b34801561014757600080fd5b50610139610156366004613eca565b610816565b34801561016757600080fd5b5061013961089a565b34801561017c57600080fd5b5061013961018b366004613f17565b610905565b34801561019c57600080fd5b506101396101ab366004613f33565b61091b565b3480156101bc57600080fd5b506101396101cb366004613fbc565b610963565b3480156101dc57600080fd5b506101396109fe565b3480156101f157600080fd5b50610220610200366004613eca565b6006602090815260009283526040808420909152908252902054600f0b81565b604051600f9190910b81526020015b60405180910390f35b61024b61024636600461406a565b610a12565b60405190815260200161022f565b34801561026557600080fd5b506000546001600160a01b03165b6040516001600160a01b03909116815260200161022f565b34801561029757600080fd5b506101396102a63660046140cf565b6110a3565b3480156102b757600080fd5b506101396102c636600461411f565b6110fd565b3480156102d757600080fd5b50600354610273906001600160a01b031681565b3480156102f757600080fd5b50600454610273906001600160a01b031681565b34801561031757600080fd5b506101396103263660046141b9565b6111a3565b34801561033757600080fd5b506101396103463660046141d6565b6112ae565b34801561035757600080fd5b506103a1610366366004613eca565b60056020908152600092835260408084209091529082529020805460019091015460ff8216916001600160a01b036101009091048116911683565b60405161022f93929190614232565b3480156103bc57600080fd5b506101396103cb3660046141b9565b61189d565b6000856001600160a01b03166394cc699e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610410573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104349190614272565b90506000866001600160a01b0316634f4ce61d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610476573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049a9190614272565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156104e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610508919061428f565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610552573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610576919061428f565b905061058d6001600160a01b03851633308b6118d8565b6040516370a0823160e01b8152306004820152600090610614908b90879086906001600160a01b038316906370a0823190602401602060405180830381865afa1580156105de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610602919061428f565b61060c91906142be565b8b8b8b611945565b6040516370a0823160e01b815230600482015290915081906001600160a01b038c16906370a0823190602401602060405180830381865afa15801561065d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610681919061428f565b111561071157610711335b6040516370a0823160e01b815230600482015283906001600160a01b038e16906370a0823190602401602060405180830381865afa1580156106d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f6919061428f565b61070091906142be565b6001600160a01b038d169190611cf5565b6040516370a0823160e01b815230600482015282906001600160a01b038616906370a0823190602401602060405180830381865afa158015610757573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077b919061428f565b111561080a5761080a336040516370a0823160e01b815230600482015284906001600160a01b038816906370a0823190602401602060405180830381865afa1580156107cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ef919061428f565b6107f991906142be565b6001600160a01b0387169190611cf5565b50505050505050505050565b61081e611d26565b6001600160a01b038216156108335781610840565b6003546001600160a01b03165b600380546001600160a01b0319166001600160a01b039283161790558116156108695780610876565b6004546001600160a01b03165b600480546001600160a01b0319166001600160a01b03929092169190911790555050565b6108a2611d26565b600080546040516001600160a01b039091169047908381818185875af1925050503d80600081146108ef576040519150601f19603f3d011682016040523d82523d6000602084013e6108f4565b606091505b505090508061090257600080fd5b50565b61090d611d26565b6109178282611d53565b5050565b610923611d26565b6103e881111561095e5760405162461bcd60e51b81526020600482015260016024820152602160f91b60448201526064015b60405180910390fd5b600255565b61096b611d26565b6001600160a01b0380841660009081526005602090815260408083209386168352929052208151815483929190829060ff191660018360028111156109b2576109b261421c565b021790555060208201518154610100600160a81b0319166101006001600160a01b0392831602178255604090920151600190910180546001600160a01b03191691909216179055505050565b610a06611d26565b610a1060006120b1565b565b6000808890506000896001600160a01b0316634f4ce61d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7c9190614272565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610ac6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aea919061428f565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610b34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b58919061428f565b90506000610b6634476142be565b9050610b7d6001600160a01b03861633308f6118d8565b6001600160a01b038b16610bcd5760003411610bc55760405162461bcd60e51b815260206004820152600760248201526609c8a8a888aa8960cb1b6044820152606401610955565b349950610be2565b610be26001600160a01b038c1633308d6118d8565b836001600160a01b03168b6001600160a01b031614610c0957610c078b858c8c612101565b505b6040516370a0823160e01b8152306004820152610c9490869084906001600160a01b038816906370a0823190602401602060405180830381865afa158015610c55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c79919061428f565b610c8391906142be565b6001600160a01b0387169190612a29565b6001600160a01b038d1663a9e9c8bc8415610caf5784610cb2565b60015b6040516370a0823160e01b81523060048201526001600160a01b038916906370a0823190602401602060405180830381865afa158015610cf6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1a919061428f565b610d2491906142be565b8415610d305784610d33565b60015b6040516370a0823160e01b81523060048201526001600160a01b038916906370a0823190602401602060405180830381865afa158015610d77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9b919061428f565b610da591906142be565b6040516001600160e01b031960e085901b16815260048101929092526024820152604481018b9052606481018a90526084016020604051808303816000875af1158015610df6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1a919061428f565b955060008611610e525760405162461bcd60e51b81526020600482015260036024820152624c504d60e81b6044820152606401610955565b610f5d8d6001600160a01b03166394cc699e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb79190614272565b604051639f4f974560e01b81526001600160a01b038881166004830152878116602483015289917f000000000000000000000000000000000000000000000000000000000000000090911690639f4f974590604401602060405180830381865afa158015610f29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4d9190614272565b6001600160a01b03169190612a29565b610fc98d6001600160a01b03166394cc699e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc29190614272565b3388612ab3565b95508047111561106a57600033610fe083476142be565b604051600081818185875af1925050503d806000811461101c576040519150601f19603f3d011682016040523d82523d6000602084013e611021565b606091505b505090508080156110325750814710155b6110685760405162461bcd60e51b81526020600482015260076024820152660a89e9e9aaa86960cb1b6044820152606401610955565b505b6110823386851561107b5785612c7f565b6001612c7f565b6110933385841561107b5784612c7f565b5050505050979650505050505050565b6110ab611d26565b6103e88111156110e15760405162461bcd60e51b81526020600482015260016024820152602160f91b6044820152606401610955565b6001600160a01b03909116600090815260016020526040902055565b805160005b8181101561119e5782818151811061111c5761111c6142d1565b60200260200101516001600160a01b031663d279c1916111393390565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b15801561117a57600080fd5b505af115801561118e573d6000803e3d6000fd5b5050600190920191506111029050565b505050565b6111ab611d26565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156111f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611216919061428f565b1161122057600080fd5b6109026112356000546001600160a01b031690565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa158015611279573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061129d919061428f565b6001600160a01b0384169190611cf5565b6000846001600160a01b0316632acada4d6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156112ee573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261131691908101906142e7565b90506000815167ffffffffffffffff81111561133457611334613f4c565b60405190808252806020026020018201604052801561135d578160200160208202803683370190505b5060405163f3e0ffbf60e01b81526001600160a01b03878116600483015291925060009188169063f3e0ffbf90602401602060405180830381865afa1580156113aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ce919061428f565b90506000876001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611410573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611434919061428f565b156114575781611448600160601b886143c9565b61145291906143e0565b61145d565b600160601b5b845190915060005b818110156117595760008a6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d1919061428f565b1561158a57600160601b848c6001600160a01b031663f3e0ffbf8a86815181106114fd576114fd6142d1565b6020908102919091010151516040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561154d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611571919061428f565b61157b91906143c9565b61158591906143e0565b611632565b8a6001600160a01b031663e4b549578b8b8a86815181106115ad576115ad6142d1565b6020908102919091010151516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201526024810192909252919091166044820152606401602060405180830381865afa15801561160e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611632919061428f565b9050868281518110611646576116466142d1565b6020908102919091010151516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116bb919061428f565b8683815181106116cd576116cd6142d1565b60209081029190910101526117153330838a86815181106116f0576116f06142d1565b6020026020010151600001516001600160a01b03166118d8909392919063ffffffff16565b6117508b8289858151811061172c5761172c6142d1565b6020026020010151600001516001600160a01b0316612a299092919063ffffffff16565b50600101611465565b506040516370a0823160e01b81523060048201526000906001600160a01b038b16906370a0823190602401602060405180830381865afa1580156117a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c5919061428f565b60405163b08d033360e01b81526001600160a01b038b81166004830152602482018b9052604482018a9052919250908b169063b08d033390606401600060405180830381600087803b15801561181a57600080fd5b505af115801561182e573d6000803e3d6000fd5b5050505061183c61068c3390565b60005b82811015611890576118883388838151811061185d5761185d6142d1565b60200260200101516000015188848151811061187b5761187b6142d1565b6020026020010151612c7f565b60010161183f565b5050505050505050505050565b6118a5611d26565b6001600160a01b0381166118cf57604051631e4fbdf760e01b815260006004820152602401610955565b610902816120b1565b6040516001600160a01b03848116602483015283811660448301526064820183905261193f9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050612d13565b50505050565b600080876001600160a01b0316634f4ce61d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611986573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119aa9190614272565b604051639f4f974560e01b81526001600160a01b038a8116600483015280831660248301529192506000917f00000000000000000000000000000000000000000000000000000000000000001690639f4f974590604401602060405180830381865afa158015611a1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a429190614272565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015611a8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ab0919061428f565b6040516305c2fbcf60e31b8152600481018a90529091506001600160a01b038a1690632e17de7890602401600060405180830381600087803b158015611af557600080fd5b505af1158015611b09573d6000803e3d6000fd5b50506040516370a0823160e01b81523060048201526001600160a01b038d1692506370a082319150602401602060405180830381865afa158015611b51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b75919061428f565b6040516370a0823160e01b8152306004820152909450611c03908b9083906001600160a01b038616906370a0823190602401602060405180830381865afa158015611bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611be8919061428f565b611bf291906142be565b6001600160a01b0385169190612a29565b6040516370a0823160e01b81523060048201526001600160a01b03808c169163f6823996918491908616906370a0823190602401602060405180830381865afa158015611c54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c78919061428f565b611c8291906142be565b6040516001600160e01b031960e084901b1681526004810191909152602481018a90526044810189905260648101889052608401600060405180830381600087803b158015611cd057600080fd5b505af1158015611ce4573d6000803e3d6000fd5b505050505050509695505050505050565b6040516001600160a01b0383811660248301526044820183905261119e91859182169063a9059cbb9060640161190d565b6000546001600160a01b03163314610a105760405163118cdaa760e01b8152336004820152602401610955565b60008080846002811115611d6957611d6961421c565b03611ea05760405163c661065760e01b8152600060048201526001600160a01b0384169063c6610657906024016020604051808303816000875af1158015611db5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd99190614272565b60405163c661065760e01b8152600160048201529092506001600160a01b0384169063c6610657906024016020604051808303816000875af1158015611e23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e479190614272565b6001600160a01b038481166000908152600660209081526040808320878516845290915280822080546fffffffffffffffffffffffffffffffff1990811690915592841682529020805490911660011790559050611f69565b826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ede573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f029190614272565b9150826001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f669190614272565b90505b60006040518060600160405280866002811115611f8857611f8861421c565b81526001600160a01b0380871660208084019190915260006040938401819052878316815260058252838120928716815291905220815181549293508392829060ff19166001836002811115611fe057611fe061421c565b02179055506020828101518254610100600160a81b0319166101006001600160a01b0392831602178355604093840151600193840180546001600160a01b0319169183169190911790558581166000908152600583528481209188168152915291909120825181548493839160ff1916908360028111156120635761206361421c565b021790555060208201518154610100600160a81b0319166101006001600160a01b0392831602178255604090920151600190910180546001600160a01b031916919092161790555050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006001600160a01b03851661217f5761211a83612d84565b92507f000000000000000000000000000000000000000000000000000000000000000094507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b03160361217f575081612a21565b6004546000906001600160a01b038087169116036121a957506003546001600160a01b0316935060015b6001600160a01b038516731bed97cbc3c24a4fb5c069c6e311a967386131f714806121f057506001600160a01b03851673583019ff0f430721ada9cfb4fac8f06ca104d0b4145b15612291577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b03161461225f5760405162461bcd60e51b81526020600482015260066024820152652ca2aa2424a760d11b6044820152606401610955565b61228984846001600160a01b03881673583019ff0f430721ada9cfb4fac8f06ca104d0b414612f1b565b915050612a21565b6001600160a01b038616731bed97cbc3c24a4fb5c069c6e311a967386131f714806122d857506001600160a01b03861673583019ff0f430721ada9cfb4fac8f06ca104d0b4145b15612372577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316146123485760405162461bcd60e51b81526020600482015260076024820152661651551213d55560ca1b6044820152606401610955565b61228984846001600160a01b038916731bed97cbc3c24a4fb5c069c6e311a967386131f714613000565b6001600160a01b03808716600090815260056020908152604080832093891683529290528181208251606081019093528054919291829060ff1660028111156123bd576123bd61421c565b60028111156123ce576123ce61421c565b815281546001600160a01b036101009091048116602080840191909152600190930154811660409092019190915290820151919250166124a457604080516002808252606082018352600092602083019080368337019050509050878160008151811061243d5761243d6142d1565b60200260200101906001600160a01b031690816001600160a01b0316815250508681600181518110612471576124716142d1565b60200260200101906001600160a01b031690816001600160a01b03168152505061249c8187876130c2565b935050612893565b60408101516001600160a01b031615156000825160028111156124c9576124c961421c565b0361252e57602080830180516001600160a01b038082166000908152600680865260408083208f85168452875280832054955184168352908652808220928d16825291909452909220546125279291600f90810b91900b8989613504565b9350612891565b6001825160028111156125435761254361421c565b0361275257600082602001516001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa15801561258c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b09190614272565b90506000826125c05760026125c3565b60035b60ff1667ffffffffffffffff8111156125de576125de613f4c565b604051908082528060200260200182016040528015612607578160200160208202803683370190505b509050898160008151811061261e5761261e6142d1565b60200260200101906001600160a01b031690816001600160a01b03168152505082156126ce57896001600160a01b0316826001600160a01b03161461266357816126d0565b83602001516001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126c99190614272565b6126d0565b885b816001815181106126e3576126e36142d1565b60200260200101906001600160a01b031690816001600160a01b031681525050821561273e57888160028151811061271d5761271d6142d1565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6127498189896130c2565b95505050612891565b801561287557600082602001516001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa15801561279c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127c09190614272565b905061286d896127d385602001516135fb565b8b6001600160a01b0316846001600160a01b0316146127f25783612858565b85602001516001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612834573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128589190614272565b61286587604001516135fb565b8c8c8c613676565b945050612891565b61288e8861288684602001516135fb565b89898961388e565b93505b505b8161289f575050612a21565b600480546040516370a0823160e01b815230928101929092526000916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156128ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612911919061428f565b600454600354919250612931916001600160a01b03908116911686612a29565b6004805460035460405163b08d033360e01b81526001600160a01b03918216938101939093526024830187905260006044840152169063b08d033390606401600060405180830381600087803b15801561298a57600080fd5b505af115801561299e573d6000803e3d6000fd5b5050600480546040516370a0823160e01b815230928101929092528493506001600160a01b031691506370a0823190602401602060405180830381865afa1580156129ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a11919061428f565b612a1b91906142be565b93505050505b949350505050565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015612a79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a9d919061428f565b905061193f8484612aae8585614402565b613d97565b6040516370a0823160e01b815230600482015281906000906001600160a01b038616906370a0823190602401602060405180830381865afa158015612afc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b20919061428f565b1115612b8d576040516356e4bb9760e11b81526001600160a01b0384811660048301526024820184905285169063adc9772e90604401600060405180830381600087803b158015612b7057600080fd5b505af1158015612b84573d6000803e3d6000fd5b50505050612c78565b6040516356e4bb9760e11b8152306004820152602481018390526001600160a01b0385169063adc9772e90604401600060405180830381600087803b158015612bd557600080fd5b505af1158015612be9573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600192506001600160a01b03871691506370a0823190602401602060405180830381865afa158015612c34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c58919061428f565b612c6291906142be565b9050612c786001600160a01b0385168483611cf5565b9392505050565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015612cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cea919061428f565b90508181111561193f5761193f84612d0284846142be565b6001600160a01b0386169190611cf5565b600080602060008451602086016000885af180612d36576040513d6000823e3d81fd5b50506000513d91508115612d4e578060011415612d5b565b6001600160a01b0384163b155b1561193f57604051635274afe760e01b81526001600160a01b0385166004820152602401610955565b6040516370a0823160e01b815230600482015260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015612ded573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e11919061428f565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b158015612e6e57600080fd5b505af1158015612e82573d6000803e3d6000fd5b50506040516370a0823160e01b81523060048201528493507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031692506370a082319150602401602060405180830381865afa158015612eed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f11919061428f565b612c7891906142be565b600080612f417369accb968b19a53790f43e57558f5e443a91af22600060018888613504565b90508215612a2157612f7c731bed97cbc3c24a4fb5c069c6e311a967386131f773583019ff0f430721ada9cfb4fac8f06ca104d0b483612a29565b604051636e553f6560e01b81526004810182905230602482015273583019ff0f430721ada9cfb4fac8f06ca104d0b490636e553f65906044016020604051808303816000875af1158015612fd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ff8919061428f565b915050612c78565b6000808215613010575083613096565b604051635d043b2960e11b8152600481018690523060248201819052604482015273583019ff0f430721ada9cfb4fac8f06ca104d0b49063ba087652906064016020604051808303816000875af115801561306f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613093919061428f565b90505b6130b97369accb968b19a53790f43e57558f5e443a91af22600160008488613504565b95945050505050565b825160009060031481816130f057856001815181106130e3576130e36142d1565b602002602001015161310c565b85600281518110613103576131036142d1565b60200260200101515b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015613156573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061317a919061428f565b90506131d47f000000000000000000000000000000000000000000000000000000000000000087896000815181106131b4576131b46142d1565b60200260200101516001600160a01b0316612a299092919063ffffffff16565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166383e4b89f88600081518110613216576132166142d1565b602002602001015189600181518110613231576132316142d1565b602002602001015189876132455789613248565b60005b6040516001600160e01b031960e087901b1681526001600160a01b0394851660048201529390921660248401526044830152606482015230608482015260a4016020604051808303816000875af11580156132a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132cb919061428f565b508215613485576000876001815181106132e7576132e76142d1565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015613337573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061335b919061428f565b90506133957f0000000000000000000000000000000000000000000000000000000000000000828a6001815181106131b4576131b46142d1565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166383e4b89f896001815181106133d7576133d76142d1565b60200260200101518a6002815181106133f2576133f26142d1565b60209081029190910101516040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604481018490526064810189905230608482015260a4016020604051808303816000875af115801561345e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613482919061428f565b50505b6040516370a0823160e01b815230600482015281906001600160a01b038416906370a0823190602401602060405180830381865afa1580156134cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134ef919061428f565b6134f991906142be565b979650505050505050565b60405163c661065760e01b81526fffffffffffffffffffffffffffffffff8516600482015260009061356790879085906001600160a01b0383169063c6610657906024016020604051808303816000875af1158015610f29573d6000803e3d6000fd5b60405163ddc1f59d60e01b8152600f86810b600483015285900b602482015260448101849052606481018390523060848201526001600160a01b0387169063ddc1f59d9060a4016020604051808303816000875af11580156135cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135f1919061428f565b9695505050505050565b60004661a4b11461366d57816001600160a01b031663ddca3f436040518163ffffffff1660e01b8152600401602060405180830381865afa158015613644573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136689190614415565b613670565b60005b92915050565b6040516370a0823160e01b815230600482015260009081906001600160a01b038616906370a0823190602401602060405180830381865afa1580156136bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e3919061428f565b905061370d6001600160a01b038a1673e592427a0aece92de3edee1f18e0157c0586156486612a29565b6040516bffffffffffffffffffffffff1960608b811b821660208401526001600160e81b031960e88c811b821660348601528b831b841660378601528a901b16604b84015287901b16604e82015260009060620160408051601f1981840301815260a08301825280835230602084015242838301526060830188905260808301879052905163c04b8d5960e01b815290925073e592427a0aece92de3edee1f18e0157c058615649163c04b8d59916137c8919060040161443a565b6020604051808303816000875af11580156137e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061380b919061428f565b506040516370a0823160e01b815230600482015282906001600160a01b038816906370a0823190602401602060405180830381865afa158015613852573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613876919061428f565b61388091906142be565b9a9950505050505050505050565b60405163e3ddd77960e01b81526001600160a01b0386811660048301528481166024830152612710604483015260009182917f0000000000000000000000000000000000000000000000000000000000000000169063e3ddd77990606401602060405180830381865afa925050508015613925575060408051601f3d908101601f1916820190925261392291810190614272565b60015b6139c957604051630a8e060f60e01b81526001600160a01b038881166004830152868116602483015260c860448301527f00000000000000000000000000000000000000000000000000000000000000001690630a8e060f90606401602060405180830381865afa15801561399e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139c29190614272565b90506139cc565b90505b82600003613b4e576000856001600160a01b0316886001600160a01b0316106139f557856139f7565b875b604051637fb4f79d60e01b81526001600160a01b0384811660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063d4bf1334908290637fb4f79d90602401602060405180830381865afa158015613a6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a8f9190614272565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015613ad3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613af7919061428f565b9050816001600160a01b0316896001600160a01b031614613b305780613b21600160601b886143c9565b613b2b91906143e0565b613b49565b600160601b613b3f87836143c9565b613b4991906143e0565b945050505b6040516370a0823160e01b81523060048201526000906001600160a01b038716906370a0823190602401602060405180830381865afa158015613b95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bb9919061428f565b6001600160a01b03831660009081526001602052604081205491925090613be257600254613bfc565b6001600160a01b0383166000908152600160205260409020545b9050613c326001600160a01b038a167f000000000000000000000000000000000000000000000000000000000000000088612a29565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016638d5752d68a898b8a6103e8613c7288826142be565b613c7c908d6143c9565b613c8691906143e0565b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015294909316602485015262ffffff9091166044840152606483015260848201523060a482015260c4016020604051808303816000875af1158015613cf1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d15919061428f565b506040516370a0823160e01b815230600482015282906001600160a01b038916906370a0823190602401602060405180830381865afa158015613d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d80919061428f565b613d8a91906142be565b9998505050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052613de88482613e27565b61193f576040516001600160a01b03848116602483015260006044830152613e1d91869182169063095ea7b39060640161190d565b61193f8482612d13565b6000806000806020600086516020880160008a5af192503d915060005190508280156135f157508115613e5d57806001146135f1565b50505050506001600160a01b03163b151590565b6001600160a01b038116811461090257600080fd5b600080600080600060a08688031215613e9e57600080fd5b8535613ea981613e71565b97602087013597506040870135966060810135965060800135945092505050565b60008060408385031215613edd57600080fd5b8235613ee881613e71565b91506020830135613ef881613e71565b809150509250929050565b803560038110613f1257600080fd5b919050565b60008060408385031215613f2a57600080fd5b613ee883613f03565b600060208284031215613f4557600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613f8557613f85613f4c565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613fb457613fb4613f4c565b604052919050565b600080600083850360a0811215613fd257600080fd5b8435613fdd81613e71565b93506020850135613fed81613e71565b92506060603f198201121561400157600080fd5b506040516060810167ffffffffffffffff8111828210171561402557614025613f4c565b806040525061403660408601613f03565b8152606085013561404681613e71565b6020820152608085013561405981613e71565b604082015292959194509192509050565b600080600080600080600060e0888a03121561408557600080fd5b873561409081613e71565b96506020880135955060408801356140a781613e71565b969995985095966060810135965060808101359560a0820135955060c0909101359350915050565b600080604083850312156140e257600080fd5b82356140ed81613e71565b946020939093013593505050565b600067ffffffffffffffff82111561411557614115613f4c565b5060051b60200190565b60006020828403121561413157600080fd5b813567ffffffffffffffff81111561414857600080fd5b8201601f8101841361415957600080fd5b803561416c614167826140fb565b613f8b565b8082825260208201915060208360051b85010192508683111561418e57600080fd5b6020840193505b828410156135f15783356141a881613e71565b825260209384019390910190614195565b6000602082840312156141cb57600080fd5b8135612c7881613e71565b600080600080608085870312156141ec57600080fd5b84356141f781613e71565b9350602085013561420781613e71565b93969395505050506040820135916060013590565b634e487b7160e01b600052602160045260246000fd5b606081016003851061425457634e487b7160e01b600052602160045260246000fd5b9381526001600160a01b039283166020820152911660409091015290565b60006020828403121561428457600080fd5b8151612c7881613e71565b6000602082840312156142a157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115613670576136706142a8565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156142f957600080fd5b815167ffffffffffffffff81111561431057600080fd5b8201601f8101841361432157600080fd5b805161432f614167826140fb565b80828252602082019150602060a0840285010192508683111561435157600080fd5b6020840193505b828410156135f15760a0848803121561437057600080fd5b614378613f62565b845161438381613e71565b8152602085810151908201526040808601519082015260608501516143a781613e71565b606082015260808581015190820152825260a090930192602090910190614358565b8082028115828204841417613670576136706142a8565b6000826143fd57634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115613670576136706142a8565b60006020828403121561442757600080fd5b815162ffffff81168114612c7857600080fd5b602081526000825160a0602084015280518060c085015260005b8181101561447157602081840181015160e0878401015201614454565b50600084820160e0015260208501516001600160a01b038116604086015291506040850151606085015260608501516080850152608085015160a085015260e0601f19601f830116850101925050509291505056fea2646970667358221220d853182d443cded93fdec3916805151ff36016fe2ae7f718ca1a9da406f09dcd64736f6c634300081c00330000000000000000000000009de8aa7743660e73a481e5647e75050da9504533000000000000000000000000440daf974bf6c97e9442fffd022ca554ee94219c
Deployed Bytecode
0x60806040526004361061010d5760003560e01c80638da5cb5b11610095578063ae7eb64611610064578063ae7eb646146102eb578063ccec37161461030b578063d71f11fb1461032b578063e42f53431461034b578063f2fde38b146103b057600080fd5b80638da5cb5b1461025957806394d994591461028b578063a1879d90146102ab578063a6c41fec146102cb57600080fd5b806344bd1afd116100dc57806344bd1afd1461019057806353eedc67146101b0578063715018a6146101d0578063816846c8146101e557806384614e1a1461023857600080fd5b80631fd8ecd914610119578063205b7d031461013b57806320800a001461015b57806338e781111461017057600080fd5b3661011457005b600080fd5b34801561012557600080fd5b50610139610134366004613e86565b6103d0565b005b34801561014757600080fd5b50610139610156366004613eca565b610816565b34801561016757600080fd5b5061013961089a565b34801561017c57600080fd5b5061013961018b366004613f17565b610905565b34801561019c57600080fd5b506101396101ab366004613f33565b61091b565b3480156101bc57600080fd5b506101396101cb366004613fbc565b610963565b3480156101dc57600080fd5b506101396109fe565b3480156101f157600080fd5b50610220610200366004613eca565b6006602090815260009283526040808420909152908252902054600f0b81565b604051600f9190910b81526020015b60405180910390f35b61024b61024636600461406a565b610a12565b60405190815260200161022f565b34801561026557600080fd5b506000546001600160a01b03165b6040516001600160a01b03909116815260200161022f565b34801561029757600080fd5b506101396102a63660046140cf565b6110a3565b3480156102b757600080fd5b506101396102c636600461411f565b6110fd565b3480156102d757600080fd5b50600354610273906001600160a01b031681565b3480156102f757600080fd5b50600454610273906001600160a01b031681565b34801561031757600080fd5b506101396103263660046141b9565b6111a3565b34801561033757600080fd5b506101396103463660046141d6565b6112ae565b34801561035757600080fd5b506103a1610366366004613eca565b60056020908152600092835260408084209091529082529020805460019091015460ff8216916001600160a01b036101009091048116911683565b60405161022f93929190614232565b3480156103bc57600080fd5b506101396103cb3660046141b9565b61189d565b6000856001600160a01b03166394cc699e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610410573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104349190614272565b90506000866001600160a01b0316634f4ce61d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610476573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049a9190614272565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa1580156104e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610508919061428f565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610552573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610576919061428f565b905061058d6001600160a01b03851633308b6118d8565b6040516370a0823160e01b8152306004820152600090610614908b90879086906001600160a01b038316906370a0823190602401602060405180830381865afa1580156105de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610602919061428f565b61060c91906142be565b8b8b8b611945565b6040516370a0823160e01b815230600482015290915081906001600160a01b038c16906370a0823190602401602060405180830381865afa15801561065d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610681919061428f565b111561071157610711335b6040516370a0823160e01b815230600482015283906001600160a01b038e16906370a0823190602401602060405180830381865afa1580156106d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f6919061428f565b61070091906142be565b6001600160a01b038d169190611cf5565b6040516370a0823160e01b815230600482015282906001600160a01b038616906370a0823190602401602060405180830381865afa158015610757573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077b919061428f565b111561080a5761080a336040516370a0823160e01b815230600482015284906001600160a01b038816906370a0823190602401602060405180830381865afa1580156107cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ef919061428f565b6107f991906142be565b6001600160a01b0387169190611cf5565b50505050505050505050565b61081e611d26565b6001600160a01b038216156108335781610840565b6003546001600160a01b03165b600380546001600160a01b0319166001600160a01b039283161790558116156108695780610876565b6004546001600160a01b03165b600480546001600160a01b0319166001600160a01b03929092169190911790555050565b6108a2611d26565b600080546040516001600160a01b039091169047908381818185875af1925050503d80600081146108ef576040519150601f19603f3d011682016040523d82523d6000602084013e6108f4565b606091505b505090508061090257600080fd5b50565b61090d611d26565b6109178282611d53565b5050565b610923611d26565b6103e881111561095e5760405162461bcd60e51b81526020600482015260016024820152602160f91b60448201526064015b60405180910390fd5b600255565b61096b611d26565b6001600160a01b0380841660009081526005602090815260408083209386168352929052208151815483929190829060ff191660018360028111156109b2576109b261421c565b021790555060208201518154610100600160a81b0319166101006001600160a01b0392831602178255604090920151600190910180546001600160a01b03191691909216179055505050565b610a06611d26565b610a1060006120b1565b565b6000808890506000896001600160a01b0316634f4ce61d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7c9190614272565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610ac6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aea919061428f565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610b34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b58919061428f565b90506000610b6634476142be565b9050610b7d6001600160a01b03861633308f6118d8565b6001600160a01b038b16610bcd5760003411610bc55760405162461bcd60e51b815260206004820152600760248201526609c8a8a888aa8960cb1b6044820152606401610955565b349950610be2565b610be26001600160a01b038c1633308d6118d8565b836001600160a01b03168b6001600160a01b031614610c0957610c078b858c8c612101565b505b6040516370a0823160e01b8152306004820152610c9490869084906001600160a01b038816906370a0823190602401602060405180830381865afa158015610c55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c79919061428f565b610c8391906142be565b6001600160a01b0387169190612a29565b6001600160a01b038d1663a9e9c8bc8415610caf5784610cb2565b60015b6040516370a0823160e01b81523060048201526001600160a01b038916906370a0823190602401602060405180830381865afa158015610cf6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1a919061428f565b610d2491906142be565b8415610d305784610d33565b60015b6040516370a0823160e01b81523060048201526001600160a01b038916906370a0823190602401602060405180830381865afa158015610d77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9b919061428f565b610da591906142be565b6040516001600160e01b031960e085901b16815260048101929092526024820152604481018b9052606481018a90526084016020604051808303816000875af1158015610df6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1a919061428f565b955060008611610e525760405162461bcd60e51b81526020600482015260036024820152624c504d60e81b6044820152606401610955565b610f5d8d6001600160a01b03166394cc699e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb79190614272565b604051639f4f974560e01b81526001600160a01b038881166004830152878116602483015289917f000000000000000000000000440daf974bf6c97e9442fffd022ca554ee94219c90911690639f4f974590604401602060405180830381865afa158015610f29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4d9190614272565b6001600160a01b03169190612a29565b610fc98d6001600160a01b03166394cc699e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc29190614272565b3388612ab3565b95508047111561106a57600033610fe083476142be565b604051600081818185875af1925050503d806000811461101c576040519150601f19603f3d011682016040523d82523d6000602084013e611021565b606091505b505090508080156110325750814710155b6110685760405162461bcd60e51b81526020600482015260076024820152660a89e9e9aaa86960cb1b6044820152606401610955565b505b6110823386851561107b5785612c7f565b6001612c7f565b6110933385841561107b5784612c7f565b5050505050979650505050505050565b6110ab611d26565b6103e88111156110e15760405162461bcd60e51b81526020600482015260016024820152602160f91b6044820152606401610955565b6001600160a01b03909116600090815260016020526040902055565b805160005b8181101561119e5782818151811061111c5761111c6142d1565b60200260200101516001600160a01b031663d279c1916111393390565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b15801561117a57600080fd5b505af115801561118e573d6000803e3d6000fd5b5050600190920191506111029050565b505050565b6111ab611d26565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156111f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611216919061428f565b1161122057600080fd5b6109026112356000546001600160a01b031690565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa158015611279573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061129d919061428f565b6001600160a01b0384169190611cf5565b6000846001600160a01b0316632acada4d6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156112ee573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261131691908101906142e7565b90506000815167ffffffffffffffff81111561133457611334613f4c565b60405190808252806020026020018201604052801561135d578160200160208202803683370190505b5060405163f3e0ffbf60e01b81526001600160a01b03878116600483015291925060009188169063f3e0ffbf90602401602060405180830381865afa1580156113aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ce919061428f565b90506000876001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611410573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611434919061428f565b156114575781611448600160601b886143c9565b61145291906143e0565b61145d565b600160601b5b845190915060005b818110156117595760008a6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d1919061428f565b1561158a57600160601b848c6001600160a01b031663f3e0ffbf8a86815181106114fd576114fd6142d1565b6020908102919091010151516040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561154d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611571919061428f565b61157b91906143c9565b61158591906143e0565b611632565b8a6001600160a01b031663e4b549578b8b8a86815181106115ad576115ad6142d1565b6020908102919091010151516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201526024810192909252919091166044820152606401602060405180830381865afa15801561160e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611632919061428f565b9050868281518110611646576116466142d1565b6020908102919091010151516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116bb919061428f565b8683815181106116cd576116cd6142d1565b60209081029190910101526117153330838a86815181106116f0576116f06142d1565b6020026020010151600001516001600160a01b03166118d8909392919063ffffffff16565b6117508b8289858151811061172c5761172c6142d1565b6020026020010151600001516001600160a01b0316612a299092919063ffffffff16565b50600101611465565b506040516370a0823160e01b81523060048201526000906001600160a01b038b16906370a0823190602401602060405180830381865afa1580156117a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c5919061428f565b60405163b08d033360e01b81526001600160a01b038b81166004830152602482018b9052604482018a9052919250908b169063b08d033390606401600060405180830381600087803b15801561181a57600080fd5b505af115801561182e573d6000803e3d6000fd5b5050505061183c61068c3390565b60005b82811015611890576118883388838151811061185d5761185d6142d1565b60200260200101516000015188848151811061187b5761187b6142d1565b6020026020010151612c7f565b60010161183f565b5050505050505050505050565b6118a5611d26565b6001600160a01b0381166118cf57604051631e4fbdf760e01b815260006004820152602401610955565b610902816120b1565b6040516001600160a01b03848116602483015283811660448301526064820183905261193f9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050612d13565b50505050565b600080876001600160a01b0316634f4ce61d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611986573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119aa9190614272565b604051639f4f974560e01b81526001600160a01b038a8116600483015280831660248301529192506000917f000000000000000000000000440daf974bf6c97e9442fffd022ca554ee94219c1690639f4f974590604401602060405180830381865afa158015611a1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a429190614272565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015611a8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ab0919061428f565b6040516305c2fbcf60e31b8152600481018a90529091506001600160a01b038a1690632e17de7890602401600060405180830381600087803b158015611af557600080fd5b505af1158015611b09573d6000803e3d6000fd5b50506040516370a0823160e01b81523060048201526001600160a01b038d1692506370a082319150602401602060405180830381865afa158015611b51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b75919061428f565b6040516370a0823160e01b8152306004820152909450611c03908b9083906001600160a01b038616906370a0823190602401602060405180830381865afa158015611bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611be8919061428f565b611bf291906142be565b6001600160a01b0385169190612a29565b6040516370a0823160e01b81523060048201526001600160a01b03808c169163f6823996918491908616906370a0823190602401602060405180830381865afa158015611c54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c78919061428f565b611c8291906142be565b6040516001600160e01b031960e084901b1681526004810191909152602481018a90526044810189905260648101889052608401600060405180830381600087803b158015611cd057600080fd5b505af1158015611ce4573d6000803e3d6000fd5b505050505050509695505050505050565b6040516001600160a01b0383811660248301526044820183905261119e91859182169063a9059cbb9060640161190d565b6000546001600160a01b03163314610a105760405163118cdaa760e01b8152336004820152602401610955565b60008080846002811115611d6957611d6961421c565b03611ea05760405163c661065760e01b8152600060048201526001600160a01b0384169063c6610657906024016020604051808303816000875af1158015611db5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd99190614272565b60405163c661065760e01b8152600160048201529092506001600160a01b0384169063c6610657906024016020604051808303816000875af1158015611e23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e479190614272565b6001600160a01b038481166000908152600660209081526040808320878516845290915280822080546fffffffffffffffffffffffffffffffff1990811690915592841682529020805490911660011790559050611f69565b826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ede573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f029190614272565b9150826001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f669190614272565b90505b60006040518060600160405280866002811115611f8857611f8861421c565b81526001600160a01b0380871660208084019190915260006040938401819052878316815260058252838120928716815291905220815181549293508392829060ff19166001836002811115611fe057611fe061421c565b02179055506020828101518254610100600160a81b0319166101006001600160a01b0392831602178355604093840151600193840180546001600160a01b0319169183169190911790558581166000908152600583528481209188168152915291909120825181548493839160ff1916908360028111156120635761206361421c565b021790555060208201518154610100600160a81b0319166101006001600160a01b0392831602178255604090920151600190910180546001600160a01b031916919092161790555050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006001600160a01b03851661217f5761211a83612d84565b92507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc294507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b0316846001600160a01b03160361217f575081612a21565b6004546000906001600160a01b038087169116036121a957506003546001600160a01b0316935060015b6001600160a01b038516731bed97cbc3c24a4fb5c069c6e311a967386131f714806121f057506001600160a01b03851673583019ff0f430721ada9cfb4fac8f06ca104d0b4145b15612291577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b0316866001600160a01b03161461225f5760405162461bcd60e51b81526020600482015260066024820152652ca2aa2424a760d11b6044820152606401610955565b61228984846001600160a01b03881673583019ff0f430721ada9cfb4fac8f06ca104d0b414612f1b565b915050612a21565b6001600160a01b038616731bed97cbc3c24a4fb5c069c6e311a967386131f714806122d857506001600160a01b03861673583019ff0f430721ada9cfb4fac8f06ca104d0b4145b15612372577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b0316856001600160a01b0316146123485760405162461bcd60e51b81526020600482015260076024820152661651551213d55560ca1b6044820152606401610955565b61228984846001600160a01b038916731bed97cbc3c24a4fb5c069c6e311a967386131f714613000565b6001600160a01b03808716600090815260056020908152604080832093891683529290528181208251606081019093528054919291829060ff1660028111156123bd576123bd61421c565b60028111156123ce576123ce61421c565b815281546001600160a01b036101009091048116602080840191909152600190930154811660409092019190915290820151919250166124a457604080516002808252606082018352600092602083019080368337019050509050878160008151811061243d5761243d6142d1565b60200260200101906001600160a01b031690816001600160a01b0316815250508681600181518110612471576124716142d1565b60200260200101906001600160a01b031690816001600160a01b03168152505061249c8187876130c2565b935050612893565b60408101516001600160a01b031615156000825160028111156124c9576124c961421c565b0361252e57602080830180516001600160a01b038082166000908152600680865260408083208f85168452875280832054955184168352908652808220928d16825291909452909220546125279291600f90810b91900b8989613504565b9350612891565b6001825160028111156125435761254361421c565b0361275257600082602001516001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa15801561258c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b09190614272565b90506000826125c05760026125c3565b60035b60ff1667ffffffffffffffff8111156125de576125de613f4c565b604051908082528060200260200182016040528015612607578160200160208202803683370190505b509050898160008151811061261e5761261e6142d1565b60200260200101906001600160a01b031690816001600160a01b03168152505082156126ce57896001600160a01b0316826001600160a01b03161461266357816126d0565b83602001516001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126c99190614272565b6126d0565b885b816001815181106126e3576126e36142d1565b60200260200101906001600160a01b031690816001600160a01b031681525050821561273e57888160028151811061271d5761271d6142d1565b60200260200101906001600160a01b031690816001600160a01b0316815250505b6127498189896130c2565b95505050612891565b801561287557600082602001516001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa15801561279c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127c09190614272565b905061286d896127d385602001516135fb565b8b6001600160a01b0316846001600160a01b0316146127f25783612858565b85602001516001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612834573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128589190614272565b61286587604001516135fb565b8c8c8c613676565b945050612891565b61288e8861288684602001516135fb565b89898961388e565b93505b505b8161289f575050612a21565b600480546040516370a0823160e01b815230928101929092526000916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156128ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612911919061428f565b600454600354919250612931916001600160a01b03908116911686612a29565b6004805460035460405163b08d033360e01b81526001600160a01b03918216938101939093526024830187905260006044840152169063b08d033390606401600060405180830381600087803b15801561298a57600080fd5b505af115801561299e573d6000803e3d6000fd5b5050600480546040516370a0823160e01b815230928101929092528493506001600160a01b031691506370a0823190602401602060405180830381865afa1580156129ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a11919061428f565b612a1b91906142be565b93505050505b949350505050565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015612a79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a9d919061428f565b905061193f8484612aae8585614402565b613d97565b6040516370a0823160e01b815230600482015281906000906001600160a01b038616906370a0823190602401602060405180830381865afa158015612afc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b20919061428f565b1115612b8d576040516356e4bb9760e11b81526001600160a01b0384811660048301526024820184905285169063adc9772e90604401600060405180830381600087803b158015612b7057600080fd5b505af1158015612b84573d6000803e3d6000fd5b50505050612c78565b6040516356e4bb9760e11b8152306004820152602481018390526001600160a01b0385169063adc9772e90604401600060405180830381600087803b158015612bd557600080fd5b505af1158015612be9573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600192506001600160a01b03871691506370a0823190602401602060405180830381865afa158015612c34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c58919061428f565b612c6291906142be565b9050612c786001600160a01b0385168483611cf5565b9392505050565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015612cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cea919061428f565b90508181111561193f5761193f84612d0284846142be565b6001600160a01b0386169190611cf5565b600080602060008451602086016000885af180612d36576040513d6000823e3d81fd5b50506000513d91508115612d4e578060011415612d5b565b6001600160a01b0384163b155b1561193f57604051635274afe760e01b81526001600160a01b0385166004820152602401610955565b6040516370a0823160e01b815230600482015260009081906001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc216906370a0823190602401602060405180830381865afa158015612ded573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e11919061428f565b90507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b158015612e6e57600080fd5b505af1158015612e82573d6000803e3d6000fd5b50506040516370a0823160e01b81523060048201528493507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031692506370a082319150602401602060405180830381865afa158015612eed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f11919061428f565b612c7891906142be565b600080612f417369accb968b19a53790f43e57558f5e443a91af22600060018888613504565b90508215612a2157612f7c731bed97cbc3c24a4fb5c069c6e311a967386131f773583019ff0f430721ada9cfb4fac8f06ca104d0b483612a29565b604051636e553f6560e01b81526004810182905230602482015273583019ff0f430721ada9cfb4fac8f06ca104d0b490636e553f65906044016020604051808303816000875af1158015612fd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ff8919061428f565b915050612c78565b6000808215613010575083613096565b604051635d043b2960e11b8152600481018690523060248201819052604482015273583019ff0f430721ada9cfb4fac8f06ca104d0b49063ba087652906064016020604051808303816000875af115801561306f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613093919061428f565b90505b6130b97369accb968b19a53790f43e57558f5e443a91af22600160008488613504565b95945050505050565b825160009060031481816130f057856001815181106130e3576130e36142d1565b602002602001015161310c565b85600281518110613103576131036142d1565b60200260200101515b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015613156573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061317a919061428f565b90506131d47f000000000000000000000000440daf974bf6c97e9442fffd022ca554ee94219c87896000815181106131b4576131b46142d1565b60200260200101516001600160a01b0316612a299092919063ffffffff16565b7f000000000000000000000000440daf974bf6c97e9442fffd022ca554ee94219c6001600160a01b03166383e4b89f88600081518110613216576132166142d1565b602002602001015189600181518110613231576132316142d1565b602002602001015189876132455789613248565b60005b6040516001600160e01b031960e087901b1681526001600160a01b0394851660048201529390921660248401526044830152606482015230608482015260a4016020604051808303816000875af11580156132a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132cb919061428f565b508215613485576000876001815181106132e7576132e76142d1565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015613337573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061335b919061428f565b90506133957f000000000000000000000000440daf974bf6c97e9442fffd022ca554ee94219c828a6001815181106131b4576131b46142d1565b7f000000000000000000000000440daf974bf6c97e9442fffd022ca554ee94219c6001600160a01b03166383e4b89f896001815181106133d7576133d76142d1565b60200260200101518a6002815181106133f2576133f26142d1565b60209081029190910101516040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604481018490526064810189905230608482015260a4016020604051808303816000875af115801561345e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613482919061428f565b50505b6040516370a0823160e01b815230600482015281906001600160a01b038416906370a0823190602401602060405180830381865afa1580156134cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134ef919061428f565b6134f991906142be565b979650505050505050565b60405163c661065760e01b81526fffffffffffffffffffffffffffffffff8516600482015260009061356790879085906001600160a01b0383169063c6610657906024016020604051808303816000875af1158015610f29573d6000803e3d6000fd5b60405163ddc1f59d60e01b8152600f86810b600483015285900b602482015260448101849052606481018390523060848201526001600160a01b0387169063ddc1f59d9060a4016020604051808303816000875af11580156135cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135f1919061428f565b9695505050505050565b60004661a4b11461366d57816001600160a01b031663ddca3f436040518163ffffffff1660e01b8152600401602060405180830381865afa158015613644573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136689190614415565b613670565b60005b92915050565b6040516370a0823160e01b815230600482015260009081906001600160a01b038616906370a0823190602401602060405180830381865afa1580156136bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e3919061428f565b905061370d6001600160a01b038a1673e592427a0aece92de3edee1f18e0157c0586156486612a29565b6040516bffffffffffffffffffffffff1960608b811b821660208401526001600160e81b031960e88c811b821660348601528b831b841660378601528a901b16604b84015287901b16604e82015260009060620160408051601f1981840301815260a08301825280835230602084015242838301526060830188905260808301879052905163c04b8d5960e01b815290925073e592427a0aece92de3edee1f18e0157c058615649163c04b8d59916137c8919060040161443a565b6020604051808303816000875af11580156137e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061380b919061428f565b506040516370a0823160e01b815230600482015282906001600160a01b038816906370a0823190602401602060405180830381865afa158015613852573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613876919061428f565b61388091906142be565b9a9950505050505050505050565b60405163e3ddd77960e01b81526001600160a01b0386811660048301528481166024830152612710604483015260009182917f000000000000000000000000440daf974bf6c97e9442fffd022ca554ee94219c169063e3ddd77990606401602060405180830381865afa925050508015613925575060408051601f3d908101601f1916820190925261392291810190614272565b60015b6139c957604051630a8e060f60e01b81526001600160a01b038881166004830152868116602483015260c860448301527f000000000000000000000000440daf974bf6c97e9442fffd022ca554ee94219c1690630a8e060f90606401602060405180830381865afa15801561399e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139c29190614272565b90506139cc565b90505b82600003613b4e576000856001600160a01b0316886001600160a01b0316106139f557856139f7565b875b604051637fb4f79d60e01b81526001600160a01b0384811660048301529192506000917f0000000000000000000000009de8aa7743660e73a481e5647e75050da9504533169063d4bf1334908290637fb4f79d90602401602060405180830381865afa158015613a6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a8f9190614272565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015613ad3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613af7919061428f565b9050816001600160a01b0316896001600160a01b031614613b305780613b21600160601b886143c9565b613b2b91906143e0565b613b49565b600160601b613b3f87836143c9565b613b4991906143e0565b945050505b6040516370a0823160e01b81523060048201526000906001600160a01b038716906370a0823190602401602060405180830381865afa158015613b95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bb9919061428f565b6001600160a01b03831660009081526001602052604081205491925090613be257600254613bfc565b6001600160a01b0383166000908152600160205260409020545b9050613c326001600160a01b038a167f000000000000000000000000440daf974bf6c97e9442fffd022ca554ee94219c88612a29565b6001600160a01b037f000000000000000000000000440daf974bf6c97e9442fffd022ca554ee94219c16638d5752d68a898b8a6103e8613c7288826142be565b613c7c908d6143c9565b613c8691906143e0565b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015294909316602485015262ffffff9091166044840152606483015260848201523060a482015260c4016020604051808303816000875af1158015613cf1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d15919061428f565b506040516370a0823160e01b815230600482015282906001600160a01b038916906370a0823190602401602060405180830381865afa158015613d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d80919061428f565b613d8a91906142be565b9998505050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052613de88482613e27565b61193f576040516001600160a01b03848116602483015260006044830152613e1d91869182169063095ea7b39060640161190d565b61193f8482612d13565b6000806000806020600086516020880160008a5af192503d915060005190508280156135f157508115613e5d57806001146135f1565b50505050506001600160a01b03163b151590565b6001600160a01b038116811461090257600080fd5b600080600080600060a08688031215613e9e57600080fd5b8535613ea981613e71565b97602087013597506040870135966060810135965060800135945092505050565b60008060408385031215613edd57600080fd5b8235613ee881613e71565b91506020830135613ef881613e71565b809150509250929050565b803560038110613f1257600080fd5b919050565b60008060408385031215613f2a57600080fd5b613ee883613f03565b600060208284031215613f4557600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613f8557613f85613f4c565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613fb457613fb4613f4c565b604052919050565b600080600083850360a0811215613fd257600080fd5b8435613fdd81613e71565b93506020850135613fed81613e71565b92506060603f198201121561400157600080fd5b506040516060810167ffffffffffffffff8111828210171561402557614025613f4c565b806040525061403660408601613f03565b8152606085013561404681613e71565b6020820152608085013561405981613e71565b604082015292959194509192509050565b600080600080600080600060e0888a03121561408557600080fd5b873561409081613e71565b96506020880135955060408801356140a781613e71565b969995985095966060810135965060808101359560a0820135955060c0909101359350915050565b600080604083850312156140e257600080fd5b82356140ed81613e71565b946020939093013593505050565b600067ffffffffffffffff82111561411557614115613f4c565b5060051b60200190565b60006020828403121561413157600080fd5b813567ffffffffffffffff81111561414857600080fd5b8201601f8101841361415957600080fd5b803561416c614167826140fb565b613f8b565b8082825260208201915060208360051b85010192508683111561418e57600080fd5b6020840193505b828410156135f15783356141a881613e71565b825260209384019390910190614195565b6000602082840312156141cb57600080fd5b8135612c7881613e71565b600080600080608085870312156141ec57600080fd5b84356141f781613e71565b9350602085013561420781613e71565b93969395505050506040820135916060013590565b634e487b7160e01b600052602160045260246000fd5b606081016003851061425457634e487b7160e01b600052602160045260246000fd5b9381526001600160a01b039283166020820152911660409091015290565b60006020828403121561428457600080fd5b8151612c7881613e71565b6000602082840312156142a157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115613670576136706142a8565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156142f957600080fd5b815167ffffffffffffffff81111561431057600080fd5b8201601f8101841361432157600080fd5b805161432f614167826140fb565b80828252602082019150602060a0840285010192508683111561435157600080fd5b6020840193505b828410156135f15760a0848803121561437057600080fd5b614378613f62565b845161438381613e71565b8152602085810151908201526040808601519082015260608501516143a781613e71565b606082015260808581015190820152825260a090930192602090910190614358565b8082028115828204841417613670576136706142a8565b6000826143fd57634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115613670576136706142a8565b60006020828403121561442757600080fd5b815162ffffff81168114612c7857600080fd5b602081526000825160a0602084015280518060c085015260005b8181101561447157602081840181015160e0878401015201614454565b50600084820160e0015260208501516001600160a01b038116604086015291506040850151606085015260608501516080850152608085015160a085015260e0601f19601f830116850101925050509291505056fea2646970667358221220d853182d443cded93fdec3916805151ff36016fe2ae7f718ca1a9da406f09dcd64736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009de8aa7743660e73a481e5647e75050da9504533000000000000000000000000440daf974bf6c97e9442fffd022ca554ee94219c
-----Decoded View---------------
Arg [0] : _v3TwapUtilities (address): 0x9dE8AA7743660e73a481E5647E75050dA9504533
Arg [1] : _dexAdapter (address): 0x440dAF974BF6C97e9442FfFd022cA554eE94219c
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000009de8aa7743660e73a481e5647e75050da9504533
Arg [1] : 000000000000000000000000440daf974bf6c97e9442fffd022ca554ee94219c
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.