false
false
0

Contract Address Details

0x4C46b3Ef0Fada5e33A82c7Cc117C73840e72170f

Contract Name
CallistoBridge
Creator
0xb7971f–a51f91 at 0x043ec3–c0d216
Balance
0 CLO
Tokens
Fetching tokens...
Transactions
16 Transactions
Transfers
0 Transfers
Gas Used
877,402
Last Balance Update
16286287
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
CallistoBridge




Optimization enabled
true
Compiler version
v0.8.7+commit.e28d00a7




Optimization runs
200
EVM Version
default




Verified at
2024-09-26T08:16:40.702009Z

Contract source code

// SPDX-License-Identifier: No License (None)
pragma solidity ^0.8.0;

interface IERC223TokenCloned {
    // initialize cloned token just for ERC223TokenCloned
    function initialize(address newOwner, string calldata name, string calldata symbol, uint8 decimals) external;
    function mint(address user, uint256 amount) external;
    function burnFrom(address account, uint256 amount) external returns(bool);
    function burn(uint256 amount) external returns(bool);
    function balanceOf(address account) external view returns (uint256);
    function allowance(address _owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
}

interface IContractCaller {
    function callContract(address user, address token, uint256 value, address toContract, bytes memory data) external payable;
}

/**
 * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for
 * deploying minimal proxy contracts, also known as "clones".
 *
 * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies
 * > a minimal bytecode implementation that delegates all calls to a known, fixed address.
 *
 * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`
 * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the
 * deterministic method.
 *
 * _Available since v3.4._
 */
library Clones {
    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     *
     * This function uses the create opcode, which should never revert.
     */
    function clone(address implementation) internal returns (address instance) {
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(ptr, 0x14), shl(0x60, implementation))
            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
            instance := create(0, ptr, 0x37)
        }
        require(instance != address(0), "ERC1167: create failed");
    }

    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     *
     * This function uses the create2 opcode and a `salt` to deterministically deploy
     * the clone. Using the same `implementation` and `salt` multiple time will revert, since
     * the clones cannot be deployed twice at the same address.
     */
    function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(ptr, 0x14), shl(0x60, implementation))
            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
            instance := create2(0, ptr, 0x37, salt)
        }
        require(instance != address(0), "ERC1167: create2 failed");
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(
        address implementation,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(ptr, 0x14), shl(0x60, implementation))
            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)
            mstore(add(ptr, 0x38), shl(0x60, deployer))
            mstore(add(ptr, 0x4c), salt)
            mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))
            predicted := keccak256(add(ptr, 0x37), 0x55)
        }
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(address implementation, bytes32 salt)
        internal
        view
        returns (address predicted)
    {
        return predictDeterministicAddress(implementation, salt, address(this));
    }
}

// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
    function safeApprove(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
    }

    function safeTransfer(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
    }

    function safeTransferFrom(address token, address from, address to, uint value) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
    }

    function safeTransferETH(address to, uint value) internal {
        (bool success,) = to.call{value:value}(new bytes(0));
        require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
    }
}

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256`
 * (`UintSet`) are supported.
 */
library EnumerableSet {

    struct AddressSet {
        // Storage of set values
        address[] _values;

        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping (address => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        if (!contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) { // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            address lastvalue = set._values[lastIndex];

            // Move the last value to the index where the value to delete is
            set._values[toDeleteIndex] = lastvalue;
            // Update the index for the moved value
            set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns 1-based index of value in the set. O(1).
     */
    function indexOf(AddressSet storage set, address value) internal view returns (uint256) {
        return set._indexes[value];
    }


    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return set._values.length;
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        require(set._values.length > index, "EnumerableSet: index out of bounds");
        return set._values[index];
    }
}

abstract contract Ownable {
    address internal _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    /* will use initialize instead
    constructor () {
        _owner = msg.sender;
        emit OwnershipTransferred(address(0), msg.sender);
    }
    */
    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == msg.sender, "Ownable: caller is not the owner");
        _;
    }

}

contract CallistoBridge is Ownable {
    using TransferHelper for address;
    using EnumerableSet for EnumerableSet.AddressSet;
    EnumerableSet.AddressSet authorities; // authority has to sign claim transaction (message)

    address constant MAX_NATIVE_COINS = address(31); // addresses from address(1) to MAX_NATIVE_COINS are considered as native coins 
                                            // CLO = address(1)
    struct Token {
        address token;  // foreign token address
        bool isWrapped; // is native token wrapped of foreign
    }

    struct Upgrade {
        address newContract;
        uint64  validFrom;
    }

    uint256 public threshold;   // minimum number of signatures required to approve swap
    address public tokenImplementation;    // implementation of wrapped token
    address public feeTo; // send fee to this address
    bool public frozen; // if frozen - swap will not work
    uint256 public wrapNonce;   // the last nonce used to create wrapped token address begin with 0xCC.... 
    mapping(uint256 => mapping(bytes32 => bool)) public isTxProcessed;    // chainID => txID => isProcessed
    mapping(uint256 => mapping(address => Token)) public tokenPair;       // chainID => native token address => Token struct
    mapping(uint256 => mapping(address => address)) public tokenForeign;  // chainID => foreign token address => native token
    mapping(address => uint256) public tokenDeposits;  // amount of tokens were deposited by users
    mapping(address => bool) public isFreezer;  // addresses that have right to freeze contract 
    uint256 public setupMode;   // time when setup mode will start, 0 if disable
    Upgrade public upgradeData;
    address public founders;
    address public requiredAuthority;   // authority address that MUST sign swap transaction
    mapping(address => address) public migration;   // migration oldToken => newToken
    bool public migrationSetupForbidden;    // forbid adding migration tokens
    address public contractCaller; // intermediate contract that calls third-party contract functions (toContract)
    uint256 public functionMapping;    // bitmap of locked functions (one bit per function)

    event SetAuthority(address authority, bool isEnable);
    event SetFeeTo(address previousFeeTo, address newFeeTo);
    event SetThreshold(uint256 threshold);
    event SetContractCaller(address newContractCaller);
    event Deposit(address indexed token, address indexed sender, uint256 value, uint256 toChainId, address toToken);
    event Claim(address indexed token, address indexed to, uint256 value, bytes32 txId, uint256 fromChainId, address fromToken);
    event Fee(address indexed sender, uint256 fee);
    event CreatePair(address toToken, bool isWrapped, address fromToken, uint256 fromChainId);
    event Frozen(bool status);
    event RescuedERC20(address token, address to, uint256 value);
    event SetFreezer(address freezer, bool isActive);
    event SetupMode(uint time);
    event UpgradeRequest(address newContract, uint256 validFrom);
    event AddTokenMigration(address tokenFrom, address tokenTo);
    event BridgeToContract(address indexed token, address indexed sender, uint256 value, uint256 toChainId, address toToken, address toContract, bytes data);
    event ClaimToContract(address indexed token, address indexed to, uint256 value, bytes32 txId, uint256 fromChainId, address fromToken, address toContract);

    // run only once from proxy
    function initialize(address newOwner, address newFounders, address _tokenImplementation) external {
        require(newOwner != address(0) && newFounders != address(0) && founders == address(0)); // run only once
        _owner = newOwner;
        founders = newFounders;
        emit OwnershipTransferred(address(0), msg.sender);
        require(_tokenImplementation != address(0), "Wrong tokenImplementation");
        tokenImplementation = _tokenImplementation;
        feeTo = msg.sender;
        threshold = 1;
        setupMode = 1; // allow setup after deployment
    }
    /*
    constructor (address _tokenImplementation) {
        require(_tokenImplementation != address(0), "Wrong tokenImplementation");
        tokenImplementation = _tokenImplementation;
        feeTo = msg.sender;
        threshold = 1;
    }
    */
    modifier notFrozen() {
        require(!frozen, "Bridge is frozen");
        _;
    }

    // allowed only in setup mode
    modifier onlySetup() {
        uint256 mode = setupMode; //use local variable to save gas
        require(mode != 0 && mode < block.timestamp, "Not in setup mode");
        _;
    }

    function upgradeTo() external view returns(address newContract) {
        Upgrade memory upg = upgradeData;
        require(upg.validFrom < block.timestamp && upg.newContract != address(0), "Upgrade not allowed");
        newContract = upg.newContract;
    }

    function requestUpgrade(address newContract) external onlyOwner {
        require(newContract != address(0), "Zero address");
        uint256 validFrom = block.timestamp + 3 days;
        upgradeData = Upgrade(newContract, uint64(validFrom));
        emit UpgradeRequest(newContract, validFrom);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */

    function transferOwnership(address newOwner) public {
        require(founders == msg.sender, "Ownable: caller is not the founders");
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }

    function ChangeFounder(address newFounders) public {
        require(founders == msg.sender, "caller is not the founders");
        require(newFounders != address(0), "new owner is the zero address");
        emit OwnershipTransferred(founders, newFounders);
        founders = newFounders;
    }

    // get number of authorities
    function getAuthoritiesNumber() external view returns(uint256) {
        return authorities.length();
    }

    // returns list of authorities addresses
    function getAuthorities() external view returns(address[] memory) {
        return authorities._values;
    }

    // Owner or Authority may freeze bridge in case of anomaly detection
    function freeze() external {
        require(msg.sender == owner() || authorities.contains(msg.sender) || isFreezer[msg.sender]);
        frozen = true;
        emit Frozen(true);
    }

    // Only owner can manually unfreeze contract
    function unfreeze() external onlyOwner onlySetup {
        frozen = false;
        emit Frozen(false);
    }

    function lockFunctions(uint256 _functionMapping) external onlyOwner {
        functionMapping = _functionMapping;
    }

    // add authority
    function setFreezer(address freezer, bool isActive) external onlyOwner {
        require(freezer != address(0), "Zero address");
        isFreezer[freezer] = isActive;
        emit SetFreezer(freezer, isActive);
    }

    // add authority
    function addAuthority(address authority) external onlyOwner onlySetup {
        require(authority != address(0), "Zero address");
        require(authorities.length() < 255, "Too many authorities");
        require(authorities.add(authority), "Authority already added");
        emit SetAuthority(authority, true);
    }

    // remove authority
    function removeAuthority(address authority) external onlyOwner {
        require(authorities.remove(authority), "Authority does not exist");
        emit SetAuthority(authority, false);
    }

    // set authority address that MUST sign claim request
    function setRequiredAuthority(address authority) external onlyOwner onlySetup {
        requiredAuthority = authority;
    }

    // set fee receiver address
    function setFeeTo(address newFeeTo) external onlyOwner onlySetup {
        require(newFeeTo != address(0), "Zero address");
        address previousFeeTo = feeTo;
        feeTo = newFeeTo;
        emit SetFeeTo(previousFeeTo, newFeeTo);
    }

    // set threshold - minimum number of signatures required to approve swap
    function setThreshold(uint256 _threshold) external onlyOwner onlySetup {
        require(threshold != 0 && threshold <= authorities.length(), "Wrong threshold");
        threshold = _threshold;
        emit SetThreshold(threshold);
    }

    // set contractCaller address
    function setContractCaller(address newContractCaller) external onlyOwner onlySetup {
        contractCaller = newContractCaller;
        emit SetContractCaller(newContractCaller);
    }

    function disableSetupMode() external onlyOwner {
        setupMode = 0;
        emit SetupMode(0);
    }

    function enableSetupMode() external onlyOwner {
        setupMode = block.timestamp + 1 days;
        emit SetupMode(setupMode);
    }

    // returns `nonce` to use in `createWrappedToken()` to create address starting with 0xCC.....
    function calculateNonce() external view returns(uint256 nonce, address addr) {
        nonce = wrapNonce;
        address implementation = tokenImplementation;
        while (true) {
            nonce++;
            addr = Clones.predictDeterministicAddress(implementation, bytes32(nonce));
            if (uint160(addr) & uint160(0xfF00000000000000000000000000000000000000) == uint160(0xCc00000000000000000000000000000000000000))
                break;
        }
    }

    function rescueERC20(address token, address to) external onlyOwner {
        uint256 value = IERC223TokenCloned(token).balanceOf(address(this)) - tokenDeposits[token];
        token.safeTransfer(to, value);
        emit RescuedERC20(token, to, value);
    }

    // Create wrapped token for foreign token
    function createWrappedToken(
        address fromToken,      // foreign token address
        uint256 fromChainId,    // foreign chain ID where token deployed
        string memory name,     // wrapped token name
        string memory symbol,   // wrapped token symbol
        uint8 decimals,         // wrapped token decimals (should be the same as in original token)
        uint256 nonce           // nonce to create wrapped token address begin with 0xCC.... 
    )
        external
        onlyOwner
        onlySetup
    {
        require(fromToken != address(0), "Wrong token address");
        require(tokenForeign[fromChainId][fromToken] == address(0), "This token already wrapped");
        require(nonce > wrapNonce, "Nonce must be higher then wrapNonce");
        wrapNonce = nonce;
        address wrappedToken = Clones.cloneDeterministic(tokenImplementation, bytes32(nonce));
        IERC223TokenCloned(wrappedToken).initialize(owner(), name, symbol, decimals);
        tokenPair[fromChainId][wrappedToken] = Token(fromToken, true);
        tokenForeign[fromChainId][fromToken] = wrappedToken;
        emit CreatePair(wrappedToken, true, fromToken, fromChainId); //wrappedToken - wrapped token contract address
    }

    /**
     * @dev Create pair between existing tokens on native and foreign chains
     * @param toToken token address on native chain
     * @param fromToken token address on foreign chain
     * @param fromChainId foreign chain ID
     * @param isWrapped `true` if `toToken` is our wrapped token otherwise `false`
     */
    function createPair(address toToken, address fromToken, uint256 fromChainId, bool isWrapped) external onlyOwner onlySetup {
        require(tokenPair[fromChainId][toToken].token == address(0), "Pair already exist");
        tokenPair[fromChainId][toToken] = Token(fromToken, isWrapped);
        tokenForeign[fromChainId][fromToken] = toToken;
        emit CreatePair(toToken, isWrapped, fromToken, fromChainId);
    }

    /**
     * @dev Delete unused pair
     * @param toToken token address on native chain
     * @param fromChainId foreign chain ID
     */
    function deletePair(address toToken, uint256 fromChainId) external onlyOwner onlySetup {
        delete tokenPair[fromChainId][toToken];
    }

    // Move tokens through the bridge and call the contract with 'data' parameters on the destination chain
    function bridgeToContract(
        address receiver,   // address of token receiver on destination chain
        address token,      // token that user send (if token address < 32, then send native coin)
        uint256 value,      // tokens value
        uint256 toChainId,  // destination chain Id where will be claimed tokens
        address toContract, // this contract will be called on destination chain
        bytes memory data   // this data will be passed to contract call (ABI encoded parameters)
    )
        external
        payable
        notFrozen
    {
        require(functionMapping & 2 == 0, "locked");    // check bit 1
        require(receiver != address(0), "Incorrect receiver address");
        address pair_token = _deposit(token, value, toChainId);
        if (token == address(0xbf6c50889d3a620eb42C0F188b65aDe90De958c4) && // BUSDT token on the Callisto chain
            pair_token == address(0xdAC17F958D2ee523a2206206994597C13D831ec7) && // USDT token on the ETH chain
            toChainId == 1 ) // destination is ETH chain
        {
            // Since USDT token on ETH chain has 6 decimals we have to convert 18 decimals of BUSDT to 6 decimals
            value = value / 10**12;
        }
        emit BridgeToContract(token, receiver, value, toChainId, pair_token, toContract, data);
    }

    // Claim tokens from the bridge and call the contract with 'data' parameters
    function claimToContract(
        address token,          // token to receive
        bytes32 txId,           // deposit transaction hash on fromChain 
        address to,             // user address
        uint256 value,          // value of tokens
        uint256 fromChainId,    // chain ID where user deposited
        address toContract,     // this contract will be called on destination chain
        bytes memory data,      // this data will be passed to contract call (ABI encoded parameters)
        bytes[] memory sig      // authority signatures
    ) 
        external
        payable
        notFrozen
    {
        require(functionMapping & 4 == 0, "locked");    // check bit 2
        require(!isTxProcessed[fromChainId][txId], "Transaction already processed");
        Token memory pair = tokenPair[fromChainId][token];
        require(pair.token != address(0), "There is no pair");
        {
        isTxProcessed[fromChainId][txId] = true;

        // Check signature
        address must = requiredAuthority;
        bytes32 messageHash = keccak256(abi.encodePacked(token, to, value, txId, fromChainId, block.chainid, toContract, data));
        messageHash = prefixed(messageHash);
        uint256 uniqSig;
        uint256 set;    // maximum number of authorities is 255
        for (uint i = 0; i < sig.length; i++) {
            address authority = recoverSigner(messageHash, sig[i]);
            if (authority == must) must = address(0);
            uint256 index = authorities.indexOf(authority);
            uint256 mask = 1 << index;
            if (index != 0 && (set & mask) == 0 ) {
                set |= mask;
                uniqSig++;
            }
        }
        require(threshold <= uniqSig, "Require more signatures");
        require(must == address(0), "The required authority does not sign");
        }
        // fix decimals for USDT on ETH
        if (token == address(0xbf6c50889d3a620eb42C0F188b65aDe90De958c4) && // BUSDT token on the Callisto chain
            pair.token == address(0xdAC17F958D2ee523a2206206994597C13D831ec7) && // USDT token on the ETH chain
            fromChainId == 1 ) // from ETH chain
        {
            // Since USDT token on ETH chain has 6 decimals we have to convert 6 decimals to 18 decimals of BUSDT 
            value = value * 10**12;
        }

        if (msg.value != 0) to.safeTransferETH(msg.value);  // send CLO to user as bonus

        // Call toContract
        if(isContract(toContract) && toContract != address(this)) {
            if (token <= MAX_NATIVE_COINS) {
                IContractCaller(contractCaller).callContract{value: value}(to, token, value, toContract, data);
            } else {
                if(pair.isWrapped) {
                    IERC223TokenCloned(token).mint(contractCaller, value);
                } else {
                    tokenDeposits[token] -= value;
                    token.safeTransfer(contractCaller, value);
                }
                IContractCaller(contractCaller).callContract(to, token, value, toContract, data);               
            }
        } else {    // if not contract
            if (token <= MAX_NATIVE_COINS) {
                to.safeTransferETH(value);
            } else {
                if(pair.isWrapped) {
                    IERC223TokenCloned(token).mint(to, value);
                } else {
                    tokenDeposits[token] -= value;
                    token.safeTransfer(to, value);
                }
            }
        }
        emit ClaimToContract(token, to, value, txId, fromChainId, pair.token, toContract);
    }

    // Due to issue in Callisto Explorer when createPair with isWrapped = 0 it sends transaction with isWrapped = 1
    // It makes this pair unusable without chance to fix it.
    // function reversIsWrapped allow to reverse isWrapped value
    function reversIsWrapped(address toToken, uint256 fromChainId) external onlyOwner onlySetup {
        bool isWrapped = tokenPair[fromChainId][toToken].isWrapped;
        tokenPair[fromChainId][toToken].isWrapped = !isWrapped;
    }

    function depositTokens(
        address receiver,   // address of token receiver on destination chain
        address token,      // token that user send (if token address < 32, then send native coin)
        uint256 value,      // tokens value
        uint256 toChainId   // destination chain Id where will be claimed tokens
    ) 
        external
        payable
        notFrozen
    {
        require(functionMapping & 1 == 0, "locked");    // check bit 0
        require(receiver != address(0), "Incorrect receiver address");
        address pair_token = _deposit(token, value, toChainId);
        if (token == address(0xbf6c50889d3a620eb42C0F188b65aDe90De958c4) && // BUSDT token on the Callisto chain
            pair_token == address(0xdAC17F958D2ee523a2206206994597C13D831ec7) && // USDT token on the ETH chain
            toChainId == 1 ) // destination is ETH chain
        {
            // Since USDT token on ETH chain has 6 decimals we have to convert 18 decimals of BUSDT to 6 decimals
            value = value / 10**12;
        }
        emit Deposit(token, receiver, value, toChainId, pair_token);
    }
    
    function depositTokens(
        address token,      // token that user send (if token address < 32, then send native coin)
        uint256 value,      // tokens value
        uint256 toChainId   // destination chain Id where will be claimed tokens
    ) 
        external
        payable
        notFrozen
    {
        address pair_token = _deposit(token, value, toChainId);
        if (token == address(0xbf6c50889d3a620eb42C0F188b65aDe90De958c4) && // BUSDT token on the Callisto chain
            pair_token == address(0xdAC17F958D2ee523a2206206994597C13D831ec7) && // USDT token on the ETH chain
            toChainId == 1 ) // destination is ETH chain
        {
            // Since USDT token on ETH chain has 6 decimals we have to convert 18 decimals of BUSDT to 6 decimals
            value = value / 10**12;
        }
        emit Deposit(token, msg.sender, value, toChainId, pair_token);
    }

    // ERC223 token transfer callback
    // bytes _data = abi.encode(address receiver, uint256 toChainId)
    function tokenReceived(address _from, uint _value, bytes calldata _data) external {
        require(_data.length == 64, "Incorrect _data");
        (
        address receiver,   // address of token receiver on destination chain
        uint256 toChainId   // destination chain Id where will be claimed tokens
        ) = abi.decode(_data, (address, uint256));
        require(receiver != address(0), "Incorrect receiver address");
        address token = msg.sender;
        Token memory pair = tokenPair[toChainId][token];
        require(pair.token != address(0), "There is no pair");
        if(pair.isWrapped) {
            IERC223TokenCloned(token).burn(_value);
        } else {
            tokenDeposits[token] += _value;
        }
        
        emit Deposit(token, receiver, _value, toChainId, pair.token);
    }

    // migrate from ERC20 to ERC223
    function migrate(address token, uint value) external {
        address newToken = migration[token];
        require(newToken != address(0), "No migration token");
        IERC223TokenCloned(token).burnFrom(msg.sender, value);
        IERC223TokenCloned(newToken).mint(msg.sender, value);
    }

/*
    // setup token migration
    function setupTokenMigration(address tokenFrom, address tokenTo) external onlyOwner onlySetup {
        require(!migrationSetupForbidden);
        // assign tokenImplementation here to avoid creation unnecessary function
        tokenImplementation = address(0x4320e2310274dF1C1A46319044286389C6D16987);  // ERC223 token implementation. 
        migration[tokenFrom] = tokenTo;
        emit AddTokenMigration(tokenFrom, tokenTo);
    }

    // forbid setup token migration
    function forbidMigrationSetup() external onlyOwner onlySetup {
        migrationSetupForbidden = true;
    }
*/

    function _deposit(
        address token,      // token that user send (if token address < 32, then send native coin)
        uint256 value,      // tokens value
        uint256 toChainId   // destination chain Id where will be claimed tokens
    ) 
        internal 
        returns (address pair_token) 
    {
        Token memory pair = tokenPair[toChainId][token];
        require(pair.token != address(0), "There is no pair");
        pair_token = pair.token;
        uint256 fee = msg.value;
        if (token <= MAX_NATIVE_COINS) {
            require(value <= msg.value, "Wrong value");
            fee -= value;
        } else {
            if(pair.isWrapped) {
                IERC223TokenCloned(token).burnFrom(msg.sender, value);
            } else {
                tokenDeposits[token] += value;
                token.safeTransferFrom(msg.sender, address(this), value);
            }
        }
        if (fee != 0) {
            feeTo.safeTransferETH(fee);
            emit Fee(msg.sender, fee);
        }
    }

    // claim
    function claim(
        address token,          // token to receive
        bytes32 txId,           // deposit transaction hash on fromChain 
        address to,             // user address
        uint256 value,          // value of tokens
        uint256 fromChainId,    // chain ID where user deposited
        bytes[] memory sig      // authority signatures
    ) 
        external
        notFrozen
    {
        require(!isTxProcessed[fromChainId][txId], "Transaction already processed");
        Token memory pair = tokenPair[fromChainId][token];
        require(pair.token != address(0), "There is no pair");
        isTxProcessed[fromChainId][txId] = true;
        address must = requiredAuthority;
        bytes32 messageHash = keccak256(abi.encodePacked(token, to, value, txId, fromChainId, block.chainid));
        messageHash = prefixed(messageHash);
        uint256 uniqSig;
        uint256 set;    // maximum number of authorities is 255
        for (uint i = 0; i < sig.length; i++) {
            address authority = recoverSigner(messageHash, sig[i]);
            if (authority == must) must = address(0);
            uint256 index = authorities.indexOf(authority);
            uint256 mask = 1 << index;
            if (index != 0 && (set & mask) == 0 ) {
                set |= mask;
                uniqSig++;
            }
        }
        require(threshold <= uniqSig, "Require more signatures");
        require(must == address(0), "The required authority does not sign");
        
        if (token == address(0xbf6c50889d3a620eb42C0F188b65aDe90De958c4) && // BUSDT token on the Callisto chain
            pair.token == address(0xdAC17F958D2ee523a2206206994597C13D831ec7) && // USDT token on the ETH chain
            fromChainId == 1 ) // from ETH chain
        {
            // Since USDT token on ETH chain has 6 decimals we have to convert 6 decimals to 18 decimals of BUSDT 
            value = value * 10**12;
        }

        if (token <= MAX_NATIVE_COINS) {
            to.safeTransferETH(value);
        } else {
            if(pair.isWrapped) {
                IERC223TokenCloned(token).mint(to, value);
            } else {
                tokenDeposits[token] -= value;
                token.safeTransfer(to, value);
            }
        }
        emit Claim(token, to, value, txId, fromChainId, pair.token);
    }

    // Signature methods

    function splitSignature(bytes memory sig)
        internal
        pure
        returns (uint8 v, bytes32 r, bytes32 s)
    {
        require(sig.length == 65);
        assembly {
            // first 32 bytes, after the length prefix
            r := mload(add(sig, 32))
            // second 32 bytes
            s := mload(add(sig, 64))
            // final byte (first byte of the next 32 bytes)
            v := byte(0, mload(add(sig, 96)))
        }
    }

    function recoverSigner(bytes32 message, bytes memory sig)
        internal
        pure
        returns (address)
    {
        uint8 v;
        bytes32 r;
        bytes32 s;

        (v, r, s) = splitSignature(sig);

        return ecrecover(message, v, r, s);
    }

    // Builds a prefixed hash to mimic the behavior of eth_sign.
    function prefixed(bytes32 hash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    function isContract(address account) internal view returns (bool) {
        // This method relies in extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }
}
        

Contract ABI

[{"type":"event","name":"AddTokenMigration","inputs":[{"type":"address","name":"tokenFrom","internalType":"address","indexed":false},{"type":"address","name":"tokenTo","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"BridgeToContract","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false},{"type":"uint256","name":"toChainId","internalType":"uint256","indexed":false},{"type":"address","name":"toToken","internalType":"address","indexed":false},{"type":"address","name":"toContract","internalType":"address","indexed":false},{"type":"bytes","name":"data","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"Claim","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false},{"type":"bytes32","name":"txId","internalType":"bytes32","indexed":false},{"type":"uint256","name":"fromChainId","internalType":"uint256","indexed":false},{"type":"address","name":"fromToken","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"ClaimToContract","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false},{"type":"bytes32","name":"txId","internalType":"bytes32","indexed":false},{"type":"uint256","name":"fromChainId","internalType":"uint256","indexed":false},{"type":"address","name":"fromToken","internalType":"address","indexed":false},{"type":"address","name":"toContract","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"CreatePair","inputs":[{"type":"address","name":"toToken","internalType":"address","indexed":false},{"type":"bool","name":"isWrapped","internalType":"bool","indexed":false},{"type":"address","name":"fromToken","internalType":"address","indexed":false},{"type":"uint256","name":"fromChainId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Deposit","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false},{"type":"uint256","name":"toChainId","internalType":"uint256","indexed":false},{"type":"address","name":"toToken","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Fee","inputs":[{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"uint256","name":"fee","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Frozen","inputs":[{"type":"bool","name":"status","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RescuedERC20","inputs":[{"type":"address","name":"token","internalType":"address","indexed":false},{"type":"address","name":"to","internalType":"address","indexed":false},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SetAuthority","inputs":[{"type":"address","name":"authority","internalType":"address","indexed":false},{"type":"bool","name":"isEnable","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"SetContractCaller","inputs":[{"type":"address","name":"newContractCaller","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"SetFeeTo","inputs":[{"type":"address","name":"previousFeeTo","internalType":"address","indexed":false},{"type":"address","name":"newFeeTo","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"SetFreezer","inputs":[{"type":"address","name":"freezer","internalType":"address","indexed":false},{"type":"bool","name":"isActive","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"SetThreshold","inputs":[{"type":"uint256","name":"threshold","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SetupMode","inputs":[{"type":"uint256","name":"time","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"UpgradeRequest","inputs":[{"type":"address","name":"newContract","internalType":"address","indexed":false},{"type":"uint256","name":"validFrom","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"ChangeFounder","inputs":[{"type":"address","name":"newFounders","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addAuthority","inputs":[{"type":"address","name":"authority","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"bridgeToContract","inputs":[{"type":"address","name":"receiver","internalType":"address"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"uint256","name":"toChainId","internalType":"uint256"},{"type":"address","name":"toContract","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"nonce","internalType":"uint256"},{"type":"address","name":"addr","internalType":"address"}],"name":"calculateNonce","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claim","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"bytes32","name":"txId","internalType":"bytes32"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"uint256","name":"fromChainId","internalType":"uint256"},{"type":"bytes[]","name":"sig","internalType":"bytes[]"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"claimToContract","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"bytes32","name":"txId","internalType":"bytes32"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"uint256","name":"fromChainId","internalType":"uint256"},{"type":"address","name":"toContract","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"bytes[]","name":"sig","internalType":"bytes[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"contractCaller","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createPair","inputs":[{"type":"address","name":"toToken","internalType":"address"},{"type":"address","name":"fromToken","internalType":"address"},{"type":"uint256","name":"fromChainId","internalType":"uint256"},{"type":"bool","name":"isWrapped","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createWrappedToken","inputs":[{"type":"address","name":"fromToken","internalType":"address"},{"type":"uint256","name":"fromChainId","internalType":"uint256"},{"type":"string","name":"name","internalType":"string"},{"type":"string","name":"symbol","internalType":"string"},{"type":"uint8","name":"decimals","internalType":"uint8"},{"type":"uint256","name":"nonce","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deletePair","inputs":[{"type":"address","name":"toToken","internalType":"address"},{"type":"uint256","name":"fromChainId","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"depositTokens","inputs":[{"type":"address","name":"receiver","internalType":"address"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"uint256","name":"toChainId","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"depositTokens","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"uint256","name":"toChainId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"disableSetupMode","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"enableSetupMode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"feeTo","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"founders","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"freeze","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"frozen","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"functionMapping","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getAuthorities","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getAuthoritiesNumber","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"newOwner","internalType":"address"},{"type":"address","name":"newFounders","internalType":"address"},{"type":"address","name":"_tokenImplementation","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isFreezer","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isTxProcessed","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"lockFunctions","inputs":[{"type":"uint256","name":"_functionMapping","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"migrate","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"migration","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"migrationSetupForbidden","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeAuthority","inputs":[{"type":"address","name":"authority","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"requestUpgrade","inputs":[{"type":"address","name":"newContract","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"requiredAuthority","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"rescueERC20","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"to","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"reversIsWrapped","inputs":[{"type":"address","name":"toToken","internalType":"address"},{"type":"uint256","name":"fromChainId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setContractCaller","inputs":[{"type":"address","name":"newContractCaller","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setFeeTo","inputs":[{"type":"address","name":"newFeeTo","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setFreezer","inputs":[{"type":"address","name":"freezer","internalType":"address"},{"type":"bool","name":"isActive","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRequiredAuthority","inputs":[{"type":"address","name":"authority","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setThreshold","inputs":[{"type":"uint256","name":"_threshold","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"setupMode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"threshold","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"tokenDeposits","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"tokenForeign","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"tokenImplementation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"token","internalType":"address"},{"type":"bool","name":"isWrapped","internalType":"bool"}],"name":"tokenPair","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"tokenReceived","inputs":[{"type":"address","name":"_from","internalType":"address"},{"type":"uint256","name":"_value","internalType":"uint256"},{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unfreeze","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"newContract","internalType":"address"},{"type":"uint64","name":"validFrom","internalType":"uint64"}],"name":"upgradeData","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"newContract","internalType":"address"}],"name":"upgradeTo","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"wrapNonce","inputs":[]}]
              

Contract Creation Code

Verify & Publish
0x608060405234801561001057600080fd5b506144ec806100206000396000f3fe6080604052600436106102e45760003560e01c80636b9f97ef11610190578063c21b4865116100dc578063db43968811610095578063f0f201271161006f578063f0f2012714610935578063f2fde38b14610955578063f46901ed14610975578063fa0876711461099557600080fd5b8063db439688146108ba578063df42fd36146108cd578063e6074da71461090857600080fd5b8063c21b4865146107f1578063c987c79414610813578063cda7f83f14610833578063cea9e11014610865578063d04567f314610885578063d544e0101461089a57600080fd5b8063960bfe0411610149578063ad68ebf711610123578063ad68ebf714610771578063b2e916d614610791578063bfd06304146107b1578063c0c53b8b146107d157600080fd5b8063960bfe041461071b578063a02a66ec1461073b578063abb718631461075b57600080fd5b80636b9f97ef146106585780636c65fd6a146106785780638943ec02146106a85780638da5cb5b146106c85780638f715701146106e65780638f995234146106fb57600080fd5b8063411b007e1161024f5780635c5b9f8f1161020857806362a5af3b116101e257806362a5af3b146105de578063685e2486146105f35780636a28f000146106295780636adf74121461063e57600080fd5b80635c5b9f8f1461058b5780635d799f871461059e5780635e14e319146105be57600080fd5b8063411b007e146104f457806342cde4e81461051457806344ddcb601461052a578063487cda0d1461053d5780634dead7321461055057806354cf428a1461056657600080fd5b806326defa73116102a157806326defa73146103f35780632a94a9c8146104135780632b1a7b58146104335780632f3a3d5d1461049f5780633af84ac4146104bf5780633cbdef56146104d457600080fd5b8063017e7e58146102e9578063054f7d9c1461032657806313bf81261461035757806316a27ecd1461037b57806318d27b04146103905780631c673ab8146103b2575b600080fd5b3480156102f557600080fd5b50600554610309906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561033257600080fd5b5060055461034790600160a01b900460ff1681565b604051901515815260200161031d565b34801561036357600080fd5b5061036d600c5481565b60405190815260200161031d565b34801561038757600080fd5b506103096109f0565b34801561039c57600080fd5b506103b06103ab366004613f91565b610a89565b005b3480156103be57600080fd5b506103096103cd366004613fc3565b60096020908152600092835260408084209091529082529020546001600160a01b031681565b3480156103ff57600080fd5b506103b061040e366004613ace565b610ac7565b34801561041f57600080fd5b506103b061042e366004613ace565b610c40565b34801561043f57600080fd5b5061048061044e366004613fc3565b60086020908152600092835260408084209091529082529020546001600160a01b03811690600160a01b900460ff1682565b604080516001600160a01b03909316835290151560208301520161031d565b3480156104ab57600080fd5b50600454610309906001600160a01b031681565b3480156104cb57600080fd5b5061036d610cfc565b3480156104e057600080fd5b506103b06104ef366004613ace565b610d0c565b34801561050057600080fd5b50600e54610309906001600160a01b031681565b34801561052057600080fd5b5061036d60035481565b6103b0610538366004613c34565b610e18565b6103b061054b366004613bee565b610f61565b34801561055c57600080fd5b5061036d60125481565b34801561057257600080fd5b506011546103099061010090046001600160a01b031681565b6103b0610599366004613f3f565b6110a6565b3480156105aa57600080fd5b506103b06105b9366004613b17565b61119f565b3480156105ca57600080fd5b506103b06105d9366004613cbb565b6112d2565b3480156105ea57600080fd5b506103b061138d565b3480156105ff57600080fd5b5061030961060e366004613ace565b6010602052600090815260409020546001600160a01b031681565b34801561063557600080fd5b506103b0611421565b34801561064a57600080fd5b506011546103479060ff1681565b34801561066457600080fd5b506103b0610673366004613ace565b6114cc565b34801561068457600080fd5b50610347610693366004613ace565b600b6020526000908152604090205460ff1681565b3480156106b457600080fd5b506103b06106c3366004613e13565b6115b7565b3480156106d457600080fd5b506000546001600160a01b0316610309565b3480156106f257600080fd5b506103b06117ab565b34801561070757600080fd5b506103b0610716366004613da2565b611826565b34801561072757600080fd5b506103b0610736366004613f91565b611c8d565b34801561074757600080fd5b506103b0610756366004613ace565b611d7b565b34801561076757600080fd5b5061036d60065481565b34801561077d57600080fd5b506103b061078c366004613aeb565b611e04565b34801561079d57600080fd5b506103b06107ac366004613b9b565b611f47565b3480156107bd57600080fd5b506103b06107cc366004613e9c565b6120e3565b3480156107dd57600080fd5b506103b06107ec366004613b50565b612468565b3480156107fd57600080fd5b5061080661258a565b60405161031d9190614151565b34801561081f57600080fd5b506103b061082e366004613aeb565b6125ef565b34801561083f57600080fd5b50610848612698565b604080519283526001600160a01b0390911660208301520161031d565b34801561087157600080fd5b506103b0610880366004613aeb565b6126e1565b34801561089157600080fd5b506103b061277a565b3480156108a657600080fd5b506103b06108b5366004613ace565b6127ea565b6103b06108c8366004613ce9565b6128b9565b3480156108d957600080fd5b506103476108e8366004613fe8565b600760209081526000928352604080842090915290825290205460ff1681565b34801561091457600080fd5b5061036d610923366004613ace565b600a6020526000908152604090205481565b34801561094157600080fd5b50600f54610309906001600160a01b031681565b34801561096157600080fd5b506103b0610970366004613ace565b612eda565b34801561098157600080fd5b506103b0610990366004613ace565b613000565b3480156109a157600080fd5b50600d546109c8906001600160a01b03811690600160a01b900467ffffffffffffffff1682565b604080516001600160a01b03909316835267ffffffffffffffff90911660208301520161031d565b60408051808201909152600d546001600160a01b0381168252600160a01b900467ffffffffffffffff16602082018190526000919042118015610a3c575080516001600160a01b031615155b610a835760405162461bcd60e51b8152602060048201526013602482015272155c19dc985919481b9bdd08185b1b1bddd959606a1b60448201526064015b60405180910390fd5b51919050565b33610a9c6000546001600160a01b031690565b6001600160a01b031614610ac25760405162461bcd60e51b8152600401610a7a90614287565b601255565b33610ada6000546001600160a01b031690565b6001600160a01b031614610b005760405162461bcd60e51b8152600401610a7a90614287565b600c548015801590610b1157504281105b610b2d5760405162461bcd60e51b8152600401610a7a9061420c565b6001600160a01b038216610b535760405162461bcd60e51b8152600401610a7a90614237565b60ff610b5e60015490565b10610ba25760405162461bcd60e51b8152602060048201526014602482015273546f6f206d616e7920617574686f72697469657360601b6044820152606401610a7a565b610bad6001836130e6565b610bf95760405162461bcd60e51b815260206004820152601760248201527f417574686f7269747920616c72656164792061646465640000000000000000006044820152606401610a7a565b604080516001600160a01b0384168152600160208201527f9019659af698fad527191eef17d6d00706d88aa9fabff25a08edea756c36199391015b60405180910390a15050565b33610c536000546001600160a01b031690565b6001600160a01b031614610c795760405162461bcd60e51b8152600401610a7a90614287565b600c548015801590610c8a57504281105b610ca65760405162461bcd60e51b8152600401610a7a9061420c565b60118054610100600160a81b0319166101006001600160a01b038516908102919091179091556040519081527f850b65e0a4a0af8155b0d56212b309166a3618bcd7ba7c1e83f09f3e721f294c90602001610c34565b6000610d0760015490565b905090565b600e546001600160a01b03163314610d665760405162461bcd60e51b815260206004820152601a60248201527f63616c6c6572206973206e6f742074686520666f756e646572730000000000006044820152606401610a7a565b6001600160a01b038116610dbc5760405162461bcd60e51b815260206004820152601d60248201527f6e6577206f776e657220697320746865207a65726f20616464726573730000006044820152606401610a7a565b600e546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600e80546001600160a01b0319166001600160a01b0392909216919091179055565b600554600160a01b900460ff1615610e425760405162461bcd60e51b8152600401610a7a906141e2565b60125460021615610e655760405162461bcd60e51b8152600401610a7a906142bc565b6001600160a01b038616610e8b5760405162461bcd60e51b8152600401610a7a906142dc565b6000610e9886868661315a565b90506001600160a01b03861673bf6c50889d3a620eb42c0f188b65ade90de958c4148015610ee257506001600160a01b03811673dac17f958d2ee523a2206206994597c13d831ec7145b8015610eee5750836001145b15610f0557610f0264e8d4a5100086614395565b94505b866001600160a01b0316866001600160a01b03167f8e3af9ffa3a105195ae58520a6e3ab241268521cd0a0ca519896e650d4fbebe48787858888604051610f50959493929190614313565b60405180910390a350505050505050565b600554600160a01b900460ff1615610f8b5760405162461bcd60e51b8152600401610a7a906141e2565b60125460011615610fae5760405162461bcd60e51b8152600401610a7a906142bc565b6001600160a01b038416610fd45760405162461bcd60e51b8152600401610a7a906142dc565b6000610fe184848461315a565b90506001600160a01b03841673bf6c50889d3a620eb42c0f188b65ade90de958c414801561102b57506001600160a01b03811673dac17f958d2ee523a2206206994597c13d831ec7145b80156110375750816001145b1561104e5761104b64e8d4a5100084614395565b92505b60408051848152602081018490526001600160a01b03838116828401529151878316928716917ff5dd9317b9e63ac316ce44acc85f670b54b339cfa3e9076e1dd55065b922314b919081900360600190a35050505050565b600554600160a01b900460ff16156110d05760405162461bcd60e51b8152600401610a7a906141e2565b60006110dd84848461315a565b90506001600160a01b03841673bf6c50889d3a620eb42c0f188b65ade90de958c414801561112757506001600160a01b03811673dac17f958d2ee523a2206206994597c13d831ec7145b80156111335750816001145b1561114a5761114764e8d4a5100084614395565b92505b60408051848152602081018490526001600160a01b0383811682840152915133928716917ff5dd9317b9e63ac316ce44acc85f670b54b339cfa3e9076e1dd55065b922314b919081900360600190a350505050565b336111b26000546001600160a01b031690565b6001600160a01b0316146111d85760405162461bcd60e51b8152600401610a7a90614287565b6001600160a01b0382166000818152600a60205260408082205490516370a0823160e01b8152306004820152919290916370a082319060240160206040518083038186803b15801561122957600080fd5b505afa15801561123d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112619190613faa565b61126b91906143d6565b90506112816001600160a01b0384168383613351565b604080516001600160a01b038086168252841660208201529081018290527f2c5650189f92c7058626efc371b51fe7e71f37dacb696bc7cad0b1320931974a906060015b60405180910390a1505050565b336112e56000546001600160a01b031690565b6001600160a01b03161461130b5760405162461bcd60e51b8152600401610a7a90614287565b6001600160a01b0382166113315760405162461bcd60e51b8152600401610a7a90614237565b6001600160a01b0382166000818152600b6020908152604091829020805460ff19168515159081179091558251938452908301527feabe320fe7911eab2e5125ac393caa5937659b712f0c3ac43316c61d4bc088019101610c34565b6000546001600160a01b03163314806113b457503360009081526002602052604090205415155b806113ce5750336000908152600b602052604090205460ff165b6113d757600080fd5b6005805460ff60a01b1916600160a01b179055604051600181527f59800d968fcce138300a0019410b4b75041610d65b3cdc5f31656b03ed14912e906020015b60405180910390a1565b336114346000546001600160a01b031690565b6001600160a01b03161461145a5760405162461bcd60e51b8152600401610a7a90614287565b600c54801580159061146b57504281105b6114875760405162461bcd60e51b8152600401610a7a9061420c565b6005805460ff60a01b19169055604051600081527f59800d968fcce138300a0019410b4b75041610d65b3cdc5f31656b03ed14912e906020015b60405180910390a150565b336114df6000546001600160a01b031690565b6001600160a01b0316146115055760405162461bcd60e51b8152600401610a7a90614287565b6001600160a01b03811661152b5760405162461bcd60e51b8152600401610a7a90614237565b600061153a426203f48061437d565b6040805180820182526001600160a01b03851680825267ffffffffffffffff84166020928301819052600d80546001600160e01b0319168317600160a01b90920291909117905582519081529081018390529192507fd990f8f4f90cd3307c50ab3d095cfb65516e999b7584aee60c0af83eb48118de9101610c34565b604081146115f95760405162461bcd60e51b815260206004820152600f60248201526e496e636f7272656374205f6461746160881b6044820152606401610a7a565b60008061160883850185613aeb565b90925090506001600160a01b0382166116335760405162461bcd60e51b8152600401610a7a906142dc565b600081815260086020908152604080832033808552908352928190208151808301909252546001600160a01b038116808352600160a01b90910460ff16151592820192909252906116965760405162461bcd60e51b8152600401610a7a9061425d565b80602001511561172057604051630852cd8d60e31b8152600481018890526001600160a01b038316906342966c6890602401602060405180830381600087803b1580156116e257600080fd5b505af11580156116f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171a9190613f74565b5061174e565b6001600160a01b0382166000908152600a60205260408120805489929061174890849061437d565b90915550505b805160408051898152602081018690526001600160a01b03928316818301529051868316928516917ff5dd9317b9e63ac316ce44acc85f670b54b339cfa3e9076e1dd55065b922314b919081900360600190a35050505050505050565b336117be6000546001600160a01b031690565b6001600160a01b0316146117e45760405162461bcd60e51b8152600401610a7a90614287565b6117f1426201518061437d565b600c8190556040519081527f14936c23481f8e50ff3a556eb966606eaa9dd8180100eb757f3dccb05eb8af4290602001611417565b600554600160a01b900460ff16156118505760405162461bcd60e51b8152600401610a7a906141e2565b600082815260076020908152604080832088845290915290205460ff16156118ba5760405162461bcd60e51b815260206004820152601d60248201527f5472616e73616374696f6e20616c72656164792070726f6365737365640000006044820152606401610a7a565b60008281526008602090815260408083206001600160a01b038a8116855290835292819020815180830190925254928316808252600160a01b90930460ff161515918101919091529061191f5760405162461bcd60e51b8152600401610a7a9061425d565b60008381526007602090815260408083208984528252808320805460ff19166001179055600f54905160608b811b6bffffffffffffffffffffffff199081169483019490945289901b90921660348301526048820187905260688201899052608882018690524660a88301526001600160a01b0316919060c8016040516020818303038152906040528051906020012090506119ba8161346c565b905060008060005b8651811015611a6a5760006119f0858984815181106119e3576119e3614464565b60200260200101516134bf565b9050856001600160a01b0316816001600160a01b03161415611a1157600095505b6001600160a01b0381166000908152600260205260409020546001811b8115801590611a3d5750848116155b15611a54579384179385611a508161441d565b9650505b5050508080611a629061441d565b9150506119c2565b50816003541115611ab75760405162461bcd60e51b815260206004820152601760248201527652657175697265206d6f7265207369676e61747572657360481b6044820152606401610a7a565b6001600160a01b03841615611ade5760405162461bcd60e51b8152600401610a7a9061419e565b6001600160a01b038b1673bf6c50889d3a620eb42c0f188b65ade90de958c4148015611b27575084516001600160a01b031673dac17f958d2ee523a2206206994597c13d831ec7145b8015611b335750866001145b15611b4a57611b478864e8d4a510006143b7565b97505b601f6001600160a01b038c1611611b7357611b6e6001600160a01b038a168961353e565b611c26565b846020015115611be4576040516340c10f1960e01b81526001600160a01b038a81166004830152602482018a90528c16906340c10f1990604401600060405180830381600087803b158015611bc757600080fd5b505af1158015611bdb573d6000803e3d6000fd5b50505050611c26565b6001600160a01b038b166000908152600a6020526040812080548a9290611c0c9084906143d6565b90915550611c2690506001600160a01b038c168a8a613351565b8451604080518a8152602081018d90529081018990526001600160a01b039182166060820152818b16918d16907fc9e45b9f44cc745053533754942aa17989494514aeadbb624b4b5e34a0ce5fc29060800160405180910390a35050505050505050505050565b33611ca06000546001600160a01b031690565b6001600160a01b031614611cc65760405162461bcd60e51b8152600401610a7a90614287565b600c548015801590611cd757504281105b611cf35760405162461bcd60e51b8152600401610a7a9061420c565b60035415801590611d08575060015460035411155b611d465760405162461bcd60e51b815260206004820152600f60248201526e15dc9bdb99c81d1a1c995cda1bdb19608a1b6044820152606401610a7a565b60038290556040518281527f46e8115bf463f9c29a9424fe152addef1bfaf2b43180d19bb7c2c78cc0ff1ebf90602001610c34565b33611d8e6000546001600160a01b031690565b6001600160a01b031614611db45760405162461bcd60e51b8152600401610a7a90614287565b600c548015801590611dc557504281105b611de15760405162461bcd60e51b8152600401610a7a9061420c565b50600f80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b038083166000908152601060205260409020541680611e615760405162461bcd60e51b815260206004820152601260248201527127379036b4b3b930ba34b7b7103a37b5b2b760711b6044820152606401610a7a565b60405163079cc67960e41b8152336004820152602481018390526001600160a01b038416906379cc679090604401602060405180830381600087803b158015611ea957600080fd5b505af1158015611ebd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee19190613f74565b506040516340c10f1960e01b8152336004820152602481018390526001600160a01b038216906340c10f1990604401600060405180830381600087803b158015611f2a57600080fd5b505af1158015611f3e573d6000803e3d6000fd5b50505050505050565b33611f5a6000546001600160a01b031690565b6001600160a01b031614611f805760405162461bcd60e51b8152600401610a7a90614287565b600c548015801590611f9157504281105b611fad5760405162461bcd60e51b8152600401610a7a9061420c565b60008381526008602090815260408083206001600160a01b03898116855292529091205416156120145760405162461bcd60e51b815260206004820152601260248201527114185a5c88185b1c9958591e48195e1a5cdd60721b6044820152606401610a7a565b6040805180820182526001600160a01b03868116808352851515602080850182815260008a8152600883528781208d87168083529084528882209751885493511515600160a01b026001600160a81b0319909416971696909617919091179095558885526009815285852083865281529385902080546001600160a01b0319168417905584519283529282019290925291820152606081018490527f4e37907d987e2429cd26da336a410ffe2d567dc727ed293e6c500023525af2959060800160405180910390a15050505050565b336120f66000546001600160a01b031690565b6001600160a01b03161461211c5760405162461bcd60e51b8152600401610a7a90614287565b600c54801580159061212d57504281105b6121495760405162461bcd60e51b8152600401610a7a9061420c565b6001600160a01b0387166121955760405162461bcd60e51b815260206004820152601360248201527257726f6e6720746f6b656e206164647265737360681b6044820152606401610a7a565b60008681526009602090815260408083206001600160a01b038b8116855292529091205416156122075760405162461bcd60e51b815260206004820152601a60248201527f5468697320746f6b656e20616c726561647920777261707065640000000000006044820152606401610a7a565b60065482116122645760405162461bcd60e51b815260206004820152602360248201527f4e6f6e6365206d75737420626520686967686572207468656e20777261704e6f6044820152626e636560e81b6064820152608401610a7a565b6006829055600454600090612282906001600160a01b03168461360c565b9050806001600160a01b031663f6d2ee866122a56000546001600160a01b031690565b8888886040518563ffffffff1660e01b81526004016122c79493929190614106565b600060405180830381600087803b1580156122e157600080fd5b505af11580156122f5573d6000803e3d6000fd5b505050506040518060400160405280896001600160a01b0316815260200160011515815250600860008981526020019081526020016000206000836001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548160ff021916908315150217905550905050806009600089815260200190815260200160002060008a6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055507f4e37907d987e2429cd26da336a410ffe2d567dc727ed293e6c500023525af2958160018a8a60405161245694939291906001600160a01b039485168152921515602084015292166040820152606081019190915260800190565b60405180910390a15050505050505050565b6001600160a01b0383161580159061248857506001600160a01b03821615155b801561249d5750600e546001600160a01b0316155b6124a657600080fd5b600080546001600160a01b038086166001600160a01b0319928316178355600e8054918616919092161790556040513391907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36001600160a01b0381166125535760405162461bcd60e51b815260206004820152601960248201527f57726f6e6720746f6b656e496d706c656d656e746174696f6e000000000000006044820152606401610a7a565b600480546001600160a01b039092166001600160a01b03199283161790556005805490911633179055505060016003819055600c55565b606060016000018054806020026020016040519081016040528092919081815260200182805480156125e557602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116125c7575b5050505050905090565b336126026000546001600160a01b031690565b6001600160a01b0316146126285760405162461bcd60e51b8152600401610a7a90614287565b600c54801580159061263957504281105b6126555760405162461bcd60e51b8152600401610a7a9061420c565b5060009081526008602090815260408083206001600160a01b0394909416835292905220805460ff60a01b198116600160a01b9182900460ff1615909102179055565b6006546004546000906001600160a01b03165b826126b58161441d565b93506126c3905081846136ac565b915060ff60981b82166033609a1b14156126dc57509091565b6126ab565b336126f46000546001600160a01b031690565b6001600160a01b03161461271a5760405162461bcd60e51b8152600401610a7a90614287565b600c54801580159061272b57504281105b6127475760405162461bcd60e51b8152600401610a7a9061420c565b5060009081526008602090815260408083206001600160a01b0390941683529290522080546001600160a81b0319169055565b3361278d6000546001600160a01b031690565b6001600160a01b0316146127b35760405162461bcd60e51b8152600401610a7a90614287565b6000600c8190556040519081527f14936c23481f8e50ff3a556eb966606eaa9dd8180100eb757f3dccb05eb8af4290602001611417565b336127fd6000546001600160a01b031690565b6001600160a01b0316146128235760405162461bcd60e51b8152600401610a7a90614287565b61282e600182613719565b61287a5760405162461bcd60e51b815260206004820152601860248201527f417574686f7269747920646f6573206e6f7420657869737400000000000000006044820152606401610a7a565b604080516001600160a01b0383168152600060208201527f9019659af698fad527191eef17d6d00706d88aa9fabff25a08edea756c36199391016114c1565b600554600160a01b900460ff16156128e35760405162461bcd60e51b8152600401610a7a906141e2565b601254600416156129065760405162461bcd60e51b8152600401610a7a906142bc565b60008481526007602090815260408083208a845290915290205460ff16156129705760405162461bcd60e51b815260206004820152601d60248201527f5472616e73616374696f6e20616c72656164792070726f6365737365640000006044820152606401610a7a565b60008481526008602090815260408083206001600160a01b038c8116855290835292819020815180830190925254928316808252600160a01b90930460ff16151591810191909152906129d55760405162461bcd60e51b8152600401610a7a9061425d565b60008581526007602090815260408083208b84528252808320805460ff19166001179055600f5490516001600160a01b039091169291612a25918d918c918c918f918d9146918e918e9101614036565b604051602081830303815290604052805190602001209050612a468161346c565b905060008060005b8651811015612ae9576000612a6f858984815181106119e3576119e3614464565b9050856001600160a01b0316816001600160a01b03161415612a9057600095505b6001600160a01b0381166000908152600260205260409020546001811b8115801590612abc5750848116155b15612ad3579384179385612acf8161441d565b9650505b5050508080612ae19061441d565b915050612a4e565b50816003541115612b365760405162461bcd60e51b815260206004820152601760248201527652657175697265206d6f7265207369676e61747572657360481b6044820152606401610a7a565b6001600160a01b03841615612b5d5760405162461bcd60e51b8152600401610a7a9061419e565b505050506001600160a01b03891673bf6c50889d3a620eb42c0f188b65ade90de958c4148015612baa575080516001600160a01b031673dac17f958d2ee523a2206206994597c13d831ec7145b8015612bb65750846001145b15612bcd57612bca8664e8d4a510006143b7565b95505b3415612be657612be66001600160a01b0388163461353e565b833b15158015612bff57506001600160a01b0384163014155b15612dc357601f6001600160a01b038a1611612c8a57601154604051631490ba2d60e31b81526101009091046001600160a01b03169063a485d168908890612c53908b908e9084908b908b906004016140c0565b6000604051808303818588803b158015612c6c57600080fd5b505af1158015612c80573d6000803e3d6000fd5b5050505050612e6d565b806020015115612d04576011546040516340c10f1960e01b81526101009091046001600160a01b039081166004830152602482018890528a16906340c10f1990604401600060405180830381600087803b158015612ce757600080fd5b505af1158015612cfb573d6000803e3d6000fd5b50505050612d50565b6001600160a01b0389166000908152600a602052604081208054889290612d2c9084906143d6565b9091555050601154612d50906001600160a01b038b81169161010090041688613351565b601154604051631490ba2d60e31b81526101009091046001600160a01b03169063a485d16890612d8c908a908d908b908a908a906004016140c0565b600060405180830381600087803b158015612da657600080fd5b505af1158015612dba573d6000803e3d6000fd5b50505050612e6d565b601f6001600160a01b038a1611612dec57612de76001600160a01b0388168761353e565b612e6d565b806020015115612e2b576040516340c10f1960e01b81526001600160a01b038881166004830152602482018890528a16906340c10f1990604401612d8c565b6001600160a01b0389166000908152600a602052604081208054889290612e539084906143d6565b90915550612e6d90506001600160a01b038a168888613351565b805160408051888152602081018b90529081018790526001600160a01b0391821660608201528582166080820152818916918b16907f28c02ecb5177e8f760c85b230b3c9ca9529c7412274a05918bfe438f55dd46429060a00160405180910390a3505050505050505050565b600e546001600160a01b03163314612f405760405162461bcd60e51b815260206004820152602360248201527f4f776e61626c653a2063616c6c6572206973206e6f742074686520666f756e6460448201526265727360e81b6064820152608401610a7a565b6001600160a01b038116612fa55760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a7a565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b336130136000546001600160a01b031690565b6001600160a01b0316146130395760405162461bcd60e51b8152600401610a7a90614287565b600c54801580159061304a57504281105b6130665760405162461bcd60e51b8152600401610a7a9061420c565b6001600160a01b03821661308c5760405162461bcd60e51b8152600401610a7a90614237565b600580546001600160a01b038481166001600160a01b031983168117909355604080519190921680825260208201939093527f41d2755f00068d89c23ebc6f1e73ce119a6236a44517ca061f544a3f91c9bca491016112c5565b6001600160a01b038116600090815260018301602052604081205461315057508154600180820184556000848152602080822090930180546001600160a01b0319166001600160a01b03861690811790915585549082528286019093526040902091909155613154565b5060005b92915050565b60008181526008602090815260408083206001600160a01b038781168552908352818420825180840190935254908116808352600160a01b90910460ff16151592820192909252906131be5760405162461bcd60e51b8152600401610a7a9061425d565b8051915034601f6001600160a01b0387161161322357348511156132125760405162461bcd60e51b815260206004820152600b60248201526a57726f6e672076616c756560a81b6044820152606401610a7a565b61321c85826143d6565b90506132f6565b8160200151156132b35760405163079cc67960e41b8152336004820152602481018690526001600160a01b038716906379cc679090604401602060405180830381600087803b15801561327557600080fd5b505af1158015613289573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132ad9190613f74565b506132f6565b6001600160a01b0386166000908152600a6020526040812080548792906132db90849061437d565b909155506132f690506001600160a01b03871633308861385b565b801561334857600554613312906001600160a01b03168261353e565b60405181815233907f7bd3aa7d673767f759ebf216e7f6c12844986c661ae6e0f1d988cf7eb7394d1d9060200160405180910390a25b50509392505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916133ad91906140a4565b6000604051808303816000865af19150503d80600081146133ea576040519150601f19603f3d011682016040523d82523d6000602084013e6133ef565b606091505b50915091508180156134195750805115806134195750808060200190518101906134199190613f74565b6134655760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610a7a565b5050505050565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b6000806000806134ce8561398b565b6040805160008152602081018083528b905260ff8516918101919091526060810183905260808101829052929550909350915060019060a0016020604051602081039080840390855afa158015613529573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b604080516000808252602082019092526001600160a01b03841690839060405161356891906140a4565b60006040518083038185875af1925050503d80600081146135a5576040519150601f19603f3d011682016040523d82523d6000602084013e6135aa565b606091505b50509050806136075760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b6064820152608401610a7a565b505050565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b6028820152826037826000f59150506001600160a01b0381166131545760405162461bcd60e51b815260206004820152601760248201527f455243313136373a2063726561746532206661696c65640000000000000000006044820152606401610a7a565b6000613712838330604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b8152606093841b60148201526f5af43d82803e903d91602b57fd5bf3ff60801b6028820152921b6038830152604c8201526037808220606c830152605591012090565b9392505050565b6001600160a01b038116600090815260018301602052604081205480156138515760006137476001836143d6565b855490915060009061375b906001906143d6565b9050600086600001828154811061377457613774614464565b60009182526020909120015487546001600160a01b03909116915081908890859081106137a3576137a3614464565b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790556137d783600161437d565b6001600160a01b038216600090815260018901602052604090205586548790806138035761380361444e565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b03881682526001898101909152604082209190915594506131549350505050565b6000915050613154565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916138bf91906140a4565b6000604051808303816000865af19150503d80600081146138fc576040519150601f19603f3d011682016040523d82523d6000602084013e613901565b606091505b509150915081801561392b57508051158061392b57508080602001905181019061392b9190613f74565b6139835760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f46416044820152631253115160e21b6064820152608401610a7a565b505050505050565b6000806000835160411461399e57600080fd5b5050506020810151604082015160609092015160001a92909190565b600082601f8301126139cb57600080fd5b8135602067ffffffffffffffff808311156139e8576139e861447a565b8260051b6139f783820161434c565b8481528381019087850183890186018a1015613a1257600080fd5b60009350835b87811015613a4f57813586811115613a2e578586fd5b613a3c8c89838e0101613a5e565b8552509286019290860190600101613a18565b50909998505050505050505050565b600082601f830112613a6f57600080fd5b813567ffffffffffffffff811115613a8957613a8961447a565b613a9c601f8201601f191660200161434c565b818152846020838601011115613ab157600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613ae057600080fd5b813561371281614490565b60008060408385031215613afe57600080fd5b8235613b0981614490565b946020939093013593505050565b60008060408385031215613b2a57600080fd5b8235613b3581614490565b91506020830135613b4581614490565b809150509250929050565b600080600060608486031215613b6557600080fd5b8335613b7081614490565b92506020840135613b8081614490565b91506040840135613b9081614490565b809150509250925092565b60008060008060808587031215613bb157600080fd5b8435613bbc81614490565b93506020850135613bcc81614490565b9250604085013591506060850135613be3816144a8565b939692955090935050565b60008060008060808587031215613c0457600080fd5b8435613c0f81614490565b93506020850135613c1f81614490565b93969395505050506040820135916060013590565b60008060008060008060c08789031215613c4d57600080fd5b8635613c5881614490565b95506020870135613c6881614490565b945060408701359350606087013592506080870135613c8681614490565b915060a087013567ffffffffffffffff811115613ca257600080fd5b613cae89828a01613a5e565b9150509295509295509295565b60008060408385031215613cce57600080fd5b8235613cd981614490565b91506020830135613b45816144a8565b600080600080600080600080610100898b031215613d0657600080fd5b8835613d1181614490565b9750602089013596506040890135613d2881614490565b9550606089013594506080890135935060a0890135613d4681614490565b925060c089013567ffffffffffffffff80821115613d6357600080fd5b613d6f8c838d01613a5e565b935060e08b0135915080821115613d8557600080fd5b50613d928b828c016139ba565b9150509295985092959890939650565b60008060008060008060c08789031215613dbb57600080fd5b8635613dc681614490565b9550602087013594506040870135613ddd81614490565b9350606087013592506080870135915060a087013567ffffffffffffffff811115613e0757600080fd5b613cae89828a016139ba565b60008060008060608587031215613e2957600080fd5b8435613e3481614490565b935060208501359250604085013567ffffffffffffffff80821115613e5857600080fd5b818701915087601f830112613e6c57600080fd5b813581811115613e7b57600080fd5b886020828501011115613e8d57600080fd5b95989497505060200194505050565b60008060008060008060c08789031215613eb557600080fd5b8635613ec081614490565b955060208701359450604087013567ffffffffffffffff80821115613ee457600080fd5b613ef08a838b01613a5e565b95506060890135915080821115613f0657600080fd5b50613f1389828a01613a5e565b935050608087013560ff81168114613f2a57600080fd5b8092505060a087013590509295509295509295565b600080600060608486031215613f5457600080fd5b8335613f5f81614490565b95602085013595506040909401359392505050565b600060208284031215613f8657600080fd5b8151613712816144a8565b600060208284031215613fa357600080fd5b5035919050565b600060208284031215613fbc57600080fd5b5051919050565b60008060408385031215613fd657600080fd5b823591506020830135613b4581614490565b60008060408385031215613ffb57600080fd5b50508035926020909101359150565b600081518084526140228160208601602086016143ed565b601f01601f19169290920160200192915050565b60006bffffffffffffffffffffffff19808b60601b168352808a60601b166014840152886028840152876048840152866068840152856088840152808560601b1660a88401525082516140908160bc8501602087016143ed565b9190910160bc019998505050505050505050565b600082516140b68184602087016143ed565b9190910192915050565b6001600160a01b0386811682528581166020830152604082018590528316606082015260a0608082018190526000906140fb9083018461400a565b979650505050505050565b6001600160a01b038516815260806020820181905260009061412a9083018661400a565b828103604084015261413c818661400a565b91505060ff8316606083015295945050505050565b6020808252825182820181905260009190848201906040850190845b818110156141925783516001600160a01b03168352928401929184019160010161416d565b50909695505050505050565b60208082526024908201527f54686520726571756972656420617574686f7269747920646f6573206e6f742060408201526339b4b3b760e11b606082015260800190565b60208082526010908201526f213934b233b29034b990333937bd32b760811b604082015260600190565b6020808252601190820152704e6f7420696e207365747570206d6f646560781b604082015260600190565b6020808252600c908201526b5a65726f206164647265737360a01b604082015260600190565b60208082526010908201526f2a3432b9329034b9903737903830b4b960811b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252600690820152651b1bd8dad95960d21b604082015260600190565b6020808252601a908201527f496e636f72726563742072656365697665722061646472657373000000000000604082015260600190565b858152602081018590526001600160a01b0384811660408301528316606082015260a0608082018190526000906140fb9083018461400a565b604051601f8201601f1916810167ffffffffffffffff811182821017156143755761437561447a565b604052919050565b6000821982111561439057614390614438565b500190565b6000826143b257634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156143d1576143d1614438565b500290565b6000828210156143e8576143e8614438565b500390565b60005b838110156144085781810151838201526020016143f0565b83811115614417576000848401525b50505050565b600060001982141561443157614431614438565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146144a557600080fd5b50565b80151581146144a557600080fdfea2646970667358221220c754242ef14fc5391e99bf5373eea3041adc0aaedc01346f940786d4a5d23f7864736f6c63430008070033

Deployed ByteCode

0x6080604052600436106102e45760003560e01c80636b9f97ef11610190578063c21b4865116100dc578063db43968811610095578063f0f201271161006f578063f0f2012714610935578063f2fde38b14610955578063f46901ed14610975578063fa0876711461099557600080fd5b8063db439688146108ba578063df42fd36146108cd578063e6074da71461090857600080fd5b8063c21b4865146107f1578063c987c79414610813578063cda7f83f14610833578063cea9e11014610865578063d04567f314610885578063d544e0101461089a57600080fd5b8063960bfe0411610149578063ad68ebf711610123578063ad68ebf714610771578063b2e916d614610791578063bfd06304146107b1578063c0c53b8b146107d157600080fd5b8063960bfe041461071b578063a02a66ec1461073b578063abb718631461075b57600080fd5b80636b9f97ef146106585780636c65fd6a146106785780638943ec02146106a85780638da5cb5b146106c85780638f715701146106e65780638f995234146106fb57600080fd5b8063411b007e1161024f5780635c5b9f8f1161020857806362a5af3b116101e257806362a5af3b146105de578063685e2486146105f35780636a28f000146106295780636adf74121461063e57600080fd5b80635c5b9f8f1461058b5780635d799f871461059e5780635e14e319146105be57600080fd5b8063411b007e146104f457806342cde4e81461051457806344ddcb601461052a578063487cda0d1461053d5780634dead7321461055057806354cf428a1461056657600080fd5b806326defa73116102a157806326defa73146103f35780632a94a9c8146104135780632b1a7b58146104335780632f3a3d5d1461049f5780633af84ac4146104bf5780633cbdef56146104d457600080fd5b8063017e7e58146102e9578063054f7d9c1461032657806313bf81261461035757806316a27ecd1461037b57806318d27b04146103905780631c673ab8146103b2575b600080fd5b3480156102f557600080fd5b50600554610309906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561033257600080fd5b5060055461034790600160a01b900460ff1681565b604051901515815260200161031d565b34801561036357600080fd5b5061036d600c5481565b60405190815260200161031d565b34801561038757600080fd5b506103096109f0565b34801561039c57600080fd5b506103b06103ab366004613f91565b610a89565b005b3480156103be57600080fd5b506103096103cd366004613fc3565b60096020908152600092835260408084209091529082529020546001600160a01b031681565b3480156103ff57600080fd5b506103b061040e366004613ace565b610ac7565b34801561041f57600080fd5b506103b061042e366004613ace565b610c40565b34801561043f57600080fd5b5061048061044e366004613fc3565b60086020908152600092835260408084209091529082529020546001600160a01b03811690600160a01b900460ff1682565b604080516001600160a01b03909316835290151560208301520161031d565b3480156104ab57600080fd5b50600454610309906001600160a01b031681565b3480156104cb57600080fd5b5061036d610cfc565b3480156104e057600080fd5b506103b06104ef366004613ace565b610d0c565b34801561050057600080fd5b50600e54610309906001600160a01b031681565b34801561052057600080fd5b5061036d60035481565b6103b0610538366004613c34565b610e18565b6103b061054b366004613bee565b610f61565b34801561055c57600080fd5b5061036d60125481565b34801561057257600080fd5b506011546103099061010090046001600160a01b031681565b6103b0610599366004613f3f565b6110a6565b3480156105aa57600080fd5b506103b06105b9366004613b17565b61119f565b3480156105ca57600080fd5b506103b06105d9366004613cbb565b6112d2565b3480156105ea57600080fd5b506103b061138d565b3480156105ff57600080fd5b5061030961060e366004613ace565b6010602052600090815260409020546001600160a01b031681565b34801561063557600080fd5b506103b0611421565b34801561064a57600080fd5b506011546103479060ff1681565b34801561066457600080fd5b506103b0610673366004613ace565b6114cc565b34801561068457600080fd5b50610347610693366004613ace565b600b6020526000908152604090205460ff1681565b3480156106b457600080fd5b506103b06106c3366004613e13565b6115b7565b3480156106d457600080fd5b506000546001600160a01b0316610309565b3480156106f257600080fd5b506103b06117ab565b34801561070757600080fd5b506103b0610716366004613da2565b611826565b34801561072757600080fd5b506103b0610736366004613f91565b611c8d565b34801561074757600080fd5b506103b0610756366004613ace565b611d7b565b34801561076757600080fd5b5061036d60065481565b34801561077d57600080fd5b506103b061078c366004613aeb565b611e04565b34801561079d57600080fd5b506103b06107ac366004613b9b565b611f47565b3480156107bd57600080fd5b506103b06107cc366004613e9c565b6120e3565b3480156107dd57600080fd5b506103b06107ec366004613b50565b612468565b3480156107fd57600080fd5b5061080661258a565b60405161031d9190614151565b34801561081f57600080fd5b506103b061082e366004613aeb565b6125ef565b34801561083f57600080fd5b50610848612698565b604080519283526001600160a01b0390911660208301520161031d565b34801561087157600080fd5b506103b0610880366004613aeb565b6126e1565b34801561089157600080fd5b506103b061277a565b3480156108a657600080fd5b506103b06108b5366004613ace565b6127ea565b6103b06108c8366004613ce9565b6128b9565b3480156108d957600080fd5b506103476108e8366004613fe8565b600760209081526000928352604080842090915290825290205460ff1681565b34801561091457600080fd5b5061036d610923366004613ace565b600a6020526000908152604090205481565b34801561094157600080fd5b50600f54610309906001600160a01b031681565b34801561096157600080fd5b506103b0610970366004613ace565b612eda565b34801561098157600080fd5b506103b0610990366004613ace565b613000565b3480156109a157600080fd5b50600d546109c8906001600160a01b03811690600160a01b900467ffffffffffffffff1682565b604080516001600160a01b03909316835267ffffffffffffffff90911660208301520161031d565b60408051808201909152600d546001600160a01b0381168252600160a01b900467ffffffffffffffff16602082018190526000919042118015610a3c575080516001600160a01b031615155b610a835760405162461bcd60e51b8152602060048201526013602482015272155c19dc985919481b9bdd08185b1b1bddd959606a1b60448201526064015b60405180910390fd5b51919050565b33610a9c6000546001600160a01b031690565b6001600160a01b031614610ac25760405162461bcd60e51b8152600401610a7a90614287565b601255565b33610ada6000546001600160a01b031690565b6001600160a01b031614610b005760405162461bcd60e51b8152600401610a7a90614287565b600c548015801590610b1157504281105b610b2d5760405162461bcd60e51b8152600401610a7a9061420c565b6001600160a01b038216610b535760405162461bcd60e51b8152600401610a7a90614237565b60ff610b5e60015490565b10610ba25760405162461bcd60e51b8152602060048201526014602482015273546f6f206d616e7920617574686f72697469657360601b6044820152606401610a7a565b610bad6001836130e6565b610bf95760405162461bcd60e51b815260206004820152601760248201527f417574686f7269747920616c72656164792061646465640000000000000000006044820152606401610a7a565b604080516001600160a01b0384168152600160208201527f9019659af698fad527191eef17d6d00706d88aa9fabff25a08edea756c36199391015b60405180910390a15050565b33610c536000546001600160a01b031690565b6001600160a01b031614610c795760405162461bcd60e51b8152600401610a7a90614287565b600c548015801590610c8a57504281105b610ca65760405162461bcd60e51b8152600401610a7a9061420c565b60118054610100600160a81b0319166101006001600160a01b038516908102919091179091556040519081527f850b65e0a4a0af8155b0d56212b309166a3618bcd7ba7c1e83f09f3e721f294c90602001610c34565b6000610d0760015490565b905090565b600e546001600160a01b03163314610d665760405162461bcd60e51b815260206004820152601a60248201527f63616c6c6572206973206e6f742074686520666f756e646572730000000000006044820152606401610a7a565b6001600160a01b038116610dbc5760405162461bcd60e51b815260206004820152601d60248201527f6e6577206f776e657220697320746865207a65726f20616464726573730000006044820152606401610a7a565b600e546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600e80546001600160a01b0319166001600160a01b0392909216919091179055565b600554600160a01b900460ff1615610e425760405162461bcd60e51b8152600401610a7a906141e2565b60125460021615610e655760405162461bcd60e51b8152600401610a7a906142bc565b6001600160a01b038616610e8b5760405162461bcd60e51b8152600401610a7a906142dc565b6000610e9886868661315a565b90506001600160a01b03861673bf6c50889d3a620eb42c0f188b65ade90de958c4148015610ee257506001600160a01b03811673dac17f958d2ee523a2206206994597c13d831ec7145b8015610eee5750836001145b15610f0557610f0264e8d4a5100086614395565b94505b866001600160a01b0316866001600160a01b03167f8e3af9ffa3a105195ae58520a6e3ab241268521cd0a0ca519896e650d4fbebe48787858888604051610f50959493929190614313565b60405180910390a350505050505050565b600554600160a01b900460ff1615610f8b5760405162461bcd60e51b8152600401610a7a906141e2565b60125460011615610fae5760405162461bcd60e51b8152600401610a7a906142bc565b6001600160a01b038416610fd45760405162461bcd60e51b8152600401610a7a906142dc565b6000610fe184848461315a565b90506001600160a01b03841673bf6c50889d3a620eb42c0f188b65ade90de958c414801561102b57506001600160a01b03811673dac17f958d2ee523a2206206994597c13d831ec7145b80156110375750816001145b1561104e5761104b64e8d4a5100084614395565b92505b60408051848152602081018490526001600160a01b03838116828401529151878316928716917ff5dd9317b9e63ac316ce44acc85f670b54b339cfa3e9076e1dd55065b922314b919081900360600190a35050505050565b600554600160a01b900460ff16156110d05760405162461bcd60e51b8152600401610a7a906141e2565b60006110dd84848461315a565b90506001600160a01b03841673bf6c50889d3a620eb42c0f188b65ade90de958c414801561112757506001600160a01b03811673dac17f958d2ee523a2206206994597c13d831ec7145b80156111335750816001145b1561114a5761114764e8d4a5100084614395565b92505b60408051848152602081018490526001600160a01b0383811682840152915133928716917ff5dd9317b9e63ac316ce44acc85f670b54b339cfa3e9076e1dd55065b922314b919081900360600190a350505050565b336111b26000546001600160a01b031690565b6001600160a01b0316146111d85760405162461bcd60e51b8152600401610a7a90614287565b6001600160a01b0382166000818152600a60205260408082205490516370a0823160e01b8152306004820152919290916370a082319060240160206040518083038186803b15801561122957600080fd5b505afa15801561123d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112619190613faa565b61126b91906143d6565b90506112816001600160a01b0384168383613351565b604080516001600160a01b038086168252841660208201529081018290527f2c5650189f92c7058626efc371b51fe7e71f37dacb696bc7cad0b1320931974a906060015b60405180910390a1505050565b336112e56000546001600160a01b031690565b6001600160a01b03161461130b5760405162461bcd60e51b8152600401610a7a90614287565b6001600160a01b0382166113315760405162461bcd60e51b8152600401610a7a90614237565b6001600160a01b0382166000818152600b6020908152604091829020805460ff19168515159081179091558251938452908301527feabe320fe7911eab2e5125ac393caa5937659b712f0c3ac43316c61d4bc088019101610c34565b6000546001600160a01b03163314806113b457503360009081526002602052604090205415155b806113ce5750336000908152600b602052604090205460ff165b6113d757600080fd5b6005805460ff60a01b1916600160a01b179055604051600181527f59800d968fcce138300a0019410b4b75041610d65b3cdc5f31656b03ed14912e906020015b60405180910390a1565b336114346000546001600160a01b031690565b6001600160a01b03161461145a5760405162461bcd60e51b8152600401610a7a90614287565b600c54801580159061146b57504281105b6114875760405162461bcd60e51b8152600401610a7a9061420c565b6005805460ff60a01b19169055604051600081527f59800d968fcce138300a0019410b4b75041610d65b3cdc5f31656b03ed14912e906020015b60405180910390a150565b336114df6000546001600160a01b031690565b6001600160a01b0316146115055760405162461bcd60e51b8152600401610a7a90614287565b6001600160a01b03811661152b5760405162461bcd60e51b8152600401610a7a90614237565b600061153a426203f48061437d565b6040805180820182526001600160a01b03851680825267ffffffffffffffff84166020928301819052600d80546001600160e01b0319168317600160a01b90920291909117905582519081529081018390529192507fd990f8f4f90cd3307c50ab3d095cfb65516e999b7584aee60c0af83eb48118de9101610c34565b604081146115f95760405162461bcd60e51b815260206004820152600f60248201526e496e636f7272656374205f6461746160881b6044820152606401610a7a565b60008061160883850185613aeb565b90925090506001600160a01b0382166116335760405162461bcd60e51b8152600401610a7a906142dc565b600081815260086020908152604080832033808552908352928190208151808301909252546001600160a01b038116808352600160a01b90910460ff16151592820192909252906116965760405162461bcd60e51b8152600401610a7a9061425d565b80602001511561172057604051630852cd8d60e31b8152600481018890526001600160a01b038316906342966c6890602401602060405180830381600087803b1580156116e257600080fd5b505af11580156116f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171a9190613f74565b5061174e565b6001600160a01b0382166000908152600a60205260408120805489929061174890849061437d565b90915550505b805160408051898152602081018690526001600160a01b03928316818301529051868316928516917ff5dd9317b9e63ac316ce44acc85f670b54b339cfa3e9076e1dd55065b922314b919081900360600190a35050505050505050565b336117be6000546001600160a01b031690565b6001600160a01b0316146117e45760405162461bcd60e51b8152600401610a7a90614287565b6117f1426201518061437d565b600c8190556040519081527f14936c23481f8e50ff3a556eb966606eaa9dd8180100eb757f3dccb05eb8af4290602001611417565b600554600160a01b900460ff16156118505760405162461bcd60e51b8152600401610a7a906141e2565b600082815260076020908152604080832088845290915290205460ff16156118ba5760405162461bcd60e51b815260206004820152601d60248201527f5472616e73616374696f6e20616c72656164792070726f6365737365640000006044820152606401610a7a565b60008281526008602090815260408083206001600160a01b038a8116855290835292819020815180830190925254928316808252600160a01b90930460ff161515918101919091529061191f5760405162461bcd60e51b8152600401610a7a9061425d565b60008381526007602090815260408083208984528252808320805460ff19166001179055600f54905160608b811b6bffffffffffffffffffffffff199081169483019490945289901b90921660348301526048820187905260688201899052608882018690524660a88301526001600160a01b0316919060c8016040516020818303038152906040528051906020012090506119ba8161346c565b905060008060005b8651811015611a6a5760006119f0858984815181106119e3576119e3614464565b60200260200101516134bf565b9050856001600160a01b0316816001600160a01b03161415611a1157600095505b6001600160a01b0381166000908152600260205260409020546001811b8115801590611a3d5750848116155b15611a54579384179385611a508161441d565b9650505b5050508080611a629061441d565b9150506119c2565b50816003541115611ab75760405162461bcd60e51b815260206004820152601760248201527652657175697265206d6f7265207369676e61747572657360481b6044820152606401610a7a565b6001600160a01b03841615611ade5760405162461bcd60e51b8152600401610a7a9061419e565b6001600160a01b038b1673bf6c50889d3a620eb42c0f188b65ade90de958c4148015611b27575084516001600160a01b031673dac17f958d2ee523a2206206994597c13d831ec7145b8015611b335750866001145b15611b4a57611b478864e8d4a510006143b7565b97505b601f6001600160a01b038c1611611b7357611b6e6001600160a01b038a168961353e565b611c26565b846020015115611be4576040516340c10f1960e01b81526001600160a01b038a81166004830152602482018a90528c16906340c10f1990604401600060405180830381600087803b158015611bc757600080fd5b505af1158015611bdb573d6000803e3d6000fd5b50505050611c26565b6001600160a01b038b166000908152600a6020526040812080548a9290611c0c9084906143d6565b90915550611c2690506001600160a01b038c168a8a613351565b8451604080518a8152602081018d90529081018990526001600160a01b039182166060820152818b16918d16907fc9e45b9f44cc745053533754942aa17989494514aeadbb624b4b5e34a0ce5fc29060800160405180910390a35050505050505050505050565b33611ca06000546001600160a01b031690565b6001600160a01b031614611cc65760405162461bcd60e51b8152600401610a7a90614287565b600c548015801590611cd757504281105b611cf35760405162461bcd60e51b8152600401610a7a9061420c565b60035415801590611d08575060015460035411155b611d465760405162461bcd60e51b815260206004820152600f60248201526e15dc9bdb99c81d1a1c995cda1bdb19608a1b6044820152606401610a7a565b60038290556040518281527f46e8115bf463f9c29a9424fe152addef1bfaf2b43180d19bb7c2c78cc0ff1ebf90602001610c34565b33611d8e6000546001600160a01b031690565b6001600160a01b031614611db45760405162461bcd60e51b8152600401610a7a90614287565b600c548015801590611dc557504281105b611de15760405162461bcd60e51b8152600401610a7a9061420c565b50600f80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b038083166000908152601060205260409020541680611e615760405162461bcd60e51b815260206004820152601260248201527127379036b4b3b930ba34b7b7103a37b5b2b760711b6044820152606401610a7a565b60405163079cc67960e41b8152336004820152602481018390526001600160a01b038416906379cc679090604401602060405180830381600087803b158015611ea957600080fd5b505af1158015611ebd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee19190613f74565b506040516340c10f1960e01b8152336004820152602481018390526001600160a01b038216906340c10f1990604401600060405180830381600087803b158015611f2a57600080fd5b505af1158015611f3e573d6000803e3d6000fd5b50505050505050565b33611f5a6000546001600160a01b031690565b6001600160a01b031614611f805760405162461bcd60e51b8152600401610a7a90614287565b600c548015801590611f9157504281105b611fad5760405162461bcd60e51b8152600401610a7a9061420c565b60008381526008602090815260408083206001600160a01b03898116855292529091205416156120145760405162461bcd60e51b815260206004820152601260248201527114185a5c88185b1c9958591e48195e1a5cdd60721b6044820152606401610a7a565b6040805180820182526001600160a01b03868116808352851515602080850182815260008a8152600883528781208d87168083529084528882209751885493511515600160a01b026001600160a81b0319909416971696909617919091179095558885526009815285852083865281529385902080546001600160a01b0319168417905584519283529282019290925291820152606081018490527f4e37907d987e2429cd26da336a410ffe2d567dc727ed293e6c500023525af2959060800160405180910390a15050505050565b336120f66000546001600160a01b031690565b6001600160a01b03161461211c5760405162461bcd60e51b8152600401610a7a90614287565b600c54801580159061212d57504281105b6121495760405162461bcd60e51b8152600401610a7a9061420c565b6001600160a01b0387166121955760405162461bcd60e51b815260206004820152601360248201527257726f6e6720746f6b656e206164647265737360681b6044820152606401610a7a565b60008681526009602090815260408083206001600160a01b038b8116855292529091205416156122075760405162461bcd60e51b815260206004820152601a60248201527f5468697320746f6b656e20616c726561647920777261707065640000000000006044820152606401610a7a565b60065482116122645760405162461bcd60e51b815260206004820152602360248201527f4e6f6e6365206d75737420626520686967686572207468656e20777261704e6f6044820152626e636560e81b6064820152608401610a7a565b6006829055600454600090612282906001600160a01b03168461360c565b9050806001600160a01b031663f6d2ee866122a56000546001600160a01b031690565b8888886040518563ffffffff1660e01b81526004016122c79493929190614106565b600060405180830381600087803b1580156122e157600080fd5b505af11580156122f5573d6000803e3d6000fd5b505050506040518060400160405280896001600160a01b0316815260200160011515815250600860008981526020019081526020016000206000836001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548160ff021916908315150217905550905050806009600089815260200190815260200160002060008a6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055507f4e37907d987e2429cd26da336a410ffe2d567dc727ed293e6c500023525af2958160018a8a60405161245694939291906001600160a01b039485168152921515602084015292166040820152606081019190915260800190565b60405180910390a15050505050505050565b6001600160a01b0383161580159061248857506001600160a01b03821615155b801561249d5750600e546001600160a01b0316155b6124a657600080fd5b600080546001600160a01b038086166001600160a01b0319928316178355600e8054918616919092161790556040513391907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36001600160a01b0381166125535760405162461bcd60e51b815260206004820152601960248201527f57726f6e6720746f6b656e496d706c656d656e746174696f6e000000000000006044820152606401610a7a565b600480546001600160a01b039092166001600160a01b03199283161790556005805490911633179055505060016003819055600c55565b606060016000018054806020026020016040519081016040528092919081815260200182805480156125e557602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116125c7575b5050505050905090565b336126026000546001600160a01b031690565b6001600160a01b0316146126285760405162461bcd60e51b8152600401610a7a90614287565b600c54801580159061263957504281105b6126555760405162461bcd60e51b8152600401610a7a9061420c565b5060009081526008602090815260408083206001600160a01b0394909416835292905220805460ff60a01b198116600160a01b9182900460ff1615909102179055565b6006546004546000906001600160a01b03165b826126b58161441d565b93506126c3905081846136ac565b915060ff60981b82166033609a1b14156126dc57509091565b6126ab565b336126f46000546001600160a01b031690565b6001600160a01b03161461271a5760405162461bcd60e51b8152600401610a7a90614287565b600c54801580159061272b57504281105b6127475760405162461bcd60e51b8152600401610a7a9061420c565b5060009081526008602090815260408083206001600160a01b0390941683529290522080546001600160a81b0319169055565b3361278d6000546001600160a01b031690565b6001600160a01b0316146127b35760405162461bcd60e51b8152600401610a7a90614287565b6000600c8190556040519081527f14936c23481f8e50ff3a556eb966606eaa9dd8180100eb757f3dccb05eb8af4290602001611417565b336127fd6000546001600160a01b031690565b6001600160a01b0316146128235760405162461bcd60e51b8152600401610a7a90614287565b61282e600182613719565b61287a5760405162461bcd60e51b815260206004820152601860248201527f417574686f7269747920646f6573206e6f7420657869737400000000000000006044820152606401610a7a565b604080516001600160a01b0383168152600060208201527f9019659af698fad527191eef17d6d00706d88aa9fabff25a08edea756c36199391016114c1565b600554600160a01b900460ff16156128e35760405162461bcd60e51b8152600401610a7a906141e2565b601254600416156129065760405162461bcd60e51b8152600401610a7a906142bc565b60008481526007602090815260408083208a845290915290205460ff16156129705760405162461bcd60e51b815260206004820152601d60248201527f5472616e73616374696f6e20616c72656164792070726f6365737365640000006044820152606401610a7a565b60008481526008602090815260408083206001600160a01b038c8116855290835292819020815180830190925254928316808252600160a01b90930460ff16151591810191909152906129d55760405162461bcd60e51b8152600401610a7a9061425d565b60008581526007602090815260408083208b84528252808320805460ff19166001179055600f5490516001600160a01b039091169291612a25918d918c918c918f918d9146918e918e9101614036565b604051602081830303815290604052805190602001209050612a468161346c565b905060008060005b8651811015612ae9576000612a6f858984815181106119e3576119e3614464565b9050856001600160a01b0316816001600160a01b03161415612a9057600095505b6001600160a01b0381166000908152600260205260409020546001811b8115801590612abc5750848116155b15612ad3579384179385612acf8161441d565b9650505b5050508080612ae19061441d565b915050612a4e565b50816003541115612b365760405162461bcd60e51b815260206004820152601760248201527652657175697265206d6f7265207369676e61747572657360481b6044820152606401610a7a565b6001600160a01b03841615612b5d5760405162461bcd60e51b8152600401610a7a9061419e565b505050506001600160a01b03891673bf6c50889d3a620eb42c0f188b65ade90de958c4148015612baa575080516001600160a01b031673dac17f958d2ee523a2206206994597c13d831ec7145b8015612bb65750846001145b15612bcd57612bca8664e8d4a510006143b7565b95505b3415612be657612be66001600160a01b0388163461353e565b833b15158015612bff57506001600160a01b0384163014155b15612dc357601f6001600160a01b038a1611612c8a57601154604051631490ba2d60e31b81526101009091046001600160a01b03169063a485d168908890612c53908b908e9084908b908b906004016140c0565b6000604051808303818588803b158015612c6c57600080fd5b505af1158015612c80573d6000803e3d6000fd5b5050505050612e6d565b806020015115612d04576011546040516340c10f1960e01b81526101009091046001600160a01b039081166004830152602482018890528a16906340c10f1990604401600060405180830381600087803b158015612ce757600080fd5b505af1158015612cfb573d6000803e3d6000fd5b50505050612d50565b6001600160a01b0389166000908152600a602052604081208054889290612d2c9084906143d6565b9091555050601154612d50906001600160a01b038b81169161010090041688613351565b601154604051631490ba2d60e31b81526101009091046001600160a01b03169063a485d16890612d8c908a908d908b908a908a906004016140c0565b600060405180830381600087803b158015612da657600080fd5b505af1158015612dba573d6000803e3d6000fd5b50505050612e6d565b601f6001600160a01b038a1611612dec57612de76001600160a01b0388168761353e565b612e6d565b806020015115612e2b576040516340c10f1960e01b81526001600160a01b038881166004830152602482018890528a16906340c10f1990604401612d8c565b6001600160a01b0389166000908152600a602052604081208054889290612e539084906143d6565b90915550612e6d90506001600160a01b038a168888613351565b805160408051888152602081018b90529081018790526001600160a01b0391821660608201528582166080820152818916918b16907f28c02ecb5177e8f760c85b230b3c9ca9529c7412274a05918bfe438f55dd46429060a00160405180910390a3505050505050505050565b600e546001600160a01b03163314612f405760405162461bcd60e51b815260206004820152602360248201527f4f776e61626c653a2063616c6c6572206973206e6f742074686520666f756e6460448201526265727360e81b6064820152608401610a7a565b6001600160a01b038116612fa55760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a7a565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b336130136000546001600160a01b031690565b6001600160a01b0316146130395760405162461bcd60e51b8152600401610a7a90614287565b600c54801580159061304a57504281105b6130665760405162461bcd60e51b8152600401610a7a9061420c565b6001600160a01b03821661308c5760405162461bcd60e51b8152600401610a7a90614237565b600580546001600160a01b038481166001600160a01b031983168117909355604080519190921680825260208201939093527f41d2755f00068d89c23ebc6f1e73ce119a6236a44517ca061f544a3f91c9bca491016112c5565b6001600160a01b038116600090815260018301602052604081205461315057508154600180820184556000848152602080822090930180546001600160a01b0319166001600160a01b03861690811790915585549082528286019093526040902091909155613154565b5060005b92915050565b60008181526008602090815260408083206001600160a01b038781168552908352818420825180840190935254908116808352600160a01b90910460ff16151592820192909252906131be5760405162461bcd60e51b8152600401610a7a9061425d565b8051915034601f6001600160a01b0387161161322357348511156132125760405162461bcd60e51b815260206004820152600b60248201526a57726f6e672076616c756560a81b6044820152606401610a7a565b61321c85826143d6565b90506132f6565b8160200151156132b35760405163079cc67960e41b8152336004820152602481018690526001600160a01b038716906379cc679090604401602060405180830381600087803b15801561327557600080fd5b505af1158015613289573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132ad9190613f74565b506132f6565b6001600160a01b0386166000908152600a6020526040812080548792906132db90849061437d565b909155506132f690506001600160a01b03871633308861385b565b801561334857600554613312906001600160a01b03168261353e565b60405181815233907f7bd3aa7d673767f759ebf216e7f6c12844986c661ae6e0f1d988cf7eb7394d1d9060200160405180910390a25b50509392505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916133ad91906140a4565b6000604051808303816000865af19150503d80600081146133ea576040519150601f19603f3d011682016040523d82523d6000602084013e6133ef565b606091505b50915091508180156134195750805115806134195750808060200190518101906134199190613f74565b6134655760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610a7a565b5050505050565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b6000806000806134ce8561398b565b6040805160008152602081018083528b905260ff8516918101919091526060810183905260808101829052929550909350915060019060a0016020604051602081039080840390855afa158015613529573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b604080516000808252602082019092526001600160a01b03841690839060405161356891906140a4565b60006040518083038185875af1925050503d80600081146135a5576040519150601f19603f3d011682016040523d82523d6000602084013e6135aa565b606091505b50509050806136075760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b6064820152608401610a7a565b505050565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b6028820152826037826000f59150506001600160a01b0381166131545760405162461bcd60e51b815260206004820152601760248201527f455243313136373a2063726561746532206661696c65640000000000000000006044820152606401610a7a565b6000613712838330604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b8152606093841b60148201526f5af43d82803e903d91602b57fd5bf3ff60801b6028820152921b6038830152604c8201526037808220606c830152605591012090565b9392505050565b6001600160a01b038116600090815260018301602052604081205480156138515760006137476001836143d6565b855490915060009061375b906001906143d6565b9050600086600001828154811061377457613774614464565b60009182526020909120015487546001600160a01b03909116915081908890859081106137a3576137a3614464565b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790556137d783600161437d565b6001600160a01b038216600090815260018901602052604090205586548790806138035761380361444e565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b03881682526001898101909152604082209190915594506131549350505050565b6000915050613154565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916138bf91906140a4565b6000604051808303816000865af19150503d80600081146138fc576040519150601f19603f3d011682016040523d82523d6000602084013e613901565b606091505b509150915081801561392b57508051158061392b57508080602001905181019061392b9190613f74565b6139835760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f46416044820152631253115160e21b6064820152608401610a7a565b505050505050565b6000806000835160411461399e57600080fd5b5050506020810151604082015160609092015160001a92909190565b600082601f8301126139cb57600080fd5b8135602067ffffffffffffffff808311156139e8576139e861447a565b8260051b6139f783820161434c565b8481528381019087850183890186018a1015613a1257600080fd5b60009350835b87811015613a4f57813586811115613a2e578586fd5b613a3c8c89838e0101613a5e565b8552509286019290860190600101613a18565b50909998505050505050505050565b600082601f830112613a6f57600080fd5b813567ffffffffffffffff811115613a8957613a8961447a565b613a9c601f8201601f191660200161434c565b818152846020838601011115613ab157600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613ae057600080fd5b813561371281614490565b60008060408385031215613afe57600080fd5b8235613b0981614490565b946020939093013593505050565b60008060408385031215613b2a57600080fd5b8235613b3581614490565b91506020830135613b4581614490565b809150509250929050565b600080600060608486031215613b6557600080fd5b8335613b7081614490565b92506020840135613b8081614490565b91506040840135613b9081614490565b809150509250925092565b60008060008060808587031215613bb157600080fd5b8435613bbc81614490565b93506020850135613bcc81614490565b9250604085013591506060850135613be3816144a8565b939692955090935050565b60008060008060808587031215613c0457600080fd5b8435613c0f81614490565b93506020850135613c1f81614490565b93969395505050506040820135916060013590565b60008060008060008060c08789031215613c4d57600080fd5b8635613c5881614490565b95506020870135613c6881614490565b945060408701359350606087013592506080870135613c8681614490565b915060a087013567ffffffffffffffff811115613ca257600080fd5b613cae89828a01613a5e565b9150509295509295509295565b60008060408385031215613cce57600080fd5b8235613cd981614490565b91506020830135613b45816144a8565b600080600080600080600080610100898b031215613d0657600080fd5b8835613d1181614490565b9750602089013596506040890135613d2881614490565b9550606089013594506080890135935060a0890135613d4681614490565b925060c089013567ffffffffffffffff80821115613d6357600080fd5b613d6f8c838d01613a5e565b935060e08b0135915080821115613d8557600080fd5b50613d928b828c016139ba565b9150509295985092959890939650565b60008060008060008060c08789031215613dbb57600080fd5b8635613dc681614490565b9550602087013594506040870135613ddd81614490565b9350606087013592506080870135915060a087013567ffffffffffffffff811115613e0757600080fd5b613cae89828a016139ba565b60008060008060608587031215613e2957600080fd5b8435613e3481614490565b935060208501359250604085013567ffffffffffffffff80821115613e5857600080fd5b818701915087601f830112613e6c57600080fd5b813581811115613e7b57600080fd5b886020828501011115613e8d57600080fd5b95989497505060200194505050565b60008060008060008060c08789031215613eb557600080fd5b8635613ec081614490565b955060208701359450604087013567ffffffffffffffff80821115613ee457600080fd5b613ef08a838b01613a5e565b95506060890135915080821115613f0657600080fd5b50613f1389828a01613a5e565b935050608087013560ff81168114613f2a57600080fd5b8092505060a087013590509295509295509295565b600080600060608486031215613f5457600080fd5b8335613f5f81614490565b95602085013595506040909401359392505050565b600060208284031215613f8657600080fd5b8151613712816144a8565b600060208284031215613fa357600080fd5b5035919050565b600060208284031215613fbc57600080fd5b5051919050565b60008060408385031215613fd657600080fd5b823591506020830135613b4581614490565b60008060408385031215613ffb57600080fd5b50508035926020909101359150565b600081518084526140228160208601602086016143ed565b601f01601f19169290920160200192915050565b60006bffffffffffffffffffffffff19808b60601b168352808a60601b166014840152886028840152876048840152866068840152856088840152808560601b1660a88401525082516140908160bc8501602087016143ed565b9190910160bc019998505050505050505050565b600082516140b68184602087016143ed565b9190910192915050565b6001600160a01b0386811682528581166020830152604082018590528316606082015260a0608082018190526000906140fb9083018461400a565b979650505050505050565b6001600160a01b038516815260806020820181905260009061412a9083018661400a565b828103604084015261413c818661400a565b91505060ff8316606083015295945050505050565b6020808252825182820181905260009190848201906040850190845b818110156141925783516001600160a01b03168352928401929184019160010161416d565b50909695505050505050565b60208082526024908201527f54686520726571756972656420617574686f7269747920646f6573206e6f742060408201526339b4b3b760e11b606082015260800190565b60208082526010908201526f213934b233b29034b990333937bd32b760811b604082015260600190565b6020808252601190820152704e6f7420696e207365747570206d6f646560781b604082015260600190565b6020808252600c908201526b5a65726f206164647265737360a01b604082015260600190565b60208082526010908201526f2a3432b9329034b9903737903830b4b960811b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252600690820152651b1bd8dad95960d21b604082015260600190565b6020808252601a908201527f496e636f72726563742072656365697665722061646472657373000000000000604082015260600190565b858152602081018590526001600160a01b0384811660408301528316606082015260a0608082018190526000906140fb9083018461400a565b604051601f8201601f1916810167ffffffffffffffff811182821017156143755761437561447a565b604052919050565b6000821982111561439057614390614438565b500190565b6000826143b257634e487b7160e01b600052601260045260246000fd5b500490565b60008160001904831182151516156143d1576143d1614438565b500290565b6000828210156143e8576143e8614438565b500390565b60005b838110156144085781810151838201526020016143f0565b83811115614417576000848401525b50505050565b600060001982141561443157614431614438565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146144a557600080fd5b50565b80151581146144a557600080fdfea2646970667358221220c754242ef14fc5391e99bf5373eea3041adc0aaedc01346f940786d4a5d23f7864736f6c63430008070033