Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
23605789 | 854 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
ConstantProductPool
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
Yes with 999999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.0; import {ERC20} from "@rari-capital/solmate/src/tokens/ERC20.sol"; import {ReentrancyGuard} from "@rari-capital/solmate/src/utils/ReentrancyGuard.sol"; import {IBentoBoxMinimal} from "../../interfaces/IBentoBoxMinimal.sol"; import {IPool} from "../../interfaces/IPool.sol"; import {ITridentCallee} from "../../interfaces/ITridentCallee.sol"; import {IConstantProductPoolFactory} from "../../interfaces/IConstantProductPoolFactory.sol"; import {IMasterDeployer} from "../../interfaces/IMasterDeployer.sol"; import {TridentMath} from "../../libraries/TridentMath.sol"; /// @dev Custom Errors error ZeroAddress(); error IdenticalAddress(); error InvalidSwapFee(); error InvalidAmounts(); error InsufficientLiquidityMinted(); error InvalidOutputToken(); error InvalidInputToken(); error PoolUninitialized(); error InsufficientAmountIn(); error Overflow(); /// @notice Trident exchange pool template with constant product formula for swapping between an ERC-20 token pair. /// @dev The reserves are stored as bento shares. /// The curve is applied to shares as well. This pool does not care about the underlying amounts. contract ConstantProductPool is IPool, ERC20, ReentrancyGuard { event Mint(address indexed sender, uint256 amount0, uint256 amount1, address indexed recipient); event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed recipient); event Sync(uint256 reserve0, uint256 reserve1); uint256 internal constant MINIMUM_LIQUIDITY = 1000; uint8 internal constant PRECISION = 112; uint256 internal constant MAX_FEE = 10000; // @dev 100%. uint256 public immutable swapFee; uint256 internal immutable MAX_FEE_MINUS_SWAP_FEE; IBentoBoxMinimal public immutable bento; IMasterDeployer public immutable masterDeployer; address public immutable token0; address public immutable token1; uint256 public barFee; address public barFeeTo; uint256 public price0CumulativeLast; uint256 public price1CumulativeLast; uint256 public kLast; uint112 internal reserve0; uint112 internal reserve1; uint32 internal blockTimestampLast; bytes32 public constant override poolIdentifier = "Trident:ConstantProduct"; constructor() ERC20("Sushi Constant Product LP Token", "SCPLP", 18) { (bytes memory _deployData, IMasterDeployer _masterDeployer) = IConstantProductPoolFactory(msg.sender).getDeployData(); (address _token0, address _token1, uint256 _swapFee, bool _twapSupport) = abi.decode( _deployData, (address, address, uint256, bool) ); // Factory ensures that the tokens are sorted. if (_token0 == address(0)) revert ZeroAddress(); if (_token0 == _token1) revert IdenticalAddress(); if (_swapFee > MAX_FEE) revert InvalidSwapFee(); token0 = _token0; token1 = _token1; swapFee = _swapFee; // This is safe from underflow - `swapFee` cannot exceed `MAX_FEE` per previous check. unchecked { MAX_FEE_MINUS_SWAP_FEE = MAX_FEE - _swapFee; } barFee = _masterDeployer.barFee(); barFeeTo = _masterDeployer.barFeeTo(); bento = IBentoBoxMinimal(_masterDeployer.bento()); masterDeployer = _masterDeployer; if (_twapSupport) blockTimestampLast = uint32(block.timestamp); } /// @dev Mints LP tokens - should be called via the router after transferring `bento` tokens. /// The router must ensure that sufficient LP tokens are minted by using the return value. function mint(bytes calldata data) public override nonReentrant returns (uint256 liquidity) { address recipient = abi.decode(data, (address)); (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) = _getReserves(); (uint256 balance0, uint256 balance1) = _balance(); uint256 computed = TridentMath.sqrt(balance0 * balance1); uint256 amount0 = balance0 - _reserve0; uint256 amount1 = balance1 - _reserve1; (uint256 fee0, uint256 fee1) = _nonOptimalMintFee(amount0, amount1, _reserve0, _reserve1); _reserve0 += uint112(fee0); _reserve1 += uint112(fee1); (uint256 _totalSupply, uint256 k) = _mintFee(_reserve0, _reserve1); if (_totalSupply == 0) { if (amount0 == 0 || amount1 == 0) revert InvalidAmounts(); liquidity = computed - MINIMUM_LIQUIDITY; _mint(address(0), MINIMUM_LIQUIDITY); } else { uint256 kIncrease; unchecked { kIncrease = computed - k; } liquidity = (kIncrease * _totalSupply) / k; } if (liquidity == 0) revert InsufficientLiquidityMinted(); _mint(recipient, liquidity); _update(balance0, balance1, _reserve0, _reserve1, _blockTimestampLast); kLast = computed; emit Mint(msg.sender, amount0, amount1, recipient); } /// @dev Burns LP tokens sent to this contract. The router must ensure that the user gets sufficient output tokens. function burn(bytes calldata data) public override nonReentrant returns (IPool.TokenAmount[] memory withdrawnAmounts) { (address recipient, bool unwrapBento) = abi.decode(data, (address, bool)); (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) = _getReserves(); (uint256 balance0, uint256 balance1) = _balance(); uint256 liquidity = balanceOf[address(this)]; (uint256 _totalSupply, ) = _mintFee(_reserve0, _reserve1); uint256 amount0 = (liquidity * balance0) / _totalSupply; uint256 amount1 = (liquidity * balance1) / _totalSupply; _burn(address(this), liquidity); _transfer(token0, amount0, recipient, unwrapBento); _transfer(token1, amount1, recipient, unwrapBento); // This is safe from underflow - amounts are lesser figures derived from balances. unchecked { balance0 -= amount0; balance1 -= amount1; } _update(balance0, balance1, _reserve0, _reserve1, _blockTimestampLast); kLast = TridentMath.sqrt(balance0 * balance1); withdrawnAmounts = new TokenAmount[](2); withdrawnAmounts[0] = TokenAmount({token: address(token0), amount: amount0}); withdrawnAmounts[1] = TokenAmount({token: address(token1), amount: amount1}); emit Burn(msg.sender, amount0, amount1, recipient); } /// @dev Burns LP tokens sent to this contract and swaps one of the output tokens for another /// - i.e., the user gets a single token out by burning LP tokens. function burnSingle(bytes calldata data) public override nonReentrant returns (uint256 amountOut) { (address tokenOut, address recipient, bool unwrapBento) = abi.decode(data, (address, address, bool)); (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) = _getReserves(); uint256 liquidity = balanceOf[address(this)]; (uint256 _totalSupply, ) = _mintFee(_reserve0, _reserve1); uint256 amount0 = (liquidity * _reserve0) / _totalSupply; uint256 amount1 = (liquidity * _reserve1) / _totalSupply; kLast = TridentMath.sqrt((_reserve0 - amount0) * (_reserve1 - amount1)); _burn(address(this), liquidity); // Swap one token for another unchecked { if (tokenOut == token1) { // Swap `token0` for `token1` // - calculate `amountOut` as if the user first withdrew balanced liquidity and then swapped `token0` for `token1`. amount1 += _getAmountOut(amount0, _reserve0 - amount0, _reserve1 - amount1); _transfer(token1, amount1, recipient, unwrapBento); amountOut = amount1; amount0 = 0; } else { // Swap `token1` for `token0`. if (tokenOut != token0) revert InvalidOutputToken(); amount0 += _getAmountOut(amount1, _reserve1 - amount1, _reserve0 - amount0); _transfer(token0, amount0, recipient, unwrapBento); amountOut = amount0; amount1 = 0; } } (uint256 balance0, uint256 balance1) = _balance(); _update(balance0, balance1, _reserve0, _reserve1, _blockTimestampLast); emit Burn(msg.sender, amount0, amount1, recipient); } /// @dev Swaps one token for another. The router must prefund this contract and ensure there isn't too much slippage. function swap(bytes calldata data) public override nonReentrant returns (uint256 amountOut) { (address tokenIn, address recipient, bool unwrapBento) = abi.decode(data, (address, address, bool)); (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) = _getReserves(); if (_reserve0 == 0) revert PoolUninitialized(); (uint256 balance0, uint256 balance1) = _balance(); uint256 amountIn; address tokenOut; unchecked { if (tokenIn == token0) { tokenOut = token1; amountIn = balance0 - _reserve0; amountOut = _getAmountOut(amountIn, _reserve0, _reserve1); balance1 -= amountOut; } else { if (tokenIn != token1) revert InvalidInputToken(); tokenOut = token0; amountIn = balance1 - reserve1; amountOut = _getAmountOut(amountIn, _reserve1, _reserve0); balance0 -= amountOut; } } _transfer(tokenOut, amountOut, recipient, unwrapBento); _update(balance0, balance1, _reserve0, _reserve1, _blockTimestampLast); emit Swap(recipient, tokenIn, tokenOut, amountIn, amountOut); } /// @dev Swaps one token for another. The router must support swap callbacks and ensure there isn't too much slippage. function flashSwap(bytes calldata data) public override nonReentrant returns (uint256 amountOut) { (address tokenIn, address recipient, bool unwrapBento, uint256 amountIn, bytes memory context) = abi.decode( data, (address, address, bool, uint256, bytes) ); (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) = _getReserves(); if (_reserve0 == 0) revert PoolUninitialized(); unchecked { if (tokenIn == token0) { amountOut = _getAmountOut(amountIn, _reserve0, _reserve1); _transfer(token1, amountOut, recipient, unwrapBento); ITridentCallee(msg.sender).tridentSwapCallback(context); (uint256 balance0, uint256 balance1) = _balance(); if (balance0 - _reserve0 < amountIn) revert InsufficientAmountIn(); _update(balance0, balance1, _reserve0, _reserve1, _blockTimestampLast); emit Swap(recipient, tokenIn, token1, amountIn, amountOut); } else { if (tokenIn != token1) revert InvalidInputToken(); amountOut = _getAmountOut(amountIn, _reserve1, _reserve0); _transfer(token0, amountOut, recipient, unwrapBento); ITridentCallee(msg.sender).tridentSwapCallback(context); (uint256 balance0, uint256 balance1) = _balance(); if (balance1 - _reserve1 < amountIn) revert InsufficientAmountIn(); _update(balance0, balance1, _reserve0, _reserve1, _blockTimestampLast); emit Swap(recipient, tokenIn, token0, amountIn, amountOut); } } } /// @dev Updates `barFee` and `barFeeTo` for Trident protocol. function updateBarParameters() public { barFee = masterDeployer.barFee(); barFeeTo = masterDeployer.barFeeTo(); } function _getReserves() internal view returns ( uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast ) { _reserve0 = reserve0; _reserve1 = reserve1; _blockTimestampLast = blockTimestampLast; } function _balance() internal view returns (uint256 balance0, uint256 balance1) { balance0 = bento.balanceOf(token0, address(this)); balance1 = bento.balanceOf(token1, address(this)); } function _update( uint256 balance0, uint256 balance1, uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast ) internal { if (balance0 > type(uint112).max || balance1 > type(uint112).max) revert Overflow(); if (_blockTimestampLast == 0) { // TWAP support is disabled for gas efficiency. reserve0 = uint112(balance0); reserve1 = uint112(balance1); } else { uint32 blockTimestamp = uint32(block.timestamp); if (blockTimestamp != _blockTimestampLast && _reserve0 != 0 && _reserve1 != 0) { unchecked { uint32 timeElapsed = blockTimestamp - _blockTimestampLast; uint256 price0 = (uint256(_reserve1) << PRECISION) / _reserve0; price0CumulativeLast += price0 * timeElapsed; uint256 price1 = (uint256(_reserve0) << PRECISION) / _reserve1; price1CumulativeLast += price1 * timeElapsed; } } reserve0 = uint112(balance0); reserve1 = uint112(balance1); blockTimestampLast = blockTimestamp; } emit Sync(balance0, balance1); } function _mintFee(uint112 _reserve0, uint112 _reserve1) internal returns (uint256 _totalSupply, uint256 computed) { _totalSupply = totalSupply; uint256 _kLast = kLast; if (_kLast != 0) { computed = TridentMath.sqrt(uint256(_reserve0) * _reserve1); if (computed > _kLast) { // `barFee` % of increase in liquidity. uint256 _barFee = barFee; uint256 numerator = _totalSupply * (computed - _kLast) * _barFee; uint256 denominator = (MAX_FEE - _barFee) * computed + _barFee * _kLast; uint256 liquidity = numerator / denominator; if (liquidity != 0) { _mint(barFeeTo, liquidity); _totalSupply += liquidity; } } } } function _getAmountOut( uint256 amountIn, uint256 reserveAmountIn, uint256 reserveAmountOut ) internal view returns (uint256 amountOut) { uint256 amountInWithFee = amountIn * MAX_FEE_MINUS_SWAP_FEE; amountOut = (amountInWithFee * reserveAmountOut) / (reserveAmountIn * MAX_FEE + amountInWithFee); } function _getAmountIn( uint256 amountOut, uint256 reserveAmountIn, uint256 reserveAmountOut ) internal view returns (uint256 amountIn) { amountIn = (reserveAmountIn * amountOut * MAX_FEE) / ((reserveAmountOut - amountOut) * MAX_FEE_MINUS_SWAP_FEE) + 1; } function _transfer( address token, uint256 shares, address to, bool unwrapBento ) internal { if (unwrapBento) { bento.withdraw(token, address(this), to, 0, shares); } else { bento.transfer(token, address(this), to, shares); } } /// @dev This fee is charged to cover for `swapFee` when users add unbalanced liquidity. function _nonOptimalMintFee( uint256 _amount0, uint256 _amount1, uint256 _reserve0, uint256 _reserve1 ) internal view returns (uint256 token0Fee, uint256 token1Fee) { if (_reserve0 == 0 || _reserve1 == 0) return (0, 0); uint256 amount1Optimal = (_amount0 * _reserve1) / _reserve0; if (amount1Optimal <= _amount1) { token1Fee = (swapFee * (_amount1 - amount1Optimal)) / (2 * MAX_FEE); } else { uint256 amount0Optimal = (_amount1 * _reserve0) / _reserve1; token0Fee = (swapFee * (_amount0 - amount0Optimal)) / (2 * MAX_FEE); } } function getAssets() public view override returns (address[] memory assets) { assets = new address[](2); assets[0] = token0; assets[1] = token1; } function getAmountOut(bytes calldata data) public view override returns (uint256 finalAmountOut) { (address tokenIn, uint256 amountIn) = abi.decode(data, (address, uint256)); (uint112 _reserve0, uint112 _reserve1, ) = _getReserves(); if (tokenIn == token0) { finalAmountOut = _getAmountOut(amountIn, _reserve0, _reserve1); } else { if (tokenIn != token1) revert InvalidInputToken(); finalAmountOut = _getAmountOut(amountIn, _reserve1, _reserve0); } } function getAmountIn(bytes calldata data) public view override returns (uint256 finalAmountIn) { (address tokenOut, uint256 amountOut) = abi.decode(data, (address, uint256)); (uint112 _reserve0, uint112 _reserve1, ) = _getReserves(); if (tokenOut == token1) { finalAmountIn = _getAmountIn(amountOut, _reserve0, _reserve1); } else { if (tokenOut != token0) revert InvalidOutputToken(); finalAmountIn = _getAmountIn(amountOut, _reserve1, _reserve0); } } /// @dev Returned values are in terms of BentoBox "shares". function getReserves() public view returns ( uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast ) { return _getReserves(); } /// @dev Returned values are the native ERC20 token amounts. function getNativeReserves() public view returns ( uint256 _nativeReserve0, uint256 _nativeReserve1, uint32 _blockTimestampLast ) { (uint112 _reserve0, uint112 _reserve1, uint32 __blockTimestampLast) = _getReserves(); _nativeReserve0 = bento.toAmount(token0, _reserve0, false); _nativeReserve1 = bento.toAmount(token1, _reserve1, false); _blockTimestampLast = __blockTimestampLast; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*/////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*/////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*/////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*/////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*/////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*/////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*/////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { bytes32 digest = keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline)) ) ); address recoveredAddress = ecrecover(digest, v, r, s); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*/////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Gas optimized reentrancy protection for smart contracts. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/ReentrancyGuard.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol) abstract contract ReentrancyGuard { uint256 private reentrancyStatus = 1; modifier nonReentrant() { require(reentrancyStatus == 1, "REENTRANCY"); reentrancyStatus = 2; _; reentrancyStatus = 1; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.0; import "../libraries/RebaseLibrary.sol"; /// @notice Minimal BentoBox vault interface. /// @dev `token` is aliased as `address` from `IERC20` for simplicity. interface IBentoBoxMinimal { /// @notice Balance per ERC-20 token per account in shares. function balanceOf(address, address) external view returns (uint256); /// @dev Helper function to represent an `amount` of `token` in shares. /// @param token The ERC-20 token. /// @param amount The `token` amount. /// @param roundUp If the result `share` should be rounded up. /// @return share The token amount represented in shares. function toShare( address token, uint256 amount, bool roundUp ) external view returns (uint256 share); /// @dev Helper function to represent shares back into the `token` amount. /// @param token The ERC-20 token. /// @param share The amount of shares. /// @param roundUp If the result should be rounded up. /// @return amount The share amount back into native representation. function toAmount( address token, uint256 share, bool roundUp ) external view returns (uint256 amount); /// @notice Registers this contract so that users can approve it for BentoBox. function registerProtocol() external; /// @notice Deposit an amount of `token` represented in either `amount` or `share`. /// @param token The ERC-20 token to deposit. /// @param from which account to pull the tokens. /// @param to which account to push the tokens. /// @param amount Token amount in native representation to deposit. /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`. /// @return amountOut The amount deposited. /// @return shareOut The deposited amount represented in shares. function deposit( address token, address from, address to, uint256 amount, uint256 share ) external payable returns (uint256 amountOut, uint256 shareOut); /// @notice Withdraws an amount of `token` from a user account. /// @param token_ The ERC-20 token to withdraw. /// @param from which user to pull the tokens. /// @param to which user to push the tokens. /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied. /// @param share Like above, but `share` takes precedence over `amount`. function withdraw( address token_, address from, address to, uint256 amount, uint256 share ) external returns (uint256 amountOut, uint256 shareOut); /// @notice Transfer shares from a user account to another one. /// @param token The ERC-20 token to transfer. /// @param from which user to pull the tokens. /// @param to which user to push the tokens. /// @param share The amount of `token` in shares. function transfer( address token, address from, address to, uint256 share ) external; /// @dev Reads the Rebase `totals`from storage for a given token function totals(address token) external view returns (Rebase memory total); /// @dev Approves users' BentoBox assets to a "master" contract. function setMasterContractApproval( address user, address masterContract, bool approved, uint8 v, bytes32 r, bytes32 s ) external; function harvest( address token, bool balance, uint256 maxChangeAmount ) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.5.0; pragma experimental ABIEncoderV2; /// @notice Trident pool interface. interface IPool { /// @notice Executes a swap from one token to another. /// @dev The input tokens must've already been sent to the pool. /// @param data ABI-encoded params that the pool requires. /// @return finalAmountOut The amount of output tokens that were sent to the user. function swap(bytes calldata data) external returns (uint256 finalAmountOut); /// @notice Executes a swap from one token to another with a callback. /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback. /// @param data ABI-encoded params that the pool requires. /// @return finalAmountOut The amount of output tokens that were sent to the user. function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut); /// @notice Mints liquidity tokens. /// @param data ABI-encoded params that the pool requires. /// @return liquidity The amount of liquidity tokens that were minted for the user. function mint(bytes calldata data) external returns (uint256 liquidity); /// @notice Burns liquidity tokens. /// @dev The input LP tokens must've already been sent to the pool. /// @param data ABI-encoded params that the pool requires. /// @return withdrawnAmounts The amount of various output tokens that were sent to the user. function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts); /// @notice Burns liquidity tokens for a single output token. /// @dev The input LP tokens must've already been sent to the pool. /// @param data ABI-encoded params that the pool requires. /// @return amountOut The amount of output tokens that were sent to the user. function burnSingle(bytes calldata data) external returns (uint256 amountOut); /// @return A unique identifier for the pool type. function poolIdentifier() external pure returns (bytes32); /// @return An array of tokens supported by the pool. function getAssets() external view returns (address[] memory); /// @notice Simulates a trade and returns the expected output. /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library. /// @param data ABI-encoded params that the pool requires. /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed. function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut); /// @notice Simulates a trade and returns the expected output. /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library. /// @param data ABI-encoded params that the pool requires. /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed. function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn); /// @dev This event must be emitted on all swaps. event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut); /// @dev This struct frames output tokens for burns. struct TokenAmount { address token; uint256 amount; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.0; /// @notice Trident pool callback interface. interface ITridentCallee { function tridentSwapCallback(bytes calldata data) external; function tridentMintCallback(bytes calldata data) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.0; import "./IMasterDeployer.sol"; interface IConstantProductPoolFactory { function getDeployData() external view returns (bytes memory, IMasterDeployer); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.0; /// @notice Trident pool deployer interface. interface IMasterDeployer { function barFee() external view returns (uint256); function barFeeTo() external view returns (address); function bento() external view returns (address); function migrator() external view returns (address); function pools(address pool) external view returns (bool); function deployPool(address factory, bytes calldata deployData) external returns (address); function owner() external returns (address); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.0; /// @notice Trident sqrt helper library. library TridentMath { /// @dev Modified from Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol) function sqrt(uint256 x) internal pure returns (uint256 z) { assembly { // This segment is to get a reasonable initial estimate for the Babylonian method. // If the initial estimate is bad, the number of correct bits increases ~linearly // each iteration instead of ~quadratically. // The idea is to get z*z*y within a small factor of x. // More iterations here gets y in a tighter range. Currently, we will have // y in [256, 256*2^16). We ensure y>= 256 so that the relative difference // between y and y+1 is small. If x < 256 this is not possible, but those cases // are easy enough to verify exhaustively. z := 181 // The 'correct' value is 1, but this saves a multiply later let y := x // Note that we check y>= 2^(k + 8) but shift right by k bits each branch, // this is to ensure that if x >= 256, then y >= 256. if iszero(lt(y, 0x10000000000000000000000000000000000)) { y := shr(128, y) z := shl(64, z) } if iszero(lt(y, 0x1000000000000000000)) { y := shr(64, y) z := shl(32, z) } if iszero(lt(y, 0x10000000000)) { y := shr(32, y) z := shl(16, z) } if iszero(lt(y, 0x1000000)) { y := shr(16, y) z := shl(8, z) } // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), // and either y >= 256, or x < 256. // Correctness can be checked exhaustively for x < 256, so we assume y >= 256. // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps. // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) // is in the range (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s=1 // and when s = 256 or 1/256. Since y is in [256, 256*2^16), let a = y/65536, so // that a is in [1/256, 256). Then we can estimate sqrt(y) as // sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18 // There is no overflow risk here since y < 2^136 after the first branch above. z := shr(18, mul(z, add(y, 65536))) // A multiply is saved from the initial z := 181 // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough. // Possibly with a quadratic/cubic polynomial above we could get 4-6. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) // See https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division. // If x+1 is a perfect square, the Babylonian method cycles between // floor(sqrt(x)) and ceil(sqrt(x)). This check ensures we return floor. // Since this case is rare, we choose to save gas on the assignment and // repeat division in the rare case. // If you don't care whether floor or ceil is returned, you can skip this. if lt(div(x, z), z) { z := div(x, z) } } } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8; struct Rebase { uint128 elastic; uint128 base; } /// @notice A rebasing library library RebaseLibrary { /// @notice Calculates the base value in relationship to `elastic` and `total`. function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) { if (total.elastic == 0) { base = elastic; } else { base = (elastic * total.base) / total.elastic; } } /// @notice Calculates the elastic value in relationship to `base` and `total`. function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) { if (total.base == 0) { elastic = base; } else { elastic = (base * total.elastic) / total.base; } } }
{ "optimizer": { "enabled": true, "runs": 999999 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"IdenticalAddress","type":"error"},{"inputs":[],"name":"InsufficientAmountIn","type":"error"},{"inputs":[],"name":"InsufficientLiquidityMinted","type":"error"},{"inputs":[],"name":"InvalidAmounts","type":"error"},{"inputs":[],"name":"InvalidInputToken","type":"error"},{"inputs":[],"name":"InvalidOutputToken","type":"error"},{"inputs":[],"name":"InvalidSwapFee","type":"error"},{"inputs":[],"name":"Overflow","type":"error"},{"inputs":[],"name":"PoolUninitialized","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reserve0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reserve1","type":"uint256"}],"name":"Sync","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"barFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"barFeeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bento","outputs":[{"internalType":"contract IBentoBoxMinimal","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"burn","outputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IPool.TokenAmount[]","name":"withdrawnAmounts","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"burnSingle","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"flashSwap","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"finalAmountIn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"finalAmountOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAssets","outputs":[{"internalType":"address[]","name":"assets","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeReserves","outputs":[{"internalType":"uint256","name":"_nativeReserve0","type":"uint256"},{"internalType":"uint256","name":"_nativeReserve1","type":"uint256"},{"internalType":"uint32","name":"_blockTimestampLast","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserves","outputs":[{"internalType":"uint112","name":"_reserve0","type":"uint112"},{"internalType":"uint112","name":"_reserve1","type":"uint112"},{"internalType":"uint32","name":"_blockTimestampLast","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"kLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"masterDeployer","outputs":[{"internalType":"contract IMasterDeployer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mint","outputs":[{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"poolIdentifier","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price0CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price1CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"swap","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateBarParameters","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101a060405260016006553480156200001757600080fd5b50604080518082018252601f81527f537573686920436f6e7374616e742050726f64756374204c5020546f6b656e0060208083019182528351808501909452600584526405343504c560dc1b9084015281519192916012916200007e91600091906200042d565b508151620000949060019060208501906200042d565b5060ff81166080524660a052620000aa62000391565b60c08181525050505050600080336001600160a01b031663d039f6226040518163ffffffff1660e01b8152600401600060405180830381865afa158015620000f6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000120919081019062000514565b915091506000806000808580602001905181019062000140919062000605565b929650909450925090506001600160a01b038416620001725760405163d92e233d60e01b815260040160405180910390fd5b826001600160a01b0316846001600160a01b03161415620001a65760405163065af08d60e01b815260040160405180910390fd5b612710821115620001ca5760405163da7459b760e01b815260040160405180910390fd5b6001600160a01b03808516610160528381166101805260e083905261271083900361010052604080516360a56c0160e11b815290519187169163c14ad802916004808201926020929091908290030181865afa1580156200022f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000255919062000665565b600781905550846001600160a01b0316630c0a0cd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200029a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002c091906200067f565b600860006101000a8154816001600160a01b0302191690836001600160a01b03160217905550846001600160a01b0316634da318276040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000325573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200034b91906200067f565b6001600160a01b039081166101205285166101405280156200038557600c80546001600160e01b0316600160e01b4263ffffffff16021790555b50505050505062000787565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051620003c59190620006e3565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b8280546200043b90620006a6565b90600052602060002090601f0160209004810192826200045f5760008555620004aa565b82601f106200047a57805160ff1916838001178555620004aa565b82800160010185558215620004aa579182015b82811115620004aa5782518255916020019190600101906200048d565b50620004b8929150620004bc565b5090565b5b80821115620004b85760008155600101620004bd565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114620004ff57600080fd5b50565b80516200050f81620004e9565b919050565b600080604083850312156200052857600080fd5b82516001600160401b03808211156200054057600080fd5b818501915085601f8301126200055557600080fd5b8151818111156200056a576200056a620004d3565b604051601f8201601f19908116603f01168101908382118183101715620005955762000595620004d3565b81604052828152602093508884848701011115620005b257600080fd5b600091505b82821015620005d65784820184015181830185015290830190620005b7565b82821115620005e85760008484830101525b9550620005fa91505085820162000502565b925050509250929050565b600080600080608085870312156200061c57600080fd5b84516200062981620004e9565b60208601519094506200063c81620004e9565b60408601516060870151919450925080151581146200065a57600080fd5b939692955090935050565b6000602082840312156200067857600080fd5b5051919050565b6000602082840312156200069257600080fd5b81516200069f81620004e9565b9392505050565b600181811c90821680620006bb57607f821691505b60208210811415620006dd57634e487b7160e01b600052602260045260246000fd5b50919050565b600080835481600182811c9150808316806200070057607f831692505b60208084108214156200072157634e487b7160e01b86526022600452602486fd5b8180156200073857600181146200074a5762000779565b60ff1986168952848901965062000779565b60008a81526020902060005b86811015620007715781548b82015290850190830162000756565b505084890196505b509498975050505050505050565b60805160a05160c05160e0516101005161012051610140516101605161018051613bad62000909600039600081816105ac015281816107df015281816108de0152818161098c015281816110350152818161113d015281816112f2015281816115d3015281816116420152818161195a01528181611aaa01528181611f03015281816121e40152818161226b0152612bb90152600081816103290152818161075b01528181610a4101528181610b4001528181611009015281816110d4015281816113780152818161157f015281816116f30152818161186301528181611a3c01528181611e84015281816122a00152818161235b0152612ade0152600081816105850152818161273e01526127d3015260008181610407015281816118b0015281816119a20152818161297101528181612a3e01528181612b110152612bea0152600081816128af01526131d601526000818161042e0152818161329801526133030152600061125901526000611224015260006103b30152613bad6000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c8063627dd56a11610145578063a8f1f52e116100bd578063cf58879a1161008c578063d505accf11610071578063d505accf146105ce578063dd62ed3e146105e3578063f1c49a391461060e57600080fd5b8063cf58879a14610580578063d21220a7146105a757600080fd5b8063a8f1f52e1461053e578063a9059cbb14610551578063af8c09bf14610564578063c14ad8021461057757600080fd5b80637464fc3d116101145780637ecebe00116100f95780637ecebe00146104ef57806395d89b411461050f578063a69840a81461051757600080fd5b80637464fc3d146104d35780637ba0e2e7146104dc57600080fd5b8063627dd56a1461046257806365dfc7671461047557806367e4ac2c1461049e57806370a08231146104b357600080fd5b80632a07b6c7116101d8578063499a3c50116101a757806354cf2aeb1161018c57806354cf2aeb146104295780635909c0d5146104505780635a3d54931461045957600080fd5b8063499a3c50146103ef5780634da318271461040257600080fd5b80632a07b6c71461036757806330adf81f14610387578063313ce567146103ae5780633644e515146103e757600080fd5b80630c0a0cd2116102145780630c0a0cd2146102df5780630dfe16811461032457806318160ddd1461034b57806323b872dd1461035457600080fd5b8063053da1c81461024657806306fdde031461026c5780630902f1ac14610281578063095ea7b3146102bc575b600080fd5b6102596102543660046133b1565b610616565b6040519081526020015b60405180910390f35b610274610bfc565b604051610263919061348e565b610289610c8a565b604080516dffffffffffffffffffffffffffff948516815293909216602084015263ffffffff1690820152606001610263565b6102cf6102ca3660046134cd565b610cf3565b6040519015158152602001610263565b6008546102ff9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610263565b6102ff7f000000000000000000000000000000000000000000000000000000000000000081565b61025960025481565b6102cf6103623660046134f9565b610d6c565b61037a6103753660046133b1565b610eb0565b604051610263919061353a565b6102597f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b6103d57f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff9091168152602001610263565b610259611220565b6102596103fd3660046133b1565b61127b565b6102ff7f000000000000000000000000000000000000000000000000000000000000000081565b6102597f000000000000000000000000000000000000000000000000000000000000000081565b61025960095481565b610259600a5481565b6102596104703660046133b1565b611433565b61047d6117c4565b60408051938452602084019290925263ffffffff1690820152606001610263565b6104a6611a1a565b604051610263919061359f565b6102596104c13660046135f9565b60036020526000908152604090205481565b610259600b5481565b6102596104ea3660046133b1565b611b19565b6102596104fd3660046135f9565b60056020526000908152604090205481565b610274611e00565b6102597f54726964656e743a436f6e7374616e7450726f6475637400000000000000000081565b61025961054c3660046133b1565b611e0d565b6102cf61055f3660046134cd565b611fb1565b6102596105723660046133b1565b612036565b61025960075481565b6102ff7f000000000000000000000000000000000000000000000000000000000000000081565b6102ff7f000000000000000000000000000000000000000000000000000000000000000081565b6105e16105dc366004613616565b612410565b005b6102596105f136600461368d565b600460209081526000928352604080842090915290825290205481565b6105e161273c565b6000600654600114610689576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b60026006556000808080806106a087890189613705565b945094509450945094506000806000610708600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b925092509250826dffffffffffffffffffffffffffff1660001415610759576040517fd886367700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16141561098a576107d885846dffffffffffffffffffffffffffff16846dffffffffffffffffffffffffffff166128a7565b98506108067f00000000000000000000000000000000000000000000000000000000000000008a898961290a565b6040517fbd50c7b1000000000000000000000000000000000000000000000000000000008152339063bd50c7b19061084290879060040161348e565b600060405180830381600087803b15801561085c57600080fd5b505af1158015610870573d6000803e3d6000fd5b5050505060008061087f612aa1565b9150915086856dffffffffffffffffffffffffffff16830310156108cf576040517fdf5b2ee600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108dc8282878787612c5d565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fcd3829a3813dc3cdd188fd3d01dcf3268c16be2fdd2dd21d0665418816e460628a8f60405161097b929190918252602082015260400190565b60405180910390a45050610be8565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614610a0f576040517f2df9739b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a3a85836dffffffffffffffffffffffffffff16856dffffffffffffffffffffffffffff166128a7565b9850610a687f00000000000000000000000000000000000000000000000000000000000000008a898961290a565b6040517fbd50c7b1000000000000000000000000000000000000000000000000000000008152339063bd50c7b190610aa490879060040161348e565b600060405180830381600087803b158015610abe57600080fd5b505af1158015610ad2573d6000803e3d6000fd5b50505050600080610ae1612aa1565b9150915086846dffffffffffffffffffffffffffff1682031015610b31576040517fdf5b2ee600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b3e8282878787612c5d565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fcd3829a3813dc3cdd188fd3d01dcf3268c16be2fdd2dd21d0665418816e460628a8f604051610bdd929190918252602082015260400190565b60405180910390a450505b505060016006555094979650505050505050565b60008054610c0990613814565b80601f0160208091040260200160405190810160405280929190818152602001828054610c3590613814565b8015610c825780601f10610c5757610100808354040283529160200191610c82565b820191906000526020600020905b815481529060010190602001808311610c6557829003601f168201915b505050505081565b6000806000610ce8600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b925092509250909192565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610d5b9086815260200190565b60405180910390a350600192915050565b73ffffffffffffffffffffffffffffffffffffffff831660009081526004602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610e0057610dce8382613897565b73ffffffffffffffffffffffffffffffffffffffff861660009081526004602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff851660009081526003602052604081208054859290610e35908490613897565b909155505073ffffffffffffffffffffffffffffffffffffffff808516600081815260036020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610e9d9087815260200190565b60405180910390a3506001949350505050565b6060600654600114610f1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610680565b6002600655600080610f32848601866138ae565b915091506000806000610f94600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b925092509250600080610fa5612aa1565b30600090815260036020526040812054929450909250610fc58787612f0a565b509050600081610fd586856138e3565b610fdf919061394f565b9050600082610fee86866138e3565b610ff8919061394f565b90506110043085612fe9565b6110307f0000000000000000000000000000000000000000000000000000000000000000838d8d61290a565b61105c7f0000000000000000000000000000000000000000000000000000000000000000828d8d61290a565b8186039550808503945061107386868b8b8b612c5d565b61108561108086886138e3565b61307f565b600b556040805160028082526060820190925290816020015b604080518082019091526000808252602082015281526020019060019003908161109e579050509b5060405180604001604052807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168152602001838152508c6000815181106111255761112561398a565b602002602001018190525060405180604001604052807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168152602001828152508c60018151811061118e5761118e61398a565b60200260200101819052508a73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d819364968484604051611201929190918252602082015260400190565b60405180910390a35050600160065550979a9950505050505050505050565b60007f0000000000000000000000000000000000000000000000000000000000000000461461125657611251613138565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b6000808061128b848601866134cd565b915091506000806112eb600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b50915091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156113765761136f83836dffffffffffffffffffffffffffff16836dffffffffffffffffffffffffffff166131d2565b9450611429565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146113fb576040517f0620202000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61142683826dffffffffffffffffffffffffffff16846dffffffffffffffffffffffffffff166131d2565b94505b5050505092915050565b60006006546001146114a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610680565b6002600655600080806114b6858701876139b9565b925092509250600080600061151a600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b925092509250826dffffffffffffffffffffffffffff166000141561156b576040517fd886367700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080611576612aa1565b915091506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415611640577f00000000000000000000000000000000000000000000000000000000000000009050866dffffffffffffffffffffffffffff168403915061163482886dffffffffffffffffffffffffffff16886dffffffffffffffffffffffffffff166128a7565b9a508a8303925061172c565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16146116c5576040517f2df9739b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600c546dffffffffffffffffffffffffffff6e01000000000000000000000000000090910481168203907f000000000000000000000000000000000000000000000000000000000000000090611724908390888116908a166128a7565b9a508a840393505b611738818c8b8b61290a565b6117458484898989612c5d565b8073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fcd3829a3813dc3cdd188fd3d01dcf3268c16be2fdd2dd21d0665418816e46062858f604051610bdd929190918252602082015260400190565b600080600080600080611826600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b6040517f5662311800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526dffffffffffffffffffffffffffff851660248301526000604483015293965091945092507f000000000000000000000000000000000000000000000000000000000000000090911690635662311890606401602060405180830381865afa1580156118f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191d9190613a00565b6040517f5662311800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526dffffffffffffffffffffffffffff85166024830152600060448301529197507f000000000000000000000000000000000000000000000000000000000000000090911690635662311890606401602060405180830381865afa1580156119eb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0f9190613a00565b959690945092505050565b60408051600280825260608083018452926020830190803683370190505090507f000000000000000000000000000000000000000000000000000000000000000081600081518110611a6e57611a6e61398a565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507f000000000000000000000000000000000000000000000000000000000000000081600181518110611adc57611adc61398a565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505090565b6000600654600114611b87576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610680565b60026006556000611b9a838501856135f9565b90506000806000611bfa600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b925092509250600080611c0b612aa1565b90925090506000611c1f61108083856138e3565b90506000611c3d6dffffffffffffffffffffffffffff881685613897565b90506000611c5b6dffffffffffffffffffffffffffff881685613897565b9050600080611c8c84848c6dffffffffffffffffffffffffffff168c6dffffffffffffffffffffffffffff1661323d565b9092509050611c9b828b613a19565b9950611ca7818a613a19565b9850600080611cb68c8c612f0a565b915091508160001415611d2557851580611cce575084155b15611d05576040517fd856fc5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d116103e888613897565b9d50611d2060006103e8613340565b611d41565b80870381611d3384836138e3565b611d3d919061394f565b9e50505b8d611d78576040517fd226f9d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d828d8f613340565b611d8f89898e8e8e612c5d565b600b879055604080518781526020810187905273ffffffffffffffffffffffffffffffffffffffff8f169133917fdbba30eb0402b389513e87f51f4db2db80bed454384ec6925a24097c3548a02a910160405180910390a35050600160065550999c9b505050505050505050505050565b60018054610c0990613814565b60008080611e1d848601866134cd565b91509150600080611e7d600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b50915091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415611f015761136f83836dffffffffffffffffffffffffffff16836dffffffffffffffffffffffffffff166128a7565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614611f86576040517f2df9739b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61142683826dffffffffffffffffffffffffffff16846dffffffffffffffffffffffffffff166128a7565b33600090815260036020526040812080548391908390611fd2908490613897565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600081815260036020526040908190208054850190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610d5b9086815260200190565b60006006546001146120a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610680565b6002600655600080806120b9858701876139b9565b925092509250600080600061211d600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b30600090815260036020526040812054939650919450925061213f8585612f0a565b50905060008161215f6dffffffffffffffffffffffffffff8816856138e3565b612169919061394f565b90506000826121886dffffffffffffffffffffffffffff8816866138e3565b612192919061394f565b90506121d56121b1826dffffffffffffffffffffffffffff8916613897565b6121cb846dffffffffffffffffffffffffffff8b16613897565b61108091906138e3565b600b556121e23085612fe9565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16141561229e576122658283896dffffffffffffffffffffffffffff160383896dffffffffffffffffffffffffffff16036128a7565b016122927f0000000000000000000000000000000000000000000000000000000000000000828b8b61290a565b809a5060009150612389565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff1614612323576040517f0620202000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123528182886dffffffffffffffffffffffffffff1603848a6dffffffffffffffffffffffffffff16036128a7565b820191506123827f0000000000000000000000000000000000000000000000000000000000000000838b8b61290a565b5098508860005b600080612394612aa1565b915091506123a582828b8b8b612c5d565b604080518581526020810185905273ffffffffffffffffffffffffffffffffffffffff8d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a35050600160065550989b9a5050505050505050505050565b4284101561247a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f455850495245440000000000000000006044820152606401610680565b6000612484611220565b73ffffffffffffffffffffffffffffffffffffffff89811660008181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938c166060840152608083018b905260a083019390935260c08083018a90528151808403909101815260e0830190915280519201919091207f190100000000000000000000000000000000000000000000000000000000000061010083015261010282019290925261012281019190915261014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa1580156125e3573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81161580159061265e57508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b6126c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f494e56414c49445f5349474e45520000000000000000000000000000000000006044820152606401610680565b73ffffffffffffffffffffffffffffffffffffffff90811660009081526004602090815260408083208b8516808552908352928190208a905551898152919350918a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663c14ad8026040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127cb9190613a00565b6007819055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630c0a0cd26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561283c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128609190613a4b565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000806128d47f0000000000000000000000000000000000000000000000000000000000000000866138e3565b9050806128e3612710866138e3565b6128ed9190613a68565b6128f784836138e3565b612901919061394f565b95945050505050565b80156129e4576040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152838116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af11580156129b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129dd9190613a80565b5050612a9b565b6040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612a8257600080fd5b505af1158015612a96573d6000803e3d6000fd5b505050505b50505050565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116600483015230602483015260009182917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612b58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b7c9190613a00565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301523060248301529193507f00000000000000000000000000000000000000000000000000000000000000009091169063f7888aec90604401602060405180830381865afa158015612c33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c579190613a00565b90509091565b6dffffffffffffffffffffffffffff851180612c8657506dffffffffffffffffffffffffffff84115b15612cbd576040517f35278d1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8116612d1f57600c80546dffffffffffffffffffffffffffff8681166e010000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090921690881617179055612eca565b4263ffffffff80821690831614801590612d4857506dffffffffffffffffffffffffffff841615155b8015612d6357506dffffffffffffffffffffffffffff831615155b15612e285781810360006dffffffffffffffffffffffffffff86167bffffffffffffffffffffffffffff0000000000000000000000000000607087901b1681612dae57612dae613920565b600980549290910463ffffffff851681029092019055905060006dffffffffffffffffffffffffffff8616607088901b7bffffffffffffffffffffffffffff00000000000000000000000000001681612e0957612e09613920565b0490508263ffffffff168102600a600082825401925050819055505050505b600c805463ffffffff9092167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff6dffffffffffffffffffffffffffff8881166e010000000000000000000000000000027fffffffff00000000000000000000000000000000000000000000000000000000909516908a161793909317929092169190911790555b60408051868152602081018690527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a15050505050565b600254600b546000908015612fe157612f396110806dffffffffffffffffffffffffffff8087169088166138e3565b915080821115612fe157600754600081612f538486613897565b612f5d90876138e3565b612f6791906138e3565b90506000612f7584846138e3565b85612f8285612710613897565b612f8c91906138e3565b612f969190613a68565b90506000612fa4828461394f565b90508015612fdc57600854612fcf9073ffffffffffffffffffffffffffffffffffffffff1682613340565b612fd98188613a68565b96505b505050505b509250929050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260408120805483929061301e908490613897565b909155505060028054829003905560405181815260009073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b60b5817101000000000000000000000000000000000081106130a65760409190911b9060801c5b690100000000000000000081106130c25760209190911b9060401c5b6501000000000081106130da5760109190911b9060201c5b630100000081106130f05760089190911b9060101c5b62010000010260121c80820401600190811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c8082048111156131335781045b919050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f600060405161316a9190613aa4565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b60007f00000000000000000000000000000000000000000000000000000000000000006131ff8584613897565b61320991906138e3565b61271061321686866138e3565b61322091906138e3565b61322a919061394f565b613235906001613a68565b949350505050565b60008083158061324b575082155b1561325b57506000905080613337565b60008461326885896138e3565b613272919061394f565b90508581116132cd5761328861271060026138e3565b6132928288613897565b6132bc907f00000000000000000000000000000000000000000000000000000000000000006138e3565b6132c6919061394f565b9150613335565b6000846132da87896138e3565b6132e4919061394f565b90506132f361271060026138e3565b6132fd828a613897565b613327907f00000000000000000000000000000000000000000000000000000000000000006138e3565b613331919061394f565b9350505b505b94509492505050565b80600260008282546133529190613a68565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152600360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101613073565b600080602083850312156133c457600080fd5b823567ffffffffffffffff808211156133dc57600080fd5b818501915085601f8301126133f057600080fd5b8135818111156133ff57600080fd5b86602082850101111561341157600080fd5b60209290920196919550909350505050565b6000815180845260005b818110156134495760208185018101518683018201520161342d565b8181111561345b576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006134a16020830184613423565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146134ca57600080fd5b50565b600080604083850312156134e057600080fd5b82356134eb816134a8565b946020939093013593505050565b60008060006060848603121561350e57600080fd5b8335613519816134a8565b92506020840135613529816134a8565b929592945050506040919091013590565b602080825282518282018190526000919060409081850190868401855b82811015613592578151805173ffffffffffffffffffffffffffffffffffffffff168552860151868501529284019290850190600101613557565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156135ed57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016135bb565b50909695505050505050565b60006020828403121561360b57600080fd5b81356134a1816134a8565b600080600080600080600060e0888a03121561363157600080fd5b873561363c816134a8565b9650602088013561364c816134a8565b95506040880135945060608801359350608088013560ff8116811461367057600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156136a057600080fd5b82356136ab816134a8565b915060208301356136bb816134a8565b809150509250929050565b8035801515811461313357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080600060a0868803121561371d57600080fd5b8535613728816134a8565b94506020860135613738816134a8565b9350613746604087016136c6565b925060608601359150608086013567ffffffffffffffff8082111561376a57600080fd5b818801915088601f83011261377e57600080fd5b813581811115613790576137906136d6565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156137d6576137d66136d6565b816040528281528b60208487010111156137ef57600080fd5b8260208601602083013760006020848301015280955050505050509295509295909350565b600181811c9082168061382857607f821691505b60208210811415613862577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156138a9576138a9613868565b500390565b600080604083850312156138c157600080fd5b82356138cc816134a8565b91506138da602084016136c6565b90509250929050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561391b5761391b613868565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613985577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000806000606084860312156139ce57600080fd5b83356139d9816134a8565b925060208401356139e9816134a8565b91506139f7604085016136c6565b90509250925092565b600060208284031215613a1257600080fd5b5051919050565b60006dffffffffffffffffffffffffffff808316818516808303821115613a4257613a42613868565b01949350505050565b600060208284031215613a5d57600080fd5b81516134a1816134a8565b60008219821115613a7b57613a7b613868565b500190565b60008060408385031215613a9357600080fd5b505080516020909101519092909150565b600080835481600182811c915080831680613ac057607f831692505b6020808410821415613af9577f4e487b710000000000000000000000000000000000000000000000000000000086526022600452602486fd5b818015613b0d5760018114613b3c57613b69565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00861689528489019650613b69565b60008a81526020902060005b86811015613b615781548b820152908501908301613b48565b505084890196505b50949897505050505050505056fea2646970667358221220860e8cf8543ab713382b6536fca66307d46924b935d4b3b4d13f57dd57da62ae64736f6c634300080a0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102415760003560e01c8063627dd56a11610145578063a8f1f52e116100bd578063cf58879a1161008c578063d505accf11610071578063d505accf146105ce578063dd62ed3e146105e3578063f1c49a391461060e57600080fd5b8063cf58879a14610580578063d21220a7146105a757600080fd5b8063a8f1f52e1461053e578063a9059cbb14610551578063af8c09bf14610564578063c14ad8021461057757600080fd5b80637464fc3d116101145780637ecebe00116100f95780637ecebe00146104ef57806395d89b411461050f578063a69840a81461051757600080fd5b80637464fc3d146104d35780637ba0e2e7146104dc57600080fd5b8063627dd56a1461046257806365dfc7671461047557806367e4ac2c1461049e57806370a08231146104b357600080fd5b80632a07b6c7116101d8578063499a3c50116101a757806354cf2aeb1161018c57806354cf2aeb146104295780635909c0d5146104505780635a3d54931461045957600080fd5b8063499a3c50146103ef5780634da318271461040257600080fd5b80632a07b6c71461036757806330adf81f14610387578063313ce567146103ae5780633644e515146103e757600080fd5b80630c0a0cd2116102145780630c0a0cd2146102df5780630dfe16811461032457806318160ddd1461034b57806323b872dd1461035457600080fd5b8063053da1c81461024657806306fdde031461026c5780630902f1ac14610281578063095ea7b3146102bc575b600080fd5b6102596102543660046133b1565b610616565b6040519081526020015b60405180910390f35b610274610bfc565b604051610263919061348e565b610289610c8a565b604080516dffffffffffffffffffffffffffff948516815293909216602084015263ffffffff1690820152606001610263565b6102cf6102ca3660046134cd565b610cf3565b6040519015158152602001610263565b6008546102ff9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610263565b6102ff7f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c3160781565b61025960025481565b6102cf6103623660046134f9565b610d6c565b61037a6103753660046133b1565b610eb0565b604051610263919061353a565b6102597f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b6103d57f000000000000000000000000000000000000000000000000000000000000001281565b60405160ff9091168152602001610263565b610259611220565b6102596103fd3660046133b1565b61127b565b6102ff7f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c481565b6102597f000000000000000000000000000000000000000000000000000000000000000181565b61025960095481565b610259600a5481565b6102596104703660046133b1565b611433565b61047d6117c4565b60408051938452602084019290925263ffffffff1690820152606001610263565b6104a6611a1a565b604051610263919061359f565b6102596104c13660046135f9565b60036020526000908152604090205481565b610259600b5481565b6102596104ea3660046133b1565b611b19565b6102596104fd3660046135f9565b60056020526000908152604090205481565b610274611e00565b6102597f54726964656e743a436f6e7374616e7450726f6475637400000000000000000081565b61025961054c3660046133b1565b611e0d565b6102cf61055f3660046134cd565b611fb1565b6102596105723660046133b1565b612036565b61025960075481565b6102ff7f000000000000000000000000caabdd9cf4b61813d4a52f980d6bc1b713fe66f581565b6102ff7f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e5881565b6105e16105dc366004613616565b612410565b005b6102596105f136600461368d565b600460209081526000928352604080842090915290825290205481565b6105e161273c565b6000600654600114610689576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b60026006556000808080806106a087890189613705565b945094509450945094506000806000610708600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b925092509250826dffffffffffffffffffffffffffff1660001415610759576040517fd886367700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c3160773ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16141561098a576107d885846dffffffffffffffffffffffffffff16846dffffffffffffffffffffffffffff166128a7565b98506108067f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e588a898961290a565b6040517fbd50c7b1000000000000000000000000000000000000000000000000000000008152339063bd50c7b19061084290879060040161348e565b600060405180830381600087803b15801561085c57600080fd5b505af1158015610870573d6000803e3d6000fd5b5050505060008061087f612aa1565b9150915086856dffffffffffffffffffffffffffff16830310156108cf576040517fdf5b2ee600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108dc8282878787612c5d565b7f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e5873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fcd3829a3813dc3cdd188fd3d01dcf3268c16be2fdd2dd21d0665418816e460628a8f60405161097b929190918252602082015260400190565b60405180910390a45050610be8565b7f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e5873ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614610a0f576040517f2df9739b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a3a85836dffffffffffffffffffffffffffff16856dffffffffffffffffffffffffffff166128a7565b9850610a687f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c316078a898961290a565b6040517fbd50c7b1000000000000000000000000000000000000000000000000000000008152339063bd50c7b190610aa490879060040161348e565b600060405180830381600087803b158015610abe57600080fd5b505af1158015610ad2573d6000803e3d6000fd5b50505050600080610ae1612aa1565b9150915086846dffffffffffffffffffffffffffff1682031015610b31576040517fdf5b2ee600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b3e8282878787612c5d565b7f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c3160773ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fcd3829a3813dc3cdd188fd3d01dcf3268c16be2fdd2dd21d0665418816e460628a8f604051610bdd929190918252602082015260400190565b60405180910390a450505b505060016006555094979650505050505050565b60008054610c0990613814565b80601f0160208091040260200160405190810160405280929190818152602001828054610c3590613814565b8015610c825780601f10610c5757610100808354040283529160200191610c82565b820191906000526020600020905b815481529060010190602001808311610c6557829003601f168201915b505050505081565b6000806000610ce8600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b925092509250909192565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610d5b9086815260200190565b60405180910390a350600192915050565b73ffffffffffffffffffffffffffffffffffffffff831660009081526004602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610e0057610dce8382613897565b73ffffffffffffffffffffffffffffffffffffffff861660009081526004602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff851660009081526003602052604081208054859290610e35908490613897565b909155505073ffffffffffffffffffffffffffffffffffffffff808516600081815260036020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610e9d9087815260200190565b60405180910390a3506001949350505050565b6060600654600114610f1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610680565b6002600655600080610f32848601866138ae565b915091506000806000610f94600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b925092509250600080610fa5612aa1565b30600090815260036020526040812054929450909250610fc58787612f0a565b509050600081610fd586856138e3565b610fdf919061394f565b9050600082610fee86866138e3565b610ff8919061394f565b90506110043085612fe9565b6110307f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c31607838d8d61290a565b61105c7f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e58828d8d61290a565b8186039550808503945061107386868b8b8b612c5d565b61108561108086886138e3565b61307f565b600b556040805160028082526060820190925290816020015b604080518082019091526000808252602082015281526020019060019003908161109e579050509b5060405180604001604052807f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c3160773ffffffffffffffffffffffffffffffffffffffff168152602001838152508c6000815181106111255761112561398a565b602002602001018190525060405180604001604052807f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e5873ffffffffffffffffffffffffffffffffffffffff168152602001828152508c60018151811061118e5761118e61398a565b60200260200101819052508a73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d819364968484604051611201929190918252602082015260400190565b60405180910390a35050600160065550979a9950505050505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000a461461125657611251613138565b905090565b507f270515d782c90a37cfeced856215927af70d406c21f44c3102a7134eca03260190565b6000808061128b848601866134cd565b915091506000806112eb600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b50915091507f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e5873ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156113765761136f83836dffffffffffffffffffffffffffff16836dffffffffffffffffffffffffffff166131d2565b9450611429565b7f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c3160773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146113fb576040517f0620202000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61142683826dffffffffffffffffffffffffffff16846dffffffffffffffffffffffffffff166131d2565b94505b5050505092915050565b60006006546001146114a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610680565b6002600655600080806114b6858701876139b9565b925092509250600080600061151a600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b925092509250826dffffffffffffffffffffffffffff166000141561156b576040517fd886367700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080611576612aa1565b915091506000807f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c3160773ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415611640577f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e589050866dffffffffffffffffffffffffffff168403915061163482886dffffffffffffffffffffffffffff16886dffffffffffffffffffffffffffff166128a7565b9a508a8303925061172c565b7f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e5873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16146116c5576040517f2df9739b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600c546dffffffffffffffffffffffffffff6e01000000000000000000000000000090910481168203907f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c3160790611724908390888116908a166128a7565b9a508a840393505b611738818c8b8b61290a565b6117458484898989612c5d565b8073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fcd3829a3813dc3cdd188fd3d01dcf3268c16be2fdd2dd21d0665418816e46062858f604051610bdd929190918252602082015260400190565b600080600080600080611826600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b6040517f5662311800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c31607811660048301526dffffffffffffffffffffffffffff851660248301526000604483015293965091945092507f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c490911690635662311890606401602060405180830381865afa1580156118f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191d9190613a00565b6040517f5662311800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e58811660048301526dffffffffffffffffffffffffffff85166024830152600060448301529197507f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c490911690635662311890606401602060405180830381865afa1580156119eb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0f9190613a00565b959690945092505050565b60408051600280825260608083018452926020830190803683370190505090507f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c3160781600081518110611a6e57611a6e61398a565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e5881600181518110611adc57611adc61398a565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505090565b6000600654600114611b87576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610680565b60026006556000611b9a838501856135f9565b90506000806000611bfa600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b925092509250600080611c0b612aa1565b90925090506000611c1f61108083856138e3565b90506000611c3d6dffffffffffffffffffffffffffff881685613897565b90506000611c5b6dffffffffffffffffffffffffffff881685613897565b9050600080611c8c84848c6dffffffffffffffffffffffffffff168c6dffffffffffffffffffffffffffff1661323d565b9092509050611c9b828b613a19565b9950611ca7818a613a19565b9850600080611cb68c8c612f0a565b915091508160001415611d2557851580611cce575084155b15611d05576040517fd856fc5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d116103e888613897565b9d50611d2060006103e8613340565b611d41565b80870381611d3384836138e3565b611d3d919061394f565b9e50505b8d611d78576040517fd226f9d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d828d8f613340565b611d8f89898e8e8e612c5d565b600b879055604080518781526020810187905273ffffffffffffffffffffffffffffffffffffffff8f169133917fdbba30eb0402b389513e87f51f4db2db80bed454384ec6925a24097c3548a02a910160405180910390a35050600160065550999c9b505050505050505050505050565b60018054610c0990613814565b60008080611e1d848601866134cd565b91509150600080611e7d600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b50915091507f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c3160773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415611f015761136f83836dffffffffffffffffffffffffffff16836dffffffffffffffffffffffffffff166128a7565b7f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e5873ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614611f86576040517f2df9739b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61142683826dffffffffffffffffffffffffffff16846dffffffffffffffffffffffffffff166128a7565b33600090815260036020526040812080548391908390611fd2908490613897565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600081815260036020526040908190208054850190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610d5b9086815260200190565b60006006546001146120a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610680565b6002600655600080806120b9858701876139b9565b925092509250600080600061211d600c546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b30600090815260036020526040812054939650919450925061213f8585612f0a565b50905060008161215f6dffffffffffffffffffffffffffff8816856138e3565b612169919061394f565b90506000826121886dffffffffffffffffffffffffffff8816866138e3565b612192919061394f565b90506121d56121b1826dffffffffffffffffffffffffffff8916613897565b6121cb846dffffffffffffffffffffffffffff8b16613897565b61108091906138e3565b600b556121e23085612fe9565b7f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e5873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16141561229e576122658283896dffffffffffffffffffffffffffff160383896dffffffffffffffffffffffffffff16036128a7565b016122927f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e58828b8b61290a565b809a5060009150612389565b7f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c3160773ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff1614612323576040517f0620202000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123528182886dffffffffffffffffffffffffffff1603848a6dffffffffffffffffffffffffffff16036128a7565b820191506123827f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c31607838b8b61290a565b5098508860005b600080612394612aa1565b915091506123a582828b8b8b612c5d565b604080518581526020810185905273ffffffffffffffffffffffffffffffffffffffff8d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a35050600160065550989b9a5050505050505050505050565b4284101561247a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f455850495245440000000000000000006044820152606401610680565b6000612484611220565b73ffffffffffffffffffffffffffffffffffffffff89811660008181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938c166060840152608083018b905260a083019390935260c08083018a90528151808403909101815260e0830190915280519201919091207f190100000000000000000000000000000000000000000000000000000000000061010083015261010282019290925261012281019190915261014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa1580156125e3573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81161580159061265e57508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b6126c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f494e56414c49445f5349474e45520000000000000000000000000000000000006044820152606401610680565b73ffffffffffffffffffffffffffffffffffffffff90811660009081526004602090815260408083208b8516808552908352928190208a905551898152919350918a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b7f000000000000000000000000caabdd9cf4b61813d4a52f980d6bc1b713fe66f573ffffffffffffffffffffffffffffffffffffffff1663c14ad8026040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127cb9190613a00565b6007819055507f000000000000000000000000caabdd9cf4b61813d4a52f980d6bc1b713fe66f573ffffffffffffffffffffffffffffffffffffffff16630c0a0cd26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561283c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128609190613a4b565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000806128d47f000000000000000000000000000000000000000000000000000000000000270f866138e3565b9050806128e3612710866138e3565b6128ed9190613a68565b6128f784836138e3565b612901919061394f565b95945050505050565b80156129e4576040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152838116604483015260006064830152608482018590527f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c416906397da6d309060a40160408051808303816000875af11580156129b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129dd9190613a80565b5050612a9b565b6040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301528381166044830152606482018590527f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c4169063f18d03cc90608401600060405180830381600087803b158015612a8257600080fd5b505af1158015612a96573d6000803e3d6000fd5b505050505b50505050565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c316078116600483015230602483015260009182917f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c4169063f7888aec90604401602060405180830381865afa158015612b58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b7c9190613a00565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e58811660048301523060248301529193507f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c49091169063f7888aec90604401602060405180830381865afa158015612c33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c579190613a00565b90509091565b6dffffffffffffffffffffffffffff851180612c8657506dffffffffffffffffffffffffffff84115b15612cbd576040517f35278d1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8116612d1f57600c80546dffffffffffffffffffffffffffff8681166e010000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090921690881617179055612eca565b4263ffffffff80821690831614801590612d4857506dffffffffffffffffffffffffffff841615155b8015612d6357506dffffffffffffffffffffffffffff831615155b15612e285781810360006dffffffffffffffffffffffffffff86167bffffffffffffffffffffffffffff0000000000000000000000000000607087901b1681612dae57612dae613920565b600980549290910463ffffffff851681029092019055905060006dffffffffffffffffffffffffffff8616607088901b7bffffffffffffffffffffffffffff00000000000000000000000000001681612e0957612e09613920565b0490508263ffffffff168102600a600082825401925050819055505050505b600c805463ffffffff9092167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff6dffffffffffffffffffffffffffff8881166e010000000000000000000000000000027fffffffff00000000000000000000000000000000000000000000000000000000909516908a161793909317929092169190911790555b60408051868152602081018690527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a15050505050565b600254600b546000908015612fe157612f396110806dffffffffffffffffffffffffffff8087169088166138e3565b915080821115612fe157600754600081612f538486613897565b612f5d90876138e3565b612f6791906138e3565b90506000612f7584846138e3565b85612f8285612710613897565b612f8c91906138e3565b612f969190613a68565b90506000612fa4828461394f565b90508015612fdc57600854612fcf9073ffffffffffffffffffffffffffffffffffffffff1682613340565b612fd98188613a68565b96505b505050505b509250929050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260408120805483929061301e908490613897565b909155505060028054829003905560405181815260009073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b60b5817101000000000000000000000000000000000081106130a65760409190911b9060801c5b690100000000000000000081106130c25760209190911b9060401c5b6501000000000081106130da5760109190911b9060201c5b630100000081106130f05760089190911b9060101c5b62010000010260121c80820401600190811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c8082048111156131335781045b919050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f600060405161316a9190613aa4565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b60007f000000000000000000000000000000000000000000000000000000000000270f6131ff8584613897565b61320991906138e3565b61271061321686866138e3565b61322091906138e3565b61322a919061394f565b613235906001613a68565b949350505050565b60008083158061324b575082155b1561325b57506000905080613337565b60008461326885896138e3565b613272919061394f565b90508581116132cd5761328861271060026138e3565b6132928288613897565b6132bc907f00000000000000000000000000000000000000000000000000000000000000016138e3565b6132c6919061394f565b9150613335565b6000846132da87896138e3565b6132e4919061394f565b90506132f361271060026138e3565b6132fd828a613897565b613327907f00000000000000000000000000000000000000000000000000000000000000016138e3565b613331919061394f565b9350505b505b94509492505050565b80600260008282546133529190613a68565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152600360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101613073565b600080602083850312156133c457600080fd5b823567ffffffffffffffff808211156133dc57600080fd5b818501915085601f8301126133f057600080fd5b8135818111156133ff57600080fd5b86602082850101111561341157600080fd5b60209290920196919550909350505050565b6000815180845260005b818110156134495760208185018101518683018201520161342d565b8181111561345b576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006134a16020830184613423565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146134ca57600080fd5b50565b600080604083850312156134e057600080fd5b82356134eb816134a8565b946020939093013593505050565b60008060006060848603121561350e57600080fd5b8335613519816134a8565b92506020840135613529816134a8565b929592945050506040919091013590565b602080825282518282018190526000919060409081850190868401855b82811015613592578151805173ffffffffffffffffffffffffffffffffffffffff168552860151868501529284019290850190600101613557565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156135ed57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016135bb565b50909695505050505050565b60006020828403121561360b57600080fd5b81356134a1816134a8565b600080600080600080600060e0888a03121561363157600080fd5b873561363c816134a8565b9650602088013561364c816134a8565b95506040880135945060608801359350608088013560ff8116811461367057600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156136a057600080fd5b82356136ab816134a8565b915060208301356136bb816134a8565b809150509250929050565b8035801515811461313357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080600060a0868803121561371d57600080fd5b8535613728816134a8565b94506020860135613738816134a8565b9350613746604087016136c6565b925060608601359150608086013567ffffffffffffffff8082111561376a57600080fd5b818801915088601f83011261377e57600080fd5b813581811115613790576137906136d6565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156137d6576137d66136d6565b816040528281528b60208487010111156137ef57600080fd5b8260208601602083013760006020848301015280955050505050509295509295909350565b600181811c9082168061382857607f821691505b60208210811415613862577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156138a9576138a9613868565b500390565b600080604083850312156138c157600080fd5b82356138cc816134a8565b91506138da602084016136c6565b90509250929050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561391b5761391b613868565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613985577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000806000606084860312156139ce57600080fd5b83356139d9816134a8565b925060208401356139e9816134a8565b91506139f7604085016136c6565b90509250925092565b600060208284031215613a1257600080fd5b5051919050565b60006dffffffffffffffffffffffffffff808316818516808303821115613a4257613a42613868565b01949350505050565b600060208284031215613a5d57600080fd5b81516134a1816134a8565b60008219821115613a7b57613a7b613868565b500190565b60008060408385031215613a9357600080fd5b505080516020909101519092909150565b600080835481600182811c915080831680613ac057607f831692505b6020808410821415613af9577f4e487b710000000000000000000000000000000000000000000000000000000086526022600452602486fd5b818015613b0d5760018114613b3c57613b69565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00861689528489019650613b69565b60008a81526020902060005b86811015613b615781548b820152908501908301613b48565b505084890196505b50949897505050505050505056fea2646970667358221220860e8cf8543ab713382b6536fca66307d46924b935d4b3b4d13f57dd57da62ae64736f6c634300080a0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
[ 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.