Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
13303754 | 4 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
RainbowRouter
Compiler Version
v0.8.11+commit.d7f03943
Contract Source Code (Solidity)
/** *Submitted for verification at KatanaScan.com on 2025-10-09 */ /* ▐██▒ ███ ,╓, ▄▄ ,▄▄▄, .▄▄. ,╓, ▄▄▄ ██▌ ▄▄▄ ,▄▄▄, ,╓╓ ╓╓ ,╓ ██████ ███▀▀██⌐ ▐██⌐ ███▀▀███⌐ ████▀▀███ ╓██▀▀▀██▄`██▌ ▐██▌ ▐██ ███ ▄▄█████▌ ▐██⌐ ██▌ ▐██▌ ██▌ ║██⌐███ ▓██ ╙██▄█▌██▄██⌐ ██▌ ▐██▄▄███▌,▐██⌐ ██▌ ▐██▌ ███▓▄▄███ ╙██▄▄▄██▀ ║███¬╙███▌ ╙╙└ ╙╙▀╙─╙▀▀└"╙╙` ╙╙└ ╙╙" ╙╙`╙╙▀▀└ ╙╙▀▀╙` ╙╙└ ╙╙╙ _," _ _"""ⁿ=-, _ ⌠ _ __"=.__ ▐░...... _ _ "=._ ▐░░░░░░░░░░░░░░░░. "= _ ╚╩╩╩╩╩╩δφφφφ░░░░░░░░░░░ >__ ▐░░░░░░░░__ _ ╙╙╚╩φφ░░░░░░░ ^=_ ▐░░░░░░░░░░░░░░░,░ `╙╠φ░░░░░░░ ⁿ ▐░░░░░░░░░░░░░░░░░░░░._ `╚Åφ░░░░░ " _ ╚╠╠╠╠╠╠╠╬╬╬▒▒φ░░░░░░░░░░░░ ╙╠░░░░░ " ╚╝╝╝╝╝╝╝╬╬╬╠╢╬╠╬╠╬▒░░░░░░░░░░ "╚φ░░░░ ½_ ▐░░░░░░░░░░;░╙╙╝╬╠╬╠╠▒▒░░░░░░░░_ ╚φ░░░░ "_ ╚▒φφφ░░░░░░░░░░░░-╙╚╬╠╠╠╬▒░░░░░░░ `╠▒░░░░ , ╞╬╬╬╠╠╠╬╬╬╬▒φ▒░░░░░░░╙╚╬╬╠╬▒▒░░░░░ .╙╠░░░░ ≥ _▒░░░ΓΓ╙╙╙╚╩╬╠╬╠▒▒░░░░░░╙╬╬╠╬▒▒░░░░░' ╠▒░░░░ ≥ `╙ⁿⁿ≈≈σ╓░ '╙╙╚╬╠╬▒░░░░░░╙╬╬╠╬▒░░░░░ ╠▒░░░░ [ _╙Θ░ ░╙╠╠╬╬▒░░░░░╬╠╠╠▒▒░░░░ ╠▒░░░░ '_ _╙φ░'╙╠╠╬▒░░░░░╟╠╠╠▒░░░░░ _╠▒░░░ ░_ _`φ ░╚╬╠╠▒░░░░║╠╠╠▒░░░░░.`╠░░░░ [ _╚░⌡╚╠╬╬▒░░░░╠╠╠╬▒░░░░░ ╠▒░░░░ ░ _╙░⌡╚╠╠╬▒░░░"▒╠╠╬▒░░░░ ⌠╠░░░░ ⌡_ ╠ ░╠╠╠╬▒░░░║╠╬╠╬▒░░░ _╠▒░░░ Γ ▐░░░╠╠╠▒░░░╟╠╠╠╬▒░░░░ ╠▒░░░░ [ _░.░╠╠╠▒░░░▐╬╠╠╬▒░░░░[╠╬░░░░ │ _╙φ░╠╠╠╬▒░░▐╬╬╠╬╬▒░░░[╠╬░░░░ ░≥_ ____ ____ __ _______ ____ /$$$$$$ /$$$$$$ /$$ /$$__ $$ /$$__ $$ | $$ | $$ \__/ /$$ /$$ /$$ /$$$$$$ /$$$$$$ | $$ \ $$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ | $$$$$$ | $$ | $$ | $$ |____ $$ /$$__ $$ | $$$$$$$$ /$$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ |____ $$|_ $$_/ /$$__ $$ /$$__ $$ \____ $$| $$ | $$ | $$ /$$$$$$$| $$ \ $$ | $$__ $$| $$ \ $$| $$ \ $$| $$ \__/| $$$$$$$$| $$ \ $$ /$$$$$$$ | $$ | $$ \ $$| $$ \__/ /$$ \ $$| $$ | $$ | $$ /$$__ $$| $$ | $$ | $$ | $$| $$ | $$| $$ | $$| $$ | $$_____/| $$ | $$ /$$__ $$ | $$ /$$| $$ | $$| $$ | $$$$$$/| $$$$$/$$$$/| $$$$$$$| $$$$$$$/ | $$ | $$| $$$$$$$| $$$$$$$| $$ | $$$$$$$| $$$$$$$| $$$$$$$ | $$$$/| $$$$$$/| $$ \______/ \_____/\___/ \_______/| $$____/ |__/ |__/ \____ $$ \____ $$|__/ \_______/ \____ $$ \_______/ \___/ \______/ |__/ | $$ /$$ \ $$ /$$ \ $$ /$$ \ $$ | $$ | $$$$$$/| $$$$$$/ | $$$$$$/ |__/ \______/ \______/ \______/ */ //SPDX-License-Identifier: GPL-3.0 pragma solidity =0.8.11; /// @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); } } /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @author Modified from Gnosis (https://github.com/gnosis/gp-v2-contracts/blob/main/src/contracts/libraries/GPv2SafeERC20.sol) /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. library SafeTransferLib { /*/////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool callStatus; assembly { // Transfer the ETH and store if it succeeded or not. callStatus := call(gas(), to, amount, 0, 0, 0, 0) } require(callStatus, "ETH_TRANSFER_FAILED"); } /*/////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( ERC20 token, address from, address to, uint256 amount ) internal { bool callStatus; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata to memory piece by piece: mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) // Begin with the function selector. mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "from" argument. mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Finally append the "amount" argument. No mask as it's a full 32 byte value. // Call the token and store if it succeeded or not. // We use 100 because the calldata length is 4 + 32 * 3. callStatus := call(gas(), token, 0, freeMemoryPointer, 100, 0, 0) } require(didLastOptionalReturnCallSucceed(callStatus), "TRANSFER_FROM_FAILED"); } function safeTransfer( ERC20 token, address to, uint256 amount ) internal { bool callStatus; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata to memory piece by piece: mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) // Begin with the function selector. mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Finally append the "amount" argument. No mask as it's a full 32 byte value. // Call the token and store if it succeeded or not. // We use 68 because the calldata length is 4 + 32 * 2. callStatus := call(gas(), token, 0, freeMemoryPointer, 68, 0, 0) } require(didLastOptionalReturnCallSucceed(callStatus), "TRANSFER_FAILED"); } function safeApprove( ERC20 token, address to, uint256 amount ) internal { bool callStatus; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata to memory piece by piece: mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) // Begin with the function selector. mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Finally append the "amount" argument. No mask as it's a full 32 byte value. // Call the token and store if it succeeded or not. // We use 68 because the calldata length is 4 + 32 * 2. callStatus := call(gas(), token, 0, freeMemoryPointer, 68, 0, 0) } require(didLastOptionalReturnCallSucceed(callStatus), "APPROVE_FAILED"); } /*/////////////////////////////////////////////////////////////// INTERNAL HELPER LOGIC //////////////////////////////////////////////////////////////*/ function didLastOptionalReturnCallSucceed(bool callStatus) private pure returns (bool success) { assembly { // Get how many bytes the call returned. let returnDataSize := returndatasize() // If the call reverted: if iszero(callStatus) { // Copy the revert message into memory. returndatacopy(0, 0, returnDataSize) // Revert with the same message. revert(0, returnDataSize) } switch returnDataSize case 32 { // Copy the return data into memory. returndatacopy(0, 0, returnDataSize) // Set success to whether it returned true. success := iszero(iszero(mload(0))) } case 0 { // There was no return data. success := 1 } default { // It returned some malformed input. success := 0 } } } } // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) // OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol) /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); } interface IERC2612 is IERC20Metadata, IERC20Permit { function _nonces(address owner) external view returns (uint256); function version() external view returns (string memory); } /// @title Interface for permit /// @notice Interface used by DAI/CHAI for permit interface IERC20PermitAllowed { /// @notice Approve the spender to spend some tokens via the holder signature /// @dev This is the permit interface used by DAI and CHAI /// @param holder The address of the token holder, the token owner /// @param spender The address of the token spender /// @param nonce The holder's nonce, increases at each call to permit /// @param expiry The timestamp at which the permit is no longer valid /// @param allowed Boolean that sets approval amount, true for type(uint256).max and false for 0 /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` function permit( address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s ) external; } interface IDAI is IERC20Metadata, IERC20PermitAllowed { function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint256); function version() external view returns (string memory); } /// @title PermitHelper /// @dev Helper methods for using ERC20 Permit (ERC2612 or DAI/CHAI like) library PermitHelper { struct Permit { uint256 value; uint256 nonce; uint256 deadline; bool isDaiStylePermit; uint8 v; bytes32 r; bytes32 s; } /// @dev permit method helper that will handle both known implementations // DAI vs ERC2612 tokens /// @param permitData bytes containing the encoded permit signature /// @param tokenAddress address of the token that will be permitted /// @param holder address that holds the tokens to be permitted /// @param spender address that will be permitted to spend the tokens function permit( Permit memory permitData, address tokenAddress, address holder, address spender ) internal { if (permitData.isDaiStylePermit) { IDAI(tokenAddress).permit( holder, spender, permitData.nonce, permitData.deadline, true, permitData.v, permitData.r, permitData.s ); } else { IERC2612(tokenAddress).permit( holder, spender, permitData.value, permitData.deadline, permitData.v, permitData.r, permitData.s ); } } } /// @title Rainbow base aggregator contract contract BaseAggregator { /// @dev Used to prevent re-entrancy uint256 internal status; /// @dev Set of allowed swapTargets. mapping(address => bool) public swapTargets; /// @dev modifier that prevents reentrancy attacks on specific methods modifier nonReentrant() { // On the first call to nonReentrant, status will be 1 require(status != 2, "NON_REENTRANT"); // Any calls to nonReentrant after this point will fail status = 2; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) status = 1; } /// @dev modifier that ensures only approved targets can be called modifier onlyApprovedTarget(address target) { require(swapTargets[target], "TARGET_NOT_AUTH"); _; } /** EXTERNAL **/ /// @param buyTokenAddress the address of token that the user should receive /// @param target the address of the aggregator contract that will exec the swap /// @param swapCallData the calldata that will be passed to the aggregator contract /// @param feeAmount the amount of ETH that we will take as a fee function fillQuoteEthToToken( address buyTokenAddress, address payable target, bytes calldata swapCallData, uint256 feeAmount ) external payable nonReentrant onlyApprovedTarget(target) { // 1 - Get the initial balances uint256 initialTokenBalance = ERC20(buyTokenAddress).balanceOf( address(this) ); uint256 initialEthAmount = address(this).balance - msg.value; uint256 sellAmount = msg.value - feeAmount; // 2 - Call the encoded swap function call on the contract at `target`, // passing along any ETH attached to this function call to cover protocol fees // minus our fees, which are kept in this contract (bool success, bytes memory res) = target.call{value: sellAmount}( swapCallData ); // Get the revert message of the call and revert with it if the call failed if (!success) { assembly { let returndata_size := mload(res) revert(add(32, res), returndata_size) } } // 3 - Make sure we received the tokens { uint256 finalTokenBalance = ERC20(buyTokenAddress).balanceOf( address(this) ); require(initialTokenBalance < finalTokenBalance, "NO_TOKENS"); } // 4 - Send the received tokens back to the user SafeTransferLib.safeTransfer( ERC20(buyTokenAddress), msg.sender, ERC20(buyTokenAddress).balanceOf(address(this)) - initialTokenBalance ); // 5 - Return the remaining ETH to the user (if any) { uint256 finalEthAmount = address(this).balance - feeAmount; if (finalEthAmount > initialEthAmount) { SafeTransferLib.safeTransferETH( msg.sender, finalEthAmount - initialEthAmount ); } } } /// @param sellTokenAddress the address of token that the user is selling /// @param buyTokenAddress the address of token that the user should receive /// @param target the address of the aggregator contract that will exec the swap /// @param swapCallData the calldata that will be passed to the aggregator contract /// @param sellAmount the amount of tokens that the user is selling /// @param feeAmount the amount of the tokens to sell that we will take as a fee function fillQuoteTokenToToken( address sellTokenAddress, address buyTokenAddress, address payable target, bytes calldata swapCallData, uint256 sellAmount, uint256 feeAmount ) external payable nonReentrant onlyApprovedTarget(target) { _fillQuoteTokenToToken( sellTokenAddress, buyTokenAddress, target, swapCallData, sellAmount, feeAmount ); } /// @dev method that executes ERC20 to ERC20 token swaps with the ability to take a fee from the input // and accepts a signature to use permit, so the user doesn't have to make an previous approval transaction /// @param sellTokenAddress the address of token that the user is selling /// @param buyTokenAddress the address of token that the user should receive /// @param target the address of the aggregator contract that will exec the swap /// @param swapCallData the calldata that will be passed to the aggregator contract /// @param sellAmount the amount of tokens that the user is selling /// @param feeAmount the amount of the tokens to sell that we will take as a fee /// @param permitData struct containing the value, nonce, deadline, v, r and s values of the permit data function fillQuoteTokenToTokenWithPermit( address sellTokenAddress, address buyTokenAddress, address payable target, bytes calldata swapCallData, uint256 sellAmount, uint256 feeAmount, PermitHelper.Permit calldata permitData ) external payable nonReentrant onlyApprovedTarget(target) { // 1 - Apply permit PermitHelper.permit( permitData, sellTokenAddress, msg.sender, address(this) ); //2 - Call fillQuoteTokenToToken _fillQuoteTokenToToken( sellTokenAddress, buyTokenAddress, target, swapCallData, sellAmount, feeAmount ); } /// @dev method that executes ERC20 to ETH token swaps with the ability to take a fee from the output /// @param sellTokenAddress the address of token that the user is selling /// @param target the address of the aggregator contract that will exec the swap /// @param swapCallData the calldata that will be passed to the aggregator contract /// @param sellAmount the amount of tokens that the user is selling /// @param feePercentageBasisPoints the amount of ETH that we will take as a fee in 1e18 basis points (basis points with 4 decimals plus 14 extra decimals of precision) function fillQuoteTokenToEth( address sellTokenAddress, address payable target, bytes calldata swapCallData, uint256 sellAmount, uint256 feePercentageBasisPoints ) external payable nonReentrant onlyApprovedTarget(target) { _fillQuoteTokenToEth( sellTokenAddress, target, swapCallData, sellAmount, feePercentageBasisPoints ); } /// @dev method that executes ERC20 to ETH token swaps with the ability to take a fee from the output // and accepts a signature to use permit, so the user doesn't have to make an previous approval transaction /// @param sellTokenAddress the address of token that the user is selling /// @param target the address of the aggregator contract that will exec the swap /// @param swapCallData the calldata that will be passed to the aggregator contract /// @param sellAmount the amount of tokens that the user is selling /// @param feePercentageBasisPoints the amount of ETH that we will take as a fee in 1e18 basis points (basis points with 4 decimals plus 14 extra decimals of precision) /// @param permitData struct containing the amount, nonce, deadline, v, r and s values of the permit data function fillQuoteTokenToEthWithPermit( address sellTokenAddress, address payable target, bytes calldata swapCallData, uint256 sellAmount, uint256 feePercentageBasisPoints, PermitHelper.Permit calldata permitData ) external payable nonReentrant onlyApprovedTarget(target) { // 1 - Apply permit PermitHelper.permit( permitData, sellTokenAddress, msg.sender, address(this) ); // 2 - call fillQuoteTokenToEth _fillQuoteTokenToEth( sellTokenAddress, target, swapCallData, sellAmount, feePercentageBasisPoints ); } /** INTERNAL **/ /// @dev internal method that executes ERC20 to ETH token swaps with the ability to take a fee from the output function _fillQuoteTokenToEth( address sellTokenAddress, address payable target, bytes calldata swapCallData, uint256 sellAmount, uint256 feePercentageBasisPoints ) internal { // 1 - Get the initial ETH amount uint256 initialEthAmount = address(this).balance - msg.value; // 2 - Move the tokens to this contract // NOTE: This implicitly assumes that the the necessary approvals have been granted // from msg.sender to the BaseAggregator SafeTransferLib.safeTransferFrom( ERC20(sellTokenAddress), msg.sender, address(this), sellAmount ); // 3 - Approve the aggregator's contract to swap the tokens SafeTransferLib.safeApprove( ERC20(sellTokenAddress), target, sellAmount ); // 4 - Call the encoded swap function call on the contract at `target`, // passing along any ETH attached to this function call to cover protocol fees. (bool success, bytes memory res) = target.call{value: msg.value}( swapCallData ); // Get the revert message of the call and revert with it if the call failed if (!success) { assembly { let returndata_size := mload(res) revert(add(32, res), returndata_size) } } // 5 - Check that the tokens were fully spent during the swap uint256 allowance = ERC20(sellTokenAddress).allowance( address(this), target ); require(allowance == 0, "ALLOWANCE_NOT_ZERO"); // 6 - Subtract the fees and send the rest to the user // Fees will be held in this contract uint256 finalEthAmount = address(this).balance; uint256 ethDiff = finalEthAmount - initialEthAmount; require(ethDiff > 0, "NO_ETH_BACK"); if (feePercentageBasisPoints > 0) { uint256 fees = (ethDiff * feePercentageBasisPoints) / 1e18; uint256 amountMinusFees = ethDiff - fees; SafeTransferLib.safeTransferETH(msg.sender, amountMinusFees); // when there's no fee, 1inch sends the funds directly to the user // we check to prevent sending 0 ETH in that case } else if (ethDiff > 0) { SafeTransferLib.safeTransferETH(msg.sender, ethDiff); } } /// @dev internal method that executes ERC20 to ERC20 token swaps with the ability to take a fee from the input function _fillQuoteTokenToToken( address sellTokenAddress, address buyTokenAddress, address payable target, bytes calldata swapCallData, uint256 sellAmount, uint256 feeAmount ) internal { // 1 - Get the initial output token balance uint256 initialOutputTokenAmount = ERC20(buyTokenAddress).balanceOf( address(this) ); // 2 - Move the tokens to this contract (which includes our fees) // NOTE: This implicitly assumes that the the necessary approvals have been granted // from msg.sender to the BaseAggregator SafeTransferLib.safeTransferFrom( ERC20(sellTokenAddress), msg.sender, address(this), sellAmount ); // 3 - Approve the aggregator's contract to swap the tokens if needed SafeTransferLib.safeApprove( ERC20(sellTokenAddress), target, sellAmount - feeAmount ); // 4 - Call the encoded swap function call on the contract at `target`, // passing along any ETH attached to this function call to cover protocol fees. (bool success, bytes memory res) = target.call{value: msg.value}( swapCallData ); // Get the revert message of the call and revert with it if the call failed if (!success) { assembly { let returndata_size := mload(res) revert(add(32, res), returndata_size) } } // 5 - Check that the tokens were fully spent during the swap uint256 allowance = ERC20(sellTokenAddress).allowance( address(this), target ); require(allowance == 0, "ALLOWANCE_NOT_ZERO"); // 6 - Make sure we received the tokens uint256 finalOutputTokenAmount = ERC20(buyTokenAddress).balanceOf( address(this) ); require(initialOutputTokenAmount < finalOutputTokenAmount, "NO_TOKENS"); // 7 - Send tokens to the user SafeTransferLib.safeTransfer( ERC20(buyTokenAddress), msg.sender, finalOutputTokenAmount - initialOutputTokenAmount ); } } /// @title Rainbow swap aggregator contract contract RainbowRouter is BaseAggregator { /// @dev The address that is the current owner of this contract address public owner; /// @dev Event emitted when the owner changes event OwnerChanged(address indexed newOwner, address indexed oldOwner); /// @dev Event emitted when a swap target gets added event SwapTargetAdded(address indexed target); /// @dev Event emitted when a swap target gets removed event SwapTargetRemoved(address indexed target); /// @dev Event emitted when token fees are withdrawn event TokenWithdrawn( address indexed token, address indexed target, uint256 amount ); /// @dev Event emitted when ETH fees are withdrawn event EthWithdrawn(address indexed target, uint256 amount); /// @dev modifier that ensures only the owner is allowed to call a specific method modifier onlyOwner() { require(msg.sender == owner, "ONLY_OWNER"); _; } constructor() { owner = msg.sender; status = 1; } /// @dev We don't want to accept any ETH, except refunds from aggregators /// or the owner (for testing purposes), which can also withdraw /// This is done by evaluating the value of status, which is set to 2 /// only during swaps due to the "nonReentrant" modifier receive() external payable { require(status == 2 || msg.sender == owner, "NO_RECEIVE"); } /// @dev method to add or remove swap targets from swapTargets /// This is required so we only approve "trusted" swap targets /// to transfer tokens out of this contract /// @param target address of the swap target to add /// @param add flag to add or remove the swap target function updateSwapTargets(address target, bool add) external onlyOwner { swapTargets[target] = add; if (add) { emit SwapTargetAdded(target); } else { emit SwapTargetRemoved(target); } } /// @dev method to withdraw ERC20 tokens (from the fees) /// @param token address of the token to withdraw /// @param to address that's receiving the tokens /// @param amount amount of tokens to withdraw function withdrawToken( address token, address to, uint256 amount ) external onlyOwner { require(to != address(0), "ZERO_ADDRESS"); SafeTransferLib.safeTransfer(ERC20(token), to, amount); emit TokenWithdrawn(token, to, amount); } /// @dev method to withdraw ETH (from the fees) /// @param to address that's receiving the ETH /// @param amount amount of ETH to withdraw function withdrawEth(address to, uint256 amount) external onlyOwner { require(to != address(0), "ZERO_ADDRESS"); SafeTransferLib.safeTransferETH(to, amount); emit EthWithdrawn(to, amount); } /// @dev Transfers ownership of the contract to a new account (`newOwner`). /// @param newOwner address of the new owner /// Can only be called by the current owner. function transferOwnership(address newOwner) external virtual onlyOwner { require(newOwner != address(0), "ZERO_ADDRESS"); require(newOwner != owner, "SAME_OWNER"); address previousOwner = owner; owner = newOwner; emit OwnerChanged(newOwner, previousOwner); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EthWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newOwner","type":"address"},{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"}],"name":"SwapTargetAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"}],"name":"SwapTargetRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenWithdrawn","type":"event"},{"inputs":[{"internalType":"address","name":"buyTokenAddress","type":"address"},{"internalType":"address payable","name":"target","type":"address"},{"internalType":"bytes","name":"swapCallData","type":"bytes"},{"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"fillQuoteEthToToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"sellTokenAddress","type":"address"},{"internalType":"address payable","name":"target","type":"address"},{"internalType":"bytes","name":"swapCallData","type":"bytes"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"feePercentageBasisPoints","type":"uint256"}],"name":"fillQuoteTokenToEth","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"sellTokenAddress","type":"address"},{"internalType":"address payable","name":"target","type":"address"},{"internalType":"bytes","name":"swapCallData","type":"bytes"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"feePercentageBasisPoints","type":"uint256"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"isDaiStylePermit","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct PermitHelper.Permit","name":"permitData","type":"tuple"}],"name":"fillQuoteTokenToEthWithPermit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"sellTokenAddress","type":"address"},{"internalType":"address","name":"buyTokenAddress","type":"address"},{"internalType":"address payable","name":"target","type":"address"},{"internalType":"bytes","name":"swapCallData","type":"bytes"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"fillQuoteTokenToToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"sellTokenAddress","type":"address"},{"internalType":"address","name":"buyTokenAddress","type":"address"},{"internalType":"address payable","name":"target","type":"address"},{"internalType":"bytes","name":"swapCallData","type":"bytes"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"isDaiStylePermit","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct PermitHelper.Permit","name":"permitData","type":"tuple"}],"name":"fillQuoteTokenToTokenWithPermit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"swapTargets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"add","type":"bool"}],"name":"updateSwapTargets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawEth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
608060405234801561001057600080fd5b50600280546001600160a01b031916331790556001600055611afd806100376000396000f3fe6080604052600436106100c05760003560e01c80638da5cb5b11610074578063b0480bbd1161004e578063b0480bbd1461024e578063b309383814610261578063f2fde38b1461027457600080fd5b80638da5cb5b146101e357806397bbda0e1461021b578063999b64641461023b57600080fd5b80633c2b9a7d116100a55780633c2b9a7d1461017857806355e4b7be1461018b57806383c4a19d1461019e57600080fd5b806301e33667146101385780631b9a91a41461015857600080fd5b3661013357600054600214806100e057506002546001600160a01b031633145b6101315760405162461bcd60e51b815260206004820152600a60248201527f4e4f5f524543454956450000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b005b600080fd5b34801561014457600080fd5b506101316101533660046115a6565b610294565b34801561016457600080fd5b506101316101733660046115e7565b61037d565b61013161018636600461165c565b61045a565b6101316101993660046116c9565b61075f565b3480156101aa57600080fd5b506101ce6101b9366004611754565b60016020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156101ef57600080fd5b50600254610203906001600160a01b031681565b6040516001600160a01b0390911681526020016101da565b34801561022757600080fd5b5061013161023636600461178d565b610820565b6101316102493660046117c2565b610904565b61013161025c366004611851565b6109c3565b61013161026f3660046118f1565b610a9f565b34801561028057600080fd5b5061013161028f366004611754565b610b6a565b6002546001600160a01b031633146102db5760405162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b6044820152606401610128565b6001600160a01b0382166103205760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606401610128565b61032b838383610cbd565b816001600160a01b0316836001600160a01b03167f8210728e7c071f615b840ee026032693858fbcd5e5359e67e438c890f59e56208360405161037091815260200190565b60405180910390a3505050565b6002546001600160a01b031633146103c45760405162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b6044820152606401610128565b6001600160a01b0382166104095760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606401610128565b6104138282610d63565b816001600160a01b03167f8455ae6be5d92f1df1c3c1484388e247a36c7e60d72055ae216dbc258f257d4b8260405161044e91815260200190565b60405180910390a25050565b6000546002141561049d5760405162461bcd60e51b815260206004820152600d60248201526c1393d397d49151539514905395609a1b6044820152606401610128565b600260009081556001600160a01b038516815260016020526040902054849060ff166104fd5760405162461bcd60e51b815260206004820152600f60248201526e0a882a48e8aa8be9c9ea8be82aaa89608b1b6044820152606401610128565b6040516370a0823160e01b81523060048201526000906001600160a01b038816906370a0823190602401602060405180830381865afa158015610544573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610568919061197f565b9050600061057634476119ae565b9050600061058485346119ae565b9050600080896001600160a01b0316838a8a6040516105a49291906119c5565b60006040518083038185875af1925050503d80600081146105e1576040519150601f19603f3d011682016040523d82523d6000602084013e6105e6565b606091505b5091509150816105f95780518082602001fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038d16906370a0823190602401602060405180830381865afa158015610640573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610664919061197f565b90508086106106a15760405162461bcd60e51b81526020600482015260096024820152684e4f5f544f4b454e5360b81b6044820152606401610128565b506040516370a0823160e01b8152306004820152610723908c90339088906001600160a01b038416906370a0823190602401602060405180830381865afa1580156106f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610714919061197f565b61071e91906119ae565b610cbd565b600061072f88476119ae565b90508481111561074c5761074c3361074787846119ae565b610d63565b5050600160005550505050505050505050565b600054600214156107a25760405162461bcd60e51b815260206004820152600d60248201526c1393d397d49151539514905395609a1b6044820152606401610128565b600260009081556001600160a01b038616815260016020526040902054859060ff166108025760405162461bcd60e51b815260206004820152600f60248201526e0a882a48e8aa8be9c9ea8be82aaa89608b1b6044820152606401610128565b61081188888888888888610dc3565b50506001600055505050505050565b6002546001600160a01b031633146108675760405162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b6044820152606401610128565b6001600160a01b0382166000908152600160205260409020805460ff191682158015919091179091556108cc576040516001600160a01b038316907fb907822409611d127ab6a64611591b98e03a6a85ade4f258bae26b7c1efdfeaf90600090a25050565b6040516001600160a01b038316907f393b8be3e26787f19285ecd039dfd80bc6507828750f4d50367e6efe2524695c90600090a25050565b600054600214156109475760405162461bcd60e51b815260206004820152600d60248201526c1393d397d49151539514905395609a1b6044820152606401610128565b600260009081556001600160a01b038616815260016020526040902054859060ff166109a75760405162461bcd60e51b815260206004820152600f60248201526e0a882a48e8aa8be9c9ea8be82aaa89608b1b6044820152606401610128565b6109b587878787878761104c565b505060016000555050505050565b60005460021415610a065760405162461bcd60e51b815260206004820152600d60248201526c1393d397d49151539514905395609a1b6044820152606401610128565b600260009081556001600160a01b038716815260016020526040902054869060ff16610a665760405162461bcd60e51b815260206004820152600f60248201526e0a882a48e8aa8be9c9ea8be82aaa89608b1b6044820152606401610128565b610a80610a78368490038401846119e6565b8a333061125d565b610a8f89898989898989610dc3565b5050600160005550505050505050565b60005460021415610ae25760405162461bcd60e51b815260206004820152600d60248201526c1393d397d49151539514905395609a1b6044820152606401610128565b600260009081556001600160a01b038716815260016020526040902054869060ff16610b425760405162461bcd60e51b815260206004820152600f60248201526e0a882a48e8aa8be9c9ea8be82aaa89608b1b6044820152606401610128565b610b5c610b54368490038401846119e6565b89333061125d565b61081188888888888861104c565b6002546001600160a01b03163314610bb15760405162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b6044820152606401610128565b6001600160a01b038116610bf65760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606401610128565b6002546001600160a01b0382811691161415610c545760405162461bcd60e51b815260206004820152600a60248201527f53414d455f4f574e4552000000000000000000000000000000000000000000006044820152606401610128565b600280546001600160a01b038381167fffffffffffffffffffffffff00000000000000000000000000000000000000008316811790935560405191169182917fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c90600090a35050565b60006040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201528260248201526000806044836000895af1915050610d11816113f1565b610d5d5760405162461bcd60e51b815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610128565b50505050565b600080600080600085875af1905080610dbe5760405162461bcd60e51b815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401610128565b505050565b6040516370a0823160e01b81523060048201526000906001600160a01b038816906370a0823190602401602060405180830381865afa158015610e0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2e919061197f565b9050610e3c88333086611438565b610e508887610e4b85876119ae565b6114ee565b600080876001600160a01b0316348888604051610e6e9291906119c5565b60006040518083038185875af1925050503d8060008114610eab576040519150601f19603f3d011682016040523d82523d6000602084013e610eb0565b606091505b509150915081610ec35780518082602001fd5b604051636eb1769f60e11b81523060048201526001600160a01b038981166024830152600091908c169063dd62ed3e90604401602060405180830381865afa158015610f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f37919061197f565b90508015610f875760405162461bcd60e51b815260206004820152601260248201527f414c4c4f57414e43455f4e4f545f5a45524f00000000000000000000000000006044820152606401610128565b6040516370a0823160e01b81523060048201526000906001600160a01b038c16906370a0823190602401602060405180830381865afa158015610fce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff2919061197f565b905080851061102f5760405162461bcd60e51b81526020600482015260096024820152684e4f5f544f4b454e5360b81b6044820152606401610128565b61103e8b3361071e88856119ae565b505050505050505050505050565b600061105834476119ae565b905061106687333086611438565b6110718787856114ee565b600080876001600160a01b031634888860405161108f9291906119c5565b60006040518083038185875af1925050503d80600081146110cc576040519150601f19603f3d011682016040523d82523d6000602084013e6110d1565b606091505b5091509150816110e45780518082602001fd5b604051636eb1769f60e11b81523060048201526001600160a01b038981166024830152600091908b169063dd62ed3e90604401602060405180830381865afa158015611134573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611158919061197f565b905080156111a85760405162461bcd60e51b815260206004820152601260248201527f414c4c4f57414e43455f4e4f545f5a45524f00000000000000000000000000006044820152606401610128565b4760006111b586836119ae565b9050600081116112075760405162461bcd60e51b815260206004820152600b60248201527f4e4f5f4554485f4241434b0000000000000000000000000000000000000000006044820152606401610128565b861561124d576000670de0b6b3a76400006112228984611a86565b61122c9190611aa5565b9050600061123a82846119ae565b90506112463382610d63565b505061103e565b801561103e5761103e3382610d63565b836060015115611331576020840151604080860151608087015160a088015160c089015193517f8fcbaf0c0000000000000000000000000000000000000000000000000000000081526001600160a01b0388811660048301528781166024830152604482019690965260648101939093526001608484015260ff90911660a483015260c482015260e481019190915290841690638fcbaf0c9061010401600060405180830381600087803b15801561131457600080fd5b505af1158015611328573d6000803e3d6000fd5b50505050610d5d565b8351604080860151608087015160a088015160c089015193517fd505accf0000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015287811660248301526044820196909652606481019390935260ff909116608483015260a482015260c48101919091529084169063d505accf9060e401600060405180830381600087803b1580156113d357600080fd5b505af11580156113e7573d6000803e3d6000fd5b5050505050505050565b60003d8261140357806000803e806000fd5b806020811461141b57801561142c5760009250611431565b816000803e60005115159250611431565b600192505b5050919050565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526001600160a01b038416602482015282604482015260008060648360008a5af191505061149b816113f1565b6114e75760405162461bcd60e51b815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610128565b5050505050565b60006040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201528260248201526000806044836000895af1915050611542816113f1565b610d5d5760405162461bcd60e51b815260206004820152600e60248201527f415050524f56455f4641494c45440000000000000000000000000000000000006044820152606401610128565b6001600160a01b03811681146115a357600080fd5b50565b6000806000606084860312156115bb57600080fd5b83356115c68161158e565b925060208401356115d68161158e565b929592945050506040919091013590565b600080604083850312156115fa57600080fd5b82356116058161158e565b946020939093013593505050565b60008083601f84011261162557600080fd5b50813567ffffffffffffffff81111561163d57600080fd5b60208301915083602082850101111561165557600080fd5b9250929050565b60008060008060006080868803121561167457600080fd5b853561167f8161158e565b9450602086013561168f8161158e565b9350604086013567ffffffffffffffff8111156116ab57600080fd5b6116b788828901611613565b96999598509660600135949350505050565b600080600080600080600060c0888a0312156116e457600080fd5b87356116ef8161158e565b965060208801356116ff8161158e565b9550604088013561170f8161158e565b9450606088013567ffffffffffffffff81111561172b57600080fd5b6117378a828b01611613565b989b979a50959895979660808701359660a0013595509350505050565b60006020828403121561176657600080fd5b81356117718161158e565b9392505050565b8035801515811461178857600080fd5b919050565b600080604083850312156117a057600080fd5b82356117ab8161158e565b91506117b960208401611778565b90509250929050565b60008060008060008060a087890312156117db57600080fd5b86356117e68161158e565b955060208701356117f68161158e565b9450604087013567ffffffffffffffff81111561181257600080fd5b61181e89828a01611613565b979a9699509760608101359660809091013595509350505050565b600060e0828403121561184b57600080fd5b50919050565b6000806000806000806000806101a0898b03121561186e57600080fd5b88356118798161158e565b975060208901356118898161158e565b965060408901356118998161158e565b9550606089013567ffffffffffffffff8111156118b557600080fd5b6118c18b828c01611613565b9096509450506080890135925060a089013591506118e28a60c08b01611839565b90509295985092959890939650565b6000806000806000806000610180888a03121561190d57600080fd5b87356119188161158e565b965060208801356119288161158e565b9550604088013567ffffffffffffffff81111561194457600080fd5b6119508a828b01611613565b90965094505060608801359250608088013591506119718960a08a01611839565b905092959891949750929550565b60006020828403121561199157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156119c0576119c0611998565b500390565b8183823760009101908152919050565b803560ff8116811461178857600080fd5b600060e082840312156119f857600080fd5b60405160e0810181811067ffffffffffffffff82111715611a2957634e487b7160e01b600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152611a5260608401611778565b6060820152611a63608084016119d5565b608082015260a083013560a082015260c083013560c08201528091505092915050565b6000816000190483118215151615611aa057611aa0611998565b500290565b600082611ac257634e487b7160e01b600052601260045260246000fd5b50049056fea26469706673582212209870dd0dc3fb83baf72036a002768c9388c9b2cbf93b6d7b09369fddefaaf87764736f6c634300080b0033
Deployed Bytecode
0x6080604052600436106100c05760003560e01c80638da5cb5b11610074578063b0480bbd1161004e578063b0480bbd1461024e578063b309383814610261578063f2fde38b1461027457600080fd5b80638da5cb5b146101e357806397bbda0e1461021b578063999b64641461023b57600080fd5b80633c2b9a7d116100a55780633c2b9a7d1461017857806355e4b7be1461018b57806383c4a19d1461019e57600080fd5b806301e33667146101385780631b9a91a41461015857600080fd5b3661013357600054600214806100e057506002546001600160a01b031633145b6101315760405162461bcd60e51b815260206004820152600a60248201527f4e4f5f524543454956450000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b005b600080fd5b34801561014457600080fd5b506101316101533660046115a6565b610294565b34801561016457600080fd5b506101316101733660046115e7565b61037d565b61013161018636600461165c565b61045a565b6101316101993660046116c9565b61075f565b3480156101aa57600080fd5b506101ce6101b9366004611754565b60016020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156101ef57600080fd5b50600254610203906001600160a01b031681565b6040516001600160a01b0390911681526020016101da565b34801561022757600080fd5b5061013161023636600461178d565b610820565b6101316102493660046117c2565b610904565b61013161025c366004611851565b6109c3565b61013161026f3660046118f1565b610a9f565b34801561028057600080fd5b5061013161028f366004611754565b610b6a565b6002546001600160a01b031633146102db5760405162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b6044820152606401610128565b6001600160a01b0382166103205760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606401610128565b61032b838383610cbd565b816001600160a01b0316836001600160a01b03167f8210728e7c071f615b840ee026032693858fbcd5e5359e67e438c890f59e56208360405161037091815260200190565b60405180910390a3505050565b6002546001600160a01b031633146103c45760405162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b6044820152606401610128565b6001600160a01b0382166104095760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606401610128565b6104138282610d63565b816001600160a01b03167f8455ae6be5d92f1df1c3c1484388e247a36c7e60d72055ae216dbc258f257d4b8260405161044e91815260200190565b60405180910390a25050565b6000546002141561049d5760405162461bcd60e51b815260206004820152600d60248201526c1393d397d49151539514905395609a1b6044820152606401610128565b600260009081556001600160a01b038516815260016020526040902054849060ff166104fd5760405162461bcd60e51b815260206004820152600f60248201526e0a882a48e8aa8be9c9ea8be82aaa89608b1b6044820152606401610128565b6040516370a0823160e01b81523060048201526000906001600160a01b038816906370a0823190602401602060405180830381865afa158015610544573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610568919061197f565b9050600061057634476119ae565b9050600061058485346119ae565b9050600080896001600160a01b0316838a8a6040516105a49291906119c5565b60006040518083038185875af1925050503d80600081146105e1576040519150601f19603f3d011682016040523d82523d6000602084013e6105e6565b606091505b5091509150816105f95780518082602001fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038d16906370a0823190602401602060405180830381865afa158015610640573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610664919061197f565b90508086106106a15760405162461bcd60e51b81526020600482015260096024820152684e4f5f544f4b454e5360b81b6044820152606401610128565b506040516370a0823160e01b8152306004820152610723908c90339088906001600160a01b038416906370a0823190602401602060405180830381865afa1580156106f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610714919061197f565b61071e91906119ae565b610cbd565b600061072f88476119ae565b90508481111561074c5761074c3361074787846119ae565b610d63565b5050600160005550505050505050505050565b600054600214156107a25760405162461bcd60e51b815260206004820152600d60248201526c1393d397d49151539514905395609a1b6044820152606401610128565b600260009081556001600160a01b038616815260016020526040902054859060ff166108025760405162461bcd60e51b815260206004820152600f60248201526e0a882a48e8aa8be9c9ea8be82aaa89608b1b6044820152606401610128565b61081188888888888888610dc3565b50506001600055505050505050565b6002546001600160a01b031633146108675760405162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b6044820152606401610128565b6001600160a01b0382166000908152600160205260409020805460ff191682158015919091179091556108cc576040516001600160a01b038316907fb907822409611d127ab6a64611591b98e03a6a85ade4f258bae26b7c1efdfeaf90600090a25050565b6040516001600160a01b038316907f393b8be3e26787f19285ecd039dfd80bc6507828750f4d50367e6efe2524695c90600090a25050565b600054600214156109475760405162461bcd60e51b815260206004820152600d60248201526c1393d397d49151539514905395609a1b6044820152606401610128565b600260009081556001600160a01b038616815260016020526040902054859060ff166109a75760405162461bcd60e51b815260206004820152600f60248201526e0a882a48e8aa8be9c9ea8be82aaa89608b1b6044820152606401610128565b6109b587878787878761104c565b505060016000555050505050565b60005460021415610a065760405162461bcd60e51b815260206004820152600d60248201526c1393d397d49151539514905395609a1b6044820152606401610128565b600260009081556001600160a01b038716815260016020526040902054869060ff16610a665760405162461bcd60e51b815260206004820152600f60248201526e0a882a48e8aa8be9c9ea8be82aaa89608b1b6044820152606401610128565b610a80610a78368490038401846119e6565b8a333061125d565b610a8f89898989898989610dc3565b5050600160005550505050505050565b60005460021415610ae25760405162461bcd60e51b815260206004820152600d60248201526c1393d397d49151539514905395609a1b6044820152606401610128565b600260009081556001600160a01b038716815260016020526040902054869060ff16610b425760405162461bcd60e51b815260206004820152600f60248201526e0a882a48e8aa8be9c9ea8be82aaa89608b1b6044820152606401610128565b610b5c610b54368490038401846119e6565b89333061125d565b61081188888888888861104c565b6002546001600160a01b03163314610bb15760405162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b6044820152606401610128565b6001600160a01b038116610bf65760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606401610128565b6002546001600160a01b0382811691161415610c545760405162461bcd60e51b815260206004820152600a60248201527f53414d455f4f574e4552000000000000000000000000000000000000000000006044820152606401610128565b600280546001600160a01b038381167fffffffffffffffffffffffff00000000000000000000000000000000000000008316811790935560405191169182917fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c90600090a35050565b60006040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201528260248201526000806044836000895af1915050610d11816113f1565b610d5d5760405162461bcd60e51b815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610128565b50505050565b600080600080600085875af1905080610dbe5760405162461bcd60e51b815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401610128565b505050565b6040516370a0823160e01b81523060048201526000906001600160a01b038816906370a0823190602401602060405180830381865afa158015610e0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2e919061197f565b9050610e3c88333086611438565b610e508887610e4b85876119ae565b6114ee565b600080876001600160a01b0316348888604051610e6e9291906119c5565b60006040518083038185875af1925050503d8060008114610eab576040519150601f19603f3d011682016040523d82523d6000602084013e610eb0565b606091505b509150915081610ec35780518082602001fd5b604051636eb1769f60e11b81523060048201526001600160a01b038981166024830152600091908c169063dd62ed3e90604401602060405180830381865afa158015610f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f37919061197f565b90508015610f875760405162461bcd60e51b815260206004820152601260248201527f414c4c4f57414e43455f4e4f545f5a45524f00000000000000000000000000006044820152606401610128565b6040516370a0823160e01b81523060048201526000906001600160a01b038c16906370a0823190602401602060405180830381865afa158015610fce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff2919061197f565b905080851061102f5760405162461bcd60e51b81526020600482015260096024820152684e4f5f544f4b454e5360b81b6044820152606401610128565b61103e8b3361071e88856119ae565b505050505050505050505050565b600061105834476119ae565b905061106687333086611438565b6110718787856114ee565b600080876001600160a01b031634888860405161108f9291906119c5565b60006040518083038185875af1925050503d80600081146110cc576040519150601f19603f3d011682016040523d82523d6000602084013e6110d1565b606091505b5091509150816110e45780518082602001fd5b604051636eb1769f60e11b81523060048201526001600160a01b038981166024830152600091908b169063dd62ed3e90604401602060405180830381865afa158015611134573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611158919061197f565b905080156111a85760405162461bcd60e51b815260206004820152601260248201527f414c4c4f57414e43455f4e4f545f5a45524f00000000000000000000000000006044820152606401610128565b4760006111b586836119ae565b9050600081116112075760405162461bcd60e51b815260206004820152600b60248201527f4e4f5f4554485f4241434b0000000000000000000000000000000000000000006044820152606401610128565b861561124d576000670de0b6b3a76400006112228984611a86565b61122c9190611aa5565b9050600061123a82846119ae565b90506112463382610d63565b505061103e565b801561103e5761103e3382610d63565b836060015115611331576020840151604080860151608087015160a088015160c089015193517f8fcbaf0c0000000000000000000000000000000000000000000000000000000081526001600160a01b0388811660048301528781166024830152604482019690965260648101939093526001608484015260ff90911660a483015260c482015260e481019190915290841690638fcbaf0c9061010401600060405180830381600087803b15801561131457600080fd5b505af1158015611328573d6000803e3d6000fd5b50505050610d5d565b8351604080860151608087015160a088015160c089015193517fd505accf0000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015287811660248301526044820196909652606481019390935260ff909116608483015260a482015260c48101919091529084169063d505accf9060e401600060405180830381600087803b1580156113d357600080fd5b505af11580156113e7573d6000803e3d6000fd5b5050505050505050565b60003d8261140357806000803e806000fd5b806020811461141b57801561142c5760009250611431565b816000803e60005115159250611431565b600192505b5050919050565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526001600160a01b038416602482015282604482015260008060648360008a5af191505061149b816113f1565b6114e75760405162461bcd60e51b815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610128565b5050505050565b60006040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201528260248201526000806044836000895af1915050611542816113f1565b610d5d5760405162461bcd60e51b815260206004820152600e60248201527f415050524f56455f4641494c45440000000000000000000000000000000000006044820152606401610128565b6001600160a01b03811681146115a357600080fd5b50565b6000806000606084860312156115bb57600080fd5b83356115c68161158e565b925060208401356115d68161158e565b929592945050506040919091013590565b600080604083850312156115fa57600080fd5b82356116058161158e565b946020939093013593505050565b60008083601f84011261162557600080fd5b50813567ffffffffffffffff81111561163d57600080fd5b60208301915083602082850101111561165557600080fd5b9250929050565b60008060008060006080868803121561167457600080fd5b853561167f8161158e565b9450602086013561168f8161158e565b9350604086013567ffffffffffffffff8111156116ab57600080fd5b6116b788828901611613565b96999598509660600135949350505050565b600080600080600080600060c0888a0312156116e457600080fd5b87356116ef8161158e565b965060208801356116ff8161158e565b9550604088013561170f8161158e565b9450606088013567ffffffffffffffff81111561172b57600080fd5b6117378a828b01611613565b989b979a50959895979660808701359660a0013595509350505050565b60006020828403121561176657600080fd5b81356117718161158e565b9392505050565b8035801515811461178857600080fd5b919050565b600080604083850312156117a057600080fd5b82356117ab8161158e565b91506117b960208401611778565b90509250929050565b60008060008060008060a087890312156117db57600080fd5b86356117e68161158e565b955060208701356117f68161158e565b9450604087013567ffffffffffffffff81111561181257600080fd5b61181e89828a01611613565b979a9699509760608101359660809091013595509350505050565b600060e0828403121561184b57600080fd5b50919050565b6000806000806000806000806101a0898b03121561186e57600080fd5b88356118798161158e565b975060208901356118898161158e565b965060408901356118998161158e565b9550606089013567ffffffffffffffff8111156118b557600080fd5b6118c18b828c01611613565b9096509450506080890135925060a089013591506118e28a60c08b01611839565b90509295985092959890939650565b6000806000806000806000610180888a03121561190d57600080fd5b87356119188161158e565b965060208801356119288161158e565b9550604088013567ffffffffffffffff81111561194457600080fd5b6119508a828b01611613565b90965094505060608801359250608088013591506119718960a08a01611839565b905092959891949750929550565b60006020828403121561199157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156119c0576119c0611998565b500390565b8183823760009101908152919050565b803560ff8116811461178857600080fd5b600060e082840312156119f857600080fd5b60405160e0810181811067ffffffffffffffff82111715611a2957634e487b7160e01b600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152611a5260608401611778565b6060820152611a63608084016119d5565b608082015260a083013560a082015260c083013560c08201528091505092915050565b6000816000190483118215151615611aa057611aa0611998565b500290565b600082611ac257634e487b7160e01b600052601260045260246000fd5b50049056fea26469706673582212209870dd0dc3fb83baf72036a002768c9388c9b2cbf93b6d7b09369fddefaaf87764736f6c634300080b0033
Deployed Bytecode Sourcemap
41579:3441:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42992:6;;43002:1;42992:11;:34;;;-1:-1:-1;43021:5:0;;-1:-1:-1;;;;;43021:5:0;43007:10;:19;42992:34;42984:57;;;;-1:-1:-1;;;42984:57:0;;216:2:1;42984:57:0;;;198:21:1;255:2;235:18;;;228:30;294:12;274:18;;;267:40;324:18;;42984:57:0;;;;;;;;;41579:3441;;;;;43842:293;;;;;;;;;;-1:-1:-1;43842:293:0;;;;;:::i;:::-;;:::i;44297:222::-;;;;;;;;;;-1:-1:-1;44297:222:0;;;;;:::i;:::-;;:::i;29093:2054::-;;;;;;:::i;:::-;;:::i;31650:502::-;;;;;;:::i;:::-;;:::i;28000:43::-;;;;;;;;;;-1:-1:-1;28000:43:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;3807:14:1;;3800:22;3782:41;;3770:2;3755:18;28000:43:0;;;;;;;;41696:20;;;;;;;;;;-1:-1:-1;41696:20:0;;;;-1:-1:-1;;;;;41696:20:0;;;;;;-1:-1:-1;;;;;3998:55:1;;;3980:74;;3968:2;3953:18;41696:20:0;3834:226:1;43357:253:0;;;;;;;;;;-1:-1:-1;43357:253:0;;;;;:::i;:::-;;:::i;34387:464::-;;;;;;:::i;:::-;;:::i;32986:785::-;;;;;;:::i;:::-;;:::i;35691:746::-;;;;;;:::i;:::-;;:::i;44708:309::-;;;;;;;;;;-1:-1:-1;44708:309:0;;;;;:::i;:::-;;:::i;43842:293::-;42532:5;;-1:-1:-1;;;;;42532:5:0;42518:10;:19;42510:42;;;;-1:-1:-1;;;42510:42:0;;7810:2:1;42510:42:0;;;7792:21:1;7849:2;7829:18;;;7822:30;-1:-1:-1;;;7868:18:1;;;7861:40;7918:18;;42510:42:0;7608:334:1;42510:42:0;-1:-1:-1;;;;;43980:16:0;::::1;43972:41;;;::::0;-1:-1:-1;;;43972:41:0;;8149:2:1;43972:41:0::1;::::0;::::1;8131:21:1::0;8188:2;8168:18;;;8161:30;-1:-1:-1;;;8207:18:1;;;8200:42;8259:18;;43972:41:0::1;7947:336:1::0;43972:41:0::1;44024:54;44059:5;44067:2;44071:6;44024:28;:54::i;:::-;44116:2;-1:-1:-1::0;;;;;44094:33:0::1;44109:5;-1:-1:-1::0;;;;;44094:33:0::1;;44120:6;44094:33;;;;8434:25:1::0;;8422:2;8407:18;;8288:177;44094:33:0::1;;;;;;;;43842:293:::0;;;:::o;44297:222::-;42532:5;;-1:-1:-1;;;;;42532:5:0;42518:10;:19;42510:42;;;;-1:-1:-1;;;42510:42:0;;7810:2:1;42510:42:0;;;7792:21:1;7849:2;7829:18;;;7822:30;-1:-1:-1;;;7868:18:1;;;7861:40;7918:18;;42510:42:0;7608:334:1;42510:42:0;-1:-1:-1;;;;;44384:16:0;::::1;44376:41;;;::::0;-1:-1:-1;;;44376:41:0;;8149:2:1;44376:41:0::1;::::0;::::1;8131:21:1::0;8188:2;8168:18;;;8161:30;-1:-1:-1;;;8207:18:1;;;8200:42;8259:18;;44376:41:0::1;7947:336:1::0;44376:41:0::1;44428:43;44460:2;44464:6;44428:31;:43::i;:::-;44500:2;-1:-1:-1::0;;;;;44487:24:0::1;;44504:6;44487:24;;;;8434:25:1::0;;8422:2;8407:18;;8288:177;44487:24:0::1;;;;;;;;44297:222:::0;;:::o;29093:2054::-;28235:6;;28245:1;28235:11;;28227:37;;;;-1:-1:-1;;;28227:37:0;;8672:2:1;28227:37:0;;;8654:21:1;8711:2;8691:18;;;8684:30;-1:-1:-1;;;8730:18:1;;;8723:43;8783:18;;28227:37:0;8470:337:1;28227:37:0;28351:1;28342:6;:10;;;-1:-1:-1;;;;;28674:19:0;::::1;::::0;;:11:::1;:19;::::0;;;;;29311:6;;28674:19:::1;;28666:47;;;::::0;-1:-1:-1;;;28666:47:0;;9014:2:1;28666:47:0::1;::::0;::::1;8996:21:1::0;9053:2;9033:18;;;9026:30;-1:-1:-1;;;9072:18:1;;;9065:45;9127:18;;28666:47:0::1;8812:339:1::0;28666:47:0::1;29401:71:::2;::::0;-1:-1:-1;;;29401:71:0;;29456:4:::2;29401:71;::::0;::::2;3980:74:1::0;29371:27:0::2;::::0;-1:-1:-1;;;;;29401:32:0;::::2;::::0;::::2;::::0;3953:18:1;;29401:71:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;29371:101:::0;-1:-1:-1;29483:24:0::2;29510:33;29534:9;29510:21;:33;:::i;:::-;29483:60:::0;-1:-1:-1;29554:18:0::2;29575:21;29587:9:::0;29575::::2;:21;:::i;:::-;29554:42;;29839:12;29853:16:::0;29873:6:::2;-1:-1:-1::0;;;;;29873:11:0::2;29892:10;29918:12;;29873:68;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29838:103;;;;30044:7;30039:171;;30125:3;30119:10;30168:15;30162:3;30158:2;30154:12;30147:37;30039:171;30314:79;::::0;-1:-1:-1;;;30314:79:0;;30373:4:::2;30314:79;::::0;::::2;3980:74:1::0;30286:25:0::2;::::0;-1:-1:-1;;;;;30314:32:0;::::2;::::0;::::2;::::0;3953:18:1;;30314:79:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;30286:107;;30438:17;30416:19;:39;30408:61;;;::::0;-1:-1:-1;;;30408:61:0;;10142:2:1;30408:61:0::2;::::0;::::2;10124:21:1::0;10181:1;10161:18;;;10154:29;-1:-1:-1;;;10199:18:1;;;10192:39;10248:18;;30408:61:0::2;9940:332:1::0;30408:61:0::2;-1:-1:-1::0;30656:47:0::2;::::0;-1:-1:-1;;;30656:47:0;;30697:4:::2;30656:47;::::0;::::2;3980:74:1::0;30551:202:0::2;::::0;30600:15;;30631:10:::2;::::0;30723:19;;-1:-1:-1;;;;;30656:32:0;::::2;::::0;::::2;::::0;3953:18:1;;30656:47:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:86;;;;:::i;:::-;30551:28;:202::i;:::-;30843:22;30868:33;30892:9:::0;30868:21:::2;:33;:::i;:::-;30843:58;;30937:16;30920:14;:33;30916:213;;;30974:139;31028:10;31061:33;31078:16:::0;31061:14;:33:::2;:::i;:::-;30974:31;:139::i;:::-;-1:-1:-1::0;;28522:1:0;28513:6;:10;-1:-1:-1;;;;;;;;;;29093:2054:0:o;31650:502::-;28235:6;;28245:1;28235:11;;28227:37;;;;-1:-1:-1;;;28227:37:0;;8672:2:1;28227:37:0;;;8654:21:1;8711:2;8691:18;;;8684:30;-1:-1:-1;;;8730:18:1;;;8723:43;8783:18;;28227:37:0;8470:337:1;28227:37:0;28351:1;28342:6;:10;;;-1:-1:-1;;;;;28674:19:0;::::1;::::0;;:11:::1;:19;::::0;;;;;31934:6;;28674:19:::1;;28666:47;;;::::0;-1:-1:-1;;;28666:47:0;;9014:2:1;28666:47:0::1;::::0;::::1;8996:21:1::0;9053:2;9033:18;;;9026:30;-1:-1:-1;;;9072:18:1;;;9065:45;9127:18;;28666:47:0::1;8812:339:1::0;28666:47:0::1;31953:191:::2;31990:16;32021:15;32051:6;32072:12;;32099:10;32124:9;31953:22;:191::i;:::-;-1:-1:-1::0;;28522:1:0;28513:6;:10;-1:-1:-1;;;;;;31650:502:0:o;43357:253::-;42532:5;;-1:-1:-1;;;;;42532:5:0;42518:10;:19;42510:42;;;;-1:-1:-1;;;42510:42:0;;7810:2:1;42510:42:0;;;7792:21:1;7849:2;7829:18;;;7822:30;-1:-1:-1;;;7868:18:1;;;7861:40;7918:18;;42510:42:0;7608:334:1;42510:42:0;-1:-1:-1;;;;;43440:19:0;::::1;;::::0;;;:11:::1;:19;::::0;;;;:25;;-1:-1:-1;;43440:25:0::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;;;43476:127:::1;;43505:23;::::0;-1:-1:-1;;;;;43505:23:0;::::1;::::0;::::1;::::0;;;::::1;43357:253:::0;;:::o;43476:127::-:1;43566:25;::::0;-1:-1:-1;;;;;43566:25:0;::::1;::::0;::::1;::::0;;;::::1;43357:253:::0;;:::o;34387:464::-;28235:6;;28245:1;28235:11;;28227:37;;;;-1:-1:-1;;;28227:37:0;;8672:2:1;28227:37:0;;;8654:21:1;8711:2;8691:18;;;8684:30;-1:-1:-1;;;8730:18:1;;;8723:43;8783:18;;28227:37:0;8470:337:1;28227:37:0;28351:1;28342:6;:10;;;-1:-1:-1;;;;;28674:19:0;::::1;::::0;;:11:::1;:19;::::0;;;;;34650:6;;28674:19:::1;;28666:47;;;::::0;-1:-1:-1;;;28666:47:0;;9014:2:1;28666:47:0::1;::::0;::::1;8996:21:1::0;9053:2;9033:18;;;9026:30;-1:-1:-1;;;9072:18:1;;;9065:45;9127:18;;28666:47:0::1;8812:339:1::0;28666:47:0::1;34669:174:::2;34704:16;34735:6;34756:12;;34783:10;34808:24;34669:20;:174::i;:::-;-1:-1:-1::0;;28522:1:0;28513:6;:10;-1:-1:-1;;;;;34387:464:0:o;32986:785::-;28235:6;;28245:1;28235:11;;28227:37;;;;-1:-1:-1;;;28227:37:0;;8672:2:1;28227:37:0;;;8654:21:1;8711:2;8691:18;;;8684:30;-1:-1:-1;;;8730:18:1;;;8723:43;8783:18;;28227:37:0;8470:337:1;28227:37:0;28351:1;28342:6;:10;;;-1:-1:-1;;;;;28674:19:0;::::1;::::0;;:11:::1;:19;::::0;;;;;33330:6;;28674:19:::1;;28666:47;;;::::0;-1:-1:-1;;;28666:47:0;;9014:2:1;28666:47:0::1;::::0;::::1;8996:21:1::0;9053:2;9033:18;;;9026:30;-1:-1:-1;;;9072:18:1;;;9065:45;9127:18;;28666:47:0::1;8812:339:1::0;28666:47:0::1;33378:139:::2;;;::::0;;::::2;::::0;::::2;33412:10:::0;33378:139:::2;:::i;:::-;33437:16;33468:10;33501:4;33378:19;:139::i;:::-;33572:191;33609:16;33640:15;33670:6;33691:12;;33718:10;33743:9;33572:22;:191::i;:::-;-1:-1:-1::0;;28522:1:0;28513:6;:10;-1:-1:-1;;;;;;;32986:785:0:o;35691:746::-;28235:6;;28245:1;28235:11;;28227:37;;;;-1:-1:-1;;;28227:37:0;;8672:2:1;28227:37:0;;;8654:21:1;8711:2;8691:18;;;8684:30;-1:-1:-1;;;8730:18:1;;;8723:43;8783:18;;28227:37:0;8470:337:1;28227:37:0;28351:1;28342:6;:10;;;-1:-1:-1;;;;;28674:19:0;::::1;::::0;;:11:::1;:19;::::0;;;;;36014:6;;28674:19:::1;;28666:47;;;::::0;-1:-1:-1;;;28666:47:0;;9014:2:1;28666:47:0::1;::::0;::::1;8996:21:1::0;9053:2;9033:18;;;9026:30;-1:-1:-1;;;9072:18:1;;;9065:45;9127:18;;28666:47:0::1;8812:339:1::0;28666:47:0::1;36062:139:::2;;;::::0;;::::2;::::0;::::2;36096:10:::0;36062:139:::2;:::i;:::-;36121:16;36152:10;36185:4;36062:19;:139::i;:::-;36255:174;36290:16;36321:6;36342:12;;36369:10;36394:24;36255:20;:174::i;44708:309::-:0;42532:5;;-1:-1:-1;;;;;42532:5:0;42518:10;:19;42510:42;;;;-1:-1:-1;;;42510:42:0;;7810:2:1;42510:42:0;;;7792:21:1;7849:2;7829:18;;;7822:30;-1:-1:-1;;;7868:18:1;;;7861:40;7918:18;;42510:42:0;7608:334:1;42510:42:0;-1:-1:-1;;;;;44799:22:0;::::1;44791:47;;;::::0;-1:-1:-1;;;44791:47:0;;8149:2:1;44791:47:0::1;::::0;::::1;8131:21:1::0;8188:2;8168:18;;;8161:30;-1:-1:-1;;;8207:18:1;;;8200:42;8259:18;;44791:47:0::1;7947:336:1::0;44791:47:0::1;44869:5;::::0;-1:-1:-1;;;;;44857:17:0;;::::1;44869:5:::0;::::1;44857:17;;44849:40;;;::::0;-1:-1:-1;;;44849:40:0;;11646:2:1;44849:40:0::1;::::0;::::1;11628:21:1::0;11685:2;11665:18;;;11658:30;11724:12;11704:18;;;11697:40;11754:18;;44849:40:0::1;11444:334:1::0;44849:40:0::1;44924:5;::::0;;-1:-1:-1;;;;;44940:16:0;;::::1;::::0;;::::1;::::0;::::1;::::0;;;44972:37:::1;::::0;44924:5;::::1;::::0;;;44972:37:::1;::::0;44900:21:::1;::::0;44972:37:::1;44780:237;44708:309:::0;:::o;15493:1065::-;15610:15;15744:4;15738:11;15864:66;15845:17;15838:93;-1:-1:-1;;;;;16020:2:0;16016:51;16012:1;15993:17;15989:25;15982:86;16155:6;16150:2;16131:17;16127:26;16120:42;16453:1;16450;16446:2;16427:17;16424:1;16417:5;16410;16405:50;16391:64;;;16486:44;16519:10;16486:32;:44::i;:::-;16478:72;;;;-1:-1:-1;;;16478:72:0;;11985:2:1;16478:72:0;;;11967:21:1;12024:2;12004:18;;;11997:30;12063:17;12043:18;;;12036:45;12098:18;;16478:72:0;11783:339:1;16478:72:0;15599:959;15493:1065;;;:::o;13733:314::-;13806:15;13972:1;13969;13966;13963;13955:6;13951:2;13944:5;13939:35;13925:49;;14005:10;13997:42;;;;-1:-1:-1;;;13997:42:0;;12329:2:1;13997:42:0;;;12311:21:1;12368:2;12348:18;;;12341:30;12407:21;12387:18;;;12380:49;12446:18;;13997:42:0;12127:343:1;13997:42:0;13795:252;13733:314;;:::o;39216:2311::-;39560:71;;-1:-1:-1;;;39560:71:0;;39615:4;39560:71;;;3980:74:1;39525:32:0;;-1:-1:-1;;;;;39560:32:0;;;;;3953:18:1;;39560:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;39525:106;;39862:159;39915:16;39947:10;39980:4;40000:10;39862:32;:159::i;:::-;40113:134;40161:16;40193:6;40214:22;40227:9;40214:10;:22;:::i;:::-;40113:27;:134::i;:::-;40431:12;40445:16;40465:6;-1:-1:-1;;;;;40465:11:0;40484:9;40509:12;;40465:67;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40430:102;;;;40635:7;40630:171;;40716:3;40710:10;40759:15;40753:3;40749:2;40745:12;40738:37;40630:171;40904:93;;-1:-1:-1;;;40904:93:0;;40960:4;40904:93;;;12718:34:1;-1:-1:-1;;;;;12788:15:1;;;12768:18;;;12761:43;40884:17:0;;40904:33;;;;;;12630:18:1;;40904:93:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;40884:113;-1:-1:-1;41016:14:0;;41008:45;;;;-1:-1:-1;;;41008:45:0;;13017:2:1;41008:45:0;;;12999:21:1;13056:2;13036:18;;;13029:30;13095:20;13075:18;;;13068:48;13133:18;;41008:45:0;12815:342:1;41008:45:0;41148:71;;-1:-1:-1;;;41148:71:0;;41203:4;41148:71;;;3980:74:1;41115:30:0;;-1:-1:-1;;;;;41148:32:0;;;;;3953:18:1;;41148:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41115:104;;41265:22;41238:24;:49;41230:71;;;;-1:-1:-1;;;41230:71:0;;10142:2:1;41230:71:0;;;10124:21:1;10181:1;10161:18;;;10154:29;-1:-1:-1;;;10199:18:1;;;10192:39;10248:18;;41230:71:0;9940:332:1;41230:71:0;41354:165;41403:15;41434:10;41459:49;41484:24;41459:22;:49;:::i;41354:165::-;39461:2066;;;;;39216:2311;;;;;;;:::o;36585:2506::-;36863:24;36890:33;36914:9;36890:21;:33;:::i;:::-;36863:60;;37128:159;37181:16;37213:10;37246:4;37266:10;37128:32;:159::i;:::-;37369:122;37417:16;37449:6;37470:10;37369:27;:122::i;:::-;37675:12;37689:16;37709:6;-1:-1:-1;;;;;37709:11:0;37728:9;37753:12;;37709:67;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37674:102;;;;37879:7;37874:171;;37960:3;37954:10;38003:15;37997:3;37993:2;37989:12;37982:37;37874:171;38148:93;;-1:-1:-1;;;38148:93:0;;38204:4;38148:93;;;12718:34:1;-1:-1:-1;;;;;12788:15:1;;;12768:18;;;12761:43;38128:17:0;;38148:33;;;;;;12630:18:1;;38148:93:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;38128:113;-1:-1:-1;38260:14:0;;38252:45;;;;-1:-1:-1;;;38252:45:0;;13017:2:1;38252:45:0;;;12999:21:1;13056:2;13036:18;;;13029:30;13095:20;13075:18;;;13068:48;13133:18;;38252:45:0;12815:342:1;38252:45:0;38446:21;38421:22;38496:33;38513:16;38446:21;38496:33;:::i;:::-;38478:51;;38560:1;38550:7;:11;38542:35;;;;-1:-1:-1;;;38542:35:0;;13364:2:1;38542:35:0;;;13346:21:1;13403:2;13383:18;;;13376:30;13442:13;13422:18;;;13415:41;13473:18;;38542:35:0;13162:335:1;38542:35:0;38594:28;;38590:494;;38639:12;38693:4;38655:34;38665:24;38655:7;:34;:::i;:::-;38654:43;;;;:::i;:::-;38639:58;-1:-1:-1;38712:23:0;38738:14;38639:58;38738:7;:14;:::i;:::-;38712:40;;38767:60;38799:10;38811:15;38767:31;:60::i;:::-;38624:358;;38590:494;;;38992:11;;38988:96;;39020:52;39052:10;39064:7;39020:31;:52::i;27000:801::-;27164:10;:27;;;27160:634;;;27303:16;;;;27338:19;;;;;27399:12;;;;27430;;;;27461;;;;27208:280;;;;;-1:-1:-1;;;;;14366:15:1;;;27208:280:0;;;14348:34:1;14418:15;;;14398:18;;;14391:43;14450:18;;;14443:34;;;;14493:18;;;14486:34;;;;27376:4:0;14536:19:1;;;14529:51;14629:4;14617:17;;;14596:19;;;14589:46;14651:19;;;14644:35;14695:19;;;14688:35;;;;27208:25:0;;;;;;14259:19:1;;27208:280:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27160:634;;;27620:16;;27655:19;;;;;27693:12;;;;27724;;;;27755;;;;27521:261;;;;;-1:-1:-1;;;;;15124:15:1;;;27521:261:0;;;15106:34:1;15176:15;;;15156:18;;;15149:43;15208:18;;;15201:34;;;;15251:18;;;15244:34;;;;15327:4;15315:17;;;15294:19;;;15287:46;15349:19;;;15342:35;15393:19;;;15386:35;;;;27521:29:0;;;;;;15017:19:1;;27521:261:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27000:801;;;;:::o;17828:1072::-;17909:12;18034:16;18114:10;18104:244;;18223:14;18220:1;18217;18202:36;18318:14;18315:1;18308:25;18104:244;18371:14;18404:2;18399:248;;;;18661:99;;;;18866:1;18855:12;;18364:518;;18399:248;18501:14;18498:1;18495;18480:36;18628:1;18622:8;18615:16;18608:24;18597:35;;18399:248;;18661:99;18744:1;18733:12;;18364:518;;;17828:1072;;;:::o;14243:1242::-;14387:15;14521:4;14515:11;14641:66;14622:17;14615:93;-1:-1:-1;;;;;14797:4:0;14793:53;14789:1;14770:17;14766:25;14759:88;-1:-1:-1;;;;;14940:2:0;14936:51;14931:2;14912:17;14908:26;14901:87;15075:6;15070:2;15051:17;15047:26;15040:42;15375:1;15372;15367:3;15348:17;15345:1;15338:5;15331;15326:51;15312:65;;;15408:44;15441:10;15408:32;:44::i;:::-;15400:77;;;;-1:-1:-1;;;15400:77:0;;15634:2:1;15400:77:0;;;15616:21:1;15673:2;15653:18;;;15646:30;15712:22;15692:18;;;15685:50;15752:18;;15400:77:0;15432:344:1;15400:77:0;14376:1109;14243:1242;;;;:::o;16566:1063::-;16682:15;16816:4;16810:11;16936:66;16917:17;16910:93;-1:-1:-1;;;;;17092:2:0;17088:51;17084:1;17065:17;17061:25;17054:86;17227:6;17222:2;17203:17;17199:26;17192:42;17525:1;17522;17518:2;17499:17;17496:1;17489:5;17482;17477:50;17463:64;;;17558:44;17591:10;17558:32;:44::i;:::-;17550:71;;;;-1:-1:-1;;;17550:71:0;;15983:2:1;17550:71:0;;;15965:21:1;16022:2;16002:18;;;15995:30;16061:16;16041:18;;;16034:44;16095:18;;17550:71:0;15781:338:1;353:154;-1:-1:-1;;;;;432:5:1;428:54;421:5;418:65;408:93;;497:1;494;487:12;408:93;353:154;:::o;512:456::-;589:6;597;605;658:2;646:9;637:7;633:23;629:32;626:52;;;674:1;671;664:12;626:52;713:9;700:23;732:31;757:5;732:31;:::i;:::-;782:5;-1:-1:-1;839:2:1;824:18;;811:32;852:33;811:32;852:33;:::i;:::-;512:456;;904:7;;-1:-1:-1;;;958:2:1;943:18;;;;930:32;;512:456::o;973:315::-;1041:6;1049;1102:2;1090:9;1081:7;1077:23;1073:32;1070:52;;;1118:1;1115;1108:12;1070:52;1157:9;1144:23;1176:31;1201:5;1176:31;:::i;:::-;1226:5;1278:2;1263:18;;;;1250:32;;-1:-1:-1;;;973:315:1:o;1293:347::-;1344:8;1354:6;1408:3;1401:4;1393:6;1389:17;1385:27;1375:55;;1426:1;1423;1416:12;1375:55;-1:-1:-1;1449:20:1;;1492:18;1481:30;;1478:50;;;1524:1;1521;1514:12;1478:50;1561:4;1553:6;1549:17;1537:29;;1613:3;1606:4;1597:6;1589;1585:19;1581:30;1578:39;1575:59;;;1630:1;1627;1620:12;1575:59;1293:347;;;;;:::o;1645:762::-;1750:6;1758;1766;1774;1782;1835:3;1823:9;1814:7;1810:23;1806:33;1803:53;;;1852:1;1849;1842:12;1803:53;1891:9;1878:23;1910:31;1935:5;1910:31;:::i;:::-;1960:5;-1:-1:-1;2017:2:1;2002:18;;1989:32;2030:33;1989:32;2030:33;:::i;:::-;2082:7;-1:-1:-1;2140:2:1;2125:18;;2112:32;2167:18;2156:30;;2153:50;;;2199:1;2196;2189:12;2153:50;2238:58;2288:7;2279:6;2268:9;2264:22;2238:58;:::i;:::-;1645:762;;;;-1:-1:-1;2315:8:1;2397:2;2382:18;2369:32;;1645:762;-1:-1:-1;;;;1645:762:1:o;2412:973::-;2535:6;2543;2551;2559;2567;2575;2583;2636:3;2624:9;2615:7;2611:23;2607:33;2604:53;;;2653:1;2650;2643:12;2604:53;2692:9;2679:23;2711:31;2736:5;2711:31;:::i;:::-;2761:5;-1:-1:-1;2818:2:1;2803:18;;2790:32;2831:33;2790:32;2831:33;:::i;:::-;2883:7;-1:-1:-1;2942:2:1;2927:18;;2914:32;2955:33;2914:32;2955:33;:::i;:::-;3007:7;-1:-1:-1;3065:2:1;3050:18;;3037:32;3092:18;3081:30;;3078:50;;;3124:1;3121;3114:12;3078:50;3163:58;3213:7;3204:6;3193:9;3189:22;3163:58;:::i;:::-;2412:973;;;;-1:-1:-1;2412:973:1;;3240:8;;3137:84;3322:3;3307:19;;3294:33;;3374:3;3359:19;3346:33;;-1:-1:-1;2412:973:1;-1:-1:-1;;;;2412:973:1:o;3390:247::-;3449:6;3502:2;3490:9;3481:7;3477:23;3473:32;3470:52;;;3518:1;3515;3508:12;3470:52;3557:9;3544:23;3576:31;3601:5;3576:31;:::i;:::-;3626:5;3390:247;-1:-1:-1;;;3390:247:1:o;4065:160::-;4130:20;;4186:13;;4179:21;4169:32;;4159:60;;4215:1;4212;4205:12;4159:60;4065:160;;;:::o;4230:315::-;4295:6;4303;4356:2;4344:9;4335:7;4331:23;4327:32;4324:52;;;4372:1;4369;4362:12;4324:52;4411:9;4398:23;4430:31;4455:5;4430:31;:::i;:::-;4480:5;-1:-1:-1;4504:35:1;4535:2;4520:18;;4504:35;:::i;:::-;4494:45;;4230:315;;;;;:::o;4550:831::-;4664:6;4672;4680;4688;4696;4704;4757:3;4745:9;4736:7;4732:23;4728:33;4725:53;;;4774:1;4771;4764:12;4725:53;4813:9;4800:23;4832:31;4857:5;4832:31;:::i;:::-;4882:5;-1:-1:-1;4939:2:1;4924:18;;4911:32;4952:33;4911:32;4952:33;:::i;:::-;5004:7;-1:-1:-1;5062:2:1;5047:18;;5034:32;5089:18;5078:30;;5075:50;;;5121:1;5118;5111:12;5075:50;5160:58;5210:7;5201:6;5190:9;5186:22;5160:58;:::i;:::-;4550:831;;;;-1:-1:-1;5237:8:1;5319:2;5304:18;;5291:32;;5370:3;5355:19;;;5342:33;;-1:-1:-1;4550:831:1;-1:-1:-1;;;;4550:831:1:o;5386:155::-;5445:5;5490:3;5481:6;5476:3;5472:16;5468:26;5465:46;;;5507:1;5504;5497:12;5465:46;-1:-1:-1;5529:6:1;5386:155;-1:-1:-1;5386:155:1:o;5546:1097::-;5703:6;5711;5719;5727;5735;5743;5751;5759;5812:3;5800:9;5791:7;5787:23;5783:33;5780:53;;;5829:1;5826;5819:12;5780:53;5868:9;5855:23;5887:31;5912:5;5887:31;:::i;:::-;5937:5;-1:-1:-1;5994:2:1;5979:18;;5966:32;6007:33;5966:32;6007:33;:::i;:::-;6059:7;-1:-1:-1;6118:2:1;6103:18;;6090:32;6131:33;6090:32;6131:33;:::i;:::-;6183:7;-1:-1:-1;6241:2:1;6226:18;;6213:32;6268:18;6257:30;;6254:50;;;6300:1;6297;6290:12;6254:50;6339:58;6389:7;6380:6;6369:9;6365:22;6339:58;:::i;:::-;6416:8;;-1:-1:-1;6313:84:1;-1:-1:-1;;6498:3:1;6483:19;;6470:33;;-1:-1:-1;6550:3:1;6535:19;;6522:33;;-1:-1:-1;6574:63:1;6629:7;6623:3;6608:19;;6574:63;:::i;:::-;6564:73;;5546:1097;;;;;;;;;;;:::o;6648:955::-;6796:6;6804;6812;6820;6828;6836;6844;6897:3;6885:9;6876:7;6872:23;6868:33;6865:53;;;6914:1;6911;6904:12;6865:53;6953:9;6940:23;6972:31;6997:5;6972:31;:::i;:::-;7022:5;-1:-1:-1;7079:2:1;7064:18;;7051:32;7092:33;7051:32;7092:33;:::i;:::-;7144:7;-1:-1:-1;7202:2:1;7187:18;;7174:32;7229:18;7218:30;;7215:50;;;7261:1;7258;7251:12;7215:50;7300:58;7350:7;7341:6;7330:9;7326:22;7300:58;:::i;:::-;7377:8;;-1:-1:-1;7274:84:1;-1:-1:-1;;7459:2:1;7444:18;;7431:32;;-1:-1:-1;7510:3:1;7495:19;;7482:33;;-1:-1:-1;7534:63:1;7589:7;7583:3;7568:19;;7534:63;:::i;:::-;7524:73;;6648:955;;;;;;;;;;:::o;9156:184::-;9226:6;9279:2;9267:9;9258:7;9254:23;9250:32;9247:52;;;9295:1;9292;9285:12;9247:52;-1:-1:-1;9318:16:1;;9156:184;-1:-1:-1;9156:184:1:o;9345:::-;-1:-1:-1;;;9394:1:1;9387:88;9494:4;9491:1;9484:15;9518:4;9515:1;9508:15;9534:125;9574:4;9602:1;9599;9596:8;9593:34;;;9607:18;;:::i;:::-;-1:-1:-1;9644:9:1;;9534:125::o;9664:271::-;9847:6;9839;9834:3;9821:33;9803:3;9873:16;;9898:13;;;9873:16;9664:271;-1:-1:-1;9664:271:1:o;10277:156::-;10343:20;;10403:4;10392:16;;10382:27;;10372:55;;10423:1;10420;10413:12;10438:1001;10520:6;10573:3;10561:9;10552:7;10548:23;10544:33;10541:53;;;10590:1;10587;10580:12;10541:53;10623:2;10617:9;10665:3;10657:6;10653:16;10735:6;10723:10;10720:22;10699:18;10687:10;10684:34;10681:62;10678:242;;;-1:-1:-1;;;10773:1:1;10766:88;10877:4;10874:1;10867:15;10905:4;10902:1;10895:15;10678:242;10940:10;10936:2;10929:22;;10988:9;10975:23;10967:6;10960:39;11060:2;11049:9;11045:18;11032:32;11027:2;11019:6;11015:15;11008:57;11126:2;11115:9;11111:18;11098:32;11093:2;11085:6;11081:15;11074:57;11164:35;11195:2;11184:9;11180:18;11164:35;:::i;:::-;11159:2;11151:6;11147:15;11140:60;11234:37;11266:3;11255:9;11251:19;11234:37;:::i;:::-;11228:3;11220:6;11216:16;11209:63;11334:3;11323:9;11319:19;11306:33;11300:3;11292:6;11288:16;11281:59;11402:3;11391:9;11387:19;11374:33;11368:3;11360:6;11356:16;11349:59;11427:6;11417:16;;;10438:1001;;;;:::o;13502:168::-;13542:7;13608:1;13604;13600:6;13596:14;13593:1;13590:21;13585:1;13578:9;13571:17;13567:45;13564:71;;;13615:18;;:::i;:::-;-1:-1:-1;13655:9:1;;13502:168::o;13675:274::-;13715:1;13741;13731:189;;-1:-1:-1;;;13773:1:1;13766:88;13877:4;13874:1;13867:15;13905:4;13902:1;13895:15;13731:189;-1:-1:-1;13934:9:1;;13675:274::o
Swarm Source
ipfs://9870dd0dc3fb83baf72036a002768c9388c9b2cbf93b6d7b09369fddefaaf877
Loading...
Loading
Loading...
Loading

Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.