UNPKG

@zarclays/zswap-trident

Version:
363 lines 73.6 kB
{ "address": "0x1be211D8DA40BC0ae8719c6663307Bfc987b1d6c", "abi": [ { "inputs": [ { "internalType": "contract IBentoBoxMinimal", "name": "_bentoBox", "type": "address" }, { "internalType": "contract IPoolFactory", "name": "_poolFactoryCP", "type": "address" }, { "internalType": "contract IMasterDeployer", "name": "_masterDeployer", "type": "address" } ], "stateMutability": "nonpayable", "type": "constructor" }, { "inputs": [], "name": "MinimumOutput", "type": "error" }, { "inputs": [], "name": "bentoBox", "outputs": [ { "internalType": "contract IBentoBoxMinimal", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "masterDeployer", "outputs": [ { "internalType": "contract IMasterDeployer", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "contract IConstantProductPool", "name": "currentPool", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" }, { "internalType": "uint256", "name": "swapFee", "type": "uint256" }, { "internalType": "bool", "name": "twapSupport", "type": "bool" }, { "internalType": "uint256", "name": "minToken0Received", "type": "uint256" }, { "internalType": "uint256", "name": "minToken1Received", "type": "uint256" }, { "internalType": "uint256", "name": "minLpReceived", "type": "uint256" } ], "name": "migrateCP", "outputs": [ { "internalType": "uint256", "name": "liquidity", "type": "uint256" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "contract IUniswapV2Minimal", "name": "pair", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" }, { "internalType": "uint256", "name": "swapFee", "type": "uint256" }, { "internalType": "bool", "name": "twapSupport", "type": "bool" }, { "internalType": "uint256", "name": "minToken0Received", "type": "uint256" }, { "internalType": "uint256", "name": "minToken1Received", "type": "uint256" }, { "internalType": "uint256", "name": "minLpReceived", "type": "uint256" } ], "name": "migrateLegacyToCP", "outputs": [ { "internalType": "uint256", "name": "liquidity", "type": "uint256" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "bytes[]", "name": "data", "type": "bytes[]" } ], "name": "multicall", "outputs": [ { "internalType": "bytes[]", "name": "results", "type": "bytes[]" } ], "stateMutability": "payable", "type": "function" }, { "inputs": [], "name": "poolFactoryCP", "outputs": [ { "internalType": "contract IPoolFactory", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "token", "type": "address" }, { "internalType": "uint256", "name": "value", "type": "uint256" }, { "internalType": "uint256", "name": "deadline", "type": "uint256" }, { "internalType": "uint8", "name": "v", "type": "uint8" }, { "internalType": "bytes32", "name": "r", "type": "bytes32" }, { "internalType": "bytes32", "name": "s", "type": "bytes32" } ], "name": "selfPermit", "outputs": [], "stateMutability": "payable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "token", "type": "address" }, { "internalType": "uint256", "name": "nonce", "type": "uint256" }, { "internalType": "uint256", "name": "expiry", "type": "uint256" }, { "internalType": "uint8", "name": "v", "type": "uint8" }, { "internalType": "bytes32", "name": "r", "type": "bytes32" }, { "internalType": "bytes32", "name": "s", "type": "bytes32" } ], "name": "selfPermitAllowed", "outputs": [], "stateMutability": "payable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "token", "type": "address" }, { "internalType": "uint256", "name": "nonce", "type": "uint256" }, { "internalType": "uint256", "name": "expiry", "type": "uint256" }, { "internalType": "uint8", "name": "v", "type": "uint8" }, { "internalType": "bytes32", "name": "r", "type": "bytes32" }, { "internalType": "bytes32", "name": "s", "type": "bytes32" } ], "name": "selfPermitAllowedIfNecessary", "outputs": [], "stateMutability": "payable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "token", "type": "address" }, { "internalType": "uint256", "name": "value", "type": "uint256" }, { "internalType": "uint256", "name": "deadline", "type": "uint256" }, { "internalType": "uint8", "name": "v", "type": "uint8" }, { "internalType": "bytes32", "name": "r", "type": "bytes32" }, { "internalType": "bytes32", "name": "s", "type": "bytes32" } ], "name": "selfPermitIfNecessary", "outputs": [], "stateMutability": "payable", "type": "function" } ], "transactionHash": "0x884fae642f03e14bce61be1d0a0626f0d1c2a8fbcee4efbb94dbd1327e9a416a", "receipt": { "to": null, "from": "0xf87BC5535602077d340806D71f805EA9907a843D", "contractAddress": "0x1be211D8DA40BC0ae8719c6663307Bfc987b1d6c", "transactionIndex": 1, "gasUsed": "1458798", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "blockHash": "0x9a484ab403de976edcfd5b17ee16c482d8bb7f034108320f2aba59a95bde1fbb", "transactionHash": "0x884fae642f03e14bce61be1d0a0626f0d1c2a8fbcee4efbb94dbd1327e9a416a", "logs": [], "blockNumber": 162103, "cumulativeGasUsed": "1762933", "status": 1, "byzantium": true }, "args": [ "0xc35DADB65012eC5796536bD9864eD8773aBc74C4", "0x0769fd68dFb93167989C6f7254cd0D766Fb2841F", "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506" ], "numDeployments": 1, "solcInputHash": "76e6dc96ea94c96e1c2463853d56dcaa", "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"contract IPoolFactory\",\"name\":\"_poolFactoryCP\",\"type\":\"address\"},{\"internalType\":\"contract IMasterDeployer\",\"name\":\"_masterDeployer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"MinimumOutput\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"masterDeployer\",\"outputs\":[{\"internalType\":\"contract IMasterDeployer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IConstantProductPool\",\"name\":\"currentPool\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"swapFee\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"twapSupport\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"minToken0Received\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minToken1Received\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLpReceived\",\"type\":\"uint256\"}],\"name\":\"migrateCP\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IUniswapV2Minimal\",\"name\":\"pair\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"swapFee\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"twapSupport\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"minToken0Received\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minToken1Received\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLpReceived\",\"type\":\"uint256\"}],\"name\":\"migrateLegacyToCP\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"multicall\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"poolFactoryCP\",\"outputs\":[{\"internalType\":\"contract IPoolFactory\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"selfPermit\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"selfPermitAllowed\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"selfPermitAllowedIfNecessary\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"selfPermitIfNecessary\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"migrateCP(address,uint256,uint256,bool,uint256,uint256,uint256)\":{\"details\":\"If the pool with the current conditions doesn't exist it will be deployed. \",\"params\":{\"amount\":\"Liquidity amount (Lp token balance) to be migrated.\",\"currentPool\":\"Trident CP pool address we want to migrate from. Can be form an outdated CP factory.\",\"minLpReceived\":\"Slippage protection for minting liquidity on the Trident CP pool.\",\"minToken0Received\":\"Slippage protection for removing liquidity. Values are in BentoBox shares.\",\"minToken1Received\":\"Slippage protection for removing liquidity. Values are in BentoBox shares.\",\"swapFee\":\"Swap fee of the Trident CP pool we are migrating into.\",\"twapSupport\":\"Whether the Trident CP pool we are migrating into supports twap oracles.\"}},\"migrateLegacyToCP(address,uint256,uint256,bool,uint256,uint256,uint256)\":{\"details\":\"If the pool with the current conditions doesn't exist it will be deployed. \",\"params\":{\"amount\":\"Liquidity amount (Lp token balance) to be migrated.\",\"minLpReceived\":\"Slippage protection for minting liquidity on the Trident CP pool.\",\"minToken0Received\":\"Slippage protection for removing liquidity from a UniV2 style pool.\",\"minToken1Received\":\"Slippage protection for removing liquidity from a UniV2 style pool.\",\"pair\":\"Uniswap V2 style liquidity pool address.\",\"swapFee\":\"Swap fee of the Trident CP pool we are migrating into.\",\"twapSupport\":\"Whether the Trident CP pool we are migrating into supports twap oracles.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"migrateCP(address,uint256,uint256,bool,uint256,uint256,uint256)\":{\"notice\":\"Function to migrate betewwn Trident CP pools with different fee / twap settings.\"},\"migrateLegacyToCP(address,uint256,uint256,bool,uint256,uint256,uint256)\":{\"notice\":\"Function to migrate existing Sushiswap or other Uniswap V2 style pools to Trident.\"}},\"notice\":\"Liquidity migrator from UniV2 style pool to Trident Constant product pool.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/migration/TridentSushiRollCP.sol\":\"TridentSushiRollCP\"},\"evmVersion\":\"london\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x00000000d41867734bbee4c6863d9255b2b06ac1\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xbbc8ac883ac3c0078ce5ad3e288fbb3ffcc8a30c3a98c0fda0114d64fc44fca2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"contracts/abstract/Multicall.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\n/// @notice Helper utility that enables calling multiple local methods in a single call.\\n/// @author Modified from Uniswap (https://github.com/Uniswap/v3-periphery/blob/main/contracts/base/Multicall.sol)\\n/// License-Identifier: GPL-2.0-or-later\\nabstract contract Multicall {\\n function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {\\n results = new bytes[](data.length);\\n \\n for (uint256 i; i < data.length;) {\\n (bool success, bytes memory result) = address(this).delegatecall(data[i]);\\n\\n if (!success) {\\n // Next 5 lines from https://ethereum.stackexchange.com/a/83577\\n if (result.length < 68) revert();\\n assembly {\\n result := add(result, 0x04)\\n }\\n revert(abi.decode(result, (string)));\\n }\\n\\n results[i] = result;\\n\\n // cannot realistically overflow on human timescales\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6f23b4ab12c911b68e01bac097dcf6d6b88c2ac86a41f7b180c3792fc68e7d59\",\"license\":\"GPL-3.0-or-later\"},\"contracts/abstract/SelfPermit.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\\\";\\n\\nimport \\\"../interfaces/IERC20PermitAllowed.sol\\\";\\n\\nabstract contract SelfPermit {\\n function selfPermit(\\n address token,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public payable {\\n IERC20Permit(token).permit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n\\n function selfPermitIfNecessary(\\n address token,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external payable {\\n if (IERC20(token).allowance(msg.sender, address(this)) < value) selfPermit(token, value, deadline, v, r, s);\\n }\\n\\n function selfPermitAllowed(\\n address token,\\n uint256 nonce,\\n uint256 expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public payable {\\n IERC20PermitAllowed(token).permit(msg.sender, address(this), nonce, expiry, true, v, r, s);\\n }\\n\\n function selfPermitAllowedIfNecessary(\\n address token,\\n uint256 nonce,\\n uint256 expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external payable {\\n if (IERC20(token).allowance(msg.sender, address(this)) < type(uint256).max)\\n selfPermitAllowed(token, nonce, expiry, v, r, s);\\n }\\n}\",\"keccak256\":\"0x7c3fc6ac4702a69fd99e90daaa8a40deed174a6d55034acf36c9e8f5aff60e46\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\nimport \\\"../libraries/RebaseLibrary.sol\\\";\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe9dfcff95da3b487ff37f646aef14a998a36f90122fd5693096b5e3b14ea09af\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IConstantProductPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IPool.sol\\\";\\n\\ninterface IConstantProductPool is IPool, IERC20 {\\n function getNativeReserves()\\n external\\n view\\n returns (\\n uint256 _nativeReserve0,\\n uint256 _nativeReserve1,\\n uint32\\n );\\n}\\n\",\"keccak256\":\"0xa5b857865863dcba3024d6eb8670605344d9d4d0525ccb4737e0093860eb190d\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IERC20PermitAllowed.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\ninterface IERC20PermitAllowed {\\n function permit(\\n address holder,\\n address spender,\\n uint256 nonce,\\n uint256 expiry,\\n bool allowed,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n}\",\"keccak256\":\"0xe943e4b44f10a53f75a23b957da3206c7c9fc0a38fe95aecd982073b061d651d\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IMasterDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\n/// @notice Trident pool deployer interface.\\ninterface IMasterDeployer {\\n function barFee() external view returns (uint256);\\n\\n function barFeeTo() external view returns (address);\\n\\n function bento() external view returns (address);\\n\\n function migrator() external view returns (address);\\n\\n function pools(address pool) external view returns (bool);\\n\\n function deployPool(address factory, bytes calldata deployData) external returns (address);\\n}\\n\",\"keccak256\":\"0x91c23deb7e4372faa35a0ae4ef6ccd684049aea7b2c75cf63009b28591b91cbc\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IPoolFactory.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\n/// @notice Trident pool deployment interface.\\ninterface IPoolFactory {\\n function deployPool(bytes calldata _deployData) external returns (address pool);\\n\\n function configAddress(bytes32 data) external returns (address pool);\\n}\\n\",\"keccak256\":\"0x03b9677a7914f97ca3ae57deb690cb80d0f1ef4d3541573b4dee6d3cebd5df2e\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/ITridentRouter.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\n/// @notice Trident pool router interface.\\ninterface ITridentRouter {\\n struct Path {\\n address pool;\\n bytes data;\\n }\\n\\n struct ExactInputSingleParams {\\n uint256 amountIn;\\n uint256 amountOutMinimum;\\n address pool;\\n address tokenIn;\\n bytes data;\\n }\\n\\n struct ExactInputParams {\\n address tokenIn;\\n uint256 amountIn;\\n uint256 amountOutMinimum;\\n Path[] path;\\n }\\n\\n struct TokenInput {\\n address token;\\n bool native;\\n uint256 amount;\\n }\\n\\n struct InitialPath {\\n address tokenIn;\\n address pool;\\n bool native;\\n uint256 amount;\\n bytes data;\\n }\\n\\n struct PercentagePath {\\n address tokenIn;\\n address pool;\\n uint64 balancePercentage; // Multiplied by 10^6. 100% = 100_000_000\\n bytes data;\\n }\\n\\n struct Output {\\n address token;\\n address to;\\n bool unwrapBento;\\n uint256 minAmount;\\n }\\n\\n struct ComplexPathParams {\\n InitialPath[] initialPath;\\n PercentagePath[] percentagePath;\\n Output[] output;\\n }\\n}\\n\",\"keccak256\":\"0x40f1af6b213ff8827d515460f9057eb87ddc35d8020501f727d229ea239cbf24\",\"license\":\"GPL-3.0-or-later\"},\"contracts/interfaces/IUniswapV2Minimal.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Minimal Uniswap V2 LP interface.\\ninterface IUniswapV2Minimal is IERC20 {\\n function token0() external view returns (address);\\n\\n function token1() external view returns (address);\\n\\n function burn(address to) external returns (uint256 amount0, uint256 amount1);\\n}\\n\",\"keccak256\":\"0xddc65849aeea92db01b9e679d498b71f7479f0207dd61c9e758176d57058cfcb\",\"license\":\"GPL-3.0-or-later\"},\"contracts/libraries/RebaseLibrary.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity ^0.8;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa83360497e7e2a04332211832a8ceb41ef0301892fcf1b17174d7d4466782d44\",\"license\":\"GPL-3.0-or-later\"},\"contracts/migration/TridentSushiRollCP.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.8.0;\\n\\nimport \\\"../abstract/SelfPermit.sol\\\";\\nimport \\\"../abstract/Multicall.sol\\\";\\nimport \\\"../interfaces/IUniswapV2Minimal.sol\\\";\\nimport \\\"../interfaces/IBentoBoxMinimal.sol\\\";\\nimport \\\"../interfaces/ITridentRouter.sol\\\";\\nimport \\\"../interfaces/IMasterDeployer.sol\\\";\\nimport \\\"../interfaces/IPoolFactory.sol\\\";\\nimport \\\"../interfaces/IPool.sol\\\";\\nimport \\\"../interfaces/IConstantProductPool.sol\\\";\\n\\n/// @notice Liquidity migrator from UniV2 style pool to Trident Constant product pool.\\ncontract TridentSushiRollCP is SelfPermit, Multicall {\\n error MinimumOutput();\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n IPoolFactory public immutable poolFactoryCP;\\n IMasterDeployer public immutable masterDeployer;\\n\\n constructor(\\n IBentoBoxMinimal _bentoBox,\\n IPoolFactory _poolFactoryCP,\\n IMasterDeployer _masterDeployer\\n ) {\\n bentoBox = _bentoBox;\\n poolFactoryCP = _poolFactoryCP;\\n masterDeployer = _masterDeployer;\\n }\\n\\n /** @notice Function to migrate existing Sushiswap or other Uniswap V2 style pools to Trident.\\n @param pair Uniswap V2 style liquidity pool address.\\n @param amount Liquidity amount (Lp token balance) to be migrated.\\n @param swapFee Swap fee of the Trident CP pool we are migrating into.\\n @param twapSupport Whether the Trident CP pool we are migrating into supports twap oracles.\\n @param minToken0Received Slippage protection for removing liquidity from a UniV2 style pool.\\n @param minToken1Received Slippage protection for removing liquidity from a UniV2 style pool.\\n @param minLpReceived Slippage protection for minting liquidity on the Trident CP pool.\\n @dev If the pool with the current conditions doesn't exist it will be deployed. */\\n function migrateLegacyToCP(\\n IUniswapV2Minimal pair,\\n uint256 amount,\\n uint256 swapFee,\\n bool twapSupport,\\n uint256 minToken0Received,\\n uint256 minToken1Received,\\n uint256 minLpReceived\\n ) external returns (uint256 liquidity) {\\n address token0 = pair.token0();\\n address token1 = pair.token1();\\n\\n bytes memory poolData = abi.encode(token0, token1, swapFee, twapSupport);\\n address tridentPool = poolFactoryCP.configAddress(keccak256(poolData));\\n\\n if (tridentPool == address(0)) {\\n tridentPool = masterDeployer.deployPool(address(poolFactoryCP), poolData);\\n }\\n\\n pair.transferFrom(msg.sender, address(pair), amount);\\n (uint256 amount0, uint256 amount1) = pair.burn(address(bentoBox));\\n\\n if (amount0 < minToken0Received || amount1 < minToken1Received) revert MinimumOutput();\\n\\n bentoBox.deposit(token0, address(bentoBox), tridentPool, amount0, 0);\\n bentoBox.deposit(token1, address(bentoBox), tridentPool, amount1, 0);\\n\\n liquidity = IPool(tridentPool).mint(abi.encode(msg.sender));\\n\\n if (liquidity < minLpReceived) revert MinimumOutput();\\n }\\n\\n /** @notice Function to migrate betewwn Trident CP pools with different fee / twap settings.\\n @param currentPool Trident CP pool address we want to migrate from. Can be form an outdated CP factory.\\n @param amount Liquidity amount (Lp token balance) to be migrated.\\n @param swapFee Swap fee of the Trident CP pool we are migrating into.\\n @param twapSupport Whether the Trident CP pool we are migrating into supports twap oracles.\\n @param minToken0Received Slippage protection for removing liquidity. Values are in BentoBox shares.\\n @param minToken1Received Slippage protection for removing liquidity. Values are in BentoBox shares.\\n @param minLpReceived Slippage protection for minting liquidity on the Trident CP pool.\\n @dev If the pool with the current conditions doesn't exist it will be deployed. */\\n function migrateCP(\\n IConstantProductPool currentPool,\\n uint256 amount,\\n uint256 swapFee,\\n bool twapSupport,\\n uint256 minToken0Received,\\n uint256 minToken1Received,\\n uint256 minLpReceived\\n ) external returns (uint256 liquidity) {\\n address[] memory tokens = currentPool.getAssets();\\n\\n bytes memory newPoolData = abi.encode(tokens[0], tokens[1], swapFee, twapSupport);\\n\\n address newPool = poolFactoryCP.configAddress(keccak256(newPoolData));\\n\\n if (newPool == address(0)) {\\n newPool = masterDeployer.deployPool(address(poolFactoryCP), newPoolData);\\n }\\n\\n currentPool.transferFrom(msg.sender, address(currentPool), amount);\\n\\n IPool.TokenAmount[] memory tokenAmounts = currentPool.burn(abi.encode(newPool, false));\\n\\n (uint256 amount0, uint256 amount1) = (tokenAmounts[0].amount, tokenAmounts[1].amount);\\n\\n if (amount0 < minToken0Received || amount1 < minToken1Received) revert MinimumOutput();\\n\\n liquidity = IPool(newPool).mint(abi.encode(msg.sender));\\n\\n if (liquidity < minLpReceived) revert MinimumOutput();\\n }\\n}\\n\",\"keccak256\":\"0x9013497569f9e0778c407cde648872e14e09d1559f715f17e43c825b6ab2206d\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", "bytecode": "0x60e06040523480156200001157600080fd5b5060405162001ab538038062001ab583398101604081905262000034916200006b565b6001600160a01b0392831660805290821660a0521660c052620000bf565b6001600160a01b03811681146200006857600080fd5b50565b6000806000606084860312156200008157600080fd5b83516200008e8162000052565b6020850151909350620000a18162000052565b6040850151909250620000b48162000052565b809150509250925092565b60805160a05160c0516119876200012e60003960008181610203015281816105480152610b360152600081816101cf0152818161046c0152818161057501528181610a5a0152610b6301526000818161013001528181610caf01528181610db50152610e8601526119876000f3fe6080604052600436106100b15760003560e01c8063ac9650d811610069578063c98ce1c91161004e578063c98ce1c9146101bd578063cf58879a146101f1578063f3995c671461022557600080fd5b8063ac9650d81461018a578063c2e3140a146101aa57600080fd5b806354b6ee591161009a57806354b6ee59146100fe5780636b2ace871461011e578063a4a78f0c1461017757600080fd5b80634659a494146100b6578063543d0ee9146100cb575b600080fd5b6100c96100c43660046112ca565b610238565b005b3480156100d757600080fd5b506100eb6100e636600461133a565b6102f3565b6040519081526020015b60405180910390f35b34801561010a57600080fd5b506100eb61011936600461133a565b6108ce565b34801561012a57600080fd5b506101527f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f5565b6100c96101853660046112ca565b610f40565b61019d61019836600461139f565b611012565b6040516100f5919061148e565b6100c96101b83660046112ca565b611182565b3480156101c957600080fd5b506101527f000000000000000000000000000000000000000000000000000000000000000081565b3480156101fd57600080fd5b506101527f000000000000000000000000000000000000000000000000000000000000000081565b6100c96102333660046112ca565b611228565b6040517f8fcbaf0c00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101869052606481018590526001608482015260ff841660a482015260c4810183905260e4810182905273ffffffffffffffffffffffffffffffffffffffff871690638fcbaf0c90610104015b600060405180830381600087803b1580156102d357600080fd5b505af11580156102e7573d6000803e3d6000fd5b50505050505050505050565b6000808873ffffffffffffffffffffffffffffffffffffffff166367e4ac2c6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610341573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261038791908101906115d9565b905060008160008151811061039e5761039e611678565b6020026020010151826001815181106103b9576103b9611678565b60200260200101518989604051602001610407949392919073ffffffffffffffffffffffffffffffffffffffff94851681529290931660208301526040820152901515606082015260800190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160208201207ff6ab6d99000000000000000000000000000000000000000000000000000000008352600483015291506000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063f6ab6d99906024016020604051808303816000875af11580156104ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ee91906116a7565b905073ffffffffffffffffffffffffffffffffffffffff81166105e5576040517f250558dc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063250558dc9061059f907f00000000000000000000000000000000000000000000000000000000000000009086906004016116cb565b6020604051808303816000875af11580156105be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e291906116a7565b90505b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8c1660248201819052604482018c9052906323b872dd906064016020604051808303816000875af115801561065f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106839190611702565b506040805173ffffffffffffffffffffffffffffffffffffffff8381166020830152600082840181905283518084038501815260608401948590527f2a07b6c70000000000000000000000000000000000000000000000000000000090945292908e1691632a07b6c7916106f99160640161171f565b6000604051808303816000875af1158015610718573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261075e9190810190611732565b90506000808260008151811061077657610776611678565b6020026020010151602001518360018151811061079557610795611678565b60200260200101516020015191509150898210806107b257508881105b156107e9576040517f9b9d48e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805133602082015273ffffffffffffffffffffffffffffffffffffffff861691637ba0e2e791015b6040516020818303038152906040526040518263ffffffff1660e01b815260040161083e919061171f565b6020604051808303816000875af115801561085d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061088191906117e6565b9650878710156108bd576040517f9b9d48e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050979650505050505050565b6000808873ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa15801561091c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094091906116a7565b905060008973ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561098f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b391906116a7565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660208301528316918101919091526060810