ETH Price: $3,378.38 (-1.91%)
Gas: 2 Gwei

Contract

0x48193776062991c2fE024D9c99C35576A51DaDe0
 
Transaction Hash
Method
Block
From
To
Value
Bulk Unstake201686692024-06-25 12:23:113 days ago1719318191IN
0x48193776...6A51DaDe0
0 ETH0.000827034.40303267
Unstake Llama201355622024-06-20 21:17:118 days ago1718918231IN
0x48193776...6A51DaDe0
0 ETH0.000524915.41704127
Unstake Llama201297022024-06-20 1:35:358 days ago1718847335IN
0x48193776...6A51DaDe0
0 ETH0.000557625.75466426
Unstake Llama201223062024-06-19 0:46:239 days ago1718757983IN
0x48193776...6A51DaDe0
0 ETH0.000122044.66812769
Unstake Llama201223022024-06-19 0:45:359 days ago1718757935IN
0x48193776...6A51DaDe0
0 ETH0.000454454.68990644
Unstake Llama201011442024-06-16 1:43:5912 days ago1718502239IN
0x48193776...6A51DaDe0
0 ETH0.000217872.24846374
Unstake Llama200663022024-06-11 4:48:5917 days ago1718081339IN
0x48193776...6A51DaDe0
0 ETH0.000501376.2829015
Bulk Unstake200492972024-06-08 19:48:2320 days ago1717876103IN
0x48193776...6A51DaDe0
0 ETH0.001024777.03836613
Unstake Llama200479312024-06-08 15:13:3520 days ago1717859615IN
0x48193776...6A51DaDe0
0 ETH0.000591516.10441915
Bulk Unstake200472212024-06-08 12:50:2320 days ago1717851023IN
0x48193776...6A51DaDe0
0 ETH0.001000576.87375884
Bulk Unstake200185902024-06-04 12:54:5924 days ago1717505699IN
0x48193776...6A51DaDe0
0 ETH0.00124058.52206142
Unstake Llama200162932024-06-04 5:12:5924 days ago1717477979IN
0x48193776...6A51DaDe0
0 ETH0.000479484.94940796
Unstake Llama200148672024-06-04 0:26:5924 days ago1717460819IN
0x48193776...6A51DaDe0
0 ETH0.000554355.72147518
Unstake Llama200060722024-06-02 18:57:2326 days ago1717354643IN
0x48193776...6A51DaDe0
0 ETH0.00094839.78640898
Bulk Unstake200029302024-06-02 8:25:4726 days ago1717316747IN
0x48193776...6A51DaDe0
0 ETH0.000752425.3212749
Bulk Unstake199952752024-06-01 6:48:1127 days ago1717224491IN
0x48193776...6A51DaDe0
0 ETH0.000739585.08085079
Bulk Unstake199934172024-06-01 0:33:5927 days ago1717202039IN
0x48193776...6A51DaDe0
0 ETH0.000778945.35123834
Unstake Llama199775502024-05-29 19:19:2330 days ago1717010363IN
0x48193776...6A51DaDe0
0 ETH0.0009883310.19957353
Unstake Llama199601672024-05-27 8:58:5932 days ago1716800339IN
0x48193776...6A51DaDe0
0 ETH0.0011935612.31748767
Unstake Pixlet C...199563522024-05-26 20:10:5933 days ago1716754259IN
0x48193776...6A51DaDe0
0 ETH0.0011315513.26734171
Unstake Llama199549162024-05-26 15:22:3533 days ago1716736955IN
0x48193776...6A51DaDe0
0 ETH0.0013782714.22369515
Unstake Llama199451502024-05-25 6:38:2334 days ago1716619103IN
0x48193776...6A51DaDe0
0 ETH0.00033343.4406862
Bulk Unstake199451282024-05-25 6:33:5934 days ago1716618839IN
0x48193776...6A51DaDe0
0 ETH0.000508893.49493697
Unstake Llama199413742024-05-24 17:56:5935 days ago1716573419IN
0x48193776...6A51DaDe0
0 ETH0.000812797.7886303
Unstake Llama199244432024-05-22 9:10:4737 days ago1716369047IN
0x48193776...6A51DaDe0
0 ETH0.000773797.98547627
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
LlamaZoo

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
Yes with 9999 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity Multiple files format)

File 1 of 12: LlamaZoo.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

import "./ERC1155.sol";
import "./SpitToken.sol";
import "./ERC721.sol";
import "./FxBaseRootTunnel.sol";
import "./Ownable.sol";

/**
   __ _                                               
  / /| | __ _ _ __ ___   __ _/\   /\___ _ __ ___  ___ 
 / / | |/ _` | '_ ` _ \ / _` \ \ / / _ \ '__/ __|/ _ \
/ /__| | (_| | | | | | | (_| |\ V /  __/ |  \__ \  __/
\____/_|\__,_|_| |_| |_|\__,_| \_/ \___|_|  |___/\___|

**/

/// @title Llama Zoo
/// @author delta devs (https://twitter.com/deltadevelopers)

contract LlamaZoo is FxBaseRootTunnel, Ownable {
    /*///////////////////////////////////////////////////////////////
                            STORAGE
    //////////////////////////////////////////////////////////////*/

    /// @notice ERC721 instance of the PixelatedLlama contract.
    ERC721 public pixellatedLlamaContract;
    /// @notice ERC721 instance of the LlamaDraws contract.
    ERC721 public llamaDrawsContract;
    /// @notice ERC1155 instance of the StakingBoost contract.
    ERC1155 public boostContract;
    /// @notice ERC1155 instance of the Pixlet contract.
    ERC1155 public pixletContract;

    struct Staker {
        uint256[] stakedLlamas;
        uint256 stakedPixletCanvas;
        uint256 stakedLlamaDraws;
        uint128 stakedSilverBoosts;
        uint128 stakedGoldBoosts;
    }

    mapping(address => Staker) public userInfo;

    bool public stakingPaused;

    /*///////////////////////////////////////////////////////////////
                            CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/
    constructor(
        address checkpointManager,
        address fxRoot,
        address _pixellatedLlamaContract,
        address _llamaDrawsContract,
        address _boostContract,
        address _pixletContract
    ) FxBaseRootTunnel(checkpointManager, fxRoot) {
        pixellatedLlamaContract = ERC721(_pixellatedLlamaContract);
        llamaDrawsContract = ERC721(_llamaDrawsContract);
        boostContract = ERC1155(_boostContract);
        pixletContract = ERC1155(_pixletContract);
    }

    /*///////////////////////////////////////////////////////////////
                        CONTRACT SETTERS
    //////////////////////////////////////////////////////////////*/

    /// @notice Set the contract addresses for all contract instances.
    /// @param _pixellatedLlamaContract The contract address of PixellatedLlama.
    /// @param _llamaDrawsContract The contract address of LlamaDraws.
    /// @param _boostContract The contract address of RewardBooster.
    /// @param _pixletContract The contract address of the Pixlet contract.
    function setContractAddresses(
        address _pixellatedLlamaContract,
        address _llamaDrawsContract,
        address _boostContract,
        address _pixletContract
    ) public onlyOwner {
        pixellatedLlamaContract = ERC721(_pixellatedLlamaContract);
        llamaDrawsContract = ERC721(_llamaDrawsContract);
        boostContract = ERC1155(_boostContract);
        pixletContract = ERC1155(_pixletContract);
    }

    /// @notice Pauses staking and unstaking, for emergency purposes
    /// @dev If we have to migrate because of Polygon instability or state sync issues, this will save us
    function setStakingPaused(bool paused) public onlyOwner {
        stakingPaused = paused;
    }

    /// @notice For collab.land to give a role based on staking status
    function balanceOf(address owner) public view returns (uint256) {
        uint[] memory llamas = userInfo[owner].stakedLlamas;
        if(llamas.length == 0) return 0;
        for (uint256 i = 0; i < llamas.length; i++) {
           if(llamas[i] < 500) return 1;
        }
        return 2;
    }

    /// @dev Using the mapping directly wasn't returning the array, so we made this helper fuction.
    function getStakedTokens(address user)
        public
        view
        returns (
            uint256[] memory llamas,
            uint256 pixletCanvas,
            uint256 llamaDraws,
            uint128 silverBoosts,
            uint128 goldBoosts
        )
    {
        Staker memory staker = userInfo[user];
        return (
            staker.stakedLlamas,
            staker.stakedPixletCanvas,
            staker.stakedLlamaDraws,
            staker.stakedSilverBoosts,
            staker.stakedGoldBoosts
        );
    }

    /*///////////////////////////////////////////////////////////////
                        UTILITY STAKING LOGIC
    //////////////////////////////////////////////////////////////*/

    function bulkStake(
        uint256[] memory llamas,
        uint128 silverBoosts,
        uint128 goldBoosts,
        uint256 pixletStudio,
        uint256 llamaDraws
    ) public {
        if (llamas.length > 0) stakeMultipleLlamas(llamas);
        stakeBoosts(silverBoosts, goldBoosts);
        if (pixletStudio != 0) stakePixletCanvas(pixletStudio);
        if (llamaDraws != 0) stakeLlamaDraws(llamaDraws);
    }

    function bulkUnstake(
        uint256[] memory llamas,
        uint128 silverBoosts,
        uint128 goldBoosts,
        bool pixletStudio,
        bool llamaDraws
    ) public {
        if (llamas.length > 0) unstakeMultipleLlamas(llamas);
        unstakeBoosts(silverBoosts, goldBoosts);
        if (pixletStudio) unstakePixletCanvas();
        if (llamaDraws) unstakeLlamaDraws();
    }

    function stakeMultipleLlamas(uint256[] memory tokenIds) public {
        require(!stakingPaused, "Staking is currently paused.");
        uint256 animatedCount = 0;
        Staker storage staker = userInfo[msg.sender];
        for (uint256 i = 0; i < tokenIds.length; i++) {
            if (tokenIds[i] < 500) ++animatedCount;
            staker.stakedLlamas.push(tokenIds[i]);
            pixellatedLlamaContract.transferFrom(
                msg.sender,
                address(this),
                tokenIds[i]
            );
        }
        if (animatedCount > 0) {
            _sendMessageToChild(
                abi.encode(
                    msg.sender,
                    uint256(TokenType.AnimatedLlama),
                    animatedCount,
                    true
                )
            );
        }
        if ((tokenIds.length - animatedCount) > 0) {
            _sendMessageToChild(
                abi.encode(
                    msg.sender,
                    uint256(TokenType.StaticLlama),
                    tokenIds.length - animatedCount,
                    true
                )
            );
        }
    }

    function unstakeMultipleLlamas(uint256[] memory tokenIds) public {
        require(!stakingPaused, "Staking is currently paused.");
        uint256 animatedCount = 0;
        Staker storage staker = userInfo[msg.sender];
        for (uint256 i = 0; i < tokenIds.length; i++) {
            uint256 tokenId = tokenIds[i];
            require(containsElement(staker.stakedLlamas, tokenId), "You do not own this llama.");
            if (tokenId < 500) ++animatedCount;
            pixellatedLlamaContract.transferFrom(
                address(this),
                msg.sender,
                tokenId
            );

            uint256[] memory stakedLlamas = staker.stakedLlamas;
            uint256 index;
            for (uint256 j; j < stakedLlamas.length; j++) {
                if (stakedLlamas[j] == tokenId) index = j;
            }
            if (stakedLlamas[index] == tokenId) {
                staker.stakedLlamas[index] = stakedLlamas[
                    staker.stakedLlamas.length - 1
                ];
                staker.stakedLlamas.pop();
            }
        }

        if (animatedCount > 0) {
            _sendMessageToChild(
                abi.encode(
                    msg.sender,
                    uint256(TokenType.AnimatedLlama),
                    animatedCount,
                    false
                )
            );
        }
        if ((tokenIds.length - animatedCount) > 0) {
            _sendMessageToChild(
                abi.encode(
                    msg.sender,
                    uint256(TokenType.StaticLlama),
                    tokenIds.length - animatedCount,
                    false
                )
            );
        }
    }

    /// @notice Stake a LlamaVerse llama.
    /// @param tokenId The tokenId of the llama to stake
    function stakeLlama(uint256 tokenId) external {
        require(!stakingPaused, "Staking is currently paused.");
        bool animated = tokenId < 500;
        Staker storage staker = userInfo[msg.sender];
        staker.stakedLlamas.push(tokenId);
        pixellatedLlamaContract.transferFrom(
            msg.sender,
            address(this),
            tokenId
        );
        _sendMessageToChild(
            abi.encode(
                msg.sender,
                uint256(
                    animated ? TokenType.AnimatedLlama : TokenType.StaticLlama
                ),
                1,
                true
            )
        );
    }

    /// @notice Unstake a LlamaVerse llama.
    /// @param tokenId The tokenId of the llama to unstake
    function unstakeLlama(uint256 tokenId) external {
        require(!stakingPaused, "Staking is currently paused.");
        bool animated = tokenId < 500;
        Staker storage staker = userInfo[msg.sender];
        require(containsElement(staker.stakedLlamas, tokenId), "You do not own this llama.");

        pixellatedLlamaContract.transferFrom(
            address(this),
            msg.sender,
            tokenId
        );

        uint256[] memory stakedLlamas = staker.stakedLlamas;
        uint256 index;
        for (uint256 i; i < stakedLlamas.length; i++) {
            if (stakedLlamas[i] == tokenId) index = i;
        }
        if (stakedLlamas[index] == tokenId) {
            _sendMessageToChild(
                abi.encode(
                    msg.sender,
                    uint256(
                        animated
                            ? TokenType.AnimatedLlama
                            : TokenType.StaticLlama
                    ),
                    1,
                    false
                )
            );
            staker.stakedLlamas[index] = stakedLlamas[
                staker.stakedLlamas.length - 1
            ];
            staker.stakedLlamas.pop();
        }
    }

    /// @notice Stake silver boosts.
    /// @param amount The amount of boosts to stake.
    function stakeSilverBoosts(uint128 amount) public {
        require(!stakingPaused, "Staking is currently paused.");
        require(amount != 0, "Staking 0 is not allowed.");

        userInfo[msg.sender].stakedSilverBoosts += amount;
        boostContract.safeTransferFrom(
            msg.sender,
            address(this),
            2,
            amount,
            ""
        );
        _sendMessageToChild(
            abi.encode(msg.sender, uint256(TokenType.SilverBoost), amount, true)
        );
    }

    /// @notice Unstake silver boosts.
    /// @param amount The amount of boosts to unstake.
    function unstakeSilverBoosts(uint128 amount) public {
        require(!stakingPaused, "Staking is currently paused.");
        require(amount != 0, "Unstaking 0 is not allowed.");

        userInfo[msg.sender].stakedSilverBoosts -= amount;
        boostContract.safeTransferFrom(
            address(this),
            msg.sender,
            2,
            amount,
            ""
        );
        _sendMessageToChild(
            abi.encode(
                msg.sender,
                uint256(TokenType.SilverBoost),
                amount,
                false
            )
        );
    }

    /// @notice Stake gold boosts with the requested tokenID.
    /// @param amount The amount of boosts to stake.
    function stakeGoldBoosts(uint128 amount) public {
        require(!stakingPaused, "Staking is currently paused.");
        require(amount != 0, "Staking 0 is not allowed.");
        userInfo[msg.sender].stakedGoldBoosts += amount;
        boostContract.safeTransferFrom(
            msg.sender,
            address(this),
            1,
            amount,
            ""
        );
        _sendMessageToChild(
            abi.encode(msg.sender, uint256(TokenType.GoldBoost), amount, true)
        );
    }

    /// @notice Unstake gold boosts with the requested tokenID.
    /// @param amount The amount of boosts to stake.
    function unstakeGoldBoosts(uint128 amount) public {
        require(!stakingPaused, "Staking is currently paused.");
        require(amount != 0, "Unstaking 0 is not allowed.");
        userInfo[msg.sender].stakedGoldBoosts -= amount;
        boostContract.safeTransferFrom(
            address(this),
            msg.sender,
            1,
            amount,
            ""
        );
        _sendMessageToChild(
            abi.encode(msg.sender, uint256(TokenType.GoldBoost), amount, false)
        );
    }

    function stakeBoosts(uint128 silverAmount, uint128 goldAmount) public {
        if (silverAmount != 0) stakeSilverBoosts(silverAmount);
        if (goldAmount != 0) stakeGoldBoosts(goldAmount);
    }

    function unstakeBoosts(uint128 silverAmount, uint128 goldAmount) public {
        if (silverAmount != 0) unstakeSilverBoosts(silverAmount);
        if (goldAmount != 0) unstakeGoldBoosts(goldAmount);
    }

    /// @notice Stake a Pixlet Canvas with the requested tokenID.
    /// @param tokenId The token ID of the pixlet canvas to stake.
    function stakePixletCanvas(uint256 tokenId) public {
        require(!stakingPaused, "Staking is currently paused.");
        require(
            userInfo[msg.sender].stakedPixletCanvas == 0,
            "You already have a pixlet canvas staked."
        );

        userInfo[msg.sender].stakedPixletCanvas = tokenId;
        pixletContract.safeTransferFrom(
            msg.sender,
            address(this),
            tokenId,
            1,
            ""
        );

        _sendMessageToChild(
            abi.encode(msg.sender, uint256(TokenType.PixletCanvas), 1, true)
        );
    }

    /// @notice Unstake your Pixlet Canvas.
    function unstakePixletCanvas() public {
        require(!stakingPaused, "Staking is currently paused.");
        require(
            userInfo[msg.sender].stakedPixletCanvas != 0,
            "You do not have a pixlet canvas staked."
        );

        pixletContract.safeTransferFrom(
            address(this),
            msg.sender,
            userInfo[msg.sender].stakedPixletCanvas,
            1,
            ""
        );
        userInfo[msg.sender].stakedPixletCanvas = 0;

        _sendMessageToChild(
            abi.encode(msg.sender, uint256(TokenType.PixletCanvas), 1, false)
        );
    }

    /// @notice Stake a Llamadraws.
    /// @param tokenId The token ID of the llamadraws to stake.
    function stakeLlamaDraws(uint256 tokenId) public {
        require(!stakingPaused, "Staking is currently paused.");
        require(
            userInfo[msg.sender].stakedLlamaDraws == 0,
            "You already have a llamadraws staked."
        );

        userInfo[msg.sender].stakedLlamaDraws = tokenId;
        llamaDrawsContract.transferFrom(msg.sender, address(this), tokenId);

        _sendMessageToChild(
            abi.encode(msg.sender, uint256(TokenType.LlamaDraws), 1, true)
        );
    }

    /// @notice Unstake your Llamadraws.
    function unstakeLlamaDraws() public {
        require(!stakingPaused, "Staking is currently paused.");
        require(
            userInfo[msg.sender].stakedLlamaDraws != 0,
            "You do not have a llamadraws staked."
        );

        llamaDrawsContract.transferFrom(
            address(this),
            msg.sender,
            userInfo[msg.sender].stakedLlamaDraws
        );
        userInfo[msg.sender].stakedLlamaDraws = 0;

        _sendMessageToChild(
            abi.encode(msg.sender, uint256(TokenType.LlamaDraws), 1, false)
        );
    }

    function _processMessageFromChild(bytes memory message) internal override {
        // We don't need a message from child
    }

    function containsElement(uint[] memory elements, uint tokenId) internal returns (bool) {
        for (uint256 i = 0; i < elements.length; i++) {
           if(elements[i] == tokenId) return true;
        }
        return false;
    }


    /*///////////////////////////////////////////////////////////////
                        ERC ON RECEIVED LOGIC
    //////////////////////////////////////////////////////////////*/

    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 id,
        bytes calldata data
    ) external returns (bytes4) {
        return ERC721TokenReceiver.onERC721Received.selector;
    }

    /**
     * @notice Handle the receipt of a single ERC1155 token type.
     * @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeTransferFrom` after the balance has been updated.
     * This function MAY throw to revert and reject the transfer.
     * Return of other amount than the magic value MUST result in the transaction being reverted.
     * Note: The token contract address is always the message sender.
     * @param operator  The address which called the `safeTransferFrom` function.
     * @param from      The address which previously owned the token.
     * @param id        The id of the token being transferred.
     * @param amount    The amount of tokens being transferred.
     * @param data      Additional data with no specified format.
     * @return           `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`.
     */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) external returns (bytes4) {
        return ERC1155TokenReceiver.onERC1155Received.selector;
    }

    /**
     * @notice Handle the receipt of multiple ERC1155 token types.
     * @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeBatchTransferFrom` after the balances have been updated.
     * This function MAY throw to revert and reject the transfer.
     * Return of other amount than the magic value WILL result in the transaction being reverted.
     * Note: The token contract address is always the message sender.
     * @param operator  The address which called the `safeBatchTransferFrom` function.
     * @param from      The address which previously owned the token.
     * @param ids       An array containing ids of each token being transferred.
     * @param amounts   An array containing amounts of each token being transferred.
     * @param data      Additional data with no specified format.
     * @return           `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`.
     */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) external returns (bytes4) {
        return ERC1155TokenReceiver.onERC1155BatchReceived.selector;
    }
}

File 2 of 12: ERC1155.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Minimalist and gas efficient standard ERC1155 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC1155.sol)
abstract contract ERC1155 {
    /*///////////////////////////////////////////////////////////////
                                EVENTS
    //////////////////////////////////////////////////////////////*/

    event TransferSingle(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 id,
        uint256 amount
    );

    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] amounts
    );

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    event URI(string value, uint256 indexed id);

    /*///////////////////////////////////////////////////////////////
                            ERC1155 STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(address => mapping(uint256 => uint256)) public balanceOf;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*///////////////////////////////////////////////////////////////
                             METADATA LOGIC
    //////////////////////////////////////////////////////////////*/

    function uri(uint256 id) public view virtual returns (string memory);

    /*///////////////////////////////////////////////////////////////
                             ERC1155 LOGIC
    //////////////////////////////////////////////////////////////*/

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) public virtual {
        require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");

        balanceOf[from][id] -= amount;
        balanceOf[to][id] += amount;

        emit TransferSingle(msg.sender, from, to, id, amount);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) ==
                    ERC1155TokenReceiver.onERC1155Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) public virtual {
        uint256 idsLength = ids.length; // Saves MLOADs.

        require(idsLength == amounts.length, "LENGTH_MISMATCH");

        require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");

        for (uint256 i = 0; i < idsLength; ) {
            uint256 id = ids[i];
            uint256 amount = amounts[i];

            balanceOf[from][id] -= amount;
            balanceOf[to][id] += amount;

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                i++;
            }
        }

        emit TransferBatch(msg.sender, from, to, ids, amounts);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) ==
                    ERC1155TokenReceiver.onERC1155BatchReceived.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function balanceOfBatch(address[] memory owners, uint256[] memory ids)
        public
        view
        virtual
        returns (uint256[] memory balances)
    {
        uint256 ownersLength = owners.length; // Saves MLOADs.

        require(ownersLength == ids.length, "LENGTH_MISMATCH");

        balances = new uint256[](owners.length);

        // Unchecked because the only math done is incrementing
        // the array index counter which cannot possibly overflow.
        unchecked {
            for (uint256 i = 0; i < ownersLength; i++) {
                balances[i] = balanceOf[owners[i]][ids[i]];
            }
        }
    }

    /*///////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155
            interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI
    }

    /*///////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) internal {
        balanceOf[to][id] += amount;

        emit TransferSingle(msg.sender, address(0), to, id, amount);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) ==
                    ERC1155TokenReceiver.onERC1155Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _batchMint(
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal {
        uint256 idsLength = ids.length; // Saves MLOADs.

        require(idsLength == amounts.length, "LENGTH_MISMATCH");

        for (uint256 i = 0; i < idsLength; ) {
            balanceOf[to][ids[i]] += amounts[i];

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                i++;
            }
        }

        emit TransferBatch(msg.sender, address(0), to, ids, amounts);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) ==
                    ERC1155TokenReceiver.onERC1155BatchReceived.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _batchBurn(
        address from,
        uint256[] memory ids,
        uint256[] memory amounts
    ) internal {
        uint256 idsLength = ids.length; // Saves MLOADs.

        require(idsLength == amounts.length, "LENGTH_MISMATCH");

        for (uint256 i = 0; i < idsLength; ) {
            balanceOf[from][ids[i]] -= amounts[i];

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                i++;
            }
        }

        emit TransferBatch(msg.sender, from, address(0), ids, amounts);
    }

    function _burn(
        address from,
        uint256 id,
        uint256 amount
    ) internal {
        balanceOf[from][id] -= amount;

        emit TransferSingle(msg.sender, from, address(0), id, amount);
    }
}

/// @notice A generic interface for a contract which properly accepts ERC1155 tokens.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC1155.sol)
interface ERC1155TokenReceiver {
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) external returns (bytes4);

    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) external returns (bytes4);
}

File 3 of 12: ERC20.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
    /*///////////////////////////////////////////////////////////////
                                  EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 amount);

    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /*///////////////////////////////////////////////////////////////
                             METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    uint8 public immutable decimals;

    /*///////////////////////////////////////////////////////////////
                              ERC20 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

    mapping(address => mapping(address => uint256)) public allowance;

    /*///////////////////////////////////////////////////////////////
                             EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

    bytes32 public constant PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

    /*///////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals
    ) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;

        INITIAL_CHAIN_ID = block.chainid;
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
    }

    /*///////////////////////////////////////////////////////////////
                              ERC20 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 amount) public virtual returns (bool) {
        allowance[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);

        return true;
    }

    function transfer(address to, uint256 amount) public virtual returns (bool) {
        balanceOf[msg.sender] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(msg.sender, to, amount);

        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual returns (bool) {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);

        return true;
    }

    /*///////////////////////////////////////////////////////////////
                              EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        // Unchecked because the only math done is incrementing
        // the owner's nonce which cannot realistically overflow.
        unchecked {
            bytes32 digest = keccak256(
                abi.encodePacked(
                    "\x19\x01",
                    DOMAIN_SEPARATOR(),
                    keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
                )
            );

            address recoveredAddress = ecrecover(digest, v, r, s);

            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
    }

    function computeDomainSeparator() internal view virtual returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                    keccak256(bytes(name)),
                    keccak256("1"),
                    block.chainid,
                    address(this)
                )
            );
    }

    /*///////////////////////////////////////////////////////////////
                       INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 amount) internal virtual {
        totalSupply += amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint256 amount) internal virtual {
        balanceOf[from] -= amount;

        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }
}

File 4 of 12: ERC721.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
/// @dev Note that balanceOf does not revert if passed the zero address, in defiance of the ERC.
abstract contract ERC721 {
    /*///////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    event Approval(address indexed owner, address indexed spender, uint256 indexed id);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /*///////////////////////////////////////////////////////////////
                          METADATA STORAGE/LOGIC
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    function tokenURI(uint256 id) public view virtual returns (string memory);

    /*///////////////////////////////////////////////////////////////
                            ERC721 STORAGE                        
    //////////////////////////////////////////////////////////////*/

    mapping(address => uint256) public balanceOf;

    mapping(uint256 => address) public ownerOf;

    mapping(uint256 => address) public getApproved;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*///////////////////////////////////////////////////////////////
                              CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    /*///////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 id) public virtual {
        address owner = ownerOf[id];

        require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");

        getApproved[id] = spender;

        emit Approval(owner, spender, id);
    }

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function transferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        require(from == ownerOf[id], "WRONG_FROM");

        require(to != address(0), "INVALID_RECIPIENT");

        require(
            msg.sender == from || msg.sender == getApproved[id] || isApprovedForAll[from][msg.sender],
            "NOT_AUTHORIZED"
        );

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        unchecked {
            balanceOf[from]--;

            balanceOf[to]++;
        }

        ownerOf[id] = to;

        delete getApproved[id];

        emit Transfer(from, to, id);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes memory data
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    /*///////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
            interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
    }

    /*///////////////////////////////////////////////////////////////
                       INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 id) internal virtual {
        require(to != address(0), "INVALID_RECIPIENT");

        require(ownerOf[id] == address(0), "ALREADY_MINTED");

        // Counter overflow is incredibly unrealistic.
        unchecked {
            balanceOf[to]++;
        }

        ownerOf[id] = to;

        emit Transfer(address(0), to, id);
    }

    function _burn(uint256 id) internal virtual {
        address owner = ownerOf[id];

        require(ownerOf[id] != address(0), "NOT_MINTED");

        // Ownership check above ensures no underflow.
        unchecked {
            balanceOf[owner]--;
        }

        delete ownerOf[id];

        delete getApproved[id];

        emit Transfer(owner, address(0), id);
    }

    /*///////////////////////////////////////////////////////////////
                       INTERNAL SAFE MINT LOGIC
    //////////////////////////////////////////////////////////////*/

    function _safeMint(address to, uint256 id) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _safeMint(
        address to,
        uint256 id,
        bytes memory data
    ) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }
}

/// @notice A generic interface for a contract which properly accepts ERC721 tokens.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
interface ERC721TokenReceiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 id,
        bytes calldata data
    ) external returns (bytes4);
}

File 5 of 12: ExitPayloadReader.sol
pragma solidity ^0.8.0;

import {RLPReader} from "./RLPReader.sol";

library ExitPayloadReader {
    using RLPReader for bytes;
    using RLPReader for RLPReader.RLPItem;

    uint8 constant WORD_SIZE = 32;

    struct ExitPayload {
        RLPReader.RLPItem[] data;
    }

    struct Receipt {
        RLPReader.RLPItem[] data;
        bytes raw;
        uint256 logIndex;
    }

    struct Log {
        RLPReader.RLPItem data;
        RLPReader.RLPItem[] list;
    }

    struct LogTopics {
        RLPReader.RLPItem[] data;
    }

    // copy paste of private copy() from RLPReader to avoid changing of existing contracts
    function copy(
        uint256 src,
        uint256 dest,
        uint256 len
    ) private pure {
        if (len == 0) return;

        // copy as many word sizes as possible
        for (; len >= WORD_SIZE; len -= WORD_SIZE) {
            assembly {
                mstore(dest, mload(src))
            }

            src += WORD_SIZE;
            dest += WORD_SIZE;
        }

        // left over bytes. Mask is used to remove unwanted bytes from the word
        uint256 mask = 256**(WORD_SIZE - len) - 1;
        assembly {
            let srcpart := and(mload(src), not(mask)) // zero out src
            let destpart := and(mload(dest), mask) // retrieve the bytes
            mstore(dest, or(destpart, srcpart))
        }
    }

    function toExitPayload(bytes memory data) internal pure returns (ExitPayload memory) {
        RLPReader.RLPItem[] memory payloadData = data.toRlpItem().toList();

        return ExitPayload(payloadData);
    }

    function getHeaderNumber(ExitPayload memory payload) internal pure returns (uint256) {
        return payload.data[0].toUint();
    }

    function getBlockProof(ExitPayload memory payload) internal pure returns (bytes memory) {
        return payload.data[1].toBytes();
    }

    function getBlockNumber(ExitPayload memory payload) internal pure returns (uint256) {
        return payload.data[2].toUint();
    }

    function getBlockTime(ExitPayload memory payload) internal pure returns (uint256) {
        return payload.data[3].toUint();
    }

    function getTxRoot(ExitPayload memory payload) internal pure returns (bytes32) {
        return bytes32(payload.data[4].toUint());
    }

    function getReceiptRoot(ExitPayload memory payload) internal pure returns (bytes32) {
        return bytes32(payload.data[5].toUint());
    }

    function getReceipt(ExitPayload memory payload) internal pure returns (Receipt memory receipt) {
        receipt.raw = payload.data[6].toBytes();
        RLPReader.RLPItem memory receiptItem = receipt.raw.toRlpItem();

        if (receiptItem.isList()) {
            // legacy tx
            receipt.data = receiptItem.toList();
        } else {
            // pop first byte before parsting receipt
            bytes memory typedBytes = receipt.raw;
            bytes memory result = new bytes(typedBytes.length - 1);
            uint256 srcPtr;
            uint256 destPtr;
            assembly {
                srcPtr := add(33, typedBytes)
                destPtr := add(0x20, result)
            }

            copy(srcPtr, destPtr, result.length);
            receipt.data = result.toRlpItem().toList();
        }

        receipt.logIndex = getReceiptLogIndex(payload);
        return receipt;
    }

    function getReceiptProof(ExitPayload memory payload) internal pure returns (bytes memory) {
        return payload.data[7].toBytes();
    }

    function getBranchMaskAsBytes(ExitPayload memory payload) internal pure returns (bytes memory) {
        return payload.data[8].toBytes();
    }

    function getBranchMaskAsUint(ExitPayload memory payload) internal pure returns (uint256) {
        return payload.data[8].toUint();
    }

    function getReceiptLogIndex(ExitPayload memory payload) internal pure returns (uint256) {
        return payload.data[9].toUint();
    }

    // Receipt methods
    function toBytes(Receipt memory receipt) internal pure returns (bytes memory) {
        return receipt.raw;
    }

    function getLog(Receipt memory receipt) internal pure returns (Log memory) {
        RLPReader.RLPItem memory logData = receipt.data[3].toList()[receipt.logIndex];
        return Log(logData, logData.toList());
    }

    // Log methods
    function getEmitter(Log memory log) internal pure returns (address) {
        return RLPReader.toAddress(log.list[0]);
    }

    function getTopics(Log memory log) internal pure returns (LogTopics memory) {
        return LogTopics(log.list[1].toList());
    }

    function getData(Log memory log) internal pure returns (bytes memory) {
        return log.list[2].toBytes();
    }

    function toRlpBytes(Log memory log) internal pure returns (bytes memory) {
        return log.data.toRlpBytes();
    }

    // LogTopics methods
    function getField(LogTopics memory topics, uint256 index) internal pure returns (RLPReader.RLPItem memory) {
        return topics.data[index];
    }
}

File 6 of 12: FXBaseChildTunnel.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// IFxMessageProcessor represents interface to process message
interface IFxMessageProcessor {
    function processMessageFromRoot(
        uint256 stateId,
        address rootMessageSender,
        bytes calldata data
    ) external;
}

/**
 * @notice Mock child tunnel contract to receive and send message from L2
 */
abstract contract FxBaseChildTunnel is IFxMessageProcessor {
    // MessageTunnel on L1 will get data from this event
    event MessageSent(bytes message);

    // fx child
    address public fxChild;

    // fx root tunnel
    address public fxRootTunnel;

    constructor(address _fxChild) {
        fxChild = _fxChild;
    }

    // Sender must be fxRootTunnel in case of ERC20 tunnel
    modifier validateSender(address sender) {
        require(sender == fxRootTunnel, "FxBaseChildTunnel: INVALID_SENDER_FROM_ROOT");
        _;
    }

    // set fxRootTunnel if not set already
    function setFxRootTunnel(address _fxRootTunnel) external {
        require(fxRootTunnel == address(0x0), "FxBaseChildTunnel: ROOT_TUNNEL_ALREADY_SET");
        fxRootTunnel = _fxRootTunnel;
    }

    function processMessageFromRoot(
        uint256 stateId,
        address rootMessageSender,
        bytes calldata data
    ) external override {
        require(msg.sender == fxChild, "FxBaseChildTunnel: INVALID_SENDER");
        _processMessageFromRoot(stateId, rootMessageSender, data);
    }

    /**
     * @notice Emit message that can be received on Root Tunnel
     * @dev Call the internal function when need to emit message
     * @param message bytes message that will be sent to Root Tunnel
     * some message examples -
     *   abi.encode(tokenId);
     *   abi.encode(tokenId, tokenMetadata);
     *   abi.encode(messageType, messageData);
     */
    function _sendMessageToRoot(bytes memory message) internal {
        emit MessageSent(message);
    }

    /**
     * @notice Process message received from Root Tunnel
     * @dev function needs to be implemented to handle message as per requirement
     * This is called by onStateReceive function.
     * Since it is called via a system call, any event will not be emitted during its execution.
     * @param stateId unique state id
     * @param sender root message sender
     * @param message bytes message that was sent from Root Tunnel
     */
    function _processMessageFromRoot(
        uint256 stateId,
        address sender,
        bytes memory message
    ) internal virtual;
}

File 7 of 12: FxBaseRootTunnel.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {RLPReader} from "./RLPReader.sol";
import {MerklePatriciaProof} from "./MerklePatriciaProof.sol";
import {Merkle} from "./Merkle.sol";
import "./ExitPayloadReader.sol";

interface IFxStateSender {
    function sendMessageToChild(address _receiver, bytes calldata _data) external;
}

contract ICheckpointManager {
    struct HeaderBlock {
        bytes32 root;
        uint256 start;
        uint256 end;
        uint256 createdAt;
        address proposer;
    }

    /**
     * @notice mapping of checkpoint header numbers to block details
     * @dev These checkpoints are submited by plasma contracts
     */
    mapping(uint256 => HeaderBlock) public headerBlocks;
}

abstract contract FxBaseRootTunnel {
    using RLPReader for RLPReader.RLPItem;
    using Merkle for bytes32;
    using ExitPayloadReader for bytes;
    using ExitPayloadReader for ExitPayloadReader.ExitPayload;
    using ExitPayloadReader for ExitPayloadReader.Log;
    using ExitPayloadReader for ExitPayloadReader.LogTopics;
    using ExitPayloadReader for ExitPayloadReader.Receipt;

    // keccak256(MessageSent(bytes))
    bytes32 public constant SEND_MESSAGE_EVENT_SIG = 0x8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036;

    // state sender contract
    IFxStateSender public fxRoot;
    // root chain manager
    ICheckpointManager public checkpointManager;
    // child tunnel contract which receives and sends messages
    address public fxChildTunnel;

    // storage to avoid duplicate exits
    mapping(bytes32 => bool) public processedExits;

    constructor(address _checkpointManager, address _fxRoot) {
        checkpointManager = ICheckpointManager(_checkpointManager);
        fxRoot = IFxStateSender(_fxRoot);
    }

    // set fxChildTunnel if not set already
    function setFxChildTunnel(address _fxChildTunnel) public {
        require(fxChildTunnel == address(0x0), "FxBaseRootTunnel: CHILD_TUNNEL_ALREADY_SET");
        fxChildTunnel = _fxChildTunnel;
    }

    /**
     * @notice Send bytes message to Child Tunnel
     * @param message bytes message that will be sent to Child Tunnel
     * some message examples -
     *   abi.encode(tokenId);
     *   abi.encode(tokenId, tokenMetadata);
     *   abi.encode(messageType, messageData);
     */
    function _sendMessageToChild(bytes memory message) internal {
        fxRoot.sendMessageToChild(fxChildTunnel, message);
    }

    function _validateAndExtractMessage(bytes memory inputData) internal returns (bytes memory) {
        ExitPayloadReader.ExitPayload memory payload = inputData.toExitPayload();

        bytes memory branchMaskBytes = payload.getBranchMaskAsBytes();
        uint256 blockNumber = payload.getBlockNumber();
        // checking if exit has already been processed
        // unique exit is identified using hash of (blockNumber, branchMask, receiptLogIndex)
        bytes32 exitHash = keccak256(
            abi.encodePacked(
                blockNumber,
                // first 2 nibbles are dropped while generating nibble array
                // this allows branch masks that are valid but bypass exitHash check (changing first 2 nibbles only)
                // so converting to nibble array and then hashing it
                MerklePatriciaProof._getNibbleArray(branchMaskBytes),
                payload.getReceiptLogIndex()
            )
        );
        require(processedExits[exitHash] == false, "FxRootTunnel: EXIT_ALREADY_PROCESSED");
        processedExits[exitHash] = true;

        ExitPayloadReader.Receipt memory receipt = payload.getReceipt();
        ExitPayloadReader.Log memory log = receipt.getLog();

        // check child tunnel
        require(fxChildTunnel == log.getEmitter(), "FxRootTunnel: INVALID_FX_CHILD_TUNNEL");

        bytes32 receiptRoot = payload.getReceiptRoot();
        // verify receipt inclusion
        require(
            MerklePatriciaProof.verify(receipt.toBytes(), branchMaskBytes, payload.getReceiptProof(), receiptRoot),
            "FxRootTunnel: INVALID_RECEIPT_PROOF"
        );

        // verify checkpoint inclusion
        _checkBlockMembershipInCheckpoint(
            blockNumber,
            payload.getBlockTime(),
            payload.getTxRoot(),
            receiptRoot,
            payload.getHeaderNumber(),
            payload.getBlockProof()
        );

        ExitPayloadReader.LogTopics memory topics = log.getTopics();

        require(
            bytes32(topics.getField(0).toUint()) == SEND_MESSAGE_EVENT_SIG, // topic0 is event sig
            "FxRootTunnel: INVALID_SIGNATURE"
        );

        // received message data
        bytes memory message = abi.decode(log.getData(), (bytes)); // event decodes params again, so decoding bytes to get message
        return message;
    }

    function _checkBlockMembershipInCheckpoint(
        uint256 blockNumber,
        uint256 blockTime,
        bytes32 txRoot,
        bytes32 receiptRoot,
        uint256 headerNumber,
        bytes memory blockProof
    ) private view returns (uint256) {
        (bytes32 headerRoot, uint256 startBlock, , uint256 createdAt, ) = checkpointManager.headerBlocks(headerNumber);

        require(
            keccak256(abi.encodePacked(blockNumber, blockTime, txRoot, receiptRoot)).checkMembership(
                blockNumber - startBlock,
                headerRoot,
                blockProof
            ),
            "FxRootTunnel: INVALID_HEADER"
        );
        return createdAt;
    }

    /**
     * @notice receive message from  L2 to L1, validated by proof
     * @dev This function verifies if the transaction actually happened on child chain
     *
     * @param inputData RLP encoded data of the reference tx containing following list of fields
     *  0 - headerNumber - Checkpoint header block number containing the reference tx
     *  1 - blockProof - Proof that the block header (in the child chain) is a leaf in the submitted merkle root
     *  2 - blockNumber - Block number containing the reference tx on child chain
     *  3 - blockTime - Reference tx block time
     *  4 - txRoot - Transactions root of block
     *  5 - receiptRoot - Receipts root of block
     *  6 - receipt - Receipt of the reference transaction
     *  7 - receiptProof - Merkle proof of the reference receipt
     *  8 - branchMask - 32 bits denoting the path of receipt in merkle tree
     *  9 - receiptLogIndex - Log Index to read from the receipt
     */
    function receiveMessage(bytes memory inputData) public virtual {
        bytes memory message = _validateAndExtractMessage(inputData);
        _processMessageFromChild(message);
    }

    /**
     * @notice Process message received from Child Tunnel
     * @dev function needs to be implemented to handle message as per requirement
     * This is called by onStateReceive function.
     * Since it is called via a system call, any event will not be emitted during its execution.
     * @param message bytes message that was sent from Child Tunnel
     */
    function _processMessageFromChild(bytes memory message) internal virtual;
}

File 8 of 12: Merkle.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library Merkle {
    function checkMembership(
        bytes32 leaf,
        uint256 index,
        bytes32 rootHash,
        bytes memory proof
    ) internal pure returns (bool) {
        require(proof.length % 32 == 0, "Invalid proof length");
        uint256 proofHeight = proof.length / 32;
        // Proof of size n means, height of the tree is n+1.
        // In a tree of height n+1, max #leafs possible is 2 ^ n
        require(index < 2**proofHeight, "Leaf index is too big");

        bytes32 proofElement;
        bytes32 computedHash = leaf;
        for (uint256 i = 32; i <= proof.length; i += 32) {
            assembly {
                proofElement := mload(add(proof, i))
            }

            if (index % 2 == 0) {
                computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
            } else {
                computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
            }

            index = index / 2;
        }
        return computedHash == rootHash;
    }
}

File 9 of 12: MerklePatriciaProof.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {RLPReader} from "./RLPReader.sol";

library MerklePatriciaProof {
    /*
     * @dev Verifies a merkle patricia proof.
     * @param value The terminating value in the trie.
     * @param encodedPath The path in the trie leading to value.
     * @param rlpParentNodes The rlp encoded stack of nodes.
     * @param root The root hash of the trie.
     * @return The boolean validity of the proof.
     */
    function verify(
        bytes memory value,
        bytes memory encodedPath,
        bytes memory rlpParentNodes,
        bytes32 root
    ) internal pure returns (bool) {
        RLPReader.RLPItem memory item = RLPReader.toRlpItem(rlpParentNodes);
        RLPReader.RLPItem[] memory parentNodes = RLPReader.toList(item);

        bytes memory currentNode;
        RLPReader.RLPItem[] memory currentNodeList;

        bytes32 nodeKey = root;
        uint256 pathPtr = 0;

        bytes memory path = _getNibbleArray(encodedPath);
        if (path.length == 0) {
            return false;
        }

        for (uint256 i = 0; i < parentNodes.length; i++) {
            if (pathPtr > path.length) {
                return false;
            }

            currentNode = RLPReader.toRlpBytes(parentNodes[i]);
            if (nodeKey != keccak256(currentNode)) {
                return false;
            }
            currentNodeList = RLPReader.toList(parentNodes[i]);

            if (currentNodeList.length == 17) {
                if (pathPtr == path.length) {
                    if (keccak256(RLPReader.toBytes(currentNodeList[16])) == keccak256(value)) {
                        return true;
                    } else {
                        return false;
                    }
                }

                uint8 nextPathNibble = uint8(path[pathPtr]);
                if (nextPathNibble > 16) {
                    return false;
                }
                nodeKey = bytes32(RLPReader.toUintStrict(currentNodeList[nextPathNibble]));
                pathPtr += 1;
            } else if (currentNodeList.length == 2) {
                uint256 traversed = _nibblesToTraverse(RLPReader.toBytes(currentNodeList[0]), path, pathPtr);
                if (pathPtr + traversed == path.length) {
                    //leaf node
                    if (keccak256(RLPReader.toBytes(currentNodeList[1])) == keccak256(value)) {
                        return true;
                    } else {
                        return false;
                    }
                }

                //extension node
                if (traversed == 0) {
                    return false;
                }

                pathPtr += traversed;
                nodeKey = bytes32(RLPReader.toUintStrict(currentNodeList[1]));
            } else {
                return false;
            }
        }
    }

    function _nibblesToTraverse(
        bytes memory encodedPartialPath,
        bytes memory path,
        uint256 pathPtr
    ) private pure returns (uint256) {
        uint256 len = 0;
        // encodedPartialPath has elements that are each two hex characters (1 byte), but partialPath
        // and slicedPath have elements that are each one hex character (1 nibble)
        bytes memory partialPath = _getNibbleArray(encodedPartialPath);
        bytes memory slicedPath = new bytes(partialPath.length);

        // pathPtr counts nibbles in path
        // partialPath.length is a number of nibbles
        for (uint256 i = pathPtr; i < pathPtr + partialPath.length; i++) {
            bytes1 pathNibble = path[i];
            slicedPath[i - pathPtr] = pathNibble;
        }

        if (keccak256(partialPath) == keccak256(slicedPath)) {
            len = partialPath.length;
        } else {
            len = 0;
        }
        return len;
    }

    // bytes b must be hp encoded
    function _getNibbleArray(bytes memory b) internal pure returns (bytes memory) {
        bytes memory nibbles = "";
        if (b.length > 0) {
            uint8 offset;
            uint8 hpNibble = uint8(_getNthNibbleOfBytes(0, b));
            if (hpNibble == 1 || hpNibble == 3) {
                nibbles = new bytes(b.length * 2 - 1);
                bytes1 oddNibble = _getNthNibbleOfBytes(1, b);
                nibbles[0] = oddNibble;
                offset = 1;
            } else {
                nibbles = new bytes(b.length * 2 - 2);
                offset = 0;
            }

            for (uint256 i = offset; i < nibbles.length; i++) {
                nibbles[i] = _getNthNibbleOfBytes(i - offset + 2, b);
            }
        }
        return nibbles;
    }

    function _getNthNibbleOfBytes(uint256 n, bytes memory str) private pure returns (bytes1) {
        return bytes1(n % 2 == 0 ? uint8(str[n / 2]) / 0x10 : uint8(str[n / 2]) % 0x10);
    }
}

File 10 of 12: Ownable.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.10;

error NotOwner();

// https://github.com/m1guelpf/erc721-drop/blob/main/src/LilOwnable.sol
abstract contract Ownable {
    address internal _owner;

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

    modifier onlyOwner() {
        require(_owner == msg.sender);
        _;
    }

    constructor() {
        _owner = msg.sender;
    }

    function owner() external view returns (address) {
        return _owner;
    }

    function transferOwnership(address _newOwner) external {
        if (msg.sender != _owner) revert NotOwner();

        _owner = _newOwner;
    }

    function renounceOwnership() public {
        if (msg.sender != _owner) revert NotOwner();

        _owner = address(0);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        pure
        virtual
        returns (bool)
    {
        return interfaceId == 0x7f5828d0; // ERC165 Interface ID for ERC173
    }
}

File 11 of 12: RLPReader.sol
/*
 * @author Hamdi Allam [email protected]
 * Please reach out with any questions or concerns
 */
pragma solidity ^0.8.0;

library RLPReader {
    uint8 constant STRING_SHORT_START = 0x80;
    uint8 constant STRING_LONG_START = 0xb8;
    uint8 constant LIST_SHORT_START = 0xc0;
    uint8 constant LIST_LONG_START = 0xf8;
    uint8 constant WORD_SIZE = 32;

    struct RLPItem {
        uint256 len;
        uint256 memPtr;
    }

    struct Iterator {
        RLPItem item; // Item that's being iterated over.
        uint256 nextPtr; // Position of the next item in the list.
    }

    /*
     * @dev Returns the next element in the iteration. Reverts if it has not next element.
     * @param self The iterator.
     * @return The next element in the iteration.
     */
    function next(Iterator memory self) internal pure returns (RLPItem memory) {
        require(hasNext(self));

        uint256 ptr = self.nextPtr;
        uint256 itemLength = _itemLength(ptr);
        self.nextPtr = ptr + itemLength;

        return RLPItem(itemLength, ptr);
    }

    /*
     * @dev Returns true if the iteration has more elements.
     * @param self The iterator.
     * @return true if the iteration has more elements.
     */
    function hasNext(Iterator memory self) internal pure returns (bool) {
        RLPItem memory item = self.item;
        return self.nextPtr < item.memPtr + item.len;
    }

    /*
     * @param item RLP encoded bytes
     */
    function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) {
        uint256 memPtr;
        assembly {
            memPtr := add(item, 0x20)
        }

        return RLPItem(item.length, memPtr);
    }

    /*
     * @dev Create an iterator. Reverts if item is not a list.
     * @param self The RLP item.
     * @return An 'Iterator' over the item.
     */
    function iterator(RLPItem memory self) internal pure returns (Iterator memory) {
        require(isList(self));

        uint256 ptr = self.memPtr + _payloadOffset(self.memPtr);
        return Iterator(self, ptr);
    }

    /*
     * @param item RLP encoded bytes
     */
    function rlpLen(RLPItem memory item) internal pure returns (uint256) {
        return item.len;
    }

    /*
     * @param item RLP encoded bytes
     */
    function payloadLen(RLPItem memory item) internal pure returns (uint256) {
        return item.len - _payloadOffset(item.memPtr);
    }

    /*
     * @param item RLP encoded list in bytes
     */
    function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) {
        require(isList(item));

        uint256 items = numItems(item);
        RLPItem[] memory result = new RLPItem[](items);

        uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr);
        uint256 dataLen;
        for (uint256 i = 0; i < items; i++) {
            dataLen = _itemLength(memPtr);
            result[i] = RLPItem(dataLen, memPtr);
            memPtr = memPtr + dataLen;
        }

        return result;
    }

    // @return indicator whether encoded payload is a list. negate this function call for isData.
    function isList(RLPItem memory item) internal pure returns (bool) {
        if (item.len == 0) return false;

        uint8 byte0;
        uint256 memPtr = item.memPtr;
        assembly {
            byte0 := byte(0, mload(memPtr))
        }

        if (byte0 < LIST_SHORT_START) return false;
        return true;
    }

    /*
     * @dev A cheaper version of keccak256(toRlpBytes(item)) that avoids copying memory.
     * @return keccak256 hash of RLP encoded bytes.
     */
    function rlpBytesKeccak256(RLPItem memory item) internal pure returns (bytes32) {
        uint256 ptr = item.memPtr;
        uint256 len = item.len;
        bytes32 result;
        assembly {
            result := keccak256(ptr, len)
        }
        return result;
    }

    function payloadLocation(RLPItem memory item) internal pure returns (uint256, uint256) {
        uint256 offset = _payloadOffset(item.memPtr);
        uint256 memPtr = item.memPtr + offset;
        uint256 len = item.len - offset; // data length
        return (memPtr, len);
    }

    /*
     * @dev A cheaper version of keccak256(toBytes(item)) that avoids copying memory.
     * @return keccak256 hash of the item payload.
     */
    function payloadKeccak256(RLPItem memory item) internal pure returns (bytes32) {
        (uint256 memPtr, uint256 len) = payloadLocation(item);
        bytes32 result;
        assembly {
            result := keccak256(memPtr, len)
        }
        return result;
    }

    /** RLPItem conversions into data types **/

    // @returns raw rlp encoding in bytes
    function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) {
        bytes memory result = new bytes(item.len);
        if (result.length == 0) return result;

        uint256 ptr;
        assembly {
            ptr := add(0x20, result)
        }

        copy(item.memPtr, ptr, item.len);
        return result;
    }

    // any non-zero byte is considered true
    function toBoolean(RLPItem memory item) internal pure returns (bool) {
        require(item.len == 1);
        uint256 result;
        uint256 memPtr = item.memPtr;
        assembly {
            result := byte(0, mload(memPtr))
        }

        return result == 0 ? false : true;
    }

    function toAddress(RLPItem memory item) internal pure returns (address) {
        // 1 byte for the length prefix
        require(item.len == 21);

        return address(uint160(toUint(item)));
    }

    function toUint(RLPItem memory item) internal pure returns (uint256) {
        require(item.len > 0 && item.len <= 33);

        uint256 offset = _payloadOffset(item.memPtr);
        uint256 len = item.len - offset;

        uint256 result;
        uint256 memPtr = item.memPtr + offset;
        assembly {
            result := mload(memPtr)

            // shfit to the correct location if neccesary
            if lt(len, 32) {
                result := div(result, exp(256, sub(32, len)))
            }
        }

        return result;
    }

    // enforces 32 byte length
    function toUintStrict(RLPItem memory item) internal pure returns (uint256) {
        // one byte prefix
        require(item.len == 33);

        uint256 result;
        uint256 memPtr = item.memPtr + 1;
        assembly {
            result := mload(memPtr)
        }

        return result;
    }

    function toBytes(RLPItem memory item) internal pure returns (bytes memory) {
        require(item.len > 0);

        uint256 offset = _payloadOffset(item.memPtr);
        uint256 len = item.len - offset; // data length
        bytes memory result = new bytes(len);

        uint256 destPtr;
        assembly {
            destPtr := add(0x20, result)
        }

        copy(item.memPtr + offset, destPtr, len);
        return result;
    }

    /*
     * Private Helpers
     */

    // @return number of payload items inside an encoded list.
    function numItems(RLPItem memory item) private pure returns (uint256) {
        if (item.len == 0) return 0;

        uint256 count = 0;
        uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr);
        uint256 endPtr = item.memPtr + item.len;
        while (currPtr < endPtr) {
            currPtr = currPtr + _itemLength(currPtr); // skip over an item
            count++;
        }

        return count;
    }

    // @return entire rlp item byte length
    function _itemLength(uint256 memPtr) private pure returns (uint256) {
        uint256 itemLen;
        uint256 byte0;
        assembly {
            byte0 := byte(0, mload(memPtr))
        }

        if (byte0 < STRING_SHORT_START) itemLen = 1;
        else if (byte0 < STRING_LONG_START) itemLen = byte0 - STRING_SHORT_START + 1;
        else if (byte0 < LIST_SHORT_START) {
            assembly {
                let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is
                memPtr := add(memPtr, 1) // skip over the first byte
                /* 32 byte word size */
                let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len
                itemLen := add(dataLen, add(byteLen, 1))
            }
        } else if (byte0 < LIST_LONG_START) {
            itemLen = byte0 - LIST_SHORT_START + 1;
        } else {
            assembly {
                let byteLen := sub(byte0, 0xf7)
                memPtr := add(memPtr, 1)

                let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length
                itemLen := add(dataLen, add(byteLen, 1))
            }
        }

        return itemLen;
    }

    // @return number of bytes until the data
    function _payloadOffset(uint256 memPtr) private pure returns (uint256) {
        uint256 byte0;
        assembly {
            byte0 := byte(0, mload(memPtr))
        }

        if (byte0 < STRING_SHORT_START) return 0;
        else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) return 1;
        else if (byte0 < LIST_SHORT_START)
            // being explicit
            return byte0 - (STRING_LONG_START - 1) + 1;
        else return byte0 - (LIST_LONG_START - 1) + 1;
    }

    /*
     * @param src Pointer to source
     * @param dest Pointer to destination
     * @param len Amount of memory to copy from the source
     */
    function copy(
        uint256 src,
        uint256 dest,
        uint256 len
    ) private pure {
        if (len == 0) return;

        // copy as many word sizes as possible
        for (; len >= WORD_SIZE; len -= WORD_SIZE) {
            assembly {
                mstore(dest, mload(src))
            }

            src += WORD_SIZE;
            dest += WORD_SIZE;
        }

        if (len == 0) return;

        // left over bytes. Mask is used to remove unwanted bytes from the word
        uint256 mask = 256**(WORD_SIZE - len) - 1;

        assembly {
            let srcpart := and(mload(src), not(mask)) // zero out src
            let destpart := and(mload(dest), mask) // retrieve the bytes
            mstore(dest, or(destpart, srcpart))
        }
    }
}

File 12 of 12: SpitToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

import "./ERC20.sol";
import "./FXBaseChildTunnel.sol";
import "./Ownable.sol";

/**
   __ _                                               
  / /| | __ _ _ __ ___   __ _/\   /\___ _ __ ___  ___ 
 / / | |/ _` | '_ ` _ \ / _` \ \ / / _ \ '__/ __|/ _ \
/ /__| | (_| | | | | | | (_| |\ V /  __/ |  \__ \  __/
\____/_|\__,_|_| |_| |_|\__,_| \_/ \___|_|  |___/\___|

**/

/// @title $SPIT Token
/// @author delta devs (https://twitter.com/deltadevelopers)

enum TokenType {
    StaticLlama,
    AnimatedLlama,
    SilverBoost,
    GoldBoost,
    PixletCanvas,
    LlamaDraws
}

contract SpitToken is ERC20, FxBaseChildTunnel, Ownable {
    /*///////////////////////////////////////////////////////////////
                            STORAGE
    /////////////////////////////////////////////////////////////*/

    struct Rewards {
        uint256 staticLlama;
        uint256 animatedLlama;
        uint256 silverEnergy;
        uint256 goldEnergy;
        uint256 pixletCanvas;
        uint256 llamaDraws;
    }

    /// @notice The current reward rates per token type.
    Rewards public rewards;

    /// @notice Keeps track of the staking balances (how much is being staked) of each token type for all holders.
    mapping(address => mapping(uint256 => uint256)) public balances;

    /// @notice Keeps track of the timestamp of when a holder last withdrew their rewards.
    mapping(address => uint256) public lastUpdated;

    /*///////////////////////////////////////////////////////////////
                            CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(address _fxChild)
        FxBaseChildTunnel(_fxChild)
        ERC20("Spit Token", "SPIT", 18)
    {
        rewards.staticLlama = (uint256(10) * 1e18) / 1 days;
        rewards.animatedLlama = (uint256(30) * 1e18) / 1 days;
        rewards.silverEnergy = (uint256(4) * 1e18) / 1 days;
        rewards.goldEnergy = (uint256(12) * 1e18) / 1 days;
        rewards.llamaDraws = (uint256(1) * 1e18) / 1 days;
        rewards.pixletCanvas = (uint256(1) * 1e18) / 1 days;

        _mint(address(this), 100_000_000 * 1e18);
        uint256 allocation = (30_000_000 + 5_000_000 + 5_000_000 + 2_500_000) *
            1e18;
        balanceOf[address(this)] -= allocation;

        unchecked {
            balanceOf[
                0xcc5cDaB325689Bcd654aB8611c528e60CC8CBe6A
            ] += (30_000_000 * 1e18);
            balanceOf[
                0x58B96f5C8ef1CdD7e12a9b71Bbbe575E7B26b142
            ] += (5_000_000 * 1e18);
            balanceOf[
                0x58caDf06fcC222f573F81B08B6Cc156e420D35d7
            ] += (5_000_000 * 1e18);
            balanceOf[
                0x5D31E4A33470e1a15e54aAdD1d913b613fd0E9ED
            ] += (2_500_000 * 1e18);
        }

        emit Transfer(
            address(this),
            0xcc5cDaB325689Bcd654aB8611c528e60CC8CBe6A,
            30_000_000 * 1e18
        );
        emit Transfer(
            address(this),
            0x58B96f5C8ef1CdD7e12a9b71Bbbe575E7B26b142,
            5_000_000 * 1e18
        );
        emit Transfer(
            address(this),
            0x58caDf06fcC222f573F81B08B6Cc156e420D35d7,
            5_000_000 * 1e18
        );
        emit Transfer(
            address(this),
            0x5D31E4A33470e1a15e54aAdD1d913b613fd0E9ED,
            2_500_000 * 1e18
        );
    }

    /*///////////////////////////////////////////////////////////////
                            STAKING LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Called when withdrawing rewards. $SPIT is transferred to the address, and the lastUpdated field is updated.
    /// @param account The address to mint to.
    modifier updateReward(address account) {
        uint256 amount = earned(account);
        balanceOf[address(this)] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[account] += amount;
        }

        lastUpdated[account] = block.timestamp;
        emit Transfer(address(this), account, amount);
        _;
    }

    /// @notice Internal call to stake an amount of a specific token type.
    /// @param account The address which will be staking.
    /// @param tokenType The token type to stake.
    /// @param amount The amount to stake.
    function processStake(
        address account,
        TokenType tokenType,
        uint256 amount
    ) internal updateReward(account) {
        balances[account][uint256(tokenType)] += amount;
    }

    /// @notice Internal call to unstake an amount of a specific token type.
    /// @param account The address which will be unstaking.
    /// @param tokenType The token type to unstake.
    /// @param amount The amount to unstake.
    function processUnstake(
        address account,
        TokenType tokenType,
        uint256 amount
    ) internal updateReward(account) {
        balances[account][uint256(tokenType)] -= amount;
    }

    /**
     * @notice Process message received from FxChild
     * @param stateId unique state id
     * @param sender root message sender
     * @param message bytes message that was sent from Root Tunnel
     */
    function _processMessageFromRoot(
        uint256 stateId,
        address sender,
        bytes memory message
    ) internal override validateSender(sender) {
        (address from, uint256 token, uint256 count, bool action) = abi.decode(
            message,
            (address, uint256, uint256, bool)
        );
        action
            ? processStake(from, TokenType(token), count)
            : processUnstake(from, TokenType(token), count);
    }

    /*///////////////////////////////////////////////////////////////
                            USER UTILITIES
    //////////////////////////////////////////////////////////////*/

    /// @notice Forwards a user's purchase in SPIT to this contract using EIP-2612
    /// @dev This function exists so that the permit and transfer can be done in a single transaction.
    function purchaseUtility(
        address owner,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public updateReward(owner) {
        permit(owner, msg.sender, value, deadline, v, r, s);
        transferFrom(owner, address(this), value);
    }

    /// @notice Calculates the total amount of rewards accumulated for a staker, for staking all owned token types.
    /// @dev Calculates based on when the staker last withdrew rewards, and compares it with the current block's timestamp.
    /// @param account The account to calculate the accumulated rewards for.
    function earned(address account) public view returns (uint256) {
        return
            spitPerSecond(account) * (block.timestamp - lastUpdated[account]);
    }

    /// @notice Calculates the current balance of the user including the unclaimed rewards.
    /// @dev Unclaimed rewards are withdrawn automatically when a utility purchase is made or an unstake/stake occurs.
    function totalBalance(address account) public view returns (uint256) {
        return balanceOf[account] + earned(account);
    }

    /// @notice Calculates the amount of SPIT earned per second by the given user
    /// @param account The account to calculate the accumulated rewards for.
    function spitPerSecond(address account) public view returns (uint256) {
        return ((balances[account][0] * rewards.staticLlama) +
            (balances[account][1] * rewards.animatedLlama) +
            (min(balances[account][2], balances[account][0]) *
                rewards.silverEnergy) +
            (min(balances[account][3], balances[account][1]) *
                rewards.goldEnergy) +
            (balances[account][4] * rewards.pixletCanvas) +
            (balances[account][5] * rewards.llamaDraws));
    }

    /*///////////////////////////////////////////////////////////////
                            ADMIN UTILITIES
    //////////////////////////////////////////////////////////////*/

    /// @notice Allows the contract owner to burn SPIT owned by the contract.
    function burn(uint256 amount) public onlyOwner {
        _burn(address(this), amount);
    }

    /// @notice Allows the contract owner to airdrop SPIT owned by the contract.
    function airdrop(address[] calldata accounts, uint256[] calldata amounts) public onlyOwner {
        require(accounts.length == amounts.length);
        for(uint i = 0; i < accounts.length; i++) {
            uint amount = amounts[i];
            balanceOf[address(this)] -= amount;

            // Cannot overflow because the sum of all user
            // balances can't exceed the max uint256 value.
            unchecked {
                balanceOf[accounts[i]] += amount;
            }

            emit Transfer(address(this), accounts[i], amount);
        }
    }

    /// @notice Allows the contract owner to mint SPIT to the contract.
    function mint(uint256 amount) public onlyOwner {
        _mint(address(this), amount);
    }

    /// @notice Withdraw  $SPIT being held on this contract to the requested address.
    /// @param recipient The address to withdraw the funds to.
    /// @param amount The amount of SPIT to withdraw
    function withdrawSpit(address recipient, uint256 amount) public onlyOwner {
        balanceOf[address(this)] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[recipient] += amount;
        }

        emit Transfer(address(this), recipient, amount);
    }

    /// @notice Allows the contract deployer to sets the reward rates for each token type.
    /// @param staticLlama The reward rate for staking a static llama.
    /// @param animatedLlama The reward rate for staking an animated llama.
    /// @param silverEnergy The reward rate for staking a silver llama boost.
    /// @param goldEnergy The reward rate for staking a gold llama boost.
    /// @param pixletCanvas The reward rate for staking a pixlet canvas.
    function setRewardRates(
        uint256 staticLlama,
        uint256 animatedLlama,
        uint256 silverEnergy,
        uint256 goldEnergy,
        uint256 pixletCanvas,
        uint256 llamaDraws
    ) public onlyOwner {
        rewards.staticLlama = staticLlama;
        rewards.animatedLlama = animatedLlama;
        rewards.silverEnergy = silverEnergy;
        rewards.goldEnergy = goldEnergy;
        rewards.pixletCanvas = pixletCanvas;
        rewards.llamaDraws = llamaDraws;
    }

    function updateFxRootRunnel(address _fxRootTunnel) external onlyOwner {
        fxRootTunnel = _fxRootTunnel;
    }

    /*///////////////////////////////////////////////////////////////
                                HELPERS
    //////////////////////////////////////////////////////////////*/

    function min(uint256 x, uint256 y) internal pure returns (uint256) {
        return x < y ? x : y;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"checkpointManager","type":"address"},{"internalType":"address","name":"fxRoot","type":"address"},{"internalType":"address","name":"_pixellatedLlamaContract","type":"address"},{"internalType":"address","name":"_llamaDrawsContract","type":"address"},{"internalType":"address","name":"_boostContract","type":"address"},{"internalType":"address","name":"_pixletContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NotOwner","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"SEND_MESSAGE_EVENT_SIG","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boostContract","outputs":[{"internalType":"contract ERC1155","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"llamas","type":"uint256[]"},{"internalType":"uint128","name":"silverBoosts","type":"uint128"},{"internalType":"uint128","name":"goldBoosts","type":"uint128"},{"internalType":"uint256","name":"pixletStudio","type":"uint256"},{"internalType":"uint256","name":"llamaDraws","type":"uint256"}],"name":"bulkStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"llamas","type":"uint256[]"},{"internalType":"uint128","name":"silverBoosts","type":"uint128"},{"internalType":"uint128","name":"goldBoosts","type":"uint128"},{"internalType":"bool","name":"pixletStudio","type":"bool"},{"internalType":"bool","name":"llamaDraws","type":"bool"}],"name":"bulkUnstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"checkpointManager","outputs":[{"internalType":"contract ICheckpointManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fxChildTunnel","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fxRoot","outputs":[{"internalType":"contract IFxStateSender","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getStakedTokens","outputs":[{"internalType":"uint256[]","name":"llamas","type":"uint256[]"},{"internalType":"uint256","name":"pixletCanvas","type":"uint256"},{"internalType":"uint256","name":"llamaDraws","type":"uint256"},{"internalType":"uint128","name":"silverBoosts","type":"uint128"},{"internalType":"uint128","name":"goldBoosts","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"llamaDrawsContract","outputs":[{"internalType":"contract ERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pixellatedLlamaContract","outputs":[{"internalType":"contract ERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pixletContract","outputs":[{"internalType":"contract ERC1155","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"processedExits","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"inputData","type":"bytes"}],"name":"receiveMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pixellatedLlamaContract","type":"address"},{"internalType":"address","name":"_llamaDrawsContract","type":"address"},{"internalType":"address","name":"_boostContract","type":"address"},{"internalType":"address","name":"_pixletContract","type":"address"}],"name":"setContractAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fxChildTunnel","type":"address"}],"name":"setFxChildTunnel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"paused","type":"bool"}],"name":"setStakingPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"silverAmount","type":"uint128"},{"internalType":"uint128","name":"goldAmount","type":"uint128"}],"name":"stakeBoosts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"amount","type":"uint128"}],"name":"stakeGoldBoosts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"stakeLlama","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"stakeLlamaDraws","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"stakeMultipleLlamas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"stakePixletCanvas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"amount","type":"uint128"}],"name":"stakeSilverBoosts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"silverAmount","type":"uint128"},{"internalType":"uint128","name":"goldAmount","type":"uint128"}],"name":"unstakeBoosts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"amount","type":"uint128"}],"name":"unstakeGoldBoosts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"unstakeLlama","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unstakeLlamaDraws","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"unstakeMultipleLlamas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unstakePixletCanvas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"amount","type":"uint128"}],"name":"unstakeSilverBoosts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"stakedPixletCanvas","type":"uint256"},{"internalType":"uint256","name":"stakedLlamaDraws","type":"uint256"},{"internalType":"uint128","name":"stakedSilverBoosts","type":"uint128"},{"internalType":"uint128","name":"stakedGoldBoosts","type":"uint128"}],"stateMutability":"view","type":"function"}]

60806040523480156200001157600080fd5b5060405162004c0938038062004c098339810160408190526200003491620000cf565b600180546001600160a01b03199081166001600160a01b0398891617909155600080548216968816969096179095556004805433908716179055600580548616948716949094179093556006805485169286169290921790915560078054841691851691909117905560088054909216921691909117905562000150565b80516001600160a01b0381168114620000ca57600080fd5b919050565b60008060008060008060c08789031215620000e957600080fd5b620000f487620000b2565b95506200010460208801620000b2565b94506200011460408801620000b2565b93506200012460608801620000b2565b92506200013460808801620000b2565b91506200014460a08801620000b2565b90509295509295509295565b614aa980620001606000396000f3fe608060405234801561001057600080fd5b50600436106102c85760003560e01c8063860420e31161017b578063c0857ba0116100d8578063e72cb05b1161008c578063f2fde38b11610071578063f2fde38b146107b1578063f3fa98a7146107c4578063f953cec7146107d757600080fd5b8063e72cb05b14610765578063f23a6e611461077857600080fd5b8063c7059488116100bd578063c70594881461071d578063de9b771f14610725578063dfcedeee1461074557600080fd5b8063c0857ba0146106ea578063c5bf09641461070a57600080fd5b8063abbe08181161012f578063bbb781cc11610114578063bbb781cc1461068f578063bc197c811461069c578063bd88119f146106d757600080fd5b8063abbe081814610674578063aea4e49e1461067c57600080fd5b80638da5cb5b116101605780638da5cb5b14610623578063972c492814610641578063aaa687771461066157600080fd5b8063860420e3146105fd578063891bc3d21461061057600080fd5b806350acac5511610229578063652972d4116101dd57806370a08231116101c257806370a08231146105cf578063715018a6146105e25780638282052b146105ea57600080fd5b8063652972d41461059c5780636f251724146105bc57600080fd5b80635d939ed01161020e5780635d939ed014610542578063607f2d421461055557806363c28db11461057857600080fd5b806350acac551461050f578063584a22061461052257600080fd5b80631820743d116102805780632176dfce116102655780632176dfce146104d65780633b0d79fa146104e95780634f9ce271146104fc57600080fd5b80631820743d1461042f5780631959a0021461044257600080fd5b80630f147692116102b15780630f1476921461036c578063150b7a02146103b157806315b31bbb1461041a57600080fd5b806301ffc9a7146102cd5780630e387de614610337575b600080fd5b6103226102db366004613e0b565b7fffffffff00000000000000000000000000000000000000000000000000000000167f7f5828d0000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b61035e7f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b03681565b60405190815260200161032e565b60055461038c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161032e565b6103e96103bf366004613eb8565b7f150b7a020000000000000000000000000000000000000000000000000000000095945050505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161032e565b61042d610428366004613f40565b6107ea565b005b61042d61043d366004613f7b565b61083f565b61049e610450366004613f96565b6009602052600090815260409020600181015460028201546003909201549091906fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041684565b6040805194855260208501939093526fffffffffffffffffffffffffffffffff9182169284019290925216606082015260800161032e565b61042d6104e43660046140b1565b610a63565b61042d6104f73660046140e6565b610e28565b61042d61050a366004614119565b610e6e565b61042d61051d366004614119565b611031565b60065461038c9073ffffffffffffffffffffffffffffffffffffffff1681565b61042d610550366004613f7b565b611359565b610322610563366004614119565b60036020526000908152604090205460ff1681565b61058b610586366004613f96565b611535565b60405161032e959493929190614132565b60085461038c9073ffffffffffffffffffffffffffffffffffffffff1681565b61042d6105ca3660046141a3565b611642565b61035e6105dd366004613f96565b61167a565b61042d611752565b61042d6105f83660046140b1565b6117cd565b61042d61060b366004613f7b565b611a2c565b61042d61061e366004614213565b611c4f565b60045473ffffffffffffffffffffffffffffffffffffffff1661038c565b60025461038c9073ffffffffffffffffffffffffffffffffffffffff1681565b61042d61066f366004614293565b611c85565b61042d611d1e565b61042d61068a366004613f96565b611ed2565b600a546103229060ff1681565b6103e96106aa366004614334565b7fbc197c810000000000000000000000000000000000000000000000000000000098975050505050505050565b61042d6106e53660046140e6565b611fa5565b60015461038c9073ffffffffffffffffffffffffffffffffffffffff1681565b61042d610718366004614119565b611fe7565b61042d61211c565b60005461038c9073ffffffffffffffffffffffffffffffffffffffff1681565b60075461038c9073ffffffffffffffffffffffffffffffffffffffff1681565b61042d610773366004613f7b565b6122b8565b6103e96107863660046143f3565b7ff23a6e61000000000000000000000000000000000000000000000000000000009695505050505050565b61042d6107bf366004613f96565b61247d565b61042d6107d2366004614119565b612515565b61042d6107e53660046144b5565b6126b7565b60045473ffffffffffffffffffffffffffffffffffffffff16331461080e57600080fd5b600a80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b600a5460ff16156108975760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e0000000060448201526064015b60405180910390fd5b806fffffffffffffffffffffffffffffffff166000036108f95760405162461bcd60e51b815260206004820152601960248201527f5374616b696e672030206973206e6f7420616c6c6f7765642e00000000000000604482015260640161088e565b336000908152600960205260408120600301805483929061092d9084906fffffffffffffffffffffffffffffffff16614564565b82546101009290920a6fffffffffffffffffffffffffffffffff8181021990931691831602179091556007546040517ff242432a00000000000000000000000000000000000000000000000000000000815233600482015230602482015260026044820152918416606483015260a06084830152600060a483015273ffffffffffffffffffffffffffffffffffffffff16915063f242432a9060c401600060405180830381600087803b1580156109e357600080fd5b505af11580156109f7573d6000803e3d6000fd5b50610a609250339150600290505b6040805173ffffffffffffffffffffffffffffffffffffffff90931660208401528201526fffffffffffffffffffffffffffffffff831660608201526001608082015260a0015b6040516020818303038152906040526126c2565b50565b600a5460ff1615610ab65760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b336000908152600960205260408120815b8351811015610d79576000848281518110610ae457610ae46145c7565b60200260200101519050610b4a83600001805480602002602001604051908101604052809291908181526020018280548015610b3f57602002820191906000526020600020905b815481526020019060010190808311610b2b575b50505050508261274c565b610b965760405162461bcd60e51b815260206004820152601a60248201527f596f7520646f206e6f74206f776e2074686973206c6c616d612e000000000000604482015260640161088e565b6101f4811015610bac57610ba9846145f6565b93505b6005546040517f23b872dd0000000000000000000000000000000000000000000000000000000081523060048201523360248201526044810183905273ffffffffffffffffffffffffffffffffffffffff909116906323b872dd90606401600060405180830381600087803b158015610c2457600080fd5b505af1158015610c38573d6000803e3d6000fd5b5050845460408051602080840282018101909252828152600094509250869190830182828015610c8757602002820191906000526020600020905b815481526020019060010190808311610c73575b505050505090506000805b8251811015610cd15783838281518110610cae57610cae6145c7565b602002602001015103610cbf578091505b80610cc9816145f6565b915050610c92565b5082828281518110610ce557610ce56145c7565b602002602001015103610d635784548290610d029060019061462e565b81518110610d1257610d126145c7565b6020026020010151856000018281548110610d2f57610d2f6145c7565b6000918252602090912001558454859080610d4c57610d4c614645565b600190038181906000526020600020016000905590555b5050508080610d71906145f6565b915050610ac7565b508115610dc057610dc03360016040805173ffffffffffffffffffffffffffffffffffffffff9093166020840152820152606081018490526000608082015260a001610a4c565b6000828451610dcf919061462e565b1115610e2357610e23336000848651610de8919061462e565b6040805173ffffffffffffffffffffffffffffffffffffffff909416602085015283019190915260608201526000608082015260a001610a4c565b505050565b6fffffffffffffffffffffffffffffffff821615610e4957610e498261083f565b6fffffffffffffffffffffffffffffffff811615610e6a57610e6a81611359565b5050565b600a5460ff1615610ec15760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b3360009081526009602052604090206002015415610f475760405162461bcd60e51b815260206004820152602560248201527f596f7520616c726561647920686176652061206c6c616d61647261777320737460448201527f616b65642e000000000000000000000000000000000000000000000000000000606482015260840161088e565b336000818152600960205260409081902060020183905560065490517f23b872dd00000000000000000000000000000000000000000000000000000000815260048101929092523060248301526044820183905273ffffffffffffffffffffffffffffffffffffffff16906323b872dd90606401600060405180830381600087803b158015610fd557600080fd5b505af1158015610fe9573d6000803e3d6000fd5b50610a609250339150600590505b6040805173ffffffffffffffffffffffffffffffffffffffff9093166020840152820152600160608201819052608082015260a001610a4c565b600a5460ff16156110845760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b3360009081526009602090815260409182902080548351818402810184019094528084526101f485109391926110f1929184918301828280156110e657602002820191906000526020600020905b8154815260200190600101908083116110d2575b50505050508461274c565b61113d5760405162461bcd60e51b815260206004820152601a60248201527f596f7520646f206e6f74206f776e2074686973206c6c616d612e000000000000604482015260640161088e565b6005546040517f23b872dd0000000000000000000000000000000000000000000000000000000081523060048201523360248201526044810185905273ffffffffffffffffffffffffffffffffffffffff909116906323b872dd90606401600060405180830381600087803b1580156111b557600080fd5b505af11580156111c9573d6000803e3d6000fd5b505082546040805160208084028201810190925282815260009450925084919083018282801561121857602002820191906000526020600020905b815481526020019060010190808311611204575b505050505090506000805b8251811015611262578583828151811061123f5761123f6145c7565b602002602001015103611250578091505b8061125a816145f6565b915050611223565b5084828281518110611276576112766145c7565b602002602001015103611352576112e13385611293576000611296565b60015b60058111156112a7576112a7614598565b6040805173ffffffffffffffffffffffffffffffffffffffff9093166020840152820152600160608201526000608082015260a001610a4c565b825482906112f19060019061462e565b81518110611301576113016145c7565b602002602001015183600001828154811061131e5761131e6145c7565b600091825260209091200155825483908061133b5761133b614645565b600190038181906000526020600020016000905590555b5050505050565b600a5460ff16156113ac5760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b806fffffffffffffffffffffffffffffffff1660000361140e5760405162461bcd60e51b815260206004820152601960248201527f5374616b696e672030206973206e6f7420616c6c6f7765642e00000000000000604482015260640161088e565b336000908152600960205260409020600301805482919060109061145990849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16614564565b82546101009290920a6fffffffffffffffffffffffffffffffff8181021990931691831602179091556007546040517ff242432a00000000000000000000000000000000000000000000000000000000815233600482015230602482015260016044820152918416606483015260a06084830152600060a483015273ffffffffffffffffffffffffffffffffffffffff16915063f242432a9060c401600060405180830381600087803b15801561150f57600080fd5b505af1158015611523573d6000803e3d6000fd5b50610a60925033915060039050610a05565b73ffffffffffffffffffffffffffffffffffffffff811660009081526009602090815260408083208151815460c09481028201850190935260a081018381526060959485948594859485949093919284928491908401828280156115b857602002820191906000526020600020905b8154815260200190600101908083116115a4575b5050509183525050600182015460208083019190915260028301546040808401919091526003909301546fffffffffffffffffffffffffffffffff8082166060808601919091527001000000000000000000000000000000009092041660809384015284519185015193850151908501519490920151909b929a5090985091965090945092505050565b84511561165257611652856117cd565b61165c8484610e28565b811561166b5761166b82612515565b80156113525761135281610e6e565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600960209081526040808320805482518185028101850190935280835284938301828280156116e457602002820191906000526020600020905b8154815260200190600101908083116116d0575b5050505050905080516000036116fd5750600092915050565b60005b8151811015611748576101f482828151811061171e5761171e6145c7565b60200260200101511015611736575060019392505050565b80611740816145f6565b915050611700565b5060029392505050565b60045473ffffffffffffffffffffffffffffffffffffffff1633146117a3576040517f30cd747100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b600a5460ff16156118205760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b336000908152600960205260408120815b8351811015611982576101f484828151811061184f5761184f6145c7565b6020026020010151101561186957611866836145f6565b92505b8160000184828151811061187f5761187f6145c7565b60209081029190910181015182546001810184556000938452919092200155600554845173ffffffffffffffffffffffffffffffffffffffff909116906323b872dd90339030908890869081106118d8576118d86145c7565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff93841660048201529290911660248301526044820152606401600060405180830381600087803b15801561195757600080fd5b505af115801561196b573d6000803e3d6000fd5b50505050808061197a906145f6565b915050611831565b5081156119c9576119c93360016040805173ffffffffffffffffffffffffffffffffffffffff9093166020840152820152606081018490526001608082015260a001610a4c565b60008284516119d8919061462e565b1115610e2357610e233360008486516119f1919061462e565b6040805173ffffffffffffffffffffffffffffffffffffffff909416602085015283019190915260608201526001608082015260a001610a4c565b600a5460ff1615611a7f5760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b806fffffffffffffffffffffffffffffffff16600003611ae15760405162461bcd60e51b815260206004820152601b60248201527f556e7374616b696e672030206973206e6f7420616c6c6f7765642e0000000000604482015260640161088e565b3360009081526009602052604090206003018054829190601090611b2c90849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16614674565b82546101009290920a6fffffffffffffffffffffffffffffffff8181021990931691831602179091556007546040517ff242432a00000000000000000000000000000000000000000000000000000000815230600482015233602482015260016044820152918416606483015260a06084830152600060a483015273ffffffffffffffffffffffffffffffffffffffff16915063f242432a9060c401600060405180830381600087803b158015611be257600080fd5b505af1158015611bf6573d6000803e3d6000fd5b50610a609250339150600390505b6040805173ffffffffffffffffffffffffffffffffffffffff90931660208401528201526fffffffffffffffffffffffffffffffff831660608201526000608082015260a001610a4c565b845115611c5f57611c5f85610a63565b611c698484611fa5565b8115611c7757611c77611d1e565b80156113525761135261211c565b60045473ffffffffffffffffffffffffffffffffffffffff163314611ca957600080fd5b6005805473ffffffffffffffffffffffffffffffffffffffff9586167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179091556006805494861694821694909417909355600780549285169284169290921790915560088054919093169116179055565b600a5460ff1615611d715760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b336000908152600960205260408120600101549003611df85760405162461bcd60e51b815260206004820152602760248201527f596f7520646f206e6f7420686176652061207069786c65742063616e7661732060448201527f7374616b65642e00000000000000000000000000000000000000000000000000606482015260840161088e565b6008543360008181526009602052604080822060019081015491517ff242432a00000000000000000000000000000000000000000000000000000000815230600482015260248101949094526044840191909152606483015260a0608483015260a482015273ffffffffffffffffffffffffffffffffffffffff9091169063f242432a9060c401600060405180830381600087803b158015611e9957600080fd5b505af1158015611ead573d6000803e3d6000fd5b505033600081815260096020526040812060010155611ed09250905060046112a7565b565b60025473ffffffffffffffffffffffffffffffffffffffff1615611f5e5760405162461bcd60e51b815260206004820152602a60248201527f467842617365526f6f7454756e6e656c3a204348494c445f54554e4e454c5f4160448201527f4c52454144595f53455400000000000000000000000000000000000000000000606482015260840161088e565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6fffffffffffffffffffffffffffffffff821615611fc657611fc6826122b8565b6fffffffffffffffffffffffffffffffff811615610e6a57610e6a81611a2c565b600a5460ff161561203a5760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b33600081815260096020908152604080832080546001810182558185529290932090910184905560055490517f23b872dd0000000000000000000000000000000000000000000000000000000081526004810193909352306024840152604483018490526101f484109273ffffffffffffffffffffffffffffffffffffffff909116906323b872dd90606401600060405180830381600087803b1580156120e057600080fd5b505af11580156120f4573d6000803e3d6000fd5b50505050610e23338361210857600061210b565b60015b6005811115610ff757610ff7614598565b600a5460ff161561216f5760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b3360009081526009602052604081206002015490036121f55760405162461bcd60e51b8152602060048201526024808201527f596f7520646f206e6f7420686176652061206c6c616d6164726177732073746160448201527f6b65642e00000000000000000000000000000000000000000000000000000000606482015260840161088e565b60065433600081815260096020526040908190206002015490517f23b872dd0000000000000000000000000000000000000000000000000000000081523060048201526024810192909252604482015273ffffffffffffffffffffffffffffffffffffffff909116906323b872dd90606401600060405180830381600087803b15801561228157600080fd5b505af1158015612295573d6000803e3d6000fd5b505033600081815260096020526040812060020155611ed09250905060056112a7565b600a5460ff161561230b5760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b806fffffffffffffffffffffffffffffffff1660000361236d5760405162461bcd60e51b815260206004820152601b60248201527f556e7374616b696e672030206973206e6f7420616c6c6f7765642e0000000000604482015260640161088e565b33600090815260096020526040812060030180548392906123a19084906fffffffffffffffffffffffffffffffff16614674565b82546101009290920a6fffffffffffffffffffffffffffffffff8181021990931691831602179091556007546040517ff242432a00000000000000000000000000000000000000000000000000000000815230600482015233602482015260026044820152918416606483015260a06084830152600060a483015273ffffffffffffffffffffffffffffffffffffffff16915063f242432a9060c401600060405180830381600087803b15801561245757600080fd5b505af115801561246b573d6000803e3d6000fd5b50610a60925033915060029050611c04565b60045473ffffffffffffffffffffffffffffffffffffffff1633146124ce576040517f30cd747100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600a5460ff16156125685760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b33600090815260096020526040902060010154156125ee5760405162461bcd60e51b815260206004820152602860248201527f596f7520616c726561647920686176652061207069786c65742063616e76617360448201527f207374616b65642e000000000000000000000000000000000000000000000000606482015260840161088e565b33600081815260096020526040808220600190810185905560085491517ff242432a000000000000000000000000000000000000000000000000000000008152600481019490945230602485015260448401859052606484015260a0608484015260a483019190915273ffffffffffffffffffffffffffffffffffffffff169063f242432a9060c401600060405180830381600087803b15801561269157600080fd5b505af11580156126a5573d6000803e3d6000fd5b50610a60925033915060049050610ff7565b6000610e23826127a1565b6000546002546040517fb472047700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169263b47204779261271e9291169085906004016146d5565b600060405180830381600087803b15801561273857600080fd5b505af1158015611352573d6000803e3d6000fd5b6000805b8351811015612795578284828151811061276c5761276c6145c7565b60200260200101510361278357600191505061279b565b8061278d816145f6565b915050612750565b50600090505b92915050565b606060006127ae83612b1b565b905060006127bb82612b7a565b905060006127c883612ba3565b90506000816127d684612bcc565b6127df86612dba565b6040516020016127f193929190614743565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600390935291205490915060ff16156128ac5760405162461bcd60e51b8152602060048201526024808201527f4678526f6f7454756e6e656c3a20455849545f414c52454144595f50524f434560448201527f5353454400000000000000000000000000000000000000000000000000000000606482015260840161088e565b600081815260036020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556128ec85612dd6565b905060006128f982612f20565b905061290481612fb0565b60025473ffffffffffffffffffffffffffffffffffffffff9081169116146129945760405162461bcd60e51b815260206004820152602560248201527f4678526f6f7454756e6e656c3a20494e56414c49445f46585f4348494c445f5460448201527f554e4e454c000000000000000000000000000000000000000000000000000000606482015260840161088e565b600061299f87612fd9565b90506129bf6129af846020015190565b876129b98a612ff5565b84613011565b612a315760405162461bcd60e51b815260206004820152602360248201527f4678526f6f7454756e6e656c3a20494e56414c49445f524543454950545f505260448201527f4f4f460000000000000000000000000000000000000000000000000000000000606482015260840161088e565b612a5f85612a3e896132c4565b612a478a6132e0565b84612a518c6132fc565b612a5a8d613318565b613334565b506000612a6b83613480565b90507f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036612aa1612a9c8360006134bc565b6134f4565b14612aee5760405162461bcd60e51b815260206004820152601f60248201527f4678526f6f7454756e6e656c3a20494e56414c49445f5349474e415455524500604482015260640161088e565b6000612af98461356f565b806020019051810190612b0c9190614770565b9b9a5050505050505050505050565b6040805160208101909152606081526000612b65612b608460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b61358b565b60408051602081019091529081529392505050565b606061279b8260000151600881518110612b9657612b966145c7565b60200260200101516136a1565b600061279b8260000151600281518110612bbf57612bbf6145c7565b60200260200101516134f4565b6040805160208101909152600081528151606091901561279b57600080612bf460008661373e565b60f81c90506001811480612c0b57508060ff166003145b15612ccb57600185516002612c2091906147e7565b612c2a919061462e565b67ffffffffffffffff811115612c4257612c42613fb3565b6040519080825280601f01601f191660200182016040528015612c6c576020820181803683370190505b5092506000612c7c60018761373e565b90508084600081518110612c9257612c926145c7565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001925050612d2f565b600285516002612cdb91906147e7565b612ce5919061462e565b67ffffffffffffffff811115612cfd57612cfd613fb3565b6040519080825280601f01601f191660200182016040528015612d27576020820181803683370190505b509250600091505b60ff82165b8351811015612db157612d5e612d4d60ff85168361462e565b612d58906002614824565b8761373e565b848281518110612d7057612d706145c7565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080612da9816145f6565b915050612d34565b50505092915050565b600061279b8260000151600981518110612bbf57612bbf6145c7565b612dfa60405180606001604052806060815260200160608152602001600081525090565b612e148260000151600681518110612b9657612b966145c7565b602082810182905260408051808201825260008082529083015280518082019091528251815291810190820152612e4a816137bf565b15612e5f57612e588161358b565b8252612f0c565b60208201518051600090612e759060019061462e565b67ffffffffffffffff811115612e8d57612e8d613fb3565b6040519080825280601f01601f191660200182016040528015612eb7576020820181803683370190505b509050600080836021019150826020019050612ed5828285516137fa565b604080518082018252600080825260209182015281518083019092528451825280850190820152612f059061358b565b8652505050505b612f1583612dba565b604083015250919050565b604080516080810182526000918101828152606080830193909352815260208101919091526000612f6e8360000151600381518110612f6157612f616145c7565b602002602001015161358b565b836040015181518110612f8357612f836145c7565b602002602001015190506040518060400160405280828152602001612fa78361358b565b90529392505050565b600061279b8260200151600081518110612fcc57612fcc6145c7565b6020026020010151613878565b600061279b8260000151600581518110612bbf57612bbf6145c7565b606061279b8260000151600781518110612b9657612b966145c7565b6000806130458460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b905060006130528261358b565b9050606080856000806130648b612bcc565b9050805160000361307f5760009750505050505050506132bc565b60005b86518110156132b35781518311156130a5576000985050505050505050506132bc565b6130c78782815181106130ba576130ba6145c7565b6020026020010151613892565b9550858051906020012084146130e8576000985050505050505050506132bc565b6130fd878281518110612f6157612f616145c7565b945084516011036131cf578151830361315c578c8051906020012061312e86601081518110612b9657612b966145c7565b805190602001200361314b576001985050505050505050506132bc565b6000985050505050505050506132bc565b6000828481518110613170576131706145c7565b016020015160f81c9050601081111561319557600099505050505050505050506132bc565b6131ba868260ff16815181106131ad576131ad6145c7565b6020026020010151613911565b94506131c7600185614824565b9350506132a1565b845160020361314b5760006131fa6131f387600081518110612b9657612b966145c7565b848661393f565b83519091506132098286614824565b0361325c578d8051906020012061322c87600181518110612b9657612b966145c7565b805190602001200361324a57600199505050505050505050506132bc565b600099505050505050505050506132bc565b8060000361327657600099505050505050505050506132bc565b6132808185614824565b9350613298866001815181106131ad576131ad6145c7565b94506132a19050565b806132ab816145f6565b915050613082565b50505050505050505b949350505050565b600061279b8260000151600381518110612bbf57612bbf6145c7565b600061279b8260000151600481518110612bbf57612bbf6145c7565b600061279b8260000151600081518110612bbf57612bbf6145c7565b606061279b8260000151600181518110612b9657612b966145c7565b6001546040517f41539d4a0000000000000000000000000000000000000000000000000000000081526004810184905260009182918291829173ffffffffffffffffffffffffffffffffffffffff909116906341539d4a9060240160a060405180830381865afa1580156133ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133d0919061483c565b5093505092509250613427828b6133e7919061462e565b6040805160208082018f90528183018e9052606082018d905260808083018d90528351808403909101815260a09092019092528051910120908588613a77565b6134735760405162461bcd60e51b815260206004820152601c60248201527f4678526f6f7454756e6e656c3a20494e56414c49445f48454144455200000000604482015260640161088e565b9998505050505050505050565b60408051602081019091526060815260405180602001604052806134b48460200151600181518110612f6157612f616145c7565b905292915050565b604080518082019091526000808252602082015282518051839081106134e4576134e46145c7565b6020026020010151905092915050565b80516000901580159061350957508151602110155b61351257600080fd5b60006135218360200151613bf0565b90506000818460000151613535919061462e565b905060008083866020015161354a9190614824565b905080519150602083101561356657826020036101000a820491505b50949350505050565b606061279b8260200151600281518110612b9657612b966145c7565b6060613596826137bf565b61359f57600080fd5b60006135aa83613c72565b905060008167ffffffffffffffff8111156135c7576135c7613fb3565b60405190808252806020026020018201604052801561360c57816020015b60408051808201909152600080825260208201528152602001906001900390816135e55790505b509050600061361e8560200151613bf0565b856020015161362d9190614824565b90506000805b848110156136965761364483613cf7565b915060405180604001604052808381526020018481525084828151811061366d5761366d6145c7565b60209081029190910101526136828284614824565b92508061368e816145f6565b915050613633565b509195945050505050565b80516060906136af57600080fd5b60006136be8360200151613bf0565b905060008184600001516136d2919061462e565b905060008167ffffffffffffffff8111156136ef576136ef613fb3565b6040519080825280601f01601f191660200182016040528015613719576020820181803683370190505b50905060008160200190506135668487602001516137379190614824565b8285613db9565b600061374b6002846148b8565b156137855760108261375e6002866148cc565b8151811061376e5761376e6145c7565b0160200151613780919060f81c6148e0565b6137b5565b6010826137936002866148cc565b815181106137a3576137a36145c7565b01602001516137b5919060f81c614902565b60f81b9392505050565b805160009081036137d257506000919050565b6020820151805160001a9060c08210156137f0575060009392505050565b5060019392505050565b8060000361380757505050565b6020811061383f578251825261381e602084614824565b925061382b602083614824565b915061383860208261462e565b9050613807565b6000600161384e83602061462e565b61385a90610100614a44565b613864919061462e565b935183518516941916939093179091525050565b805160009060151461388957600080fd5b61279b826134f4565b60606000826000015167ffffffffffffffff8111156138b3576138b3613fb3565b6040519080825280601f01601f1916602001820160405280156138dd576020820181803683370190505b50905080516000036138ef5792915050565b600081602001905061390a8460200151828660000151613db9565b5092915050565b805160009060211461392257600080fd5b600080836020015160016139369190614824565b51949350505050565b6000808061394c86612bcc565b90506000815167ffffffffffffffff81111561396a5761396a613fb3565b6040519080825280601f01601f191660200182016040528015613994576020820181803683370190505b509050845b82516139a59087614824565b811015613a485760008782815181106139c0576139c06145c7565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016905080836139f5898561462e565b81518110613a0557613a056145c7565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350508080613a40906145f6565b915050613999565b508080519060200120828051906020012003613a675781519250613a6c565b600092505b509095945050505050565b600060208251613a8791906148b8565b15613ad45760405162461bcd60e51b815260206004820152601460248201527f496e76616c69642070726f6f66206c656e677468000000000000000000000000604482015260640161088e565b600060208351613ae491906148cc565b9050613af1816002614a44565b8510613b3f5760405162461bcd60e51b815260206004820152601560248201527f4c65616620696e64657820697320746f6f206269670000000000000000000000604482015260640161088e565b60008660205b85518111613be257858101519250613b5e6002896148b8565b600003613b96576040805160208101849052908101849052606001604051602081830303815290604052805190602001209150613bc3565b60408051602081018590529081018390526060016040516020818303038152906040528051906020012091505b613bce6002896148cc565b9750613bdb602082614824565b9050613b45565b509094149695505050505050565b8051600090811a6080811015613c095750600092915050565b60b8811080613c24575060c08110801590613c24575060f881105b15613c325750600192915050565b60c0811015613c6657613c47600160b8614a50565b613c549060ff168261462e565b613c5f906001614824565b9392505050565b613c47600160f8614a50565b80516000908103613c8557506000919050565b600080613c958460200151613bf0565b8460200151613ca49190614824565b9050600084600001518560200151613cbc9190614824565b90505b80821015613cee57613cd082613cf7565b613cda9083614824565b915082613ce6816145f6565b935050613cbf565b50909392505050565b80516000908190811a6080811015613d12576001915061390a565b60b8811015613d3857613d2660808261462e565b613d31906001614824565b915061390a565b60c0811015613d655760b78103600185019450806020036101000a8551046001820181019350505061390a565b60f8811015613d7957613d2660c08261462e565b60019390930151602084900360f7016101000a90049092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0a0192915050565b80600003613dc657505050565b60208110613dfe5782518252613ddd602084614824565b9250613dea602083614824565b9150613df760208261462e565b9050613dc6565b8060000361383f57505050565b600060208284031215613e1d57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114613c5f57600080fd5b73ffffffffffffffffffffffffffffffffffffffff81168114610a6057600080fd5b60008083601f840112613e8157600080fd5b50813567ffffffffffffffff811115613e9957600080fd5b602083019150836020828501011115613eb157600080fd5b9250929050565b600080600080600060808688031215613ed057600080fd5b8535613edb81613e4d565b94506020860135613eeb81613e4d565b935060408601359250606086013567ffffffffffffffff811115613f0e57600080fd5b613f1a88828901613e6f565b969995985093965092949392505050565b80358015158114613f3b57600080fd5b919050565b600060208284031215613f5257600080fd5b613c5f82613f2b565b80356fffffffffffffffffffffffffffffffff81168114613f3b57600080fd5b600060208284031215613f8d57600080fd5b613c5f82613f5b565b600060208284031215613fa857600080fd5b8135613c5f81613e4d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561402957614029613fb3565b604052919050565b600082601f83011261404257600080fd5b8135602067ffffffffffffffff82111561405e5761405e613fb3565b8160051b61406d828201613fe2565b928352848101820192828101908785111561408757600080fd5b83870192505b848310156140a65782358252918301919083019061408d565b979650505050505050565b6000602082840312156140c357600080fd5b813567ffffffffffffffff8111156140da57600080fd5b6132bc84828501614031565b600080604083850312156140f957600080fd5b61410283613f5b565b915061411060208401613f5b565b90509250929050565b60006020828403121561412b57600080fd5b5035919050565b60a0808252865190820181905260009060209060c0840190828a01845b8281101561416b5781518452928401929084019060010161414f565b505050908301969096525060408101939093526fffffffffffffffffffffffffffffffff918216606084015216608090910152919050565b600080600080600060a086880312156141bb57600080fd5b853567ffffffffffffffff8111156141d257600080fd5b6141de88828901614031565b9550506141ed60208701613f5b565b93506141fb60408701613f5b565b94979396509394606081013594506080013592915050565b600080600080600060a0868803121561422b57600080fd5b853567ffffffffffffffff81111561424257600080fd5b61424e88828901614031565b95505061425d60208701613f5b565b935061426b60408701613f5b565b925061427960608701613f2b565b915061428760808701613f2b565b90509295509295909350565b600080600080608085870312156142a957600080fd5b84356142b481613e4d565b935060208501356142c481613e4d565b925060408501356142d481613e4d565b915060608501356142e481613e4d565b939692955090935050565b60008083601f84011261430157600080fd5b50813567ffffffffffffffff81111561431957600080fd5b6020830191508360208260051b8501011115613eb157600080fd5b60008060008060008060008060a0898b03121561435057600080fd5b883561435b81613e4d565b9750602089013561436b81613e4d565b9650604089013567ffffffffffffffff8082111561438857600080fd5b6143948c838d016142ef565b909850965060608b01359150808211156143ad57600080fd5b6143b98c838d016142ef565b909650945060808b01359150808211156143d257600080fd5b506143df8b828c01613e6f565b999c989b5096995094979396929594505050565b60008060008060008060a0878903121561440c57600080fd5b863561441781613e4d565b9550602087013561442781613e4d565b94506040870135935060608701359250608087013567ffffffffffffffff81111561445157600080fd5b61445d89828a01613e6f565b979a9699509497509295939492505050565b600067ffffffffffffffff82111561448957614489613fb3565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b6000602082840312156144c757600080fd5b813567ffffffffffffffff8111156144de57600080fd5b8201601f810184136144ef57600080fd5b80356145026144fd8261446f565b613fe2565b81815285602083850101111561451757600080fd5b81602084016020830137600091810160200191909152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006fffffffffffffffffffffffffffffffff80831681851680830382111561458f5761458f614535565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361462757614627614535565b5060010190565b60008282101561464057614640614535565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60006fffffffffffffffffffffffffffffffff8381169083168181101561469d5761469d614535565b039392505050565b60005b838110156146c05781810151838201526020016146a8565b838111156146cf576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600082518060408401526147108160608501602087016146a5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016060019392505050565b8381526000835161475b8160208501602088016146a5565b60209201918201929092526040019392505050565b60006020828403121561478257600080fd5b815167ffffffffffffffff81111561479957600080fd5b8201601f810184136147aa57600080fd5b80516147b86144fd8261446f565b8181528560208385010111156147cd57600080fd5b6147de8260208301602086016146a5565b95945050505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561481f5761481f614535565b500290565b6000821982111561483757614837614535565b500190565b600080600080600060a0868803121561485457600080fd5b85519450602086015193506040860151925060608601519150608086015161487b81613e4d565b809150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826148c7576148c7614889565b500690565b6000826148db576148db614889565b500490565b600060ff8316806148f3576148f3614889565b8060ff84160691505092915050565b600060ff83168061491557614915614889565b8060ff84160491505092915050565b600181815b8085111561497d57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561496357614963614535565b8085161561497057918102915b93841c9390800290614929565b509250929050565b6000826149945750600161279b565b816149a15750600061279b565b81600181146149b757600281146149c1576149dd565b600191505061279b565b60ff8411156149d2576149d2614535565b50506001821b61279b565b5060208310610133831016604e8410600b8410161715614a00575081810a61279b565b614a0a8383614924565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115614a3c57614a3c614535565b029392505050565b6000613c5f8383614985565b600060ff821660ff841680821015614a6a57614a6a614535565b9003939250505056fea26469706673582212209217d194649c8ac2c51aa00479d69ea51ac54bd1aa40db13a821cd0d44e3efe164736f6c634300080d003300000000000000000000000086e4dc95c7fbdbf52e33d563bbdb00823894c287000000000000000000000000fe5e5d361b2ad62c541bab87c45a0b9b018389a20000000000000000000000009df8aa7c681f33e442a0d57b838555da863504f300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bd4d37e0907c9f564aaa0a7528837b81b25c6050000000000000000000000000612dbc8671270768a10d1f6d5d988fc4ff23a1b

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102c85760003560e01c8063860420e31161017b578063c0857ba0116100d8578063e72cb05b1161008c578063f2fde38b11610071578063f2fde38b146107b1578063f3fa98a7146107c4578063f953cec7146107d757600080fd5b8063e72cb05b14610765578063f23a6e611461077857600080fd5b8063c7059488116100bd578063c70594881461071d578063de9b771f14610725578063dfcedeee1461074557600080fd5b8063c0857ba0146106ea578063c5bf09641461070a57600080fd5b8063abbe08181161012f578063bbb781cc11610114578063bbb781cc1461068f578063bc197c811461069c578063bd88119f146106d757600080fd5b8063abbe081814610674578063aea4e49e1461067c57600080fd5b80638da5cb5b116101605780638da5cb5b14610623578063972c492814610641578063aaa687771461066157600080fd5b8063860420e3146105fd578063891bc3d21461061057600080fd5b806350acac5511610229578063652972d4116101dd57806370a08231116101c257806370a08231146105cf578063715018a6146105e25780638282052b146105ea57600080fd5b8063652972d41461059c5780636f251724146105bc57600080fd5b80635d939ed01161020e5780635d939ed014610542578063607f2d421461055557806363c28db11461057857600080fd5b806350acac551461050f578063584a22061461052257600080fd5b80631820743d116102805780632176dfce116102655780632176dfce146104d65780633b0d79fa146104e95780634f9ce271146104fc57600080fd5b80631820743d1461042f5780631959a0021461044257600080fd5b80630f147692116102b15780630f1476921461036c578063150b7a02146103b157806315b31bbb1461041a57600080fd5b806301ffc9a7146102cd5780630e387de614610337575b600080fd5b6103226102db366004613e0b565b7fffffffff00000000000000000000000000000000000000000000000000000000167f7f5828d0000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b61035e7f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b03681565b60405190815260200161032e565b60055461038c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161032e565b6103e96103bf366004613eb8565b7f150b7a020000000000000000000000000000000000000000000000000000000095945050505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161032e565b61042d610428366004613f40565b6107ea565b005b61042d61043d366004613f7b565b61083f565b61049e610450366004613f96565b6009602052600090815260409020600181015460028201546003909201549091906fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041684565b6040805194855260208501939093526fffffffffffffffffffffffffffffffff9182169284019290925216606082015260800161032e565b61042d6104e43660046140b1565b610a63565b61042d6104f73660046140e6565b610e28565b61042d61050a366004614119565b610e6e565b61042d61051d366004614119565b611031565b60065461038c9073ffffffffffffffffffffffffffffffffffffffff1681565b61042d610550366004613f7b565b611359565b610322610563366004614119565b60036020526000908152604090205460ff1681565b61058b610586366004613f96565b611535565b60405161032e959493929190614132565b60085461038c9073ffffffffffffffffffffffffffffffffffffffff1681565b61042d6105ca3660046141a3565b611642565b61035e6105dd366004613f96565b61167a565b61042d611752565b61042d6105f83660046140b1565b6117cd565b61042d61060b366004613f7b565b611a2c565b61042d61061e366004614213565b611c4f565b60045473ffffffffffffffffffffffffffffffffffffffff1661038c565b60025461038c9073ffffffffffffffffffffffffffffffffffffffff1681565b61042d61066f366004614293565b611c85565b61042d611d1e565b61042d61068a366004613f96565b611ed2565b600a546103229060ff1681565b6103e96106aa366004614334565b7fbc197c810000000000000000000000000000000000000000000000000000000098975050505050505050565b61042d6106e53660046140e6565b611fa5565b60015461038c9073ffffffffffffffffffffffffffffffffffffffff1681565b61042d610718366004614119565b611fe7565b61042d61211c565b60005461038c9073ffffffffffffffffffffffffffffffffffffffff1681565b60075461038c9073ffffffffffffffffffffffffffffffffffffffff1681565b61042d610773366004613f7b565b6122b8565b6103e96107863660046143f3565b7ff23a6e61000000000000000000000000000000000000000000000000000000009695505050505050565b61042d6107bf366004613f96565b61247d565b61042d6107d2366004614119565b612515565b61042d6107e53660046144b5565b6126b7565b60045473ffffffffffffffffffffffffffffffffffffffff16331461080e57600080fd5b600a80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b600a5460ff16156108975760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e0000000060448201526064015b60405180910390fd5b806fffffffffffffffffffffffffffffffff166000036108f95760405162461bcd60e51b815260206004820152601960248201527f5374616b696e672030206973206e6f7420616c6c6f7765642e00000000000000604482015260640161088e565b336000908152600960205260408120600301805483929061092d9084906fffffffffffffffffffffffffffffffff16614564565b82546101009290920a6fffffffffffffffffffffffffffffffff8181021990931691831602179091556007546040517ff242432a00000000000000000000000000000000000000000000000000000000815233600482015230602482015260026044820152918416606483015260a06084830152600060a483015273ffffffffffffffffffffffffffffffffffffffff16915063f242432a9060c401600060405180830381600087803b1580156109e357600080fd5b505af11580156109f7573d6000803e3d6000fd5b50610a609250339150600290505b6040805173ffffffffffffffffffffffffffffffffffffffff90931660208401528201526fffffffffffffffffffffffffffffffff831660608201526001608082015260a0015b6040516020818303038152906040526126c2565b50565b600a5460ff1615610ab65760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b336000908152600960205260408120815b8351811015610d79576000848281518110610ae457610ae46145c7565b60200260200101519050610b4a83600001805480602002602001604051908101604052809291908181526020018280548015610b3f57602002820191906000526020600020905b815481526020019060010190808311610b2b575b50505050508261274c565b610b965760405162461bcd60e51b815260206004820152601a60248201527f596f7520646f206e6f74206f776e2074686973206c6c616d612e000000000000604482015260640161088e565b6101f4811015610bac57610ba9846145f6565b93505b6005546040517f23b872dd0000000000000000000000000000000000000000000000000000000081523060048201523360248201526044810183905273ffffffffffffffffffffffffffffffffffffffff909116906323b872dd90606401600060405180830381600087803b158015610c2457600080fd5b505af1158015610c38573d6000803e3d6000fd5b5050845460408051602080840282018101909252828152600094509250869190830182828015610c8757602002820191906000526020600020905b815481526020019060010190808311610c73575b505050505090506000805b8251811015610cd15783838281518110610cae57610cae6145c7565b602002602001015103610cbf578091505b80610cc9816145f6565b915050610c92565b5082828281518110610ce557610ce56145c7565b602002602001015103610d635784548290610d029060019061462e565b81518110610d1257610d126145c7565b6020026020010151856000018281548110610d2f57610d2f6145c7565b6000918252602090912001558454859080610d4c57610d4c614645565b600190038181906000526020600020016000905590555b5050508080610d71906145f6565b915050610ac7565b508115610dc057610dc03360016040805173ffffffffffffffffffffffffffffffffffffffff9093166020840152820152606081018490526000608082015260a001610a4c565b6000828451610dcf919061462e565b1115610e2357610e23336000848651610de8919061462e565b6040805173ffffffffffffffffffffffffffffffffffffffff909416602085015283019190915260608201526000608082015260a001610a4c565b505050565b6fffffffffffffffffffffffffffffffff821615610e4957610e498261083f565b6fffffffffffffffffffffffffffffffff811615610e6a57610e6a81611359565b5050565b600a5460ff1615610ec15760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b3360009081526009602052604090206002015415610f475760405162461bcd60e51b815260206004820152602560248201527f596f7520616c726561647920686176652061206c6c616d61647261777320737460448201527f616b65642e000000000000000000000000000000000000000000000000000000606482015260840161088e565b336000818152600960205260409081902060020183905560065490517f23b872dd00000000000000000000000000000000000000000000000000000000815260048101929092523060248301526044820183905273ffffffffffffffffffffffffffffffffffffffff16906323b872dd90606401600060405180830381600087803b158015610fd557600080fd5b505af1158015610fe9573d6000803e3d6000fd5b50610a609250339150600590505b6040805173ffffffffffffffffffffffffffffffffffffffff9093166020840152820152600160608201819052608082015260a001610a4c565b600a5460ff16156110845760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b3360009081526009602090815260409182902080548351818402810184019094528084526101f485109391926110f1929184918301828280156110e657602002820191906000526020600020905b8154815260200190600101908083116110d2575b50505050508461274c565b61113d5760405162461bcd60e51b815260206004820152601a60248201527f596f7520646f206e6f74206f776e2074686973206c6c616d612e000000000000604482015260640161088e565b6005546040517f23b872dd0000000000000000000000000000000000000000000000000000000081523060048201523360248201526044810185905273ffffffffffffffffffffffffffffffffffffffff909116906323b872dd90606401600060405180830381600087803b1580156111b557600080fd5b505af11580156111c9573d6000803e3d6000fd5b505082546040805160208084028201810190925282815260009450925084919083018282801561121857602002820191906000526020600020905b815481526020019060010190808311611204575b505050505090506000805b8251811015611262578583828151811061123f5761123f6145c7565b602002602001015103611250578091505b8061125a816145f6565b915050611223565b5084828281518110611276576112766145c7565b602002602001015103611352576112e13385611293576000611296565b60015b60058111156112a7576112a7614598565b6040805173ffffffffffffffffffffffffffffffffffffffff9093166020840152820152600160608201526000608082015260a001610a4c565b825482906112f19060019061462e565b81518110611301576113016145c7565b602002602001015183600001828154811061131e5761131e6145c7565b600091825260209091200155825483908061133b5761133b614645565b600190038181906000526020600020016000905590555b5050505050565b600a5460ff16156113ac5760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b806fffffffffffffffffffffffffffffffff1660000361140e5760405162461bcd60e51b815260206004820152601960248201527f5374616b696e672030206973206e6f7420616c6c6f7765642e00000000000000604482015260640161088e565b336000908152600960205260409020600301805482919060109061145990849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16614564565b82546101009290920a6fffffffffffffffffffffffffffffffff8181021990931691831602179091556007546040517ff242432a00000000000000000000000000000000000000000000000000000000815233600482015230602482015260016044820152918416606483015260a06084830152600060a483015273ffffffffffffffffffffffffffffffffffffffff16915063f242432a9060c401600060405180830381600087803b15801561150f57600080fd5b505af1158015611523573d6000803e3d6000fd5b50610a60925033915060039050610a05565b73ffffffffffffffffffffffffffffffffffffffff811660009081526009602090815260408083208151815460c09481028201850190935260a081018381526060959485948594859485949093919284928491908401828280156115b857602002820191906000526020600020905b8154815260200190600101908083116115a4575b5050509183525050600182015460208083019190915260028301546040808401919091526003909301546fffffffffffffffffffffffffffffffff8082166060808601919091527001000000000000000000000000000000009092041660809384015284519185015193850151908501519490920151909b929a5090985091965090945092505050565b84511561165257611652856117cd565b61165c8484610e28565b811561166b5761166b82612515565b80156113525761135281610e6e565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600960209081526040808320805482518185028101850190935280835284938301828280156116e457602002820191906000526020600020905b8154815260200190600101908083116116d0575b5050505050905080516000036116fd5750600092915050565b60005b8151811015611748576101f482828151811061171e5761171e6145c7565b60200260200101511015611736575060019392505050565b80611740816145f6565b915050611700565b5060029392505050565b60045473ffffffffffffffffffffffffffffffffffffffff1633146117a3576040517f30cd747100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b600a5460ff16156118205760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b336000908152600960205260408120815b8351811015611982576101f484828151811061184f5761184f6145c7565b6020026020010151101561186957611866836145f6565b92505b8160000184828151811061187f5761187f6145c7565b60209081029190910181015182546001810184556000938452919092200155600554845173ffffffffffffffffffffffffffffffffffffffff909116906323b872dd90339030908890869081106118d8576118d86145c7565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff93841660048201529290911660248301526044820152606401600060405180830381600087803b15801561195757600080fd5b505af115801561196b573d6000803e3d6000fd5b50505050808061197a906145f6565b915050611831565b5081156119c9576119c93360016040805173ffffffffffffffffffffffffffffffffffffffff9093166020840152820152606081018490526001608082015260a001610a4c565b60008284516119d8919061462e565b1115610e2357610e233360008486516119f1919061462e565b6040805173ffffffffffffffffffffffffffffffffffffffff909416602085015283019190915260608201526001608082015260a001610a4c565b600a5460ff1615611a7f5760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b806fffffffffffffffffffffffffffffffff16600003611ae15760405162461bcd60e51b815260206004820152601b60248201527f556e7374616b696e672030206973206e6f7420616c6c6f7765642e0000000000604482015260640161088e565b3360009081526009602052604090206003018054829190601090611b2c90849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16614674565b82546101009290920a6fffffffffffffffffffffffffffffffff8181021990931691831602179091556007546040517ff242432a00000000000000000000000000000000000000000000000000000000815230600482015233602482015260016044820152918416606483015260a06084830152600060a483015273ffffffffffffffffffffffffffffffffffffffff16915063f242432a9060c401600060405180830381600087803b158015611be257600080fd5b505af1158015611bf6573d6000803e3d6000fd5b50610a609250339150600390505b6040805173ffffffffffffffffffffffffffffffffffffffff90931660208401528201526fffffffffffffffffffffffffffffffff831660608201526000608082015260a001610a4c565b845115611c5f57611c5f85610a63565b611c698484611fa5565b8115611c7757611c77611d1e565b80156113525761135261211c565b60045473ffffffffffffffffffffffffffffffffffffffff163314611ca957600080fd5b6005805473ffffffffffffffffffffffffffffffffffffffff9586167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179091556006805494861694821694909417909355600780549285169284169290921790915560088054919093169116179055565b600a5460ff1615611d715760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b336000908152600960205260408120600101549003611df85760405162461bcd60e51b815260206004820152602760248201527f596f7520646f206e6f7420686176652061207069786c65742063616e7661732060448201527f7374616b65642e00000000000000000000000000000000000000000000000000606482015260840161088e565b6008543360008181526009602052604080822060019081015491517ff242432a00000000000000000000000000000000000000000000000000000000815230600482015260248101949094526044840191909152606483015260a0608483015260a482015273ffffffffffffffffffffffffffffffffffffffff9091169063f242432a9060c401600060405180830381600087803b158015611e9957600080fd5b505af1158015611ead573d6000803e3d6000fd5b505033600081815260096020526040812060010155611ed09250905060046112a7565b565b60025473ffffffffffffffffffffffffffffffffffffffff1615611f5e5760405162461bcd60e51b815260206004820152602a60248201527f467842617365526f6f7454756e6e656c3a204348494c445f54554e4e454c5f4160448201527f4c52454144595f53455400000000000000000000000000000000000000000000606482015260840161088e565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6fffffffffffffffffffffffffffffffff821615611fc657611fc6826122b8565b6fffffffffffffffffffffffffffffffff811615610e6a57610e6a81611a2c565b600a5460ff161561203a5760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b33600081815260096020908152604080832080546001810182558185529290932090910184905560055490517f23b872dd0000000000000000000000000000000000000000000000000000000081526004810193909352306024840152604483018490526101f484109273ffffffffffffffffffffffffffffffffffffffff909116906323b872dd90606401600060405180830381600087803b1580156120e057600080fd5b505af11580156120f4573d6000803e3d6000fd5b50505050610e23338361210857600061210b565b60015b6005811115610ff757610ff7614598565b600a5460ff161561216f5760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b3360009081526009602052604081206002015490036121f55760405162461bcd60e51b8152602060048201526024808201527f596f7520646f206e6f7420686176652061206c6c616d6164726177732073746160448201527f6b65642e00000000000000000000000000000000000000000000000000000000606482015260840161088e565b60065433600081815260096020526040908190206002015490517f23b872dd0000000000000000000000000000000000000000000000000000000081523060048201526024810192909252604482015273ffffffffffffffffffffffffffffffffffffffff909116906323b872dd90606401600060405180830381600087803b15801561228157600080fd5b505af1158015612295573d6000803e3d6000fd5b505033600081815260096020526040812060020155611ed09250905060056112a7565b600a5460ff161561230b5760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b806fffffffffffffffffffffffffffffffff1660000361236d5760405162461bcd60e51b815260206004820152601b60248201527f556e7374616b696e672030206973206e6f7420616c6c6f7765642e0000000000604482015260640161088e565b33600090815260096020526040812060030180548392906123a19084906fffffffffffffffffffffffffffffffff16614674565b82546101009290920a6fffffffffffffffffffffffffffffffff8181021990931691831602179091556007546040517ff242432a00000000000000000000000000000000000000000000000000000000815230600482015233602482015260026044820152918416606483015260a06084830152600060a483015273ffffffffffffffffffffffffffffffffffffffff16915063f242432a9060c401600060405180830381600087803b15801561245757600080fd5b505af115801561246b573d6000803e3d6000fd5b50610a60925033915060029050611c04565b60045473ffffffffffffffffffffffffffffffffffffffff1633146124ce576040517f30cd747100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600a5460ff16156125685760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e672069732063757272656e746c79207061757365642e00000000604482015260640161088e565b33600090815260096020526040902060010154156125ee5760405162461bcd60e51b815260206004820152602860248201527f596f7520616c726561647920686176652061207069786c65742063616e76617360448201527f207374616b65642e000000000000000000000000000000000000000000000000606482015260840161088e565b33600081815260096020526040808220600190810185905560085491517ff242432a000000000000000000000000000000000000000000000000000000008152600481019490945230602485015260448401859052606484015260a0608484015260a483019190915273ffffffffffffffffffffffffffffffffffffffff169063f242432a9060c401600060405180830381600087803b15801561269157600080fd5b505af11580156126a5573d6000803e3d6000fd5b50610a60925033915060049050610ff7565b6000610e23826127a1565b6000546002546040517fb472047700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169263b47204779261271e9291169085906004016146d5565b600060405180830381600087803b15801561273857600080fd5b505af1158015611352573d6000803e3d6000fd5b6000805b8351811015612795578284828151811061276c5761276c6145c7565b60200260200101510361278357600191505061279b565b8061278d816145f6565b915050612750565b50600090505b92915050565b606060006127ae83612b1b565b905060006127bb82612b7a565b905060006127c883612ba3565b90506000816127d684612bcc565b6127df86612dba565b6040516020016127f193929190614743565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600390935291205490915060ff16156128ac5760405162461bcd60e51b8152602060048201526024808201527f4678526f6f7454756e6e656c3a20455849545f414c52454144595f50524f434560448201527f5353454400000000000000000000000000000000000000000000000000000000606482015260840161088e565b600081815260036020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556128ec85612dd6565b905060006128f982612f20565b905061290481612fb0565b60025473ffffffffffffffffffffffffffffffffffffffff9081169116146129945760405162461bcd60e51b815260206004820152602560248201527f4678526f6f7454756e6e656c3a20494e56414c49445f46585f4348494c445f5460448201527f554e4e454c000000000000000000000000000000000000000000000000000000606482015260840161088e565b600061299f87612fd9565b90506129bf6129af846020015190565b876129b98a612ff5565b84613011565b612a315760405162461bcd60e51b815260206004820152602360248201527f4678526f6f7454756e6e656c3a20494e56414c49445f524543454950545f505260448201527f4f4f460000000000000000000000000000000000000000000000000000000000606482015260840161088e565b612a5f85612a3e896132c4565b612a478a6132e0565b84612a518c6132fc565b612a5a8d613318565b613334565b506000612a6b83613480565b90507f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036612aa1612a9c8360006134bc565b6134f4565b14612aee5760405162461bcd60e51b815260206004820152601f60248201527f4678526f6f7454756e6e656c3a20494e56414c49445f5349474e415455524500604482015260640161088e565b6000612af98461356f565b806020019051810190612b0c9190614770565b9b9a5050505050505050505050565b6040805160208101909152606081526000612b65612b608460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b61358b565b60408051602081019091529081529392505050565b606061279b8260000151600881518110612b9657612b966145c7565b60200260200101516136a1565b600061279b8260000151600281518110612bbf57612bbf6145c7565b60200260200101516134f4565b6040805160208101909152600081528151606091901561279b57600080612bf460008661373e565b60f81c90506001811480612c0b57508060ff166003145b15612ccb57600185516002612c2091906147e7565b612c2a919061462e565b67ffffffffffffffff811115612c4257612c42613fb3565b6040519080825280601f01601f191660200182016040528015612c6c576020820181803683370190505b5092506000612c7c60018761373e565b90508084600081518110612c9257612c926145c7565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001925050612d2f565b600285516002612cdb91906147e7565b612ce5919061462e565b67ffffffffffffffff811115612cfd57612cfd613fb3565b6040519080825280601f01601f191660200182016040528015612d27576020820181803683370190505b509250600091505b60ff82165b8351811015612db157612d5e612d4d60ff85168361462e565b612d58906002614824565b8761373e565b848281518110612d7057612d706145c7565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080612da9816145f6565b915050612d34565b50505092915050565b600061279b8260000151600981518110612bbf57612bbf6145c7565b612dfa60405180606001604052806060815260200160608152602001600081525090565b612e148260000151600681518110612b9657612b966145c7565b602082810182905260408051808201825260008082529083015280518082019091528251815291810190820152612e4a816137bf565b15612e5f57612e588161358b565b8252612f0c565b60208201518051600090612e759060019061462e565b67ffffffffffffffff811115612e8d57612e8d613fb3565b6040519080825280601f01601f191660200182016040528015612eb7576020820181803683370190505b509050600080836021019150826020019050612ed5828285516137fa565b604080518082018252600080825260209182015281518083019092528451825280850190820152612f059061358b565b8652505050505b612f1583612dba565b604083015250919050565b604080516080810182526000918101828152606080830193909352815260208101919091526000612f6e8360000151600381518110612f6157612f616145c7565b602002602001015161358b565b836040015181518110612f8357612f836145c7565b602002602001015190506040518060400160405280828152602001612fa78361358b565b90529392505050565b600061279b8260200151600081518110612fcc57612fcc6145c7565b6020026020010151613878565b600061279b8260000151600581518110612bbf57612bbf6145c7565b606061279b8260000151600781518110612b9657612b966145c7565b6000806130458460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b905060006130528261358b565b9050606080856000806130648b612bcc565b9050805160000361307f5760009750505050505050506132bc565b60005b86518110156132b35781518311156130a5576000985050505050505050506132bc565b6130c78782815181106130ba576130ba6145c7565b6020026020010151613892565b9550858051906020012084146130e8576000985050505050505050506132bc565b6130fd878281518110612f6157612f616145c7565b945084516011036131cf578151830361315c578c8051906020012061312e86601081518110612b9657612b966145c7565b805190602001200361314b576001985050505050505050506132bc565b6000985050505050505050506132bc565b6000828481518110613170576131706145c7565b016020015160f81c9050601081111561319557600099505050505050505050506132bc565b6131ba868260ff16815181106131ad576131ad6145c7565b6020026020010151613911565b94506131c7600185614824565b9350506132a1565b845160020361314b5760006131fa6131f387600081518110612b9657612b966145c7565b848661393f565b83519091506132098286614824565b0361325c578d8051906020012061322c87600181518110612b9657612b966145c7565b805190602001200361324a57600199505050505050505050506132bc565b600099505050505050505050506132bc565b8060000361327657600099505050505050505050506132bc565b6132808185614824565b9350613298866001815181106131ad576131ad6145c7565b94506132a19050565b806132ab816145f6565b915050613082565b50505050505050505b949350505050565b600061279b8260000151600381518110612bbf57612bbf6145c7565b600061279b8260000151600481518110612bbf57612bbf6145c7565b600061279b8260000151600081518110612bbf57612bbf6145c7565b606061279b8260000151600181518110612b9657612b966145c7565b6001546040517f41539d4a0000000000000000000000000000000000000000000000000000000081526004810184905260009182918291829173ffffffffffffffffffffffffffffffffffffffff909116906341539d4a9060240160a060405180830381865afa1580156133ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133d0919061483c565b5093505092509250613427828b6133e7919061462e565b6040805160208082018f90528183018e9052606082018d905260808083018d90528351808403909101815260a09092019092528051910120908588613a77565b6134735760405162461bcd60e51b815260206004820152601c60248201527f4678526f6f7454756e6e656c3a20494e56414c49445f48454144455200000000604482015260640161088e565b9998505050505050505050565b60408051602081019091526060815260405180602001604052806134b48460200151600181518110612f6157612f616145c7565b905292915050565b604080518082019091526000808252602082015282518051839081106134e4576134e46145c7565b6020026020010151905092915050565b80516000901580159061350957508151602110155b61351257600080fd5b60006135218360200151613bf0565b90506000818460000151613535919061462e565b905060008083866020015161354a9190614824565b905080519150602083101561356657826020036101000a820491505b50949350505050565b606061279b8260200151600281518110612b9657612b966145c7565b6060613596826137bf565b61359f57600080fd5b60006135aa83613c72565b905060008167ffffffffffffffff8111156135c7576135c7613fb3565b60405190808252806020026020018201604052801561360c57816020015b60408051808201909152600080825260208201528152602001906001900390816135e55790505b509050600061361e8560200151613bf0565b856020015161362d9190614824565b90506000805b848110156136965761364483613cf7565b915060405180604001604052808381526020018481525084828151811061366d5761366d6145c7565b60209081029190910101526136828284614824565b92508061368e816145f6565b915050613633565b509195945050505050565b80516060906136af57600080fd5b60006136be8360200151613bf0565b905060008184600001516136d2919061462e565b905060008167ffffffffffffffff8111156136ef576136ef613fb3565b6040519080825280601f01601f191660200182016040528015613719576020820181803683370190505b50905060008160200190506135668487602001516137379190614824565b8285613db9565b600061374b6002846148b8565b156137855760108261375e6002866148cc565b8151811061376e5761376e6145c7565b0160200151613780919060f81c6148e0565b6137b5565b6010826137936002866148cc565b815181106137a3576137a36145c7565b01602001516137b5919060f81c614902565b60f81b9392505050565b805160009081036137d257506000919050565b6020820151805160001a9060c08210156137f0575060009392505050565b5060019392505050565b8060000361380757505050565b6020811061383f578251825261381e602084614824565b925061382b602083614824565b915061383860208261462e565b9050613807565b6000600161384e83602061462e565b61385a90610100614a44565b613864919061462e565b935183518516941916939093179091525050565b805160009060151461388957600080fd5b61279b826134f4565b60606000826000015167ffffffffffffffff8111156138b3576138b3613fb3565b6040519080825280601f01601f1916602001820160405280156138dd576020820181803683370190505b50905080516000036138ef5792915050565b600081602001905061390a8460200151828660000151613db9565b5092915050565b805160009060211461392257600080fd5b600080836020015160016139369190614824565b51949350505050565b6000808061394c86612bcc565b90506000815167ffffffffffffffff81111561396a5761396a613fb3565b6040519080825280601f01601f191660200182016040528015613994576020820181803683370190505b509050845b82516139a59087614824565b811015613a485760008782815181106139c0576139c06145c7565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016905080836139f5898561462e565b81518110613a0557613a056145c7565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350508080613a40906145f6565b915050613999565b508080519060200120828051906020012003613a675781519250613a6c565b600092505b509095945050505050565b600060208251613a8791906148b8565b15613ad45760405162461bcd60e51b815260206004820152601460248201527f496e76616c69642070726f6f66206c656e677468000000000000000000000000604482015260640161088e565b600060208351613ae491906148cc565b9050613af1816002614a44565b8510613b3f5760405162461bcd60e51b815260206004820152601560248201527f4c65616620696e64657820697320746f6f206269670000000000000000000000604482015260640161088e565b60008660205b85518111613be257858101519250613b5e6002896148b8565b600003613b96576040805160208101849052908101849052606001604051602081830303815290604052805190602001209150613bc3565b60408051602081018590529081018390526060016040516020818303038152906040528051906020012091505b613bce6002896148cc565b9750613bdb602082614824565b9050613b45565b509094149695505050505050565b8051600090811a6080811015613c095750600092915050565b60b8811080613c24575060c08110801590613c24575060f881105b15613c325750600192915050565b60c0811015613c6657613c47600160b8614a50565b613c549060ff168261462e565b613c5f906001614824565b9392505050565b613c47600160f8614a50565b80516000908103613c8557506000919050565b600080613c958460200151613bf0565b8460200151613ca49190614824565b9050600084600001518560200151613cbc9190614824565b90505b80821015613cee57613cd082613cf7565b613cda9083614824565b915082613ce6816145f6565b935050613cbf565b50909392505050565b80516000908190811a6080811015613d12576001915061390a565b60b8811015613d3857613d2660808261462e565b613d31906001614824565b915061390a565b60c0811015613d655760b78103600185019450806020036101000a8551046001820181019350505061390a565b60f8811015613d7957613d2660c08261462e565b60019390930151602084900360f7016101000a90049092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0a0192915050565b80600003613dc657505050565b60208110613dfe5782518252613ddd602084614824565b9250613dea602083614824565b9150613df760208261462e565b9050613dc6565b8060000361383f57505050565b600060208284031215613e1d57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114613c5f57600080fd5b73ffffffffffffffffffffffffffffffffffffffff81168114610a6057600080fd5b60008083601f840112613e8157600080fd5b50813567ffffffffffffffff811115613e9957600080fd5b602083019150836020828501011115613eb157600080fd5b9250929050565b600080600080600060808688031215613ed057600080fd5b8535613edb81613e4d565b94506020860135613eeb81613e4d565b935060408601359250606086013567ffffffffffffffff811115613f0e57600080fd5b613f1a88828901613e6f565b969995985093965092949392505050565b80358015158114613f3b57600080fd5b919050565b600060208284031215613f5257600080fd5b613c5f82613f2b565b80356fffffffffffffffffffffffffffffffff81168114613f3b57600080fd5b600060208284031215613f8d57600080fd5b613c5f82613f5b565b600060208284031215613fa857600080fd5b8135613c5f81613e4d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561402957614029613fb3565b604052919050565b600082601f83011261404257600080fd5b8135602067ffffffffffffffff82111561405e5761405e613fb3565b8160051b61406d828201613fe2565b928352848101820192828101908785111561408757600080fd5b83870192505b848310156140a65782358252918301919083019061408d565b979650505050505050565b6000602082840312156140c357600080fd5b813567ffffffffffffffff8111156140da57600080fd5b6132bc84828501614031565b600080604083850312156140f957600080fd5b61410283613f5b565b915061411060208401613f5b565b90509250929050565b60006020828403121561412b57600080fd5b5035919050565b60a0808252865190820181905260009060209060c0840190828a01845b8281101561416b5781518452928401929084019060010161414f565b505050908301969096525060408101939093526fffffffffffffffffffffffffffffffff918216606084015216608090910152919050565b600080600080600060a086880312156141bb57600080fd5b853567ffffffffffffffff8111156141d257600080fd5b6141de88828901614031565b9550506141ed60208701613f5b565b93506141fb60408701613f5b565b94979396509394606081013594506080013592915050565b600080600080600060a0868803121561422b57600080fd5b853567ffffffffffffffff81111561424257600080fd5b61424e88828901614031565b95505061425d60208701613f5b565b935061426b60408701613f5b565b925061427960608701613f2b565b915061428760808701613f2b565b90509295509295909350565b600080600080608085870312156142a957600080fd5b84356142b481613e4d565b935060208501356142c481613e4d565b925060408501356142d481613e4d565b915060608501356142e481613e4d565b939692955090935050565b60008083601f84011261430157600080fd5b50813567ffffffffffffffff81111561431957600080fd5b6020830191508360208260051b8501011115613eb157600080fd5b60008060008060008060008060a0898b03121561435057600080fd5b883561435b81613e4d565b9750602089013561436b81613e4d565b9650604089013567ffffffffffffffff8082111561438857600080fd5b6143948c838d016142ef565b909850965060608b01359150808211156143ad57600080fd5b6143b98c838d016142ef565b909650945060808b01359150808211156143d257600080fd5b506143df8b828c01613e6f565b999c989b5096995094979396929594505050565b60008060008060008060a0878903121561440c57600080fd5b863561441781613e4d565b9550602087013561442781613e4d565b94506040870135935060608701359250608087013567ffffffffffffffff81111561445157600080fd5b61445d89828a01613e6f565b979a9699509497509295939492505050565b600067ffffffffffffffff82111561448957614489613fb3565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b6000602082840312156144c757600080fd5b813567ffffffffffffffff8111156144de57600080fd5b8201601f810184136144ef57600080fd5b80356145026144fd8261446f565b613fe2565b81815285602083850101111561451757600080fd5b81602084016020830137600091810160200191909152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006fffffffffffffffffffffffffffffffff80831681851680830382111561458f5761458f614535565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361462757614627614535565b5060010190565b60008282101561464057614640614535565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60006fffffffffffffffffffffffffffffffff8381169083168181101561469d5761469d614535565b039392505050565b60005b838110156146c05781810151838201526020016146a8565b838111156146cf576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600082518060408401526147108160608501602087016146a5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016060019392505050565b8381526000835161475b8160208501602088016146a5565b60209201918201929092526040019392505050565b60006020828403121561478257600080fd5b815167ffffffffffffffff81111561479957600080fd5b8201601f810184136147aa57600080fd5b80516147b86144fd8261446f565b8181528560208385010111156147cd57600080fd5b6147de8260208301602086016146a5565b95945050505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561481f5761481f614535565b500290565b6000821982111561483757614837614535565b500190565b600080600080600060a0868803121561485457600080fd5b85519450602086015193506040860151925060608601519150608086015161487b81613e4d565b809150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826148c7576148c7614889565b500690565b6000826148db576148db614889565b500490565b600060ff8316806148f3576148f3614889565b8060ff84160691505092915050565b600060ff83168061491557614915614889565b8060ff84160491505092915050565b600181815b8085111561497d57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561496357614963614535565b8085161561497057918102915b93841c9390800290614929565b509250929050565b6000826149945750600161279b565b816149a15750600061279b565b81600181146149b757600281146149c1576149dd565b600191505061279b565b60ff8411156149d2576149d2614535565b50506001821b61279b565b5060208310610133831016604e8410600b8410161715614a00575081810a61279b565b614a0a8383614924565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115614a3c57614a3c614535565b029392505050565b6000613c5f8383614985565b600060ff821660ff841680821015614a6a57614a6a614535565b9003939250505056fea26469706673582212209217d194649c8ac2c51aa00479d69ea51ac54bd1aa40db13a821cd0d44e3efe164736f6c634300080d0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000086e4dc95c7fbdbf52e33d563bbdb00823894c287000000000000000000000000fe5e5d361b2ad62c541bab87c45a0b9b018389a20000000000000000000000009df8aa7c681f33e442a0d57b838555da863504f300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bd4d37e0907c9f564aaa0a7528837b81b25c6050000000000000000000000000612dbc8671270768a10d1f6d5d988fc4ff23a1b

-----Decoded View---------------
Arg [0] : checkpointManager (address): 0x86E4Dc95c7FBdBf52e33D563BbDB00823894C287
Arg [1] : fxRoot (address): 0xfe5e5D361b2ad62c541bAb87C45a0B9B018389a2
Arg [2] : _pixellatedLlamaContract (address): 0x9df8Aa7C681f33E442A0d57B838555da863504f3
Arg [3] : _llamaDrawsContract (address): 0x0000000000000000000000000000000000000000
Arg [4] : _boostContract (address): 0x0BD4D37E0907C9F564aaa0a7528837B81B25c605
Arg [5] : _pixletContract (address): 0x0612DBC8671270768A10d1F6D5D988fc4FF23A1B

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 00000000000000000000000086e4dc95c7fbdbf52e33d563bbdb00823894c287
Arg [1] : 000000000000000000000000fe5e5d361b2ad62c541bab87c45a0b9b018389a2
Arg [2] : 0000000000000000000000009df8aa7c681f33e442a0d57b838555da863504f3
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000bd4d37e0907c9f564aaa0a7528837b81b25c605
Arg [5] : 0000000000000000000000000612dbc8671270768a10d1f6d5d988fc4ff23a1b


Deployed Bytecode Sourcemap

557:19180:6:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;840:201:9;;;;;;:::i;:::-;975:25;;;;;840:201;;;;516:14:12;;509:22;491:41;;479:2;464:18;840:201:9;;;;;;;;1166:115:5;;1215:66;1166:115;;;;;689:25:12;;;677:2;662:18;1166:115:5;543:177:12;850:37:6;;;;;;;;;;;;916:42:12;904:55;;;886:74;;874:2;859:18;850:37:6;725:241:12;17016:224:6;;;;;;:::i;:::-;17188:45;17016:224;;;;;;;;;;;2415:66:12;2403:79;;;2385:98;;2373:2;2358:18;17016:224:6;2241:248:12;3304:95:6;;;;;;:::i;:::-;;:::i;:::-;;10451:514;;;;;;:::i;:::-;;:::i;1380:42::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3711:25:12;;;3767:2;3752:18;;3745:34;;;;3798;3868:15;;;3848:18;;;3841:43;;;;3920:15;3915:2;3900:18;;3893:43;3698:3;3683:19;1380:42:6;3480:462:12;6574:1696:6;;;;;;:::i;:::-;;:::i;12931:199::-;;;;;;:::i;:::-;;:::i;14841:508::-;;;;;;:::i;:::-;;:::i;9135:1220::-;;;;;;:::i;:::-;;:::i;953:32::-;;;;;;;;;11783:507;;;;;;:::i;:::-;;:::i;1564:46:5:-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;3878:533:6;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;:::i;1145:29::-;;;;;;;;;4603:417;;;;;;:::i;:::-;;:::i;3476:296::-;;;;;;:::i;:::-;;:::i;708:126:9:-;;;:::i;5421:1147:6:-;;;;;;:::i;:::-;;:::i;12413:512::-;;;;;;:::i;:::-;;:::i;5026:389::-;;;;;;:::i;:::-;;:::i;473:79:9:-;539:6;;;;473:79;;1489:28:5;;;;;;;;;2693:430:6;;;;;;:::i;:::-;;:::i;14126:609::-;;;:::i;1841:198:5:-;;;;;;:::i;:::-;;:::i;1429:25:6:-;;;;;;;;;19450:285;;;;;;:::i;:::-;19676:52;19450:285;;;;;;;;;;;13136:205;;;;;;:::i;:::-;;:::i;1377:43:5:-;;;;;;;;;8375:651:6;;;;;;:::i;:::-;;:::i;15396:565::-;;;:::i;1317:28:5:-;;;;;;;;;1054::6;;;;;;;;;11065:597;;;;;;:::i;:::-;;:::i;18189:251::-;;;;;;:::i;:::-;18386:47;18189:251;;;;;;;;;558:144:9;;;;;;:::i;:::-;;:::i;13480:596:6:-;;;;;;:::i;:::-;;:::i;6492:183:5:-;;;;;;:::i;:::-;;:::i;3304:95:6:-;372:6:9;;:20;:6;382:10;372:20;364:29;;;;;;3370:13:6::1;:22:::0;;;::::1;::::0;::::1;;::::0;;;::::1;::::0;;3304:95::o;10451:514::-;10520:13;;;;10519:14;10511:55;;;;-1:-1:-1;;;10511:55:6;;13974:2:12;10511:55:6;;;13956:21:12;14013:2;13993:18;;;13986:30;14052;14032:18;;;14025:58;14100:18;;10511:55:6;;;;;;;;;10584:6;:11;;10594:1;10584:11;10576:49;;;;-1:-1:-1;;;10576:49:6;;14331:2:12;10576:49:6;;;14313:21:12;14370:2;14350:18;;;14343:30;14409:27;14389:18;;;14382:55;14454:18;;10576:49:6;14129:349:12;10576:49:6;10645:10;10636:20;;;;:8;:20;;;;;:39;;:49;;10679:6;;10636:20;:49;;10679:6;;10636:49;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;10695:13;;:142;;;;;10739:10;10695:142;;;15294:34:12;10771:4:6;15344:18:12;;;15337:43;10790:1:6;15396:18:12;;;15389:34;15459:47;;;15439:18;;;15432:75;15544:3;15523:19;;;15516:32;-1:-1:-1;15564:19:12;;;15557:30;10695:13:6;;;-1:-1:-1;10695:30:6;;15604:19:12;;10695:142:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;10847:111:6;;-1:-1:-1;10891:10:6;;-1:-1:-1;10911:21:6;;-1:-1:-1;10903:30:6;10880:68;;;16078:42:12;16066:55;;;10880:68:6;;;16048:74:12;16138:18;;16131:34;16213;16201:47;;16181:18;;;16174:75;10943:4:6;16265:18:12;;;16258:50;16020:19;;10880:68:6;;;;;;;;;;;;;10847:19;:111::i;:::-;10451:514;:::o;6574:1696::-;6658:13;;;;6657:14;6649:55;;;;-1:-1:-1;;;6649:55:6;;13974:2:12;6649:55:6;;;13956:21:12;14013:2;13993:18;;;13986:30;14052;14032:18;;;14025:58;14100:18;;6649:55:6;13772:352:12;6649:55:6;6782:10;6714:21;6773:20;;;:8;:20;;;;;6714:21;6803:856;6827:8;:15;6823:1;:19;6803:856;;;6863:15;6881:8;6890:1;6881:11;;;;;;;;:::i;:::-;;;;;;;6863:29;;6914:45;6930:6;:19;;6914:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6951:7;6914:15;:45::i;:::-;6906:84;;;;-1:-1:-1;;;6906:84:6;;16710:2:12;6906:84:6;;;16692:21:12;16749:2;16729:18;;;16722:30;16788:28;16768:18;;;16761:56;16834:18;;6906:84:6;16508:350:12;6906:84:6;7018:3;7008:7;:13;7004:34;;;7023:15;;;:::i;:::-;;;7004:34;7052:23;;:134;;;;;7114:4;7052:134;;;17326:34:12;7137:10:6;17376:18:12;;;17369:43;17428:18;;;17421:34;;;7052:23:6;;;;;:36;;17238:18:12;;7052:134:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;7201:51:6;;;;;;;;;;;;;;;;;;;:29;;-1:-1:-1;7201:51:6;-1:-1:-1;7233:6:6;;7201:51;;;7233:6;7201:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7266:13;7298:9;7293:120;7313:12;:19;7309:1;:23;7293:120;;;7380:7;7361:12;7374:1;7361:15;;;;;;;;:::i;:::-;;;;;;;:26;7357:41;;7397:1;7389:9;;7357:41;7334:3;;;;:::i;:::-;;;;7293:120;;;;7453:7;7430:12;7443:5;7430:19;;;;;;;;:::i;:::-;;;;;;;:30;7426:223;;7543:26;;7509:12;;7543:30;;7572:1;;7543:30;:::i;:::-;7509:82;;;;;;;;:::i;:::-;;;;;;;7480:6;:19;;7500:5;7480:26;;;;;;;;:::i;:::-;;;;;;;;;;:111;7609:25;;:6;;:25;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;7426:223;6849:810;;;6844:3;;;;;:::i;:::-;;;;6803:856;;;-1:-1:-1;7673:17:6;;7669:275;;7706:227;7775:10;7815:23;7743:176;;;18040:42:12;18028:55;;;7743:176:6;;;18010:74:12;18100:18;;18093:34;18143:18;;;18136:34;;;7896:5:6;18186:18:12;;;18179:50;17982:19;;7743:176:6;17785:450:12;7706:227:6;7993:1;7976:13;7958:8;:15;:31;;;;:::i;:::-;7957:37;7953:311;;;8010:243;8079:10;8119:21;8181:13;8163:8;:15;:31;;;;:::i;:::-;8047:192;;;18040:42:12;18028:55;;;8047:192:6;;;18010:74:12;18100:18;;18093:34;;;;18143:18;;;18136:34;8216:5:6;18186:18:12;;;18179:50;17982:19;;8047:192:6;17785:450:12;8010:243:6;6639:1631;;6574:1696;:::o;12931:199::-;13015:17;;;;13011:54;;13034:31;13052:12;13034:17;:31::i;:::-;13079:15;;;;13075:48;;13096:27;13112:10;13096:15;:27::i;:::-;12931:199;;:::o;14841:508::-;14909:13;;;;14908:14;14900:55;;;;-1:-1:-1;;;14900:55:6;;13974:2:12;14900:55:6;;;13956:21:12;14013:2;13993:18;;;13986:30;14052;14032:18;;;14025:58;14100:18;;14900:55:6;13772:352:12;14900:55:6;14995:10;14986:20;;;;:8;:20;;;;;:37;;;:42;14965:126;;;;-1:-1:-1;;;14965:126:6;;18442:2:12;14965:126:6;;;18424:21:12;18481:2;18461:18;;;18454:30;18520:34;18500:18;;;18493:62;18591:7;18571:18;;;18564:35;18616:19;;14965:126:6;18240:401:12;14965:126:6;15111:10;15102:20;;;;:8;:20;;;;;;;:37;;:47;;;15159:18;;:67;;;;;;;;17326:34:12;;;;15211:4:6;17376:18:12;;;17369:43;17428:18;;;17421:34;;;15102:20:6;15159:18;;:31;;17238:18:12;;15159:67:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;15237:105:6;;-1:-1:-1;15281:10:6;;-1:-1:-1;15301:20:6;;-1:-1:-1;15293:29:6;15270:62;;;18907:42:12;18895:55;;;15270:62:6;;;18877:74:12;18967:18;;18960:34;15324:1:6;19010:18:12;;;19003:45;;;19064:18;;;19057:50;18849:19;;15270:62:6;18646:467:12;9135:1220:6;9202:13;;;;9201:14;9193:55;;;;-1:-1:-1;;;9193:55:6;;13974:2:12;9193:55:6;;;13956:21:12;14013:2;13993:18;;;13986:30;14052;14032:18;;;14025:58;14100:18;;9193:55:6;13772:352:12;9193:55:6;9330:10;9258:13;9321:20;;;:8;:20;;;;;;;;;9359:45;;;;;;;;;;;;;;;;;9284:3;9274:13;;;9321:20;;9359:45;;;9321:20;;9359:45;;9321:20;9359:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9396:7;9359:15;:45::i;:::-;9351:84;;;;-1:-1:-1;;;9351:84:6;;16710:2:12;9351:84:6;;;16692:21:12;16749:2;16729:18;;;16722:30;16788:28;16768:18;;;16761:56;16834:18;;9351:84:6;16508:350:12;9351:84:6;9446:23;;:118;;;;;9504:4;9446:118;;;17326:34:12;9523:10:6;17376:18:12;;;17369:43;17428:18;;;17421:34;;;9446:23:6;;;;;:36;;17238:18:12;;9446:118:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;9575:51:6;;;;;;;;;;;;;;;;;;;:29;;-1:-1:-1;9575:51:6;-1:-1:-1;9607:6:6;;9575:51;;;9607:6;9575:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9636:13;9664:9;9659:112;9679:12;:19;9675:1;:23;9659:112;;;9742:7;9723:12;9736:1;9723:15;;;;;;;;:::i;:::-;;;;;;;:26;9719:41;;9759:1;9751:9;;9719:41;9700:3;;;;:::i;:::-;;;;9659:112;;;;9807:7;9784:12;9797:5;9784:19;;;;;;;;:::i;:::-;;;;;;;:30;9780:569;;9830:352;9899:10;9964:8;:114;;10057:21;9964:114;;;10003:23;9964:114;9931:169;;;;;;;;:::i;:::-;9867:301;;;18907:42:12;18895:55;;;9867:301:6;;;18877:74:12;18967:18;;18960:34;10122:1:6;19010:18:12;;;19003:45;10145:5:6;19064:18:12;;;19057:50;18849:19;;9867:301:6;18646:467:12;9830:352:6;10255:26;;10225:12;;10255:30;;10284:1;;10255:30;:::i;:::-;10225:74;;;;;;;;:::i;:::-;;;;;;;10196:6;:19;;10216:5;10196:26;;;;;;;;:::i;:::-;;;;;;;;;;:103;10313:25;;:6;;:25;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;9780:569;9183:1172;;;;9135:1220;:::o;11783:507::-;11850:13;;;;11849:14;11841:55;;;;-1:-1:-1;;;11841:55:6;;13974:2:12;11841:55:6;;;13956:21:12;14013:2;13993:18;;;13986:30;14052;14032:18;;;14025:58;14100:18;;11841:55:6;13772:352:12;11841:55:6;11914:6;:11;;11924:1;11914:11;11906:49;;;;-1:-1:-1;;;11906:49:6;;14331:2:12;11906:49:6;;;14313:21:12;14370:2;14350:18;;;14343:30;14409:27;14389:18;;;14382:55;14454:18;;11906:49:6;14129:349:12;11906:49:6;11974:10;11965:20;;;;:8;:20;;;;;:37;;:47;;12006:6;;11965:37;;;:47;;12006:6;;11965:47;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;12022:13;;:142;;;;;12066:10;12022:142;;;15294:34:12;12098:4:6;15344:18:12;;;15337:43;-1:-1:-1;15396:18:12;;;15389:34;15459:47;;;15439:18;;;15432:75;15544:3;15523:19;;;15516:32;-1:-1:-1;15564:19:12;;;15557:30;12022:13:6;;;-1:-1:-1;12022:30:6;;15604:19:12;;12022:142:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;12174:109:6;;-1:-1:-1;12218:10:6;;-1:-1:-1;12238:19:6;;-1:-1:-1;12230:28:6;;3878:533;4178:14;;;4012:20;4178:14;;;:8;:14;;;;;;;;4155:37;;;;;;;;;;;;;;;;;;;;;3975:23;;4012:20;;;;;;;;;4155:37;;4178:14;;4155:37;;4178:14;;4155:37;;;4178:14;4155:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;4155:37:6;;;-1:-1:-1;;4155:37:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4223:19;;4256:25;;;;4295:23;;;;4332:25;;;;4371:23;;;;;4223:19;;4256:25;;-1:-1:-1;4295:23:6;;-1:-1:-1;4332:25:6;;-1:-1:-1;4371:23:6;;-1:-1:-1;3878:533:6;-1:-1:-1;;;3878:533:6:o;4603:417::-;4798:13;;:17;4794:50;;4817:27;4837:6;4817:19;:27::i;:::-;4854:37;4866:12;4880:10;4854:11;:37::i;:::-;4905:17;;4901:54;;4924:31;4942:12;4924:17;:31::i;:::-;4969:15;;4965:48;;4986:27;5002:10;4986:15;:27::i;3476:296::-;3573:15;;;3531:7;3573:15;;;:8;:15;;;;;;;;3550:51;;;;;;;;;;;;;;;;;3531:7;;3550:51;;3573:15;3550:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3614:6;:13;3631:1;3614:18;3611:31;;-1:-1:-1;3641:1:6;;3476:296;-1:-1:-1;;3476:296:6:o;3611:31::-;3657:9;3652:96;3676:6;:13;3672:1;:17;3652:96;;;3724:3;3712:6;3719:1;3712:9;;;;;;;;:::i;:::-;;;;;;;:15;3709:28;;;-1:-1:-1;3736:1:6;;3476:296;-1:-1:-1;;;3476:296:6:o;3709:28::-;3691:3;;;;:::i;:::-;;;;3652:96;;;-1:-1:-1;3764:1:6;;3476:296;-1:-1:-1;;;3476:296:6:o;708:126:9:-;772:6;;;;758:10;:20;754:43;;787:10;;;;;;;;;;;;;;754:43;808:6;:19;;;;;;708:126::o;5421:1147:6:-;5503:13;;;;5502:14;5494:55;;;;-1:-1:-1;;;5494:55:6;;13974:2:12;5494:55:6;;;13956:21:12;14013:2;13993:18;;;13986:30;14052;14032:18;;;14025:58;14100:18;;5494:55:6;13772:352:12;5494:55:6;5627:10;5559:21;5618:20;;;:8;:20;;;;;5559:21;5648:312;5672:8;:15;5668:1;:19;5648:312;;;5726:3;5712:8;5721:1;5712:11;;;;;;;;:::i;:::-;;;;;;;:17;5708:38;;;5731:15;;;:::i;:::-;;;5708:38;5760:6;:19;;5785:8;5794:1;5785:11;;;;;;;;:::i;:::-;;;;;;;;;;;;5760:37;;;;;;;-1:-1:-1;5760:37:6;;;;;;;;;5811:23;;5924:11;;5811:23;;;;;:36;;5865:10;;5901:4;;5924:8;;5933:1;;5924:11;;;;;;:::i;:::-;;;;;;;;;;;5811:138;;;;;;;;;;17275:42:12;17344:15;;;5811:138:6;;;17326:34:12;17396:15;;;;17376:18;;;17369:43;17428:18;;;17421:34;17238:18;;5811:138:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5689:3;;;;;:::i;:::-;;;;5648:312;;;-1:-1:-1;5973:17:6;;5969:274;;6006:226;6075:10;6115:23;6043:175;;;18040:42:12;18028:55;;;6043:175:6;;;18010:74:12;18100:18;;18093:34;18143:18;;;18136:34;;;6196:4:6;18186:18:12;;;18179:50;17982:19;;6043:175:6;17785:450:12;6006:226:6;6292:1;6275:13;6257:8;:15;:31;;;;:::i;:::-;6256:37;6252:310;;;6309:242;6378:10;6418:21;6480:13;6462:8;:15;:31;;;;:::i;:::-;6346:191;;;18040:42:12;18028:55;;;6346:191:6;;;18010:74:12;18100:18;;18093:34;;;;18143:18;;;18136:34;6515:4:6;18186:18:12;;;18179:50;17982:19;;6346:191:6;17785:450:12;12413:512:6;12482:13;;;;12481:14;12473:55;;;;-1:-1:-1;;;12473:55:6;;13974:2:12;12473:55:6;;;13956:21:12;14013:2;13993:18;;;13986:30;14052;14032:18;;;14025:58;14100:18;;12473:55:6;13772:352:12;12473:55:6;12546:6;:11;;12556:1;12546:11;12538:51;;;;-1:-1:-1;;;12538:51:6;;20024:2:12;12538:51:6;;;20006:21:12;20063:2;20043:18;;;20036:30;20102:29;20082:18;;;20075:57;20149:18;;12538:51:6;19822:351:12;12538:51:6;12608:10;12599:20;;;;:8;:20;;;;;:37;;:47;;12640:6;;12599:37;;;:47;;12640:6;;12599:47;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;12656:13;;:142;;;;;12708:4;12656:142;;;15294:34:12;12727:10:6;15344:18:12;;;15337:43;-1:-1:-1;15396:18:12;;;15389:34;15459:47;;;15439:18;;;15432:75;15544:3;15523:19;;;15516:32;-1:-1:-1;15564:19:12;;;15557:30;12656:13:6;;;-1:-1:-1;12656:30:6;;15604:19:12;;12656:142:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;12808:110:6;;-1:-1:-1;12852:10:6;;-1:-1:-1;12872:19:6;;-1:-1:-1;12864:28:6;12841:67;;;16078:42:12;16066:55;;;12841:67:6;;;16048:74:12;16138:18;;16131:34;16213;16201:47;;16181:18;;;16174:75;12902:5:6;16265:18:12;;;16258:50;16020:19;;12841:67:6;15823:491:12;5026:389:6;5217:13;;:17;5213:52;;5236:29;5258:6;5236:21;:29::i;:::-;5275:39;5289:12;5303:10;5275:13;:39::i;:::-;5328:12;5324:39;;;5342:21;:19;:21::i;:::-;5377:10;5373:35;;;5389:19;:17;:19::i;2693:430::-;372:6:9;;:20;:6;382:10;372:20;364:29;;;;;;2900:23:6::1;:58:::0;;::::1;::::0;;::::1;::::0;;;::::1;;::::0;;;2968:18:::1;:48:::0;;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;3026:13:::1;:39:::0;;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;3075:14:::1;:41:::0;;;;;::::1;::::0;::::1;;::::0;;2693:430::o;14126:609::-;14183:13;;;;14182:14;14174:55;;;;-1:-1:-1;;;14174:55:6;;13974:2:12;14174:55:6;;;13956:21:12;14013:2;13993:18;;;13986:30;14052;14032:18;;;14025:58;14100:18;;14174:55:6;13772:352:12;14174:55:6;14269:10;14260:20;;;;:8;:20;;;;;:39;;;:44;;14239:130;;;;-1:-1:-1;;;14239:130:6;;20631:2:12;14239:130:6;;;20613:21:12;20670:2;20650:18;;;20643:30;20709:34;20689:18;;;20682:62;20780:9;20760:18;;;20753:37;20807:19;;14239:130:6;20429:403:12;14239:130:6;14380:14;;14452:10;14380:14;14476:20;;;:8;:20;;;;;;14380:14;14476:39;;;;14380:176;;;;;14433:4;14380:176;;;21201:34:12;21251:18;;;21244:43;;;;21303:18;;;21296:34;;;;21346:18;;;21339:34;21410:3;21389:19;;;21382:32;21430:19;;;21423:30;14380:14:6;;;;;:31;;21470:19:12;;14380:176:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;14575:10:6;14608:1;14566:20;;;:8;:20;;;;;:39;;:43;14620:108;;-1:-1:-1;14575:10:6;-1:-1:-1;14684:22:6;14676:31;;14620:108;14126:609::o;1841:198:5:-;1916:13;;:29;:13;:29;1908:84;;;;-1:-1:-1;;;1908:84:5;;21702:2:12;1908:84:5;;;21684:21:12;21741:2;21721:18;;;21714:30;21780:34;21760:18;;;21753:62;21851:12;21831:18;;;21824:40;21881:19;;1908:84:5;21500:406:12;1908:84:5;2002:13;:30;;;;;;;;;;;;;;;1841:198::o;13136:205:6:-;13222:17;;;;13218:56;;13241:33;13261:12;13241:19;:33::i;:::-;13288:15;;;;13284:50;;13305:29;13323:10;13305:17;:29::i;8375:651::-;8440:13;;;;8439:14;8431:55;;;;-1:-1:-1;;;8431:55:6;;13974:2:12;8431:55:6;;;13956:21:12;14013:2;13993:18;;;13986:30;14052;14032:18;;;14025:58;14100:18;;8431:55:6;13772:352:12;8431:55:6;8568:10;8496:13;8559:20;;;:8;:20;;;;;;;;8589:33;;;;;;;;;;;;;;;;;;;;8632:23;;:118;;;;;;;;17326:34:12;;;;8714:4:6;17376:18:12;;;17369:43;17428:18;;;17421:34;;;8522:3:6;8512:13;;;8559:20;8632:23;;;;:36;;17238:18:12;;8632:118:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8760:259;8821:10;8878:8;:58;;8915:21;8878:58;;;8889:23;8878:58;8849:105;;;;;;;;:::i;15396:565::-;15451:13;;;;15450:14;15442:55;;;;-1:-1:-1;;;15442:55:6;;13974:2:12;15442:55:6;;;13956:21:12;14013:2;13993:18;;;13986:30;14052;14032:18;;;14025:58;14100:18;;15442:55:6;13772:352:12;15442:55:6;15537:10;15528:20;;;;:8;:20;;;;;:37;;;:42;;15507:125;;;;-1:-1:-1;;;15507:125:6;;22113:2:12;15507:125:6;;;22095:21:12;22152:2;22132:18;;;22125:30;22191:34;22171:18;;;22164:62;22262:6;22242:18;;;22235:34;22286:19;;15507:125:6;21911:400:12;15507:125:6;15643:18;;15715:10;15643:18;15739:20;;;:8;:20;;;;;;;:37;;;15643:143;;;;;15696:4;15643:143;;;17326:34:12;17376:18;;;17369:43;;;;17428:18;;;17421:34;15643:18:6;;;;;:31;;17238:18:12;;15643:143:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;15805:10:6;15836:1;15796:20;;;:8;:20;;;;;:37;;:41;15848:106;;-1:-1:-1;15805:10:6;-1:-1:-1;15912:20:6;15904:29;;11065:597;11136:13;;;;11135:14;11127:55;;;;-1:-1:-1;;;11127:55:6;;13974:2:12;11127:55:6;;;13956:21:12;14013:2;13993:18;;;13986:30;14052;14032:18;;;14025:58;14100:18;;11127:55:6;13772:352:12;11127:55:6;11200:6;:11;;11210:1;11200:11;11192:51;;;;-1:-1:-1;;;11192:51:6;;20024:2:12;11192:51:6;;;20006:21:12;20063:2;20043:18;;;20036:30;20102:29;20082:18;;;20075:57;20149:18;;11192:51:6;19822:351:12;11192:51:6;11263:10;11254:20;;;;:8;:20;;;;;:39;;:49;;11297:6;;11254:20;:49;;11297:6;;11254:49;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;11313:13;;:142;;;;;11365:4;11313:142;;;15294:34:12;11384:10:6;15344:18:12;;;15337:43;11408:1:6;15396:18:12;;;15389:34;15459:47;;;15439:18;;;15432:75;15544:3;15523:19;;;15516:32;-1:-1:-1;15564:19:12;;;15557:30;11313:13:6;;;-1:-1:-1;11313:30:6;;15604:19:12;;11313:142:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;11465:190:6;;-1:-1:-1;11526:10:6;;-1:-1:-1;11562:21:6;;-1:-1:-1;11554:30:6;;558:144:9;641:6;;;;627:10;:20;623:43;;656:10;;;;;;;;;;;;;;623:43;677:6;:18;;;;;;;;;;;;;;;558:144::o;13480:596:6:-;13550:13;;;;13549:14;13541:55;;;;-1:-1:-1;;;13541:55:6;;13974:2:12;13541:55:6;;;13956:21:12;14013:2;13993:18;;;13986:30;14052;14032:18;;;14025:58;14100:18;;13541:55:6;13772:352:12;13541:55:6;13636:10;13627:20;;;;:8;:20;;;;;:39;;;:44;13606:131;;;;-1:-1:-1;;;13606:131:6;;22518:2:12;13606:131:6;;;22500:21:12;22557:2;22537:18;;;22530:30;22596:34;22576:18;;;22569:62;22667:10;22647:18;;;22640:38;22695:19;;13606:131:6;22316:404:12;13606:131:6;13757:10;13748:20;;;;:8;:20;;;;;;:39;;;;:49;;;13807:14;;:144;;;;;;;;21201:34:12;;;;13884:4:6;21251:18:12;;;21244:43;21303:18;;;21296:34;;;21346:18;;;21339:34;21410:3;21389:19;;;21382:32;21430:19;;;21423:30;;;;13748:20:6;13807:14;;:31;;21470:19:12;;13807:144:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;13962:107:6;;-1:-1:-1;14006:10:6;;-1:-1:-1;14026:22:6;;-1:-1:-1;14018:31:6;;6492:183:5;6565:20;6588:37;6615:9;6588:26;:37::i;2334:126::-;2404:6;;2430:13;;2404:49;;;;;:6;;;;;:25;;:49;;2430:13;;;2445:7;;2404:49;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16100:233:6;16181:4;;16197:108;16221:8;:15;16217:1;:19;16197:108;;;16274:7;16259:8;16268:1;16259:11;;;;;;;;:::i;:::-;;;;;;;:22;16256:38;;16290:4;16283:11;;;;;16256:38;16238:3;;;;:::i;:::-;;;;16197:108;;;;16321:5;16314:12;;16100:233;;;;;:::o;2466:2358:5:-;2544:12;2568:44;2615:25;:9;:23;:25::i;:::-;2568:72;;2651:28;2682:30;:7;:28;:30::i;:::-;2651:61;;2722:19;2744:24;:7;:22;:24::i;:::-;2722:46;;2927:16;3003:11;3295:52;3331:15;3295:35;:52::i;:::-;3365:28;:7;:26;:28::i;:::-;2969:438;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;2946:471;;2969:438;2946:471;;;;3435:24;;;;:14;:24;;;;;;2946:471;;-1:-1:-1;3435:24:5;;:33;3427:82;;;;-1:-1:-1;;;3427:82:5;;24191:2:12;3427:82:5;;;24173:21:12;24230:2;24210:18;;;24203:30;24269:34;24249:18;;;24242:62;24340:6;24320:18;;;24313:34;24364:19;;3427:82:5;23989:400:12;3427:82:5;3519:24;;;;:14;:24;;;;;:31;;;;3546:4;3519:31;;;3604:20;:7;:18;:20::i;:::-;3561:63;;3634:32;3669:16;:7;:14;:16::i;:::-;3634:51;;3751:16;:3;:14;:16::i;:::-;3734:13;;:33;:13;;;:33;;;3726:83;;;;-1:-1:-1;;;3726:83:5;;24596:2:12;3726:83:5;;;24578:21:12;24635:2;24615:18;;;24608:30;24674:34;24654:18;;;24647:62;24745:7;24725:18;;;24718:35;24770:19;;3726:83:5;24394:401:12;3726:83:5;3820:19;3842:24;:7;:22;:24::i;:::-;3820:46;;3933:102;3960:17;:7;4045:11:3;;;;3950:113;3960:17:5;3979:15;3996:25;:7;:23;:25::i;:::-;4023:11;3933:26;:102::i;:::-;3912:184;;;;-1:-1:-1;;;3912:184:5;;25002:2:12;3912:184:5;;;24984:21:12;25041:2;25021:18;;;25014:30;25080:34;25060:18;;;25053:62;25151:5;25131:18;;;25124:33;25174:19;;3912:184:5;24800:399:12;3912:184:5;4146:238;4193:11;4218:22;:7;:20;:22::i;:::-;4254:19;:7;:17;:19::i;:::-;4287:11;4312:25;:7;:23;:25::i;:::-;4351:23;:7;:21;:23::i;:::-;4146:33;:238::i;:::-;;4395:41;4439:15;:3;:13;:15::i;:::-;4395:59;-1:-1:-1;1215:66:5;4494:27;:18;4395:59;4526:22;4494:15;:18::i;:::-;:25;:27::i;:::-;4486:62;4465:163;;;;-1:-1:-1;;;4465:163:5;;25406:2:12;4465:163:5;;;25388:21:12;25445:2;25425:18;;;25418:30;25484:33;25464:18;;;25457:61;25535:18;;4465:163:5;25204:355:12;4465:163:5;4672:20;4706:13;:3;:11;:13::i;:::-;4695:34;;;;;;;;;;;;:::i;:::-;4672:57;2466:2358;-1:-1:-1;;;;;;;;;;;2466:2358:5:o;1373:210:3:-;-1:-1:-1;;;;;;;;;;;;1468:38:3;1509:25;:16;:4;-1:-1:-1;;;;;;;;;;;;;;;;;1650:28:10;;;;;;;;1658:11;;1650:28;;1608:15;;;1650:28;;;;;;;;1464:221;1509:16:3;:23;:25::i;:::-;1552:24;;;;;;;;;;;;;1373:210;-1:-1:-1;;;1373:210:3:o;3492:144::-;3573:12;3604:25;:7;:12;;;3617:1;3604:15;;;;;;;;:::i;:::-;;;;;;;:23;:25::i;1871:132::-;1946:7;1972:24;:7;:12;;;1985:1;1972:15;;;;;;;;:::i;:::-;;;;;;;:22;:24::i;3875:775:8:-;3963:25;;;;;;;;;:20;:25;;4002:8;;3939:12;;3963:25;4002:12;3998:622;;4030:12;4056:14;4079:26;4100:1;4103;4079:20;:26::i;:::-;4073:33;;;-1:-1:-1;4136:1:8;4124:13;;;:30;;;4141:8;:13;;4153:1;4141:13;4124:30;4120:341;;;4209:1;4194;:8;4205:1;4194:12;;;;:::i;:::-;:16;;;;:::i;:::-;4184:27;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4184:27:8;;4174:37;;4229:16;4248:26;4269:1;4272;4248:20;:26::i;:::-;4229:45;;4305:9;4292:7;4300:1;4292:10;;;;;;;;:::i;:::-;;;;:22;;;;;;;;;;;4341:1;4332:10;;4156:201;4120:341;;;4416:1;4401;:8;4412:1;4401:12;;;;:::i;:::-;:16;;;;:::i;:::-;4391:27;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4391:27:8;;4381:37;;4445:1;4436:10;;4120:341;4480:18;;;4475:135;4504:7;:14;4500:1;:18;4475:135;;;4556:39;4577:10;;;;:1;:10;:::i;:::-;:14;;4590:1;4577:14;:::i;:::-;4593:1;4556:20;:39::i;:::-;4543:7;4551:1;4543:10;;;;;;;;:::i;:::-;;;;:52;;;;;;;;;;-1:-1:-1;4520:3:8;;;;:::i;:::-;;;;4475:135;;;;4016:604;;4636:7;3875:775;-1:-1:-1;;3875:775:8:o;3785:136:3:-;3864:7;3890:24;:7;:12;;;3903:1;3890:15;;;;;;;;:::i;2434:907::-;2505:22;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;2505:22:3;2553:25;:7;:12;;;2566:1;2553:15;;;;;;;;:::i;:25::-;2539:11;;;;:39;;;-1:-1:-1;;;;;;;;;;;;;;;;1650:28:10;;;;;;;;1658:11;;1650:28;;1608:15;;;1650:28;;;;2665:20:3;1650:28:10;2665:18:3;:20::i;:::-;2661:593;;;2741:20;:11;:18;:20::i;:::-;2726:35;;2661:593;;;2872:11;;;;2929:17;;2846:23;;2929:21;;2949:1;;2929:21;:::i;:::-;2919:32;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2919:32:3;;2897:54;;2965:14;2993:15;3067:10;3063:2;3059:19;3049:29;;3116:6;3110:4;3106:17;3095:28;;3151:36;3156:6;3164:7;3173:6;:13;3151:4;:36::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;1650:28:10;;;;;;;;1658:11;;1650:28;;1608:15;;;1650:28;;;;3216:27:3;;1509:23;:25::i;3216:27::-;3201:42;;-1:-1:-1;;;;2661:593:3;3283:27;3302:7;3283:18;:27::i;:::-;3264:16;;;:46;-1:-1:-1;3264:7:3;2434:907;-1:-1:-1;2434:907:3:o;4069:216::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4154:32:3;4189:24;:7;:12;;;4202:1;4189:15;;;;;;;;:::i;:::-;;;;;;;:22;:24::i;:::-;4214:7;:16;;;4189:42;;;;;;;;:::i;:::-;;;;;;;4154:77;;4248:30;;;;;;;;4252:7;4248:30;;;;4261:16;:7;:14;:16::i;:::-;4248:30;;4241:37;4069:216;-1:-1:-1;;;4069:216:3:o;4310:124::-;4369:7;4395:32;4415:3;:8;;;4424:1;4415:11;;;;;;;;:::i;:::-;;;;;;;4395:19;:32::i;2287:141::-;2362:7;2396:24;:7;:12;;;2409:1;2396:15;;;;;;;;:::i;3347:139::-;3423:12;3454:25;:7;:12;;;3467:1;3454:15;;;;;;;;:::i;473:2402:8:-;639:4;655:29;687:35;707:14;-1:-1:-1;;;;;;;;;;;;;;;;;1650:28:10;;;;;;;;1658:11;;1650:28;;1608:15;;;1650:28;;;;;;;;1464:221;687:35:8;655:67;;732:38;773:22;790:4;773:16;:22::i;:::-;732:63;-1:-1:-1;806:24:8;;911:4;893:15;;975:28;991:11;975:15;:28::i;:::-;955:48;;1017:4;:11;1032:1;1017:16;1013:59;;1056:5;1049:12;;;;;;;;;;;1013:59;1087:9;1082:1787;1106:11;:18;1102:1;:22;1082:1787;;;1159:4;:11;1149:7;:21;1145:72;;;1197:5;1190:12;;;;;;;;;;;;1145:72;1245:36;1266:11;1278:1;1266:14;;;;;;;;:::i;:::-;;;;;;;1245:20;:36::i;:::-;1231:50;;1320:11;1310:22;;;;;;1299:7;:33;1295:84;;1359:5;1352:12;;;;;;;;;;;;1295:84;1410:32;1427:11;1439:1;1427:14;;;;;;;;:::i;1410:32::-;1392:50;;1461:15;:22;1487:2;1461:28;1457:1402;;1524:4;:11;1513:7;:22;1509:270;;1626:5;1616:16;;;;;;1573:38;1591:15;1607:2;1591:19;;;;;;;;:::i;1573:38::-;1563:49;;;;;;:69;1559:202;;1667:4;1660:11;;;;;;;;;;;;1559:202;1733:5;1726:12;;;;;;;;;;;;1559:202;1797:20;1826:4;1831:7;1826:13;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;1879:2:8;1862:19;;1858:78;;;1912:5;1905:12;;;;;;;;;;;;;1858:78;1971:55;1994:15;2010:14;1994:31;;;;;;;;;;:::i;:::-;;;;;;;1971:22;:55::i;:::-;1963:64;-1:-1:-1;2045:12:8;2056:1;2045:12;;:::i;:::-;;;1491:581;1457:1402;;;2082:15;:22;2108:1;2082:27;2078:781;;2129:17;2149:72;2168:37;2186:15;2202:1;2186:18;;;;;;;;:::i;2168:37::-;2207:4;2213:7;2149:18;:72::i;:::-;2266:11;;2129:92;;-1:-1:-1;2243:19:8;2129:92;2243:7;:19;:::i;:::-;:34;2239:313;;2399:5;2389:16;;;;;;2347:37;2365:15;2381:1;2365:18;;;;;;;;:::i;2347:37::-;2337:48;;;;;;:68;2333:201;;2440:4;2433:11;;;;;;;;;;;;;2333:201;2506:5;2499:12;;;;;;;;;;;;;2333:201;2607:9;2620:1;2607:14;2603:73;;2652:5;2645:12;;;;;;;;;;;;;2603:73;2694:20;2705:9;2694:20;;:::i;:::-;;;2750:42;2773:15;2789:1;2773:18;;;;;;;;:::i;2750:42::-;2742:51;-1:-1:-1;2078:781:8;;-1:-1:-1;2078:781:8;;1126:3;;;;:::i;:::-;;;;1082:1787;;;;645:2230;;;;;;;473:2402;;;;;;;:::o;2009:130:3:-;2082:7;2108:24;:7;:12;;;2121:1;2108:15;;;;;;;;:::i;2145:136::-;2215:7;2249:24;:7;:12;;;2262:1;2249:15;;;;;;;;:::i;1589:133::-;1665:7;1691:24;:7;:12;;;1704:1;1691:15;;;;;;;;:::i;1728:137::-;1802:12;1833:25;:7;:12;;;1846:1;1833:15;;;;;;;;:::i;4830:691:5:-;5158:17;;:44;;;;;;;;689:25:12;;;5073:7:5;;;;;;;;5158:17;;;;;:30;;662:18:12;;5158:44:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5092:110;;;;;;;;5234:200;5354:10;5340:11;:24;;;;:::i;:::-;5244:61;;;;;;;27284:19:12;;;27319:12;;;27312:28;;;27356:12;;;27349:28;;;27393:12;;;;27386:28;;;5244:61:5;;;;;;;;;;27430:13:12;;;;5244:61:5;;;5234:72;;;;;;5382:10;5410;5234:88;:200::i;:::-;5213:275;;;;-1:-1:-1;;;5213:275:5;;27656:2:12;5213:275:5;;;27638:21:12;27695:2;27675:18;;;27668:30;27734;27714:18;;;27707:58;27782:18;;5213:275:5;27454:352:12;5213:275:5;5505:9;4830:691;-1:-1:-1;;;;;;;;;4830:691:5:o;4440:131:3:-;-1:-1:-1;;;;;;;;;;;;4533:31:3;;;;;;;;4543:20;:3;:8;;;4552:1;4543:11;;;;;;;;:::i;:20::-;4533:31;;4526:38;4440:131;-1:-1:-1;;4440:131:3:o;4847:149::-;-1:-1:-1;;;;;;;;;;;;;;;;;4971:11:3;;:18;;4983:5;;4971:18;;;;;;:::i;:::-;;;;;;;4964:25;;4847:149;;;;:::o;5560:546:10:-;5647:8;;5620:7;;5647:12;;;;:30;;-1:-1:-1;5663:8:10;;5675:2;-1:-1:-1;5663:14:10;5647:30;5639:39;;;;;;5689:14;5706:27;5721:4;:11;;;5706:14;:27::i;:::-;5689:44;;5743:11;5768:6;5757:4;:8;;;:17;;;;:::i;:::-;5743:31;;5785:14;5809;5840:6;5826:4;:11;;;:20;;;;:::i;:::-;5809:37;;5895:6;5889:13;5879:23;;5985:2;5980:3;5977:11;5974:92;;;6046:3;6042:2;6038:12;6033:3;6029:22;6021:6;6017:35;6007:45;;5974:92;-1:-1:-1;6093:6:10;5560:546;-1:-1:-1;;;;5560:546:10:o;4577:115:3:-;4633:12;4664:21;:3;:8;;;4673:1;4664:11;;;;;;;;:::i;2483:519:10:-;2543:16;2579:12;2586:4;2579:6;:12::i;:::-;2571:21;;;;;;2603:13;2619:14;2628:4;2619:8;:14::i;:::-;2603:30;;2643:23;2683:5;2669:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;2669:20:10;;;;;;;;;;;;;;;;2643:46;;2700:14;2731:27;2746:4;:11;;;2731:14;:27::i;:::-;2717:4;:11;;;:41;;;;:::i;:::-;2700:58;-1:-1:-1;2768:15:10;;2793:179;2817:5;2813:1;:9;2793:179;;;2853:19;2865:6;2853:11;:19::i;:::-;2843:29;;2898:24;;;;;;;;2906:7;2898:24;;;;2915:6;2898:24;;;2886:6;2893:1;2886:9;;;;;;;;:::i;:::-;;;;;;;;;;:36;2945:16;2954:7;2945:6;:16;:::i;:::-;2936:25;-1:-1:-1;2824:3:10;;;;:::i;:::-;;;;2793:179;;;-1:-1:-1;2989:6:10;;2483:519;-1:-1:-1;;;;;2483:519:10:o;6447:440::-;6540:8;;6508:12;;6532:21;;;;;;6564:14;6581:27;6596:4;:11;;;6581:14;:27::i;:::-;6564:44;;6618:11;6643:6;6632:4;:8;;;:17;;;;:::i;:::-;6618:31;;6674:19;6706:3;6696:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;6696:14:10;;6674:36;;6721:15;6790:6;6784:4;6780:17;6769:28;;6817:40;6836:6;6822:4;:11;;;:20;;;;:::i;:::-;6844:7;6853:3;6817:4;:40::i;4656:185:8:-;4737:6;4769:5;4773:1;4769;:5;:::i;:::-;:10;:64;;4829:4;4815:3;4819:5;4823:1;4819;:5;:::i;:::-;4815:10;;;;;;;;:::i;:::-;;;;;4809:24;;;4815:10;;4809:24;:::i;:::-;4769:64;;;4802:4;4788:3;4792:5;4796:1;4792;:5;:::i;:::-;4788:10;;;;;;;;:::i;:::-;;;;;4782:24;;;4788:10;;4782:24;:::i;:::-;4762:72;;;4656:185;-1:-1:-1;;;4656:185:8:o;3106:321:10:-;3186:8;;3166:4;;3186:13;;3182:31;;-1:-1:-1;3208:5:10;;3106:321;-1:-1:-1;3106:321:10:o;3182:31::-;3262:11;;;;3323:13;;3224:11;3315:22;;279:4;3361:24;;3357:42;;;-1:-1:-1;3394:5:10;;3106:321;-1:-1:-1;;;3106:321:10:o;3357:42::-;-1:-1:-1;3416:4:10;;3106:321;-1:-1:-1;;;3106:321:10:o;630:737:3:-;741:3;748:1;741:8;737:21;;630:737;;;:::o;737:21::-;203:2;822:16;;815:194;;912:10;;899:24;;951:16;203:2;918:3;951:16;:::i;:::-;;-1:-1:-1;981:17:3;203:2;981:17;;:::i;:::-;;-1:-1:-1;840:16:3;203:2;840:16;;:::i;:::-;;;815:194;;;1099:12;1139:1;1120:15;1132:3;203:2;1120:15;:::i;:::-;1114:22;;:3;:22;:::i;:::-;:26;;;;:::i;:::-;1192:10;;1263:11;;1259:22;;1204:9;;1188:26;1329:21;;;;1316:35;;;-1:-1:-1;;630:737:3:o;5354:200:10:-;5484:8;;5417:7;;5496:2;5484:14;5476:23;;;;;;5533:12;5540:4;5533:6;:12::i;4673:337::-;4737:12;4761:19;4793:4;:8;;;4783:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4783:19:10;;4761:41;;4816:6;:13;4833:1;4816:18;4812:37;;4843:6;4673:337;-1:-1:-1;;4673:337:10:o;4812:37::-;4860:11;4921:6;4915:4;4911:17;4904:24;;4948:32;4953:4;:11;;;4966:3;4971:4;:8;;;4948:4;:32::i;:::-;-1:-1:-1;4997:6:10;4673:337;-1:-1:-1;;4673:337:10:o;6143:298::-;6263:8;;6209:7;;6275:2;6263:14;6255:23;;;;;;6289:14;6313;6330:4;:11;;;6344:1;6330:15;;;;:::i;:::-;6388:13;;6143:298;-1:-1:-1;;;;6143:298:10:o;2881:954:8:-;3030:7;;;3286:35;3302:18;3286:15;:35::i;:::-;3259:62;;3331:23;3367:11;:18;3357:29;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3357:29:8;-1:-1:-1;3331:55:8;-1:-1:-1;3509:7:8;3492:167;3532:18;;3522:28;;:7;:28;:::i;:::-;3518:1;:32;3492:167;;;3571:17;3591:4;3596:1;3591:7;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;3591:7:8;3612:10;3623:11;3627:7;3623:1;:11;:::i;:::-;3612:23;;;;;;;;:::i;:::-;;;;:36;;;;;;;;;;;3557:102;3552:3;;;;;:::i;:::-;;;;3492:167;;;;3709:10;3699:21;;;;;;3683:11;3673:22;;;;;;:47;3669:140;;3742:11;:18;3736:24;;3669:140;;;3797:1;3791:7;;3669:140;-1:-1:-1;3825:3:8;;2881:954;-1:-1:-1;;;;;2881:954:8:o;78:1018:7:-;231:4;270:2;255:5;:12;:17;;;;:::i;:::-;:22;247:55;;;;-1:-1:-1;;;247:55:7;;30270:2:12;247:55:7;;;30252:21:12;30309:2;30289:18;;;30282:30;30348:22;30328:18;;;30321:50;30388:18;;247:55:7;30068:344:12;247:55:7;312:19;349:2;334:5;:12;:17;;;;:::i;:::-;312:39;-1:-1:-1;503:14:7;312:39;503:1;:14;:::i;:::-;495:5;:22;487:56;;;;-1:-1:-1;;;487:56:7;;30619:2:12;487:56:7;;;30601:21:12;30658:2;30638:18;;;30631:30;30697:23;30677:18;;;30670:51;30738:18;;487:56:7;30417:345:12;487:56:7;554:20;607:4;638:2;621:428;647:5;:12;642:1;:17;621:428;;733:13;;;727:20;;-1:-1:-1;779:9:7;787:1;779:5;:9;:::i;:::-;792:1;779:14;775:232;;838:44;;;;;;30924:19:12;;;30959:12;;;30952:28;;;30996:12;;838:44:7;;;;;;;;;;;;828:55;;;;;;813:70;;775:232;;;947:44;;;;;;30924:19:12;;;30959:12;;;30952:28;;;30996:12;;947:44:7;;;;;;;;;;;;937:55;;;;;;922:70;;775:232;1029:9;1037:1;1029:5;:9;:::i;:::-;1021:17;-1:-1:-1;661:7:7;666:2;661:7;;:::i;:::-;;;621:428;;;-1:-1:-1;1065:24:7;;;;78:1018;-1:-1:-1;;;;;;78:1018:7:o;8750:521:10:-;8894:13;;8812:7;;8886:22;;190:4;8932:26;;8928:336;;;-1:-1:-1;8967:1:10;;8750:521;-1:-1:-1;;8750:521:10:o;8928:336::-;235:4;8987:25;;;:83;;-1:-1:-1;279:4:10;9017:25;;;;;:52;;-1:-1:-1;322:4:10;9046:23;;9017:52;8983:281;;;-1:-1:-1;9079:1:10;;8750:521;-1:-1:-1;;8750:521:10:o;8983:281::-;279:4;9099:24;;9095:169;;;9183:21;9203:1;235:4;9183:21;:::i;:::-;9174:31;;;;:5;:31;:::i;:::-;:35;;9208:1;9174:35;:::i;:::-;9167:42;8750:521;-1:-1:-1;;;8750:521:10:o;9095:169::-;9240:19;9258:1;322:4;9240:19;:::i;6995:424::-;7079:8;;7056:7;;7079:13;;7075:27;;-1:-1:-1;7101:1:10;;6995:424;-1:-1:-1;6995:424:10:o;7075:27::-;7113:13;7140:15;7172:27;7187:4;:11;;;7172:14;:27::i;:::-;7158:4;:11;;;:41;;;;:::i;:::-;7140:59;;7209:14;7240:4;:8;;;7226:4;:11;;;:22;;;;:::i;:::-;7209:39;;7258:132;7275:6;7265:7;:16;7258:132;;;7317:20;7329:7;7317:11;:20::i;:::-;7307:30;;:7;:30;:::i;:::-;7297:40;-1:-1:-1;7372:7:10;;;;:::i;:::-;;;;7258:132;;;-1:-1:-1;7407:5:10;;6995:424;-1:-1:-1;;;6995:424:10:o;7468:1230::-;7634:13;;7527:7;;;;7626:22;;190:4;7672:26;;7668:999;;;7710:1;7700:11;;7668:999;;;235:4;7730:25;;7726:941;;;7767:26;190:4;7767:5;:26;:::i;:::-;:30;;7796:1;7767:30;:::i;:::-;7757:40;;7726:941;;;279:4;7816:24;;7812:855;;;7909:4;7902:5;7898:16;7988:1;7980:6;7976:14;7966:24;;8126:7;8122:2;8118:16;8113:3;8109:26;8100:6;8094:13;8090:46;8223:1;8214:7;8210:15;8201:7;8197:29;8186:40;;;;7812:855;;;322:4;8260:23;;8256:411;;;8309:24;279:4;8309:5;:24;:::i;8256:411::-;8465:1;8453:14;;;;8504:13;8532:2;8528:16;;;8421:4;8528:16;8523:3;8519:26;8500:46;;8614:29;;;8627:15;8614:29;;8684:7;-1:-1:-1;;7468:1230:10:o;9429:769::-;9540:3;9547:1;9540:8;9536:21;;9429:769;;;:::o;9536:21::-;359:2;9621:16;;9614:194;;9711:10;;9698:24;;9750:16;359:2;9717:3;9750:16;:::i;:::-;;-1:-1:-1;9780:17:10;359:2;9780:17;;:::i;:::-;;-1:-1:-1;9639:16:10;359:2;9639:16;;:::i;:::-;;;9614:194;;;9822:3;9829:1;9822:8;9818:21;;9429:769;;;:::o;14:332:12:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;180:9;167:23;230:66;223:5;219:78;212:5;209:89;199:117;;312:1;309;302:12;971:154;1057:42;1050:5;1046:54;1039:5;1036:65;1026:93;;1115:1;1112;1105:12;1130:347;1181:8;1191:6;1245:3;1238:4;1230:6;1226:17;1222:27;1212:55;;1263:1;1260;1253:12;1212:55;-1:-1:-1;1286:20:12;;1329:18;1318:30;;1315:50;;;1361:1;1358;1351:12;1315:50;1398:4;1390:6;1386:17;1374:29;;1450:3;1443:4;1434:6;1426;1422:19;1418:30;1415:39;1412:59;;;1467:1;1464;1457:12;1412:59;1130:347;;;;;:::o;1482:754::-;1579:6;1587;1595;1603;1611;1664:3;1652:9;1643:7;1639:23;1635:33;1632:53;;;1681:1;1678;1671:12;1632:53;1720:9;1707:23;1739:31;1764:5;1739:31;:::i;:::-;1789:5;-1:-1:-1;1846:2:12;1831:18;;1818:32;1859:33;1818:32;1859:33;:::i;:::-;1911:7;-1:-1:-1;1965:2:12;1950:18;;1937:32;;-1:-1:-1;2020:2:12;2005:18;;1992:32;2047:18;2036:30;;2033:50;;;2079:1;2076;2069:12;2033:50;2118:58;2168:7;2159:6;2148:9;2144:22;2118:58;:::i;:::-;1482:754;;;;-1:-1:-1;1482:754:12;;-1:-1:-1;2195:8:12;;2092:84;1482:754;-1:-1:-1;;;1482:754:12:o;2494:160::-;2559:20;;2615:13;;2608:21;2598:32;;2588:60;;2644:1;2641;2634:12;2588:60;2494:160;;;:::o;2659:180::-;2715:6;2768:2;2756:9;2747:7;2743:23;2739:32;2736:52;;;2784:1;2781;2774:12;2736:52;2807:26;2823:9;2807:26;:::i;2844:188::-;2912:20;;2972:34;2961:46;;2951:57;;2941:85;;3022:1;3019;3012:12;3037:186;3096:6;3149:2;3137:9;3128:7;3124:23;3120:32;3117:52;;;3165:1;3162;3155:12;3117:52;3188:29;3207:9;3188:29;:::i;3228:247::-;3287:6;3340:2;3328:9;3319:7;3315:23;3311:32;3308:52;;;3356:1;3353;3346:12;3308:52;3395:9;3382:23;3414:31;3439:5;3414:31;:::i;3947:184::-;3999:77;3996:1;3989:88;4096:4;4093:1;4086:15;4120:4;4117:1;4110:15;4136:334;4207:2;4201:9;4263:2;4253:13;;4268:66;4249:86;4237:99;;4366:18;4351:34;;4387:22;;;4348:62;4345:88;;;4413:18;;:::i;:::-;4449:2;4442:22;4136:334;;-1:-1:-1;4136:334:12:o;4475:712::-;4529:5;4582:3;4575:4;4567:6;4563:17;4559:27;4549:55;;4600:1;4597;4590:12;4549:55;4636:6;4623:20;4662:4;4685:18;4681:2;4678:26;4675:52;;;4707:18;;:::i;:::-;4753:2;4750:1;4746:10;4776:28;4800:2;4796;4792:11;4776:28;:::i;:::-;4838:15;;;4908;;;4904:24;;;4869:12;;;;4940:15;;;4937:35;;;4968:1;4965;4958:12;4937:35;5004:2;4996:6;4992:15;4981:26;;5016:142;5032:6;5027:3;5024:15;5016:142;;;5098:17;;5086:30;;5049:12;;;;5136;;;;5016:142;;;5176:5;4475:712;-1:-1:-1;;;;;;;4475:712:12:o;5192:348::-;5276:6;5329:2;5317:9;5308:7;5304:23;5300:32;5297:52;;;5345:1;5342;5335:12;5297:52;5385:9;5372:23;5418:18;5410:6;5407:30;5404:50;;;5450:1;5447;5440:12;5404:50;5473:61;5526:7;5517:6;5506:9;5502:22;5473:61;:::i;5545:260::-;5613:6;5621;5674:2;5662:9;5653:7;5649:23;5645:32;5642:52;;;5690:1;5687;5680:12;5642:52;5713:29;5732:9;5713:29;:::i;:::-;5703:39;;5761:38;5795:2;5784:9;5780:18;5761:38;:::i;:::-;5751:48;;5545:260;;;;;:::o;5810:180::-;5869:6;5922:2;5910:9;5901:7;5897:23;5893:32;5890:52;;;5938:1;5935;5928:12;5890:52;-1:-1:-1;5961:23:12;;5810:180;-1:-1:-1;5810:180:12:o;6180:993::-;6482:3;6495:22;;;6566:13;;6467:19;;;6588:22;;;6434:4;;6664;;6641:3;6626:19;;;6691:15;;;6434:4;6734:169;6748:6;6745:1;6742:13;6734:169;;;6809:13;;6797:26;;6843:12;;;;6878:15;;;;6770:1;6763:9;6734:169;;;-1:-1:-1;;;6939:18:12;;;6932:34;;;;-1:-1:-1;6997:2:12;6982:18;;6975:34;;;;7028;7098:15;;;7093:2;7078:18;;7071:43;7151:15;7145:3;7130:19;;;7123:44;6920:3;6180:993;-1:-1:-1;6180:993:12:o;7424:634::-;7544:6;7552;7560;7568;7576;7629:3;7617:9;7608:7;7604:23;7600:33;7597:53;;;7646:1;7643;7636:12;7597:53;7686:9;7673:23;7719:18;7711:6;7708:30;7705:50;;;7751:1;7748;7741:12;7705:50;7774:61;7827:7;7818:6;7807:9;7803:22;7774:61;:::i;:::-;7764:71;;;7854:38;7888:2;7877:9;7873:18;7854:38;:::i;:::-;7844:48;;7911:38;7945:2;7934:9;7930:18;7911:38;:::i;:::-;7424:634;;;;-1:-1:-1;7901:48:12;;7996:2;7981:18;;7968:32;;-1:-1:-1;8047:3:12;8032:19;8019:33;;7424:634;-1:-1:-1;;7424:634:12:o;8245:::-;8359:6;8367;8375;8383;8391;8444:3;8432:9;8423:7;8419:23;8415:33;8412:53;;;8461:1;8458;8451:12;8412:53;8501:9;8488:23;8534:18;8526:6;8523:30;8520:50;;;8566:1;8563;8556:12;8520:50;8589:61;8642:7;8633:6;8622:9;8618:22;8589:61;:::i;:::-;8579:71;;;8669:38;8703:2;8692:9;8688:18;8669:38;:::i;:::-;8659:48;;8726:38;8760:2;8749:9;8745:18;8726:38;:::i;:::-;8716:48;;8783:35;8814:2;8803:9;8799:18;8783:35;:::i;:::-;8773:45;;8837:36;8868:3;8857:9;8853:19;8837:36;:::i;:::-;8827:46;;8245:634;;;;;;;;:::o;9115:671::-;9201:6;9209;9217;9225;9278:3;9266:9;9257:7;9253:23;9249:33;9246:53;;;9295:1;9292;9285:12;9246:53;9334:9;9321:23;9353:31;9378:5;9353:31;:::i;:::-;9403:5;-1:-1:-1;9460:2:12;9445:18;;9432:32;9473:33;9432:32;9473:33;:::i;:::-;9525:7;-1:-1:-1;9584:2:12;9569:18;;9556:32;9597:33;9556:32;9597:33;:::i;:::-;9649:7;-1:-1:-1;9708:2:12;9693:18;;9680:32;9721:33;9680:32;9721:33;:::i;:::-;9115:671;;;;-1:-1:-1;9115:671:12;;-1:-1:-1;;9115:671:12:o;9791:367::-;9854:8;9864:6;9918:3;9911:4;9903:6;9899:17;9895:27;9885:55;;9936:1;9933;9926:12;9885:55;-1:-1:-1;9959:20:12;;10002:18;9991:30;;9988:50;;;10034:1;10031;10024:12;9988:50;10071:4;10063:6;10059:17;10047:29;;10131:3;10124:4;10114:6;10111:1;10107:14;10099:6;10095:27;10091:38;10088:47;10085:67;;;10148:1;10145;10138:12;10163:1338;10323:6;10331;10339;10347;10355;10363;10371;10379;10432:3;10420:9;10411:7;10407:23;10403:33;10400:53;;;10449:1;10446;10439:12;10400:53;10488:9;10475:23;10507:31;10532:5;10507:31;:::i;:::-;10557:5;-1:-1:-1;10614:2:12;10599:18;;10586:32;10627:33;10586:32;10627:33;:::i;:::-;10679:7;-1:-1:-1;10737:2:12;10722:18;;10709:32;10760:18;10790:14;;;10787:34;;;10817:1;10814;10807:12;10787:34;10856:70;10918:7;10909:6;10898:9;10894:22;10856:70;:::i;:::-;10945:8;;-1:-1:-1;10830:96:12;-1:-1:-1;11033:2:12;11018:18;;11005:32;;-1:-1:-1;11049:16:12;;;11046:36;;;11078:1;11075;11068:12;11046:36;11117:72;11181:7;11170:8;11159:9;11155:24;11117:72;:::i;:::-;11208:8;;-1:-1:-1;11091:98:12;-1:-1:-1;11296:3:12;11281:19;;11268:33;;-1:-1:-1;11313:16:12;;;11310:36;;;11342:1;11339;11332:12;11310:36;;11381:60;11433:7;11422:8;11411:9;11407:24;11381:60;:::i;:::-;10163:1338;;;;-1:-1:-1;10163:1338:12;;-1:-1:-1;10163:1338:12;;;;;;11460:8;-1:-1:-1;;;10163:1338:12:o;12018:823::-;12124:6;12132;12140;12148;12156;12164;12217:3;12205:9;12196:7;12192:23;12188:33;12185:53;;;12234:1;12231;12224:12;12185:53;12273:9;12260:23;12292:31;12317:5;12292:31;:::i;:::-;12342:5;-1:-1:-1;12399:2:12;12384:18;;12371:32;12412:33;12371:32;12412:33;:::i;:::-;12464:7;-1:-1:-1;12518:2:12;12503:18;;12490:32;;-1:-1:-1;12569:2:12;12554:18;;12541:32;;-1:-1:-1;12624:3:12;12609:19;;12596:33;12652:18;12641:30;;12638:50;;;12684:1;12681;12674:12;12638:50;12723:58;12773:7;12764:6;12753:9;12749:22;12723:58;:::i;:::-;12018:823;;;;-1:-1:-1;12018:823:12;;-1:-1:-1;12018:823:12;;12800:8;;12018:823;-1:-1:-1;;;12018:823:12:o;12846:245::-;12894:4;12927:18;12919:6;12916:30;12913:56;;;12949:18;;:::i;:::-;-1:-1:-1;13006:2:12;12994:15;13011:66;12990:88;13080:4;12986:99;;12846:245::o;13096:671::-;13164:6;13217:2;13205:9;13196:7;13192:23;13188:32;13185:52;;;13233:1;13230;13223:12;13185:52;13273:9;13260:23;13306:18;13298:6;13295:30;13292:50;;;13338:1;13335;13328:12;13292:50;13361:22;;13414:4;13406:13;;13402:27;-1:-1:-1;13392:55:12;;13443:1;13440;13433:12;13392:55;13479:2;13466:16;13504:48;13520:31;13548:2;13520:31;:::i;:::-;13504:48;:::i;:::-;13575:2;13568:5;13561:17;13615:7;13610:2;13605;13601;13597:11;13593:20;13590:33;13587:53;;;13636:1;13633;13626:12;13587:53;13691:2;13686;13682;13678:11;13673:2;13666:5;13662:14;13649:45;13735:1;13714:14;;;13730:2;13710:23;13703:34;;;;13718:5;13096:671;-1:-1:-1;;;;13096:671:12:o;14483:184::-;14535:77;14532:1;14525:88;14632:4;14629:1;14622:15;14656:4;14653:1;14646:15;14672:253;14712:3;14740:34;14801:2;14798:1;14794:10;14831:2;14828:1;14824:10;14862:3;14858:2;14854:12;14849:3;14846:21;14843:47;;;14870:18;;:::i;:::-;14906:13;;14672:253;-1:-1:-1;;;;14672:253:12:o;15634:184::-;15686:77;15683:1;15676:88;15783:4;15780:1;15773:15;15807:4;15804:1;15797:15;16319:184;16371:77;16368:1;16361:88;16468:4;16465:1;16458:15;16492:4;16489:1;16482:15;16863:195;16902:3;16933:66;16926:5;16923:77;16920:103;;17003:18;;:::i;:::-;-1:-1:-1;17050:1:12;17039:13;;16863:195::o;17466:125::-;17506:4;17534:1;17531;17528:8;17525:34;;;17539:18;;:::i;:::-;-1:-1:-1;17576:9:12;;17466:125::o;17596:184::-;17648:77;17645:1;17638:88;17745:4;17742:1;17735:15;17769:4;17766:1;17759:15;20178:246;20218:4;20247:34;20331:10;;;;20301;;20353:12;;;20350:38;;;20368:18;;:::i;:::-;20405:13;;20178:246;-1:-1:-1;;;20178:246:12:o;22725:258::-;22797:1;22807:113;22821:6;22818:1;22815:13;22807:113;;;22897:11;;;22891:18;22878:11;;;22871:39;22843:2;22836:10;22807:113;;;22938:6;22935:1;22932:13;22929:48;;;22973:1;22964:6;22959:3;22955:16;22948:27;22929:48;;22725:258;;;:::o;22988:560::-;23175:42;23167:6;23163:55;23152:9;23145:74;23255:2;23250;23239:9;23235:18;23228:30;23126:4;23287:6;23281:13;23330:6;23325:2;23314:9;23310:18;23303:34;23346:66;23405:6;23400:2;23389:9;23385:18;23380:2;23372:6;23368:15;23346:66;:::i;:::-;23464:2;23452:15;23469:66;23448:88;23433:104;;;;23539:2;23429:113;;22988:560;-1:-1:-1;;;22988:560:12:o;23553:431::-;23768:6;23763:3;23756:19;23738:3;23804:6;23798:13;23820:60;23873:6;23868:2;23863:3;23859:12;23854:2;23846:6;23842:15;23820:60;:::i;:::-;23939:2;23899:16;;23931:11;;;23924:27;;;;23975:2;23967:11;;23553:431;-1:-1:-1;;;23553:431:12:o;25564:634::-;25643:6;25696:2;25684:9;25675:7;25671:23;25667:32;25664:52;;;25712:1;25709;25702:12;25664:52;25745:9;25739:16;25778:18;25770:6;25767:30;25764:50;;;25810:1;25807;25800:12;25764:50;25833:22;;25886:4;25878:13;;25874:27;-1:-1:-1;25864:55:12;;25915:1;25912;25905:12;25864:55;25944:2;25938:9;25969:48;25985:31;26013:2;25985:31;:::i;25969:48::-;26040:2;26033:5;26026:17;26080:7;26075:2;26070;26066;26062:11;26058:20;26055:33;26052:53;;;26101:1;26098;26091:12;26052:53;26114:54;26165:2;26160;26153:5;26149:14;26144:2;26140;26136:11;26114:54;:::i;:::-;26187:5;25564:634;-1:-1:-1;;;;;25564:634:12:o;26203:228::-;26243:7;26369:1;26301:66;26297:74;26294:1;26291:81;26286:1;26279:9;26272:17;26268:105;26265:131;;;26376:18;;:::i;:::-;-1:-1:-1;26416:9:12;;26203:228::o;26436:128::-;26476:3;26507:1;26503:6;26500:1;26497:13;26494:39;;;26513:18;;:::i;:::-;-1:-1:-1;26549:9:12;;26436:128::o;26569:497::-;26675:6;26683;26691;26699;26707;26760:3;26748:9;26739:7;26735:23;26731:33;26728:53;;;26777:1;26774;26767:12;26728:53;26806:9;26800:16;26790:26;;26856:2;26845:9;26841:18;26835:25;26825:35;;26900:2;26889:9;26885:18;26879:25;26869:35;;26944:2;26933:9;26929:18;26923:25;26913:35;;26991:3;26980:9;26976:19;26970:26;27005:31;27030:5;27005:31;:::i;:::-;27055:5;27045:15;;;26569:497;;;;;;;;:::o;27811:184::-;27863:77;27860:1;27853:88;27960:4;27957:1;27950:15;27984:4;27981:1;27974:15;28000:112;28032:1;28058;28048:35;;28063:18;;:::i;:::-;-1:-1:-1;28097:9:12;;28000:112::o;28117:120::-;28157:1;28183;28173:35;;28188:18;;:::i;:::-;-1:-1:-1;28222:9:12;;28117:120::o;28242:157::-;28272:1;28306:4;28303:1;28299:12;28330:3;28320:37;;28337:18;;:::i;:::-;28389:3;28382:4;28379:1;28375:12;28371:22;28366:27;;;28242:157;;;;:::o;28404:165::-;28442:1;28476:4;28473:1;28469:12;28500:3;28490:37;;28507:18;;:::i;:::-;28559:3;28552:4;28549:1;28545:12;28541:22;28536:27;;;28404:165;;;;:::o;28574:482::-;28663:1;28706:5;28663:1;28720:330;28741:7;28731:8;28728:21;28720:330;;;28860:4;28792:66;28788:77;28782:4;28779:87;28776:113;;;28869:18;;:::i;:::-;28919:7;28909:8;28905:22;28902:55;;;28939:16;;;;28902:55;29018:22;;;;28978:15;;;;28720:330;;;28724:3;28574:482;;;;;:::o;29061:866::-;29110:5;29140:8;29130:80;;-1:-1:-1;29181:1:12;29195:5;;29130:80;29229:4;29219:76;;-1:-1:-1;29266:1:12;29280:5;;29219:76;29311:4;29329:1;29324:59;;;;29397:1;29392:130;;;;29304:218;;29324:59;29354:1;29345:10;;29368:5;;;29392:130;29429:3;29419:8;29416:17;29413:43;;;29436:18;;:::i;:::-;-1:-1:-1;;29492:1:12;29478:16;;29507:5;;29304:218;;29606:2;29596:8;29593:16;29587:3;29581:4;29578:13;29574:36;29568:2;29558:8;29555:16;29550:2;29544:4;29541:12;29537:35;29534:77;29531:159;;;-1:-1:-1;29643:19:12;;;29675:5;;29531:159;29722:34;29747:8;29741:4;29722:34;:::i;:::-;29852:6;29784:66;29780:79;29771:7;29768:92;29765:118;;;29863:18;;:::i;:::-;29901:20;;29061:866;-1:-1:-1;;;29061:866:12:o;29932:131::-;29992:5;30021:36;30048:8;30042:4;30021:36;:::i;31019:195::-;31057:4;31094;31091:1;31087:12;31126:4;31123:1;31119:12;31151:3;31146;31143:12;31140:38;;;31158:18;;:::i;:::-;31195:13;;;31019:195;-1:-1:-1;;;31019:195:12:o

Swarm Source

ipfs://9217d194649c8ac2c51aa00479d69ea51ac54bd1aa40db13a821cd0d44e3efe1

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

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