Contract 0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c 3

Contract Overview

Balance:
0 AVAX

AVAX Value:
$0.00

Token:
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x8fb61cbf4f9f8b264420ca120f8b69f60226472f2ee48e3217ea25d815f67550Claim187938692022-08-18 7:36:112 mins ago0x7f3a22f69317adc2212b973b6543ae6cd48bdd03 IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0027480235 26.‍5
0x48b2da59136b0dee73108ed1b2213c73be7a5114d97f623fcf728c12be8b7b21Level Up187931522022-08-18 7:11:4626 mins ago0xe8a4ff71f9a0f46c15d67969c69451c3c9a1112f IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0053776715 26.‍5
0x46160b4d5e3b944900e6b3dacc1173a2f48f5e4ebcabff16f7841569d12bf58eClaim187931282022-08-18 7:10:5827 mins ago0x60fc9edde8ba8d742257315dd5664e4545b54a5d IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍002696174 26
0x97ac358da773f94e77541be827d416f0abc01ff57e642c82500011b33ea7de40Claim187930412022-08-18 7:08:0230 mins ago0xe8a4ff71f9a0f46c15d67969c69451c3c9a1112f IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0027480235 26.‍5
0x5b2cd0e10f1ca3218cf19a980015c4cf4d65f6a96691abe13ac16804ec1c5fcbLevel Up187927072022-08-18 6:56:4041 mins ago0x014ad74aa942e15dc5cbebb75637cc275ee01594 IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0044686155 26.‍5
0x05b51a44389fd3e6ef1006c5bf93869aa6272b6aeea1f304de4631befd2fbe45Vote187922142022-08-18 6:39:4058 mins ago0x60fc9edde8ba8d742257315dd5664e4545b54a5d IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍00291239 26
0x948ddf1dceb5792e26a432c4cbd2488f1472a7ac6af3773971e6c973bcc618b1Claim187917792022-08-18 6:24:531 hr 13 mins ago0xd1fd9c07c0a036891ffc72c8b0d2212eca0f2599 IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0032011735 26.‍5
0xad762e6de1490bc9db3cb71738823582ca7183f12eac8c4e3ab9bd0e072ef84dLevel Up187916782022-08-18 6:21:241 hr 17 mins ago0xdafe3083bd4865ade8fea183c0e058a585bab68b IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0042397163 25.‍1
0x67eaa828725dfff215f07fd8cbd766ce4e47715cb3c2672522b123595127b700Level Up187913152022-08-18 6:08:571 hr 29 mins ago0xc0dca80b4da1ec8afe3ec2f4fe6239740d4876ac IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍004534287615 26.‍8818
0x1d1113db1f66d0ff5502a4b99f211f294f1fcc0c074888bf05c2b45ad6bec894Vote187887712022-08-18 4:41:042 hrs 57 mins ago0xaa09a0dbe81c56d1670377f61491b34283a6bf5e IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0029680265 26.‍5
0xa0c1d1903fdc09a4d6ad378e1a3a33365bc0616d1a3b45fb138b29bcac92285bLevel Up187884452022-08-18 4:30:043 hrs 8 mins ago0xb95c5ce89797968389f3d9e0b4350d5260a90b49 IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍004826926 26
0xcbe47cf64a9aea4aa88643f075c73a25fbe872b179343c12025a2b78806b0728Level Up187883262022-08-18 4:25:473 hrs 12 mins ago0xb95c5ce89797968389f3d9e0b4350d5260a90b49 IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍004385186 26
0x67dba097090cb78ec4606278faeeee3a501c3cbc4c49ea6d55a9b665e77313f4Level Up187882982022-08-18 4:24:483 hrs 13 mins ago0xb95c5ce89797968389f3d9e0b4350d5260a90b49 IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍005271266 26
0xeb6936e0a8751f412bca20b624f3807fb31694b3c5b623321551993d2591b8d6Vote187881292022-08-18 4:19:073 hrs 19 mins ago0x7a1f36cd575fc2bbe5b3c87f943de8a4bfc7e8d1 IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍00302402727
0xa33b8b46ffd7af17ba6d0381241b8f3e6183aff398c9d330207613cef64f2470Level Up187879002022-08-18 4:11:163 hrs 27 mins ago0x99db7363a308b5eea83e792bdce6020ce0db3555 IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0044697815 26.‍5
0x10a1e17be1e94d3f0f14a26a6aa705a4e24e407c0745599c2331c4ac4eb8cae5Level Up187878862022-08-18 4:10:453 hrs 27 mins ago0x99db7363a308b5eea83e792bdce6020ce0db3555 IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0044697815 26.‍5
0x82a1ff56e17c8b8d091477db9e3c8d9635bfbfb97c7b8179083a341ebfe98d63Claim187876602022-08-18 4:02:553 hrs 35 mins ago0x2b602a68da26ad5eb0eceb9d5c9472031ac8b311 IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0032011735 26.‍5
0x2cd1f8e3e12582761fa41b66b5289d23acf5e459b25bf03269eac6e9b07991b8Level Up187872992022-08-18 3:50:273 hrs 48 mins ago0x2b602a68da26ad5eb0eceb9d5c9472031ac8b311 IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0053833425 26.‍5
0x4a97a30ac96a28902c24d749c45132c00747804947b3fa9ea2937eef832f2973Level Up187872972022-08-18 3:50:233 hrs 48 mins ago0x2b602a68da26ad5eb0eceb9d5c9472031ac8b311 IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0053758695 26.‍5
0xd333e1658ab397768247511a26af018b951502e64325bea98d250ca6b89cb0ceClaim187872342022-08-18 3:48:113 hrs 50 mins ago0x2b602a68da26ad5eb0eceb9d5c9472031ac8b311 IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0027480235 26.‍5
0xe1a9e6ead71d06fa4a5d083a76cecab6bc63f575e20b0d0c29d352af4c31cb2aLevel Up187861042022-08-18 3:09:154 hrs 29 mins ago0xd1fd9c07c0a036891ffc72c8b0d2212eca0f2599 IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0044695165 26.‍5
0x0cdbf8cff50a8dfa56883b25ecccbed5a93f17c5ca02264b77b205e76f4bd857Vote187857652022-08-18 2:57:344 hrs 41 mins ago0x5f308472e47ac43ee0fc4878ef683a763f57854f IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0029683445 26.‍5
0x21ef616dbdac40c2e95f154472ad235feb83b77ef52d1d7d9380b309b5e4103eLevel Up187847922022-08-18 2:24:325 hrs 14 mins ago0x8ed5f8689393bd506df041ab09d3184deba091ff IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0044720605 26.‍5
0xdb822379f8c9b233c65571354677541a8e9fd2b51004dd88da30447fbbaf0d10Level Up187841252022-08-18 2:01:365 hrs 37 mins ago0x603a59c8e44bba7635fb8bea59eab53106865d89 IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0044742865 26.‍5
0x8761e34d8bd15c6944d8a0e7b91bbf138ad74d31c318e6c09bab7f49d50315bdLevel Up187838892022-08-18 1:53:355 hrs 45 mins ago0x88c31f648bdbc89ecdfbabe18b5a800e63ed8ee6 IN  0xec7e923e7e0bd2dc7bb2ac0fabccf4e650c5418c0 AVAX0.‍0042350445 26.‍5
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Swamp

Compiler Version
v0.8.12+commit.f00d7308

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
default evmVersion, Unlicense license

Contract Source Code (Solidity)

/**
 *Submitted for verification at snowtrace.io on 2022-03-18
*/

// SPDX-License-Identifier: Unlicense
pragma solidity 0.8.12;

/// @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
    //////////////////////////////////////////////////////////////*/

    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 {
            address recoveredAddress = ecrecover(
                keccak256(
                    abi.encodePacked(
                        "\x19\x01",
                        DOMAIN_SEPARATOR(),
                        keccak256(
                            abi.encode(
                                keccak256(
                                    "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
                                ),
                                owner,
                                spender,
                                value,
                                nonces[owner]++,
                                deadline
                            )
                        )
                    )
                ),
                v,
                r,
                s
            );

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

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

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

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

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

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

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

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

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

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

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

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
    event Debug(bool one, bool two, uint256 retsize);

    /*///////////////////////////////////////////////////////////////
                            ETH OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferETH(address to, uint256 amount) internal {
        bool success;

        assembly {
            // Transfer the ETH and store if it succeeded or not.
            success := call(gas(), to, amount, 0, 0, 0, 0)
        }

        require(success, "ETH_TRANSFER_FAILED");
    }

    /*///////////////////////////////////////////////////////////////
                           ERC20 OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferFrom(
        ERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        bool success;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument.
            mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (not just any non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the addition in the
                // order of operations or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
            )
        }

        require(success, "TRANSFER_FROM_FAILED");
    }

    function safeTransfer(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (not just any non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the addition in the
                // order of operations or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "TRANSFER_FAILED");
    }

    function safeApprove(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (not just any non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the addition in the
                // order of operations or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "APPROVE_FAILED");
    }
}/// @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 || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],
            "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 view 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(owner != 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);
}// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/MerkleProof.sol)



/**
 * @dev These functions deal with verification of Merkle Trees proofs.
 *
 * The proofs can be generated using the JavaScript library
 * https://github.com/miguelmota/merkletreejs[merkletreejs].
 * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
 *
 * See `test/utils/cryptography/MerkleProof.test.js` for some examples.
 *
 * WARNING: You should avoid using leaf values that are 64 bytes long prior to
 * hashing, or use a hash function other than keccak256 for hashing leaves.
 * This is because the concatenation of a sorted pair of internal nodes in
 * the merkle tree could be reinterpreted as a leaf value.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leafs & pre-images are assumed to be sorted.
     *
     * _Available since v4.4._
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            bytes32 proofElement = proof[i];
            if (computedHash <= proofElement) {
                // Hash(current computed hash + current element of the proof)
                computedHash = _efficientHash(computedHash, proofElement);
            } else {
                // Hash(current element of the proof + current computed hash)
                computedHash = _efficientHash(proofElement, computedHash);
            }
        }
        return computedHash;
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}
//slither-disable-next-line locked-ether
contract HopperNFT is ERC721 {
    using SafeTransferLib for address;

    address public owner;

    /*///////////////////////////////////////////////////////////////
                            IMMUTABLE STORAGE
    //////////////////////////////////////////////////////////////*/
    uint256 public immutable MAX_PER_ADDRESS;
    uint256 public immutable MAX_SUPPLY;
    uint256 public immutable MINT_COST;
    uint256 public immutable WL_MINT_COST;
    uint256 public immutable LEGENDARY_ID_START;

    /*///////////////////////////////////////////////////////////////
                              SALE DETAILS
    //////////////////////////////////////////////////////////////*/

    uint256 public reserved;
    uint256 public preSaleOpenTime;
    bytes32 public freeMerkleRoot;
    bytes32 public wlMerkleRoot;
    mapping(address => uint256) public freeRedeemed;
    mapping(address => uint256) public wlRedeemed;

    /*///////////////////////////////////////////////////////////////
                                HOPPERS
    //////////////////////////////////////////////////////////////*/

    struct Hopper {
        uint200 level; // capped by zone
        uint16 rebirths;
        uint8 strength;
        uint8 agility;
        uint8 vitality;
        uint8 intelligence;
        uint8 fertility;
    }

    mapping(uint256 => Hopper) public hoppers;
    uint256 public hoppersLength;
    uint256 public hopperMaxAttributeValue;

    mapping(uint256 => uint256) public indexer;

    string public baseURI;
    string public imageURL;

    /*///////////////////////////////////////////////////////////////
                             
    //////////////////////////////////////////////////////////////*/

    // whitelist for leveling up
    mapping(address => bool) public zones;

    // unlabeled data [key -> tokenid -> data] for potential future zones
    mapping(string => mapping(uint256 => bytes32)) public unlabeledData;

    // unlabeled data [key -> data] for potential future zones
    mapping(string => bytes32) public unlabeledGlobalData;

    /*///////////////////////////////////////////////////////////////
                            HOPPER NAMES
    //////////////////////////////////////////////////////////////*/

    uint256 public nameFee;
    mapping(bytes32 => bool) public takenNames;
    mapping(uint256 => string) public hoppersNames;

    /*///////////////////////////////////////////////////////////////
                                EVENTS
    //////////////////////////////////////////////////////////////*/

    event OwnerUpdated(address indexed newOwner);
    event LevelUp(uint256 tokenId);
    event NameChange(uint256 tokenId);
    event UpdatedNameFee(uint256 namefee);
    event Rebirth(uint256 tokenId);
    event UnlabeledData(string key, uint256 tokenId);

    /*///////////////////////////////////////////////////////////////
                                ERRORS
    //////////////////////////////////////////////////////////////*/

    error MintLimit();
    error InsufficientAmount();
    error Unauthorized();
    error InvalidTokenID();
    error MaxLength25();
    error OnlyEOAAllowed();
    error NameTaken();
    error OnlyLvL100();
    error TooSoon();
    error ReservedAmountInvalid();
    error OnlyAlphanumeric();

    constructor(
        string memory _NFT_NAME,
        string memory _NFT_SYMBOL,
        uint256 _NAME_FEE
    ) ERC721(_NFT_NAME, _NFT_SYMBOL) {
        owner = msg.sender;

        MINT_COST = 1.75 ether;
        WL_MINT_COST = 1.2 ether;
        MAX_SUPPLY = 10_000;
        MAX_PER_ADDRESS = 10;
        LEGENDARY_ID_START = 9968;

        nameFee = _NAME_FEE;
        hopperMaxAttributeValue = 10;

        unchecked {
            preSaleOpenTime = type(uint256).max - 30 minutes;
        }
    }

    /*///////////////////////////////////////////////////////////////
                    CONTRACT MANAGEMENT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    modifier onlyOwner() {
        if (msg.sender != owner) revert Unauthorized();
        _;
    }

    modifier onlyZone() {
        if (!zones[msg.sender]) revert Unauthorized();
        _;
    }

    modifier onlyOwnerOrZone() {
        if (msg.sender != owner && !zones[msg.sender]) revert Unauthorized();
        _;
    }

    function setOwner(address newOwner) external onlyOwner {
        //slither-disable-next-line missing-zero-check
        owner = newOwner;
        emit OwnerUpdated(newOwner);
    }

    function setHopperMaxAttributeValue(uint256 _hopperMaxAttributeValue)
        external
        onlyOwner
    {
        hopperMaxAttributeValue = _hopperMaxAttributeValue;
    }

    function setNameChangeFee(uint256 _nameFee) external onlyOwner {
        nameFee = _nameFee;
        emit UpdatedNameFee(_nameFee);
    }

    function setBaseURI(string calldata _baseURI) external onlyOwner {
        baseURI = _baseURI;
    }

    function setImageURL(string calldata _imageURL) external onlyOwner {
        imageURL = _imageURL;
    }

    function setSaleDetails(
        uint256 _preSaleOpenTime,
        bytes32 _wlMerkleRoot,
        bytes32 _freeMerkleRoot,
        uint256 _reserved
    ) external onlyOwner {
        preSaleOpenTime = _preSaleOpenTime;

        freeMerkleRoot = _freeMerkleRoot;
        wlMerkleRoot = _wlMerkleRoot;

        reserved = _reserved;
    }

    function withdraw() external onlyOwner {
        owner.safeTransferETH(address(this).balance);
    }

    /*///////////////////////////////////////////////////////////////
                    HOPPER VALID ZONES/ADVENTURES
    //////////////////////////////////////////////////////////////*/

    function addZones(address[] calldata _zones) external onlyOwner {
        uint256 length = _zones.length;
        for (uint256 i; i < length; ) {
            zones[_zones[i]] = true;
            unchecked {
                ++i;
            }
        }
    }

    function removeZone(address _zone) external onlyOwner {
        delete zones[_zone];
    }

    /*///////////////////////////////////////////////////////////////
                            Unlabeled Data
    //////////////////////////////////////////////////////////////*/

    function setGlobalData(string calldata _key, bytes32 _data)
        external
        onlyOwnerOrZone
    {
        unlabeledGlobalData[_key] = _data;
    }

    function unsetGlobalData(string calldata _key) external onlyOwnerOrZone {
        delete unlabeledGlobalData[_key];
    }

    function getGlobalData(string calldata _key)
        external
        view
        returns (bytes32)
    {
        return unlabeledGlobalData[_key];
    }

    function setData(
        string calldata _key,
        uint256 _tokenId,
        bytes32 _data
    ) external onlyOwnerOrZone {
        unlabeledData[_key][_tokenId] = _data;

        emit UnlabeledData(_key, _tokenId);
    }

    function unsetData(string calldata _key, uint256 _tokenId)
        external
        onlyOwnerOrZone
    {
        delete unlabeledData[_key][_tokenId];
    }

    function getData(string calldata _key, uint256 _tokenId)
        external
        view
        returns (bytes32)
    {
        return unlabeledData[_key][_tokenId];
    }

    function getHopperWithData(string[] calldata _keys, uint256 _tokenId)
        external
        view
        returns (Hopper memory hopper, bytes32[] memory arrData)
    {
        hopper = hoppers[_tokenId];

        uint256 length = _keys.length;
        arrData = new bytes32[](length);

        for (uint256 i; i < length; ) {
            arrData[i] = unlabeledData[_keys[i]][_tokenId];
            unchecked {
                ++i;
            }
        }
    }

    /*///////////////////////////////////////////////////////////////
                        HOPPER LEVEL SYSTEM
    //////////////////////////////////////////////////////////////*/

    function rebirth(uint256 _tokenId) external {
        Hopper memory hopper = hoppers[_tokenId];

        if (ownerOf[_tokenId] != msg.sender) revert Unauthorized();
        if (hopper.level < 100) revert OnlyLvL100();

        uint256 _hopperMaxAttributeValue = hopperMaxAttributeValue;

        unchecked {
            if (hopper.strength < _hopperMaxAttributeValue) {
                hoppers[_tokenId].strength = uint8(hopper.strength + 1);
            }

            if (hopper.intelligence < _hopperMaxAttributeValue) {
                hoppers[_tokenId].intelligence = uint8(hopper.intelligence + 1);
            }

            if (hopper.agility < _hopperMaxAttributeValue) {
                hoppers[_tokenId].agility = uint8(hopper.agility + 1);
            }

            if (hopper.vitality < _hopperMaxAttributeValue) {
                hoppers[_tokenId].vitality = uint8(hopper.vitality + 1);
            }

            if (hopper.fertility < _hopperMaxAttributeValue) {
                hoppers[_tokenId].fertility = uint8(hopper.fertility + 1);
            }

            ++hoppers[_tokenId].rebirths;
        }

        hoppers[_tokenId].level = 1;

        delete unlabeledData["LEVEL_GAUGE_KEY"][_tokenId];

        emit Rebirth(_tokenId);
    }

    function levelUp(uint256 tokenId) external onlyZone {
        // max level is checked on zone
        unchecked {
            ++(hoppers[tokenId].level);
        }
        emit LevelUp(tokenId);
    }

    function changeHopperName(uint256 tokenId, string calldata _newName)
        external
        onlyZone
        returns (uint256)
    {
        bytes memory newName = bytes(_newName);
        uint256 newLength = newName.length;

        if (newLength > 25) revert MaxLength25();

        // Checks it's only alphanumeric characters
        for (uint256 i; i < newLength; ) {
            bytes1 char = newName[i];

            if (
                !(char >= 0x30 && char <= 0x39) && //9-0
                !(char >= 0x41 && char <= 0x5A) && //A-Z
                !(char >= 0x61 && char <= 0x7A) && //a-z
                !(char == 0x2E) //.
            ) {
                revert OnlyAlphanumeric();
            }
            unchecked {
                ++i;
            }
        }

        // Checks new name uniqueness
        bytes32 nameHash = keccak256(newName);
        if (takenNames[nameHash]) revert NameTaken();

        // Free previous name
        takenNames[keccak256(bytes(hoppersNames[tokenId]))] = false;

        // Reserve name
        takenNames[nameHash] = true;
        hoppersNames[tokenId] = _newName;

        emit NameChange(tokenId);

        return nameFee;
    }

    /*///////////////////////////////////////////////////////////////
                          HOPPER GENERATION
    //////////////////////////////////////////////////////////////*/

    function enoughRandom() internal view returns (uint256) {
        return
            uint256(
                keccak256(
                    abi.encodePacked(
                        // solhint-disable-next-line
                        block.timestamp,
                        msg.sender,
                        blockhash(block.number)
                    )
                )
            );
    }

    //slither-disable-next-line weak-prng
    function generate(
        uint256 seed,
        uint256 minAttributeValue,
        uint256 randCap
    ) internal pure returns (Hopper memory) {
        unchecked {
            return
                Hopper({
                    strength: uint8(
                        ((seed >> (8 * 1)) % randCap) + minAttributeValue
                    ),
                    agility: uint8(
                        ((seed >> (8 * 2)) % randCap) + minAttributeValue
                    ),
                    vitality: uint8(
                        ((seed >> (8 * 3)) % randCap) + minAttributeValue
                    ),
                    intelligence: uint8(
                        ((seed >> (8 * 4)) % randCap) + minAttributeValue
                    ),
                    fertility: uint8(
                        ((seed >> (8 * 5)) % randCap) + minAttributeValue
                    ),
                    level: 1,
                    rebirths: 0
                });
        }
    }

    function _mintHoppers(uint256 numberOfMints, uint256 preTotalHoppers)
        internal
    {
        uint256 seed = enoughRandom();

        uint256 _indexerLength;
        unchecked {
            _indexerLength = MAX_SUPPLY - preTotalHoppers;
        }

        for (uint256 i; i < numberOfMints; ) {
            seed >>= i;

            // Find the next available tokenID
            //slither-disable-next-line weak-prng
            uint256 index = seed % _indexerLength;
            uint256 tokenId = indexer[index];

            if (tokenId == 0) {
                tokenId = index;
            }

            // Swap the picked tokenId for the last element
            unchecked {
                --_indexerLength;
            }

            uint256 last = indexer[_indexerLength];
            if (last == 0) {
                // this _indexerLength value had not been picked before
                indexer[index] = _indexerLength;
            } else {
                // this _indexerLength value had been picked and swapped before
                indexer[index] = last;
            }

            // Mint Hopper and generate its attributes
            _mint(msg.sender, tokenId);

            if (tokenId >= LEGENDARY_ID_START) {
                hoppers[tokenId] = generate(seed, 5, 6);
            } else {
                hoppers[tokenId] = generate(seed, 1, 10);
            }
            unchecked {
                ++i;
            }
        }
    }

    /*///////////////////////////////////////////////////////////////
                            HOPPER MINTING
    //////////////////////////////////////////////////////////////*/

    function _handleMint(uint256 numberOfMints) internal {
        // solhint-disable-next-line
        if (msg.sender != tx.origin) revert OnlyEOAAllowed();

        unchecked {
            uint256 totalHoppers = hoppersLength + numberOfMints;

            if (
                numberOfMints > MAX_PER_ADDRESS ||
                totalHoppers > (MAX_SUPPLY - reserved)
            ) revert MintLimit();

            _mintHoppers(numberOfMints, totalHoppers - numberOfMints);
            hoppersLength = totalHoppers;
        }
    }

    function freeMint(
        uint256 numberOfMints,
        uint256 totalGiven,
        bytes32[] memory proof
    ) external {
        unchecked {
            if (block.timestamp < preSaleOpenTime + 30 minutes)
                revert TooSoon();
        }

        if (freeRedeemed[msg.sender] + numberOfMints > totalGiven)
            revert Unauthorized();
        if (reserved < numberOfMints) revert ReservedAmountInvalid();

        if (
            !MerkleProof.verify(
                proof,
                freeMerkleRoot,
                keccak256(abi.encodePacked(msg.sender, totalGiven))
            )
        ) revert Unauthorized();

        unchecked {
            freeRedeemed[msg.sender] += numberOfMints;
            reserved -= numberOfMints;
        }

        _handleMint(numberOfMints);
    }

    function whitelistMint(bytes32[] memory proof) external payable {
        if (wlRedeemed[msg.sender] == 1) revert Unauthorized();
        if (block.timestamp < preSaleOpenTime) revert TooSoon();
        if (WL_MINT_COST > msg.value) revert InsufficientAmount();

        if (
            !MerkleProof.verify(
                proof,
                wlMerkleRoot,
                keccak256(abi.encodePacked(msg.sender))
            )
        ) revert Unauthorized();

        wlRedeemed[msg.sender] = 1;

        _handleMint(1);
    }

    function normalMint(uint256 numberOfMints) external payable {
        unchecked {
            if (block.timestamp < preSaleOpenTime + 30 minutes)
                revert TooSoon();
        }
        if (MINT_COST * numberOfMints > msg.value) revert InsufficientAmount();

        _handleMint(numberOfMints);
    }

    /*///////////////////////////////////////////////////////////////
                          HOPPER VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    function getHopper(uint256 tokenId) external view returns (Hopper memory) {
        return hoppers[tokenId];
    }

    function getHopperName(uint256 tokenId)
        public
        view
        returns (string memory name)
    {
        name = hoppersNames[tokenId];

        if (bytes(name).length == 0) {
            name = string(bytes.concat("hopper #", bytes(_toString(tokenId))));
        }
    }

    function _getTraits(Hopper memory hopper)
        internal
        pure
        returns (string memory)
    {
        return
            string(
                bytes.concat(
                    '{"trait_type": "rebirths", "value": ',
                    bytes(_toString(hopper.rebirths)),
                    "},",
                    '{"trait_type": "strength", "value": ',
                    bytes(_toString(hopper.strength)),
                    "},",
                    '{"trait_type": "agility", "value": ',
                    bytes(_toString(hopper.agility)),
                    "},",
                    '{"trait_type": "vitality", "value": ',
                    bytes(_toString(hopper.vitality)),
                    "},",
                    '{"trait_type": "intelligence", "value": ',
                    bytes(_toString(hopper.intelligence)),
                    "},",
                    '{"trait_type": "fertility", "value": ',
                    bytes(_toString(hopper.fertility)),
                    "}"
                )
            );
    }

    function _jsonString(uint256 tokenId)
        external
        view
        returns (string memory)
    {
        Hopper memory hopper = hoppers[tokenId];

        //slither-disable-next-line incorrect-equality
        if (hopper.level == 0) revert InvalidTokenID();

        return
            string(
                bytes.concat(
                    '{"name":"',
                    bytes(getHopperName(tokenId)),
                    '", "description":"Hopper", "attributes":[',
                    '{"trait_type": "level", "value": ',
                    bytes(_toString(hopper.level)),
                    "},",
                    bytes(_getTraits(hopper)),
                    "],",
                    '"image":"',
                    bytes(imageURL),
                    bytes(_toString(tokenId)),
                    '.png"}'
                )
            );
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override
        returns (string memory)
    {
        //slither-disable-next-line incorrect-equality
        if (hoppers[tokenId].level == 0) revert InvalidTokenID();

        return string(bytes.concat(bytes(baseURI), bytes(_toString(tokenId))));
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }

    function _toString(uint256 value) internal pure returns (string memory) {
        //slither-disable-next-line incorrect-equality
        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            //slither-disable-next-line weak-prng
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }
}
contract Fly is ERC20 {
    address public owner;

    // whitelist for minting mechanisms
    mapping(address => bool) public zones;

    /*///////////////////////////////////////////////////////////////
                                ERRORS
    //////////////////////////////////////////////////////////////*/

    error Unauthorized();

    /*///////////////////////////////////////////////////////////////
                                EVENTS
    //////////////////////////////////////////////////////////////*/

    event OwnerUpdated(address indexed newOwner);

    constructor(string memory _NAME, string memory _SYMBOL)
        ERC20(_NAME, _SYMBOL, 18)
    {
        owner = msg.sender;
    }

    /*///////////////////////////////////////////////////////////////
                    CONTRACT MANAGEMENT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    modifier onlyOwner() {
        if (msg.sender != owner) revert Unauthorized();
        _;
    }

    function setOwner(address newOwner) external onlyOwner {
        //slither-disable-next-line missing-zero-check
        owner = newOwner;
        emit OwnerUpdated(newOwner);
    }

    /*///////////////////////////////////////////////////////////////
                            Zones - can mint
    //////////////////////////////////////////////////////////////*/

    modifier onlyZone() {
        if (!zones[msg.sender]) revert Unauthorized();
        _;
    }

    function addZones(address[] calldata _zones) external onlyOwner {
        uint256 length = _zones.length;
        for (uint256 i; i < length; ) {
            zones[_zones[i]] = true;
            unchecked {
                ++i;
            }
        }
    }

    function removeZone(address zone) external onlyOwner {
        delete zones[zone];
    }

    /*///////////////////////////////////////////////////////////////
                                MINT / BURN
    //////////////////////////////////////////////////////////////*/

    function mint(address receiver, uint256 amount) external onlyZone {
        _mint(receiver, amount);
    }

    function burn(address from, uint256 amount) external onlyZone {
        _burn(from, amount);
    }
}contract Ballot {
    address public owner;

    /*///////////////////////////////////////////////////////////////
                            IMMUTABLES
    //////////////////////////////////////////////////////////////*/

    address public immutable VEFLY;
    address public immutable FLY;

    /*///////////////////////////////////////////////////////////////
                              ZONES
    //////////////////////////////////////////////////////////////*/

    address[] public arrZones;
    mapping(address => bool) public zones;
    mapping(address => uint256) public zonesVotes;

    mapping(address => mapping(address => uint256)) public zonesUserVotes;
    mapping(address => uint256) public userVeFlyUsed;

    /*///////////////////////////////////////////////////////////////
                              EMISSIONS
    //////////////////////////////////////////////////////////////*/

    uint256 public bonusEmissionRate;
    uint256 public rewardSnapshot;
    uint256 public countRewardRate;

    /*///////////////////////////////////////////////////////////////
                              EVENTS
    //////////////////////////////////////////////////////////////*/

    event UpdatedOwner(address indexed owner);

    /*///////////////////////////////////////////////////////////////
                              ERRORS
    //////////////////////////////////////////////////////////////*/

    error Unauthorized();
    error TooSoon();
    error NotEnoughVeFly();

    /*///////////////////////////////////////////////////////////////
                            CONTRACT MANAGEMENT
    //////////////////////////////////////////////////////////////*/

    constructor(address _flyAddress, address _veFlyAddress) {
        owner = msg.sender;
        rewardSnapshot = type(uint256).max;
        FLY = _flyAddress;
        VEFLY = _veFlyAddress;
    }

    modifier onlyOwner() {
        if (owner != msg.sender) revert Unauthorized();
        _;
    }

    function setOwner(address _owner) external onlyOwner {
        owner = _owner;
        emit UpdatedOwner(_owner);
    }

    function openBallot(uint256 _countRewardRate, uint256 _bonusEmissionRate)
        external
        onlyOwner
    {
        rewardSnapshot = block.timestamp;
        countRewardRate = _countRewardRate;
        bonusEmissionRate = _bonusEmissionRate;
    }

    function closeBallot() external onlyOwner {
        rewardSnapshot = type(uint256).max;
    }

    function setBonusEmissionRate(uint256 _bonusEmissionRate)
        external
        onlyOwner
    {
        bonusEmissionRate = _bonusEmissionRate;
    }

    function setCountRewardRate(uint256 _countRewardRate) external onlyOwner {
        countRewardRate = _countRewardRate;
    }

    /*///////////////////////////////////////////////////////////////
                                ZONES
    //////////////////////////////////////////////////////////////*/

    modifier onlyZone() {
        if (!zones[msg.sender]) revert Unauthorized();
        _;
    }

    function addZones(address[] calldata _zones) external onlyOwner {
        uint256 length = _zones.length;
        for (uint256 i; i < length; ) {
            address zone = _zones[i];
            arrZones.push(zone);
            zones[zone] = true;
            unchecked {
                ++i;
            }
        }
    }

    function removeZone(uint256 index) external onlyOwner {
        address removed = arrZones[index];
        arrZones[index] = arrZones[arrZones.length - 1];
        arrZones.pop();
        delete zones[removed];
    }

    /*///////////////////////////////////////////////////////////////
                            VOTING
    //////////////////////////////////////////////////////////////*/

    //slither-disable-next-line costly-loop
    function forceUnvote(address _user) external {
        if (msg.sender != VEFLY) revert Unauthorized();

        uint256 length = arrZones.length;

        for (uint256 i; i < length; ) {
            address zone = arrZones[i];

            uint256 zoneUserVotes = zonesUserVotes[zone][_user];

            if (zoneUserVotes > 0) {
                zonesVotes[zone] -= zoneUserVotes;
                delete userVeFlyUsed[_user];
                delete zonesUserVotes[zone][_user];

                // Done already by veFly on its _forceUncastAllVotes
                // veFly(VEFLY).unsetHasVoted(user)

                Zone(zone).forceUnvote(_user);
            }
            unchecked {
                ++i;
            }
        }
    }

    function _updateVotes(address user, uint256 vefly) internal {
        zonesVotes[msg.sender] =
            zonesVotes[msg.sender] +
            vefly -
            zonesUserVotes[msg.sender][user];

        zonesUserVotes[msg.sender][user] = vefly;
    }

    function vote(address user, uint256 vefly) external onlyZone {
        // veFly Accounting
        uint256 totalVeFly = userVeFlyUsed[user] + vefly;

        if (totalVeFly > veFly(VEFLY).balanceOf(user)) revert NotEnoughVeFly();

        if (vefly > 0) {
            userVeFlyUsed[user] = totalVeFly;

            unchecked {
                _updateVotes(user, zonesUserVotes[msg.sender][user] + vefly);
            }

            // First time he has voted
            if (totalVeFly == vefly) {
                veFly(VEFLY).setHasVoted(user);
            }
        }
    }

    function unvote(address user, uint256 vefly) external onlyZone {
        // veFly Accounting
        uint256 _userVeFlyUsed = userVeFlyUsed[user];
        if (_userVeFlyUsed < vefly) revert NotEnoughVeFly();

        uint256 remainingVeFly;
        unchecked {
            remainingVeFly = _userVeFlyUsed - vefly;
        }

        userVeFlyUsed[user] = remainingVeFly;

        uint256 zoneUserVotes = zonesUserVotes[msg.sender][user];

        if (zoneUserVotes < vefly) revert NotEnoughVeFly();

        unchecked {
            _updateVotes(user, zoneUserVotes - vefly);
        }

        if (remainingVeFly == 0) veFly(VEFLY).unsetHasVoted(user);
    }

    /*///////////////////////////////////////////////////////////////
                            COUNTING
    //////////////////////////////////////////////////////////////*/

    function countReward() public view returns (uint256) {
        uint256 _rewardSnapshot = rewardSnapshot;

        if (block.timestamp < _rewardSnapshot) return 0;

        return countRewardRate * (block.timestamp - _rewardSnapshot);
    }

    function count() external {
        uint256 reward = countReward();
        rewardSnapshot = block.timestamp;

        uint256 totalVotes;
        address[] memory _arrZones = arrZones;
        uint256 length = _arrZones.length;

        for (uint256 i; i < length; ) {
            unchecked {
                totalVotes += zonesVotes[_arrZones[i]];
                ++i;
            }
        }

        for (uint256 i; i < length; ) {
            if (totalVotes == 0) {
                Zone(_arrZones[i]).setBonusEmissionRate(0);
            } else {
                Zone(_arrZones[i]).setBonusEmissionRate(
                    (bonusEmissionRate * zonesVotes[_arrZones[i]]) / totalVotes
                );
            }
            unchecked {
                ++i;
            }
        }

        if (reward > 0) {
            // solhint-disable-next-line avoid-tx-origin
            Fly(FLY).mint(tx.origin, reward);
        }
    }
}
// solhint-disable-next-line
contract veFly {
    /*///////////////////////////////////////////////////////////////
                             METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    address public owner;

    // solhint-disable-next-line const-name-snakecase
    string public constant name = "veFLY";
    // solhint-disable-next-line const-name-snakecase
    string public constant symbol = "veFLY";

    address public immutable FLY;

    /*///////////////////////////////////////////////////////////////
                           FLY/VEFLY GENERATION
    //////////////////////////////////////////////////////////////*/

    struct GenerationDetails {
        uint128 maxRatio;
        uint64 generationRateNumerator;
        uint64 generationRateDenominator;
    }

    GenerationDetails public genDetails;

    mapping(address => uint256) public flyBalanceOf;
    mapping(address => uint256) private veFlyBalance;
    mapping(address => uint256) private userSnapshot;

    /*///////////////////////////////////////////////////////////////
                              VOTING
    //////////////////////////////////////////////////////////////*/

    address[] public arrValidBallots;
    mapping(address => bool) public validBallots;
    mapping(address => mapping(address => bool)) public hasUserVoted;

    /*///////////////////////////////////////////////////////////////
                              ERRORS
    //////////////////////////////////////////////////////////////*/
    error Unauthorized();
    error InvalidAmount();
    error InvalidProposal();

    /*///////////////////////////////////////////////////////////////
                              EVENTS
    //////////////////////////////////////////////////////////////*/
    event UpdatedOwner(address indexed owner);
    event AddedBallot(address indexed ballot);
    event RemovedBallot(address indexed ballot);

    /*///////////////////////////////////////////////////////////////
                            CONTRACT MANAGEMENT
    //////////////////////////////////////////////////////////////*/

    constructor(
        address _flyAddress,
        uint256 _generationRateNumerator,
        uint256 _generationRateDenominator,
        uint256 _maxRatio
    ) {
        owner = msg.sender;

        FLY = _flyAddress;

        genDetails = GenerationDetails({
            maxRatio: uint128(_maxRatio),
            generationRateNumerator: uint64(_generationRateNumerator),
            generationRateDenominator: uint64(_generationRateDenominator)
        });
    }

    modifier onlyOwner() {
        if (owner != msg.sender) revert Unauthorized();
        _;
    }

    function setOwner(address _owner) external onlyOwner {
        owner = _owner;
        emit UpdatedOwner(_owner);
    }

    function setGenerationDetails(
        uint256 _maxRatio,
        uint256 _generationRateNumerator,
        uint256 _generationRateDenominator
    ) external onlyOwner {
        GenerationDetails storage gen = genDetails;
        gen.maxRatio = uint128(_maxRatio);
        gen.generationRateNumerator = uint64(_generationRateNumerator);
        gen.generationRateDenominator = uint64(_generationRateDenominator);
    }

    /*///////////////////////////////////////////////////////////////
                               BALLOTS
    //////////////////////////////////////////////////////////////*/

    modifier onlyBallot() {
        if (!validBallots[msg.sender]) revert Unauthorized();
        _;
    }

    function addBallot(address ballot) external onlyOwner {
        if (!validBallots[ballot]) {
            arrValidBallots.push(ballot);
            validBallots[ballot] = true;
            emit AddedBallot(ballot);
        }
    }

    function removeBallot(uint256 index) external onlyOwner {
        address removed = arrValidBallots[index];

        arrValidBallots[index] = arrValidBallots[arrValidBallots.length - 1];
        arrValidBallots.pop();

        delete validBallots[removed];

        emit RemovedBallot(removed);
    }

    function _forceUncastAllVotes() internal {
        uint256 length = arrValidBallots.length;
        for (uint256 i; i < length; ) {
            address ballot = arrValidBallots[i];
            delete hasUserVoted[ballot][msg.sender];

            Ballot(ballot).forceUnvote(msg.sender);
            unchecked {
                ++i;
            }
        }
    }

    function setHasVoted(address user) external onlyBallot {
        hasUserVoted[msg.sender][user] = true;
    }

    function unsetHasVoted(address user) external onlyBallot {
        delete hasUserVoted[msg.sender][user];
    }

    /*///////////////////////////////////////////////////////////////
                               STAKING
    //////////////////////////////////////////////////////////////*/

    function deposit(uint256 amount) external {
        //slither-disable-next-line incorrect-equality
        if (genDetails.maxRatio == 0) revert Unauthorized();

        // Reset veFly calculations
        veFlyBalance[msg.sender] = balanceOf(msg.sender);
        userSnapshot[msg.sender] = block.timestamp;

        unchecked {
            flyBalanceOf[msg.sender] += amount;
        }

        // slither-disable-next-line unchecked-transfer
        Fly(FLY).transferFrom(msg.sender, address(this), amount);
    }

    function withdraw(uint256 amount) external {
        if (flyBalanceOf[msg.sender] < amount) revert InvalidAmount();

        // Reset veFly calculations
        delete veFlyBalance[msg.sender];
        userSnapshot[msg.sender] = block.timestamp;

        unchecked {
            flyBalanceOf[msg.sender] -= amount;
        }

        _forceUncastAllVotes();

        // slither-disable-next-line unchecked-transfer
        Fly(FLY).transfer(msg.sender, amount);
    }

    /*///////////////////////////////////////////////////////////////
                               veFly
    //////////////////////////////////////////////////////////////*/

    function balanceOf(address account) public view returns (uint256) {
        GenerationDetails memory gen = genDetails;

        uint256 flyBalance = flyBalanceOf[account];

        uint256 veBalance = veFlyBalance[account] +
            ((flyBalance * gen.generationRateNumerator) *
                (block.timestamp - userSnapshot[account])) /
            gen.generationRateDenominator;

        uint256 maxVe = gen.maxRatio * flyBalance;
        if (veBalance > maxVe) {
            return maxVe;
        } else {
            return veBalance;
        }
    }

    function hasUserVotedAny(address account) external view returns (bool) {
        uint256 length = arrValidBallots.length;
        for (uint256 i; i < length; ) {
            if (hasUserVoted[arrValidBallots[i]][account]) return false;
            unchecked {
                ++i;
            }
        }
        return true;
    }
}/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)
library FixedPointMathLib {
    /*///////////////////////////////////////////////////////////////
                    SIMPLIFIED FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.

    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.
    }

    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.
    }

    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.
    }

    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.
    }

    /*///////////////////////////////////////////////////////////////
                    LOW LEVEL FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function mulDivDown(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        assembly {
            // Store x * y in z for now.
            z := mul(x, y)

            // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))
            if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {
                revert(0, 0)
            }

            // Divide z by the denominator.
            z := div(z, denominator)
        }
    }

    function mulDivUp(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        assembly {
            // Store x * y in z for now.
            z := mul(x, y)

            // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))
            if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {
                revert(0, 0)
            }

            // First, divide z - 1 by the denominator and add 1.
            // We allow z - 1 to underflow if z is 0, because we multiply the
            // end result by 0 if z is zero, ensuring we return 0 if z is zero.
            z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1))
        }
    }

    function rpow(
        uint256 x,
        uint256 n,
        uint256 scalar
    ) internal pure returns (uint256 z) {
        assembly {
            switch x
            case 0 {
                switch n
                case 0 {
                    // 0 ** 0 = 1
                    z := scalar
                }
                default {
                    // 0 ** n = 0
                    z := 0
                }
            }
            default {
                switch mod(n, 2)
                case 0 {
                    // If n is even, store scalar in z for now.
                    z := scalar
                }
                default {
                    // If n is odd, store x in z for now.
                    z := x
                }

                // Shifting right by 1 is like dividing by 2.
                let half := shr(1, scalar)

                for {
                    // Shift n right by 1 before looping to halve it.
                    n := shr(1, n)
                } n {
                    // Shift n right by 1 each iteration to halve it.
                    n := shr(1, n)
                } {
                    // Revert immediately if x ** 2 would overflow.
                    // Equivalent to iszero(eq(div(xx, x), x)) here.
                    if shr(128, x) {
                        revert(0, 0)
                    }

                    // Store x squared.
                    let xx := mul(x, x)

                    // Round to the nearest number.
                    let xxRound := add(xx, half)

                    // Revert if xx + half overflowed.
                    if lt(xxRound, xx) {
                        revert(0, 0)
                    }

                    // Set x to scaled xxRound.
                    x := div(xxRound, scalar)

                    // If n is even:
                    if mod(n, 2) {
                        // Compute z * x.
                        let zx := mul(z, x)

                        // If z * x overflowed:
                        if iszero(eq(div(zx, x), z)) {
                            // Revert if x is non-zero.
                            if iszero(iszero(x)) {
                                revert(0, 0)
                            }
                        }

                        // Round to the nearest number.
                        let zxRound := add(zx, half)

                        // Revert if zx + half overflowed.
                        if lt(zxRound, zx) {
                            revert(0, 0)
                        }

                        // Return properly scaled zxRound.
                        z := div(zxRound, scalar)
                    }
                }
            }
        }
    }

    /*///////////////////////////////////////////////////////////////
                        GENERAL NUMBER UTILITIES
    //////////////////////////////////////////////////////////////*/

    function sqrt(uint256 x) internal pure returns (uint256 z) {
        assembly {
            // Start off with z at 1.
            z := 1

            // Used below to help find a nearby power of 2.
            let y := x

            // Find the lowest power of 2 that is at least sqrt(x).
            if iszero(lt(y, 0x100000000000000000000000000000000)) {
                y := shr(128, y) // Like dividing by 2 ** 128.
                z := shl(64, z) // Like multiplying by 2 ** 64.
            }
            if iszero(lt(y, 0x10000000000000000)) {
                y := shr(64, y) // Like dividing by 2 ** 64.
                z := shl(32, z) // Like multiplying by 2 ** 32.
            }
            if iszero(lt(y, 0x100000000)) {
                y := shr(32, y) // Like dividing by 2 ** 32.
                z := shl(16, z) // Like multiplying by 2 ** 16.
            }
            if iszero(lt(y, 0x10000)) {
                y := shr(16, y) // Like dividing by 2 ** 16.
                z := shl(8, z) // Like multiplying by 2 ** 8.
            }
            if iszero(lt(y, 0x100)) {
                y := shr(8, y) // Like dividing by 2 ** 8.
                z := shl(4, z) // Like multiplying by 2 ** 4.
            }
            if iszero(lt(y, 0x10)) {
                y := shr(4, y) // Like dividing by 2 ** 4.
                z := shl(2, z) // Like multiplying by 2 ** 2.
            }
            if iszero(lt(y, 0x8)) {
                // Equivalent to 2 ** z.
                z := shl(1, z)
            }

            // Shifting right by 1 is like dividing by 2.
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))

            // Compute a rounded down version of z.
            let zRoundDown := div(x, z)

            // If zRoundDown is smaller, use it.
            if lt(zRoundDown, z) {
                z := zRoundDown
            }
        }
    }
}
abstract contract Zone {
    /*///////////////////////////////////////////////////////////////
                            IMMUTABLE STORAGE
    //////////////////////////////////////////////////////////////*/
    address public immutable FLY;
    address public immutable VE_FLY;
    address public immutable HOPPER;

    /*///////////////////////////////////////////////////////////////
                                HOPPERS
    //////////////////////////////////////////////////////////////*/
    string public LEVEL_GAUGE_KEY;

    mapping(uint256 => address) public hopperOwners;
    mapping(uint256 => uint256) public hopperBaseShare;
    mapping(address => uint256) public rewards;

    address public owner;
    address public ballot;
    bool public emergency;

    /*///////////////////////////////////////////////////////////////
                        Accounting/Rewards NFT
    //////////////////////////////////////////////////////////////*/
    uint256 public emissionRate;

    uint256 public totalBaseShare;
    uint256 public lastUpdatedTime;
    uint256 public rewardPerShareStored;

    mapping(address => uint256) public baseSharesBalance;
    mapping(address => uint256) public userRewardPerSharePaid;
    mapping(address => uint256) public userMaxFlyGeneration;

    mapping(address => uint256) public generatedPerShareStored;
    mapping(uint256 => uint256) public tokenCapFilledPerShare;

    uint256 public flyLevelCapRatio;

    /*///////////////////////////////////////////////////////////////
                        Accounting/Rewards veFLY
    //////////////////////////////////////////////////////////////*/
    uint256 public bonusEmissionRate;

    uint256 public totalVeShare;
    uint256 public lastBonusUpdatedTime;
    uint256 public bonusRewardPerShareStored;

    mapping(address => uint256) public veSharesBalance;
    mapping(address => uint256) public userBonusRewardPerSharePaid;
    mapping(address => uint256) public veFlyBalance;

    /*///////////////////////////////////////////////////////////////
                                ERRORS
    //////////////////////////////////////////////////////////////*/
    error Unauthorized();
    error UnfitHopper();
    error WrongTokenID();
    error NoHopperStaked();

    /*///////////////////////////////////////////////////////////////
                                EVENTS
    //////////////////////////////////////////////////////////////*/

    event UpdatedOwner(address indexed owner);
    event UpdatedBallot(address indexed ballot);
    event UpdatedEmission(uint256 emissionRate);

    /*///////////////////////////////////////////////////////////////
                           CONTRACT MANAGEMENT
    //////////////////////////////////////////////////////////////*/
    constructor(
        address fly,
        address vefly,
        address hopper
    ) {
        owner = msg.sender;

        FLY = fly;
        VE_FLY = vefly;
        HOPPER = hopper;

        flyLevelCapRatio = 3;
        LEVEL_GAUGE_KEY = "LEVEL_GAUGE_KEY";
        lastUpdatedTime = block.timestamp;
        lastBonusUpdatedTime = block.timestamp;
    }

    modifier onlyOwner() {
        if (msg.sender != owner) revert Unauthorized();
        _;
    }

    modifier onlyBallotOrOwner() {
        if (msg.sender != owner && msg.sender != ballot) revert Unauthorized();
        _;
    }

    function setOwner(address _owner) external onlyOwner {
        owner = _owner;
        emit UpdatedOwner(_owner);
    }

    function enableEmergency() external onlyOwner {
        // no going back
        emergency = true;
    }

    function setBallot(address _ballot) external onlyOwner {
        ballot = _ballot;
        emit UpdatedBallot(_ballot);
    }

    function setEmissionRate(uint256 _emissionRate) external onlyOwner {
        _updateBaseRewardPerShareStored();

        emissionRate = _emissionRate;
        emit UpdatedEmission(_emissionRate);
    }

    function setBonusEmissionRate(uint256 _bonusEmissionRate)
        external
        onlyBallotOrOwner
    {
        _updateBonusRewardPerShareStored();

        bonusEmissionRate = _bonusEmissionRate;
    }

    function setFlyLevelCapRatio(uint256 _flyLevelCapRatio) external onlyOwner {
        flyLevelCapRatio = _flyLevelCapRatio;
    }

    /*///////////////////////////////////////////////////////////////
                        HOPPER GENERATION CAP
    //////////////////////////////////////////////////////////////*/

    function getUserBonusGeneratedFly(
        address account,
        uint256 _totalUserBonusShares
    ) public view returns (uint256, uint256) {
        // userMaxFlyGeneration gets updated at _updateAccountBaseReward which happens before this is called
        uint256 cappedFly = userMaxFlyGeneration[account] / 1e12;
        uint256 generatedFly = ((_totalUserBonusShares *
            (bonusRewardPerShare() - userBonusRewardPerSharePaid[account])) /
            1e18);

        return (
            generatedFly > cappedFly ? cappedFly : generatedFly,
            generatedFly
        );
    }

    function getUserGeneratedFly(address account, uint256 _totalUserBaseShares)
        public
        view
        returns (uint256, uint256)
    {
        uint256 cappedFly = userMaxFlyGeneration[account] / 1e12;
        uint256 generatedFly = ((_totalUserBaseShares *
            (baseRewardPerShare() - userRewardPerSharePaid[account])) / 1e18);

        return (
            generatedFly > cappedFly ? cappedFly : generatedFly,
            generatedFly
        );
    }

    function _updateHopperGenerationData(
        address _account,
        uint256 _totalAccountKindShares,
        bool isBonus
    ) internal returns (uint256) {
        uint256 cappedFly;
        uint256 generatedFly;

        if (isBonus) {
            (cappedFly, generatedFly) = getUserBonusGeneratedFly(
                _account,
                _totalAccountKindShares
            );

            // Makes calculations easier, since we don't need to add another
            //    state keeping track of generatedPerVeshare
            generatedPerShareStored[_account] += FixedPointMathLib.mulDivUp(
                generatedFly,
                1e12,
                baseSharesBalance[_account]
            );
        } else {
            (cappedFly, generatedFly) = getUserGeneratedFly(
                _account,
                _totalAccountKindShares
            );
            generatedPerShareStored[_account] += FixedPointMathLib.mulDivUp(
                generatedFly,
                1e12,
                _totalAccountKindShares
            );
        }
        return cappedFly;
    }

    /*///////////////////////////////////////////////////////////////
                           REWARDS ACCOUNTING
    //////////////////////////////////////////////////////////////*/

    function _updateAccountRewards(address _account) internal {
        _updateAccountBaseReward(_account, baseSharesBalance[_account]);
        _updateAccountBonusReward(_account, veSharesBalance[_account]);
    }

    /*///////////////////////////////////////////////////////////////
                           BASE REWARDS
    //////////////////////////////////////////////////////////////*/

    function baseRewardPerShare() public view returns (uint256) {
        uint256 _totalBaseShare = totalBaseShare;
        //slither-disable-next-line incorrect-equality
        if (_totalBaseShare == 0) {
            return rewardPerShareStored;
        }
        return
            rewardPerShareStored +
            (((block.timestamp - lastUpdatedTime) * emissionRate * 1e18) /
                _totalBaseShare);
    }

    function _updateBaseRewardPerShareStored() internal {
        rewardPerShareStored = baseRewardPerShare();
        lastUpdatedTime = block.timestamp;
    }

    function _updateAccountBaseReward(
        address _account,
        uint256 _totalAccountShares
    ) internal {
        _updateBaseRewardPerShareStored();

        if (_totalAccountShares > 0) {
            uint256 cappedFly = _updateHopperGenerationData(
                _account,
                _totalAccountShares,
                false
            );

            unchecked {
                rewards[_account] += cappedFly;
            }
            userMaxFlyGeneration[_account] -= cappedFly * 1e12;
        }

        userRewardPerSharePaid[_account] = rewardPerShareStored;
    }

    /*///////////////////////////////////////////////////////////////
                           BONUS REWARDS
    //////////////////////////////////////////////////////////////*/

    function bonusRewardPerShare() public view returns (uint256) {
        uint256 _totalVeShare = totalVeShare;
        //slither-disable-next-line incorrect-equality
        if (_totalVeShare == 0) {
            return bonusRewardPerShareStored;
        }
        return
            bonusRewardPerShareStored +
            (((block.timestamp - lastBonusUpdatedTime) *
                bonusEmissionRate *
                1e18) / _totalVeShare);
    }

    function _updateBonusRewardPerShareStored() internal {
        bonusRewardPerShareStored = bonusRewardPerShare();
        lastBonusUpdatedTime = block.timestamp;
    }

    function _updateAccountBonusReward(
        address _account,
        uint256 _totalAccountShares
    ) internal {
        _updateBonusRewardPerShareStored();

        if (_totalAccountShares > 0) {
            uint256 cappedFly = _updateHopperGenerationData(
                _account,
                _totalAccountShares,
                true
            );

            unchecked {
                rewards[_account] += cappedFly;
            }
            userMaxFlyGeneration[_account] -= cappedFly * 1e12;
        }
        userBonusRewardPerSharePaid[_account] = bonusRewardPerShareStored;
    }

    /*///////////////////////////////////////////////////////////////
                    NAMES & LEVELING
    //////////////////////////////////////////////////////////////*/

    function payAction(uint256 flyRequired, bool useOwnRewards) internal {
        if (useOwnRewards) {
            uint256 _rewards = rewards[msg.sender];

            // Pays from the pending rewards
            if (_rewards >= flyRequired) {
                unchecked {
                    rewards[msg.sender] -= flyRequired;
                    flyRequired = 0;
                }
            } else if (_rewards > 0) {
                delete rewards[msg.sender];
                unchecked {
                    flyRequired -= _rewards;
                }
            }
        }

        // Sender pays for action. Will revert, if not enough balance
        if (flyRequired > 0) {
            Fly(FLY).burn(msg.sender, flyRequired);
        }
    }

    function changeHopperName(
        uint256 tokenId,
        string calldata name,
        bool useOwnRewards
    ) external {
        if (useOwnRewards) {
            _updateAccountRewards(msg.sender);
        }

        // Check hopper ownership
        address zoneHopperOwner = hopperOwners[tokenId];
        if (zoneHopperOwner != msg.sender) {
            // Saves gas in certain paths
            if (HopperNFT(HOPPER).ownerOf(tokenId) != msg.sender) {
                revert WrongTokenID();
            }
        }

        payAction(
            HopperNFT(HOPPER).changeHopperName(tokenId, name), // returns price
            useOwnRewards
        );
    }

    function _getLevelUpCost(uint256 level) internal pure returns (uint256) {
        unchecked {
            ++level;

            if (level == 100) {
                return 598 ether;
            }
            // x**(1.43522) / 7.5 for x >= 21 where x is next level
            // packing costs in 7 bits
            else if (level > 1 && level < 21) {
                return (level * 1e18) >> 1;
            } else if (level >= 21 && level < 51) {
                return
                    ((0x1223448501f3c74e1b3464c172c54a9426488901e3c70d183058a >>
                        (7 * (level - 21))) & 127) * 1e18;
            } else if (level >= 51 && level < 81) {
                return
                    ((0x23c68b0e14180f9ebc76e9c376cd5a3262c17ae5ab15a9509d325 >>
                        (7 * (level - 51))) & 127) * 1e18;
            } else if (level >= 81 && level < 101) {
                return
                    ((0xc58705ebb6ed59af5aad3a5467ce9b2e549 >>
                        (7 * (level - 81))) & 127) * 1e18;
            } else {
                return type(uint256).max;
            }
        }
    }

    //slither-disable-next-line reentrancy-no-eth
    function levelUp(uint256 tokenId, bool useOwnRewards) external {
        HopperNFT IHOPPER = HopperNFT(HOPPER);
        if (useOwnRewards) {
            _updateAccountRewards(msg.sender);
        }

        // Check hopper ownership
        address zoneHopperOwner = hopperOwners[tokenId];
        if (zoneHopperOwner != msg.sender) {
            // Saves gas in certain paths
            if (IHOPPER.ownerOf(tokenId) != msg.sender) {
                revert WrongTokenID();
            }
        }

        HopperNFT.Hopper memory hopper = IHOPPER.getHopper(tokenId);

        // Update owners shares if hopper is staked
        if (zoneHopperOwner == msg.sender) {
            // Updated above if true
            if (!useOwnRewards) {
                _updateAccountRewards(msg.sender);
            }

            // Fill hopper gauge so we can find whats the remaining
            (, uint256 remainingGauge, ) = _updateHopperGaugeFill(tokenId);

            // Calculate the baseShare that we need to subtract from the user and total
            uint256 prevHopperShare = _calculateBaseShare(hopper);
            unchecked {
                ++hopper.level;
            }
            // Calculate the baseShare that we need to add to the user and total
            uint256 newHopperShare = _calculateBaseShare(hopper);

            // Calculate new baseShares
            uint256 diff = newHopperShare - prevHopperShare;
            unchecked {
                uint256 newBaseShare = baseSharesBalance[msg.sender] + diff;
                baseSharesBalance[msg.sender] = newBaseShare;

                totalBaseShare += diff;

                // Update new value of veShares
                _updateVeShares(newBaseShare, 0, false);
            }

            uint256 boostFill = 0;
            uint256 userMax = userMaxFlyGeneration[msg.sender];
            if (userMax < remainingGauge) {
                boostFill = remainingGauge - userMax;
            }

            // Update the new cap
            userMaxFlyGeneration[msg.sender] += (_getGaugeLimit(hopper.level) *
                1e12 -
                (remainingGauge - boostFill));

            // Make sure getLevelUpCost is passed its current level
            unchecked {
                --hopper.level;
            }
        }

        payAction(getLevelUpCost(hopper.level), useOwnRewards);

        IHOPPER.levelUp(tokenId);

        // Reset Hopper internal gauge
        IHOPPER.setData(LEVEL_GAUGE_KEY, tokenId, 0);
    }

    /*///////////////////////////////////////////////////////////////
                    STAKE / UNSTAKE NFT && CLAIM FLY
    //////////////////////////////////////////////////////////////*/

    function enter(uint256[] calldata tokenIds) external {
        if (emergency) revert Unauthorized();

        _updateAccountRewards(msg.sender);

        uint256 prevBaseShares = baseSharesBalance[msg.sender];
        uint256 _baseShares = prevBaseShares;
        uint256 numTokens = tokenIds.length;

        uint256 flyCapIncrease;

        uint256 _generatedPerShareStored = generatedPerShareStored[msg.sender];
        for (uint256 i; i < numTokens; ) {
            uint256 tokenId = tokenIds[i];

            // Resets this hopper generation tracking
            tokenCapFilledPerShare[tokenId] = _generatedPerShareStored;

            (
                HopperNFT.Hopper memory hopper,
                uint256 hopperGauge,
                uint256 gaugeLimit
            ) = _getHopperAndGauge(tokenId);

            if (!canEnter(hopper)) revert UnfitHopper();

            unchecked {
                // Increment user shares
                _baseShares += _calculateBaseShare(hopper);
            }

            // Update the maximum FLY this user can generate
            flyCapIncrease += (gaugeLimit - hopperGauge);

            // Hopper Accounting
            hopperOwners[tokenId] = msg.sender;
            HopperNFT(HOPPER).transferFrom(msg.sender, address(this), tokenId);

            unchecked {
                ++i;
            }
        }

        baseSharesBalance[msg.sender] = _baseShares;
        unchecked {
            userMaxFlyGeneration[msg.sender] += flyCapIncrease;

            totalBaseShare = totalBaseShare + _baseShares - prevBaseShares;
        }

        _updateVeShares(_baseShares, 0, false);
    }

    //slither-disable-next-line reentrancy-no-eth
    function exit(uint256[] calldata tokenIds) external {
        if (emergency) revert Unauthorized();

        _updateAccountRewards(msg.sender);

        uint256 prevBaseShares = baseSharesBalance[msg.sender];
        uint256 _baseShares = prevBaseShares;
        uint256 numTokens = tokenIds.length;

        uint256 flyCapDecrease;
        uint256 userMax = userMaxFlyGeneration[msg.sender];

        uint256[] memory rTokensRemaining = new uint256[](tokenIds.length);
        uint256[] memory rTokensLimit = new uint256[](tokenIds.length);

        for (uint256 i; i < numTokens; ) {
            uint256 tokenId = tokenIds[i];

            // Can the user unstake this hopper
            if (hopperOwners[tokenId] != msg.sender) revert WrongTokenID();

            (
                uint256 _hopperShare,
                uint256 _remainingGauge,
                uint256 _gaugeLimit
            ) = _updateHopperGaugeFill(tokenId);

            // Decrement user shares
            _baseShares -= _hopperShare;

            // Update the maximum FLY this user can generate
            flyCapDecrease += _remainingGauge;

            // To fill gauge later
            rTokensRemaining[i] = _remainingGauge;
            rTokensLimit[i] = _gaugeLimit;

            // Hopper Accounting
            //slither-disable-next-line costly-loop
            delete hopperOwners[tokenId];
            HopperNFT(HOPPER).transferFrom(address(this), msg.sender, tokenId);

            unchecked {
                ++i;
            }
        }

        baseSharesBalance[msg.sender] = _baseShares;

        if (userMax < flyCapDecrease) {
            // Being boosted, we need to go back and refill uncapped tokens
            refill(
                tokenIds,
                rTokensRemaining,
                rTokensLimit,
                flyCapDecrease - userMax
            );
            delete userMaxFlyGeneration[msg.sender];
        } else if (_baseShares == 0) {
            delete userMaxFlyGeneration[msg.sender];
        } else {
            userMaxFlyGeneration[msg.sender] -= flyCapDecrease;
        }

        unchecked {
            totalBaseShare = totalBaseShare + _baseShares - prevBaseShares;
        }
        _updateVeShares(_baseShares, 0, false);
    }

    function refill(
        uint256[] calldata tokenIds,
        uint256[] memory remaining,
        uint256[] memory limit,
        uint256 leftover
    ) internal {
        uint256 length = tokenIds.length;

        for (uint256 i; i < length; ) {
            if (remaining[i] != 0) {
                if (leftover > remaining[i]) {
                    HopperNFT(HOPPER).setData(
                        LEVEL_GAUGE_KEY,
                        tokenIds[i],
                        bytes32(limit[i] / 1e12)
                    );
                    leftover -= remaining[i];
                } else {
                    HopperNFT(HOPPER).setData(
                        LEVEL_GAUGE_KEY,
                        tokenIds[i],
                        bytes32((limit[i] - remaining[i] + leftover) / 1e12)
                    );
                    leftover = 0;
                    break;
                }
            }

            unchecked {
                ++i;
            }
        }
    }

    function emergencyExit(uint256[] calldata tokenIds, address user) external {
        if (!emergency) revert Unauthorized();

        uint256 numTokens = tokenIds.length;
        for (uint256 i; i < numTokens; ) {
            uint256 tokenId = tokenIds[i];

            // Can the user unstake this hopper
            if (hopperOwners[tokenId] != user) revert WrongTokenID();

            //slither-disable-next-line costly-loop
            delete hopperOwners[tokenId];
            HopperNFT(HOPPER).transferFrom(address(this), user, tokenId);

            unchecked {
                ++i;
            }
        }
    }

    /*///////////////////////////////////////////////////////////////
                            CLAIMING
    //////////////////////////////////////////////////////////////*/

    function claimable(address _account) external view returns (uint256) {
        uint256 cappedFly = userMaxFlyGeneration[_account] / 1e12;

        (uint256 gen, ) = getUserGeneratedFly(
            _account,
            baseSharesBalance[_account]
        );
        (uint256 bonusGen, ) = getUserBonusGeneratedFly(
            _account,
            veSharesBalance[_account]
        );

        gen += bonusGen;
        cappedFly = gen > cappedFly ? cappedFly : gen;

        unchecked {
            return rewards[_account] + cappedFly;
        }
    }

    function claim() external {
        _updateAccountRewards(msg.sender);

        uint256 _accountRewards = rewards[msg.sender];
        delete rewards[msg.sender];

        Fly(FLY).mint(msg.sender, _accountRewards);
    }

    /*///////////////////////////////////////////////////////////////
                            VOTE veFLY 
    //////////////////////////////////////////////////////////////*/

    function _calcVeShare(uint256 accountTotalBaseShares, uint256 vefly)
        internal
        pure
        returns (uint256)
    {
        return FixedPointMathLib.sqrt(accountTotalBaseShares * vefly);
    }

    //slither-disable-next-line reentrancy-no-eth
    function _updateVeShares(
        uint256 baseShares,
        uint256 veFlyAmount,
        bool incrementVeFlyAmount
    ) internal {
        uint256 beforeVeShare = veSharesBalance[msg.sender];
        if (veFlyAmount > 0) {
            // Ballot checks if the user has the veFly amount necessary, otherwise reverts
            if (incrementVeFlyAmount) {
                //slither-disable-next-line reentrancy-benign
                Ballot(ballot).vote(msg.sender, veFlyAmount);
                unchecked {
                    veFlyBalance[msg.sender] += veFlyAmount;
                }
            } else {
                //slither-disable-next-line reentrancy-benign
                Ballot(ballot).unvote(msg.sender, veFlyAmount);
                veFlyBalance[msg.sender] -= veFlyAmount;
            }
        }

        uint256 currentVeShare = _calcVeShare(
            baseShares,
            veFlyBalance[msg.sender]
        );
        veSharesBalance[msg.sender] = currentVeShare;

        unchecked {
            totalVeShare = totalVeShare + currentVeShare - beforeVeShare;
        }
    }

    function vote(uint256 veFlyAmount, bool recount) external {
        _updateAccountBonusReward(msg.sender, veSharesBalance[msg.sender]);

        _updateVeShares(baseSharesBalance[msg.sender], veFlyAmount, true);

        if (recount) Ballot(ballot).count();
    }

    function unvote(uint256 veFlyAmount, bool recount) external {
        _updateAccountBonusReward(msg.sender, veSharesBalance[msg.sender]);

        _updateVeShares(baseSharesBalance[msg.sender], veFlyAmount, false);

        if (recount) Ballot(ballot).count();
    }

    function forceUnvote(address user) external {
        if (msg.sender != ballot) revert Unauthorized();

        uint256 userVeShares = veSharesBalance[user];
        _updateAccountBonusReward(user, userVeShares);

        totalVeShare -= userVeShares;
        delete veSharesBalance[user];
        delete veFlyBalance[user];
    }

    /*///////////////////////////////////////////////////////////////
                    HELPER GAUGE FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    // _remaining is scaled with 1e12
    function _updateHopperGaugeFill(uint256 tokenId)
        internal
        returns (
            uint256 _hopperShare,
            uint256 _remaining,
            uint256
        )
    {
        uint256 _generatedPerShareStored = generatedPerShareStored[msg.sender];

        // Resets this hopper generation tracking
        uint256 filledCapPerShare = _generatedPerShareStored -
            tokenCapFilledPerShare[tokenId];

        tokenCapFilledPerShare[tokenId] = _generatedPerShareStored;

        (
            HopperNFT.Hopper memory hopper,
            uint256 prevHopperGauge,
            uint256 gaugeLimit
        ) = _getHopperAndGauge(tokenId);

        _hopperShare = _calculateBaseShare(hopper);

        uint256 flyGeneratedAndBurned = prevHopperGauge +
            filledCapPerShare *
            _hopperShare;

        uint256 currentGauge = flyGeneratedAndBurned > gaugeLimit
            ? gaugeLimit
            : flyGeneratedAndBurned;

        // Update the HOPPER gauge
        HopperNFT(HOPPER).setData(
            LEVEL_GAUGE_KEY,
            tokenId,
            bytes32(currentGauge / 1e12)
        );

        return (_hopperShare, (gaugeLimit - currentGauge), gaugeLimit);
    }

    function _getGaugeLimit(uint256 level) internal view returns (uint256) {
        if (level == 1) return 1.5 ether;
        if (level == 100) return 294 ether;
        unchecked {
            return flyLevelCapRatio * _getLevelUpCost(level - 1);
        }
    }

    function _getHopperAndGauge(uint256 _tokenId)
        internal
        view
        returns (
            HopperNFT.Hopper memory,
            uint256, // hopperGauge
            uint256 // gaugeLimit
        )
    {
        string[] memory arrData = new string[](1);
        arrData[0] = LEVEL_GAUGE_KEY;
        (HopperNFT.Hopper memory hopper, bytes32[] memory _data) = HopperNFT(
            HOPPER
        ).getHopperWithData(arrData, _tokenId);

        return (
            hopper,
            uint256(_data[0]) * 1e12,
            _getGaugeLimit(hopper.level) * 1e12
        );
    }

    function getHopperAndGauge(uint256 tokenId)
        external
        view
        returns (
            HopperNFT.Hopper memory hopper,
            uint256 hopperGauge,
            uint256 gaugeLimit
        )
    {
        (hopper, hopperGauge, gaugeLimit) = _getHopperAndGauge(tokenId);
        return (hopper, hopperGauge / 1e12, gaugeLimit / 1e12);
    }

    /*///////////////////////////////////////////////////////////////
                                VIEW
    //////////////////////////////////////////////////////////////*/

    function getLevelUpCost(uint256 currentLevel)
        public
        pure
        returns (uint256)
    {
        return _getLevelUpCost(currentLevel);
    }

    /*///////////////////////////////////////////////////////////////
                    ZONE SPECIFIC FUNCTIONALITY
    //////////////////////////////////////////////////////////////*/

    function canEnter(HopperNFT.Hopper memory hopper)
        public
        pure
        virtual
        returns (bool)
    {} // solhint-disable-line

    function _calculateBaseShare(HopperNFT.Hopper memory hopper)
        internal
        pure
        virtual
        returns (uint256)
    {} // solhint-disable-line
}

contract Swamp is Zone {
    constructor(
        address fly,
        address vefly,
        address hopper
    ) Zone(fly, vefly, hopper) {}

    // solhint-disable-next-line
    function canEnter(HopperNFT.Hopper memory hopper)
        public
        pure
        override
        returns (bool)
    {
        return true;
    }

    function _calculateBaseShare(HopperNFT.Hopper memory hopper)
        internal
        pure
        override
        returns (uint256)
    {
        unchecked {
            return uint256(hopper.vitality) * uint256(hopper.level);
        }
    }
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"fly","type":"address"},{"internalType":"address","name":"vefly","type":"address"},{"internalType":"address","name":"hopper","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NoHopperStaked","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnfitHopper","type":"error"},{"inputs":[],"name":"WrongTokenID","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"ballot","type":"address"}],"name":"UpdatedBallot","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"emissionRate","type":"uint256"}],"name":"UpdatedEmission","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"UpdatedOwner","type":"event"},{"inputs":[],"name":"FLY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HOPPER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LEVEL_GAUGE_KEY","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VE_FLY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ballot","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseRewardPerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"baseSharesBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bonusEmissionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bonusRewardPerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bonusRewardPerShareStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint200","name":"level","type":"uint200"},{"internalType":"uint16","name":"rebirths","type":"uint16"},{"internalType":"uint8","name":"strength","type":"uint8"},{"internalType":"uint8","name":"agility","type":"uint8"},{"internalType":"uint8","name":"vitality","type":"uint8"},{"internalType":"uint8","name":"intelligence","type":"uint8"},{"internalType":"uint8","name":"fertility","type":"uint8"}],"internalType":"struct HopperNFT.Hopper","name":"hopper","type":"tuple"}],"name":"canEnter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"name","type":"string"},{"internalType":"bool","name":"useOwnRewards","type":"bool"}],"name":"changeHopperName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"claimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emergency","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"address","name":"user","type":"address"}],"name":"emergencyExit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emissionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enableEmergency","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"enter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"exit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flyLevelCapRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"forceUnvote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"generatedPerShareStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getHopperAndGauge","outputs":[{"components":[{"internalType":"uint200","name":"level","type":"uint200"},{"internalType":"uint16","name":"rebirths","type":"uint16"},{"internalType":"uint8","name":"strength","type":"uint8"},{"internalType":"uint8","name":"agility","type":"uint8"},{"internalType":"uint8","name":"vitality","type":"uint8"},{"internalType":"uint8","name":"intelligence","type":"uint8"},{"internalType":"uint8","name":"fertility","type":"uint8"}],"internalType":"struct HopperNFT.Hopper","name":"hopper","type":"tuple"},{"internalType":"uint256","name":"hopperGauge","type":"uint256"},{"internalType":"uint256","name":"gaugeLimit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"currentLevel","type":"uint256"}],"name":"getLevelUpCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"_totalUserBonusShares","type":"uint256"}],"name":"getUserBonusGeneratedFly","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"_totalUserBaseShares","type":"uint256"}],"name":"getUserGeneratedFly","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"hopperBaseShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"hopperOwners","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastBonusUpdatedTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUpdatedTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool","name":"useOwnRewards","type":"bool"}],"name":"levelUp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerShareStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_ballot","type":"address"}],"name":"setBallot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bonusEmissionRate","type":"uint256"}],"name":"setBonusEmissionRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_emissionRate","type":"uint256"}],"name":"setEmissionRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_flyLevelCapRatio","type":"uint256"}],"name":"setFlyLevelCapRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenCapFilledPerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBaseShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalVeShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"veFlyAmount","type":"uint256"},{"internalType":"bool","name":"recount","type":"bool"}],"name":"unvote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userBonusRewardPerSharePaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userMaxFlyGeneration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerSharePaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"veFlyBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"veSharesBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"veFlyAmount","type":"uint256"},{"internalType":"bool","name":"recount","type":"bool"}],"name":"vote","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60e06040523480156200001157600080fd5b5060405162003bac38038062003bac83398101604081905262000034916200017c565b600480546001600160a01b031916331790556001600160a01b0380841660805280831660a052811660c0526003600f908155604080518082019091528181526e4c4556454c5f47415547455f4b455960881b6020909101908152849184918491620000a291600091620000b9565b505042600881905560125550620002039350505050565b828054620000c790620001c6565b90600052602060002090601f016020900481019282620000eb576000855562000136565b82601f106200010657805160ff191683800117855562000136565b8280016001018555821562000136579182015b828111156200013657825182559160200191906001019062000119565b506200014492915062000148565b5090565b5b8082111562000144576000815560010162000149565b80516001600160a01b03811681146200017757600080fd5b919050565b6000806000606084860312156200019257600080fd5b6200019d846200015f565b9250620001ad602085016200015f565b9150620001bd604085016200015f565b90509250925092565b600181811c90821680620001db57607f821691505b60208210811415620001fd57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05161392562000287600039600081816104cf0152818161084901528181611027015281816115c7015281816117bd015281816118b601528181611e3a0152818161217e0152818161257a015281816126940152612997015260006104430152600081816107840152818161128a01526124d101526139256000f3fe608060405234801561001057600080fd5b50600436106103365760003560e01c806379f409e0116101b2578063ad914e2e116100f9578063d881e959116100a2578063e42c4e631161007c578063e42c4e63146107a6578063e532a154146107ae578063ee569ba9146107b6578063f5544eb7146107d657600080fd5b8063d881e9591461074c578063dee935681461075f578063e1a61a0c1461077f57600080fd5b8063c9d27afe116100d3578063c9d27afe14610701578063caa6fea414610714578063d051bfa31461073957600080fd5b8063ad914e2e146106c3578063bf856895146106e5578063bf9bc0b2146106ee57600080fd5b806396afc4501161015b578063a49a3e1b11610135578063a49a3e1b1461067b578063ab20355c14610690578063ac3910a2146106a357600080fd5b806396afc4501461064c5780639d4c93c414610655578063a1bdb15e1461066857600080fd5b80638da5cb5b1161018c5780638da5cb5b146105f95780638eb3be2814610619578063968c603d1461062c57600080fd5b806379f409e0146105915780637e2d9af8146105b9578063818ae1ce146105d957600080fd5b80633cfa989e116102815780635834c36d1161022a5780635d35b5d5116102045780635d35b5d51461053e5780636351520e14610547578063769022a31461055a5780637944135d1461057e57600080fd5b80635834c36d14610502578063591adce61461050b5780635c1ab8c01461051e57600080fd5b80634b905e3f1161025b5780634b905e3f146104ca5780634b9ca431146104f15780634e71d92d146104fa57600080fd5b80633cfa989e1461048e578063402914f5146104ae57806343aba89d146104c157600080fd5b80631c1502c4116102e35780632677d07f116102bd5780632677d07f1461043e5780632df97550146104655780633bad0f711461048557600080fd5b80631c1502c4146103ba578063201e29a0146103c3578063215e0f4d1461041e57600080fd5b80630c679fa0116103145780630c679fa01461037f57806313af40351461039457806318c08f26146103a757600080fd5b80630700037d1461033b5780630ab747f01461036e5780630b24216314610377575b600080fd5b61035b610349366004612f48565b60036020526000908152604090205481565b6040519081526020015b60405180910390f35b61035b60095481565b61035b6107e9565b61039261038d366004612f75565b610847565b005b6103926103a2366004612f48565b610cdd565b6103926103b5366004612fe6565b610d9d565b61035b60135481565b6103f96103d1366004613028565b60016020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610365565b61035b61042c366004612f48565b600a6020526000908152604090205481565b6103f97f000000000000000000000000000000000000000000000000000000000000000081565b61035b610473366004612f48565b60146020526000908152604090205481565b61035b60075481565b61035b61049c366004612f48565b600d6020526000908152604090205481565b61035b6104bc366004612f48565b61112e565b61035b60105481565b6103f97f000000000000000000000000000000000000000000000000000000000000000081565b61035b60115481565b610392611221565b61035b60125481565b610392610519366004612f75565b6112e9565b61035b61052c366004612f48565b600c6020526000908152604090205481565b61035b600f5481565b610392610555366004613028565b6113ab565b61056e610568366004613110565b50600190565b6040519015158152602001610365565b61039261058c366004612fe6565b611401565b6105a461059f3660046131c8565b61168a565b60408051928352602083019190915201610365565b61035b6105c7366004612f48565b60166020526000908152604090205481565b61035b6105e7366004612f48565b600b6020526000908152604090205481565b6004546103f99073ffffffffffffffffffffffffffffffffffffffff1681565b6103926106273660046131f4565b61173c565b61035b61063a366004613028565b60026020526000908152604090205481565b61035b60065481565b610392610663366004613028565b611938565b610392610676366004613028565b6119bc565b610683611a50565b60405161036591906132ec565b6105a461069e3660046131c8565b611ade565b6005546103f99073ffffffffffffffffffffffffffffffffffffffff1681565b6106d66106d1366004613028565b611b54565b604051610365939291906132ff565b61035b60085481565b61035b6106fc366004613028565b611bca565b61039261070f366004612f75565b611bdb565b60055461056e9074010000000000000000000000000000000000000000900460ff1681565b610392610747366004612f48565b611c11565b61039261075a366004613398565b611cd1565b61035b61076d366004613028565b600e6020526000908152604090205481565b6103f97f000000000000000000000000000000000000000000000000000000000000000081565b610392611ea2565b61035b611f34565b61035b6107c4366004612f48565b60156020526000908152604090205481565b6103926107e4366004612f48565b611f8c565b600754600090806107fc57505060095490565b806006546008544261080e919061341e565b6108189190613435565b61082a90670de0b6b3a7640000613435565b6108349190613472565b60095461084191906134ad565b91505090565b7f000000000000000000000000000000000000000000000000000000000000000081156108775761087733612059565b60008381526001602052604090205473ffffffffffffffffffffffffffffffffffffffff16338114610981576040517f6352211e00000000000000000000000000000000000000000000000000000000815260048101859052339073ffffffffffffffffffffffffffffffffffffffff841690636352211e90602401602060405180830381865afa158015610910573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093491906134c5565b73ffffffffffffffffffffffffffffffffffffffff1614610981576040517f5483a62900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f5c5503530000000000000000000000000000000000000000000000000000000081526004810185905260009073ffffffffffffffffffffffffffffffffffffffff841690635c5503539060240160e060405180830381865afa1580156109ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a1391906135aa565b905073ffffffffffffffffffffffffffffffffffffffff8216331415610b9c5783610a4157610a4133612059565b6000610a4c866120be565b50835160808501516001820178ffffffffffffffffffffffffffffffffffffffffffffffffff90811680885293955060ff909116911681029250026000610a93838361341e565b336000908152600a6020526040812080548301908190556007805484019055919250610ac190829080612243565b50336000908152600c602052604081205485811015610ae757610ae4818761341e565b91505b610af1828761341e565b8751610b179078ffffffffffffffffffffffffffffffffffffffffffffffffff166123f5565b610b269064e8d4a51000613435565b610b30919061341e565b336000908152600c602052604081208054909190610b4f9084906134ad565b909155505086517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0178ffffffffffffffffffffffffffffffffffffffffffffffffff1687525050505050505b610bcd610bc7826000015178ffffffffffffffffffffffffffffffffffffffffffffffffff16611bca565b8561243e565b6040517f0ce90ec20000000000000000000000000000000000000000000000000000000081526004810186905273ffffffffffffffffffffffffffffffffffffffff841690630ce90ec290602401600060405180830381600087803b158015610c3557600080fd5b505af1158015610c49573d6000803e3d6000fd5b50506040517f3d68b4b500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86169250633d68b4b59150610ca490600090899082906004016136eb565b600060405180830381600087803b158015610cbe57600080fd5b505af1158015610cd2573d6000803e3d6000fd5b505050505050505050565b60045473ffffffffffffffffffffffffffffffffffffffff163314610d2e576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f957090e72c0a1b3ebf83c682eb8c1f88c2a18cd0578b91a819efb28859f0f3a390600090a250565b60055474010000000000000000000000000000000000000000900460ff1615610df2576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfb33612059565b336000908152600a6020908152604080832054600c90925282205490918291849190818367ffffffffffffffff811115610e3757610e37613041565b604051908082528060200260200182016040528015610e60578160200160208202803683370190505b50905060008767ffffffffffffffff811115610e7e57610e7e613041565b604051908082528060200260200182016040528015610ea7578160200160208202803683370190505b50905060005b858110156110925760008a8a83818110610ec957610ec9613710565b60209081029290920135600081815260019093526040909220549192505073ffffffffffffffffffffffffffffffffffffffff163314610f35576040517f5483a62900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806000610f43846120be565b91945092509050610f54838c61341e565b9a50610f60828a6134ad565b985081878681518110610f7557610f75613710565b60200260200101818152505080868681518110610f9457610f94613710565b6020908102919091018101919091526000858152600190915260409081902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055517f23b872dd0000000000000000000000000000000000000000000000000000000081523060048201523360248201526044810185905273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90606401600060405180830381600087803b15801561106b57600080fd5b505af115801561107f573d6000803e3d6000fd5b5050505084600101945050505050610ead565b50336000908152600a60205260409020869055838310156110d8576110c3898984846110be888a61341e565b61252a565b336000908152600c6020526040812055611117565b856110f257336000908152600c6020526040812055611117565b336000908152600c60205260408120805486929061111190849061341e565b90915550505b6007805487018890039055610cd286600080612243565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600c602052604081205481906111669064e8d4a5100090613472565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600a60205260408120549192509061119b90859061168a565b5073ffffffffffffffffffffffffffffffffffffffff8516600090815260146020526040812054919250906111d1908690611ade565b5090506111de81836134ad565b91508282116111ed57816111ef565b825b73ffffffffffffffffffffffffffffffffffffffff909516600090815260036020526040902054909401949350505050565b61122a33612059565b336000818152600360205260408082208054929055517f40c10f190000000000000000000000000000000000000000000000000000000081526004810192909252602482018190529073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906340c10f1990604401600060405180830381600087803b1580156112ce57600080fd5b505af11580156112e2573d6000803e3d6000fd5b5050505050565b3360008181526014602052604090205461130391906127c0565b336000908152600a602052604081205461131e918490612243565b80156113a757600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306661abd6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561138e57600080fd5b505af11580156113a2573d6000803e3d6000fd5b505050505b5050565b60045473ffffffffffffffffffffffffffffffffffffffff1633146113fc576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600f55565b60055474010000000000000000000000000000000000000000900460ff1615611456576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61145f33612059565b336000908152600a6020908152604080832054600d90925282205490918291849190815b8381101561164757600088888381811061149f5761149f613710565b602090810292909201356000818152600e909352604083208690559250819050806114c984612881565b9250925092506114d7600190565b61150d576040517f0ce023b900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251608084015160ff1678ffffffffffffffffffffffffffffffffffffffffffffffffff9091160290980197611543828261341e565b61154d90886134ad565b6000858152600160205260409081902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163390811790915590517f23b872dd0000000000000000000000000000000000000000000000000000000081526004810191909152306024820152604481018690529097507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906323b872dd90606401600060405180830381600087803b15801561162057600080fd5b505af1158015611634573d6000803e3d6000fd5b5050505084600101945050505050611483565b50336000908152600a60209081526040808320879055600c9091528120805484019055600780548601879003905561168190859080612243565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040812054819081906116c49064e8d4a5100090613472565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600b602052604081205491925090670de0b6b3a7640000906117006107e9565b61170a919061341e565b6117149087613435565b61171e9190613472565b905081811161172d578061172f565b815b93509150505b9250929050565b801561174b5761174b33612059565b60008481526001602052604090205473ffffffffffffffffffffffffffffffffffffffff16338114611875576040517f6352211e00000000000000000000000000000000000000000000000000000000815260048101869052339073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611804573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061182891906134c5565b73ffffffffffffffffffffffffffffffffffffffff1614611875576040517f5483a62900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fc60fb6a70000000000000000000000000000000000000000000000000000000081526112e29073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063c60fb6a7906118ef9089908990899060040161373f565b6020604051808303816000875af115801561190e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119329190613793565b8361243e565b60045473ffffffffffffffffffffffffffffffffffffffff163314801590611978575060055473ffffffffffffffffffffffffffffffffffffffff163314155b156119af576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119b7612acb565b601055565b60045473ffffffffffffffffffffffffffffffffffffffff163314611a0d576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611a15612adc565b60068190556040518181527f90e51e492b1841b8ed3d459463d02d171ced752c7fcd84a9dd79f90098166aec9060200160405180910390a150565b60008054611a5d906135c6565b80601f0160208091040260200160405190810160405280929190818152602001828054611a89906135c6565b8015611ad65780601f10611aab57610100808354040283529160200191611ad6565b820191906000526020600020905b815481529060010190602001808311611ab957829003601f168201915b505050505081565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c602052604081205481908190611b189064e8d4a5100090613472565b73ffffffffffffffffffffffffffffffffffffffff861660009081526015602052604081205491925090670de0b6b3a764000090611700611f34565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081018290529080611b9784612881565b9194509250905082611bae64e8d4a5100084613472565b611bbd64e8d4a5100084613472565b9250925092509193909250565b6000611bd582612aed565b92915050565b33600081815260146020526040902054611bf591906127c0565b336000908152600a602052604090205461131e90836001612243565b60045473ffffffffffffffffffffffffffffffffffffffff163314611c62576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f605aa74980dc92c245d8959d233f8c2d7062d874e49326a42e7418279cc8d1f890600090a250565b60055474010000000000000000000000000000000000000000900460ff16611d25576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160005b818110156112e2576000858583818110611d4557611d45613710565b60209081029290920135600081815260019093526040909220549192505073ffffffffffffffffffffffffffffffffffffffff858116911614611db4576040517f5483a62900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600160205260409081902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8581166024830152604482018390527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90606401600060405180830381600087803b158015611e7e57600080fd5b505af1158015611e92573d6000803e3d6000fd5b5050505081600101915050611d29565b60045473ffffffffffffffffffffffffffffffffffffffff163314611ef3576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600580547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b60115460009080611f4757505060135490565b8060105460125442611f59919061341e565b611f639190613435565b611f7590670de0b6b3a7640000613435565b611f7f9190613472565b60135461084191906134ad565b60055473ffffffffffffffffffffffffffffffffffffffff163314611fdd576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526014602052604090205461200d82826127c0565b806011600082825461201f919061341e565b90915550505073ffffffffffffffffffffffffffffffffffffffff1660009081526014602090815260408083208390556016909152812055565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600a602052604090205461208a908290612c41565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601460205260409020546120bb9082906127c0565b50565b336000908152600d6020908152604080832054848452600e9092528220548291829182906120ec908361341e565b6000878152600e60205260408120849055909150808061210b89612881565b8251608084015160ff1678ffffffffffffffffffffffffffffffffffffffffffffffffff909116029a509194509250905060006121488986613435565b61215290846134ad565b905060008282116121635781612165565b825b905073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016633d68b4b560008d6121b564e8d4a5100086613472565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526121f0939291906004016136eb565b600060405180830381600087803b15801561220a57600080fd5b505af115801561221e573d6000803e3d6000fd5b5050505089818461222f919061341e565b909c909b5092995091975050505050505050565b3360009081526014602052604090205482156123b4578115612304576005546040517f5f74bbde0000000000000000000000000000000000000000000000000000000081523360048201526024810185905273ffffffffffffffffffffffffffffffffffffffff90911690635f74bbde90604401600060405180830381600087803b1580156122d157600080fd5b505af11580156122e5573d6000803e3d6000fd5b5050336000908152601660205260409020805486019055506123b49050565b6005546040517f02aa9be20000000000000000000000000000000000000000000000000000000081523360048201526024810185905273ffffffffffffffffffffffffffffffffffffffff909116906302aa9be290604401600060405180830381600087803b15801561237657600080fd5b505af115801561238a573d6000803e3d6000fd5b505033600090815260166020526040812080548794509092506123ae90849061341e565b90915550505b336000908152601660205260408120546123cf908690612d02565b336000908152601460205260409020819055601180549091019290920390915550505050565b6000816001141561240f57506714d1120d7b160000919050565b81606414156124285750680ff011d2523cd80000919050565b61243460018303612aed565b600f540292915050565b8015612496573360009081526003602052604090205482811061247857336000908152600360205260408120805494909403909355612494565b8015612494573360009081526003602052604081205591829003915b505b81156113a7576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018390527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639dc29fac90604401600060405180830381600087803b15801561138e57600080fd5b8360005b818110156116815784818151811061254857612548613710565b60200260200101516000146127b85784818151811061256957612569613710565b6020026020010151831115612692577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633d68b4b560008989858181106125c8576125c8613710565b9050602002013564e8d4a510008886815181106125e7576125e7613710565b60200260200101516125f99190613472565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b168152612634939291906004016136eb565b600060405180830381600087803b15801561264e57600080fd5b505af1158015612662573d6000803e3d6000fd5b5050505084818151811061267857612678613710565b60200260200101518361268b919061341e565b92506127b8565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633d68b4b560008989858181106126e2576126e2613710565b9050602002013564e8d4a51000878a878151811061270257612702613710565b60200260200101518a888151811061271c5761271c613710565b602002602001015161272e919061341e565b61273891906134ad565b6127429190613472565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815261277d939291906004016136eb565b600060405180830381600087803b15801561279757600080fd5b505af11580156127ab573d6000803e3d6000fd5b5050505060009250611681565b60010161252e565b6127c8612acb565b80156128545760006127dc83836001612d1d565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260036020526040902080548201905590506128188164e8d4a51000613435565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c60205260408120805490919061284d90849061341e565b9091555050505b5060135473ffffffffffffffffffffffffffffffffffffffff909116600090815260156020526040902055565b6040805160e08101825260008082526020808301829052828401829052606083018290526080830182905260a0830182905260c0830182905283516001808252818601909552929391928392839282015b60608152602001906001900390816128d2579050509050600080546128f6906135c6565b80601f0160208091040260200160405190810160405280929190818152602001828054612922906135c6565b801561296f5780601f106129445761010080835404028352916020019161296f565b820191906000526020600020905b81548152906001019060200180831161295257829003601f168201915b50505050508160008151811061298757612987613710565b60200260200101819052506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630d51186584896040518363ffffffff1660e01b81526004016129f09291906137ac565b600060405180830381865afa158015612a0d573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052612a539190810190613833565b915091508181600081518110612a6b57612a6b613710565b602002602001015160001c64e8d4a51000612a869190613435565b8351612aac9078ffffffffffffffffffffffffffffffffffffffffffffffffff166123f5565b612abb9064e8d4a51000613435565b9550955095505050509193909250565b612ad3611f34565b60135542601255565b612ae46107e9565b60095542600855565b60010160006064821415612b0b575068206aeac7a903980000919050565b600182118015612b1b5750601582105b15612b315750670de0b6b3a76400000260011c90565b60158210158015612b425750603382105b15612b8057601582036007027a01223448501f3c74e1b3464c172c54a9426488901e3c70d183058a901c607f16670de0b6b3a7640000029050919050565b60338210158015612b915750605182105b15612bcf57603382036007027a023c68b0e14180f9ebc76e9c376cd5a3262c17ae5ab15a9509d325901c607f16670de0b6b3a7640000029050919050565b60518210158015612be05750606582105b15612c155760518203600702710c58705ebb6ed59af5aad3a5467ce9b2e549901c607f16670de0b6b3a7640000029050919050565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff919050565b919050565b612c49612adc565b8015612cd5576000612c5d83836000612d1d565b73ffffffffffffffffffffffffffffffffffffffff841660009081526003602052604090208054820190559050612c998164e8d4a51000613435565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c602052604081208054909190612cce90849061341e565b9091555050505b5060095473ffffffffffffffffffffffffffffffffffffffff9091166000908152600b6020526040902055565b6000612d16612d118385613435565b612e12565b9392505050565b60008060008315612daf57612d328686611ade565b73ffffffffffffffffffffffffffffffffffffffff88166000908152600a60205260409020549193509150612d6f90829064e8d4a5100090612ef8565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600d602052604081208054909190612da49084906134ad565b90915550612e099050565b612db9868661168a565b9092509050612dce8164e8d4a5100087612ef8565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600d602052604081208054909190612e039084906134ad565b90915550505b50949350505050565b6001817001000000000000000000000000000000008110612e385760409190911b9060801c5b680100000000000000008110612e535760209190911b9060401c5b6401000000008110612e6a5760109190911b9060201c5b620100008110612e7f5760089190911b9060101c5b6101008110612e935760049190911b9060081c5b60108110612ea65760029190911b9060041c5b60088110612eb5578160011b91505b5080820401600190811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c80820481811015612ef2578091505b50919050565b828202811515841585830485141716612f1057600080fd5b6001826001830304018115150290509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146120bb57600080fd5b600060208284031215612f5a57600080fd5b8135612d1681612f26565b80358015158114612c3c57600080fd5b60008060408385031215612f8857600080fd5b82359150612f9860208401612f65565b90509250929050565b60008083601f840112612fb357600080fd5b50813567ffffffffffffffff811115612fcb57600080fd5b6020830191508360208260051b850101111561173557600080fd5b60008060208385031215612ff957600080fd5b823567ffffffffffffffff81111561301057600080fd5b61301c85828601612fa1565b90969095509350505050565b60006020828403121561303a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156130b7576130b7613041565b604052919050565b78ffffffffffffffffffffffffffffffffffffffffffffffffff811681146120bb57600080fd5b61ffff811681146120bb57600080fd5b60ff811681146120bb57600080fd5b8035612c3c816130f6565b600060e0828403121561312257600080fd5b60405160e0810181811067ffffffffffffffff8211171561314557613145613041565b6040528235613153816130bf565b81526020830135613163816130e6565b60208201526040830135613176816130f6565b60408201526060830135613189816130f6565b606082015261319a60808401613105565b60808201526131ab60a08401613105565b60a08201526131bc60c08401613105565b60c08201529392505050565b600080604083850312156131db57600080fd5b82356131e681612f26565b946020939093013593505050565b6000806000806060858703121561320a57600080fd5b84359350602085013567ffffffffffffffff8082111561322957600080fd5b818701915087601f83011261323d57600080fd5b81358181111561324c57600080fd5b88602082850101111561325e57600080fd5b60208301955080945050505061327660408601612f65565b905092959194509250565b6000815180845260005b818110156132a75760208185018101518683018201520161328b565b818111156132b9576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612d166020830184613281565b60006101208201905078ffffffffffffffffffffffffffffffffffffffffffffffffff855116825261ffff602086015116602083015260ff604086015116604083015260ff606086015116606083015260ff608086015116608083015260a085015161337060a084018260ff169052565b5060c085015161338560c084018260ff169052565b5060e08201939093526101000152919050565b6000806000604084860312156133ad57600080fd5b833567ffffffffffffffff8111156133c457600080fd5b6133d086828701612fa1565b90945092505060208401356133e481612f26565b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613430576134306133ef565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561346d5761346d6133ef565b500290565b6000826134a8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600082198211156134c0576134c06133ef565b500190565b6000602082840312156134d757600080fd5b8151612d1681612f26565b8051612c3c816130f6565b600060e082840312156134ff57600080fd5b60405160e0810181811067ffffffffffffffff8211171561352257613522613041565b80604052508091508251613535816130bf565b81526020830151613545816130e6565b60208201526040830151613558816130f6565b6040820152606083015161356b816130f6565b606082015261357c608084016134e2565b608082015261358d60a084016134e2565b60a082015261359e60c084016134e2565b60c08201525092915050565b600060e082840312156135bc57600080fd5b612d1683836134ed565b600181811c908216806135da57607f821691505b60208210811415612ef2577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8054600090600181811c908083168061362e57607f831692505b6020808410821415613669577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8388526020880182801561368457600181146136b3576136de565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008716825282820197506136de565b60008981526020902060005b878110156136d8578154848201529086019084016136bf565b83019850505b5050505050505092915050565b6060815260006136fe6060830186613614565b60208301949094525060400152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b83815260406020820152816040820152818360608301376000818301606090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010192915050565b6000602082840312156137a557600080fd5b5051919050565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b83811015613821577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa088870301855261380f868351613281565b955093820193908201906001016137d5565b50509490940194909452949350505050565b600080610100838503121561384757600080fd5b61385184846134ed565b915060e083015167ffffffffffffffff8082111561386e57600080fd5b818501915085601f83011261388257600080fd5b815160208282111561389657613896613041565b8160051b92506138a7818401613070565b82815292840181019281810190898511156138c157600080fd5b948201945b848610156138df578551825294820194908201906138c6565b809650505050505050925092905056fea2646970667358221220af9fc0370af7d4a13f6e0f22d41c44e1dca6501e3e09795b54d77bf471cb938264736f6c634300080c003300000000000000000000000078ea3fef1c1f07348199bf44f45b803b9b0dbe28000000000000000000000000baf9a6f8a8afd4be0d85ca40f025bf364fa273240000000000000000000000004245a1bd84eb5f3ebc115c2edf57e50667f98b0b

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

00000000000000000000000078ea3fef1c1f07348199bf44f45b803b9b0dbe28000000000000000000000000baf9a6f8a8afd4be0d85ca40f025bf364fa273240000000000000000000000004245a1bd84eb5f3ebc115c2edf57e50667f98b0b

-----Decoded View---------------
Arg [0] : fly (address): 0x78ea3fef1c1f07348199bf44f45b803b9b0dbe28
Arg [1] : vefly (address): 0xbaf9a6f8a8afd4be0d85ca40f025bf364fa27324
Arg [2] : hopper (address): 0x4245a1bd84eb5f3ebc115c2edf57e50667f98b0b

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000078ea3fef1c1f07348199bf44f45b803b9b0dbe28
Arg [1] : 000000000000000000000000baf9a6f8a8afd4be0d85ca40f025bf364fa27324
Arg [2] : 0000000000000000000000004245a1bd84eb5f3ebc115c2edf57e50667f98b0b


Deployed ByteCode Sourcemap

96648:610:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68662:42;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;571:25:1;;;559:2;544:18;68662:42:0;;;;;;;;69096:35;;;;;;75465:428;;;:::i;80994:2561::-;;;;;;:::i;:::-;;:::i;:::-;;71475:122;;;;;;:::i;:::-;;:::i;85507:2330::-;;;;;;:::i;:::-;;:::i;69806:40::-;;;;;;68551:47;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;2200:42:1;2188:55;;;2170:74;;2158:2;2143:18;68551:47:0;2024:226:1;69140:52:0;;;;;;:::i;:::-;;;;;;;;;;;;;;68253:31;;;;;69855:50;;;;;;:::i;:::-;;;;;;;;;;;;;;69023:29;;;;;;69327:58;;;;;;:::i;:::-;;;;;;;;;;;;;;89703:572;;;;;;:::i;:::-;;:::i;69689:32::-;;;;;;68291:31;;;;;69730:27;;;;;;90283:228;;;:::i;69764:35::-;;;;;;92390:272;;;;;;:::i;:::-;;:::i;69263:55::-;;;;;;:::i;:::-;;;;;;;;;;;;;;69458:31;;;;;;72290:130;;;;;;:::i;:::-;;:::i;96837:157::-;;;;;;:::i;:::-;-1:-1:-1;96982:4:0;;96837:157;;;;4632:14:1;;4625:22;4607:41;;4595:2;4580:18;96837:157:0;4467:187:1;83760:1688:0;;;;;;:::i;:::-;;:::i;73238:483::-;;;;;;:::i;:::-;;:::i;:::-;;;;5153:25:1;;;5209:2;5194:18;;5187:34;;;;5126:18;73238:483:0;4979:248:1;69981:47:0;;;;;;:::i;:::-;;;;;;;;;;;;;;69199:57;;;;;;:::i;:::-;;;;;;;;;;;;;;68713:20;;;;;;;;;79099:686;;;;;;:::i;:::-;;:::i;68605:50::-;;;;;;:::i;:::-;;;;;;;;;;;;;;68987:27;;;;;;72070:212;;;;;;:::i;:::-;;:::i;71856:206::-;;;;;;:::i;:::-;;:::i;68513:29::-;;;:::i;:::-;;;;;;;:::i;72618:612::-;;;;;;:::i;:::-;;:::i;68740:21::-;;;;;;;;;95392:369;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;69059:30::-;;;;;;95950:163;;;;;;:::i;:::-;;:::i;92113:269::-;;;;;;:::i;:::-;;:::i;68768:21::-;;;;;;;;;;;;71720:128;;;;;;:::i;:::-;;:::i;88877:637::-;;;;;;:::i;:::-;;:::i;69392:57::-;;;;;;:::i;:::-;;;;;;;;;;;;;;68218:28;;;;;71605:107;;;:::i;76870:458::-;;;:::i;69912:62::-;;;;;;:::i;:::-;;;;;;;;;;;;;;92670:339;;;;;;:::i;:::-;;:::i;75465:428::-;75562:14;;75516:7;;75647:20;75643:80;;-1:-1:-1;;75691:20:0;;;75465:428::o;75643:80::-;75869:15;75829:12;;75810:15;;75792;:33;;;;:::i;:::-;75791:50;;;;:::i;:::-;:57;;75844:4;75791:57;:::i;:::-;75790:94;;;;:::i;:::-;75753:20;;:132;;;;:::i;:::-;75733:152;;;75465:428;:::o;80994:2561::-;81098:6;81116:79;;;;81150:33;81172:10;81150:21;:33::i;:::-;81242:23;81268:21;;;:12;:21;;;;;;;;81323:10;81304:29;;81300:204;;81397:24;;;;;;;;571:25:1;;;81425:10:0;;81397:38;:15;;;;;544:18:1;;81397:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:38;;;81393:100;;81463:14;;;;;;;;;;;;;;81393:100;81549:26;;;;;;;;571:25:1;;;81516:30:0;;81549:17;;;;;;544:18:1;;81549:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;81516:59;-1:-1:-1;81645:29:0;;;81664:10;81645:29;81641:1706;;;81734:13;81729:88;;81768:33;81790:10;81768:21;:33::i;:::-;81905:22;81933:31;81956:7;81933:22;:31::i;:::-;-1:-1:-1;97223:12:0;;97196:15;;;;82167:14;;;97215:21;82167:14;;;;;;81902:62;;-1:-1:-1;97188:24:0;;;;97215:21;;97188:48;;;-1:-1:-1;97188:48:0;82070:23;82418:32;97188:48;;82418:32;:::i;:::-;82535:10;82494:20;82517:29;;;:17;:29;;;;;;;:36;;82572:44;;;;82637:14;:22;;;;;;82403:47;;-1:-1:-1;82729:39:0;;82517:36;;82494:20;82729:15;:39::i;:::-;-1:-1:-1;82875:10:0;82800:17;82854:32;;;:20;:32;;;;;;82905:24;;;82901:101;;;82962:24;82979:7;82962:14;:24;:::i;:::-;82950:36;;82901:101;83163:26;83180:9;83163:14;:26;:::i;:::-;83105:12;;83090:28;;;;:14;:28::i;:::-;:52;;83138:4;83090:52;:::i;:::-;:100;;;;:::i;:::-;83074:10;83053:32;;;;:20;:32;;;;;:138;;:32;;;:138;;;;;:::i;:::-;;;;-1:-1:-1;;83306:14:0;;;;;;;;-1:-1:-1;;;;;;81641:1706:0;83359:54;83369:28;83384:6;:12;;;83369:28;;:14;:28::i;:::-;83399:13;83359:9;:54::i;:::-;83426:24;;;;;;;;571:25:1;;;83426:15:0;;;;;;544:18:1;;83426:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;83503:44:0;;;;;:15;;;;-1:-1:-1;83503:15:0;;-1:-1:-1;83503:44:0;;83519:15;;83536:7;;83519:15;;83503:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81057:2498;;;80994:2561;;:::o;71475:122::-;71281:5;;;;71267:10;:19;71263:46;;71295:14;;;;;;;;;;;;;;71263:46;71539:5:::1;:14:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;71569:20:::1;::::0;::::1;::::0;-1:-1:-1;;71569:20:0::1;71475:122:::0;:::o;85507:2330::-;85574:9;;;;;;;85570:36;;;85592:14;;;;;;;;;;;;;;85570:36;85619:33;85641:10;85619:21;:33::i;:::-;85708:10;85665:22;85690:29;;;:17;:29;;;;;;;;;85876:20;:32;;;;;;85690:29;;;;85797:8;;85665:22;;85797:8;85957:30;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85957:30:0;-1:-1:-1;85921:66:0;-1:-1:-1;85998:29:0;86044:8;86030:30;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;86030:30:0;;85998:62;;86078:9;86073:1007;86093:9;86089:1;:13;86073:1007;;;86121:15;86139:8;;86148:1;86139:11;;;;;;;:::i;:::-;;;;;;;;;;86220:21;;;;:12;:21;;;;;;;;86139:11;;-1:-1:-1;;86220:35:0;:21;86245:10;86220:35;86216:62;;86264:14;;;;;;;;;;;;;;86216:62;86314:20;86353:23;86395:19;86432:31;86455:7;86432:22;:31::i;:::-;86295:168;;-1:-1:-1;86295:168:0;-1:-1:-1;86295:168:0;-1:-1:-1;86518:27:0;86295:168;86518:27;;:::i;:::-;;-1:-1:-1;86624:33:0;86642:15;86624:33;;:::i;:::-;;;86732:15;86710:16;86727:1;86710:19;;;;;;;;:::i;:::-;;;;;;:37;;;;;86780:11;86762:12;86775:1;86762:15;;;;;;;;:::i;:::-;;;;;;;;;;;:29;;;;86902:21;;;;:12;:21;;;;;;;;86895:28;;;;;;86938:66;;;;86977:4;86938:66;;;13810:34:1;86984:10:0;13860:18:1;;;13853:43;13912:18;;;13905:34;;;86895:28:0;86948:6;86938:30;;;;13722:18:1;;86938:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87050:3;;;;;86106:974;;;;86073:1007;;;-1:-1:-1;87110:10:0;87092:29;;;;:17;:29;;;;;:43;;;87152:24;;;87148:522;;;87270:157;87295:8;;87322:16;87357:12;87388:24;87405:7;87388:14;:24;:::i;:::-;87270:6;:157::i;:::-;87470:10;87449:32;;;;:20;:32;;;;;87442:39;87148:522;;;87503:16;87499:171;;87564:10;87543:32;;;;:20;:32;;;;;87536:39;87499:171;;;87629:10;87608:32;;;;:20;:32;;;;;:50;;87644:14;;87608:32;:50;;87644:14;;87608:50;:::i;:::-;;;;-1:-1:-1;;87499:171:0;87724:14;;;:28;;:45;;;87707:62;;87791:38;87741:11;-1:-1:-1;;87791:15:0;:38::i;89703:572::-;89803:30;;;89763:7;89803:30;;;:20;:30;;;;;;89763:7;;89803:37;;89836:4;;89803:37;:::i;:::-;89928:27;;;89854:11;89928:27;;;:17;:27;;;;;;89783:57;;-1:-1:-1;89854:11:0;89871:95;;89905:8;;89871:19;:95::i;:::-;-1:-1:-1;90062:25:0;;;89978:16;90062:25;;;:15;:25;;;;;;89853:113;;-1:-1:-1;89978:16:0;90000:98;;90039:8;;90000:24;:98::i;:::-;-1:-1:-1;89977:121:0;-1:-1:-1;90111:15:0;89977:121;90111:15;;:::i;:::-;;;90155:9;90149:3;:15;:33;;90179:3;90149:33;;;90167:9;90149:33;90227:17;;;;;;;;:7;:17;;;;;;:29;;;;89703:572;-1:-1:-1;;;;89703:572:0:o;90283:228::-;90320:33;90342:10;90320:21;:33::i;:::-;90400:10;90366:23;90392:19;;;:7;:19;;;;;;;;90422:26;;;90461:42;;;;;;;14124:74:1;;;;14214:18;;;14207:34;;;90392:19:0;;90465:3;90461:13;;;;14097:18:1;;90461:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90309:202;90283:228::o;92390:272::-;92487:10;92499:27;;;;:15;:27;;;;;;92461:66;;92487:10;92461:25;:66::i;:::-;92574:10;92556:29;;;;:17;:29;;;;;;92540:66;;92587:11;;92540:15;:66::i;:::-;92623:7;92619:35;;;92639:6;;;;;;;;;;;92632:20;;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92619:35;92390:272;;:::o;72290:130::-;71281:5;;;;71267:10;:19;71263:46;;71295:14;;;;;;;;;;;;;;71263:46;72376:16:::1;:36:::0;72290:130::o;83760:1688::-;83828:9;;;;;;;83824:36;;;83846:14;;;;;;;;;;;;;;83824:36;83873:33;83895:10;83873:21;:33::i;:::-;83962:10;83919:22;83944:29;;;:17;:29;;;;;;;;;84149:23;:35;;;;;;83944:29;;;;84051:8;;83919:22;;84195:963;84215:9;84211:1;:13;84195:963;;;84243:15;84261:8;;84270:1;84261:11;;;;;;;:::i;:::-;;;;;;;;;;84344:31;;;;:22;:31;;;;;;:58;;;84261:11;-1:-1:-1;84344:31:0;;-1:-1:-1;84344:31:0;84561:27;84261:11;84561:18;:27::i;:::-;84419:169;;;;;;84610:16;96982:4;;96837:157;84610:16;84605:43;;84635:13;;;;;;;;;;;;;;84605:43;97223:12;;97196:15;;;;97188:24;;97215:21;;;;97188:48;84736:42;;;;84891:24;84904:11;84891:10;:24;:::i;:::-;84872:44;;;;:::i;:::-;84967:21;;;;:12;:21;;;;;;;:34;;;;84991:10;84967:34;;;;;;85016:66;;;;;;;;13810:34:1;;;;85067:4:0;13860:18:1;;;13853:43;13912:18;;;13905:34;;;84872:44:0;;-1:-1:-1;85026:6:0;84967:34;85016:30;;;;13722:18:1;;85016:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85128:3;;;;;84228:930;;;;84195:963;;;-1:-1:-1;85188:10:0;85170:29;;;;:17;:29;;;;;;;;:43;;;85249:20;:32;;;;;:50;;;;;;85333:14;;;:28;;:45;;;85316:62;;85402:38;;85202:11;;85170:29;85402:15;:38::i;:::-;83813:1635;;;;;83760:1688;;:::o;73238:483::-;73416:29;;;73362:7;73416:29;;;:20;:29;;;;;;73362:7;;;;73416:36;;73448:4;;73416:36;:::i;:::-;73548:31;;;73463:20;73548:31;;;:22;:31;;;;;;73396:56;;-1:-1:-1;73463:20:0;73584:4;;73525:20;:18;:20::i;:::-;:54;;;;:::i;:::-;73488:92;;:20;:92;:::i;:::-;73487:101;;;;:::i;:::-;73463:126;;73639:9;73624:12;:24;:51;;73663:12;73624:51;;;73651:9;73624:51;73602:111;-1:-1:-1;73690:12:0;-1:-1:-1;;73238:483:0;;;;;;:::o;79099:686::-;79242:13;79238:79;;;79272:33;79294:10;79272:21;:33::i;:::-;79364:23;79390:21;;;:12;:21;;;;;;;;79445:10;79426:29;;79422:214;;79519:34;;;;;;;;571:25:1;;;79557:10:0;;79519:48;79529:6;79519:25;;;;544:18:1;;79519:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:48;;;79515:110;;79595:14;;;;;;;;;;;;;;79515:110;79672:49;;;;;79648:129;;79672:34;79682:6;79672:34;;;;:49;;79707:7;;79716:4;;;;79672:49;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;79753:13;79648:9;:129::i;72070:212::-;71395:5;;;;71381:10;:19;;;;:43;;-1:-1:-1;71418:6:0;;;;71404:10;:20;;71381:43;71377:70;;;71433:14;;;;;;;;;;;;;;71377:70;72189:34:::1;:32;:34::i;:::-;72236:17;:38:::0;72070:212::o;71856:206::-;71281:5;;;;71267:10;:19;71263:46;;71295:14;;;;;;;;;;;;;;71263:46;71934:33:::1;:31;:33::i;:::-;71980:12;:28:::0;;;72024:30:::1;::::0;571:25:1;;;72024:30:0::1;::::0;559:2:1;544:18;72024:30:0::1;;;;;;;71856:206:::0;:::o;68513:29::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;72618:612::-;72905:29;;;72746:7;72905:29;;;:20;:29;;;;;;72746:7;;;;72905:36;;72937:4;;72905:36;:::i;:::-;73039;;;72952:20;73039:36;;;:27;:36;;;;;;72885:56;;-1:-1:-1;72952:20:0;73093:4;;73015:21;:19;:21::i;95392:369::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95661:27:0;95680:7;95661:18;:27::i;:::-;95625:63;;-1:-1:-1;95625:63:0;-1:-1:-1;95625:63:0;-1:-1:-1;95625:63:0;95715:18;95729:4;95625:63;95715:18;:::i;:::-;95735:17;95748:4;95735:10;:17;:::i;:::-;95699:54;;;;;;95392:369;;;;;:::o;95950:163::-;96044:7;96076:29;96092:12;96076:15;:29::i;:::-;96069:36;95950:163;-1:-1:-1;;95950:163:0:o;92113:269::-;92208:10;92220:27;;;;:15;:27;;;;;;92182:66;;92208:10;92182:25;:66::i;:::-;92295:10;92277:29;;;;:17;:29;;;;;;92261:65;;92308:11;92321:4;92261:15;:65::i;71720:128::-;71281:5;;;;71267:10;:19;71263:46;;71295:14;;;;;;;;;;;;;;71263:46;71786:6:::1;:16:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;71818:22:::1;::::0;::::1;::::0;-1:-1:-1;;71818:22:0::1;71720:128:::0;:::o;88877:637::-;88968:9;;;;;;;88963:37;;88986:14;;;;;;;;;;;;;;88963:37;89033:8;89013:17;89059:448;89079:9;89075:1;:13;89059:448;;;89107:15;89125:8;;89134:1;89125:11;;;;;;;:::i;:::-;;;;;;;;;;89206:21;;;;:12;:21;;;;;;;;89125:11;;-1:-1:-1;;89206:29:0;;;;:21;;:29;89202:56;;89244:14;;;;;;;;;;;;;;89202:56;89335:21;;;;:12;:21;;;;;;;89328:28;;;;;;89371:60;;;;89410:4;89371:60;;;13810:34:1;89328:28:0;13880:15:1;;;13860:18;;;13853:43;13912:18;;;13905:34;;;89381:6:0;89371:30;;;;13722:18:1;;89371:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89477:3;;;;;89092:415;89059:448;;71605:107;71281:5;;;;71267:10;:19;71263:46;;71295:14;;;;;;;;;;;;;;71263:46;71688:9:::1;:16:::0;;;::::1;::::0;::::1;::::0;;71605:107::o;76870:458::-;76966:12;;76922:7;;77049:18;77045:83;;-1:-1:-1;;77091:25:0;;;76870:458::o;77045:83::-;77306:13;77261:17;;77220:20;;77202:15;:38;;;;:::i;:::-;77201:77;;;;:::i;:::-;:101;;77298:4;77201:101;:::i;:::-;77200:119;;;;:::i;:::-;77158:25;;:162;;;;:::i;92670:339::-;92743:6;;;;92729:10;:20;92725:47;;92758:14;;;;;;;;;;;;;;92725:47;92808:21;;;92785:20;92808:21;;;:15;:21;;;;;;92840:45;92824:4;92808:21;92840:25;:45::i;:::-;92914:12;92898;;:28;;;;;;;:::i;:::-;;;;-1:-1:-1;;;92944:21:0;;;;;;:15;:21;;;;;;;;92937:28;;;92983:12;:18;;;;;92976:25;92670:339::o;75060:213::-;75164:27;;;;;;;:17;:27;;;;;;75129:63;;75154:8;;75129:24;:63::i;:::-;75239:25;;;;;;;:15;:25;;;;;;75203:62;;75229:8;;75203:25;:62::i;:::-;75060:213;:::o;93243:1248::-;93504:10;93342:20;93480:35;;;:23;:35;;;;;;;;;93647:31;;;:22;:31;;;;;;93342:20;;;;;;93607:71;;93480:35;93607:71;:::i;:::-;93691:31;;;;:22;:31;;;;;:58;;;93579:99;;-1:-1:-1;93691:31:0;;93892:27;93714:7;93892:18;:27::i;:::-;97223:12;;97196:15;;;;97188:24;;97215:21;;;;97188:48;;-1:-1:-1;97223:12:0;;-1:-1:-1;93762:157:0;-1:-1:-1;93762:157:0;-1:-1:-1;93987:29:0;94050:45;97188:48;94050:17;:45;:::i;:::-;94019:76;;:15;:76;:::i;:::-;93987:108;;94108:20;94155:10;94131:21;:34;:97;;94207:21;94131:97;;;94181:10;94131:97;94108:120;-1:-1:-1;94277:25:0;94287:6;94277:25;;94317:15;94347:7;94377:19;94392:4;94108:120;94377:19;:::i;:::-;94277:131;;;;;;;;;;;;;;94369:28;94277:131;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94429:12;94457;94444:10;:25;;;;:::i;:::-;94421:62;;;;-1:-1:-1;94472:10:0;;-1:-1:-1;93243:1248:0;;-1:-1:-1;;;;;;;;93243:1248:0:o;90975:1130::-;91162:10;91122:21;91146:27;;;:15;:27;;;;;;91188:15;;91184:625;;91316:20;91312:486;;;91427:6;;91420:44;;;;;91440:10;91420:44;;;14124:74:1;14214:18;;;14207:34;;;91427:6:0;;;;;91420:19;;14097:18:1;;91420:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;91529:10:0;91516:24;;;;:12;:24;;;;;:39;;;;;;-1:-1:-1;91312:486:0;;-1:-1:-1;91312:486:0;;91685:6;;91678:46;;;;;91700:10;91678:46;;;14124:74:1;14214:18;;;14207:34;;;91685:6:0;;;;;91678:21;;14097:18:1;;91678:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;91756:10:0;91743:24;;;;:12;:24;;;;;:39;;91771:11;;-1:-1:-1;91743:24:0;;-1:-1:-1;91743:39:0;;91771:11;;91743:39;:::i;:::-;;;;-1:-1:-1;;91312:486:0;91911:10;91821:22;91898:24;;;:12;:24;;;;;;91846:87;;91873:10;;91846:12;:87::i;:::-;91960:10;91944:27;;;;:15;:27;;;;;:44;;;92041:12;;;:29;;;:45;;;;92026:60;;;-1:-1:-1;;;;90975:1130:0:o;94499:266::-;94561:7;94585:5;94594:1;94585:10;94581:32;;;-1:-1:-1;94604:9:0;;94499:266;-1:-1:-1;94499:266:0:o;94581:32::-;94628:5;94637:3;94628:12;94624:34;;;-1:-1:-1;94649:9:0;;94499:266;-1:-1:-1;94499:266:0:o;94624:34::-;94720:26;94744:1;94736:5;:9;94720:15;:26::i;:::-;94701:16;;:45;;94499:266;-1:-1:-1;;94499:266:0:o;78322:769::-;78406:13;78402:513;;;78463:10;78436:16;78455:19;;;:7;:19;;;;;;78541:23;;;78537:367;;78626:10;78618:19;;;;:7;:19;;;;;:34;;;;;;;;;78537:367;;;78735:12;;78731:173;;78783:10;78775:19;;;;:7;:19;;;;;78768:26;78846:23;;;;;78731:173;78421:494;78402:513;79002:15;;78998:86;;79034:38;;;;;79048:10;79034:38;;;14124:74:1;14214:18;;;14207:34;;;79038:3:0;79034:13;;;;;14097:18:1;;79034:38:0;;;;;;;;;;;;;;;;;;;87845:1024;88040:8;88023:14;88068:794;88088:6;88084:1;:10;88068:794;;;88117:9;88127:1;88117:12;;;;;;;;:::i;:::-;;;;;;;88133:1;88117:17;88113:674;;88170:9;88180:1;88170:12;;;;;;;;:::i;:::-;;;;;;;88159:8;:23;88155:617;;;88217:6;88207:25;;;88259:15;88301:8;;88310:1;88301:11;;;;;;;:::i;:::-;;;;;;;88358:4;88347:5;88353:1;88347:8;;;;;;;;:::i;:::-;;;;;;;:15;;;;:::i;:::-;88207:179;;;;;;;;;;;;;;88339:24;88207:179;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88421:9;88431:1;88421:12;;;;;;;;:::i;:::-;;;;;;;88409:24;;;;;:::i;:::-;;;88155:617;;;88492:6;88482:25;;;88534:15;88576:8;;88585:1;88576:11;;;;;;;:::i;:::-;;;;;;;88661:4;88649:8;88634:9;88644:1;88634:12;;;;;;;;:::i;:::-;;;;;;;88623:5;88629:1;88623:8;;;;;;;;:::i;:::-;;;;;;;:23;;;;:::i;:::-;:34;;;;:::i;:::-;88622:43;;;;:::i;:::-;88482:207;;;;;;;;;;;;;;88614:52;88482:207;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88723:1;88712:12;;88747:5;;88155:617;88832:3;;88068:794;;77514:619;77641:34;:32;:34::i;:::-;77692:23;;77688:362;;77732:17;77752:130;77798:8;77825:19;77863:4;77752:27;:130::i;:::-;77928:17;;;;;;;:7;:17;;;;;:30;;;;;;77732:150;-1:-1:-1;78022:16:0;77732:150;78034:4;78022:16;:::i;:::-;77988:30;;;;;;;:20;:30;;;;;:50;;:30;;;:50;;;;;:::i;:::-;;;;-1:-1:-1;;;77688:362:0;-1:-1:-1;78100:25:0;;78060:37;;;;;;;;:27;:37;;;;;:65;77514:619::o;94773:611::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95033:15:0;;95046:1;95033:15;;;;;;;;;-1:-1:-1;;;;;;;;95033:15:0;;;;;;;;;;;;;;;;;;;95007:41;;95072:15;95059:28;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:7;95067:1;95059:10;;;;;;;;:::i;:::-;;;;;;:28;;;;95099:30;95131:22;95181:6;95157:59;;;95217:7;95226:8;95157:78;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;95098:137;;;;95270:6;95299:5;95305:1;95299:8;;;;;;;;:::i;:::-;;;;;;;95291:17;;95311:4;95291:24;;;;:::i;:::-;95345:12;;95330:28;;;;:14;:28::i;:::-;:35;;95361:4;95330:35;:::i;:::-;95248:128;;;;;;;;;94773:611;;;;;:::o;77336:170::-;77428:21;:19;:21::i;:::-;77400:25;:49;77483:15;77460:20;:38;77336:170::o;75901:158::-;75987:20;:18;:20::i;:::-;75964;:43;76036:15;76018;:33;75901:158::o;79793:1142::-;79901:7;;79856;79938:3;79929:12;;79925:992;;;-1:-1:-1;79969:9:0;;79793:1142;-1:-1:-1;79793:1142:0:o;79925:992::-;80134:1;80126:5;:9;:23;;;;;80147:2;80139:5;:10;80126:23;80122:795;;;-1:-1:-1;80186:4:0;80178:12;80195:1;80177:19;;79793:1142::o;80122:795::-;80231:2;80222:5;:11;;:25;;;;;80245:2;80237:5;:10;80222:25;80218:699;;;80396:2;80388:5;:10;80383:1;:16;80298:55;:102;;80404:3;80297:110;80411:4;80296:119;80268:147;;79793:1142;;;:::o;80218:699::-;80450:2;80441:5;:11;;:25;;;;;80464:2;80456:5;:10;80441:25;80437:480;;;80615:2;80607:5;:10;80602:1;:16;80517:55;:102;;80623:3;80516:110;80630:4;80515:119;80487:147;;79793:1142;;;:::o;80437:480::-;80669:2;80660:5;:11;;:26;;;;;80683:3;80675:5;:11;80660:26;80656:261;;;80817:2;80809:5;:10;80804:1;:16;80737:37;:84;;80825:3;80736:92;80832:4;80735:101;80707:129;;79793:1142;;;:::o;80656:261::-;-1:-1:-1;80884:17:0;;79793:1142;-1:-1:-1;79793:1142:0:o;80656:261::-;79793:1142;;;:::o;76067:610::-;76193:33;:31;:33::i;:::-;76243:23;;76239:363;;76283:17;76303:131;76349:8;76376:19;76414:5;76303:27;:131::i;:::-;76480:17;;;;;;;:7;:17;;;;;:30;;;;;;76283:151;-1:-1:-1;76574:16:0;76283:151;76586:4;76574:16;:::i;:::-;76540:30;;;;;;;:20;:30;;;;;:50;;:30;;;:50;;;;;:::i;:::-;;;;-1:-1:-1;;;76239:363:0;-1:-1:-1;76649:20:0;;76614:32;;;;;;;;:22;:32;;;;;:55;76067:610::o;90703:213::-;90822:7;90854:54;90877:30;90902:5;90877:22;:30;:::i;:::-;90854:22;:54::i;:::-;90847:61;90703:213;-1:-1:-1;;;90703:213:0:o;73729:1133::-;73883:7;73903:17;73931:20;73968:7;73964:864;;;74020:108;74063:8;74090:23;74020:24;:108::i;:::-;74421:27;;;;;;;:17;:27;;;;;;73992:136;;-1:-1:-1;73992:136:0;-1:-1:-1;74322:141:0;;73992:136;;74398:4;;74322:26;:141::i;:::-;74285:33;;;;;;;:23;:33;;;;;:178;;:33;;;:178;;;;;:::i;:::-;;;;-1:-1:-1;73964:864:0;;-1:-1:-1;73964:864:0;;74524:103;74562:8;74589:23;74524:19;:103::i;:::-;74496:131;;-1:-1:-1;74496:131:0;-1:-1:-1;74679:137:0;74496:131;74755:4;74778:23;74679:26;:137::i;:::-;74642:33;;;;;;;:23;:33;;;;;:174;;:33;;;:174;;;;;:::i;:::-;;;;-1:-1:-1;;73964:864:0;-1:-1:-1;74845:9:0;73729:1133;-1:-1:-1;;;;73729:1133:0:o;65824:2171::-;65962:1;66049;66151:35;66145:42;;66135:199;;66281:2;66277:10;;;;;66217:3;66213:11;66135:199;66364:19;66361:1;66358:26;66348:181;;66476:2;66472:10;;;;;66414:2;66410:10;66348:181;66559:11;66556:1;66553:18;66543:173;;66663:2;66659:10;;;;;66601:2;66597:10;66543:173;66746:7;66743:1;66740:14;66730:167;;66846:1;66842:9;;;;;66784:2;66780:10;66730:167;66927:5;66924:1;66921:12;66911:163;;67023:1;67019:9;;;;;66963:1;66959:9;66911:163;67104:4;67101:1;67098:11;67088:162;;67199:1;67195:9;;;;;67139:1;67135:9;67088:162;67280:3;67277:1;67274:10;67264:112;;67359:1;67356;67352:9;67347:14;;67264:112;-1:-1:-1;67470:9:0;;;67463:17;67460:1;67456:25;;;67514:9;;;67507:17;67500:25;;67558:9;;;67551:17;67544:25;;67602:9;;;67595:17;67588:25;;67646:9;;;67639:17;67632:25;;67690:9;;;67683:17;67676:25;;67734:9;;;67727:17;67720:25;;67832:9;;;67910:17;;;67907:70;;;67952:10;67947:15;;67907:70;;65824:2171;;;:::o;62023:771::-;62234:9;;;62368:19;;62361:27;62393:9;;62407;;;62404:16;;62390:31;62357:65;62347:123;;62453:1;62450;62443:12;62347:123;62773:1;62759:11;62755:1;62752;62748:9;62744:27;62740:35;62735:1;62728:9;62721:17;62717:59;62712:64;;62023:771;;;;;:::o;14:154:1:-;100:42;93:5;89:54;82:5;79:65;69:93;;158:1;155;148:12;173:247;232:6;285:2;273:9;264:7;260:23;256:32;253:52;;;301:1;298;291:12;253:52;340:9;327:23;359:31;384:5;359:31;:::i;607:160::-;672:20;;728:13;;721:21;711:32;;701:60;;757:1;754;747:12;772:248;837:6;845;898:2;886:9;877:7;873:23;869:32;866:52;;;914:1;911;904:12;866:52;950:9;937:23;927:33;;979:35;1010:2;999:9;995:18;979:35;:::i;:::-;969:45;;772:248;;;;;:::o;1025:367::-;1088:8;1098:6;1152:3;1145:4;1137:6;1133:17;1129:27;1119:55;;1170:1;1167;1160:12;1119:55;-1:-1:-1;1193:20:1;;1236:18;1225:30;;1222:50;;;1268:1;1265;1258:12;1222:50;1305:4;1297:6;1293:17;1281:29;;1365:3;1358:4;1348:6;1345:1;1341:14;1333:6;1329:27;1325:38;1322:47;1319:67;;;1382:1;1379;1372:12;1397:437;1483:6;1491;1544:2;1532:9;1523:7;1519:23;1515:32;1512:52;;;1560:1;1557;1550:12;1512:52;1600:9;1587:23;1633:18;1625:6;1622:30;1619:50;;;1665:1;1662;1655:12;1619:50;1704:70;1766:7;1757:6;1746:9;1742:22;1704:70;:::i;:::-;1793:8;;1678:96;;-1:-1:-1;1397:437:1;-1:-1:-1;;;;1397:437:1:o;1839:180::-;1898:6;1951:2;1939:9;1930:7;1926:23;1922:32;1919:52;;;1967:1;1964;1957:12;1919:52;-1:-1:-1;1990:23:1;;1839:180;-1:-1:-1;1839:180:1:o;2255:184::-;2307:77;2304:1;2297:88;2404:4;2401:1;2394:15;2428:4;2425:1;2418:15;2444:334;2515:2;2509:9;2571:2;2561:13;;2576:66;2557:86;2545:99;;2674:18;2659:34;;2695:22;;;2656:62;2653:88;;;2721:18;;:::i;:::-;2757:2;2750:22;2444:334;;-1:-1:-1;2444:334:1:o;2783:164::-;2869:52;2862:5;2858:64;2851:5;2848:75;2838:103;;2937:1;2934;2927:12;2952:117;3037:6;3030:5;3026:18;3019:5;3016:29;3006:57;;3059:1;3056;3049:12;3074:114;3158:4;3151:5;3147:16;3140:5;3137:27;3127:55;;3178:1;3175;3168:12;3193:130;3259:20;;3288:29;3259:20;3288:29;:::i;3328:1134::-;3411:6;3464:3;3452:9;3443:7;3439:23;3435:33;3432:53;;;3481:1;3478;3471:12;3432:53;3514:2;3508:9;3556:3;3548:6;3544:16;3626:6;3614:10;3611:22;3590:18;3578:10;3575:34;3572:62;3569:88;;;3637:18;;:::i;:::-;3673:2;3666:22;3710:23;;3742:31;3710:23;3742:31;:::i;:::-;3782:21;;3855:2;3840:18;;3827:32;3868;3827;3868;:::i;:::-;3928:2;3916:15;;3909:32;3993:2;3978:18;;3965:32;4006:31;3965:32;4006:31;:::i;:::-;4065:2;4053:15;;4046:32;4130:2;4115:18;;4102:32;4143:31;4102:32;4143:31;:::i;:::-;4202:2;4190:15;;4183:32;4249:37;4281:3;4266:19;;4249:37;:::i;:::-;4243:3;4235:6;4231:16;4224:63;4321:37;4353:3;4342:9;4338:19;4321:37;:::i;:::-;4315:3;4307:6;4303:16;4296:63;4393:37;4425:3;4414:9;4410:19;4393:37;:::i;:::-;4387:3;4375:16;;4368:63;4379:6;3328:1134;-1:-1:-1;;;3328:1134:1:o;4659:315::-;4727:6;4735;4788:2;4776:9;4767:7;4763:23;4759:32;4756:52;;;4804:1;4801;4794:12;4756:52;4843:9;4830:23;4862:31;4887:5;4862:31;:::i;:::-;4912:5;4964:2;4949:18;;;;4936:32;;-1:-1:-1;;;4659:315:1:o;5232:728::-;5318:6;5326;5334;5342;5395:2;5383:9;5374:7;5370:23;5366:32;5363:52;;;5411:1;5408;5401:12;5363:52;5447:9;5434:23;5424:33;;5508:2;5497:9;5493:18;5480:32;5531:18;5572:2;5564:6;5561:14;5558:34;;;5588:1;5585;5578:12;5558:34;5626:6;5615:9;5611:22;5601:32;;5671:7;5664:4;5660:2;5656:13;5652:27;5642:55;;5693:1;5690;5683:12;5642:55;5733:2;5720:16;5759:2;5751:6;5748:14;5745:34;;;5775:1;5772;5765:12;5745:34;5820:7;5815:2;5806:6;5802:2;5798:15;5794:24;5791:37;5788:57;;;5841:1;5838;5831:12;5788:57;5872:2;5868;5864:11;5854:21;;5894:6;5884:16;;;;;5919:35;5950:2;5939:9;5935:18;5919:35;:::i;:::-;5909:45;;5232:728;;;;;;;:::o;6120:531::-;6162:3;6200:5;6194:12;6227:6;6222:3;6215:19;6252:1;6262:162;6276:6;6273:1;6270:13;6262:162;;;6338:4;6394:13;;;6390:22;;6384:29;6366:11;;;6362:20;;6355:59;6291:12;6262:162;;;6442:6;6439:1;6436:13;6433:87;;;6508:1;6501:4;6492:6;6487:3;6483:16;6479:27;6472:38;6433:87;-1:-1:-1;6565:2:1;6553:15;6570:66;6549:88;6540:98;;;;6640:4;6536:109;;6120:531;-1:-1:-1;;6120:531:1:o;6656:220::-;6805:2;6794:9;6787:21;6768:4;6825:45;6866:2;6855:9;6851:18;6843:6;6825:45;:::i;6961:966::-;7157:4;7199:3;7188:9;7184:19;7176:27;;7249:52;7240:6;7234:13;7230:72;7219:9;7212:91;7371:6;7363:4;7355:6;7351:17;7345:24;7341:37;7334:4;7323:9;7319:20;7312:67;7447:4;7439;7431:6;7427:17;7421:24;7417:35;7410:4;7399:9;7395:20;7388:65;7521:4;7513;7505:6;7501:17;7495:24;7491:35;7484:4;7473:9;7469:20;7462:65;7595:4;7587;7579:6;7575:17;7569:24;7565:35;7558:4;7547:9;7543:20;7536:65;7648:4;7640:6;7636:17;7630:24;7663:52;7709:4;7698:9;7694:20;7680:12;6948:4;6937:16;6925:29;;6881:75;7663:52;;7764:4;7756:6;7752:17;7746:24;7779:54;7827:4;7816:9;7812:20;7796:14;6948:4;6937:16;6925:29;;6881:75;7779:54;-1:-1:-1;7864:3:1;7849:19;;7842:35;;;;7908:3;7893:19;7886:35;6961:966;;-1:-1:-1;6961:966:1:o;7932:572::-;8027:6;8035;8043;8096:2;8084:9;8075:7;8071:23;8067:32;8064:52;;;8112:1;8109;8102:12;8064:52;8152:9;8139:23;8185:18;8177:6;8174:30;8171:50;;;8217:1;8214;8207:12;8171:50;8256:70;8318:7;8309:6;8298:9;8294:22;8256:70;:::i;:::-;8345:8;;-1:-1:-1;8230:96:1;-1:-1:-1;;8430:2:1;8415:18;;8402:32;8443:31;8402:32;8443:31;:::i;:::-;8493:5;8483:15;;;7932:572;;;;;:::o;8509:184::-;8561:77;8558:1;8551:88;8658:4;8655:1;8648:15;8682:4;8679:1;8672:15;8698:125;8738:4;8766:1;8763;8760:8;8757:34;;;8771:18;;:::i;:::-;-1:-1:-1;8808:9:1;;8698:125::o;8828:228::-;8868:7;8994:1;8926:66;8922:74;8919:1;8916:81;8911:1;8904:9;8897:17;8893:105;8890:131;;;9001:18;;:::i;:::-;-1:-1:-1;9041:9:1;;8828:228::o;9061:274::-;9101:1;9127;9117:189;;9162:77;9159:1;9152:88;9263:4;9260:1;9253:15;9291:4;9288:1;9281:15;9117:189;-1:-1:-1;9320:9:1;;9061:274::o;9340:128::-;9380:3;9411:1;9407:6;9404:1;9401:13;9398:39;;;9417:18;;:::i;:::-;-1:-1:-1;9453:9:1;;9340:128::o;9473:251::-;9543:6;9596:2;9584:9;9575:7;9571:23;9567:32;9564:52;;;9612:1;9609;9602:12;9564:52;9644:9;9638:16;9663:31;9688:5;9663:31;:::i;9729:134::-;9806:13;;9828:29;9806:13;9828:29;:::i;9868:1122::-;9932:5;9980:4;9968:9;9963:3;9959:19;9955:30;9952:50;;;9998:1;9995;9988:12;9952:50;10031:2;10025:9;10073:4;10065:6;10061:17;10144:6;10132:10;10129:22;10108:18;10096:10;10093:34;10090:62;10087:88;;;10155:18;;:::i;:::-;10195:10;10191:2;10184:22;;10224:6;10215:15;;10260:9;10254:16;10279:33;10304:7;10279:33;:::i;:::-;10321:23;;10389:2;10374:18;;10368:25;10402:32;10368:25;10402:32;:::i;:::-;10462:2;10450:15;;10443:32;10520:2;10505:18;;10499:25;10533:31;10499:25;10533:31;:::i;:::-;10592:2;10580:15;;10573:32;10650:2;10635:18;;10629:25;10663:31;10629:25;10663:31;:::i;:::-;10722:2;10710:15;;10703:32;10769:48;10812:3;10797:19;;10769:48;:::i;:::-;10763:3;10755:6;10751:16;10744:74;10852:48;10895:3;10884:9;10880:19;10852:48;:::i;:::-;10846:3;10838:6;10834:16;10827:74;10935:48;10978:3;10967:9;10963:19;10935:48;:::i;:::-;10929:3;10921:6;10917:16;10910:74;;9868:1122;;;;:::o;10995:248::-;11089:6;11142:3;11130:9;11121:7;11117:23;11113:33;11110:53;;;11159:1;11156;11149:12;11110:53;11182:55;11229:7;11218:9;11182:55;:::i;11248:437::-;11327:1;11323:12;;;;11370;;;11391:61;;11445:4;11437:6;11433:17;11423:27;;11391:61;11498:2;11490:6;11487:14;11467:18;11464:38;11461:218;;;11535:77;11532:1;11525:88;11636:4;11633:1;11626:15;11664:4;11661:1;11654:15;11816:1157;11901:12;;11866:3;;11956:1;11976:18;;;;12029;;;;12056:61;;12110:4;12102:6;12098:17;12088:27;;12056:61;12136:2;12184;12176:6;12173:14;12153:18;12150:38;12147:218;;;12221:77;12218:1;12211:88;12322:4;12319:1;12312:15;12350:4;12347:1;12340:15;12147:218;6052:19;;;6104:4;6095:14;;12451:18;12478:162;;;;12654:1;12649:318;;;;12444:523;;12478:162;12528:66;12517:9;12513:82;12506:5;12499:97;12627:2;12620:5;12616:14;12609:21;;12478:162;;12649:318;11763:1;11756:14;;;11800:4;11787:18;;12743:1;12757:167;12771:6;12768:1;12765:13;12757:167;;;12851:14;;12836:13;;;12829:37;12894:16;;;;12786:10;;12757:167;;;12944:13;;;-1:-1:-1;;12444:523:1;;;;;;;;11816:1157;;;;:::o;12978:375::-;13188:2;13177:9;13170:21;13151:4;13208:53;13257:2;13246:9;13242:18;13234:6;13208:53;:::i;:::-;13292:2;13277:18;;13270:34;;;;-1:-1:-1;13335:2:1;13320:18;13313:34;13200:61;12978:375;-1:-1:-1;12978:375:1:o;13358:184::-;13410:77;13407:1;13400:88;13507:4;13504:1;13497:15;13531:4;13528:1;13521:15;14252:520;14439:6;14428:9;14421:25;14482:2;14477;14466:9;14462:18;14455:30;14521:6;14516:2;14505:9;14501:18;14494:34;14578:6;14570;14565:2;14554:9;14550:18;14537:48;14634:1;14605:22;;;14629:2;14601:31;;;14594:42;;;;14688:2;14676:15;;;14693:66;14672:88;14657:104;14653:113;;14252:520;-1:-1:-1;;14252:520:1:o;14777:184::-;14847:6;14900:2;14888:9;14879:7;14875:23;14871:32;14868:52;;;14916:1;14913;14906:12;14868:52;-1:-1:-1;14939:16:1;;14777:184;-1:-1:-1;14777:184:1:o;15338:935::-;15528:4;15576:2;15565:9;15561:18;15606:2;15595:9;15588:21;15629:6;15664;15658:13;15695:6;15687;15680:22;15733:2;15722:9;15718:18;15711:25;;15795:2;15785:6;15782:1;15778:14;15767:9;15763:30;15759:39;15745:53;;15817:4;15856:2;15848:6;15844:15;15877:1;15887:314;15901:6;15898:1;15895:13;15887:314;;;15990:66;15978:9;15970:6;15966:22;15962:95;15957:3;15950:108;16081:40;16114:6;16105;16099:13;16081:40;:::i;:::-;16071:50;-1:-1:-1;16179:12:1;;;;16144:15;;;;15923:1;15916:9;15887:314;;;-1:-1:-1;;16240:18:1;;;;16233:34;;;;16218:6;15338:935;-1:-1:-1;;;;15338:935:1:o;16278:1064::-;16406:6;16414;16467:3;16455:9;16446:7;16442:23;16438:33;16435:53;;;16484:1;16481;16474:12;16435:53;16507:55;16554:7;16543:9;16507:55;:::i;:::-;16497:65;;16606:3;16595:9;16591:19;16585:26;16630:18;16671:2;16663:6;16660:14;16657:34;;;16687:1;16684;16677:12;16657:34;16725:6;16714:9;16710:22;16700:32;;16770:7;16763:4;16759:2;16755:13;16751:27;16741:55;;16792:1;16789;16782:12;16741:55;16821:2;16815:9;16843:4;16866:2;16862;16859:10;16856:36;;;16872:18;;:::i;:::-;16918:2;16915:1;16911:10;16901:20;;16941:28;16965:2;16961;16957:11;16941:28;:::i;:::-;17003:15;;;17073:11;;;17069:20;;;17034:12;;;;17101:19;;;17098:39;;;17133:1;17130;17123:12;17098:39;17157:11;;;;17177:135;17193:6;17188:3;17185:15;17177:135;;;17259:10;;17247:23;;17210:12;;;;17290;;;;17177:135;;;17331:5;17321:15;;;;;;;;16278:1064;;;;;:::o

Swarm Source

ipfs://af9fc0370af7d4a13f6e0f22d41c44e1dca6501e3e09795b54d77bf471cb9382
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.