More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 6,640 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Sell Base Tokens... | 18137542 | 3 days ago | IN | 0 ETH | 0.0000002 | ||||
Remove Liquidity... | 17996297 | 6 days ago | IN | 0 ETH | 0.00000038 | ||||
Sell Base Tokens... | 17940514 | 8 days ago | IN | 0 ETH | 0.00000139 | ||||
Remove Liquidity | 17939411 | 8 days ago | IN | 0 ETH | 0.00000126 | ||||
Remove Liquidity | 17939188 | 8 days ago | IN | 0 ETH | 0.00000126 | ||||
Sell Base Tokens... | 17931264 | 8 days ago | IN | 0 ETH | 0.00000052 | ||||
Remove Liquidity | 17931233 | 8 days ago | IN | 0 ETH | 0.00000038 | ||||
Sell Base Tokens... | 17905559 | 8 days ago | IN | 0 ETH | 0.00000045 | ||||
Remove Liquidity | 17905542 | 8 days ago | IN | 0 ETH | 0.00000042 | ||||
Sell Quote Token... | 17746189 | 12 days ago | IN | 0 ETH | 0.00000034 | ||||
Sell Quote Token... | 17708713 | 13 days ago | IN | 0 ETH | 0.00000017 | ||||
Sell Base Tokens... | 17706146 | 13 days ago | IN | 0 ETH | 0.00000151 | ||||
Remove Liquidity... | 17660538 | 14 days ago | IN | 0 ETH | 0.0000003 | ||||
Sell Quote Token... | 17440457 | 19 days ago | IN | 0 ETH | 0.00000026 | ||||
Sell Quote Token... | 17440393 | 19 days ago | IN | 0 ETH | 0.00000026 | ||||
Sell Base Tokens... | 17415913 | 20 days ago | IN | 0 ETH | 0.00000004 | ||||
Remove Liquidity | 17415698 | 20 days ago | IN | 0 ETH | 0.00000002 | ||||
Remove Liquidity... | 17390694 | 20 days ago | IN | 0 ETH | 0.00000006 | ||||
Sell Quote Token... | 17313413 | 22 days ago | IN | 0 ETH | 0.00000003 | ||||
Remove Liquidity | 17313152 | 22 days ago | IN | 0 ETH | 0.00000002 | ||||
Sell Quote Token... | 17184385 | 25 days ago | IN | 0 ETH | 0.00000022 | ||||
Sell Quote Token... | 17184373 | 25 days ago | IN | 0 ETH | 0.00000025 | ||||
Sell Quote Token... | 17172837 | 25 days ago | IN | 0 ETH | 0.00000025 | ||||
Sell Quote Token... | 17128143 | 26 days ago | IN | 0 ETH | 0.00000023 | ||||
Remove Liquidity | 17127941 | 26 days ago | IN | 0 ETH | 0.00000021 |
Loading...
Loading
Contract Name:
BlastMIMSwapRouter
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 400 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.0; import {BlastYields} from "/blast/libraries/BlastYields.sol"; import {Router} from "/mimswap/periphery/Router.sol"; import {IWETH} from "interfaces/IWETH.sol"; import {IFactory} from "/mimswap/interfaces/IFactory.sol"; contract BlastMIMSwapRouter is Router { constructor(IWETH weth_, IFactory factory, address governor_) Router(weth_, factory) { if (governor_ == address(0)) { revert ErrZeroAddress(); } BlastYields.configureDefaultClaimables(governor_); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.0; import {IBlast, IERC20Rebasing, YieldMode, GasMode} from "interfaces/IBlast.sol"; import {Address} from "openzeppelin-contracts/utils/Address.sol"; library BlastYields { event LogBlastGasClaimed(address indexed recipient, uint256 amount); event LogBlastETHClaimed(address indexed recipient, uint256 amount); event LogBlastTokenClaimed(address indexed recipient, address indexed token, uint256 amount); event LogBlastTokenClaimableEnabled(address indexed contractAddress, address indexed token); event LogBlastNativeClaimableEnabled(address indexed contractAddress); IBlast constant BLAST_YIELD_PRECOMPILE = IBlast(0x4300000000000000000000000000000000000002); ////////////////////////////////////////////////////////////////////////////////////// // CONFIGURATION ////////////////////////////////////////////////////////////////////////////////////// function enableTokenClaimable(address token) internal { if (IERC20Rebasing(token).getConfiguration(address(this)) == YieldMode.CLAIMABLE) { return; } IERC20Rebasing(token).configure(YieldMode.CLAIMABLE); emit LogBlastTokenClaimableEnabled(address(this), token); } function configureDefaultClaimables(address governor_) internal { BLAST_YIELD_PRECOMPILE.configure(YieldMode.CLAIMABLE, GasMode.CLAIMABLE, governor_); emit LogBlastNativeClaimableEnabled(address(this)); } ////////////////////////////////////////////////////////////////////////////////////// // GAS CLAIMING ////////////////////////////////////////////////////////////////////////////////////// function claimMaxGasYields(address recipient) internal returns (uint256) { return claimMaxGasYields(address(this), recipient); } function claimMaxGasYields(address contractAddress, address recipient) internal returns (uint256 amount) { amount = BLAST_YIELD_PRECOMPILE.claimMaxGas(contractAddress, recipient); emit LogBlastGasClaimed(recipient, amount); } ////////////////////////////////////////////////////////////////////////////////////// // NATIVE CLAIMING //////////////////////////////////////////////////////////////////////////////////////< function claimAllNativeYields(address recipient) internal returns (uint256 amount) { return claimAllNativeYields(address(this), recipient); } function claimAllNativeYields(address contractAddress, address recipient) internal returns (uint256 amount) { amount = BLAST_YIELD_PRECOMPILE.claimAllYield(contractAddress, recipient); emit LogBlastETHClaimed(recipient, amount); } function claimNativeYields(address contractAddress, uint256 amount, address recipient) internal returns (uint256) { amount = BLAST_YIELD_PRECOMPILE.claimYield(contractAddress, recipient, amount); emit LogBlastETHClaimed(recipient, amount); return amount; } ////////////////////////////////////////////////////////////////////////////////////// // TOKENS CLAIMING ////////////////////////////////////////////////////////////////////////////////////// function claimAllTokenYields(address token, address recipient) internal returns (uint256 amount) { amount = IERC20Rebasing(token).claim(recipient, IERC20Rebasing(token).getClaimableAmount(address(this))); emit LogBlastTokenClaimed(recipient, address(token), amount); } function claimTokenYields(address token, uint256 amount, address recipient) internal returns (uint256) { amount = IERC20Rebasing(token).claim(recipient, amount); emit LogBlastTokenClaimed(recipient, address(token), amount); return amount; } ////////////////////////////////////////////////////////////////////////////////////// // ARBITRARY PRECOMPILE CALLS // Meant to be used for any other calls to the precompile not covered by the above ////////////////////////////////////////////////////////////////////////////////////// function callPrecompile(bytes calldata data) internal { Address.functionCall(address(BLAST_YIELD_PRECOMPILE), data); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.0; import {SafeTransferLib} from "solady/utils/SafeTransferLib.sol"; import {IERC20} from "openzeppelin-contracts/interfaces/IERC20.sol"; import {Math} from "/mimswap/libraries/Math.sol"; import {DecimalMath} from "/mimswap/libraries/DecimalMath.sol"; import {IWETH} from "interfaces/IWETH.sol"; import {IMagicLP} from "/mimswap/interfaces/IMagicLP.sol"; import {IFactory} from "/mimswap/interfaces/IFactory.sol"; import {IERC20Metadata} from "openzeppelin-contracts/interfaces/IERC20Metadata.sol"; import {ReentrancyGuard} from "solady/utils/ReentrancyGuard.sol"; struct AddLiquidityImbalancedParams { address lp; address to; uint256 baseInAmount; uint256 quoteInAmount; bool remainingAmountToSwapIsBase; uint256 remainingAmountToSwap; uint256 minimumShares; uint256 deadline; } /// @notice Router for creating and interacting with MagicLP /// Can only be used for pool created by the Factory /// /// @dev A pool can be removed from the Factory. So, when integrating with this contract, /// validate that the pool exists using the Factory `poolExists` function. contract Router is ReentrancyGuard { using SafeTransferLib for address; using SafeTransferLib for address payable; error ErrNotETHLP(); error ErrExpired(); error ErrZeroAddress(); error ErrPathTooLong(); error ErrEmptyPath(); error ErrBadPath(); error ErrTooHighSlippage(uint256 amountOut); error ErrInvalidBaseToken(); error ErrInvalidQuoteToken(); error ErrInTokenNotETH(); error ErrOutTokenNotETH(); error ErrInvalidQuoteTarget(); error ErrZeroDecimals(); error ErrTooLargeDecimals(); error ErrDecimalsDifferenceTooLarge(); error ErrUnknownPool(); uint256 public constant MAX_BASE_QUOTE_DECIMALS_DIFFERENCE = 12; IWETH public immutable weth; IFactory public immutable factory; receive() external payable {} constructor(IWETH weth_, IFactory factory_) { if (address(weth_) == address(0) || address(factory_) == address(0)) { revert ErrZeroAddress(); } weth = weth_; factory = factory_; } modifier ensureDeadline(uint256 deadline) { if (block.timestamp > deadline) { revert ErrExpired(); } _; } modifier onlyKnownPool(address pool) { if (!factory.poolExists(pool)) { revert ErrUnknownPool(); } _; } function createPool( address baseToken, address quoteToken, uint256 lpFeeRate, uint256 i, uint256 k, address to, uint256 baseInAmount, uint256 quoteInAmount, bool protocolOwnedPool ) public virtual returns (address clone, uint256 shares) { _validateDecimals(IERC20Metadata(baseToken).decimals(), IERC20Metadata(quoteToken).decimals()); clone = IFactory(factory).create(baseToken, quoteToken, lpFeeRate, i, k, protocolOwnedPool); baseToken.safeTransferFrom(msg.sender, clone, baseInAmount); quoteToken.safeTransferFrom(msg.sender, clone, quoteInAmount); (shares, , ) = IMagicLP(clone).buyShares(to); } function createPoolETH( address token, bool useTokenAsQuote, uint256 lpFeeRate, uint256 i, uint256 k, address to, uint256 tokenInAmount, bool protocolOwnedPool ) public payable virtual returns (address clone, uint256 shares) { if (useTokenAsQuote) { _validateDecimals(18, IERC20Metadata(token).decimals()); } else { _validateDecimals(IERC20Metadata(token).decimals(), 18); } clone = IFactory(factory).create( useTokenAsQuote ? address(weth) : token, useTokenAsQuote ? token : address(weth), lpFeeRate, i, k, protocolOwnedPool ); weth.deposit{value: msg.value}(); token.safeTransferFrom(msg.sender, clone, tokenInAmount); address(weth).safeTransfer(clone, msg.value); (shares, , ) = IMagicLP(clone).buyShares(to); } function previewCreatePool( uint256 i, uint256 baseInAmount, uint256 quoteInAmount ) external pure returns (uint256 baseAdjustedInAmount, uint256 quoteAdjustedInAmount, uint256 shares) { shares = quoteInAmount < DecimalMath.mulFloor(baseInAmount, i) ? DecimalMath.divFloor(quoteInAmount, i) : baseInAmount; baseAdjustedInAmount = shares; quoteAdjustedInAmount = DecimalMath.mulFloor(shares, i); if (shares <= 2001) { return (0, 0, 0); } shares -= 1001; } function addLiquidity( address lp, address to, uint256 baseInAmount, uint256 quoteInAmount, uint256 minimumShares, uint256 deadline ) public virtual ensureDeadline(deadline) onlyKnownPool(lp) returns (uint256 baseAdjustedInAmount, uint256 quoteAdjustedInAmount, uint256 shares) { (baseAdjustedInAmount, quoteAdjustedInAmount) = _adjustAddLiquidity(lp, baseInAmount, quoteInAmount); IMagicLP(lp)._BASE_TOKEN_().safeTransferFrom(msg.sender, lp, baseAdjustedInAmount); IMagicLP(lp)._QUOTE_TOKEN_().safeTransferFrom(msg.sender, lp, quoteAdjustedInAmount); shares = _addLiquidity(lp, to, minimumShares); } function addLiquidityUnsafe( address lp, address to, uint256 baseInAmount, uint256 quoteInAmount, uint256 minimumShares, uint256 deadline ) public virtual ensureDeadline(deadline) onlyKnownPool(lp) returns (uint256 shares) { IMagicLP(lp)._BASE_TOKEN_().safeTransferFrom(msg.sender, lp, baseInAmount); IMagicLP(lp)._QUOTE_TOKEN_().safeTransferFrom(msg.sender, lp, quoteInAmount); return _addLiquidity(lp, to, minimumShares); } function addLiquidityETH( address lp, address to, address payable refundTo, uint256 tokenInAmount, uint256 minimumShares, uint256 deadline ) public payable virtual nonReentrant ensureDeadline(deadline) onlyKnownPool(lp) returns (uint256 baseAdjustedInAmount, uint256 quoteAdjustedInAmount, uint256 shares) { uint256 wethAdjustedAmount; uint256 tokenAdjustedAmount; address token = IMagicLP(lp)._BASE_TOKEN_(); if (token == address(weth)) { token = IMagicLP(lp)._QUOTE_TOKEN_(); (baseAdjustedInAmount, quoteAdjustedInAmount) = _adjustAddLiquidity(lp, msg.value, tokenInAmount); wethAdjustedAmount = baseAdjustedInAmount; tokenAdjustedAmount = quoteAdjustedInAmount; } else if (IMagicLP(lp)._QUOTE_TOKEN_() == address(weth)) { (baseAdjustedInAmount, quoteAdjustedInAmount) = _adjustAddLiquidity(lp, tokenInAmount, msg.value); wethAdjustedAmount = quoteAdjustedInAmount; tokenAdjustedAmount = baseAdjustedInAmount; } else { revert ErrNotETHLP(); } weth.deposit{value: wethAdjustedAmount}(); address(weth).safeTransfer(lp, wethAdjustedAmount); // Refund unused ETH if (msg.value > wethAdjustedAmount) { refundTo.safeTransferETH(msg.value - wethAdjustedAmount); } token.safeTransferFrom(msg.sender, lp, tokenAdjustedAmount); shares = _addLiquidity(lp, to, minimumShares); } function addLiquidityETHUnsafe( address lp, address to, uint256 tokenInAmount, uint256 minimumShares, uint256 deadline ) public payable virtual ensureDeadline(deadline) onlyKnownPool(lp) returns (uint256 shares) { address token = IMagicLP(lp)._BASE_TOKEN_(); if (token == address(weth)) { token = IMagicLP(lp)._QUOTE_TOKEN_(); } else if (IMagicLP(lp)._QUOTE_TOKEN_() != address(weth)) { revert ErrNotETHLP(); } weth.deposit{value: msg.value}(); address(weth).safeTransfer(lp, msg.value); token.safeTransferFrom(msg.sender, lp, tokenInAmount); return _addLiquidity(lp, to, minimumShares); } function previewRemoveLiquidity( address lp, uint256 sharesIn ) external view nonReadReentrant onlyKnownPool(lp) returns (uint256 baseAmountOut, uint256 quoteAmountOut) { uint256 baseBalance = IMagicLP(lp)._BASE_TOKEN_().balanceOf(address(lp)); uint256 quoteBalance = IMagicLP(lp)._QUOTE_TOKEN_().balanceOf(address(lp)); uint256 totalShares = IERC20(lp).totalSupply(); baseAmountOut = (baseBalance * sharesIn) / totalShares; quoteAmountOut = (quoteBalance * sharesIn) / totalShares; } function removeLiquidity( address lp, address to, uint256 sharesIn, uint256 minimumBaseAmount, uint256 minimumQuoteAmount, uint256 deadline ) public virtual onlyKnownPool(lp) returns (uint256 baseAmountOut, uint256 quoteAmountOut) { lp.safeTransferFrom(msg.sender, address(this), sharesIn); return IMagicLP(lp).sellShares(sharesIn, to, minimumBaseAmount, minimumQuoteAmount, "", deadline); } function removeLiquidityETH( address lp, address to, uint256 sharesIn, uint256 minimumETHAmount, uint256 minimumTokenAmount, uint256 deadline ) public virtual onlyKnownPool(lp) returns (uint256 ethAmountOut, uint256 tokenAmountOut) { lp.safeTransferFrom(msg.sender, address(this), sharesIn); address token = IMagicLP(lp)._BASE_TOKEN_(); if (token == address(weth)) { token = IMagicLP(lp)._QUOTE_TOKEN_(); (ethAmountOut, tokenAmountOut) = IMagicLP(lp).sellShares( sharesIn, address(this), minimumETHAmount, minimumTokenAmount, "", deadline ); } else if (IMagicLP(lp)._QUOTE_TOKEN_() == address(weth)) { (tokenAmountOut, ethAmountOut) = IMagicLP(lp).sellShares( sharesIn, address(this), minimumTokenAmount, minimumETHAmount, "", deadline ); } else { revert ErrNotETHLP(); } weth.withdraw(ethAmountOut); to.safeTransferETH(ethAmountOut); token.safeTransfer(to, tokenAmountOut); } function swapTokensForTokens( address to, uint256 amountIn, address[] calldata path, uint256 directions, uint256 minimumOut, uint256 deadline ) public virtual ensureDeadline(deadline) returns (uint256 amountOut) { _validatePath(path); address firstLp = path[0]; // Transfer to the first LP if (directions & 1 == 0) { IMagicLP(firstLp)._BASE_TOKEN_().safeTransferFrom(msg.sender, address(firstLp), amountIn); } else { IMagicLP(firstLp)._QUOTE_TOKEN_().safeTransferFrom(msg.sender, address(firstLp), amountIn); } return _swap(to, path, directions, minimumOut); } function swapETHForTokens( address to, address[] calldata path, uint256 directions, uint256 minimumOut, uint256 deadline ) public payable virtual ensureDeadline(deadline) returns (uint256 amountOut) { _validatePath(path); address firstLp = path[0]; address inToken; if (directions & 1 == 0) { inToken = IMagicLP(firstLp)._BASE_TOKEN_(); } else { inToken = IMagicLP(firstLp)._QUOTE_TOKEN_(); } // Transfer to the first LP if (inToken != address(weth)) { revert ErrInTokenNotETH(); } weth.deposit{value: msg.value}(); inToken.safeTransfer(address(firstLp), msg.value); return _swap(to, path, directions, minimumOut); } function swapTokensForETH( address to, uint256 amountIn, address[] calldata path, uint256 directions, uint256 minimumOut, uint256 deadline ) public virtual ensureDeadline(deadline) returns (uint256 amountOut) { _validatePath(path); uint256 lastLpIndex = path.length - 1; address lastLp = path[lastLpIndex]; address outToken; if ((directions >> lastLpIndex) & 1 == 0) { outToken = IMagicLP(lastLp)._QUOTE_TOKEN_(); } else { outToken = IMagicLP(lastLp)._BASE_TOKEN_(); } if (outToken != address(weth)) { revert ErrOutTokenNotETH(); } address firstLp = path[0]; // Transfer to the first LP if (directions & 1 == 0) { IMagicLP(firstLp)._BASE_TOKEN_().safeTransferFrom(msg.sender, firstLp, amountIn); } else { IMagicLP(firstLp)._QUOTE_TOKEN_().safeTransferFrom(msg.sender, firstLp, amountIn); } amountOut = _swap(address(this), path, directions, minimumOut); weth.withdraw(amountOut); to.safeTransferETH(amountOut); } function sellBaseTokensForTokens( address lp, address to, uint256 amountIn, uint256 minimumOut, uint256 deadline ) public virtual ensureDeadline(deadline) onlyKnownPool(lp) returns (uint256 amountOut) { IMagicLP(lp)._BASE_TOKEN_().safeTransferFrom(msg.sender, lp, amountIn); return _sellBase(lp, to, minimumOut); } function sellBaseETHForTokens( address lp, address to, uint256 minimumOut, uint256 deadline ) public payable virtual ensureDeadline(deadline) onlyKnownPool(lp) returns (uint256 amountOut) { address baseToken = IMagicLP(lp)._BASE_TOKEN_(); if (baseToken != address(weth)) { revert ErrInvalidBaseToken(); } weth.deposit{value: msg.value}(); baseToken.safeTransfer(lp, msg.value); return _sellBase(lp, to, minimumOut); } function sellBaseTokensForETH( address lp, address to, uint256 amountIn, uint256 minimumOut, uint256 deadline ) public virtual ensureDeadline(deadline) onlyKnownPool(lp) returns (uint256 amountOut) { if (IMagicLP(lp)._QUOTE_TOKEN_() != address(weth)) { revert ErrInvalidQuoteToken(); } IMagicLP(lp)._BASE_TOKEN_().safeTransferFrom(msg.sender, lp, amountIn); amountOut = _sellBase(lp, address(this), minimumOut); weth.withdraw(amountOut); to.safeTransferETH(amountOut); } function sellQuoteTokensForTokens( address lp, address to, uint256 amountIn, uint256 minimumOut, uint256 deadline ) public virtual ensureDeadline(deadline) onlyKnownPool(lp) returns (uint256 amountOut) { IMagicLP(lp)._QUOTE_TOKEN_().safeTransferFrom(msg.sender, lp, amountIn); return _sellQuote(lp, to, minimumOut); } function sellQuoteETHForTokens( address lp, address to, uint256 minimumOut, uint256 deadline ) public payable virtual ensureDeadline(deadline) onlyKnownPool(lp) returns (uint256 amountOut) { address quoteToken = IMagicLP(lp)._QUOTE_TOKEN_(); if (quoteToken != address(weth)) { revert ErrInvalidQuoteToken(); } weth.deposit{value: msg.value}(); quoteToken.safeTransfer(lp, msg.value); return _sellQuote(lp, to, minimumOut); } function sellQuoteTokensForETH( address lp, address to, uint256 amountIn, uint256 minimumOut, uint256 deadline ) public virtual ensureDeadline(deadline) onlyKnownPool(lp) returns (uint256 amountOut) { if (IMagicLP(lp)._BASE_TOKEN_() != address(weth)) { revert ErrInvalidBaseToken(); } IMagicLP(lp)._QUOTE_TOKEN_().safeTransferFrom(msg.sender, lp, amountIn); amountOut = _sellQuote(lp, address(this), minimumOut); weth.withdraw(amountOut); to.safeTransferETH(amountOut); } function addLiquidityOneSide( address lp, address to, bool inAmountIsBase, uint256 inAmount, uint256 inAmountToSwap, uint256 minimumShares, uint256 deadline ) public virtual ensureDeadline(deadline) onlyKnownPool(lp) returns (uint256 baseAmount, uint256 quoteAmount, uint256 shares) { address baseToken = IMagicLP(lp)._BASE_TOKEN_(); address quoteToken = IMagicLP(lp)._QUOTE_TOKEN_(); // base -> quote if (inAmountIsBase) { baseToken.safeTransferFrom(msg.sender, address(this), inAmount); baseAmount = inAmount - inAmountToSwap; baseToken.safeTransfer(lp, inAmountToSwap); quoteAmount = IMagicLP(lp).sellBase(address(this)); } // quote -> base else { quoteToken.safeTransferFrom(msg.sender, address(this), inAmount); quoteAmount = inAmount - inAmountToSwap; quoteToken.safeTransfer(lp, inAmountToSwap); baseAmount = IMagicLP(lp).sellQuote(address(this)); } (baseAmount, quoteAmount) = _adjustAddLiquidity(lp, baseAmount, quoteAmount); baseToken.safeTransfer(lp, baseAmount); quoteToken.safeTransfer(lp, quoteAmount); shares = _addLiquidity(lp, to, minimumShares); // Refund remaining tokens uint256 remaining = baseToken.balanceOf(address(this)); if (remaining > 0) { baseToken.safeTransfer(msg.sender, remaining); } remaining = quoteToken.balanceOf(address(this)); if (remaining > 0) { quoteToken.safeTransfer(msg.sender, remaining); } } function removeLiquidityOneSide( address lp, address to, bool withdrawBase, uint256 sharesIn, uint256 minAmountOut, uint256 deadline ) public virtual ensureDeadline(deadline) onlyKnownPool(lp) returns (uint256 amountOut) { address baseToken = IMagicLP(lp)._BASE_TOKEN_(); address quoteToken = IMagicLP(lp)._QUOTE_TOKEN_(); lp.safeTransferFrom(msg.sender, address(this), sharesIn); (uint256 baseAmount, uint256 quoteAmount) = IMagicLP(lp).sellShares(sharesIn, address(this), 0, 0, "", deadline); // withdraw base if (withdrawBase) { quoteToken.safeTransfer(lp, quoteAmount); amountOut = baseAmount + IMagicLP(lp).sellQuote(address(this)); if (amountOut > 0) { baseToken.safeTransfer(to, amountOut); } } // withdraw quote else { baseToken.safeTransfer(lp, baseAmount); amountOut = quoteAmount + IMagicLP(lp).sellBase(address(this)); if (amountOut > 0) { quoteToken.safeTransfer(to, amountOut); } } if (amountOut < minAmountOut) { revert ErrTooHighSlippage(amountOut); } } function addLiquidityImbalanced( AddLiquidityImbalancedParams calldata params ) public virtual ensureDeadline(params.deadline) onlyKnownPool(params.lp) returns (uint256 baseAdjustedInAmount, uint256 quoteAdjustedInAmount, uint256 shares) { address baseToken = IMagicLP(params.lp)._BASE_TOKEN_(); address quoteToken = IMagicLP(params.lp)._QUOTE_TOKEN_(); baseToken.safeTransferFrom(msg.sender, address(this), params.baseInAmount); quoteToken.safeTransferFrom(msg.sender, address(this), params.quoteInAmount); (baseAdjustedInAmount, quoteAdjustedInAmount) = _adjustAddLiquidity(params.lp, params.baseInAmount, params.quoteInAmount); // base -> quote if (params.remainingAmountToSwapIsBase) { baseToken.safeTransfer(params.lp, params.remainingAmountToSwap); baseAdjustedInAmount += (params.baseInAmount - baseAdjustedInAmount) - params.remainingAmountToSwap; quoteAdjustedInAmount += IMagicLP(params.lp).sellBase(address(this)); } // quote -> base else { quoteToken.safeTransfer(params.lp, params.remainingAmountToSwap); baseAdjustedInAmount += IMagicLP(params.lp).sellQuote(address(this)); quoteAdjustedInAmount += (params.quoteInAmount - quoteAdjustedInAmount) - params.remainingAmountToSwap; } (baseAdjustedInAmount, quoteAdjustedInAmount) = _adjustAddLiquidity(params.lp, baseAdjustedInAmount, quoteAdjustedInAmount); baseToken.safeTransfer(params.lp, baseAdjustedInAmount); quoteToken.safeTransfer(params.lp, quoteAdjustedInAmount); shares = _addLiquidity(params.lp, params.to, params.minimumShares); // Refund remaining tokens uint256 remaining = baseToken.balanceOf(address(this)); if (remaining > 0) { baseToken.safeTransfer(msg.sender, remaining); } remaining = quoteToken.balanceOf(address(this)); if (remaining > 0) { quoteToken.safeTransfer(msg.sender, remaining); } } ////////////////////////////////////////////////////////////////////////////////////// /// INTERNALS ////////////////////////////////////////////////////////////////////////////////////// function _addLiquidity(address lp, address to, uint256 minimumShares) internal returns (uint256 shares) { (shares, , ) = IMagicLP(lp).buyShares(to); if (shares < minimumShares) { revert ErrTooHighSlippage(shares); } } /// Adapted from: https://github.com/DODOEX/contractV2/blob/main/contracts/SmartRoute/proxies/DODODspProxy.sol /// Copyright 2020 DODO ZOO. Licensed under Apache-2.0. function _adjustAddLiquidity( address lp, uint256 baseInAmount, uint256 quoteInAmount ) internal view returns (uint256 baseAdjustedInAmount, uint256 quoteAdjustedInAmount) { if (IERC20(lp).totalSupply() == 0) { uint256 i = IMagicLP(lp)._I_(); uint256 shares = quoteInAmount < DecimalMath.mulFloor(baseInAmount, i) ? DecimalMath.divFloor(quoteInAmount, i) : baseInAmount; baseAdjustedInAmount = shares; quoteAdjustedInAmount = DecimalMath.mulFloor(shares, i); } else { (uint256 baseReserve, uint256 quoteReserve) = IMagicLP(lp).getReserves(); if (quoteReserve > 0 && baseReserve > 0) { uint256 baseIncreaseRatio = DecimalMath.divFloor(baseInAmount, baseReserve); uint256 quoteIncreaseRatio = DecimalMath.divFloor(quoteInAmount, quoteReserve); if (baseIncreaseRatio <= quoteIncreaseRatio) { baseAdjustedInAmount = baseInAmount; quoteAdjustedInAmount = DecimalMath.mulFloor(quoteReserve, baseIncreaseRatio); } else { quoteAdjustedInAmount = quoteInAmount; baseAdjustedInAmount = DecimalMath.mulFloor(baseReserve, quoteIncreaseRatio); } } } } function _swap(address to, address[] calldata path, uint256 directions, uint256 minimumOut) internal returns (uint256 amountOut) { uint256 iterations = path.length - 1; // Subtract by one as last swap is done separately for (uint256 i = 0; i < iterations; ) { address lp = path[i]; if (!factory.poolExists(lp)) { revert ErrUnknownPool(); } if (directions & 1 == 0) { // Sell base IMagicLP(lp).sellBase(address(path[i + 1])); } else { // Sell quote IMagicLP(lp).sellQuote(address(path[i + 1])); } directions >>= 1; unchecked { ++i; } } if ((directions & 1 == 0)) { amountOut = IMagicLP(path[iterations]).sellBase(to); } else { amountOut = IMagicLP(path[iterations]).sellQuote(to); } if (amountOut < minimumOut) { revert ErrTooHighSlippage(amountOut); } } function _sellBase(address lp, address to, uint256 minimumOut) internal returns (uint256 amountOut) { amountOut = IMagicLP(lp).sellBase(to); if (amountOut < minimumOut) { revert ErrTooHighSlippage(amountOut); } } function _sellQuote(address lp, address to, uint256 minimumOut) internal returns (uint256 amountOut) { amountOut = IMagicLP(lp).sellQuote(to); if (amountOut < minimumOut) { revert ErrTooHighSlippage(amountOut); } } function _validatePath(address[] calldata path) internal pure { uint256 pathLength = path.length; // Max 256 because of bits in directions if (pathLength > 256) { revert ErrPathTooLong(); } if (pathLength <= 0) { revert ErrEmptyPath(); } } function _validateDecimals(uint8 baseDecimals, uint8 quoteDecimals) internal pure { if (baseDecimals == 0 || quoteDecimals == 0) { revert ErrZeroDecimals(); } if (baseDecimals > 18 || quoteDecimals > 18) { revert ErrTooLargeDecimals(); } uint256 deltaDecimals = baseDecimals > quoteDecimals ? baseDecimals - quoteDecimals : quoteDecimals - baseDecimals; if (deltaDecimals > MAX_BASE_QUOTE_DECIMALS_DIFFERENCE) { revert ErrDecimalsDifferenceTooLarge(); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {IERC20} from "BoringSolidity/interfaces/IERC20.sol"; interface IWETH is IERC20 { function deposit() external payable; function withdraw(uint256) external; } interface IWETHAlike is IWETH {}
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IFactory { function predictDeterministicAddress( address creator, address baseToken_, address quoteToken_, uint256 lpFeeRate_, uint256 i_, uint256 k_ ) external view returns (address); function maintainerFeeRateModel() external view returns (address); function create( address baseToken_, address quoteToken_, uint256 lpFeeRate_, uint256 i_, uint256 k_, bool protocolOwnedPool_ ) external returns (address clone); function poolExists(address pool) external view returns (bool); function addPool(address creator, address baseToken, address quoteToken, address pool) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; enum YieldMode { AUTOMATIC, DISABLED, CLAIMABLE } enum GasMode { VOID, CLAIMABLE } interface IBlast { function governorMap(address) external view returns (address); // configure function configureContract(address contractAddress, YieldMode _yield, GasMode gasMode, address governor) external; function configure(YieldMode _yield, GasMode gasMode, address governor) external; // base configuration options function configureClaimableYield() external; function configureClaimableYieldOnBehalf(address contractAddress) external; function configureAutomaticYield() external; function configureAutomaticYieldOnBehalf(address contractAddress) external; function configureVoidYield() external; function configureVoidYieldOnBehalf(address contractAddress) external; function configureClaimableGas() external; function configureClaimableGasOnBehalf(address contractAddress) external; function configureVoidGas() external; function configureVoidGasOnBehalf(address contractAddress) external; function configureGovernor(address _governor) external; function configureGovernorOnBehalf(address _newGovernor, address contractAddress) external; // claim yield function claimYield(address contractAddress, address recipientOfYield, uint256 amount) external returns (uint256); function claimAllYield(address contractAddress, address recipientOfYield) external returns (uint256); // claim gas function claimAllGas(address contractAddress, address recipientOfGas) external returns (uint256); function claimGasAtMinClaimRate(address contractAddress, address recipientOfGas, uint256 minClaimRateBips) external returns (uint256); function claimMaxGas(address contractAddress, address recipientOfGas) external returns (uint256); function claimGas( address contractAddress, address recipientOfGas, uint256 gasToClaim, uint256 gasSecondsToConsume ) external returns (uint256); // read functions function readClaimableYield(address contractAddress) external view returns (uint256); function readYieldConfiguration(address contractAddress) external view returns (uint8); function readGasParams( address contractAddress ) external view returns (uint256 etherSeconds, uint256 etherBalance, uint256 lastUpdated, GasMode); } interface IERC20Rebasing { function getConfiguration(address account) external view returns (YieldMode); // changes the yield mode of the caller and update the balance // to reflect the configuration function configure(YieldMode) external returns (uint256); // "claimable" yield mode accounts can call this this claim their yield // to another address function claim(address recipient, uint256 amount) external returns (uint256); // read the claimable amount for an account function getClaimableAmount(address account) external view returns (uint256); } interface IBlastPoints { function configurePointsOperator(address operator) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// /// @dev Note: /// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection. /// - For ERC20s, this implementation won't check that a token has code, /// responsibility is delegated to the caller. library SafeTransferLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ETH transfer has failed. error ETHTransferFailed(); /// @dev The ERC20 `transferFrom` has failed. error TransferFromFailed(); /// @dev The ERC20 `transfer` has failed. error TransferFailed(); /// @dev The ERC20 `approve` has failed. error ApproveFailed(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes. uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300; /// @dev Suggested gas stipend for contract receiving ETH to perform a few /// storage reads and writes, but low enough to prevent griefing. uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ETH OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants. // // The regular variants: // - Forwards all remaining gas to the target. // - Reverts if the target reverts. // - Reverts if the current contract has insufficient balance. // // The force variants: // - Forwards with an optional gas stipend // (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases). // - If the target reverts, or if the gas stipend is exhausted, // creates a temporary contract to force send the ETH via `SELFDESTRUCT`. // Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758. // - Reverts if the current contract has insufficient balance. // // The try variants: // - Forwards with a mandatory gas stipend. // - Instead of reverting, returns whether the transfer succeeded. /// @dev Sends `amount` (in wei) ETH to `to`. function safeTransferETH(address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } } } /// @dev Sends all the ETH in the current contract to `to`. function safeTransferAllETH(address to) internal { /// @solidity memory-safe-assembly assembly { // Transfer all the ETH and check if it succeeded or not. if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`. function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal { /// @solidity memory-safe-assembly assembly { if lt(selfbalance(), amount) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`. function forceSafeTransferAllETH(address to, uint256 gasStipend) internal { /// @solidity memory-safe-assembly assembly { if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`. function forceSafeTransferETH(address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { if lt(selfbalance(), amount) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`. function forceSafeTransferAllETH(address to) internal { /// @solidity memory-safe-assembly assembly { // forgefmt: disable-next-item if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`. function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00) } } /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`. function trySafeTransferAllETH(address to, uint256 gasStipend) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Sends `amount` of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have at least `amount` approved for /// the current contract to manage. function safeTransferFrom(address token, address from, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x60, amount) // Store the `amount` argument. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends all of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have their entire balance approved for /// the current contract to manage. function safeTransferAllFrom(address token, address from, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`. // Read the balance, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`. amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransfer(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Sends all of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransferAll(address token, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`. mstore(0x20, address()) // Store the address of the current contract. // Read the balance, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20) ) ) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } mstore(0x14, to) // Store the `to` argument. amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it. mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. /// Reverts upon failure. function safeApprove(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. // Perform the approval, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`. revert(0x1c, 0x04) } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. /// If the initial attempt to approve fails, attempts to reset the approved amount to zero, /// then retries the approval again (some tokens, e.g. USDT, requires this). /// Reverts upon failure. function safeApproveWithRetry(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. // Perform the approval, retrying upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x34, 0) // Store 0 for the `amount`. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval. mstore(0x34, amount) // Store back the original `amount`. // Retry the approval, reverting upon failure. if iszero( and( or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`. revert(0x1c, 0x04) } } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Returns the amount of ERC20 `token` owned by `account`. /// Returns zero if the `token` does not exist. function balanceOf(address token, address account) internal view returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x14, account) // Store the `account` argument. mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`. amount := mul( mload(0x20), and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20) ) ) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol) pragma solidity ^0.8.0; import "../token/ERC20/IERC20.sol";
/* Copyright 2020 DODO ZOO. SPDX-License-Identifier: Apache-2.0 */ pragma solidity >=0.8.0; import {DecimalMath} from "/mimswap/libraries/DecimalMath.sol"; /** * @author Adapted from https://github.com/DODOEX/contractV2/blob/main/contracts/lib/Math.sol * @notice Functions for complex calculating. Including ONE Integration and TWO Quadratic solutions */ library Math { error ErrIsZero(); function divCeil(uint256 a, uint256 b) internal pure returns (uint256) { uint256 quotient = a / b; uint256 remainder = a - quotient * b; if (remainder > 0) { return quotient + 1; } else { return quotient; } } // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) // from UniswapV2 https://github.com/Uniswap/v2-core/blob/master/contracts/libraries/Math.sol function sqrt(uint y) internal pure returns (uint z) { if (y > 3) { z = y; uint x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } } /* Integrate dodo curve from V1 to V2 require V0>=V1>=V2>0 res = (1-k)i(V1-V2)+ikV0*V0(1/V2-1/V1) let V1-V2=delta res = i*delta*(1-k+k(V0^2/V1/V2)) i is the price of V-res trading pair support k=1 & k=0 case [round down] */ function _GeneralIntegrate(uint256 V0, uint256 V1, uint256 V2, uint256 i, uint256 k) internal pure returns (uint256) { if (V0 == 0) { revert ErrIsZero(); } uint256 fairAmount = i * (V1 - V2); // i*delta if (k == 0) { return fairAmount / DecimalMath.ONE; } uint256 V0V0V1V2 = DecimalMath.divFloor((V0 * V0) / V1, V2); uint256 penalty = DecimalMath.mulFloor(k, V0V0V1V2); // k(V0^2/V1/V2) return (((DecimalMath.ONE - k) + penalty) * fairAmount) / DecimalMath.ONE2; } /* Follow the integration function above i*deltaB = (Q2-Q1)*(1-k+kQ0^2/Q1/Q2) Assume Q2=Q0, Given Q1 and deltaB, solve Q0 i is the price of delta-V trading pair give out target of V support k=1 & k=0 case [round down] */ function _SolveQuadraticFunctionForTarget(uint256 V1, uint256 delta, uint256 i, uint256 k) internal pure returns (uint256) { if (k == 0) { return V1 + DecimalMath.mulFloor(i, delta); } // V0 = V1*(1+(sqrt-1)/2k) // sqrt = √(1+4kidelta/V1) // premium = 1+(sqrt-1)/2k // uint256 sqrt = (4 * k).mul(i).mul(delta).div(V1).add(DecimalMath.ONE2).sqrt(); if (V1 == 0) { return 0; } uint256 _sqrt; uint256 ki = (4 * k) * i; if (ki == 0) { _sqrt = DecimalMath.ONE; } else if ((ki * delta) / ki == delta) { _sqrt = sqrt(((ki * delta) / V1) + DecimalMath.ONE2); } else { _sqrt = sqrt(((ki / V1) * delta) + DecimalMath.ONE2); } uint256 premium = DecimalMath.divFloor(_sqrt - DecimalMath.ONE, k * 2) + DecimalMath.ONE; // V0 is greater than or equal to V1 according to the solution return DecimalMath.mulFloor(V1, premium); } /* Follow the integration expression above, we have: i*deltaB = (Q2-Q1)*(1-k+kQ0^2/Q1/Q2) Given Q1 and deltaB, solve Q2 This is a quadratic function and the standard version is aQ2^2 + bQ2 + c = 0, where a=1-k -b=(1-k)Q1-kQ0^2/Q1+i*deltaB c=-kQ0^2 and Q2=(-b+sqrt(b^2+4(1-k)kQ0^2))/2(1-k) note: another root is negative, abondan if deltaBSig=true, then Q2>Q1, user sell Q and receive B if deltaBSig=false, then Q2<Q1, user sell B and receive Q return |Q1-Q2| as we only support sell amount as delta, the deltaB is always negative the input ideltaB is actually -ideltaB in the equation i is the price of delta-V trading pair support k=1 & k=0 case [round down] */ function _SolveQuadraticFunctionForTrade(uint256 V0, uint256 V1, uint256 delta, uint256 i, uint256 k) internal pure returns (uint256) { if (V0 == 0) { revert ErrIsZero(); } if (delta == 0) { return 0; } if (k == 0) { return DecimalMath.mulFloor(i, delta) > V1 ? V1 : DecimalMath.mulFloor(i, delta); } if (k == DecimalMath.ONE) { // if k==1 // Q2=Q1/(1+ideltaBQ1/Q0/Q0) // temp = ideltaBQ1/Q0/Q0 // Q2 = Q1/(1+temp) // Q1-Q2 = Q1*(1-1/(1+temp)) = Q1*(temp/(1+temp)) // uint256 temp = i.mul(delta).mul(V1).div(V0.mul(V0)); uint256 temp; uint256 idelta = i * delta; if (idelta == 0) { temp = 0; } else if ((idelta * V1) / idelta == V1) { temp = (idelta * V1) / (V0 * V0); } else { temp = (((delta * V1) / V0) * i) / V0; } return (V1 * temp) / (temp + DecimalMath.ONE); } // calculate -b value and sig // b = kQ0^2/Q1-i*deltaB-(1-k)Q1 // part1 = (1-k)Q1 >=0 // part2 = kQ0^2/Q1-i*deltaB >=0 // bAbs = abs(part1-part2) // if part1>part2 => b is negative => bSig is false // if part2>part1 => b is positive => bSig is true uint256 part2 = (((k * V0) / V1) * V0) + (i * delta); // kQ0^2/Q1-i*deltaB uint256 bAbs = (DecimalMath.ONE - k) * V1; // (1-k)Q1 bool bSig; if (bAbs >= part2) { bAbs = bAbs - part2; bSig = false; } else { bAbs = part2 - bAbs; bSig = true; } bAbs = bAbs / DecimalMath.ONE; // calculate sqrt uint256 squareRoot = DecimalMath.mulFloor((DecimalMath.ONE - k) * 4, DecimalMath.mulFloor(k, V0) * V0); // 4(1-k)kQ0^2 squareRoot = sqrt((bAbs * bAbs) + squareRoot); // sqrt(b*b+4(1-k)kQ0*Q0) // final res uint256 denominator = (DecimalMath.ONE - k) * 2; // 2(1-k) uint256 numerator; if (bSig) { numerator = squareRoot - bAbs; if (numerator == 0) { revert ErrIsZero(); } } else { numerator = bAbs + squareRoot; } uint256 V2 = DecimalMath.divCeil(numerator, denominator); if (V2 > V1) { return 0; } else { return V1 - V2; } } }
/* Copyright 2020 DODO ZOO. SPDX-License-Identifier: Apache-2.0 */ pragma solidity >=0.8.0; import {Math} from "/mimswap/libraries/Math.sol"; /** * @title DecimalMath * @author DODO Breeder * * @notice Functions for fixed point number with 18 decimals */ library DecimalMath { using Math for uint256; uint256 internal constant ONE = 10 ** 18; uint256 internal constant ONE2 = 10 ** 36; function mulFloor(uint256 target, uint256 d) internal pure returns (uint256) { return (target * d) / ONE; } function mulCeil(uint256 target, uint256 d) internal pure returns (uint256) { return (target * d).divCeil(ONE); } function divFloor(uint256 target, uint256 d) internal pure returns (uint256) { return (target * ONE) / d; } function divCeil(uint256 target, uint256 d) internal pure returns (uint256) { return (target * ONE).divCeil(d); } function reciprocalFloor(uint256 target) internal pure returns (uint256) { return ONE2 / target; } function reciprocalCeil(uint256 target) internal pure returns (uint256) { return ONE2.divCeil(target); } function powFloor(uint256 target, uint256 e) internal pure returns (uint256) { if (e == 0) { return 10 ** 18; } else if (e == 1) { return target; } else { uint p = powFloor(target, e / 2); p = (p * p) / ONE; if (e % 2 == 1) { p = (p * target) / ONE; } return p; } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.0; interface IMagicLP { function _BASE_TOKEN_() external view returns (address); function _QUOTE_TOKEN_() external view returns (address); function _BASE_RESERVE_() external view returns (uint112); function _QUOTE_RESERVE_() external view returns (uint112); function _BASE_TARGET_() external view returns (uint112); function _QUOTE_TARGET_() external view returns (uint112); function _I_() external view returns (uint256); function getReserves() external view returns (uint256 baseReserve, uint256 quoteReserve); function totalSupply() external view returns (uint256 totalSupply); function init( address baseTokenAddress, address quoteTokenAddress, uint256 lpFeeRate, address mtFeeRateModel, uint256 i, uint256 k, bool protocolOwnedPool ) external; function sellBase(address to) external returns (uint256 receiveQuoteAmount); function sellQuote(address to) external returns (uint256 receiveBaseAmount); function flashLoan(uint256 baseAmount, uint256 quoteAmount, address assetTo, bytes calldata data) external; function buyShares(address to) external returns (uint256 shares, uint256 baseInput, uint256 quoteInput); function sellShares( uint256 shareAmount, address to, uint256 baseMinAmount, uint256 quoteMinAmount, bytes calldata data, uint256 deadline ) external returns (uint256 baseAmount, uint256 quoteAmount); function MIN_LP_FEE_RATE() external view returns (uint256); function MAX_LP_FEE_RATE() external view returns (uint256); function _PAUSED_() external view returns (bool); function setPaused(bool paused) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../token/ERC20/extensions/IERC20Metadata.sol";
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Reentrancy guard mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ReentrancyGuard.sol) abstract contract ReentrancyGuard { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Unauthorized reentrant call. error Reentrancy(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Equivalent to: `uint72(bytes9(keccak256("_REENTRANCY_GUARD_SLOT")))`. /// 9 bytes is large enough to avoid collisions with lower slots, /// but not too large to result in excessive bytecode bloat. uint256 private constant _REENTRANCY_GUARD_SLOT = 0x929eee149b4bd21268; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* REENTRANCY GUARD */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Guards a function from reentrancy. modifier nonReentrant() virtual { /// @solidity memory-safe-assembly assembly { if eq(sload(_REENTRANCY_GUARD_SLOT), address()) { mstore(0x00, 0xab143c06) // `Reentrancy()`. revert(0x1c, 0x04) } sstore(_REENTRANCY_GUARD_SLOT, address()) } _; /// @solidity memory-safe-assembly assembly { sstore(_REENTRANCY_GUARD_SLOT, codesize()) } } /// @dev Guards a view function from read-only reentrancy. modifier nonReadReentrant() virtual { /// @solidity memory-safe-assembly assembly { if eq(sload(_REENTRANCY_GUARD_SLOT), address()) { mstore(0x00, 0xab143c06) // `Reentrancy()`. revert(0x1c, 0x04) } } _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IERC20 { // transfer and tranferFrom have been removed, because they don't work on all tokens (some aren't ERC20 complaint). // By removing them you can't accidentally use them. // name, symbol and decimals have been removed, because they are optional and sometimes wrongly implemented (MKR). // Use BoringERC20 with `using BoringERC20 for IERC20` and call `safeTransfer`, `safeTransferFrom`, etc instead. function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); /// @notice EIP 2612 function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; } interface IStrictERC20 { // This is the strict ERC20 interface. Don't use this, certainly not if you don't control the ERC20 token you're calling. function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function totalSupply() external view returns (uint256); function balanceOf(address _owner) external view returns (uint256 balance); function transfer(address _to, uint256 _value) external returns (bool success); function transferFrom(address _from, address _to, uint256 _value) external returns (bool success); function approve(address _spender, uint256 _value) external returns (bool success); function allowance(address _owner, address _spender) external view returns (uint256 remaining); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); /// @notice EIP 2612 function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ 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 amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` 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 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ 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); }
{ "remappings": [ "/=src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/", "BoringSolidity/=lib/BoringSolidity/contracts/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "solmate/=lib/solmate/src/", "utils/=utils/", "libraries/=src/libraries/", "interfaces/=src/interfaces/", "cauldrons/=src/cauldrons/", "staking/=src/staking/", "swappers/=src/swappers/", "oracles/=src/oracles/", "strategies/=src/strategies/", "tokens/=src/tokens/", "periphery/=src/periphery/", "mixins/=src/mixins/", "lenses/=src/lenses/", "surl/=lib/surl/src/", "solady/=lib/solady/src/", "forge-deploy/=lib/forge-deploy/contracts/", "ExcessivelySafeCall/=lib/ExcessivelySafeCall/src/", "safe-contracts/=lib/safe-contracts/contracts/", "fuzzlib/=lib/fuzzlib/src/" ], "optimizer": { "enabled": true, "runs": 400 }, "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 IWETH","name":"weth_","type":"address"},{"internalType":"contract IFactory","name":"factory","type":"address"},{"internalType":"address","name":"governor_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ErrBadPath","type":"error"},{"inputs":[],"name":"ErrDecimalsDifferenceTooLarge","type":"error"},{"inputs":[],"name":"ErrEmptyPath","type":"error"},{"inputs":[],"name":"ErrExpired","type":"error"},{"inputs":[],"name":"ErrInTokenNotETH","type":"error"},{"inputs":[],"name":"ErrInvalidBaseToken","type":"error"},{"inputs":[],"name":"ErrInvalidQuoteTarget","type":"error"},{"inputs":[],"name":"ErrInvalidQuoteToken","type":"error"},{"inputs":[],"name":"ErrNotETHLP","type":"error"},{"inputs":[],"name":"ErrOutTokenNotETH","type":"error"},{"inputs":[],"name":"ErrPathTooLong","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"ErrTooHighSlippage","type":"error"},{"inputs":[],"name":"ErrTooLargeDecimals","type":"error"},{"inputs":[],"name":"ErrUnknownPool","type":"error"},{"inputs":[],"name":"ErrZeroAddress","type":"error"},{"inputs":[],"name":"ErrZeroDecimals","type":"error"},{"inputs":[],"name":"Reentrancy","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"}],"name":"LogBlastNativeClaimableEnabled","type":"event"},{"inputs":[],"name":"MAX_BASE_QUOTE_DECIMALS_DIFFERENCE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"baseInAmount","type":"uint256"},{"internalType":"uint256","name":"quoteInAmount","type":"uint256"},{"internalType":"uint256","name":"minimumShares","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"baseAdjustedInAmount","type":"uint256"},{"internalType":"uint256","name":"quoteAdjustedInAmount","type":"uint256"},{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address payable","name":"refundTo","type":"address"},{"internalType":"uint256","name":"tokenInAmount","type":"uint256"},{"internalType":"uint256","name":"minimumShares","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"baseAdjustedInAmount","type":"uint256"},{"internalType":"uint256","name":"quoteAdjustedInAmount","type":"uint256"},{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenInAmount","type":"uint256"},{"internalType":"uint256","name":"minimumShares","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETHUnsafe","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"baseInAmount","type":"uint256"},{"internalType":"uint256","name":"quoteInAmount","type":"uint256"},{"internalType":"bool","name":"remainingAmountToSwapIsBase","type":"bool"},{"internalType":"uint256","name":"remainingAmountToSwap","type":"uint256"},{"internalType":"uint256","name":"minimumShares","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct AddLiquidityImbalancedParams","name":"params","type":"tuple"}],"name":"addLiquidityImbalanced","outputs":[{"internalType":"uint256","name":"baseAdjustedInAmount","type":"uint256"},{"internalType":"uint256","name":"quoteAdjustedInAmount","type":"uint256"},{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"inAmountIsBase","type":"bool"},{"internalType":"uint256","name":"inAmount","type":"uint256"},{"internalType":"uint256","name":"inAmountToSwap","type":"uint256"},{"internalType":"uint256","name":"minimumShares","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityOneSide","outputs":[{"internalType":"uint256","name":"baseAmount","type":"uint256"},{"internalType":"uint256","name":"quoteAmount","type":"uint256"},{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"baseInAmount","type":"uint256"},{"internalType":"uint256","name":"quoteInAmount","type":"uint256"},{"internalType":"uint256","name":"minimumShares","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityUnsafe","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"address","name":"quoteToken","type":"address"},{"internalType":"uint256","name":"lpFeeRate","type":"uint256"},{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"k","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"baseInAmount","type":"uint256"},{"internalType":"uint256","name":"quoteInAmount","type":"uint256"},{"internalType":"bool","name":"protocolOwnedPool","type":"bool"}],"name":"createPool","outputs":[{"internalType":"address","name":"clone","type":"address"},{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"useTokenAsQuote","type":"bool"},{"internalType":"uint256","name":"lpFeeRate","type":"uint256"},{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"k","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenInAmount","type":"uint256"},{"internalType":"bool","name":"protocolOwnedPool","type":"bool"}],"name":"createPoolETH","outputs":[{"internalType":"address","name":"clone","type":"address"},{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract IFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"baseInAmount","type":"uint256"},{"internalType":"uint256","name":"quoteInAmount","type":"uint256"}],"name":"previewCreatePool","outputs":[{"internalType":"uint256","name":"baseAdjustedInAmount","type":"uint256"},{"internalType":"uint256","name":"quoteAdjustedInAmount","type":"uint256"},{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"uint256","name":"sharesIn","type":"uint256"}],"name":"previewRemoveLiquidity","outputs":[{"internalType":"uint256","name":"baseAmountOut","type":"uint256"},{"internalType":"uint256","name":"quoteAmountOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"sharesIn","type":"uint256"},{"internalType":"uint256","name":"minimumBaseAmount","type":"uint256"},{"internalType":"uint256","name":"minimumQuoteAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"baseAmountOut","type":"uint256"},{"internalType":"uint256","name":"quoteAmountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"sharesIn","type":"uint256"},{"internalType":"uint256","name":"minimumETHAmount","type":"uint256"},{"internalType":"uint256","name":"minimumTokenAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[{"internalType":"uint256","name":"ethAmountOut","type":"uint256"},{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"withdrawBase","type":"bool"},{"internalType":"uint256","name":"sharesIn","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityOneSide","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"minimumOut","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"sellBaseETHForTokens","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"minimumOut","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"sellBaseTokensForETH","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"minimumOut","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"sellBaseTokensForTokens","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"minimumOut","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"sellQuoteETHForTokens","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"minimumOut","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"sellQuoteTokensForETH","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"lp","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"minimumOut","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"sellQuoteTokensForTokens","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint256","name":"directions","type":"uint256"},{"internalType":"uint256","name":"minimumOut","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForTokens","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint256","name":"directions","type":"uint256"},{"internalType":"uint256","name":"minimumOut","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForETH","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint256","name":"directions","type":"uint256"},{"internalType":"uint256","name":"minimumOut","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForTokens","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60c06040523480156200001157600080fd5b5060405162004df538038062004df5833981016040819052620000349162000174565b82826001600160a01b03821615806200005457506001600160a01b038116155b156200007357604051630ecc6fdf60e41b815260040160405180910390fd5b6001600160a01b03918216608052811660a0528116620000a657604051630ecc6fdf60e41b815260040160405180910390fd5b620000b181620000ba565b5050506200022a565b60405163c8992e6160e01b81527343000000000000000000000000000000000000029063c8992e6190620000f9906002906001908690600401620001de565b600060405180830381600087803b1580156200011457600080fd5b505af115801562000129573d6000803e3d6000fd5b50506040513092507fd519de07dfc6a474caab5e77d5829a6ca71ad6a4aafc5cc253bafe0f0c772bf59150600090a250565b6001600160a01b03811681146200017157600080fd5b50565b6000806000606084860312156200018a57600080fd5b835162000197816200015b565b6020850151909350620001aa816200015b565b6040850151909250620001bd816200015b565b809150509250925092565b634e487b7160e01b600052602160045260246000fd5b6060810160038510620001f557620001f5620001c8565b848252600284106200020b576200020b620001c8565b60208201939093526001600160a01b0391909116604090910152919050565b60805160a051614a6a6200038b600039600081816104470152818161056601528181610ac701528181610d60015281816110a7015281816112070152818161138c015281816115b401528181611718015281816118a101528181611a7001528181611c9d0152818161207501528181612606015281816129a601528181612e1001528181612f2e0152818161317801528181613637015261403e0152600081816102e001528181610b0101528181610b2801528181610be001528181610c7601528181610dec01528181610f3a0152818161147e015281816114d00152818161192d0152818161216701528181612209015281816122bc0152818161233a015281816124c90152818161251b01528181612c0901528181612d4301528181613020015281816130720152818161326d01528181613325015281816133f30152818161346c0152818161373e0152818161387901526139bf0152614a6a6000f3fe60806040526004361061019a5760003560e01c80636525e5f1116100e1578063c45a01551161008a578063e3f88c0b11610064578063e3f88c0b146104a9578063f2ef5d5e146104bc578063f54d44cf146104cf578063f57829a0146104ef57600080fd5b8063c45a015514610435578063cb83172f14610469578063de3d7b7f1461048957600080fd5b80638454c89b116100bb5780638454c89b146103e2578063906205f1146103f55780639e9d406e1461041557600080fd5b80636525e5f11461038f578063807bd736146103af5780638095deca146103cf57600080fd5b806338a1134611610143578063442f60ec1161011d578063442f60ec1461031a57806344483d531461033a578063579a3ac21461036f57600080fd5b806338a113461461029b5780633f46376e146102ae5780633fc8cef3146102ce57600080fd5b80632f6419f9116101745780632f6419f9146102465780633351733f14610266578063337164b31461028657600080fd5b8063011266c3146101a65780630e8cdaba146101e65780631a8e9be91461021857600080fd5b366101a157005b600080fd5b3480156101b257600080fd5b506101c66101c13660046143aa565b61050f565b604080519384526020840192909252908201526060015b60405180910390f35b6101f96101f43660046143e9565b6109df565b604080516001600160a01b0390931683526020830191909152016101dd565b34801561022457600080fd5b5061023861023336600461446e565b610d1b565b6040519081526020016101dd565b34801561025257600080fd5b506101f96102613660046144bf565b610fbd565b34801561027257600080fd5b506101c661028136600461454e565b6111bf565b34801561029257600080fd5b50610238600c81565b6102386102a93660046145a7565b611347565b3480156102ba57600080fd5b506102386102c936600461446e565b61156f565b3480156102da57600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101dd565b34801561032657600080fd5b506101c66103353660046145ed565b61168d565b34801561034657600080fd5b5061035a61035536600461454e565b6116f2565b604080519283526020830191909152016101dd565b34801561037b57600080fd5b5061023861038a36600461446e565b61185c565b34801561039b57600080fd5b5061035a6103aa366004614619565b611a2d565b3480156103bb57600080fd5b506102386103ca366004614645565b611c58565b6102386103dd36600461446e565b612030565b6102386103f03660046146f6565b612392565b34801561040157600080fd5b506101c6610410366004614765565b6125be565b34801561042157600080fd5b5061023861043036600461454e565b612961565b34801561044157600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561047557600080fd5b506102386104843660046147d3565b612ac3565b34801561049557600080fd5b506102386104a436600461446e565b612dcb565b6102386104b73660046145a7565b612ee9565b6101c66104ca36600461484a565b613105565b3480156104db57600080fd5b506102386104ea3660046147d3565b613512565b3480156104fb57600080fd5b5061035a61050a36600461454e565b613611565b60008060008360e001358042111561053a57604051630992d5df60e41b815260040160405180910390fd5b610547602086018661488e565b604051631e1c6a0760e01b81526001600160a01b0382811660048301527f00000000000000000000000000000000000000000000000000000000000000001690631e1c6a0790602401602060405180830381865afa1580156105ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d191906148ab565b6105ee576040516392c46cf760e01b815260040160405180910390fd5b60006105fd602088018861488e565b6001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561063a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065e91906148c8565b9050600061066f602089018961488e565b6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d091906148c8565b90506106eb6001600160a01b038316333060408c0135613a58565b6107046001600160a01b038216333060608c0135613a58565b61072361071460208a018a61488e565b89604001358a60600135613ab5565b909750955061073860a0890160808a016148e5565b156108155761076261074d60208a018a61488e565b6001600160a01b0384169060a08b0135613c93565b60a08801356107758860408b0135614918565b61077f9190614918565b610789908861492b565b9650610798602089018961488e565b604051632f58056d60e21b81523060048201526001600160a01b03919091169063bd6015b4906024016020604051808303816000875af11580156107e0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610804919061493e565b61080e908761492b565b95506108e9565b61083a61082560208a018a61488e565b6001600160a01b0383169060a08b0135613c93565b610847602089018961488e565b604051636ec9facd60e11b81523060048201526001600160a01b03919091169063dd93f59a906024016020604051808303816000875af115801561088f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b3919061493e565b6108bd908861492b565b965060a08801356108d28760608b0135614918565b6108dc9190614918565b6108e6908761492b565b95505b6109006108f960208a018a61488e565b8888613ab5565b909750955061092661091560208a018a61488e565b6001600160a01b0384169089613c93565b61094761093660208a018a61488e565b6001600160a01b0383169088613c93565b61097161095760208a018a61488e565b61096760408b0160208c0161488e565b8a60c00135613ce2565b945060006109886001600160a01b03841630613d82565b905080156109a4576109a46001600160a01b0384163383613c93565b6109b76001600160a01b03831630613d82565b905080156109d3576109d36001600160a01b0383163383613c93565b50505050509193909250565b6000808815610a5957610a5460128b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a4f9190614957565b613db7565b610ac5565b610ac58a6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610abe9190614957565b6012613db7565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636a132ea68a610aff578b610b21565b7f00000000000000000000000000000000000000000000000000000000000000005b8b610b4c577f0000000000000000000000000000000000000000000000000000000000000000610b4e565b8c5b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604481018b9052606481018a90526084810189905285151560a482015260c4016020604051808303816000875af1158015610bb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bdc91906148c8565b91507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610c3957600080fd5b505af1158015610c4d573d6000803e3d6000fd5b50610c69935050506001600160a01b038c169050338487613a58565b610c9d6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168334613c93565b604051634c85b42560e01b81526001600160a01b038681166004830152831690634c85b425906024016060604051808303816000875af1158015610ce5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d09919061497a565b50929b909a5098505050505050505050565b60008180421115610d3f57604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808916600483015288917f000000000000000000000000000000000000000000000000000000000000000090911690631e1c6a0790602401602060405180830381865afa158015610da9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dcd91906148ab565b610dea576040516392c46cf760e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316886001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7691906148c8565b6001600160a01b031614610e9d57604051632be739cb60e21b815260040160405180910390fd5b610f163389888b6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0591906148c8565b6001600160a01b0316929190613a58565b610f21883087613e6d565b604051632e1a7d4d60e01b8152600481018290529093507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015610f8657600080fd5b505af1158015610f9a573d6000803e3d6000fd5b50610fb2925050506001600160a01b03881684613f04565b505095945050505050565b6000806110638b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611001573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110259190614957565b8b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a2b573d6000803e3d6000fd5b604051633509975360e11b81526001600160a01b038c811660048301528b81166024830152604482018b9052606482018a90526084820189905284151560a48301527f00000000000000000000000000000000000000000000000000000000000000001690636a132ea69060c4016020604051808303816000875af11580156110f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111491906148c8565b915061112b6001600160a01b038c16338488613a58565b6111406001600160a01b038b16338487613a58565b604051634c85b42560e01b81526001600160a01b038781166004830152831690634c85b425906024016060604051808303816000875af1158015611188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ac919061497a565b50929c909b509950505050505050505050565b600080600083804211156111e657604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808c1660048301528b917f000000000000000000000000000000000000000000000000000000000000000090911690631e1c6a0790602401602060405180830381865afa158015611250573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127491906148ab565b611291576040516392c46cf760e01b815260040160405180910390fd5b61129c8b8a8a613ab5565b80955081965050506112e8338c878e6001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b61132c338c868e6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b6113378b8b89613ce2565b9250505096509650969350505050565b6000818042111561136b57604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808816600483015287917f000000000000000000000000000000000000000000000000000000000000000090911690631e1c6a0790602401602060405180830381865afa1580156113d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f991906148ab565b611416576040516392c46cf760e01b815260040160405180910390fd5b6000876001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611456573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147a91906148c8565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316146114ce57604051632be739cb60e21b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561152957600080fd5b505af115801561153d573d6000803e3d6000fd5b50611558935050506001600160a01b03831690508934613c93565b611563888888613f24565b98975050505050505050565b6000818042111561159357604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808916600483015288917f000000000000000000000000000000000000000000000000000000000000000090911690631e1c6a0790602401602060405180830381865afa1580156115fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162191906148ab565b61163e576040516392c46cf760e01b815260040160405180910390fd5b6116823389888b6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b611563888887613e6d565b600080600061169c8587613f56565b84106116a857846116b2565b6116b28487613f7e565b90508092506116c18187613f56565b91506107d181116116da575060009150819050806116e9565b6116e66103e982614918565b90505b93509350939050565b604051631e1c6a0760e01b81526001600160a01b038781166004830152600091829189917f000000000000000000000000000000000000000000000000000000000000000090911690631e1c6a0790602401602060405180830381865afa158015611761573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061178591906148ab565b6117a2576040516392c46cf760e01b815260040160405180910390fd5b6117b76001600160a01b038a1633308a613a58565b604051635ab6755360e11b8152600481018890526001600160a01b038981166024830152604482018890526064820187905260c06084830152600060c483015260a482018690528a169063b56ceaa69060e40160408051808303816000875af1158015611828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061184c91906149a8565b9250925050965096945050505050565b6000818042111561188057604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808916600483015288917f000000000000000000000000000000000000000000000000000000000000000090911690631e1c6a0790602401602060405180830381865afa1580156118ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190e91906148ab565b61192b576040516392c46cf760e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316886001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015611993573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b791906148c8565b6001600160a01b0316146119de5760405163807af6e560e01b815260040160405180910390fd5b611a223389888b6001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b610f21883087613f24565b6000803068929eee149b4bd212685403611a4f5763ab143c066000526004601cfd5b604051631e1c6a0760e01b81526001600160a01b03808616600483015285917f000000000000000000000000000000000000000000000000000000000000000090911690631e1c6a0790602401602060405180830381865afa158015611ab9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611add91906148ab565b611afa576040516392c46cf760e01b815260040160405180910390fd5b6000611b7186876001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6291906148c8565b6001600160a01b031690613d82565b90506000611bb787886001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b3e573d6000803e3d6000fd5b90506000876001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bf9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1d919061493e565b905080611c2a88856149cc565b611c3491906149e3565b955080611c4188846149cc565b611c4b91906149e3565b9450505050509250929050565b60008180421115611c7c57604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808a16600483015289917f000000000000000000000000000000000000000000000000000000000000000090911690631e1c6a0790602401602060405180830381865afa158015611ce6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d0a91906148ab565b611d27576040516392c46cf760e01b815260040160405180910390fd5b6000896001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8b91906148c8565b905060008a6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015611dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df191906148c8565b9050611e086001600160a01b038c1633308b613a58565b604051635ab6755360e11b8152600481018990523060248201526000604482018190526064820181905260c0608483015260c4820181905260a482018890529081906001600160a01b038e169063b56ceaa69060e40160408051808303816000875af1158015611e7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea091906149a8565b915091508a15611f5357611ebe6001600160a01b0384168e83613c93565b604051636ec9facd60e11b81523060048201526001600160a01b038e169063dd93f59a906024016020604051808303816000875af1158015611f04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f28919061493e565b611f32908361492b565b96508615611f4e57611f4e6001600160a01b0385168d89613c93565b611ff7565b611f676001600160a01b0385168e84613c93565b604051632f58056d60e21b81523060048201526001600160a01b038e169063bd6015b4906024016020604051808303816000875af1158015611fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd1919061493e565b611fdb908261492b565b96508615611ff757611ff76001600160a01b0384168d89613c93565b8887101561202057604051632ff97dcd60e11b8152600481018890526024015b60405180910390fd5b5050505050509695505050505050565b6000818042111561205457604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808916600483015288917f000000000000000000000000000000000000000000000000000000000000000090911690631e1c6a0790602401602060405180830381865afa1580156120be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e291906148ab565b6120ff576040516392c46cf760e01b815260040160405180910390fd5b6000886001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561213f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061216391906148c8565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b03160361220757886001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061220091906148c8565b90506122ba565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561226f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061229391906148c8565b6001600160a01b0316146122ba57604051639700d1eb60e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561231557600080fd5b505af1158015612329573d6000803e3d6000fd5b506123659350506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691508b905034613c93565b61237a6001600160a01b038216338b8a613a58565b612385898988613ce2565b9998505050505050505050565b600081804211156123b657604051630992d5df60e41b815260040160405180910390fd5b6123c08787613f93565b6000878760008181106123d5576123d5614a05565b90506020020160208101906123ea919061488e565b905060008660011660000361246257816001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612437573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245b91906148c8565b90506124c7565b816001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156124a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124c491906148c8565b90505b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316146125195760405163b1e72b7960e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561257457600080fd5b505af1158015612588573d6000803e3d6000fd5b506125a3935050506001600160a01b03831690508334613c93565b6125b08a8a8a8a8a613fd8565b9a9950505050505050505050565b600080600083804211156125e557604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808d1660048301528c917f000000000000000000000000000000000000000000000000000000000000000090911690631e1c6a0790602401602060405180830381865afa15801561264f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061267391906148ab565b612690576040516392c46cf760e01b815260040160405180910390fd5b60008c6001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f491906148c8565b905060008d6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612736573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275a91906148c8565b90508b15612808576127776001600160a01b03831633308e613a58565b6127818a8c614918565b96506127976001600160a01b0383168f8c613c93565b604051632f58056d60e21b81523060048201526001600160a01b038f169063bd6015b4906024016020604051808303816000875af11580156127dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612801919061493e565b95506128aa565b61281d6001600160a01b03821633308e613a58565b6128278a8c614918565b955061283d6001600160a01b0382168f8c613c93565b604051636ec9facd60e11b81523060048201526001600160a01b038f169063dd93f59a906024016020604051808303816000875af1158015612883573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a7919061493e565b96505b6128b58e8888613ab5565b90975095506128ce6001600160a01b0383168f89613c93565b6128e26001600160a01b0382168f88613c93565b6128ed8e8e8b613ce2565b945060006129046001600160a01b03841630613d82565b90508015612920576129206001600160a01b0384163383613c93565b6129336001600160a01b03831630613d82565b9050801561294f5761294f6001600160a01b0383163383613c93565b50505050509750975097945050505050565b6000818042111561298557604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808a16600483015289917f000000000000000000000000000000000000000000000000000000000000000090911690631e1c6a0790602401602060405180830381865afa1580156129ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a1391906148ab565b612a30576040516392c46cf760e01b815260040160405180910390fd5b612a74338a898c6001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b612ab8338a888c6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b612385898987613ce2565b60008180421115612ae757604051630992d5df60e41b815260040160405180910390fd5b612af18787613f93565b6000612afe600188614918565b90506000888883818110612b1457612b14614a05565b9050602002016020810190612b29919061488e565b90506000600188841c168103612ba257816001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b9b91906148c8565b9050612c07565b816001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612be0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c0491906148c8565b90505b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b031614612c59576040516365ba5f2960e01b815260040160405180910390fd5b60008a8a6000818110612c6e57612c6e614a05565b9050602002016020810190612c83919061488e565b905088600116600003612cd957612cd433828e846001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b612d1d565b612d1d33828e846001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b612d2a308c8c8c8c613fd8565b604051632e1a7d4d60e01b8152600481018290529096507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015612d8f57600080fd5b505af1158015612da3573d6000803e3d6000fd5b50612dbb925050506001600160a01b038e1687613f04565b5050505050979650505050505050565b60008180421115612def57604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808916600483015288917f000000000000000000000000000000000000000000000000000000000000000090911690631e1c6a0790602401602060405180830381865afa158015612e59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e7d91906148ab565b612e9a576040516392c46cf760e01b815260040160405180910390fd5b612ede3389888b6001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b611563888887613f24565b60008180421115612f0d57604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808816600483015287917f000000000000000000000000000000000000000000000000000000000000000090911690631e1c6a0790602401602060405180830381865afa158015612f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9b91906148ab565b612fb8576040516392c46cf760e01b815260040160405180910390fd5b6000876001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ff8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061301c91906148c8565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316146130705760405163807af6e560e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156130cb57600080fd5b505af11580156130df573d6000803e3d6000fd5b506130fa935050506001600160a01b03831690508934613c93565b611563888888613e6d565b60008060003068929eee149b4bd2126854036131295763ab143c066000526004601cfd5b3068929eee149b4bd2126855838042111561315757604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808c1660048301528b917f000000000000000000000000000000000000000000000000000000000000000090911690631e1c6a0790602401602060405180830381865afa1580156131c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e591906148ab565b613202576040516392c46cf760e01b815260040160405180910390fd5b60008060008d6001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613245573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061326991906148c8565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b031603613323578d6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132e2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330691906148c8565b90506133138e348d613ab5565b90985096508792508691506133f1565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168e6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561338b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133af91906148c8565b6001600160a01b0316036133d8576133c88e8c34613ab5565b90985096508692508791506133f1565b604051639700d1eb60e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b15801561344c57600080fd5b505af1158015613460573d6000803e3d6000fd5b50505050506134a38e847f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316613c939092919063ffffffff16565b823411156134c8576134c86134b88434614918565b6001600160a01b038e1690613f04565b6134e8338f84846001600160a01b0316613a58909392919063ffffffff16565b6134f38e8e8c613ce2565b955050505050503868929eee149b4bd212685596509650969350505050565b6000818042111561353657604051630992d5df60e41b815260040160405180910390fd5b6135408787613f93565b60008787600081811061355557613555614a05565b905060200201602081019061356a919061488e565b9050856001166000036135c0576135bb33828b846001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b613604565b61360433828b846001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b6125b08a89898989613fd8565b604051631e1c6a0760e01b81526001600160a01b038781166004830152600091829189917f000000000000000000000000000000000000000000000000000000000000000090911690631e1c6a0790602401602060405180830381865afa158015613680573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136a491906148ab565b6136c1576040516392c46cf760e01b815260040160405180910390fd5b6136d66001600160a01b038a1633308a613a58565b6000896001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613716573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061373a91906148c8565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b03160361387757896001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137d791906148c8565b604051635ab6755360e11b8152600481018a9052306024820152604481018990526064810188905260c06084820152600060c482015260a481018790529091506001600160a01b038b169063b56ceaa69060e40160408051808303816000875af1158015613849573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061386d91906149a8565b90945092506139a9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168a6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061390391906148c8565b6001600160a01b0316036133d857604051635ab6755360e11b815260048101899052306024820152604481018790526064810188905260c06084820152600060c482015260a481018690526001600160a01b038b169063b56ceaa69060e40160408051808303816000875af1158015613980573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139a491906149a8565b945092505b604051632e1a7d4d60e01b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015613a0b57600080fd5b505af1158015613a1f573d6000803e3d6000fd5b50613a37925050506001600160a01b038a1685613f04565b613a4b6001600160a01b0382168a85613c93565b5050965096945050505050565b60405181606052826040528360601b602c526f23b872dd000000000000000000000000600c52602060006064601c6000895af13d156001600051141716613aa757637939f4246000526004601cfd5b600060605260405250505050565b600080846001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613af6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b1a919061493e565b600003613bc1576000856001600160a01b031663f811d6926040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b85919061493e565b90506000613b938683613f56565b8510613b9f5785613ba9565b613ba98583613f7e565b9050809350613bb88183613f56565b92505050613c8b565b600080866001600160a01b0316630902f1ac6040518163ffffffff1660e01b81526004016040805180830381865afa158015613c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c2591906149a8565b91509150600081118015613c395750600082115b15613c88576000613c4a8784613f7e565b90506000613c588784613f7e565b9050808211613c7557879550613c6e8383613f56565b9450613c85565b869450613c828482613f56565b95505b50505b50505b935093915050565b81601452806034526fa9059cbb00000000000000000000000060005260206000604460106000875af13d156001600051141716613cd8576390b8ec186000526004601cfd5b6000603452505050565b604051634c85b42560e01b81526001600160a01b03838116600483015260009190851690634c85b425906024016060604051808303816000875af1158015613d2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d52919061497a565b509091505081811015613d7b57604051632ff97dcd60e11b815260048101829052602401612017565b9392505050565b6000816014526f70a0823100000000000000000000000060005260208060246010865afa601f3d111660205102905092915050565b60ff82161580613dc8575060ff8116155b15613de65760405163ca1aefb560e01b815260040160405180910390fd5b60128260ff161180613dfb575060128160ff16115b15613e195760405163062d0f8560e51b815260040160405180910390fd5b60008160ff168360ff1611613e3757613e328383614a1b565b613e41565b613e418284614a1b565b60ff169050600c811115613e68576040516397088e6160e01b815260040160405180910390fd5b505050565b604051636ec9facd60e11b81526001600160a01b0383811660048301526000919085169063dd93f59a906024015b6020604051808303816000875af1158015613eba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ede919061493e565b905081811015613d7b57604051632ff97dcd60e11b815260048101829052602401612017565b60003860003884865af1613f205763b12d13eb6000526004601cfd5b5050565b604051632f58056d60e21b81526001600160a01b0383811660048301526000919085169063bd6015b490602401613e9b565b6000670de0b6b3a7640000613f6b83856149cc565b613f7591906149e3565b90505b92915050565b600081613f6b670de0b6b3a7640000856149cc565b80610100811115613fb7576040516315e8dba360e01b815260040160405180910390fd5b60008111613e68576040516376ede79b60e11b815260040160405180910390fd5b600080613fe6600186614918565b905060005b8181101561423c57600087878381811061400757614007614a05565b905060200201602081019061401c919061488e565b604051631e1c6a0760e01b81526001600160a01b0380831660048301529192507f000000000000000000000000000000000000000000000000000000000000000090911690631e1c6a0790602401602060405180830381865afa158015614087573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140ab91906148ab565b6140c8576040516392c46cf760e01b815260040160405180910390fd5b85600116600003614183576001600160a01b03811663bd6015b489896140ef86600161492b565b8181106140fe576140fe614a05565b9050602002016020810190614113919061488e565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201526024016020604051808303816000875af1158015614159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061417d919061493e565b5061422f565b6001600160a01b03811663dd93f59a898961419f86600161492b565b8181106141ae576141ae614a05565b90506020020160208101906141c3919061488e565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201526024016020604051808303816000875af1158015614209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061422d919061493e565b505b50600194851c9401613feb565b50836001166000036142e45785858281811061425a5761425a614a05565b905060200201602081019061426f919061488e565b604051632f58056d60e21b81526001600160a01b038981166004830152919091169063bd6015b4906024016020604051808303816000875af11580156142b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142dd919061493e565b915061437c565b8585828181106142f6576142f6614a05565b905060200201602081019061430b919061488e565b604051636ec9facd60e11b81526001600160a01b038981166004830152919091169063dd93f59a906024016020604051808303816000875af1158015614355573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614379919061493e565b91505b828210156143a057604051632ff97dcd60e11b815260048101839052602401612017565b5095945050505050565b600061010082840312156143bd57600080fd5b50919050565b6001600160a01b03811681146143d857600080fd5b50565b80151581146143d857600080fd5b600080600080600080600080610100898b03121561440657600080fd5b8835614411816143c3565b97506020890135614421816143db565b965060408901359550606089013594506080890135935060a0890135614446816143c3565b925060c0890135915060e089013561445d816143db565b809150509295985092959890939650565b600080600080600060a0868803121561448657600080fd5b8535614491816143c3565b945060208601356144a1816143c3565b94979496505050506040830135926060810135926080909101359150565b60008060008060008060008060006101208a8c0312156144de57600080fd5b89356144e9816143c3565b985060208a01356144f9816143c3565b975060408a0135965060608a0135955060808a0135945060a08a013561451e816143c3565b935060c08a0135925060e08a013591506101008a013561453d816143db565b809150509295985092959850929598565b60008060008060008060c0878903121561456757600080fd5b8635614572816143c3565b95506020870135614582816143c3565b95989597505050506040840135936060810135936080820135935060a0909101359150565b600080600080608085870312156145bd57600080fd5b84356145c8816143c3565b935060208501356145d8816143c3565b93969395505050506040820135916060013590565b60008060006060848603121561460257600080fd5b505081359360208301359350604090920135919050565b6000806040838503121561462c57600080fd5b8235614637816143c3565b946020939093013593505050565b60008060008060008060c0878903121561465e57600080fd5b8635614669816143c3565b95506020870135614679816143c3565b94506040870135614689816143db565b959894975094956060810135955060808101359460a0909101359350915050565b60008083601f8401126146bc57600080fd5b50813567ffffffffffffffff8111156146d457600080fd5b6020830191508360208260051b85010111156146ef57600080fd5b9250929050565b60008060008060008060a0878903121561470f57600080fd5b863561471a816143c3565b9550602087013567ffffffffffffffff81111561473657600080fd5b61474289828a016146aa565b979a90995096976040810135976060820135975060809091013595509350505050565b600080600080600080600060e0888a03121561478057600080fd5b873561478b816143c3565b9650602088013561479b816143c3565b955060408801356147ab816143db565b969995985095966060810135965060808101359560a0820135955060c0909101359350915050565b600080600080600080600060c0888a0312156147ee57600080fd5b87356147f9816143c3565b965060208801359550604088013567ffffffffffffffff81111561481c57600080fd5b6148288a828b016146aa565b989b979a50986060810135976080820135975060a09091013595509350505050565b60008060008060008060c0878903121561486357600080fd5b863561486e816143c3565b9550602087013561487e816143c3565b94506040870135614689816143c3565b6000602082840312156148a057600080fd5b8135613d7b816143c3565b6000602082840312156148bd57600080fd5b8151613d7b816143db565b6000602082840312156148da57600080fd5b8151613d7b816143c3565b6000602082840312156148f757600080fd5b8135613d7b816143db565b634e487b7160e01b600052601160045260246000fd5b81810381811115613f7857613f78614902565b80820180821115613f7857613f78614902565b60006020828403121561495057600080fd5b5051919050565b60006020828403121561496957600080fd5b815160ff81168114613d7b57600080fd5b60008060006060848603121561498f57600080fd5b8351925060208401519150604084015190509250925092565b600080604083850312156149bb57600080fd5b505080516020909101519092909150565b8082028115828204841417613f7857613f78614902565b600082614a0057634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b60ff8281168282160390811115613f7857613f7861490256fea264697066735822122045228d232f7c69682bdc5876b4908b5797bead31ed44859911d15aa1e5911a6664736f6c6343000814003300000000000000000000000043000000000000000000000000000000000000040000000000000000000000007e05363e225c1c8096b1cd233b59457104b84908000000000000000000000000d69e75c1c2a0f2838a6bba8bdff9d08c8f137cd9
Deployed Bytecode
0x60806040526004361061019a5760003560e01c80636525e5f1116100e1578063c45a01551161008a578063e3f88c0b11610064578063e3f88c0b146104a9578063f2ef5d5e146104bc578063f54d44cf146104cf578063f57829a0146104ef57600080fd5b8063c45a015514610435578063cb83172f14610469578063de3d7b7f1461048957600080fd5b80638454c89b116100bb5780638454c89b146103e2578063906205f1146103f55780639e9d406e1461041557600080fd5b80636525e5f11461038f578063807bd736146103af5780638095deca146103cf57600080fd5b806338a1134611610143578063442f60ec1161011d578063442f60ec1461031a57806344483d531461033a578063579a3ac21461036f57600080fd5b806338a113461461029b5780633f46376e146102ae5780633fc8cef3146102ce57600080fd5b80632f6419f9116101745780632f6419f9146102465780633351733f14610266578063337164b31461028657600080fd5b8063011266c3146101a65780630e8cdaba146101e65780631a8e9be91461021857600080fd5b366101a157005b600080fd5b3480156101b257600080fd5b506101c66101c13660046143aa565b61050f565b604080519384526020840192909252908201526060015b60405180910390f35b6101f96101f43660046143e9565b6109df565b604080516001600160a01b0390931683526020830191909152016101dd565b34801561022457600080fd5b5061023861023336600461446e565b610d1b565b6040519081526020016101dd565b34801561025257600080fd5b506101f96102613660046144bf565b610fbd565b34801561027257600080fd5b506101c661028136600461454e565b6111bf565b34801561029257600080fd5b50610238600c81565b6102386102a93660046145a7565b611347565b3480156102ba57600080fd5b506102386102c936600461446e565b61156f565b3480156102da57600080fd5b506103027f000000000000000000000000430000000000000000000000000000000000000481565b6040516001600160a01b0390911681526020016101dd565b34801561032657600080fd5b506101c66103353660046145ed565b61168d565b34801561034657600080fd5b5061035a61035536600461454e565b6116f2565b604080519283526020830191909152016101dd565b34801561037b57600080fd5b5061023861038a36600461446e565b61185c565b34801561039b57600080fd5b5061035a6103aa366004614619565b611a2d565b3480156103bb57600080fd5b506102386103ca366004614645565b611c58565b6102386103dd36600461446e565b612030565b6102386103f03660046146f6565b612392565b34801561040157600080fd5b506101c6610410366004614765565b6125be565b34801561042157600080fd5b5061023861043036600461454e565b612961565b34801561044157600080fd5b506103027f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b8490881565b34801561047557600080fd5b506102386104843660046147d3565b612ac3565b34801561049557600080fd5b506102386104a436600461446e565b612dcb565b6102386104b73660046145a7565b612ee9565b6101c66104ca36600461484a565b613105565b3480156104db57600080fd5b506102386104ea3660046147d3565b613512565b3480156104fb57600080fd5b5061035a61050a36600461454e565b613611565b60008060008360e001358042111561053a57604051630992d5df60e41b815260040160405180910390fd5b610547602086018661488e565b604051631e1c6a0760e01b81526001600160a01b0382811660048301527f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b849081690631e1c6a0790602401602060405180830381865afa1580156105ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d191906148ab565b6105ee576040516392c46cf760e01b815260040160405180910390fd5b60006105fd602088018861488e565b6001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561063a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065e91906148c8565b9050600061066f602089018961488e565b6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d091906148c8565b90506106eb6001600160a01b038316333060408c0135613a58565b6107046001600160a01b038216333060608c0135613a58565b61072361071460208a018a61488e565b89604001358a60600135613ab5565b909750955061073860a0890160808a016148e5565b156108155761076261074d60208a018a61488e565b6001600160a01b0384169060a08b0135613c93565b60a08801356107758860408b0135614918565b61077f9190614918565b610789908861492b565b9650610798602089018961488e565b604051632f58056d60e21b81523060048201526001600160a01b03919091169063bd6015b4906024016020604051808303816000875af11580156107e0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610804919061493e565b61080e908761492b565b95506108e9565b61083a61082560208a018a61488e565b6001600160a01b0383169060a08b0135613c93565b610847602089018961488e565b604051636ec9facd60e11b81523060048201526001600160a01b03919091169063dd93f59a906024016020604051808303816000875af115801561088f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b3919061493e565b6108bd908861492b565b965060a08801356108d28760608b0135614918565b6108dc9190614918565b6108e6908761492b565b95505b6109006108f960208a018a61488e565b8888613ab5565b909750955061092661091560208a018a61488e565b6001600160a01b0384169089613c93565b61094761093660208a018a61488e565b6001600160a01b0383169088613c93565b61097161095760208a018a61488e565b61096760408b0160208c0161488e565b8a60c00135613ce2565b945060006109886001600160a01b03841630613d82565b905080156109a4576109a46001600160a01b0384163383613c93565b6109b76001600160a01b03831630613d82565b905080156109d3576109d36001600160a01b0383163383613c93565b50505050509193909250565b6000808815610a5957610a5460128b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a4f9190614957565b613db7565b610ac5565b610ac58a6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610abe9190614957565b6012613db7565b7f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b849086001600160a01b0316636a132ea68a610aff578b610b21565b7f00000000000000000000000043000000000000000000000000000000000000045b8b610b4c577f0000000000000000000000004300000000000000000000000000000000000004610b4e565b8c5b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604481018b9052606481018a90526084810189905285151560a482015260c4016020604051808303816000875af1158015610bb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bdc91906148c8565b91507f00000000000000000000000043000000000000000000000000000000000000046001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610c3957600080fd5b505af1158015610c4d573d6000803e3d6000fd5b50610c69935050506001600160a01b038c169050338487613a58565b610c9d6001600160a01b037f0000000000000000000000004300000000000000000000000000000000000004168334613c93565b604051634c85b42560e01b81526001600160a01b038681166004830152831690634c85b425906024016060604051808303816000875af1158015610ce5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d09919061497a565b50929b909a5098505050505050505050565b60008180421115610d3f57604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808916600483015288917f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b8490890911690631e1c6a0790602401602060405180830381865afa158015610da9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dcd91906148ab565b610dea576040516392c46cf760e01b815260040160405180910390fd5b7f00000000000000000000000043000000000000000000000000000000000000046001600160a01b0316886001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7691906148c8565b6001600160a01b031614610e9d57604051632be739cb60e21b815260040160405180910390fd5b610f163389888b6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0591906148c8565b6001600160a01b0316929190613a58565b610f21883087613e6d565b604051632e1a7d4d60e01b8152600481018290529093507f00000000000000000000000043000000000000000000000000000000000000046001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015610f8657600080fd5b505af1158015610f9a573d6000803e3d6000fd5b50610fb2925050506001600160a01b03881684613f04565b505095945050505050565b6000806110638b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611001573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110259190614957565b8b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a2b573d6000803e3d6000fd5b604051633509975360e11b81526001600160a01b038c811660048301528b81166024830152604482018b9052606482018a90526084820189905284151560a48301527f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b849081690636a132ea69060c4016020604051808303816000875af11580156110f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111491906148c8565b915061112b6001600160a01b038c16338488613a58565b6111406001600160a01b038b16338487613a58565b604051634c85b42560e01b81526001600160a01b038781166004830152831690634c85b425906024016060604051808303816000875af1158015611188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ac919061497a565b50929c909b509950505050505050505050565b600080600083804211156111e657604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808c1660048301528b917f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b8490890911690631e1c6a0790602401602060405180830381865afa158015611250573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127491906148ab565b611291576040516392c46cf760e01b815260040160405180910390fd5b61129c8b8a8a613ab5565b80955081965050506112e8338c878e6001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b61132c338c868e6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b6113378b8b89613ce2565b9250505096509650969350505050565b6000818042111561136b57604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808816600483015287917f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b8490890911690631e1c6a0790602401602060405180830381865afa1580156113d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f991906148ab565b611416576040516392c46cf760e01b815260040160405180910390fd5b6000876001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611456573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147a91906148c8565b90507f00000000000000000000000043000000000000000000000000000000000000046001600160a01b0316816001600160a01b0316146114ce57604051632be739cb60e21b815260040160405180910390fd5b7f00000000000000000000000043000000000000000000000000000000000000046001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561152957600080fd5b505af115801561153d573d6000803e3d6000fd5b50611558935050506001600160a01b03831690508934613c93565b611563888888613f24565b98975050505050505050565b6000818042111561159357604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808916600483015288917f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b8490890911690631e1c6a0790602401602060405180830381865afa1580156115fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162191906148ab565b61163e576040516392c46cf760e01b815260040160405180910390fd5b6116823389888b6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b611563888887613e6d565b600080600061169c8587613f56565b84106116a857846116b2565b6116b28487613f7e565b90508092506116c18187613f56565b91506107d181116116da575060009150819050806116e9565b6116e66103e982614918565b90505b93509350939050565b604051631e1c6a0760e01b81526001600160a01b038781166004830152600091829189917f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b8490890911690631e1c6a0790602401602060405180830381865afa158015611761573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061178591906148ab565b6117a2576040516392c46cf760e01b815260040160405180910390fd5b6117b76001600160a01b038a1633308a613a58565b604051635ab6755360e11b8152600481018890526001600160a01b038981166024830152604482018890526064820187905260c06084830152600060c483015260a482018690528a169063b56ceaa69060e40160408051808303816000875af1158015611828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061184c91906149a8565b9250925050965096945050505050565b6000818042111561188057604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808916600483015288917f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b8490890911690631e1c6a0790602401602060405180830381865afa1580156118ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190e91906148ab565b61192b576040516392c46cf760e01b815260040160405180910390fd5b7f00000000000000000000000043000000000000000000000000000000000000046001600160a01b0316886001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015611993573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b791906148c8565b6001600160a01b0316146119de5760405163807af6e560e01b815260040160405180910390fd5b611a223389888b6001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b610f21883087613f24565b6000803068929eee149b4bd212685403611a4f5763ab143c066000526004601cfd5b604051631e1c6a0760e01b81526001600160a01b03808616600483015285917f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b8490890911690631e1c6a0790602401602060405180830381865afa158015611ab9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611add91906148ab565b611afa576040516392c46cf760e01b815260040160405180910390fd5b6000611b7186876001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6291906148c8565b6001600160a01b031690613d82565b90506000611bb787886001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b3e573d6000803e3d6000fd5b90506000876001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bf9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1d919061493e565b905080611c2a88856149cc565b611c3491906149e3565b955080611c4188846149cc565b611c4b91906149e3565b9450505050509250929050565b60008180421115611c7c57604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808a16600483015289917f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b8490890911690631e1c6a0790602401602060405180830381865afa158015611ce6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d0a91906148ab565b611d27576040516392c46cf760e01b815260040160405180910390fd5b6000896001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8b91906148c8565b905060008a6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015611dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df191906148c8565b9050611e086001600160a01b038c1633308b613a58565b604051635ab6755360e11b8152600481018990523060248201526000604482018190526064820181905260c0608483015260c4820181905260a482018890529081906001600160a01b038e169063b56ceaa69060e40160408051808303816000875af1158015611e7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea091906149a8565b915091508a15611f5357611ebe6001600160a01b0384168e83613c93565b604051636ec9facd60e11b81523060048201526001600160a01b038e169063dd93f59a906024016020604051808303816000875af1158015611f04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f28919061493e565b611f32908361492b565b96508615611f4e57611f4e6001600160a01b0385168d89613c93565b611ff7565b611f676001600160a01b0385168e84613c93565b604051632f58056d60e21b81523060048201526001600160a01b038e169063bd6015b4906024016020604051808303816000875af1158015611fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd1919061493e565b611fdb908261492b565b96508615611ff757611ff76001600160a01b0384168d89613c93565b8887101561202057604051632ff97dcd60e11b8152600481018890526024015b60405180910390fd5b5050505050509695505050505050565b6000818042111561205457604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808916600483015288917f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b8490890911690631e1c6a0790602401602060405180830381865afa1580156120be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e291906148ab565b6120ff576040516392c46cf760e01b815260040160405180910390fd5b6000886001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561213f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061216391906148c8565b90507f00000000000000000000000043000000000000000000000000000000000000046001600160a01b0316816001600160a01b03160361220757886001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061220091906148c8565b90506122ba565b7f00000000000000000000000043000000000000000000000000000000000000046001600160a01b0316896001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561226f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061229391906148c8565b6001600160a01b0316146122ba57604051639700d1eb60e01b815260040160405180910390fd5b7f00000000000000000000000043000000000000000000000000000000000000046001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561231557600080fd5b505af1158015612329573d6000803e3d6000fd5b506123659350506001600160a01b037f00000000000000000000000043000000000000000000000000000000000000041691508b905034613c93565b61237a6001600160a01b038216338b8a613a58565b612385898988613ce2565b9998505050505050505050565b600081804211156123b657604051630992d5df60e41b815260040160405180910390fd5b6123c08787613f93565b6000878760008181106123d5576123d5614a05565b90506020020160208101906123ea919061488e565b905060008660011660000361246257816001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612437573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245b91906148c8565b90506124c7565b816001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156124a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124c491906148c8565b90505b7f00000000000000000000000043000000000000000000000000000000000000046001600160a01b0316816001600160a01b0316146125195760405163b1e72b7960e01b815260040160405180910390fd5b7f00000000000000000000000043000000000000000000000000000000000000046001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561257457600080fd5b505af1158015612588573d6000803e3d6000fd5b506125a3935050506001600160a01b03831690508334613c93565b6125b08a8a8a8a8a613fd8565b9a9950505050505050505050565b600080600083804211156125e557604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808d1660048301528c917f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b8490890911690631e1c6a0790602401602060405180830381865afa15801561264f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061267391906148ab565b612690576040516392c46cf760e01b815260040160405180910390fd5b60008c6001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f491906148c8565b905060008d6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612736573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275a91906148c8565b90508b15612808576127776001600160a01b03831633308e613a58565b6127818a8c614918565b96506127976001600160a01b0383168f8c613c93565b604051632f58056d60e21b81523060048201526001600160a01b038f169063bd6015b4906024016020604051808303816000875af11580156127dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612801919061493e565b95506128aa565b61281d6001600160a01b03821633308e613a58565b6128278a8c614918565b955061283d6001600160a01b0382168f8c613c93565b604051636ec9facd60e11b81523060048201526001600160a01b038f169063dd93f59a906024016020604051808303816000875af1158015612883573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a7919061493e565b96505b6128b58e8888613ab5565b90975095506128ce6001600160a01b0383168f89613c93565b6128e26001600160a01b0382168f88613c93565b6128ed8e8e8b613ce2565b945060006129046001600160a01b03841630613d82565b90508015612920576129206001600160a01b0384163383613c93565b6129336001600160a01b03831630613d82565b9050801561294f5761294f6001600160a01b0383163383613c93565b50505050509750975097945050505050565b6000818042111561298557604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808a16600483015289917f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b8490890911690631e1c6a0790602401602060405180830381865afa1580156129ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a1391906148ab565b612a30576040516392c46cf760e01b815260040160405180910390fd5b612a74338a898c6001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b612ab8338a888c6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b612385898987613ce2565b60008180421115612ae757604051630992d5df60e41b815260040160405180910390fd5b612af18787613f93565b6000612afe600188614918565b90506000888883818110612b1457612b14614a05565b9050602002016020810190612b29919061488e565b90506000600188841c168103612ba257816001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b9b91906148c8565b9050612c07565b816001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612be0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c0491906148c8565b90505b7f00000000000000000000000043000000000000000000000000000000000000046001600160a01b0316816001600160a01b031614612c59576040516365ba5f2960e01b815260040160405180910390fd5b60008a8a6000818110612c6e57612c6e614a05565b9050602002016020810190612c83919061488e565b905088600116600003612cd957612cd433828e846001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b612d1d565b612d1d33828e846001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b612d2a308c8c8c8c613fd8565b604051632e1a7d4d60e01b8152600481018290529096507f00000000000000000000000043000000000000000000000000000000000000046001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015612d8f57600080fd5b505af1158015612da3573d6000803e3d6000fd5b50612dbb925050506001600160a01b038e1687613f04565b5050505050979650505050505050565b60008180421115612def57604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808916600483015288917f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b8490890911690631e1c6a0790602401602060405180830381865afa158015612e59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e7d91906148ab565b612e9a576040516392c46cf760e01b815260040160405180910390fd5b612ede3389888b6001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b611563888887613f24565b60008180421115612f0d57604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808816600483015287917f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b8490890911690631e1c6a0790602401602060405180830381865afa158015612f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9b91906148ab565b612fb8576040516392c46cf760e01b815260040160405180910390fd5b6000876001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ff8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061301c91906148c8565b90507f00000000000000000000000043000000000000000000000000000000000000046001600160a01b0316816001600160a01b0316146130705760405163807af6e560e01b815260040160405180910390fd5b7f00000000000000000000000043000000000000000000000000000000000000046001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156130cb57600080fd5b505af11580156130df573d6000803e3d6000fd5b506130fa935050506001600160a01b03831690508934613c93565b611563888888613e6d565b60008060003068929eee149b4bd2126854036131295763ab143c066000526004601cfd5b3068929eee149b4bd2126855838042111561315757604051630992d5df60e41b815260040160405180910390fd5b604051631e1c6a0760e01b81526001600160a01b03808c1660048301528b917f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b8490890911690631e1c6a0790602401602060405180830381865afa1580156131c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e591906148ab565b613202576040516392c46cf760e01b815260040160405180910390fd5b60008060008d6001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613245573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061326991906148c8565b90507f00000000000000000000000043000000000000000000000000000000000000046001600160a01b0316816001600160a01b031603613323578d6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132e2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330691906148c8565b90506133138e348d613ab5565b90985096508792508691506133f1565b7f00000000000000000000000043000000000000000000000000000000000000046001600160a01b03168e6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561338b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133af91906148c8565b6001600160a01b0316036133d8576133c88e8c34613ab5565b90985096508692508791506133f1565b604051639700d1eb60e01b815260040160405180910390fd5b7f00000000000000000000000043000000000000000000000000000000000000046001600160a01b031663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b15801561344c57600080fd5b505af1158015613460573d6000803e3d6000fd5b50505050506134a38e847f00000000000000000000000043000000000000000000000000000000000000046001600160a01b0316613c939092919063ffffffff16565b823411156134c8576134c86134b88434614918565b6001600160a01b038e1690613f04565b6134e8338f84846001600160a01b0316613a58909392919063ffffffff16565b6134f38e8e8c613ce2565b955050505050503868929eee149b4bd212685596509650969350505050565b6000818042111561353657604051630992d5df60e41b815260040160405180910390fd5b6135408787613f93565b60008787600081811061355557613555614a05565b905060200201602081019061356a919061488e565b9050856001166000036135c0576135bb33828b846001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b613604565b61360433828b846001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee1573d6000803e3d6000fd5b6125b08a89898989613fd8565b604051631e1c6a0760e01b81526001600160a01b038781166004830152600091829189917f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b8490890911690631e1c6a0790602401602060405180830381865afa158015613680573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136a491906148ab565b6136c1576040516392c46cf760e01b815260040160405180910390fd5b6136d66001600160a01b038a1633308a613a58565b6000896001600160a01b0316634a248d2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613716573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061373a91906148c8565b90507f00000000000000000000000043000000000000000000000000000000000000046001600160a01b0316816001600160a01b03160361387757896001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137d791906148c8565b604051635ab6755360e11b8152600481018a9052306024820152604481018990526064810188905260c06084820152600060c482015260a481018790529091506001600160a01b038b169063b56ceaa69060e40160408051808303816000875af1158015613849573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061386d91906149a8565b90945092506139a9565b7f00000000000000000000000043000000000000000000000000000000000000046001600160a01b03168a6001600160a01b031663d4b970466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061390391906148c8565b6001600160a01b0316036133d857604051635ab6755360e11b815260048101899052306024820152604481018790526064810188905260c06084820152600060c482015260a481018690526001600160a01b038b169063b56ceaa69060e40160408051808303816000875af1158015613980573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139a491906149a8565b945092505b604051632e1a7d4d60e01b8152600481018590527f00000000000000000000000043000000000000000000000000000000000000046001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015613a0b57600080fd5b505af1158015613a1f573d6000803e3d6000fd5b50613a37925050506001600160a01b038a1685613f04565b613a4b6001600160a01b0382168a85613c93565b5050965096945050505050565b60405181606052826040528360601b602c526f23b872dd000000000000000000000000600c52602060006064601c6000895af13d156001600051141716613aa757637939f4246000526004601cfd5b600060605260405250505050565b600080846001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613af6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b1a919061493e565b600003613bc1576000856001600160a01b031663f811d6926040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b85919061493e565b90506000613b938683613f56565b8510613b9f5785613ba9565b613ba98583613f7e565b9050809350613bb88183613f56565b92505050613c8b565b600080866001600160a01b0316630902f1ac6040518163ffffffff1660e01b81526004016040805180830381865afa158015613c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c2591906149a8565b91509150600081118015613c395750600082115b15613c88576000613c4a8784613f7e565b90506000613c588784613f7e565b9050808211613c7557879550613c6e8383613f56565b9450613c85565b869450613c828482613f56565b95505b50505b50505b935093915050565b81601452806034526fa9059cbb00000000000000000000000060005260206000604460106000875af13d156001600051141716613cd8576390b8ec186000526004601cfd5b6000603452505050565b604051634c85b42560e01b81526001600160a01b03838116600483015260009190851690634c85b425906024016060604051808303816000875af1158015613d2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d52919061497a565b509091505081811015613d7b57604051632ff97dcd60e11b815260048101829052602401612017565b9392505050565b6000816014526f70a0823100000000000000000000000060005260208060246010865afa601f3d111660205102905092915050565b60ff82161580613dc8575060ff8116155b15613de65760405163ca1aefb560e01b815260040160405180910390fd5b60128260ff161180613dfb575060128160ff16115b15613e195760405163062d0f8560e51b815260040160405180910390fd5b60008160ff168360ff1611613e3757613e328383614a1b565b613e41565b613e418284614a1b565b60ff169050600c811115613e68576040516397088e6160e01b815260040160405180910390fd5b505050565b604051636ec9facd60e11b81526001600160a01b0383811660048301526000919085169063dd93f59a906024015b6020604051808303816000875af1158015613eba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ede919061493e565b905081811015613d7b57604051632ff97dcd60e11b815260048101829052602401612017565b60003860003884865af1613f205763b12d13eb6000526004601cfd5b5050565b604051632f58056d60e21b81526001600160a01b0383811660048301526000919085169063bd6015b490602401613e9b565b6000670de0b6b3a7640000613f6b83856149cc565b613f7591906149e3565b90505b92915050565b600081613f6b670de0b6b3a7640000856149cc565b80610100811115613fb7576040516315e8dba360e01b815260040160405180910390fd5b60008111613e68576040516376ede79b60e11b815260040160405180910390fd5b600080613fe6600186614918565b905060005b8181101561423c57600087878381811061400757614007614a05565b905060200201602081019061401c919061488e565b604051631e1c6a0760e01b81526001600160a01b0380831660048301529192507f0000000000000000000000007e05363e225c1c8096b1cd233b59457104b8490890911690631e1c6a0790602401602060405180830381865afa158015614087573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140ab91906148ab565b6140c8576040516392c46cf760e01b815260040160405180910390fd5b85600116600003614183576001600160a01b03811663bd6015b489896140ef86600161492b565b8181106140fe576140fe614a05565b9050602002016020810190614113919061488e565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201526024016020604051808303816000875af1158015614159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061417d919061493e565b5061422f565b6001600160a01b03811663dd93f59a898961419f86600161492b565b8181106141ae576141ae614a05565b90506020020160208101906141c3919061488e565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201526024016020604051808303816000875af1158015614209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061422d919061493e565b505b50600194851c9401613feb565b50836001166000036142e45785858281811061425a5761425a614a05565b905060200201602081019061426f919061488e565b604051632f58056d60e21b81526001600160a01b038981166004830152919091169063bd6015b4906024016020604051808303816000875af11580156142b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142dd919061493e565b915061437c565b8585828181106142f6576142f6614a05565b905060200201602081019061430b919061488e565b604051636ec9facd60e11b81526001600160a01b038981166004830152919091169063dd93f59a906024016020604051808303816000875af1158015614355573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614379919061493e565b91505b828210156143a057604051632ff97dcd60e11b815260048101839052602401612017565b5095945050505050565b600061010082840312156143bd57600080fd5b50919050565b6001600160a01b03811681146143d857600080fd5b50565b80151581146143d857600080fd5b600080600080600080600080610100898b03121561440657600080fd5b8835614411816143c3565b97506020890135614421816143db565b965060408901359550606089013594506080890135935060a0890135614446816143c3565b925060c0890135915060e089013561445d816143db565b809150509295985092959890939650565b600080600080600060a0868803121561448657600080fd5b8535614491816143c3565b945060208601356144a1816143c3565b94979496505050506040830135926060810135926080909101359150565b60008060008060008060008060006101208a8c0312156144de57600080fd5b89356144e9816143c3565b985060208a01356144f9816143c3565b975060408a0135965060608a0135955060808a0135945060a08a013561451e816143c3565b935060c08a0135925060e08a013591506101008a013561453d816143db565b809150509295985092959850929598565b60008060008060008060c0878903121561456757600080fd5b8635614572816143c3565b95506020870135614582816143c3565b95989597505050506040840135936060810135936080820135935060a0909101359150565b600080600080608085870312156145bd57600080fd5b84356145c8816143c3565b935060208501356145d8816143c3565b93969395505050506040820135916060013590565b60008060006060848603121561460257600080fd5b505081359360208301359350604090920135919050565b6000806040838503121561462c57600080fd5b8235614637816143c3565b946020939093013593505050565b60008060008060008060c0878903121561465e57600080fd5b8635614669816143c3565b95506020870135614679816143c3565b94506040870135614689816143db565b959894975094956060810135955060808101359460a0909101359350915050565b60008083601f8401126146bc57600080fd5b50813567ffffffffffffffff8111156146d457600080fd5b6020830191508360208260051b85010111156146ef57600080fd5b9250929050565b60008060008060008060a0878903121561470f57600080fd5b863561471a816143c3565b9550602087013567ffffffffffffffff81111561473657600080fd5b61474289828a016146aa565b979a90995096976040810135976060820135975060809091013595509350505050565b600080600080600080600060e0888a03121561478057600080fd5b873561478b816143c3565b9650602088013561479b816143c3565b955060408801356147ab816143db565b969995985095966060810135965060808101359560a0820135955060c0909101359350915050565b600080600080600080600060c0888a0312156147ee57600080fd5b87356147f9816143c3565b965060208801359550604088013567ffffffffffffffff81111561481c57600080fd5b6148288a828b016146aa565b989b979a50986060810135976080820135975060a09091013595509350505050565b60008060008060008060c0878903121561486357600080fd5b863561486e816143c3565b9550602087013561487e816143c3565b94506040870135614689816143c3565b6000602082840312156148a057600080fd5b8135613d7b816143c3565b6000602082840312156148bd57600080fd5b8151613d7b816143db565b6000602082840312156148da57600080fd5b8151613d7b816143c3565b6000602082840312156148f757600080fd5b8135613d7b816143db565b634e487b7160e01b600052601160045260246000fd5b81810381811115613f7857613f78614902565b80820180821115613f7857613f78614902565b60006020828403121561495057600080fd5b5051919050565b60006020828403121561496957600080fd5b815160ff81168114613d7b57600080fd5b60008060006060848603121561498f57600080fd5b8351925060208401519150604084015190509250925092565b600080604083850312156149bb57600080fd5b505080516020909101519092909150565b8082028115828204841417613f7857613f78614902565b600082614a0057634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b60ff8281168282160390811115613f7857613f7861490256fea264697066735822122045228d232f7c69682bdc5876b4908b5797bead31ed44859911d15aa1e5911a6664736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000043000000000000000000000000000000000000040000000000000000000000007e05363e225c1c8096b1cd233b59457104b84908000000000000000000000000d69e75c1c2a0f2838a6bba8bdff9d08c8f137cd9
-----Decoded View---------------
Arg [0] : weth_ (address): 0x4300000000000000000000000000000000000004
Arg [1] : factory (address): 0x7E05363E225c1c8096b1cd233B59457104B84908
Arg [2] : governor_ (address): 0xD69E75C1c2a0f2838A6bbA8BDFf9d08C8f137cD9
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000004300000000000000000000000000000000000004
Arg [1] : 0000000000000000000000007e05363e225c1c8096b1cd233b59457104b84908
Arg [2] : 000000000000000000000000d69e75c1c2a0f2838a6bba8bdff9d08c8f137cd9
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.