More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 119,877 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Level Up | 60797236 | 1 hr ago | IN | 0 AVAX | 0.00029977 | ||||
Level Up | 60797224 | 1 hr ago | IN | 0 AVAX | 0.00030126 | ||||
Level Up | 60797216 | 1 hr ago | IN | 0 AVAX | 0.00030057 | ||||
Level Up | 60797191 | 1 hr ago | IN | 0 AVAX | 0.00029849 | ||||
Level Up | 60797172 | 1 hr ago | IN | 0 AVAX | 0.00030004 | ||||
Level Up | 60797167 | 1 hr ago | IN | 0 AVAX | 0.00032921 | ||||
Level Up | 60788381 | 5 hrs ago | IN | 0 AVAX | 0.00027253 | ||||
Level Up | 60784196 | 6 hrs ago | IN | 0 AVAX | 0.00027224 | ||||
Level Up | 60784183 | 6 hrs ago | IN | 0 AVAX | 0.00027368 | ||||
Level Up | 60756378 | 17 hrs ago | IN | 0 AVAX | 0.00031992 | ||||
Level Up | 60756375 | 17 hrs ago | IN | 0 AVAX | 0.00031282 | ||||
Level Up | 60756371 | 17 hrs ago | IN | 0 AVAX | 0.00028006 | ||||
Level Up | 60756367 | 17 hrs ago | IN | 0 AVAX | 0.0003153 | ||||
Level Up | 60756362 | 17 hrs ago | IN | 0 AVAX | 0.00031448 | ||||
Level Up | 60756359 | 17 hrs ago | IN | 0 AVAX | 0.00031612 | ||||
Level Up | 60756355 | 17 hrs ago | IN | 0 AVAX | 0.00028362 | ||||
Level Up | 60756353 | 17 hrs ago | IN | 0 AVAX | 0.00032065 | ||||
Level Up | 60756349 | 17 hrs ago | IN | 0 AVAX | 0.00031815 | ||||
Level Up | 60756342 | 17 hrs ago | IN | 0 AVAX | 0.00032212 | ||||
Level Up | 60756339 | 17 hrs ago | IN | 0 AVAX | 0.00028729 | ||||
Level Up | 60756336 | 17 hrs ago | IN | 0 AVAX | 0.00032199 | ||||
Level Up | 60756331 | 17 hrs ago | IN | 0 AVAX | 0.00032253 | ||||
Level Up | 60756328 | 17 hrs ago | IN | 0 AVAX | 0.00028732 | ||||
Level Up | 60756326 | 17 hrs ago | IN | 0 AVAX | 0.00032301 | ||||
Level Up | 60756322 | 17 hrs ago | IN | 0 AVAX | 0.00028879 |
Loading...
Loading
Contract Name:
Lake
Compiler Version
v0.8.12+commit.f00d7308
Contract Source Code (Solidity)
/** *Submitted for verification at snowscan.xyz 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 Lake 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) { if ( hopper.agility < 5 || hopper.vitality < 5 || hopper.intelligence < 5 || hopper.strength < 5 || hopper.level < 20 ) return false; return true; } function _calculateBaseShare(HopperNFT.Hopper memory hopper) internal pure override returns (uint256) { unchecked { return uint256(hopper.agility) * uint256(hopper.vitality) * uint256(hopper.intelligence) * uint256(hopper.strength) * uint256(hopper.level); } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"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"}]
Contract Creation Code
60e06040523480156200001157600080fd5b5060405162003cf138038062003cf183398101604081905262000034916200017c565b600480546001600160a01b031916331790556001600160a01b0380841660805280831660a052811660c0526003600f908155604080518082019091528181526e4c4556454c5f47415547455f4b455960881b6020909101908152849184918491620000a291600091620000b9565b505042600881905560125550620002039350505050565b828054620000c790620001c6565b90600052602060002090601f016020900481019282620000eb576000855562000136565b82601f106200010657805160ff191683800117855562000136565b8280016001018555821562000136579182015b828111156200013657825182559160200191906001019062000119565b506200014492915062000148565b5090565b5b8082111562000144576000815560010162000149565b80516001600160a01b03811681146200017757600080fd5b919050565b6000806000606084860312156200019257600080fd5b6200019d846200015f565b9250620001ad602085016200015f565b9150620001bd604085016200015f565b90509250925092565b600181811c90821680620001db57607f821691505b60208210811415620001fd57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c051613a6a62000287600039600081816104cf0152818161084801528181611098015281816116e4015281816118da015281816119d301528181611f57015281816122c3015281816126bf015281816127d90152612adc01526000610443015260008181610783015281816112fb01526126160152613a6a6000f3fe608060405234801561001057600080fd5b50600436106103365760003560e01c806379f409e0116101b2578063ad914e2e116100f9578063d881e959116100a2578063e42c4e631161007c578063e42c4e63146107a5578063e532a154146107ad578063ee569ba9146107b5578063f5544eb7146107d557600080fd5b8063d881e9591461074b578063dee935681461075e578063e1a61a0c1461077e57600080fd5b8063c9d27afe116100d3578063c9d27afe14610700578063caa6fea414610713578063d051bfa31461073857600080fd5b8063ad914e2e146106c2578063bf856895146106e4578063bf9bc0b2146106ed57600080fd5b806396afc4501161015b578063a49a3e1b11610135578063a49a3e1b1461067a578063ab20355c1461068f578063ac3910a2146106a257600080fd5b806396afc4501461064b5780639d4c93c414610654578063a1bdb15e1461066757600080fd5b80638da5cb5b1161018c5780638da5cb5b146105f85780638eb3be2814610618578063968c603d1461062b57600080fd5b806379f409e0146105905780637e2d9af8146105b8578063818ae1ce146105d857600080fd5b80633cfa989e116102815780635834c36d1161022a5780635d35b5d5116102045780635d35b5d51461053e5780636351520e14610547578063769022a31461055a5780637944135d1461057d57600080fd5b80635834c36d14610502578063591adce61461050b5780635c1ab8c01461051e57600080fd5b80634b905e3f1161025b5780634b905e3f146104ca5780634b9ca431146104f15780634e71d92d146104fa57600080fd5b80633cfa989e1461048e578063402914f5146104ae57806343aba89d146104c157600080fd5b80631c1502c4116102e35780632677d07f116102bd5780632677d07f1461043e5780632df97550146104655780633bad0f711461048557600080fd5b80631c1502c4146103ba578063201e29a0146103c3578063215e0f4d1461041e57600080fd5b80630c679fa0116103145780630c679fa01461037f57806313af40351461039457806318c08f26146103a757600080fd5b80630700037d1461033b5780630ab747f01461036e5780630b24216314610377575b600080fd5b61035b61034936600461308d565b60036020526000908152604090205481565b6040519081526020015b60405180910390f35b61035b60095481565b61035b6107e8565b61039261038d3660046130ba565b610846565b005b6103926103a236600461308d565b610d4e565b6103926103b536600461312b565b610e0e565b61035b60135481565b6103f96103d136600461316d565b60016020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610365565b61035b61042c36600461308d565b600a6020526000908152604090205481565b6103f97f000000000000000000000000000000000000000000000000000000000000000081565b61035b61047336600461308d565b60146020526000908152604090205481565b61035b60075481565b61035b61049c36600461308d565b600d6020526000908152604090205481565b61035b6104bc36600461308d565b61119f565b61035b60105481565b6103f97f000000000000000000000000000000000000000000000000000000000000000081565b61035b60115481565b610392611292565b61035b60125481565b6103926105193660046130ba565b61135a565b61035b61052c36600461308d565b600c6020526000908152604090205481565b61035b600f5481565b61039261055536600461316d565b61141c565b61056d610568366004613255565b611472565b6040519015158152602001610365565b61039261058b36600461312b565b6114f4565b6105a361059e36600461330d565b6117a7565b60408051928352602083019190915201610365565b61035b6105c636600461308d565b60166020526000908152604090205481565b61035b6105e636600461308d565b600b6020526000908152604090205481565b6004546103f99073ffffffffffffffffffffffffffffffffffffffff1681565b610392610626366004613339565b611859565b61035b61063936600461316d565b60026020526000908152604090205481565b61035b60065481565b61039261066236600461316d565b611a55565b61039261067536600461316d565b611ad9565b610682611b6d565b6040516103659190613431565b6105a361069d36600461330d565b611bfb565b6005546103f99073ffffffffffffffffffffffffffffffffffffffff1681565b6106d56106d036600461316d565b611c71565b60405161036593929190613444565b61035b60085481565b61035b6106fb36600461316d565b611ce7565b61039261070e3660046130ba565b611cf8565b60055461056d9074010000000000000000000000000000000000000000900460ff1681565b61039261074636600461308d565b611d2e565b6103926107593660046134dd565b611dee565b61035b61076c36600461316d565b600e6020526000908152604090205481565b6103f97f000000000000000000000000000000000000000000000000000000000000000081565b610392611fbf565b61035b612051565b61035b6107c336600461308d565b60156020526000908152604090205481565b6103926107e336600461308d565b6120a9565b600754600090806107fb57505060095490565b806006546008544261080d9190613563565b610817919061357a565b61082990670de0b6b3a764000061357a565b61083391906135b7565b60095461084091906135f2565b91505090565b7f000000000000000000000000000000000000000000000000000000000000000081156108765761087633612176565b60008381526001602052604090205473ffffffffffffffffffffffffffffffffffffffff16338114610980576040517f6352211e00000000000000000000000000000000000000000000000000000000815260048101859052339073ffffffffffffffffffffffffffffffffffffffff841690636352211e90602401602060405180830381865afa15801561090f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610933919061360a565b73ffffffffffffffffffffffffffffffffffffffff1614610980576040517f5483a62900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f5c5503530000000000000000000000000000000000000000000000000000000081526004810185905260009073ffffffffffffffffffffffffffffffffffffffff841690635c5503539060240160e060405180830381865afa1580156109ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a1291906136ef565b905073ffffffffffffffffffffffffffffffffffffffff8216331415610c0d5783610a4057610a4033612176565b6000610a4b866121db565b509150506000610aa2836000816000015178ffffffffffffffffffffffffffffffffffffffffffffffffff16826040015160ff168360a0015160ff16846080015160ff16856060015160ff16020202029050919050565b835160010178ffffffffffffffffffffffffffffffffffffffffffffffffff16808552604085015160a08601516080870151606088015194955060009460ff90811691811691909102918116919091029116020290506000610b048383613563565b336000908152600a6020526040812080548301908190556007805484019055919250610b3290829080612388565b50336000908152600c602052604081205485811015610b5857610b558187613563565b91505b610b628287613563565b8751610b889078ffffffffffffffffffffffffffffffffffffffffffffffffff1661253a565b610b979064e8d4a5100061357a565b610ba19190613563565b336000908152600c602052604081208054909190610bc09084906135f2565b909155505086517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0178ffffffffffffffffffffffffffffffffffffffffffffffffff1687525050505050505b610c3e610c38826000015178ffffffffffffffffffffffffffffffffffffffffffffffffff16611ce7565b85612583565b6040517f0ce90ec20000000000000000000000000000000000000000000000000000000081526004810186905273ffffffffffffffffffffffffffffffffffffffff841690630ce90ec290602401600060405180830381600087803b158015610ca657600080fd5b505af1158015610cba573d6000803e3d6000fd5b50506040517f3d68b4b500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86169250633d68b4b59150610d159060009089908290600401613830565b600060405180830381600087803b158015610d2f57600080fd5b505af1158015610d43573d6000803e3d6000fd5b505050505050505050565b60045473ffffffffffffffffffffffffffffffffffffffff163314610d9f576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f957090e72c0a1b3ebf83c682eb8c1f88c2a18cd0578b91a819efb28859f0f3a390600090a250565b60055474010000000000000000000000000000000000000000900460ff1615610e63576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e6c33612176565b336000908152600a6020908152604080832054600c90925282205490918291849190818367ffffffffffffffff811115610ea857610ea8613186565b604051908082528060200260200182016040528015610ed1578160200160208202803683370190505b50905060008767ffffffffffffffff811115610eef57610eef613186565b604051908082528060200260200182016040528015610f18578160200160208202803683370190505b50905060005b858110156111035760008a8a83818110610f3a57610f3a613855565b60209081029290920135600081815260019093526040909220549192505073ffffffffffffffffffffffffffffffffffffffff163314610fa6576040517f5483a62900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806000610fb4846121db565b91945092509050610fc5838c613563565b9a50610fd1828a6135f2565b985081878681518110610fe657610fe6613855565b6020026020010181815250508086868151811061100557611005613855565b6020908102919091018101919091526000858152600190915260409081902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055517f23b872dd0000000000000000000000000000000000000000000000000000000081523060048201523360248201526044810185905273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90606401600060405180830381600087803b1580156110dc57600080fd5b505af11580156110f0573d6000803e3d6000fd5b5050505084600101945050505050610f1e565b50336000908152600a6020526040902086905583831015611149576111348989848461112f888a613563565b61266f565b336000908152600c6020526040812055611188565b8561116357336000908152600c6020526040812055611188565b336000908152600c602052604081208054869290611182908490613563565b90915550505b6007805487018890039055610d4386600080612388565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600c602052604081205481906111d79064e8d4a51000906135b7565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600a60205260408120549192509061120c9085906117a7565b5073ffffffffffffffffffffffffffffffffffffffff851660009081526014602052604081205491925090611242908690611bfb565b50905061124f81836135f2565b915082821161125e5781611260565b825b73ffffffffffffffffffffffffffffffffffffffff909516600090815260036020526040902054909401949350505050565b61129b33612176565b336000818152600360205260408082208054929055517f40c10f190000000000000000000000000000000000000000000000000000000081526004810192909252602482018190529073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906340c10f1990604401600060405180830381600087803b15801561133f57600080fd5b505af1158015611353573d6000803e3d6000fd5b5050505050565b336000818152601460205260409020546113749190612905565b336000908152600a602052604081205461138f918490612388565b801561141857600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306661abd6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156113ff57600080fd5b505af1158015611413573d6000803e3d6000fd5b505050505b5050565b60045473ffffffffffffffffffffffffffffffffffffffff16331461146d576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600f55565b60006005826060015160ff16108061149157506005826080015160ff16105b806114a3575060058260a0015160ff16105b806114b557506005826040015160ff16105b806114df57506014826000015178ffffffffffffffffffffffffffffffffffffffffffffffffff16105b156114ec57506000919050565b506001919050565b60055474010000000000000000000000000000000000000000900460ff1615611549576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61155233612176565b336000908152600a6020908152604080832054600d90925282205490918291849190815b8381101561176457600088888381811061159257611592613855565b602090810292909201356000818152600e909352604083208690559250819050806115bc846129c6565b9250925092506115cb83611472565b611601576040517f0ce023b900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611652836000816000015178ffffffffffffffffffffffffffffffffffffffffffffffffff16826040015160ff168360a0015160ff16846080015160ff16856060015160ff16020202029050919050565b909801976116608282613563565b61166a90886135f2565b6000858152600160205260409081902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163390811790915590517f23b872dd0000000000000000000000000000000000000000000000000000000081526004810191909152306024820152604481018690529097507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906323b872dd90606401600060405180830381600087803b15801561173d57600080fd5b505af1158015611751573d6000803e3d6000fd5b5050505084600101945050505050611576565b50336000908152600a60209081526040808320879055600c9091528120805484019055600780548601879003905561179e90859080612388565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040812054819081906117e19064e8d4a51000906135b7565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600b602052604081205491925090670de0b6b3a76400009061181d6107e8565b6118279190613563565b611831908761357a565b61183b91906135b7565b905081811161184a578061184c565b815b93509150505b9250929050565b80156118685761186833612176565b60008481526001602052604090205473ffffffffffffffffffffffffffffffffffffffff16338114611992576040517f6352211e00000000000000000000000000000000000000000000000000000000815260048101869052339073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015611921573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611945919061360a565b73ffffffffffffffffffffffffffffffffffffffff1614611992576040517f5483a62900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fc60fb6a70000000000000000000000000000000000000000000000000000000081526113539073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063c60fb6a790611a0c90899089908990600401613884565b6020604051808303816000875af1158015611a2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4f91906138d8565b83612583565b60045473ffffffffffffffffffffffffffffffffffffffff163314801590611a95575060055473ffffffffffffffffffffffffffffffffffffffff163314155b15611acc576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ad4612c10565b601055565b60045473ffffffffffffffffffffffffffffffffffffffff163314611b2a576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b32612c21565b60068190556040518181527f90e51e492b1841b8ed3d459463d02d171ced752c7fcd84a9dd79f90098166aec9060200160405180910390a150565b60008054611b7a9061370b565b80601f0160208091040260200160405190810160405280929190818152602001828054611ba69061370b565b8015611bf35780601f10611bc857610100808354040283529160200191611bf3565b820191906000526020600020905b815481529060010190602001808311611bd657829003601f168201915b505050505081565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c602052604081205481908190611c359064e8d4a51000906135b7565b73ffffffffffffffffffffffffffffffffffffffff861660009081526015602052604081205491925090670de0b6b3a76400009061181d612051565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081018290529080611cb4846129c6565b9194509250905082611ccb64e8d4a51000846135b7565b611cda64e8d4a51000846135b7565b9250925092509193909250565b6000611cf282612c32565b92915050565b33600081815260146020526040902054611d129190612905565b336000908152600a602052604090205461138f90836001612388565b60045473ffffffffffffffffffffffffffffffffffffffff163314611d7f576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f605aa74980dc92c245d8959d233f8c2d7062d874e49326a42e7418279cc8d1f890600090a250565b60055474010000000000000000000000000000000000000000900460ff16611e42576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160005b81811015611353576000858583818110611e6257611e62613855565b60209081029290920135600081815260019093526040909220549192505073ffffffffffffffffffffffffffffffffffffffff858116911614611ed1576040517f5483a62900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600160205260409081902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8581166024830152604482018390527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90606401600060405180830381600087803b158015611f9b57600080fd5b505af1158015611faf573d6000803e3d6000fd5b5050505081600101915050611e46565b60045473ffffffffffffffffffffffffffffffffffffffff163314612010576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600580547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b6011546000908061206457505060135490565b80601054601254426120769190613563565b612080919061357a565b61209290670de0b6b3a764000061357a565b61209c91906135b7565b60135461084091906135f2565b60055473ffffffffffffffffffffffffffffffffffffffff1633146120fa576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526014602052604090205461212a8282612905565b806011600082825461213c9190613563565b90915550505073ffffffffffffffffffffffffffffffffffffffff1660009081526014602090815260408083208390556016909152812055565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600a60205260409020546121a7908290612d86565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601460205260409020546121d8908290612905565b50565b336000908152600d6020908152604080832054848452600e9092528220548291829182906122099083613563565b6000878152600e602052604081208490559091508080612228896129c6565b92509250925061227f836000816000015178ffffffffffffffffffffffffffffffffffffffffffffffffff16826040015160ff168360a0015160ff16846080015160ff16856060015160ff16020202029050919050565b9750600061228d898661357a565b61229790846135f2565b905060008282116122a857816122aa565b825b905073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016633d68b4b560008d6122fa64e8d4a51000866135b7565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815261233593929190600401613830565b600060405180830381600087803b15801561234f57600080fd5b505af1158015612363573d6000803e3d6000fd5b505050508981846123749190613563565b909c909b5092995091975050505050505050565b3360009081526014602052604090205482156124f9578115612449576005546040517f5f74bbde0000000000000000000000000000000000000000000000000000000081523360048201526024810185905273ffffffffffffffffffffffffffffffffffffffff90911690635f74bbde90604401600060405180830381600087803b15801561241657600080fd5b505af115801561242a573d6000803e3d6000fd5b5050336000908152601660205260409020805486019055506124f99050565b6005546040517f02aa9be20000000000000000000000000000000000000000000000000000000081523360048201526024810185905273ffffffffffffffffffffffffffffffffffffffff909116906302aa9be290604401600060405180830381600087803b1580156124bb57600080fd5b505af11580156124cf573d6000803e3d6000fd5b505033600090815260166020526040812080548794509092506124f3908490613563565b90915550505b33600090815260166020526040812054612514908690612e47565b336000908152601460205260409020819055601180549091019290920390915550505050565b6000816001141561255457506714d1120d7b160000919050565b816064141561256d5750680ff011d2523cd80000919050565b61257960018303612c32565b600f540292915050565b80156125db57336000908152600360205260409020548281106125bd573360009081526003602052604081208054949094039093556125d9565b80156125d9573360009081526003602052604081205591829003915b505b8115611418576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018390527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639dc29fac90604401600060405180830381600087803b1580156113ff57600080fd5b8360005b8181101561179e5784818151811061268d5761268d613855565b60200260200101516000146128fd578481815181106126ae576126ae613855565b60200260200101518311156127d7577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633d68b4b5600089898581811061270d5761270d613855565b9050602002013564e8d4a5100088868151811061272c5761272c613855565b602002602001015161273e91906135b7565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815261277993929190600401613830565b600060405180830381600087803b15801561279357600080fd5b505af11580156127a7573d6000803e3d6000fd5b505050508481815181106127bd576127bd613855565b6020026020010151836127d09190613563565b92506128fd565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633d68b4b5600089898581811061282757612827613855565b9050602002013564e8d4a51000878a878151811061284757612847613855565b60200260200101518a888151811061286157612861613855565b60200260200101516128739190613563565b61287d91906135f2565b61288791906135b7565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526128c293929190600401613830565b600060405180830381600087803b1580156128dc57600080fd5b505af11580156128f0573d6000803e3d6000fd5b505050506000925061179e565b600101612673565b61290d612c10565b801561299957600061292183836001612e62565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600360205260409020805482019055905061295d8164e8d4a5100061357a565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c602052604081208054909190612992908490613563565b9091555050505b5060135473ffffffffffffffffffffffffffffffffffffffff909116600090815260156020526040902055565b6040805160e08101825260008082526020808301829052828401829052606083018290526080830182905260a0830182905260c0830182905283516001808252818601909552929391928392839282015b6060815260200190600190039081612a1757905050905060008054612a3b9061370b565b80601f0160208091040260200160405190810160405280929190818152602001828054612a679061370b565b8015612ab45780601f10612a8957610100808354040283529160200191612ab4565b820191906000526020600020905b815481529060010190602001808311612a9757829003601f168201915b505050505081600081518110612acc57612acc613855565b60200260200101819052506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630d51186584896040518363ffffffff1660e01b8152600401612b359291906138f1565b600060405180830381865afa158015612b52573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052612b989190810190613978565b915091508181600081518110612bb057612bb0613855565b602002602001015160001c64e8d4a51000612bcb919061357a565b8351612bf19078ffffffffffffffffffffffffffffffffffffffffffffffffff1661253a565b612c009064e8d4a5100061357a565b9550955095505050509193909250565b612c18612051565b60135542601255565b612c296107e8565b60095542600855565b60010160006064821415612c50575068206aeac7a903980000919050565b600182118015612c605750601582105b15612c765750670de0b6b3a76400000260011c90565b60158210158015612c875750603382105b15612cc557601582036007027a01223448501f3c74e1b3464c172c54a9426488901e3c70d183058a901c607f16670de0b6b3a7640000029050919050565b60338210158015612cd65750605182105b15612d1457603382036007027a023c68b0e14180f9ebc76e9c376cd5a3262c17ae5ab15a9509d325901c607f16670de0b6b3a7640000029050919050565b60518210158015612d255750606582105b15612d5a5760518203600702710c58705ebb6ed59af5aad3a5467ce9b2e549901c607f16670de0b6b3a7640000029050919050565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff919050565b919050565b612d8e612c21565b8015612e1a576000612da283836000612e62565b73ffffffffffffffffffffffffffffffffffffffff841660009081526003602052604090208054820190559050612dde8164e8d4a5100061357a565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c602052604081208054909190612e13908490613563565b9091555050505b5060095473ffffffffffffffffffffffffffffffffffffffff9091166000908152600b6020526040902055565b6000612e5b612e56838561357a565b612f57565b9392505050565b60008060008315612ef457612e778686611bfb565b73ffffffffffffffffffffffffffffffffffffffff88166000908152600a60205260409020549193509150612eb490829064e8d4a510009061303d565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600d602052604081208054909190612ee99084906135f2565b90915550612f4e9050565b612efe86866117a7565b9092509050612f138164e8d4a510008761303d565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600d602052604081208054909190612f489084906135f2565b90915550505b50949350505050565b6001817001000000000000000000000000000000008110612f7d5760409190911b9060801c5b680100000000000000008110612f985760209190911b9060401c5b6401000000008110612faf5760109190911b9060201c5b620100008110612fc45760089190911b9060101c5b6101008110612fd85760049190911b9060081c5b60108110612feb5760029190911b9060041c5b60088110612ffa578160011b91505b5080820401600190811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c80820481811015613037578091505b50919050565b82820281151584158583048514171661305557600080fd5b6001826001830304018115150290509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146121d857600080fd5b60006020828403121561309f57600080fd5b8135612e5b8161306b565b80358015158114612d8157600080fd5b600080604083850312156130cd57600080fd5b823591506130dd602084016130aa565b90509250929050565b60008083601f8401126130f857600080fd5b50813567ffffffffffffffff81111561311057600080fd5b6020830191508360208260051b850101111561185257600080fd5b6000806020838503121561313e57600080fd5b823567ffffffffffffffff81111561315557600080fd5b613161858286016130e6565b90969095509350505050565b60006020828403121561317f57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156131fc576131fc613186565b604052919050565b78ffffffffffffffffffffffffffffffffffffffffffffffffff811681146121d857600080fd5b61ffff811681146121d857600080fd5b60ff811681146121d857600080fd5b8035612d818161323b565b600060e0828403121561326757600080fd5b60405160e0810181811067ffffffffffffffff8211171561328a5761328a613186565b604052823561329881613204565b815260208301356132a88161322b565b602082015260408301356132bb8161323b565b604082015260608301356132ce8161323b565b60608201526132df6080840161324a565b60808201526132f060a0840161324a565b60a082015261330160c0840161324a565b60c08201529392505050565b6000806040838503121561332057600080fd5b823561332b8161306b565b946020939093013593505050565b6000806000806060858703121561334f57600080fd5b84359350602085013567ffffffffffffffff8082111561336e57600080fd5b818701915087601f83011261338257600080fd5b81358181111561339157600080fd5b8860208285010111156133a357600080fd5b6020830195508094505050506133bb604086016130aa565b905092959194509250565b6000815180845260005b818110156133ec576020818501810151868301820152016133d0565b818111156133fe576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612e5b60208301846133c6565b60006101208201905078ffffffffffffffffffffffffffffffffffffffffffffffffff855116825261ffff602086015116602083015260ff604086015116604083015260ff606086015116606083015260ff608086015116608083015260a08501516134b560a084018260ff169052565b5060c08501516134ca60c084018260ff169052565b5060e08201939093526101000152919050565b6000806000604084860312156134f257600080fd5b833567ffffffffffffffff81111561350957600080fd5b613515868287016130e6565b90945092505060208401356135298161306b565b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561357557613575613534565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156135b2576135b2613534565b500290565b6000826135ed577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000821982111561360557613605613534565b500190565b60006020828403121561361c57600080fd5b8151612e5b8161306b565b8051612d818161323b565b600060e0828403121561364457600080fd5b60405160e0810181811067ffffffffffffffff8211171561366757613667613186565b8060405250809150825161367a81613204565b8152602083015161368a8161322b565b6020820152604083015161369d8161323b565b604082015260608301516136b08161323b565b60608201526136c160808401613627565b60808201526136d260a08401613627565b60a08201526136e360c08401613627565b60c08201525092915050565b600060e0828403121561370157600080fd5b612e5b8383613632565b600181811c9082168061371f57607f821691505b60208210811415613037577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8054600090600181811c908083168061377357607f831692505b60208084108214156137ae577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b838852602088018280156137c957600181146137f857613823565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00871682528282019750613823565b60008981526020902060005b8781101561381d57815484820152908601908401613804565b83019850505b5050505050505092915050565b6060815260006138436060830186613759565b60208301949094525060400152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b83815260406020820152816040820152818360608301376000818301606090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010192915050565b6000602082840312156138ea57600080fd5b5051919050565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b83811015613966577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08887030185526139548683516133c6565b9550938201939082019060010161391a565b50509490940194909452949350505050565b600080610100838503121561398c57600080fd5b6139968484613632565b915060e083015167ffffffffffffffff808211156139b357600080fd5b818501915085601f8301126139c757600080fd5b81516020828211156139db576139db613186565b8160051b92506139ec8184016131b5565b8281529284018101928181019089851115613a0657600080fd5b948201945b84861015613a2457855182529482019490820190613a0b565b809650505050505050925092905056fea26469706673582212207dafd72379692ef45e0c5a4f2adbce4b0b1307c1dfaf6cfc4d03d6854d7760bb64736f6c634300080c003300000000000000000000000078ea3fef1c1f07348199bf44f45b803b9b0dbe28000000000000000000000000baf9a6f8a8afd4be0d85ca40f025bf364fa273240000000000000000000000004245a1bd84eb5f3ebc115c2edf57e50667f98b0b
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103365760003560e01c806379f409e0116101b2578063ad914e2e116100f9578063d881e959116100a2578063e42c4e631161007c578063e42c4e63146107a5578063e532a154146107ad578063ee569ba9146107b5578063f5544eb7146107d557600080fd5b8063d881e9591461074b578063dee935681461075e578063e1a61a0c1461077e57600080fd5b8063c9d27afe116100d3578063c9d27afe14610700578063caa6fea414610713578063d051bfa31461073857600080fd5b8063ad914e2e146106c2578063bf856895146106e4578063bf9bc0b2146106ed57600080fd5b806396afc4501161015b578063a49a3e1b11610135578063a49a3e1b1461067a578063ab20355c1461068f578063ac3910a2146106a257600080fd5b806396afc4501461064b5780639d4c93c414610654578063a1bdb15e1461066757600080fd5b80638da5cb5b1161018c5780638da5cb5b146105f85780638eb3be2814610618578063968c603d1461062b57600080fd5b806379f409e0146105905780637e2d9af8146105b8578063818ae1ce146105d857600080fd5b80633cfa989e116102815780635834c36d1161022a5780635d35b5d5116102045780635d35b5d51461053e5780636351520e14610547578063769022a31461055a5780637944135d1461057d57600080fd5b80635834c36d14610502578063591adce61461050b5780635c1ab8c01461051e57600080fd5b80634b905e3f1161025b5780634b905e3f146104ca5780634b9ca431146104f15780634e71d92d146104fa57600080fd5b80633cfa989e1461048e578063402914f5146104ae57806343aba89d146104c157600080fd5b80631c1502c4116102e35780632677d07f116102bd5780632677d07f1461043e5780632df97550146104655780633bad0f711461048557600080fd5b80631c1502c4146103ba578063201e29a0146103c3578063215e0f4d1461041e57600080fd5b80630c679fa0116103145780630c679fa01461037f57806313af40351461039457806318c08f26146103a757600080fd5b80630700037d1461033b5780630ab747f01461036e5780630b24216314610377575b600080fd5b61035b61034936600461308d565b60036020526000908152604090205481565b6040519081526020015b60405180910390f35b61035b60095481565b61035b6107e8565b61039261038d3660046130ba565b610846565b005b6103926103a236600461308d565b610d4e565b6103926103b536600461312b565b610e0e565b61035b60135481565b6103f96103d136600461316d565b60016020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610365565b61035b61042c36600461308d565b600a6020526000908152604090205481565b6103f97f000000000000000000000000baf9a6f8a8afd4be0d85ca40f025bf364fa2732481565b61035b61047336600461308d565b60146020526000908152604090205481565b61035b60075481565b61035b61049c36600461308d565b600d6020526000908152604090205481565b61035b6104bc36600461308d565b61119f565b61035b60105481565b6103f97f0000000000000000000000004245a1bd84eb5f3ebc115c2edf57e50667f98b0b81565b61035b60115481565b610392611292565b61035b60125481565b6103926105193660046130ba565b61135a565b61035b61052c36600461308d565b600c6020526000908152604090205481565b61035b600f5481565b61039261055536600461316d565b61141c565b61056d610568366004613255565b611472565b6040519015158152602001610365565b61039261058b36600461312b565b6114f4565b6105a361059e36600461330d565b6117a7565b60408051928352602083019190915201610365565b61035b6105c636600461308d565b60166020526000908152604090205481565b61035b6105e636600461308d565b600b6020526000908152604090205481565b6004546103f99073ffffffffffffffffffffffffffffffffffffffff1681565b610392610626366004613339565b611859565b61035b61063936600461316d565b60026020526000908152604090205481565b61035b60065481565b61039261066236600461316d565b611a55565b61039261067536600461316d565b611ad9565b610682611b6d565b6040516103659190613431565b6105a361069d36600461330d565b611bfb565b6005546103f99073ffffffffffffffffffffffffffffffffffffffff1681565b6106d56106d036600461316d565b611c71565b60405161036593929190613444565b61035b60085481565b61035b6106fb36600461316d565b611ce7565b61039261070e3660046130ba565b611cf8565b60055461056d9074010000000000000000000000000000000000000000900460ff1681565b61039261074636600461308d565b611d2e565b6103926107593660046134dd565b611dee565b61035b61076c36600461316d565b600e6020526000908152604090205481565b6103f97f00000000000000000000000078ea3fef1c1f07348199bf44f45b803b9b0dbe2881565b610392611fbf565b61035b612051565b61035b6107c336600461308d565b60156020526000908152604090205481565b6103926107e336600461308d565b6120a9565b600754600090806107fb57505060095490565b806006546008544261080d9190613563565b610817919061357a565b61082990670de0b6b3a764000061357a565b61083391906135b7565b60095461084091906135f2565b91505090565b7f0000000000000000000000004245a1bd84eb5f3ebc115c2edf57e50667f98b0b81156108765761087633612176565b60008381526001602052604090205473ffffffffffffffffffffffffffffffffffffffff16338114610980576040517f6352211e00000000000000000000000000000000000000000000000000000000815260048101859052339073ffffffffffffffffffffffffffffffffffffffff841690636352211e90602401602060405180830381865afa15801561090f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610933919061360a565b73ffffffffffffffffffffffffffffffffffffffff1614610980576040517f5483a62900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f5c5503530000000000000000000000000000000000000000000000000000000081526004810185905260009073ffffffffffffffffffffffffffffffffffffffff841690635c5503539060240160e060405180830381865afa1580156109ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a1291906136ef565b905073ffffffffffffffffffffffffffffffffffffffff8216331415610c0d5783610a4057610a4033612176565b6000610a4b866121db565b509150506000610aa2836000816000015178ffffffffffffffffffffffffffffffffffffffffffffffffff16826040015160ff168360a0015160ff16846080015160ff16856060015160ff16020202029050919050565b835160010178ffffffffffffffffffffffffffffffffffffffffffffffffff16808552604085015160a08601516080870151606088015194955060009460ff90811691811691909102918116919091029116020290506000610b048383613563565b336000908152600a6020526040812080548301908190556007805484019055919250610b3290829080612388565b50336000908152600c602052604081205485811015610b5857610b558187613563565b91505b610b628287613563565b8751610b889078ffffffffffffffffffffffffffffffffffffffffffffffffff1661253a565b610b979064e8d4a5100061357a565b610ba19190613563565b336000908152600c602052604081208054909190610bc09084906135f2565b909155505086517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0178ffffffffffffffffffffffffffffffffffffffffffffffffff1687525050505050505b610c3e610c38826000015178ffffffffffffffffffffffffffffffffffffffffffffffffff16611ce7565b85612583565b6040517f0ce90ec20000000000000000000000000000000000000000000000000000000081526004810186905273ffffffffffffffffffffffffffffffffffffffff841690630ce90ec290602401600060405180830381600087803b158015610ca657600080fd5b505af1158015610cba573d6000803e3d6000fd5b50506040517f3d68b4b500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86169250633d68b4b59150610d159060009089908290600401613830565b600060405180830381600087803b158015610d2f57600080fd5b505af1158015610d43573d6000803e3d6000fd5b505050505050505050565b60045473ffffffffffffffffffffffffffffffffffffffff163314610d9f576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f957090e72c0a1b3ebf83c682eb8c1f88c2a18cd0578b91a819efb28859f0f3a390600090a250565b60055474010000000000000000000000000000000000000000900460ff1615610e63576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e6c33612176565b336000908152600a6020908152604080832054600c90925282205490918291849190818367ffffffffffffffff811115610ea857610ea8613186565b604051908082528060200260200182016040528015610ed1578160200160208202803683370190505b50905060008767ffffffffffffffff811115610eef57610eef613186565b604051908082528060200260200182016040528015610f18578160200160208202803683370190505b50905060005b858110156111035760008a8a83818110610f3a57610f3a613855565b60209081029290920135600081815260019093526040909220549192505073ffffffffffffffffffffffffffffffffffffffff163314610fa6576040517f5483a62900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806000610fb4846121db565b91945092509050610fc5838c613563565b9a50610fd1828a6135f2565b985081878681518110610fe657610fe6613855565b6020026020010181815250508086868151811061100557611005613855565b6020908102919091018101919091526000858152600190915260409081902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055517f23b872dd0000000000000000000000000000000000000000000000000000000081523060048201523360248201526044810185905273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004245a1bd84eb5f3ebc115c2edf57e50667f98b0b16906323b872dd90606401600060405180830381600087803b1580156110dc57600080fd5b505af11580156110f0573d6000803e3d6000fd5b5050505084600101945050505050610f1e565b50336000908152600a6020526040902086905583831015611149576111348989848461112f888a613563565b61266f565b336000908152600c6020526040812055611188565b8561116357336000908152600c6020526040812055611188565b336000908152600c602052604081208054869290611182908490613563565b90915550505b6007805487018890039055610d4386600080612388565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600c602052604081205481906111d79064e8d4a51000906135b7565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600a60205260408120549192509061120c9085906117a7565b5073ffffffffffffffffffffffffffffffffffffffff851660009081526014602052604081205491925090611242908690611bfb565b50905061124f81836135f2565b915082821161125e5781611260565b825b73ffffffffffffffffffffffffffffffffffffffff909516600090815260036020526040902054909401949350505050565b61129b33612176565b336000818152600360205260408082208054929055517f40c10f190000000000000000000000000000000000000000000000000000000081526004810192909252602482018190529073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000078ea3fef1c1f07348199bf44f45b803b9b0dbe2816906340c10f1990604401600060405180830381600087803b15801561133f57600080fd5b505af1158015611353573d6000803e3d6000fd5b5050505050565b336000818152601460205260409020546113749190612905565b336000908152600a602052604081205461138f918490612388565b801561141857600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306661abd6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156113ff57600080fd5b505af1158015611413573d6000803e3d6000fd5b505050505b5050565b60045473ffffffffffffffffffffffffffffffffffffffff16331461146d576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600f55565b60006005826060015160ff16108061149157506005826080015160ff16105b806114a3575060058260a0015160ff16105b806114b557506005826040015160ff16105b806114df57506014826000015178ffffffffffffffffffffffffffffffffffffffffffffffffff16105b156114ec57506000919050565b506001919050565b60055474010000000000000000000000000000000000000000900460ff1615611549576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61155233612176565b336000908152600a6020908152604080832054600d90925282205490918291849190815b8381101561176457600088888381811061159257611592613855565b602090810292909201356000818152600e909352604083208690559250819050806115bc846129c6565b9250925092506115cb83611472565b611601576040517f0ce023b900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611652836000816000015178ffffffffffffffffffffffffffffffffffffffffffffffffff16826040015160ff168360a0015160ff16846080015160ff16856060015160ff16020202029050919050565b909801976116608282613563565b61166a90886135f2565b6000858152600160205260409081902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163390811790915590517f23b872dd0000000000000000000000000000000000000000000000000000000081526004810191909152306024820152604481018690529097507f0000000000000000000000004245a1bd84eb5f3ebc115c2edf57e50667f98b0b73ffffffffffffffffffffffffffffffffffffffff16906323b872dd90606401600060405180830381600087803b15801561173d57600080fd5b505af1158015611751573d6000803e3d6000fd5b5050505084600101945050505050611576565b50336000908152600a60209081526040808320879055600c9091528120805484019055600780548601879003905561179e90859080612388565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040812054819081906117e19064e8d4a51000906135b7565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600b602052604081205491925090670de0b6b3a76400009061181d6107e8565b6118279190613563565b611831908761357a565b61183b91906135b7565b905081811161184a578061184c565b815b93509150505b9250929050565b80156118685761186833612176565b60008481526001602052604090205473ffffffffffffffffffffffffffffffffffffffff16338114611992576040517f6352211e00000000000000000000000000000000000000000000000000000000815260048101869052339073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004245a1bd84eb5f3ebc115c2edf57e50667f98b0b1690636352211e90602401602060405180830381865afa158015611921573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611945919061360a565b73ffffffffffffffffffffffffffffffffffffffff1614611992576040517f5483a62900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fc60fb6a70000000000000000000000000000000000000000000000000000000081526113539073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004245a1bd84eb5f3ebc115c2edf57e50667f98b0b169063c60fb6a790611a0c90899089908990600401613884565b6020604051808303816000875af1158015611a2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4f91906138d8565b83612583565b60045473ffffffffffffffffffffffffffffffffffffffff163314801590611a95575060055473ffffffffffffffffffffffffffffffffffffffff163314155b15611acc576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ad4612c10565b601055565b60045473ffffffffffffffffffffffffffffffffffffffff163314611b2a576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b32612c21565b60068190556040518181527f90e51e492b1841b8ed3d459463d02d171ced752c7fcd84a9dd79f90098166aec9060200160405180910390a150565b60008054611b7a9061370b565b80601f0160208091040260200160405190810160405280929190818152602001828054611ba69061370b565b8015611bf35780601f10611bc857610100808354040283529160200191611bf3565b820191906000526020600020905b815481529060010190602001808311611bd657829003601f168201915b505050505081565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c602052604081205481908190611c359064e8d4a51000906135b7565b73ffffffffffffffffffffffffffffffffffffffff861660009081526015602052604081205491925090670de0b6b3a76400009061181d612051565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081018290529080611cb4846129c6565b9194509250905082611ccb64e8d4a51000846135b7565b611cda64e8d4a51000846135b7565b9250925092509193909250565b6000611cf282612c32565b92915050565b33600081815260146020526040902054611d129190612905565b336000908152600a602052604090205461138f90836001612388565b60045473ffffffffffffffffffffffffffffffffffffffff163314611d7f576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f605aa74980dc92c245d8959d233f8c2d7062d874e49326a42e7418279cc8d1f890600090a250565b60055474010000000000000000000000000000000000000000900460ff16611e42576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160005b81811015611353576000858583818110611e6257611e62613855565b60209081029290920135600081815260019093526040909220549192505073ffffffffffffffffffffffffffffffffffffffff858116911614611ed1576040517f5483a62900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600160205260409081902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8581166024830152604482018390527f0000000000000000000000004245a1bd84eb5f3ebc115c2edf57e50667f98b0b16906323b872dd90606401600060405180830381600087803b158015611f9b57600080fd5b505af1158015611faf573d6000803e3d6000fd5b5050505081600101915050611e46565b60045473ffffffffffffffffffffffffffffffffffffffff163314612010576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600580547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b6011546000908061206457505060135490565b80601054601254426120769190613563565b612080919061357a565b61209290670de0b6b3a764000061357a565b61209c91906135b7565b60135461084091906135f2565b60055473ffffffffffffffffffffffffffffffffffffffff1633146120fa576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526014602052604090205461212a8282612905565b806011600082825461213c9190613563565b90915550505073ffffffffffffffffffffffffffffffffffffffff1660009081526014602090815260408083208390556016909152812055565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600a60205260409020546121a7908290612d86565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601460205260409020546121d8908290612905565b50565b336000908152600d6020908152604080832054848452600e9092528220548291829182906122099083613563565b6000878152600e602052604081208490559091508080612228896129c6565b92509250925061227f836000816000015178ffffffffffffffffffffffffffffffffffffffffffffffffff16826040015160ff168360a0015160ff16846080015160ff16856060015160ff16020202029050919050565b9750600061228d898661357a565b61229790846135f2565b905060008282116122a857816122aa565b825b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004245a1bd84eb5f3ebc115c2edf57e50667f98b0b16633d68b4b560008d6122fa64e8d4a51000866135b7565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815261233593929190600401613830565b600060405180830381600087803b15801561234f57600080fd5b505af1158015612363573d6000803e3d6000fd5b505050508981846123749190613563565b909c909b5092995091975050505050505050565b3360009081526014602052604090205482156124f9578115612449576005546040517f5f74bbde0000000000000000000000000000000000000000000000000000000081523360048201526024810185905273ffffffffffffffffffffffffffffffffffffffff90911690635f74bbde90604401600060405180830381600087803b15801561241657600080fd5b505af115801561242a573d6000803e3d6000fd5b5050336000908152601660205260409020805486019055506124f99050565b6005546040517f02aa9be20000000000000000000000000000000000000000000000000000000081523360048201526024810185905273ffffffffffffffffffffffffffffffffffffffff909116906302aa9be290604401600060405180830381600087803b1580156124bb57600080fd5b505af11580156124cf573d6000803e3d6000fd5b505033600090815260166020526040812080548794509092506124f3908490613563565b90915550505b33600090815260166020526040812054612514908690612e47565b336000908152601460205260409020819055601180549091019290920390915550505050565b6000816001141561255457506714d1120d7b160000919050565b816064141561256d5750680ff011d2523cd80000919050565b61257960018303612c32565b600f540292915050565b80156125db57336000908152600360205260409020548281106125bd573360009081526003602052604081208054949094039093556125d9565b80156125d9573360009081526003602052604081205591829003915b505b8115611418576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018390527f00000000000000000000000078ea3fef1c1f07348199bf44f45b803b9b0dbe2873ffffffffffffffffffffffffffffffffffffffff1690639dc29fac90604401600060405180830381600087803b1580156113ff57600080fd5b8360005b8181101561179e5784818151811061268d5761268d613855565b60200260200101516000146128fd578481815181106126ae576126ae613855565b60200260200101518311156127d7577f0000000000000000000000004245a1bd84eb5f3ebc115c2edf57e50667f98b0b73ffffffffffffffffffffffffffffffffffffffff16633d68b4b5600089898581811061270d5761270d613855565b9050602002013564e8d4a5100088868151811061272c5761272c613855565b602002602001015161273e91906135b7565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815261277993929190600401613830565b600060405180830381600087803b15801561279357600080fd5b505af11580156127a7573d6000803e3d6000fd5b505050508481815181106127bd576127bd613855565b6020026020010151836127d09190613563565b92506128fd565b7f0000000000000000000000004245a1bd84eb5f3ebc115c2edf57e50667f98b0b73ffffffffffffffffffffffffffffffffffffffff16633d68b4b5600089898581811061282757612827613855565b9050602002013564e8d4a51000878a878151811061284757612847613855565b60200260200101518a888151811061286157612861613855565b60200260200101516128739190613563565b61287d91906135f2565b61288791906135b7565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526128c293929190600401613830565b600060405180830381600087803b1580156128dc57600080fd5b505af11580156128f0573d6000803e3d6000fd5b505050506000925061179e565b600101612673565b61290d612c10565b801561299957600061292183836001612e62565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600360205260409020805482019055905061295d8164e8d4a5100061357a565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c602052604081208054909190612992908490613563565b9091555050505b5060135473ffffffffffffffffffffffffffffffffffffffff909116600090815260156020526040902055565b6040805160e08101825260008082526020808301829052828401829052606083018290526080830182905260a0830182905260c0830182905283516001808252818601909552929391928392839282015b6060815260200190600190039081612a1757905050905060008054612a3b9061370b565b80601f0160208091040260200160405190810160405280929190818152602001828054612a679061370b565b8015612ab45780601f10612a8957610100808354040283529160200191612ab4565b820191906000526020600020905b815481529060010190602001808311612a9757829003601f168201915b505050505081600081518110612acc57612acc613855565b60200260200101819052506000807f0000000000000000000000004245a1bd84eb5f3ebc115c2edf57e50667f98b0b73ffffffffffffffffffffffffffffffffffffffff16630d51186584896040518363ffffffff1660e01b8152600401612b359291906138f1565b600060405180830381865afa158015612b52573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052612b989190810190613978565b915091508181600081518110612bb057612bb0613855565b602002602001015160001c64e8d4a51000612bcb919061357a565b8351612bf19078ffffffffffffffffffffffffffffffffffffffffffffffffff1661253a565b612c009064e8d4a5100061357a565b9550955095505050509193909250565b612c18612051565b60135542601255565b612c296107e8565b60095542600855565b60010160006064821415612c50575068206aeac7a903980000919050565b600182118015612c605750601582105b15612c765750670de0b6b3a76400000260011c90565b60158210158015612c875750603382105b15612cc557601582036007027a01223448501f3c74e1b3464c172c54a9426488901e3c70d183058a901c607f16670de0b6b3a7640000029050919050565b60338210158015612cd65750605182105b15612d1457603382036007027a023c68b0e14180f9ebc76e9c376cd5a3262c17ae5ab15a9509d325901c607f16670de0b6b3a7640000029050919050565b60518210158015612d255750606582105b15612d5a5760518203600702710c58705ebb6ed59af5aad3a5467ce9b2e549901c607f16670de0b6b3a7640000029050919050565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff919050565b919050565b612d8e612c21565b8015612e1a576000612da283836000612e62565b73ffffffffffffffffffffffffffffffffffffffff841660009081526003602052604090208054820190559050612dde8164e8d4a5100061357a565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c602052604081208054909190612e13908490613563565b9091555050505b5060095473ffffffffffffffffffffffffffffffffffffffff9091166000908152600b6020526040902055565b6000612e5b612e56838561357a565b612f57565b9392505050565b60008060008315612ef457612e778686611bfb565b73ffffffffffffffffffffffffffffffffffffffff88166000908152600a60205260409020549193509150612eb490829064e8d4a510009061303d565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600d602052604081208054909190612ee99084906135f2565b90915550612f4e9050565b612efe86866117a7565b9092509050612f138164e8d4a510008761303d565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600d602052604081208054909190612f489084906135f2565b90915550505b50949350505050565b6001817001000000000000000000000000000000008110612f7d5760409190911b9060801c5b680100000000000000008110612f985760209190911b9060401c5b6401000000008110612faf5760109190911b9060201c5b620100008110612fc45760089190911b9060101c5b6101008110612fd85760049190911b9060081c5b60108110612feb5760029190911b9060041c5b60088110612ffa578160011b91505b5080820401600190811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c80820481811015613037578091505b50919050565b82820281151584158583048514171661305557600080fd5b6001826001830304018115150290509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146121d857600080fd5b60006020828403121561309f57600080fd5b8135612e5b8161306b565b80358015158114612d8157600080fd5b600080604083850312156130cd57600080fd5b823591506130dd602084016130aa565b90509250929050565b60008083601f8401126130f857600080fd5b50813567ffffffffffffffff81111561311057600080fd5b6020830191508360208260051b850101111561185257600080fd5b6000806020838503121561313e57600080fd5b823567ffffffffffffffff81111561315557600080fd5b613161858286016130e6565b90969095509350505050565b60006020828403121561317f57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156131fc576131fc613186565b604052919050565b78ffffffffffffffffffffffffffffffffffffffffffffffffff811681146121d857600080fd5b61ffff811681146121d857600080fd5b60ff811681146121d857600080fd5b8035612d818161323b565b600060e0828403121561326757600080fd5b60405160e0810181811067ffffffffffffffff8211171561328a5761328a613186565b604052823561329881613204565b815260208301356132a88161322b565b602082015260408301356132bb8161323b565b604082015260608301356132ce8161323b565b60608201526132df6080840161324a565b60808201526132f060a0840161324a565b60a082015261330160c0840161324a565b60c08201529392505050565b6000806040838503121561332057600080fd5b823561332b8161306b565b946020939093013593505050565b6000806000806060858703121561334f57600080fd5b84359350602085013567ffffffffffffffff8082111561336e57600080fd5b818701915087601f83011261338257600080fd5b81358181111561339157600080fd5b8860208285010111156133a357600080fd5b6020830195508094505050506133bb604086016130aa565b905092959194509250565b6000815180845260005b818110156133ec576020818501810151868301820152016133d0565b818111156133fe576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612e5b60208301846133c6565b60006101208201905078ffffffffffffffffffffffffffffffffffffffffffffffffff855116825261ffff602086015116602083015260ff604086015116604083015260ff606086015116606083015260ff608086015116608083015260a08501516134b560a084018260ff169052565b5060c08501516134ca60c084018260ff169052565b5060e08201939093526101000152919050565b6000806000604084860312156134f257600080fd5b833567ffffffffffffffff81111561350957600080fd5b613515868287016130e6565b90945092505060208401356135298161306b565b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561357557613575613534565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156135b2576135b2613534565b500290565b6000826135ed577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000821982111561360557613605613534565b500190565b60006020828403121561361c57600080fd5b8151612e5b8161306b565b8051612d818161323b565b600060e0828403121561364457600080fd5b60405160e0810181811067ffffffffffffffff8211171561366757613667613186565b8060405250809150825161367a81613204565b8152602083015161368a8161322b565b6020820152604083015161369d8161323b565b604082015260608301516136b08161323b565b60608201526136c160808401613627565b60808201526136d260a08401613627565b60a08201526136e360c08401613627565b60c08201525092915050565b600060e0828403121561370157600080fd5b612e5b8383613632565b600181811c9082168061371f57607f821691505b60208210811415613037577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8054600090600181811c908083168061377357607f831692505b60208084108214156137ae577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b838852602088018280156137c957600181146137f857613823565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00871682528282019750613823565b60008981526020902060005b8781101561381d57815484820152908601908401613804565b83019850505b5050505050505092915050565b6060815260006138436060830186613759565b60208301949094525060400152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b83815260406020820152816040820152818360608301376000818301606090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010192915050565b6000602082840312156138ea57600080fd5b5051919050565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b83811015613966577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08887030185526139548683516133c6565b9550938201939082019060010161391a565b50509490940194909452949350505050565b600080610100838503121561398c57600080fd5b6139968484613632565b915060e083015167ffffffffffffffff808211156139b357600080fd5b818501915085601f8301126139c757600080fd5b81516020828211156139db576139db613186565b8160051b92506139ec8184016131b5565b8281529284018101928181019089851115613a0657600080fd5b948201945b84861015613a2457855182529482019490820190613a0b565b809650505050505050925092905056fea26469706673582212207dafd72379692ef45e0c5a4f2adbce4b0b1307c1dfaf6cfc4d03d6854d7760bb64736f6c634300080c0033
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:995: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;96836:374::-;;;;;;:::i;:::-;;:::i;:::-;;;4632:14:1;;4625:22;4607:41;;4595:2;4580:18;96836:374: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;:::-;81902:62;;;;82070:23;82096:27;82116:6;97347:7;97608:6;:12;;;97600:21;;97564:6;:15;;;97556:24;;97516:6;:19;;;97508:28;;97472:6;:15;;;97464:24;;97429:6;:14;;;97421:23;;:67;:115;:159;:200;97397:224;;97218:422;;;;82096:27;82167:14;;;;;;;;;97564:15;;;;97516:19;;;;97472:15;;;;97429:14;;;;82070:53;;-1:-1:-1;;;97556:24:0;97421:23;;;97464:24;;;97421:67;;;;97508:28;;;97421:115;;;;97556:24;;97421:159;:200;82293:52;-1:-1:-1;82403:12:0;82418:32;82435:15;82293:52;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;96836:374::-;96952:4;97009:1;96992:6;:14;;;:18;;;:54;;;;97045:1;97027:6;:15;;;:19;;;96992:54;:94;;;;97085:1;97063:6;:19;;;:23;;;96992:94;:130;;;;97121:1;97103:6;:15;;;:19;;;96992:130;:164;;;;97154:2;97139:6;:12;;;:17;;;96992:164;96974:206;;;-1:-1:-1;97175:5:0;;96836:374;-1:-1:-1;96836:374:0:o;96974:206::-;-1:-1:-1;97198:4:0;;96836:374;-1:-1:-1;96836:374:0: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;84619:6;84610:8;:16::i;:::-;84605:43;;84635:13;;;;;;;;;;;;;;84605:43;84751:27;84771:6;97347:7;97608:6;:12;;;97600:21;;97564:6;:15;;;97556:24;;97516:6;:19;;;97508:28;;97472:6;:15;;;97464:24;;97429:6;:14;;;97421:23;;:67;:115;:159;:200;97397:224;;97218:422;;;;84751:27;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;:::-;93762:157;;;;;;93947:27;93967:6;97347:7;97608:6;:12;;;97600:21;;97564:6;:15;;;97556:24;;97516:6;:19;;;97508:28;;97472:6;:15;;;97464:24;;97429:6;:14;;;97421:23;;:67;:115;:159;:200;97397:224;;97218:422;;;;93947:27;93932:42;-1:-1:-1;93987:29:0;94050:45;93932:42;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://7dafd72379692ef45e0c5a4f2adbce4b0b1307c1dfaf6cfc4d03d6854d7760bb
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.