ERC-721
Overview
Max Total Supply
604 TGAME
Holders
45
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
8 TGAMELoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
Goat
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity Multiple files format)
// SPDX-License-Identifier: MIT LICENSE pragma solidity ^0.8.0; import "./Ownable.sol"; import "./Pausable.sol"; import "./ERC721Enumerable.sol"; import "./IGoat.sol"; import "./IIsle.sol"; import "./ITraits.sol"; import "./EGGS.sol"; contract Goat is IGoat, ERC721Enumerable, Ownable, Pausable { // mint price uint256 public constant MINT_PRICE = .042069 ether; // max number of tokens that can be minted - 50000 in production uint256 public immutable MAX_TOKENS; // number of tokens that can be claimed for free - 20% of MAX_TOKENS uint256 public PAID_TOKENS; // number of tokens have been minted so far uint16 public minted; //Whitelisted address mapping(address => uint) public whitelist; // mapping from tokenId to a struct containing the token's traits mapping(uint256 => TortoiseGoat) public tokenTraits; // mapping from hashed(tokenTrait) to the tokenId it's associated with // used to ensure there are no duplicates mapping(uint256 => uint256) public existingCombinations; // list of probabilities for each trait type // 0 - 9 are associated with Tortoise, 10 - 18 are associated with Goats uint8[][18] public rarities; // list of aliases for Walker's Alias algorithm // 0 - 9 are associated with Tortoise, 10 - 18 are associated with Goats uint8[][18] public aliases; // reference to the Isle for choosing random Goat thieves IIsle public isle; // reference to $EGGS for burning on mint EGGS public eggs; // reference to Traits ITraits public traits; /** * instantiates contract and rarity tables */ constructor(address _eggs, address _traits, uint256 _maxTokens) ERC721("Tortoise Game", 'TGAME') { eggs = EGGS(_eggs); traits = ITraits(_traits); MAX_TOKENS = _maxTokens; PAID_TOKENS = _maxTokens / 5; //Tortoise //fur rarities[0] = [15, 50, 200, 250, 255, 50, 60, 80, 15, 90, 11, 15, 13, 15, 50, 19, 99, 50, 80, 100]; aliases[0] = [4, 4, 4, 4, 4,4, 4, 4, 4, 4,4, 4, 4, 4, 4,4, 4, 4, 4, 4]; // head rarities[1] = [190, 215, 240, 100, 110, 135, 160, 185, 80, 210]; aliases[1] = [1, 2, 4, 0, 5, 6, 7, 9, 0, 10]; // ears rarities[2] = [255, 30, 60, 60, 150, 156,255, 30, 60, 60, 150, 156,255, 30, 60, 60, 150, 156,90,85]; aliases[2] = [0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0,0, 0, 0, 0, 0,0, 0, 0, 0]; // eyes rarities[3] = [221, 100, 181, 140, 224]; aliases[3] = [1, 2, 5, 0, 1]; // nose rarities[4] = [175, 100, 40, 250, 115]; aliases[4] = [3, 0, 4, 6, 6]; // mouth rarities[5] = [80, 225, 227, 228, 112, 240, 64, 160, 167, 217]; aliases[5] = [1, 2, 3, 8, 2, 8, 8, 9, 9, 10]; // neck rarities[6] = [255]; aliases[6] = [0]; // feet rarities[7] = [243, 189, 133, 133, 57, 95, 152, 135, 133, 57, 222, 168, 57, 57, 38, 114, 114, 114, 33, 255]; aliases[7] = [1, 7, 0, 0, 0, 0, 0, 10, 0, 0, 11, 18, 0, 0, 0, 1, 7, 11, 18, 22]; // alphaIndex rarities[8] = [255]; aliases[8] = [0]; // Goats // fur rarities[9] = [210, 90, 9, 9, 9, 150, 9, 255, 9, 50,210, 90, 9, 9, 9, 150, 9, 255, 9, 50 ]; aliases[9] = [5, 0, 0, 5, 5, 7, 5, 7, 5, 0, 5, 0, 0, 5, 5, 7, 5, 7, 5, 0]; // head rarities[10] = [0,1,2,3,4,5,6,7,255]; aliases[10] = [0,0,0,0,0,0,0,0,0]; // ears rarities[11] = [255]; aliases[11] = [0]; // eyes rarities[12] = [135, 177, 219, 141, 183, 225, 147, 189, 231, 135]; aliases[12] = [1, 2, 3, 4, 5, 6, 7, 8, 13, 3]; // nose rarities[13] = [255]; aliases[13] = [0]; // mouth rarities[14] = [255, 244, 249, 234]; aliases[14] = [1, 2, 11, 0]; // neck rarities[15] = [75, 180, 165, 120, 60, 150, 105, 195, 45, 225]; aliases[15] = [1, 9, 0, 0, 0, 0, 0, 0, 0, 12]; // feet rarities[16] = [75, 180, 165, 120, 60, 150, 105, 195, 45, 225]; aliases[16] = [1, 9, 0, 0, 0, 0, 0, 0, 0, 12]; // alphaIndex rarities[17] = [8, 160, 73, 255]; aliases[17] = [2, 3, 3, 3]; } /** EXTERNAL */ /** * mint a token - 90% Tortoise, 10% Goats * The first 20% use eth to pay, the remaining cost $EGGS */ function mint(uint256 amount, bool stake) private { uint16[] memory tokenIds = stake ? new uint16[](amount) : new uint16[](0); uint256 seed; for (uint i = 0; i < amount; i++) { minted++; seed = random(minted); generate(minted, seed); address recipient = selectRecipient(seed); if (!stake || recipient != _msgSender()) { _safeMint(recipient, minted); } else { _safeMint(address(isle), minted); tokenIds[i] = minted; } } if (stake) isle.addManyToIsleAndPack(_msgSender(), tokenIds); } function mint_EGGS(uint256 amount, bool stake) external whenNotPaused { uint256 totalEggsCost = 0; require(tx.origin == _msgSender(), "Only EOA"); require(minted + amount >= PAID_TOKENS, "Only with ETH"); require(amount > 0 && amount <= 4, "Invalid mint amount"); for (uint x = 0; x < amount; x++) { //Calculate total cost in EGGS totalEggsCost += mintCost(minted+x); } uint allowance_eggs; allowance_eggs = eggs.allowance(address(this),msg.sender); if (allowance_eggs < totalEggsCost) { bool approve_eggs; approve_eggs = eggs.approve(address(this),2000000000000000000000000); require(approve_eggs,"Can't use your EGGS"); } require(eggs.transferFrom(msg.sender, address(this), totalEggsCost), "Error sending EGGS"); mint(amount, stake); } function mint_ETH(uint256 amount, bool stake) external payable whenNotPaused { require(tx.origin == _msgSender(), "Only EOA"); require(minted + amount <= PAID_TOKENS, "All tokens minted"); require(amount > 0 && amount <= 4, "Invalid mint amount"); require(amount * MINT_PRICE == msg.value, "Invalid payment amount"); mint(amount, stake); } /** * the first 20% are paid in eth * the next 20% are 20000 $EGGS * the next 40% are 40000 $EGGS * the final 20% are 80000 $EGGS * @param tokenId the ID to check the cost of to mint * @return the cost of the given token ID */ function mintCost(uint256 tokenId) public view returns (uint256) { if (tokenId <= PAID_TOKENS) return 20000 ether; if (tokenId <= MAX_TOKENS * 2 / 5) return 20000 ether; if (tokenId <= MAX_TOKENS * 4 / 5) return 40000 ether; return 80000 ether; } function transferFrom( address from, address to, uint256 tokenId ) public virtual override { // Hardcode the Isle's approval so that users don't have to waste gas approving if (_msgSender() != address(isle)) require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _transfer(from, to, tokenId); } /** INTERNAL */ /** * generates traits for a specific token, checking to make sure it's unique * @param tokenId the id of the token to generate traits for * @param seed a pseudorandom 256 bit number to derive traits from * @return t - a struct of traits for the given token ID */ function generate(uint256 tokenId, uint256 seed) internal returns (TortoiseGoat memory t) { t = selectTraits(seed); if (existingCombinations[structToHash(t)] == 0) { tokenTraits[tokenId] = t; existingCombinations[structToHash(t)] = tokenId; return t; } return generate(tokenId, random(seed)); } /** * uses A.J. Walker's Alias algorithm for O(1) rarity table lookup * ensuring O(1) instead of O(n) reduces mint cost by more than 50% * probability & alias tables are generated off-chain beforehand * @param seed portion of the 256 bit seed to remove trait correlation * @param traitType the trait type to select a trait for * @return the ID of the randomly selected trait */ function selectTrait(uint16 seed, uint8 traitType) internal view returns (uint8) { uint8 trait = uint8(seed) % uint8(rarities[traitType].length); if (seed >> 8 < rarities[traitType][trait]) return trait; return aliases[traitType][trait]; } /** * the first 20% (ETH purchases) go to the minter * the remaining 80% have a 10% chance to be given to a random staked Goat * @param seed a random value to select a recipient from * @return the address of the recipient (either the minter or the Goat thief's owner) */ function selectRecipient(uint256 seed) internal view returns (address) { if (minted <= PAID_TOKENS || ((seed >> 245) % 10) != 0) return _msgSender(); // top 10 bits haven't been used address thief = isle.randomGoatOwner(seed >> 144); // 144 bits reserved for trait selection if (thief == address(0x0)) return _msgSender(); return thief; } /** * selects the species and all of its traits based on the seed value * @param seed a pseudorandom 256 bit number to derive traits from * @return t - a struct of randomly selected traits */ function selectTraits(uint256 seed) internal view returns (TortoiseGoat memory t) { t.isTortoise = (seed & 0xFFFF) % 10 != 0; uint8 shift = t.isTortoise ? 0 : 9; seed >>= 16; t.fur = selectTrait(uint16(seed & 0xFFFF), 0 + shift); seed >>= 16; t.head = selectTrait(uint16(seed & 0xFFFF), 1 + shift); seed >>= 16; t.ears = selectTrait(uint16(seed & 0xFFFF), 2 + shift); seed >>= 16; t.eyes = selectTrait(uint16(seed & 0xFFFF), 3 + shift); seed >>= 16; t.nose = selectTrait(uint16(seed & 0xFFFF), 4 + shift); seed >>= 16; t.mouth = selectTrait(uint16(seed & 0xFFFF), 5 + shift); seed >>= 16; t.neck = selectTrait(uint16(seed & 0xFFFF), 6 + shift); seed >>= 16; t.feet = selectTrait(uint16(seed & 0xFFFF), 7 + shift); seed >>= 16; t.alphaIndex = selectTrait(uint16(seed & 0xFFFF), 8 + shift); } /** * converts a struct to a 256 bit hash to check for uniqueness * @param s the struct to pack into a hash * @return the 256 bit hash of the struct * bytes32 -> keccak256 */ function structToHash(TortoiseGoat memory s) internal pure returns (uint256) { return uint256(keccak256( abi.encodePacked( s.isTortoise, s.fur, s.head, s.eyes, s.mouth, s.neck, s.ears, s.feet, s.alphaIndex ) )); } /** * generates a pseudorandom number * @param seed a value ensure different outcomes for different sources in the same block * @return a pseudorandom value */ function random(uint256 seed) internal view returns (uint256) { return uint256(keccak256(abi.encodePacked( tx.origin, blockhash(block.number - 1), block.timestamp, seed ))); } /** READ */ function getTokenTraits(uint256 tokenId) external view override returns (TortoiseGoat memory) { return tokenTraits[tokenId]; } function getPaidTokens() external view override returns (uint256) { return PAID_TOKENS; } /** ADMIN */ /** * called after deployment so that the contract can get random goat thieves * @param _isle the address of the Isle */ function setIsle(address _isle) external onlyOwner { isle = IIsle(_isle); } /** * allows owner to withdraw funds from minting */ function withdraw() external onlyOwner { payable(owner()).transfer(address(this).balance); uint EGGSbalance = eggs.balanceOf(address(this)); eggs.transfer(owner(),EGGSbalance); } /** * updates the number of tokens for sale */ function setPaidTokens(uint256 _paidTokens) external onlyOwner { PAID_TOKENS = _paidTokens; } /** * enables owner to pause / unpause minting */ function setPaused(bool _paused) external onlyOwner { if (_paused) _pause(); else _unpause(); } /** RENDER */ function tokenURI(uint256 tokenId) public view override returns (string memory) { require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); return traits.tokenURI(tokenId); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT LICENSE pragma solidity ^0.8.0; import "./ERC20.sol"; import "./Ownable.sol"; contract EGGS is ERC20, Ownable { // a mapping from an address to whether or not it can mint / burn mapping(address => bool) controllers; constructor() ERC20("EGGS", "EGGS") { } /** * mints $WOOL to a recipient * @param to the recipient of the $EGGS * @param amount the amount of $EGGS to mint */ function mint(address to, uint256 amount) external { require(controllers[msg.sender], "Only controllers can mint"); _mint(to, amount); } /** * burns $EGGS from a holder * @param from the holder of the $WOOL * @param amount the amount of $WOOL to burn */ function burn(address from, uint256 amount) external { require(controllers[msg.sender], "Only controllers can burn"); _burn(from, amount); } /** * enables an address to mint / burn * @param controller the address to enable */ function addController(address controller) external onlyOwner { controllers[controller] = true; } /** * disables an address from minting / burning * @param controller the address to disbale */ function removeController(address controller) external onlyOwner { controllers[controller] = false; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC20.sol"; import "./IERC20Metadata.sol"; import "./Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); unchecked { _approve(sender, _msgSender(), currentAllowance - amount); } return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(_msgSender(), spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `sender` to `recipient`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[sender] = senderBalance - amount; } _balances[recipient] += amount; emit Transfer(sender, recipient, amount); _afterTokenTransfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./IERC721Metadata.sol"; import "./Address.sol"; import "./Context.sol"; import "./Strings.sol"; import "./ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: balance query for the zero address"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _owners[tokenId]; require(owner != address(0), "ERC721: owner query for nonexistent token"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overriden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not owner nor approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { require(_exists(tokenId), "ERC721: approved query for nonexistent token"); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { require(operator != _msgSender(), "ERC721: approve to caller"); _operatorApprovals[_msgSender()][operator] = approved; emit ApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory _data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _safeTransfer(from, to, tokenId, _data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `_data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory _data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _owners[tokenId] != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { require(_exists(tokenId), "ERC721: operator query for nonexistent token"); address owner = ERC721.ownerOf(tokenId); return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint( address to, uint256 tokenId, bytes memory _data ) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId); _balances[to] += 1; _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); _balances[owner] -= 1; delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner _approve(address(0), tokenId); _balances[from] -= 1; _balances[to] += 1; _owners[tokenId] = to; emit Transfer(from, to, tokenId); } /** * @dev Approve `to` to operate on `tokenId` * * Emits a {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param _data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory _data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./ERC721.sol"; import "./IERC721Enumerable.sol"; /** * @dev This implements an optional extension of {ERC721} defined in the EIP that adds * enumerability of all the token ids in the contract as well as all token ids owned by each * account. */ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => mapping(uint256 => uint256)) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) { require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds"); return _ownedTokens[owner][index]; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _allTokens.length; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds"); return _allTokens[index]; } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` cannot be the zero address. * - `to` cannot be the zero address. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override { super._beforeTokenTransfer(from, to, tokenId); if (from == address(0)) { _addTokenToAllTokensEnumeration(tokenId); } else if (from != to) { _removeTokenFromOwnerEnumeration(from, tokenId); } if (to == address(0)) { _removeTokenFromAllTokensEnumeration(tokenId); } else if (to != from) { _addTokenToOwnerEnumeration(to, tokenId); } } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { uint256 length = ERC721.balanceOf(to); _ownedTokens[to][length] = tokenId; _ownedTokensIndex[tokenId] = length; } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = ERC721.balanceOf(from) - 1; uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array delete _ownedTokensIndex[tokenId]; delete _ownedTokens[from][lastTokenIndex]; } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length - 1; uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array delete _allTokensIndex[tokenId]; _allTokens.pop(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT LICENSE pragma solidity ^0.8.0; interface IGoat { // struct to store each token's traits struct TortoiseGoat { bool isTortoise; uint8 fur; uint8 head; uint8 ears; uint8 eyes; uint8 nose; uint8 mouth; uint8 neck; uint8 feet; uint8 alphaIndex; } function getPaidTokens() external view returns (uint256); function getTokenTraits(uint256 tokenId) external view returns (TortoiseGoat memory); }
// SPDX-License-Identifier: MIT LICENSE pragma solidity ^0.8.0; interface IIsle { function addManyToIsleAndPack(address account, uint16[] calldata tokenIds) external; function randomGoatOwner(uint256 seed) external view returns (address); }
// SPDX-License-Identifier: MIT LICENSE pragma solidity ^0.8.0; import "./IERC721Receiver.sol"; import "./Pausable.sol"; import "./Goat.sol"; import "./EGGS.sol"; contract Isle is Ownable, IERC721Receiver, Pausable { // maximum alpha score for a Goat uint8 public constant MAX_ALPHA = 8; bool lock; // struct to store a stake's token, owner, and earning values struct Stake { uint16 tokenId; uint80 value; address owner; } event TokenStaked(address owner, uint256 tokenId, uint256 value); event TortoiseClaimed(uint256 tokenId, uint256 earned, bool unstaked); event GoatClaimed(uint256 tokenId, uint256 earned, bool unstaked); // reference to the Goat NFT contract Goat goat; // reference to the $EGGS contract for minting $EGGS earnings EGGS eggs; //Tokens in STAKING mapping(address => mapping(uint256 => uint256)) public mymap; uint256 contador; mapping(address => uint256) public contadorArr; //End Tokens in STAKING // maps tokenId to stake mapping(uint256 => Stake) public isle; // maps alpha to all Goat stakes with that alpha mapping(uint256 => Stake[]) public pack; // tracks location of each Goat in Pack mapping(uint256 => uint256) public packIndices; // total alpha scores staked uint256 public totalAlphaStaked = 0; // any rewards distributed when no wolves are staked uint256 public unaccountedRewards = 0; // amount of $EGGS due for each alpha point staked uint256 public eggsPerAlpha = 0; // totalNFT staked uint256 public totalNFT; // tortoise earn 10000 $EGGS per day uint256 public constant DAILY_EGGS_RATE = 10000 ether; // tortoise must have 2 days worth of $EGGS to unstake or else it's too cold //uint256 public constant MINIMUM_TO_EXIT = 2 days; uint256 public constant MINIMUM_TO_EXIT = 2 days; // Goat take a 20% tax on all $EGGS claimed uint256 public constant EGGS_CLAIM_TAX_PERCENTAGE = 20; // there will only ever be (roughly) 2.4 billion $EGGS earned through staking uint256 public constant MAXIMUM_GLOBAL_EGGS = 2400000000 ether; // amount of $EGGS earned so far uint256 public totalEggsEarned; // number of Tortoise staked in the Isle uint256 public totalTortoiseStaked; // the last time $EGGS was claimed uint256 public lastClaimTimestamp; // emergency rescue to allow unstaking without any checks but without $EGGS bool public rescueEnabled = false; /** * @param _goat reference to the Tortoise NFT contract * @param _eggs reference to the $EGGS token */ constructor(address _goat, address _eggs) { goat = Goat(_goat); eggs = EGGS(_eggs); } /** STAKING */ /** * adds Tortoises and Goats to the Isle and Pack * @param account the address of the staker * @param tokenIds the IDs of the Tortoises and Goats to stake */ function addManyToIsleAndPack(address account, uint16[] calldata tokenIds) external { require(account == _msgSender() || _msgSender() == address(goat), "DONT GIVE YOUR TOKENS AWAY"); for (uint i = 0; i < tokenIds.length; i++) { if (_msgSender() != address(goat)) { // dont do this step if its a mint + stake require(goat.ownerOf(tokenIds[i]) == _msgSender(), "AINT YO TOKEN"); goat.transferFrom(_msgSender(), address(this), tokenIds[i]); } else if (tokenIds[i] == 0) { continue; // there may be gaps in the array for stolen tokens } if (isTortoise(tokenIds[i])) _addTortoiseToIsle(account, tokenIds[i]); else _addGoatToPack(account, tokenIds[i]); } } /** * adds a single Tortoise to the Isle * @param account the address of the staker * @param tokenId the ID of the Tortoise to add to the Isle */ function _addTortoiseToIsle(address account, uint256 tokenId) internal whenNotPaused _updateEarnings { isle[tokenId] = Stake({ owner: account, tokenId: uint16(tokenId), value: uint80(block.timestamp) }); totalTortoiseStaked += 1; totalNFT += 1; _addNFT(account,tokenId); emit TokenStaked(account, tokenId, block.timestamp); } /** * adds a single Goat to the Pack * @param account the address of the staker * @param tokenId the ID of the Goat to add to the Pack */ function _addGoatToPack(address account, uint256 tokenId) internal { uint256 alpha = _alphaForGoat(tokenId); totalAlphaStaked += alpha; // Portion of earnings ranges from 8 to 5 packIndices[tokenId] = pack[alpha].length; // Store the location of the Goat in the Pack pack[alpha].push(Stake({ owner: account, tokenId: uint16(tokenId), value: uint80(eggsPerAlpha) })); // Add the goat to the Pack totalNFT += 1; _addNFT(account,tokenId); emit TokenStaked(account, tokenId, eggsPerAlpha); } /** CLAIMING / UNSTAKING */ /** * realize $EGGS earnings and optionally unstake tokens from the Isle / Pack * to unstake a Tortoise it will require it has 2 days worth of $EGGS unclaimed * @param tokenIds the IDs of the tokens to claim earnings from * @param unstake whether or not to unstake ALL of the tokens listed in tokenIds */ function claimManyFromIsleAndPack(uint16[] calldata tokenIds, bool unstake) external whenNotPaused _updateEarnings { uint256 owed = 0; for (uint i = 0; i < tokenIds.length; i++) { if (isTortoise(tokenIds[i])) owed += _claimTortoiseFromIsle(tokenIds[i], unstake); else owed += _claimGoatFromPack(tokenIds[i], unstake); } if (owed == 0) return; eggs.mint(_msgSender(), owed); } /** * realize $EGGS earnings for a single Tortoise and optionally unstake it * if not unstaking, pay a 20% tax to the staked Goats * if unstaking, there is a 50% chance all $EGGS is stolen * @param tokenId the ID of the Tortoise to claim earnings from * @param unstake whether or not to unstake the Tortoise * @return owed - the amount of $EGGS earned */ function _claimTortoiseFromIsle(uint256 tokenId, bool unstake) internal returns (uint256 owed) { require(!lock); lock = true; Stake memory stake = isle[tokenId]; require(stake.owner == _msgSender(), "SWIPER, NO SWIPING"); require(!(unstake && block.timestamp - stake.value < MINIMUM_TO_EXIT), "GONNA BE COLD WITHOUT TWO DAY'S EGGS"); if (totalEggsEarned < MAXIMUM_GLOBAL_EGGS) { owed = (block.timestamp - stake.value) * DAILY_EGGS_RATE / 1 days; } else if (stake.value > lastClaimTimestamp) { owed = 0; // $EGGS production stopped already } else { owed = (lastClaimTimestamp - stake.value) * DAILY_EGGS_RATE / 1 days; // stop earning additional $EGGS if it's all been earned } if (unstake) { if (random(tokenId) & 1 == 1) { // 50% chance of all $EGGS stolen _payGoatTax(owed); owed = 0; } goat.safeTransferFrom(address(this), _msgSender(), tokenId, ""); // send back Tortoise delete isle[tokenId]; totalTortoiseStaked -= 1; totalNFT -= 1; _deleNFT(_msgSender(),tokenId); } else { _payGoatTax(owed * EGGS_CLAIM_TAX_PERCENTAGE / 100); // percentage tax to staked goats owed = owed * (100 - EGGS_CLAIM_TAX_PERCENTAGE) / 100; // remainder goes to goat owner isle[tokenId] = Stake({ owner: _msgSender(), tokenId: uint16(tokenId), value: uint80(block.timestamp) }); // reset stake } emit TortoiseClaimed(tokenId, owed, unstake); lock = false; } /** * realize $EGGS earnings for a single Goat and optionally unstake it * Wolves earn $EGGS proportional to their Alpha rank * @param tokenId the ID of the Goat to claim earnings from * @param unstake whether or not to unstake the Goat * @return owed - the amount of $EGGS earned */ function _claimGoatFromPack(uint256 tokenId, bool unstake) internal returns (uint256 owed) { require(!lock); lock = true; require(goat.ownerOf(tokenId) == address(this), "AINT A PART OF THE PACK"); uint256 alpha = _alphaForGoat(tokenId); Stake memory stake = pack[alpha][packIndices[tokenId]]; require(stake.owner == _msgSender(), "SWIPER, NO SWIPING"); owed = (alpha) * (eggsPerAlpha - stake.value); // Calculate portion of tokens based on Alpha if (unstake) { totalAlphaStaked -= alpha; // Remove Alpha from total staked totalNFT -= 1; goat.safeTransferFrom(address(this), _msgSender(), tokenId, ""); // Send back Goat Stake memory lastStake = pack[alpha][pack[alpha].length - 1]; pack[alpha][packIndices[tokenId]] = lastStake; // Shuffle last Goat to current position packIndices[lastStake.tokenId] = packIndices[tokenId]; pack[alpha].pop(); // Remove duplicate delete packIndices[tokenId]; // Delete old mapping _deleNFT(_msgSender(),tokenId); } else { pack[alpha][packIndices[tokenId]] = Stake({ owner: _msgSender(), tokenId: uint16(tokenId), value: uint80(eggsPerAlpha) }); // reset stake } emit GoatClaimed(tokenId, owed, unstake); lock = false; } /** * emergency unstake tokens * @param tokenIds the IDs of the tokens to claim earnings from */ function rescue(uint256[] calldata tokenIds) external { require(rescueEnabled, "RESCUE DISABLED"); uint256 tokenId; Stake memory stake; Stake memory lastStake; uint256 alpha; for (uint i = 0; i < tokenIds.length; i++) { tokenId = tokenIds[i]; if (isTortoise(tokenId)) { stake = isle[tokenId]; require(stake.owner == _msgSender(), "SWIPER, NO SWIPING"); goat.safeTransferFrom(address(this), _msgSender(), tokenId, ""); // send back Tortoise delete isle[tokenId]; totalTortoiseStaked -= 1; emit TortoiseClaimed(tokenId, 0, true); } else { alpha = _alphaForGoat(tokenId); stake = pack[alpha][packIndices[tokenId]]; require(stake.owner == _msgSender(), "SWIPER, NO SWIPING"); totalAlphaStaked -= alpha; // Remove Alpha from total staked goat.safeTransferFrom(address(this), _msgSender(), tokenId, ""); // Send back Goat lastStake = pack[alpha][pack[alpha].length - 1]; pack[alpha][packIndices[tokenId]] = lastStake; // Shuffle last Goat to current position packIndices[lastStake.tokenId] = packIndices[tokenId]; pack[alpha].pop(); // Remove duplicate delete packIndices[tokenId]; // Delete old mapping emit GoatClaimed(tokenId, 0, true); } } } /** ACCOUNTING */ /** * add $EGGS to claimable pot for the Pack * @param amount $EGGS to add to the pot */ function _payGoatTax(uint256 amount) internal { if (totalAlphaStaked == 0) { // if there's no staked goats unaccountedRewards += amount; // keep track of $EGGS due to wolves return; } // makes sure to include any unaccounted $EGGS eggsPerAlpha += (amount + unaccountedRewards) / totalAlphaStaked; unaccountedRewards = 0; } /** * tracks $EGGS earnings to ensure it stops once 2.4 billion is eclipsed */ modifier _updateEarnings() { if (totalEggsEarned < MAXIMUM_GLOBAL_EGGS) { totalEggsEarned += (block.timestamp - lastClaimTimestamp) * totalTortoiseStaked * DAILY_EGGS_RATE / 1 days; lastClaimTimestamp = block.timestamp; } _; } /** ADMIN */ /** * allows owner to enable "rescue mode" * simplifies accounting, prioritizes tokens out in emergency */ function setRescueEnabled(bool _enabled) external onlyOwner { rescueEnabled = _enabled; } /** * enables owner to pause / unpause minting */ function setPaused(bool _paused) external onlyOwner { if (_paused) _pause(); else _unpause(); } /** READ ONLY */ /** * checks if a token is a Tortoise * @param tokenId the ID of the token to check * @return tortoise - whether or not a token is a Tortoise */ function isTortoise(uint256 tokenId) public view returns (bool tortoise) { (tortoise, , , , , , , , , ) = goat.tokenTraits(tokenId); } /** * gets the alpha score for a Goat * @param tokenId the ID of the Goat to get the alpha score for * @return the alpha score of the Goat (5-8) */ function _alphaForGoat(uint256 tokenId) internal view returns (uint8) { ( , , , , , , , , , uint8 alphaIndex) = goat.tokenTraits(tokenId); return MAX_ALPHA - alphaIndex; // alpha index is 0-3 } /** * chooses a random Goat thief when a newly minted token is stolen * @param seed a random value to choose a Goat from * @return the owner of the randomly selected Goat thief */ function randomGoatOwner(uint256 seed) external view returns (address) { if (totalAlphaStaked == 0) return address(0x0); uint256 bucket = (seed & 0xFFFFFFFF) % totalAlphaStaked; // choose a value from 0 to total alpha staked uint256 cumulative; seed >>= 32; // loop through each bucket of Wolves with the same alpha score for (uint i = MAX_ALPHA - 3; i <= MAX_ALPHA; i++) { cumulative += pack[i].length * i; // if the value is not inside of that bucket, keep going if (bucket >= cumulative) continue; // get the address of a random Goat with that alpha score return pack[i][seed % pack[i].length].owner; } return address(0x0); } /** * generates a pseudorandom number * @param seed a value ensure different outcomes for different sources in the same block * @return a pseudorandom value */ function random(uint256 seed) internal view returns (uint256) { return uint256(keccak256(abi.encodePacked( tx.origin, blockhash(block.number - 1), block.timestamp, seed ))); } function onERC721Received( address, address from, uint256, bytes calldata ) external pure override returns (bytes4) { require(from == address(0x0), "Cannot send tokens to Isle directly"); return IERC721Receiver.onERC721Received.selector; } function _addNFT(address _address, uint256 tokenId) internal { contador = contadorArr[_address]; mymap[_address][contador]=tokenId; contadorArr[_address]=contadorArr[_address]+1; } function _deleNFT(address _address, uint256 tokenId) internal { for (uint i=0; i<contadorArr[_address]; i++) { if (mymap[_address][i]==tokenId) { delete mymap[_address][i]; } } } function searchNFT(address _address) public view returns(uint[] memory) { uint[] memory memoryArray = new uint[](contadorArr[_address]); for(uint i = 0; i < contadorArr[_address]; i++) { memoryArray[i] = mymap[_address][i]; } return memoryArray; } }
// SPDX-License-Identifier: MIT LICENSE pragma solidity ^0.8.0; interface ITraits { function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _setOwner(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _setOwner(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _setOwner(newOwner); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol 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; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// SPDX-License-Identifier: MIT LICENSE pragma solidity ^0.8.0; import "./Ownable.sol"; import "./Strings.sol"; import "./ITraits.sol"; import "./IGoat.sol"; contract Traits is Ownable, ITraits { using Strings for uint256; // struct to store each trait's data for metadata and rendering struct Trait { string name; string png; } // mapping from trait type (index) to its name string[9] _traitTypes = [ "Fur", "Head", "Ears", "Eyes", "Nose", "Mouth", "Neck", "Feet", "Alpha" ]; // storage of each traits name and base64 PNG data mapping(uint8 => mapping(uint8 => Trait)) public traitData; // mapping from alphaIndex to its score string[4] _alphas = [ "8", "7", "6", "5" ]; IGoat public goat; constructor() { } /** ADMIN */ function setGoat(address _goat) external onlyOwner { goat = IGoat(_goat); } /** RENDER */ /** * generates an <image> element using base64 encoded PNGs * @param trait the trait storing the PNG data * @return the <image> element */ function drawTrait(Trait memory trait) internal pure returns (string memory) { return string(abi.encodePacked( '<image x="4" y="4" width="32" height="32" image-rendering="pixelated" preserveAspectRatio="xMidYMid" xlink:href="data:image/png;base64,', trait.png, '"/>' )); } /** * generates an attribute for the attributes array in the ERC721 metadata standard * @param traitType the trait type to reference as the metadata key * @param value the token's trait associated with the key * @return a JSON dictionary for the single attribute */ function attributeForTypeAndValue(string memory traitType, string memory value) internal pure returns (string memory) { return string(abi.encodePacked( '{"trait_type":"', traitType, '","value":"', value, '"}' )); } /** * generates an array composed of all the individual traits and values * @param tokenId the ID of the token to compose the metadata for * @return a JSON array of all of the attributes for given token ID */ function compileAttributes(uint256 tokenId) public view returns (string memory) { IGoat.TortoiseGoat memory s = goat.getTokenTraits(tokenId); string memory traits; if (s.isTortoise) { traits = string(abi.encodePacked( attributeForTypeAndValue(_traitTypes[0], uint2str(s.fur)),',', attributeForTypeAndValue(_traitTypes[1], uint2str(s.head)),',', attributeForTypeAndValue(_traitTypes[2], uint2str(s.ears)),',', attributeForTypeAndValue(_traitTypes[3], uint2str(s.eyes)),',', attributeForTypeAndValue(_traitTypes[4], uint2str(s.nose)),',', attributeForTypeAndValue(_traitTypes[5], uint2str(s.mouth)),',', attributeForTypeAndValue(_traitTypes[6], uint2str(s.neck)),',', attributeForTypeAndValue(_traitTypes[7], uint2str(s.feet)),',' )); } else { traits = string(abi.encodePacked( attributeForTypeAndValue(_traitTypes[0], uint2str(s.fur)),',', attributeForTypeAndValue(_traitTypes[1], uint2str(s.head)),',', attributeForTypeAndValue(_traitTypes[2], uint2str(s.ears)),',', attributeForTypeAndValue(_traitTypes[3], uint2str(s.eyes)),',', attributeForTypeAndValue(_traitTypes[4], uint2str(s.nose)),',', attributeForTypeAndValue(_traitTypes[5], uint2str(s.mouth)),',', attributeForTypeAndValue(_traitTypes[6], uint2str(s.neck)),',', attributeForTypeAndValue(_traitTypes[7], uint2str(s.feet)),',', attributeForTypeAndValue("Alpha Score", _alphas[s.alphaIndex]),',' )); } return string(abi.encodePacked( '[', traits, '{"trait_type":"Generation","value":', tokenId <= goat.getPaidTokens() ? '"Gen 0"' : '"Gen 1"', '},{"trait_type":"Type","value":', s.isTortoise ? '"Tortoise"' : '"Goat"', '}]' )); } /** * generates an entire SVG by composing multiple <image> elements of PNGs * @param tokenId the ID of the token to generate an SVG for * @return a valid SVG of the Tortise / Goat */ function drawSVG(uint256 tokenId) public view returns (string memory) { IGoat.TortoiseGoat memory s = goat.getTokenTraits(tokenId); uint8 shift = s.isTortoise ? 0 : 9; string memory svgString = string(abi.encodePacked( drawTrait(traitData[0 + shift][s.fur]), s.isTortoise ? drawTrait(traitData[1 + shift][s.head]) : drawTrait(traitData[1 + shift][s.alphaIndex]), s.isTortoise ? drawTrait(traitData[2 + shift][s.ears]) : '', drawTrait(traitData[3 + shift][s.eyes]), s.isTortoise ? drawTrait(traitData[4 + shift][s.nose]) : '', drawTrait(traitData[5 + shift][s.mouth]), s.isTortoise ? '' : drawTrait(traitData[6 + shift][s.neck]), s.isTortoise ? drawTrait(traitData[7 + shift][s.feet]) : '' )); return string(abi.encodePacked( '<svg id="Goat" width="100%" height="100%" version="1.1" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">', svgString, "</svg>" )); } /** * generates a base64 encoded metadata response without referencing off-chain content * @param tokenId the ID of the token to generate the metadata for * @return a base64 encoded JSON dictionary of the token's metadata and SVG */ function tokenURI(uint256 tokenId) public view override returns (string memory) { IGoat.TortoiseGoat memory s = goat.getTokenTraits(tokenId); string memory metadata = string(abi.encodePacked( '{"name": "', s.isTortoise ? 'Tortoise #' : 'Goat #', tokenId.toString(), '", "external_url":"https://ecclub.games/nft/images/',tokenId.toString(), '.png", "tokenid": "',tokenId.toString(), '", "description": "Thousands of Tortoises and Goats compete on a isle in the metaverse. A tempting prize of $EGGS awaits, with deadly high stakes.", "attributes":', compileAttributes(tokenId), "}" )); return string(abi.encodePacked( "data:application/json,", bytes(metadata) )); } // BASE 64 - Written by Brech Devos string internal constant TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; function base64(bytes memory data) internal pure returns (string memory) { if (data.length == 0) return ''; // load the table into memory string memory table = TABLE; // multiply by 4/3 rounded up uint256 encodedLen = 4 * ((data.length + 2) / 3); // add some extra buffer at the end required for the writing string memory result = new string(encodedLen + 32); assembly { // set the actual output length mstore(result, encodedLen) // prepare the lookup table let tablePtr := add(table, 1) // input ptr let dataPtr := data let endPtr := add(dataPtr, mload(data)) // result ptr, jump over length let resultPtr := add(result, 32) // run over the input, 3 bytes at a time for {} lt(dataPtr, endPtr) {} { dataPtr := add(dataPtr, 3) // read 3 bytes let input := mload(dataPtr) // write 4 characters mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(18, input), 0x3F))))) resultPtr := add(resultPtr, 1) mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(12, input), 0x3F))))) resultPtr := add(resultPtr, 1) mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr( 6, input), 0x3F))))) resultPtr := add(resultPtr, 1) mstore(resultPtr, shl(248, mload(add(tablePtr, and( input, 0x3F))))) resultPtr := add(resultPtr, 1) } // padding with '=' switch mod(mload(data), 3) case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) } case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) } } return result; } function uint2str(uint _i) internal pure returns (string memory _uintAsString) { if (_i == 0) { return "0"; } uint j = _i; uint len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); uint k = len; while (_i != 0) { k = k-1; uint8 temp = (48 + uint8(_i - _i / 10 * 10)); bytes1 b1 = bytes1(temp); bstr[k] = b1; _i /= 10; } return string(bstr); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_eggs","type":"address"},{"internalType":"address","name":"_traits","type":"address"},{"internalType":"uint256","name":"_maxTokens","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"MAX_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINT_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAID_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"aliases","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eggs","outputs":[{"internalType":"contract EGGS","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"existingCombinations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPaidTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getTokenTraits","outputs":[{"components":[{"internalType":"bool","name":"isTortoise","type":"bool"},{"internalType":"uint8","name":"fur","type":"uint8"},{"internalType":"uint8","name":"head","type":"uint8"},{"internalType":"uint8","name":"ears","type":"uint8"},{"internalType":"uint8","name":"eyes","type":"uint8"},{"internalType":"uint8","name":"nose","type":"uint8"},{"internalType":"uint8","name":"mouth","type":"uint8"},{"internalType":"uint8","name":"neck","type":"uint8"},{"internalType":"uint8","name":"feet","type":"uint8"},{"internalType":"uint8","name":"alphaIndex","type":"uint8"}],"internalType":"struct IGoat.TortoiseGoat","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isle","outputs":[{"internalType":"contract IIsle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"mintCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"stake","type":"bool"}],"name":"mint_EGGS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"stake","type":"bool"}],"name":"mint_ETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"minted","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"rarities","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_isle","type":"address"}],"name":"setIsle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_paidTokens","type":"uint256"}],"name":"setPaidTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenTraits","outputs":[{"internalType":"bool","name":"isTortoise","type":"bool"},{"internalType":"uint8","name":"fur","type":"uint8"},{"internalType":"uint8","name":"head","type":"uint8"},{"internalType":"uint8","name":"ears","type":"uint8"},{"internalType":"uint8","name":"eyes","type":"uint8"},{"internalType":"uint8","name":"nose","type":"uint8"},{"internalType":"uint8","name":"mouth","type":"uint8"},{"internalType":"uint8","name":"neck","type":"uint8"},{"internalType":"uint8","name":"feet","type":"uint8"},{"internalType":"uint8","name":"alphaIndex","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"traits","outputs":[{"internalType":"contract ITraits","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelist","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b5060405162007c6638038062007c66833981810160405281019062000037919062001bb6565b6040518060400160405280600d81526020017f546f72746f6973652047616d65000000000000000000000000000000000000008152506040518060400160405280600581526020017f5447414d450000000000000000000000000000000000000000000000000000008152508160009080519060200190620000bb9291906200164d565b508060019080519060200190620000d49291906200164d565b505050620000f7620000eb6200157f60201b60201c565b6200158760201b60201c565b6000600a60146101000a81548160ff02191690831515021790555082603560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081603660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060808181525050600581620001ab919062001c41565b600b81905550604051806102800160405280600f60ff168152602001603260ff16815260200160c860ff16815260200160fa60ff16815260200160ff80168152602001603260ff168152602001603c60ff168152602001605060ff168152602001600f60ff168152602001605a60ff168152602001600b60ff168152602001600f60ff168152602001600d60ff168152602001600f60ff168152602001603260ff168152602001601360ff168152602001606360ff168152602001603260ff168152602001605060ff168152602001606460ff1681525060106000601281106200029a576200029962001c79565b5b01906014620002ab929190620016de565b50604051806102800160405280600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff168152602001600460ff16815250602260006012811062000396576200039562001c79565b5b01906014620003a7929190620016de565b5060405180610140016040528060be60ff16815260200160d760ff16815260200160f060ff168152602001606460ff168152602001606e60ff168152602001608760ff16815260200160a060ff16815260200160b960ff168152602001605060ff16815260200160d260ff1681525060106001601281106200042e576200042d62001c79565b5b0190600a6200043f9291906200178c565b50604051806101400160405280600160ff168152602001600260ff168152602001600460ff168152602001600060ff168152602001600560ff168152602001600660ff168152602001600760ff168152602001600960ff168152602001600060ff168152602001600a60ff168152506022600160128110620004c657620004c562001c79565b5b0190600a620004d79291906200178c565b5060405180610280016040528060ff80168152602001601e60ff168152602001603c60ff168152602001603c60ff168152602001609660ff168152602001609c60ff16815260200160ff80168152602001601e60ff168152602001603c60ff168152602001603c60ff168152602001609660ff168152602001609c60ff16815260200160ff80168152602001601e60ff168152602001603c60ff168152602001603c60ff168152602001609660ff168152602001609c60ff168152602001605a60ff168152602001605560ff168152506010600260128110620005bf57620005be62001c79565b5b01906014620005d0929190620016de565b50604051806102800160405280600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152506022600260128110620006bb57620006ba62001c79565b5b01906014620006cc929190620016de565b506040518060a0016040528060dd60ff168152602001606460ff16815260200160b560ff168152602001608c60ff16815260200160e060ff16815250601060036012811062000720576200071f62001c79565b5b01906005620007319291906200183a565b506040518060a00160405280600160ff168152602001600260ff168152602001600560ff168152602001600060ff168152602001600160ff16815250602260036012811062000785576200078462001c79565b5b01906005620007969291906200183a565b506040518060a0016040528060af60ff168152602001606460ff168152602001602860ff16815260200160fa60ff168152602001607360ff168152506010600460128110620007ea57620007e962001c79565b5b01906005620007fb9291906200183a565b506040518060a00160405280600360ff168152602001600060ff168152602001600460ff168152602001600660ff168152602001600660ff1681525060226004601281106200084f576200084e62001c79565b5b01906005620008609291906200183a565b50604051806101400160405280605060ff16815260200160e160ff16815260200160e360ff16815260200160e460ff168152602001607060ff16815260200160f060ff168152602001604060ff16815260200160a060ff16815260200160a760ff16815260200160d960ff168152506010600560128110620008e757620008e662001c79565b5b0190600a620008f89291906200178c565b50604051806101400160405280600160ff168152602001600260ff168152602001600360ff168152602001600860ff168152602001600260ff168152602001600860ff168152602001600860ff168152602001600960ff168152602001600960ff168152602001600a60ff1681525060226005601281106200097f576200097e62001c79565b5b0190600a620009909291906200178c565b50604051806020016040528060ff80168152506010600660128110620009bb57620009ba62001c79565b5b01906001620009cc929190620018e8565b506040518060200160405280600060ff168152506022600660128110620009f857620009f762001c79565b5b0190600162000a09929190620018e8565b5060405180610280016040528060f360ff16815260200160bd60ff168152602001608560ff168152602001608560ff168152602001603960ff168152602001605f60ff168152602001609860ff168152602001608760ff168152602001608560ff168152602001603960ff16815260200160de60ff16815260200160a860ff168152602001603960ff168152602001603960ff168152602001602660ff168152602001607260ff168152602001607260ff168152602001607260ff168152602001602160ff16815260200160ff8016815250601060076012811062000af35762000af262001c79565b5b0190601462000b04929190620016de565b50604051806102800160405280600160ff168152602001600760ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600a60ff168152602001600060ff168152602001600060ff168152602001600b60ff168152602001601260ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600160ff168152602001600760ff168152602001600b60ff168152602001601260ff168152602001601660ff16815250602260076012811062000bef5762000bee62001c79565b5b0190601462000c00929190620016de565b50604051806020016040528060ff8016815250601060086012811062000c2b5762000c2a62001c79565b5b0190600162000c3c929190620018e8565b506040518060200160405280600060ff16815250602260086012811062000c685762000c6762001c79565b5b0190600162000c79929190620018e8565b5060405180610280016040528060d260ff168152602001605a60ff168152602001600960ff168152602001600960ff168152602001600960ff168152602001609660ff168152602001600960ff16815260200160ff80168152602001600960ff168152602001603260ff16815260200160d260ff168152602001605a60ff168152602001600960ff168152602001600960ff168152602001600960ff168152602001609660ff168152602001600960ff16815260200160ff80168152602001600960ff168152602001603260ff16815250601060096012811062000d625762000d6162001c79565b5b0190601462000d73929190620016de565b50604051806102800160405280600560ff168152602001600060ff168152602001600060ff168152602001600560ff168152602001600560ff168152602001600760ff168152602001600560ff168152602001600760ff168152602001600560ff168152602001600060ff168152602001600560ff168152602001600060ff168152602001600060ff168152602001600560ff168152602001600560ff168152602001600760ff168152602001600560ff168152602001600760ff168152602001600560ff168152602001600060ff16815250602260096012811062000e5e5762000e5d62001c79565b5b0190601462000e6f929190620016de565b50604051806101200160405280600060ff168152602001600160ff168152602001600260ff168152602001600360ff168152602001600460ff168152602001600560ff168152602001600660ff168152602001600760ff16815260200160ff80168152506010600a6012811062000eeb5762000eea62001c79565b5b0190600962000efc92919062001996565b50604051806101200160405280600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152506022600a6012811062000f795762000f7862001c79565b5b0190600962000f8a92919062001996565b50604051806020016040528060ff80168152506010600b6012811062000fb55762000fb462001c79565b5b0190600162000fc6929190620018e8565b506040518060200160405280600060ff168152506022600b6012811062000ff25762000ff162001c79565b5b0190600162001003929190620018e8565b50604051806101400160405280608760ff16815260200160b160ff16815260200160db60ff168152602001608d60ff16815260200160b760ff16815260200160e160ff168152602001609360ff16815260200160bd60ff16815260200160e760ff168152602001608760ff168152506010600c601281106200108a576200108962001c79565b5b0190600a6200109b9291906200178c565b50604051806101400160405280600160ff168152602001600260ff168152602001600360ff168152602001600460ff168152602001600560ff168152602001600660ff168152602001600760ff168152602001600860ff168152602001600d60ff168152602001600360ff168152506022600c6012811062001122576200112162001c79565b5b0190600a620011339291906200178c565b50604051806020016040528060ff80168152506010600d601281106200115e576200115d62001c79565b5b019060016200116f929190620018e8565b506040518060200160405280600060ff168152506022600d601281106200119b576200119a62001c79565b5b01906001620011ac929190620018e8565b50604051806080016040528060ff8016815260200160f460ff16815260200160f960ff16815260200160ea60ff168152506010600e60128110620011f557620011f462001c79565b5b019060046200120692919062001a44565b506040518060800160405280600160ff168152602001600260ff168152602001600b60ff168152602001600060ff168152506022600e6012811062001250576200124f62001c79565b5b019060046200126192919062001a44565b50604051806101400160405280604b60ff16815260200160b460ff16815260200160a560ff168152602001607860ff168152602001603c60ff168152602001609660ff168152602001606960ff16815260200160c360ff168152602001602d60ff16815260200160e160ff168152506010600f60128110620012e857620012e762001c79565b5b0190600a620012f99291906200178c565b50604051806101400160405280600160ff168152602001600960ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600c60ff168152506022600f6012811062001380576200137f62001c79565b5b0190600a620013919291906200178c565b50604051806101400160405280604b60ff16815260200160b460ff16815260200160a560ff168152602001607860ff168152602001603c60ff168152602001609660ff168152602001606960ff16815260200160c360ff168152602001602d60ff16815260200160e160ff168152506010806012811062001417576200141662001c79565b5b0190600a620014289291906200178c565b50604051806101400160405280600160ff168152602001600960ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600c60ff168152506022601060128110620014af57620014ae62001c79565b5b0190600a620014c09291906200178c565b506040518060800160405280600860ff16815260200160a060ff168152602001604960ff16815260200160ff8016815250601060116012811062001509576200150862001c79565b5b019060046200151a92919062001a44565b506040518060800160405280600260ff168152602001600360ff168152602001600360ff168152602001600360ff16815250602260116012811062001564576200156362001c79565b5b019060046200157592919062001a44565b5050505062001d0d565b600033905090565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b8280546200165b9062001cd7565b90600052602060002090601f0160209004810192826200167f5760008555620016cb565b82601f106200169a57805160ff1916838001178555620016cb565b82800160010185558215620016cb579182015b82811115620016ca578251825591602001919060010190620016ad565b5b509050620016da919062001af2565b5090565b82805482825590600052602060002090601f01602090048101928215620017795791602002820160005b838211156200174857835183826101000a81548160ff021916908360ff160217905550926020019260010160208160000104928301926001030262001708565b8015620017775782816101000a81549060ff021916905560010160208160000104928301926001030262001748565b505b50905062001788919062001af2565b5090565b82805482825590600052602060002090601f01602090048101928215620018275791602002820160005b83821115620017f657835183826101000a81548160ff021916908360ff1602179055509260200192600101602081600001049283019260010302620017b6565b8015620018255782816101000a81549060ff0219169055600101602081600001049283019260010302620017f6565b505b50905062001836919062001af2565b5090565b82805482825590600052602060002090601f01602090048101928215620018d55791602002820160005b83821115620018a457835183826101000a81548160ff021916908360ff160217905550926020019260010160208160000104928301926001030262001864565b8015620018d35782816101000a81549060ff0219169055600101602081600001049283019260010302620018a4565b505b509050620018e4919062001af2565b5090565b82805482825590600052602060002090601f01602090048101928215620019835791602002820160005b838211156200195257835183826101000a81548160ff021916908360ff160217905550926020019260010160208160000104928301926001030262001912565b8015620019815782816101000a81549060ff021916905560010160208160000104928301926001030262001952565b505b50905062001992919062001af2565b5090565b82805482825590600052602060002090601f0160209004810192821562001a315791602002820160005b8382111562001a0057835183826101000a81548160ff021916908360ff1602179055509260200192600101602081600001049283019260010302620019c0565b801562001a2f5782816101000a81549060ff021916905560010160208160000104928301926001030262001a00565b505b50905062001a40919062001af2565b5090565b82805482825590600052602060002090601f0160209004810192821562001adf5791602002820160005b8382111562001aae57835183826101000a81548160ff021916908360ff160217905550926020019260010160208160000104928301926001030262001a6e565b801562001add5782816101000a81549060ff021916905560010160208160000104928301926001030262001aae565b505b50905062001aee919062001af2565b5090565b5b8082111562001b0d57600081600090555060010162001af3565b5090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062001b438262001b16565b9050919050565b62001b558162001b36565b811462001b6157600080fd5b50565b60008151905062001b758162001b4a565b92915050565b6000819050919050565b62001b908162001b7b565b811462001b9c57600080fd5b50565b60008151905062001bb08162001b85565b92915050565b60008060006060848603121562001bd25762001bd162001b11565b5b600062001be28682870162001b64565b935050602062001bf58682870162001b64565b925050604062001c088682870162001b9f565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600062001c4e8262001b7b565b915062001c5b8362001b7b565b92508262001c6e5762001c6d62001c12565b5b828204905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168062001cf057607f821691505b6020821081141562001d075762001d0662001ca8565b5b50919050565b608051615f2f62001d376000396000818161102401528181611075015261243a0152615f2f6000f3fe6080604052600436106102465760003560e01c80636352211e11610139578063b88d4fde116100b6578063e1fc334f1161007a578063e1fc334f146108ea578063e33f76cf14610915578063e5755ea614610940578063e985e9c514610969578063f2fde38b146109a6578063f47c84c5146109cf57610246565b8063b88d4fde146107e8578063c002d23d14610811578063c084f5401461083c578063c87b56dd14610867578063e05c57bf146108a457610246565b806394e56847116100fd57806394e56847146106dd57806395d89b411461071a5780639b19251a14610745578063a1b8f37414610782578063a22cb465146107bf57610246565b80636352211e146105f857806370a0823114610635578063715018a6146106725780637502d977146106895780638da5cb5b146106b257610246565b80632f745c59116101c75780634018b1f81161018b5780634018b1f81461051157806342842e0e1461053c5780634f02c420146105655780634f6ccce7146105905780635c975abb146105cd57610246565b80632f745c591461041a57806333df4b2c146104575780633431a7531461049457806336838391146104bd5780633ccfd60b146104fa57610246565b806316c38b3c1161020e57806316c38b3c1461033557806318160ddd1461035e5780631dcc5b491461038957806323b872dd146103b457806327de8f27146103dd57610246565b806301ffc9a71461024b57806306fdde0314610288578063081812fc146102b3578063095ea7b3146102f05780630f0b704114610319575b600080fd5b34801561025757600080fd5b50610272600480360381019061026d9190613ee9565b6109fa565b60405161027f9190613f31565b60405180910390f35b34801561029457600080fd5b5061029d610a74565b6040516102aa9190613fe5565b60405180910390f35b3480156102bf57600080fd5b506102da60048036038101906102d5919061403d565b610b06565b6040516102e791906140ab565b60405180910390f35b3480156102fc57600080fd5b50610317600480360381019061031291906140f2565b610b8b565b005b610333600480360381019061032e919061415e565b610ca3565b005b34801561034157600080fd5b5061035c6004803603810190610357919061419e565b610e76565b005b34801561036a57600080fd5b50610373610f11565b60405161038091906141da565b60405180910390f35b34801561039557600080fd5b5061039e610f1e565b6040516103ab9190614254565b60405180910390f35b3480156103c057600080fd5b506103db60048036038101906103d6919061426f565b610f44565b005b3480156103e957600080fd5b5061040460048036038101906103ff919061403d565b611001565b60405161041191906141da565b60405180910390f35b34801561042657600080fd5b50610441600480360381019061043c91906140f2565b6110d3565b60405161044e91906141da565b60405180910390f35b34801561046357600080fd5b5061047e600480360381019061047991906142c2565b611178565b60405161048b919061431e565b60405180910390f35b3480156104a057600080fd5b506104bb60048036038101906104b6919061403d565b6111be565b005b3480156104c957600080fd5b506104e460048036038101906104df91906142c2565b611244565b6040516104f1919061431e565b60405180910390f35b34801561050657600080fd5b5061050f61128a565b005b34801561051d57600080fd5b5061052661149f565b60405161053391906141da565b60405180910390f35b34801561054857600080fd5b50610563600480360381019061055e919061426f565b6114a9565b005b34801561057157600080fd5b5061057a6114c9565b6040516105879190614356565b60405180910390f35b34801561059c57600080fd5b506105b760048036038101906105b2919061403d565b6114dd565b6040516105c491906141da565b60405180910390f35b3480156105d957600080fd5b506105e261154e565b6040516105ef9190613f31565b60405180910390f35b34801561060457600080fd5b5061061f600480360381019061061a919061403d565b611565565b60405161062c91906140ab565b60405180910390f35b34801561064157600080fd5b5061065c60048036038101906106579190614371565b611617565b60405161066991906141da565b60405180910390f35b34801561067e57600080fd5b506106876116cf565b005b34801561069557600080fd5b506106b060048036038101906106ab9190614371565b611757565b005b3480156106be57600080fd5b506106c7611817565b6040516106d491906140ab565b60405180910390f35b3480156106e957600080fd5b5061070460048036038101906106ff919061403d565b611841565b6040516107119190614488565b60405180910390f35b34801561072657600080fd5b5061072f61198f565b60405161073c9190613fe5565b60405180910390f35b34801561075157600080fd5b5061076c60048036038101906107679190614371565b611a21565b60405161077991906141da565b60405180910390f35b34801561078e57600080fd5b506107a960048036038101906107a4919061403d565b611a39565b6040516107b691906141da565b60405180910390f35b3480156107cb57600080fd5b506107e660048036038101906107e191906144a4565b611a51565b005b3480156107f457600080fd5b5061080f600480360381019061080a9190614619565b611bd2565b005b34801561081d57600080fd5b50610826611c34565b60405161083391906141da565b60405180910390f35b34801561084857600080fd5b50610851611c3f565b60405161085e91906141da565b60405180910390f35b34801561087357600080fd5b5061088e6004803603810190610889919061403d565b611c45565b60405161089b9190613fe5565b60405180910390f35b3480156108b057600080fd5b506108cb60048036038101906108c6919061403d565b611d37565b6040516108e19a9998979695949392919061469c565b60405180910390f35b3480156108f657600080fd5b506108ff611e0d565b60405161090c9190614759565b60405180910390f35b34801561092157600080fd5b5061092a611e33565b6040516109379190614795565b60405180910390f35b34801561094c57600080fd5b506109676004803603810190610962919061415e565b611e59565b005b34801561097557600080fd5b50610990600480360381019061098b91906147b0565b6122ac565b60405161099d9190613f31565b60405180910390f35b3480156109b257600080fd5b506109cd60048036038101906109c89190614371565b612340565b005b3480156109db57600080fd5b506109e4612438565b6040516109f191906141da565b60405180910390f35b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610a6d5750610a6c8261245c565b5b9050919050565b606060008054610a839061481f565b80601f0160208091040260200160405190810160405280929190818152602001828054610aaf9061481f565b8015610afc5780601f10610ad157610100808354040283529160200191610afc565b820191906000526020600020905b815481529060010190602001808311610adf57829003601f168201915b5050505050905090565b6000610b118261253e565b610b50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b47906148c3565b60405180910390fd5b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610b9682611565565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bfe90614955565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610c266125aa565b73ffffffffffffffffffffffffffffffffffffffff161480610c555750610c5481610c4f6125aa565b6122ac565b5b610c94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8b906149e7565b60405180910390fd5b610c9e83836125b2565b505050565b610cab61154e565b15610ceb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ce290614a53565b60405180910390fd5b610cf36125aa565b73ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614610d60576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d5790614abf565b60405180910390fd5b600b5482600c60009054906101000a900461ffff1661ffff16610d839190614b0e565b1115610dc4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dbb90614bb0565b60405180910390fd5b600082118015610dd5575060048211155b610e14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e0b90614c1c565b60405180910390fd5b3466957588590e500083610e289190614c3c565b14610e68576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e5f90614ce2565b60405180910390fd5b610e72828261266b565b5050565b610e7e6125aa565b73ffffffffffffffffffffffffffffffffffffffff16610e9c611817565b73ffffffffffffffffffffffffffffffffffffffff1614610ef2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ee990614d4e565b60405180910390fd5b8015610f0557610f0061293e565b610f0e565b610f0d6129e1565b5b50565b6000600880549050905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16610f856125aa565b73ffffffffffffffffffffffffffffffffffffffff1614610ff157610fb1610fab6125aa565b82612a83565b610ff0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fe790614de0565b60405180910390fd5b5b610ffc838383612b61565b505050565b6000600b54821161101e5769043c33c193756480000090506110ce565b600560027f000000000000000000000000000000000000000000000000000000000000000061104d9190614c3c565b6110579190614e2f565b821161106f5769043c33c193756480000090506110ce565b600560047f000000000000000000000000000000000000000000000000000000000000000061109e9190614c3c565b6110a89190614e2f565b82116110c057690878678326eac900000090506110ce565b6910f0cf064dd59200000090505b919050565b60006110de83611617565b821061111f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161111690614ed2565b60405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b6010826012811061118857600080fd5b01818154811061119757600080fd5b9060005260206000209060209182820401919006915091509054906101000a900460ff1681565b6111c66125aa565b73ffffffffffffffffffffffffffffffffffffffff166111e4611817565b73ffffffffffffffffffffffffffffffffffffffff161461123a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161123190614d4e565b60405180910390fd5b80600b8190555050565b6022826012811061125457600080fd5b01818154811061126357600080fd5b9060005260206000209060209182820401919006915091509054906101000a900460ff1681565b6112926125aa565b73ffffffffffffffffffffffffffffffffffffffff166112b0611817565b73ffffffffffffffffffffffffffffffffffffffff1614611306576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112fd90614d4e565b60405180910390fd5b61130e611817565b73ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050158015611353573d6000803e3d6000fd5b506000603560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016113b191906140ab565b602060405180830381865afa1580156113ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f29190614f07565b9050603560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb61143a611817565b836040518363ffffffff1660e01b8152600401611458929190614f34565b6020604051808303816000875af1158015611477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149b9190614f72565b5050565b6000600b54905090565b6114c483838360405180602001604052806000815250611bd2565b505050565b600c60009054906101000a900461ffff1681565b60006114e7610f11565b8210611528576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151f90615011565b60405180910390fd5b6008828154811061153c5761153b615031565b5b90600052602060002001549050919050565b6000600a60149054906101000a900460ff16905090565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561160e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611605906150d2565b60405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611688576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161167f90615164565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6116d76125aa565b73ffffffffffffffffffffffffffffffffffffffff166116f5611817565b73ffffffffffffffffffffffffffffffffffffffff161461174b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161174290614d4e565b60405180910390fd5b6117556000612dbd565b565b61175f6125aa565b73ffffffffffffffffffffffffffffffffffffffff1661177d611817565b73ffffffffffffffffffffffffffffffffffffffff16146117d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117ca90614d4e565b60405180910390fd5b80603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b611849613e0d565b600e6000838152602001908152602001600020604051806101400160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff1660ff1660ff1681526020016000820160029054906101000a900460ff1660ff1660ff1681526020016000820160039054906101000a900460ff1660ff1660ff1681526020016000820160049054906101000a900460ff1660ff1660ff1681526020016000820160059054906101000a900460ff1660ff1660ff1681526020016000820160069054906101000a900460ff1660ff1660ff1681526020016000820160079054906101000a900460ff1660ff1660ff1681526020016000820160089054906101000a900460ff1660ff1660ff1681526020016000820160099054906101000a900460ff1660ff1660ff16815250509050919050565b60606001805461199e9061481f565b80601f01602080910402602001604051908101604052809291908181526020018280546119ca9061481f565b8015611a175780601f106119ec57610100808354040283529160200191611a17565b820191906000526020600020905b8154815290600101906020018083116119fa57829003601f168201915b5050505050905090565b600d6020528060005260406000206000915090505481565b600f6020528060005260406000206000915090505481565b611a596125aa565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611ac7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611abe906151d0565b60405180910390fd5b8060056000611ad46125aa565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611b816125aa565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611bc69190613f31565b60405180910390a35050565b611be3611bdd6125aa565b83612a83565b611c22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1990614de0565b60405180910390fd5b611c2e84848484612e83565b50505050565b66957588590e500081565b600b5481565b6060611c508261253e565b611c8f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8690615262565b60405180910390fd5b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c87b56dd836040518263ffffffff1660e01b8152600401611cea91906141da565b600060405180830381865afa158015611d07573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611d309190615323565b9050919050565b600e6020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900460ff16908060000160029054906101000a900460ff16908060000160039054906101000a900460ff16908060000160049054906101000a900460ff16908060000160059054906101000a900460ff16908060000160069054906101000a900460ff16908060000160079054906101000a900460ff16908060000160089054906101000a900460ff16908060000160099054906101000a900460ff1690508a565b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611e6161154e565b15611ea1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9890614a53565b60405180910390fd5b6000611eab6125aa565b73ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614611f18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f0f90614abf565b60405180910390fd5b600b5483600c60009054906101000a900461ffff1661ffff16611f3b9190614b0e565b1015611f7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f73906153b8565b60405180910390fd5b600083118015611f8d575060048311155b611fcc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fc390614c1c565b60405180910390fd5b60005b8381101561201f57611fff81600c60009054906101000a900461ffff1661ffff16611ffa9190614b0e565b611001565b8261200a9190614b0e565b91508080612017906153d8565b915050611fcf565b506000603560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30336040518363ffffffff1660e01b815260040161207f929190615421565b602060405180830381865afa15801561209c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c09190614f07565b9050818110156121bb576000603560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b3306a01a784379d99db420000006040518363ffffffff1660e01b8152600401612134929190615485565b6020604051808303816000875af1158015612153573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121779190614f72565b9050806121b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121b0906154fa565b60405180910390fd5b505b603560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff1660e01b815260040161221a9392919061551a565b6020604051808303816000875af1158015612239573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225d9190614f72565b61229c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122939061559d565b60405180910390fd5b6122a6848461266b565b50505050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6123486125aa565b73ffffffffffffffffffffffffffffffffffffffff16612366611817565b73ffffffffffffffffffffffffffffffffffffffff16146123bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123b390614d4e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561242c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124239061562f565b60405180910390fd5b61243581612dbd565b50565b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061252757507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612537575061253682612edf565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff1661262583611565565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000816126c157600067ffffffffffffffff81111561268d5761268c6144ee565b5b6040519080825280602002602001820160405280156126bb5781602001602082028036833780820191505090505b5061270b565b8267ffffffffffffffff8111156126db576126da6144ee565b5b6040519080825280602002602001820160405280156127095781602001602082028036833780820191505090505b505b9050600080600090505b8481101561289a57600c600081819054906101000a900461ffff168092919061273d9061564f565b91906101000a81548161ffff021916908361ffff16021790555050612775600c60009054906101000a900461ffff1661ffff16612f49565b9150612795600c60009054906101000a900461ffff1661ffff1683612f8f565b5060006127a183613168565b90508415806127e357506127b36125aa565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b1561280b5761280681600c60009054906101000a900461ffff1661ffff166132a7565b612886565b61284b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600c60009054906101000a900461ffff1661ffff166132a7565b600c60009054906101000a900461ffff1684838151811061286f5761286e615031565b5b602002602001019061ffff16908161ffff16815250505b508080612892906153d8565b915050612715565b50821561293857603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fd260ad26128e76125aa565b846040518363ffffffff1660e01b8152600401612905929190615738565b600060405180830381600087803b15801561291f57600080fd5b505af1158015612933573d6000803e3d6000fd5b505050505b50505050565b61294661154e565b15612986576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161297d90614a53565b60405180910390fd5b6001600a60146101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586129ca6125aa565b6040516129d791906140ab565b60405180910390a1565b6129e961154e565b612a28576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a1f906157b4565b60405180910390fd5b6000600a60146101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612a6c6125aa565b604051612a7991906140ab565b60405180910390a1565b6000612a8e8261253e565b612acd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ac490615846565b60405180910390fd5b6000612ad883611565565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612b4757508373ffffffffffffffffffffffffffffffffffffffff16612b2f84610b06565b73ffffffffffffffffffffffffffffffffffffffff16145b80612b585750612b5781856122ac565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16612b8182611565565b73ffffffffffffffffffffffffffffffffffffffff1614612bd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bce906158d8565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612c47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c3e9061596a565b60405180910390fd5b612c528383836132c5565b612c5d6000826125b2565b6001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612cad919061598a565b925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612d049190614b0e565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b612e8e848484612b61565b612e9a848484846133d9565b612ed9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ed090615a30565b60405180910390fd5b50505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600032600143612f59919061598a565b404284604051602001612f6f9493929190615ae4565b6040516020818303038152906040528051906020012060001c9050919050565b612f97613e0d565b612fa082613561565b90506000600f6000612fb18461376e565b815260200190815260200160002054141561314d5780600e600085815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff021916908360ff16021790555060408201518160000160026101000a81548160ff021916908360ff16021790555060608201518160000160036101000a81548160ff021916908360ff16021790555060808201518160000160046101000a81548160ff021916908360ff16021790555060a08201518160000160056101000a81548160ff021916908360ff16021790555060c08201518160000160066101000a81548160ff021916908360ff16021790555060e08201518160000160076101000a81548160ff021916908360ff1602179055506101008201518160000160086101000a81548160ff021916908360ff1602179055506101208201518160000160096101000a81548160ff021916908360ff16021790555090505082600f60006131368461376e565b815260200190815260200160002081905550613162565b61315f8361315a84612f49565b612f8f565b90505b92915050565b6000600b54600c60009054906101000a900461ffff1661ffff161115806131a057506000600a60f584901c61319d9190615b32565b14155b156131b4576131ad6125aa565b90506132a2565b6000603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ff6aa2dd609085901c6040518263ffffffff1660e01b815260040161321591906141da565b602060405180830381865afa158015613232573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132569190615b78565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561329d576132956125aa565b9150506132a2565b809150505b919050565b6132c18282604051806020016040528060008152506137d7565b5050565b6132d0838383613832565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156133135761330e81613837565b613352565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614613351576133508382613880565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561339557613390816139ed565b6133d4565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146133d3576133d28282613abe565b5b5b505050565b60006133fa8473ffffffffffffffffffffffffffffffffffffffff16613b3d565b15613554578373ffffffffffffffffffffffffffffffffffffffff1663150b7a026134236125aa565b8786866040518563ffffffff1660e01b81526004016134459493929190615bfa565b6020604051808303816000875af192505050801561348157506040513d601f19601f8201168201806040525081019061347e9190615c5b565b60015b613504573d80600081146134b1576040519150601f19603f3d011682016040523d82523d6000602084013e6134b6565b606091505b506000815114156134fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016134f390615a30565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050613559565b600190505b949350505050565b613569613e0d565b6000600a61ffff841661357c9190615b32565b14158160000190151590811515815250506000816000015161359f5760096135a2565b60005b9050601083901c92506135c561ffff84168260006135c09190615c88565b613b50565b826020019060ff16908160ff1681525050601083901c92506135f761ffff84168260016135f29190615c88565b613b50565b826040019060ff16908160ff1681525050601083901c925061362961ffff84168260026136249190615c88565b613b50565b826060019060ff16908160ff1681525050601083901c925061365b61ffff84168260036136569190615c88565b613b50565b826080019060ff16908160ff1681525050601083901c925061368d61ffff84168260046136889190615c88565b613b50565b8260a0019060ff16908160ff1681525050601083901c92506136bf61ffff84168260056136ba9190615c88565b613b50565b8260c0019060ff16908160ff1681525050601083901c92506136f161ffff84168260066136ec9190615c88565b613b50565b8260e0019060ff16908160ff1681525050601083901c925061372361ffff841682600761371e9190615c88565b613b50565b82610100019060ff16908160ff1681525050601083901c925061375661ffff84168260086137519190615c88565b613b50565b82610120019060ff16908160ff168152505050919050565b600081600001518260200151836040015184608001518560c001518660e0015187606001518861010001518961012001516040516020016137b799989796959493929190615d1e565b6040516020818303038152906040528051906020012060001c9050919050565b6137e18383613c3f565b6137ee60008484846133d9565b61382d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161382490615a30565b60405180910390fd5b505050565b505050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b6000600161388d84611617565b613897919061598a565b905060006007600084815260200190815260200160002054905081811461397c576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b60006001600880549050613a01919061598a565b9050600060096000848152602001908152602001600020549050600060088381548110613a3157613a30615031565b5b906000526020600020015490508060088381548110613a5357613a52615031565b5b906000526020600020018190555081600960008381526020019081526020016000208190555060096000858152602001908152602001600020600090556008805480613aa257613aa1615dc1565b5b6001900381819060005260206000200160009055905550505050565b6000613ac983611617565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b600080823b905060008111915050919050565b60008060108360ff1660128110613b6a57613b69615031565b5b018054905084613b7a9190615df0565b905060108360ff1660128110613b9357613b92615031565b5b018160ff1681548110613ba957613ba8615031565b5b90600052602060002090602091828204019190069054906101000a900460ff1660ff1660088561ffff16901c61ffff161015613be85780915050613c39565b60228360ff1660128110613bff57613bfe615031565b5b018160ff1681548110613c1557613c14615031565b5b90600052602060002090602091828204019190069054906101000a900460ff169150505b92915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613caf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613ca690615e6d565b60405180910390fd5b613cb88161253e565b15613cf8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613cef90615ed9565b60405180910390fd5b613d04600083836132c5565b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613d549190614b0e565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b604051806101400160405280600015158152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff1681525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613ec681613e91565b8114613ed157600080fd5b50565b600081359050613ee381613ebd565b92915050565b600060208284031215613eff57613efe613e87565b5b6000613f0d84828501613ed4565b91505092915050565b60008115159050919050565b613f2b81613f16565b82525050565b6000602082019050613f466000830184613f22565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613f86578082015181840152602081019050613f6b565b83811115613f95576000848401525b50505050565b6000601f19601f8301169050919050565b6000613fb782613f4c565b613fc18185613f57565b9350613fd1818560208601613f68565b613fda81613f9b565b840191505092915050565b60006020820190508181036000830152613fff8184613fac565b905092915050565b6000819050919050565b61401a81614007565b811461402557600080fd5b50565b60008135905061403781614011565b92915050565b60006020828403121561405357614052613e87565b5b600061406184828501614028565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006140958261406a565b9050919050565b6140a58161408a565b82525050565b60006020820190506140c0600083018461409c565b92915050565b6140cf8161408a565b81146140da57600080fd5b50565b6000813590506140ec816140c6565b92915050565b6000806040838503121561410957614108613e87565b5b6000614117858286016140dd565b925050602061412885828601614028565b9150509250929050565b61413b81613f16565b811461414657600080fd5b50565b60008135905061415881614132565b92915050565b6000806040838503121561417557614174613e87565b5b600061418385828601614028565b925050602061419485828601614149565b9150509250929050565b6000602082840312156141b4576141b3613e87565b5b60006141c284828501614149565b91505092915050565b6141d481614007565b82525050565b60006020820190506141ef60008301846141cb565b92915050565b6000819050919050565b600061421a6142156142108461406a565b6141f5565b61406a565b9050919050565b600061422c826141ff565b9050919050565b600061423e82614221565b9050919050565b61424e81614233565b82525050565b60006020820190506142696000830184614245565b92915050565b60008060006060848603121561428857614287613e87565b5b6000614296868287016140dd565b93505060206142a7868287016140dd565b92505060406142b886828701614028565b9150509250925092565b600080604083850312156142d9576142d8613e87565b5b60006142e785828601614028565b92505060206142f885828601614028565b9150509250929050565b600060ff82169050919050565b61431881614302565b82525050565b6000602082019050614333600083018461430f565b92915050565b600061ffff82169050919050565b61435081614339565b82525050565b600060208201905061436b6000830184614347565b92915050565b60006020828403121561438757614386613e87565b5b6000614395848285016140dd565b91505092915050565b6143a781613f16565b82525050565b6143b681614302565b82525050565b610140820160008201516143d3600085018261439e565b5060208201516143e660208501826143ad565b5060408201516143f960408501826143ad565b50606082015161440c60608501826143ad565b50608082015161441f60808501826143ad565b5060a082015161443260a08501826143ad565b5060c082015161444560c08501826143ad565b5060e082015161445860e08501826143ad565b5061010082015161446d6101008501826143ad565b506101208201516144826101208501826143ad565b50505050565b60006101408201905061449e60008301846143bc565b92915050565b600080604083850312156144bb576144ba613e87565b5b60006144c9858286016140dd565b92505060206144da85828601614149565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61452682613f9b565b810181811067ffffffffffffffff82111715614545576145446144ee565b5b80604052505050565b6000614558613e7d565b9050614564828261451d565b919050565b600067ffffffffffffffff821115614584576145836144ee565b5b61458d82613f9b565b9050602081019050919050565b82818337600083830152505050565b60006145bc6145b784614569565b61454e565b9050828152602081018484840111156145d8576145d76144e9565b5b6145e384828561459a565b509392505050565b600082601f830112614600576145ff6144e4565b5b81356146108482602086016145a9565b91505092915050565b6000806000806080858703121561463357614632613e87565b5b6000614641878288016140dd565b9450506020614652878288016140dd565b935050604061466387828801614028565b925050606085013567ffffffffffffffff81111561468457614683613e8c565b5b614690878288016145eb565b91505092959194509250565b6000610140820190506146b2600083018d613f22565b6146bf602083018c61430f565b6146cc604083018b61430f565b6146d9606083018a61430f565b6146e6608083018961430f565b6146f360a083018861430f565b61470060c083018761430f565b61470d60e083018661430f565b61471b61010083018561430f565b61472961012083018461430f565b9b9a5050505050505050505050565b600061474382614221565b9050919050565b61475381614738565b82525050565b600060208201905061476e600083018461474a565b92915050565b600061477f82614221565b9050919050565b61478f81614774565b82525050565b60006020820190506147aa6000830184614786565b92915050565b600080604083850312156147c7576147c6613e87565b5b60006147d5858286016140dd565b92505060206147e6858286016140dd565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061483757607f821691505b6020821081141561484b5761484a6147f0565b5b50919050565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b60006148ad602c83613f57565b91506148b882614851565b604082019050919050565b600060208201905081810360008301526148dc816148a0565b9050919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b600061493f602183613f57565b915061494a826148e3565b604082019050919050565b6000602082019050818103600083015261496e81614932565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b60006149d1603883613f57565b91506149dc82614975565b604082019050919050565b60006020820190508181036000830152614a00816149c4565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b6000614a3d601083613f57565b9150614a4882614a07565b602082019050919050565b60006020820190508181036000830152614a6c81614a30565b9050919050565b7f4f6e6c7920454f41000000000000000000000000000000000000000000000000600082015250565b6000614aa9600883613f57565b9150614ab482614a73565b602082019050919050565b60006020820190508181036000830152614ad881614a9c565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614b1982614007565b9150614b2483614007565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614b5957614b58614adf565b5b828201905092915050565b7f416c6c20746f6b656e73206d696e746564000000000000000000000000000000600082015250565b6000614b9a601183613f57565b9150614ba582614b64565b602082019050919050565b60006020820190508181036000830152614bc981614b8d565b9050919050565b7f496e76616c6964206d696e7420616d6f756e7400000000000000000000000000600082015250565b6000614c06601383613f57565b9150614c1182614bd0565b602082019050919050565b60006020820190508181036000830152614c3581614bf9565b9050919050565b6000614c4782614007565b9150614c5283614007565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614c8b57614c8a614adf565b5b828202905092915050565b7f496e76616c6964207061796d656e7420616d6f756e7400000000000000000000600082015250565b6000614ccc601683613f57565b9150614cd782614c96565b602082019050919050565b60006020820190508181036000830152614cfb81614cbf565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614d38602083613f57565b9150614d4382614d02565b602082019050919050565b60006020820190508181036000830152614d6781614d2b565b9050919050565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b6000614dca603183613f57565b9150614dd582614d6e565b604082019050919050565b60006020820190508181036000830152614df981614dbd565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614e3a82614007565b9150614e4583614007565b925082614e5557614e54614e00565b5b828204905092915050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b6000614ebc602b83613f57565b9150614ec782614e60565b604082019050919050565b60006020820190508181036000830152614eeb81614eaf565b9050919050565b600081519050614f0181614011565b92915050565b600060208284031215614f1d57614f1c613e87565b5b6000614f2b84828501614ef2565b91505092915050565b6000604082019050614f49600083018561409c565b614f5660208301846141cb565b9392505050565b600081519050614f6c81614132565b92915050565b600060208284031215614f8857614f87613e87565b5b6000614f9684828501614f5d565b91505092915050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b6000614ffb602c83613f57565b915061500682614f9f565b604082019050919050565b6000602082019050818103600083015261502a81614fee565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b60006150bc602983613f57565b91506150c782615060565b604082019050919050565b600060208201905081810360008301526150eb816150af565b9050919050565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b600061514e602a83613f57565b9150615159826150f2565b604082019050919050565b6000602082019050818103600083015261517d81615141565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b60006151ba601983613f57565b91506151c582615184565b602082019050919050565b600060208201905081810360008301526151e9816151ad565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b600061524c602f83613f57565b9150615257826151f0565b604082019050919050565b6000602082019050818103600083015261527b8161523f565b9050919050565b600067ffffffffffffffff82111561529d5761529c6144ee565b5b6152a682613f9b565b9050602081019050919050565b60006152c66152c184615282565b61454e565b9050828152602081018484840111156152e2576152e16144e9565b5b6152ed848285613f68565b509392505050565b600082601f83011261530a576153096144e4565b5b815161531a8482602086016152b3565b91505092915050565b60006020828403121561533957615338613e87565b5b600082015167ffffffffffffffff81111561535757615356613e8c565b5b615363848285016152f5565b91505092915050565b7f4f6e6c7920776974682045544800000000000000000000000000000000000000600082015250565b60006153a2600d83613f57565b91506153ad8261536c565b602082019050919050565b600060208201905081810360008301526153d181615395565b9050919050565b60006153e382614007565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561541657615415614adf565b5b600182019050919050565b6000604082019050615436600083018561409c565b615443602083018461409c565b9392505050565b6000819050919050565b600061546f61546a6154658461544a565b6141f5565b614007565b9050919050565b61547f81615454565b82525050565b600060408201905061549a600083018561409c565b6154a76020830184615476565b9392505050565b7f43616e27742075736520796f7572204547475300000000000000000000000000600082015250565b60006154e4601383613f57565b91506154ef826154ae565b602082019050919050565b60006020820190508181036000830152615513816154d7565b9050919050565b600060608201905061552f600083018661409c565b61553c602083018561409c565b61554960408301846141cb565b949350505050565b7f4572726f722073656e64696e6720454747530000000000000000000000000000600082015250565b6000615587601283613f57565b915061559282615551565b602082019050919050565b600060208201905081810360008301526155b68161557a565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000615619602683613f57565b9150615624826155bd565b604082019050919050565b600060208201905081810360008301526156488161560c565b9050919050565b600061565a82614339565b915061ffff82141561566f5761566e614adf565b5b600182019050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6156af81614339565b82525050565b60006156c183836156a6565b60208301905092915050565b6000602082019050919050565b60006156e58261567a565b6156ef8185615685565b93506156fa83615696565b8060005b8381101561572b57815161571288826156b5565b975061571d836156cd565b9250506001810190506156fe565b5085935050505092915050565b600060408201905061574d600083018561409c565b818103602083015261575f81846156da565b90509392505050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b600061579e601483613f57565b91506157a982615768565b602082019050919050565b600060208201905081810360008301526157cd81615791565b9050919050565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b6000615830602c83613f57565b915061583b826157d4565b604082019050919050565b6000602082019050818103600083015261585f81615823565b9050919050565b7f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960008201527f73206e6f74206f776e0000000000000000000000000000000000000000000000602082015250565b60006158c2602983613f57565b91506158cd82615866565b604082019050919050565b600060208201905081810360008301526158f1816158b5565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000615954602483613f57565b915061595f826158f8565b604082019050919050565b6000602082019050818103600083015261598381615947565b9050919050565b600061599582614007565b91506159a083614007565b9250828210156159b3576159b2614adf565b5b828203905092915050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000615a1a603283613f57565b9150615a25826159be565b604082019050919050565b60006020820190508181036000830152615a4981615a0d565b9050919050565b60008160601b9050919050565b6000615a6882615a50565b9050919050565b6000615a7a82615a5d565b9050919050565b615a92615a8d8261408a565b615a6f565b82525050565b6000819050919050565b6000819050919050565b615abd615ab882615a98565b615aa2565b82525050565b6000819050919050565b615ade615ad982614007565b615ac3565b82525050565b6000615af08287615a81565b601482019150615b008286615aac565b602082019150615b108285615acd565b602082019150615b208284615acd565b60208201915081905095945050505050565b6000615b3d82614007565b9150615b4883614007565b925082615b5857615b57614e00565b5b828206905092915050565b600081519050615b72816140c6565b92915050565b600060208284031215615b8e57615b8d613e87565b5b6000615b9c84828501615b63565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000615bcc82615ba5565b615bd68185615bb0565b9350615be6818560208601613f68565b615bef81613f9b565b840191505092915050565b6000608082019050615c0f600083018761409c565b615c1c602083018661409c565b615c2960408301856141cb565b8181036060830152615c3b8184615bc1565b905095945050505050565b600081519050615c5581613ebd565b92915050565b600060208284031215615c7157615c70613e87565b5b6000615c7f84828501615c46565b91505092915050565b6000615c9382614302565b9150615c9e83614302565b92508260ff03821115615cb457615cb3614adf565b5b828201905092915050565b60008160f81b9050919050565b6000615cd782615cbf565b9050919050565b6000615ce982615ccc565b9050919050565b615d01615cfc82613f16565b615cde565b82525050565b615d18615d1382614302565b615ccc565b82525050565b6000615d2a828c615cf0565b600182019150615d3a828b615d07565b600182019150615d4a828a615d07565b600182019150615d5a8289615d07565b600182019150615d6a8288615d07565b600182019150615d7a8287615d07565b600182019150615d8a8286615d07565b600182019150615d9a8285615d07565b600182019150615daa8284615d07565b6001820191508190509a9950505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000615dfb82614302565b9150615e0683614302565b925082615e1657615e15614e00565b5b828206905092915050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b6000615e57602083613f57565b9150615e6282615e21565b602082019050919050565b60006020820190508181036000830152615e8681615e4a565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000615ec3601c83613f57565b9150615ece82615e8d565b602082019050919050565b60006020820190508181036000830152615ef281615eb6565b905091905056fea2646970667358221220ea37b8bb35257cd60ddb9c0481dfc6968f58f36ee347af832c5b2b87ff11c7c064736f6c634300080a003300000000000000000000000053ae3a8f0bb81234314e058ad505fdbe8b1b5bc80000000000000000000000003d6c10351a1c695729f5ad257e6fdcc7590c427c000000000000000000000000000000000000000000000000000000000000c350
Deployed Bytecode
0x6080604052600436106102465760003560e01c80636352211e11610139578063b88d4fde116100b6578063e1fc334f1161007a578063e1fc334f146108ea578063e33f76cf14610915578063e5755ea614610940578063e985e9c514610969578063f2fde38b146109a6578063f47c84c5146109cf57610246565b8063b88d4fde146107e8578063c002d23d14610811578063c084f5401461083c578063c87b56dd14610867578063e05c57bf146108a457610246565b806394e56847116100fd57806394e56847146106dd57806395d89b411461071a5780639b19251a14610745578063a1b8f37414610782578063a22cb465146107bf57610246565b80636352211e146105f857806370a0823114610635578063715018a6146106725780637502d977146106895780638da5cb5b146106b257610246565b80632f745c59116101c75780634018b1f81161018b5780634018b1f81461051157806342842e0e1461053c5780634f02c420146105655780634f6ccce7146105905780635c975abb146105cd57610246565b80632f745c591461041a57806333df4b2c146104575780633431a7531461049457806336838391146104bd5780633ccfd60b146104fa57610246565b806316c38b3c1161020e57806316c38b3c1461033557806318160ddd1461035e5780631dcc5b491461038957806323b872dd146103b457806327de8f27146103dd57610246565b806301ffc9a71461024b57806306fdde0314610288578063081812fc146102b3578063095ea7b3146102f05780630f0b704114610319575b600080fd5b34801561025757600080fd5b50610272600480360381019061026d9190613ee9565b6109fa565b60405161027f9190613f31565b60405180910390f35b34801561029457600080fd5b5061029d610a74565b6040516102aa9190613fe5565b60405180910390f35b3480156102bf57600080fd5b506102da60048036038101906102d5919061403d565b610b06565b6040516102e791906140ab565b60405180910390f35b3480156102fc57600080fd5b50610317600480360381019061031291906140f2565b610b8b565b005b610333600480360381019061032e919061415e565b610ca3565b005b34801561034157600080fd5b5061035c6004803603810190610357919061419e565b610e76565b005b34801561036a57600080fd5b50610373610f11565b60405161038091906141da565b60405180910390f35b34801561039557600080fd5b5061039e610f1e565b6040516103ab9190614254565b60405180910390f35b3480156103c057600080fd5b506103db60048036038101906103d6919061426f565b610f44565b005b3480156103e957600080fd5b5061040460048036038101906103ff919061403d565b611001565b60405161041191906141da565b60405180910390f35b34801561042657600080fd5b50610441600480360381019061043c91906140f2565b6110d3565b60405161044e91906141da565b60405180910390f35b34801561046357600080fd5b5061047e600480360381019061047991906142c2565b611178565b60405161048b919061431e565b60405180910390f35b3480156104a057600080fd5b506104bb60048036038101906104b6919061403d565b6111be565b005b3480156104c957600080fd5b506104e460048036038101906104df91906142c2565b611244565b6040516104f1919061431e565b60405180910390f35b34801561050657600080fd5b5061050f61128a565b005b34801561051d57600080fd5b5061052661149f565b60405161053391906141da565b60405180910390f35b34801561054857600080fd5b50610563600480360381019061055e919061426f565b6114a9565b005b34801561057157600080fd5b5061057a6114c9565b6040516105879190614356565b60405180910390f35b34801561059c57600080fd5b506105b760048036038101906105b2919061403d565b6114dd565b6040516105c491906141da565b60405180910390f35b3480156105d957600080fd5b506105e261154e565b6040516105ef9190613f31565b60405180910390f35b34801561060457600080fd5b5061061f600480360381019061061a919061403d565b611565565b60405161062c91906140ab565b60405180910390f35b34801561064157600080fd5b5061065c60048036038101906106579190614371565b611617565b60405161066991906141da565b60405180910390f35b34801561067e57600080fd5b506106876116cf565b005b34801561069557600080fd5b506106b060048036038101906106ab9190614371565b611757565b005b3480156106be57600080fd5b506106c7611817565b6040516106d491906140ab565b60405180910390f35b3480156106e957600080fd5b5061070460048036038101906106ff919061403d565b611841565b6040516107119190614488565b60405180910390f35b34801561072657600080fd5b5061072f61198f565b60405161073c9190613fe5565b60405180910390f35b34801561075157600080fd5b5061076c60048036038101906107679190614371565b611a21565b60405161077991906141da565b60405180910390f35b34801561078e57600080fd5b506107a960048036038101906107a4919061403d565b611a39565b6040516107b691906141da565b60405180910390f35b3480156107cb57600080fd5b506107e660048036038101906107e191906144a4565b611a51565b005b3480156107f457600080fd5b5061080f600480360381019061080a9190614619565b611bd2565b005b34801561081d57600080fd5b50610826611c34565b60405161083391906141da565b60405180910390f35b34801561084857600080fd5b50610851611c3f565b60405161085e91906141da565b60405180910390f35b34801561087357600080fd5b5061088e6004803603810190610889919061403d565b611c45565b60405161089b9190613fe5565b60405180910390f35b3480156108b057600080fd5b506108cb60048036038101906108c6919061403d565b611d37565b6040516108e19a9998979695949392919061469c565b60405180910390f35b3480156108f657600080fd5b506108ff611e0d565b60405161090c9190614759565b60405180910390f35b34801561092157600080fd5b5061092a611e33565b6040516109379190614795565b60405180910390f35b34801561094c57600080fd5b506109676004803603810190610962919061415e565b611e59565b005b34801561097557600080fd5b50610990600480360381019061098b91906147b0565b6122ac565b60405161099d9190613f31565b60405180910390f35b3480156109b257600080fd5b506109cd60048036038101906109c89190614371565b612340565b005b3480156109db57600080fd5b506109e4612438565b6040516109f191906141da565b60405180910390f35b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610a6d5750610a6c8261245c565b5b9050919050565b606060008054610a839061481f565b80601f0160208091040260200160405190810160405280929190818152602001828054610aaf9061481f565b8015610afc5780601f10610ad157610100808354040283529160200191610afc565b820191906000526020600020905b815481529060010190602001808311610adf57829003601f168201915b5050505050905090565b6000610b118261253e565b610b50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b47906148c3565b60405180910390fd5b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610b9682611565565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bfe90614955565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610c266125aa565b73ffffffffffffffffffffffffffffffffffffffff161480610c555750610c5481610c4f6125aa565b6122ac565b5b610c94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8b906149e7565b60405180910390fd5b610c9e83836125b2565b505050565b610cab61154e565b15610ceb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ce290614a53565b60405180910390fd5b610cf36125aa565b73ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614610d60576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d5790614abf565b60405180910390fd5b600b5482600c60009054906101000a900461ffff1661ffff16610d839190614b0e565b1115610dc4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dbb90614bb0565b60405180910390fd5b600082118015610dd5575060048211155b610e14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e0b90614c1c565b60405180910390fd5b3466957588590e500083610e289190614c3c565b14610e68576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e5f90614ce2565b60405180910390fd5b610e72828261266b565b5050565b610e7e6125aa565b73ffffffffffffffffffffffffffffffffffffffff16610e9c611817565b73ffffffffffffffffffffffffffffffffffffffff1614610ef2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ee990614d4e565b60405180910390fd5b8015610f0557610f0061293e565b610f0e565b610f0d6129e1565b5b50565b6000600880549050905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16610f856125aa565b73ffffffffffffffffffffffffffffffffffffffff1614610ff157610fb1610fab6125aa565b82612a83565b610ff0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fe790614de0565b60405180910390fd5b5b610ffc838383612b61565b505050565b6000600b54821161101e5769043c33c193756480000090506110ce565b600560027f000000000000000000000000000000000000000000000000000000000000c35061104d9190614c3c565b6110579190614e2f565b821161106f5769043c33c193756480000090506110ce565b600560047f000000000000000000000000000000000000000000000000000000000000c35061109e9190614c3c565b6110a89190614e2f565b82116110c057690878678326eac900000090506110ce565b6910f0cf064dd59200000090505b919050565b60006110de83611617565b821061111f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161111690614ed2565b60405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b6010826012811061118857600080fd5b01818154811061119757600080fd5b9060005260206000209060209182820401919006915091509054906101000a900460ff1681565b6111c66125aa565b73ffffffffffffffffffffffffffffffffffffffff166111e4611817565b73ffffffffffffffffffffffffffffffffffffffff161461123a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161123190614d4e565b60405180910390fd5b80600b8190555050565b6022826012811061125457600080fd5b01818154811061126357600080fd5b9060005260206000209060209182820401919006915091509054906101000a900460ff1681565b6112926125aa565b73ffffffffffffffffffffffffffffffffffffffff166112b0611817565b73ffffffffffffffffffffffffffffffffffffffff1614611306576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112fd90614d4e565b60405180910390fd5b61130e611817565b73ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050158015611353573d6000803e3d6000fd5b506000603560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016113b191906140ab565b602060405180830381865afa1580156113ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f29190614f07565b9050603560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb61143a611817565b836040518363ffffffff1660e01b8152600401611458929190614f34565b6020604051808303816000875af1158015611477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149b9190614f72565b5050565b6000600b54905090565b6114c483838360405180602001604052806000815250611bd2565b505050565b600c60009054906101000a900461ffff1681565b60006114e7610f11565b8210611528576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151f90615011565b60405180910390fd5b6008828154811061153c5761153b615031565b5b90600052602060002001549050919050565b6000600a60149054906101000a900460ff16905090565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561160e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611605906150d2565b60405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611688576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161167f90615164565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6116d76125aa565b73ffffffffffffffffffffffffffffffffffffffff166116f5611817565b73ffffffffffffffffffffffffffffffffffffffff161461174b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161174290614d4e565b60405180910390fd5b6117556000612dbd565b565b61175f6125aa565b73ffffffffffffffffffffffffffffffffffffffff1661177d611817565b73ffffffffffffffffffffffffffffffffffffffff16146117d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117ca90614d4e565b60405180910390fd5b80603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b611849613e0d565b600e6000838152602001908152602001600020604051806101400160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff1660ff1660ff1681526020016000820160029054906101000a900460ff1660ff1660ff1681526020016000820160039054906101000a900460ff1660ff1660ff1681526020016000820160049054906101000a900460ff1660ff1660ff1681526020016000820160059054906101000a900460ff1660ff1660ff1681526020016000820160069054906101000a900460ff1660ff1660ff1681526020016000820160079054906101000a900460ff1660ff1660ff1681526020016000820160089054906101000a900460ff1660ff1660ff1681526020016000820160099054906101000a900460ff1660ff1660ff16815250509050919050565b60606001805461199e9061481f565b80601f01602080910402602001604051908101604052809291908181526020018280546119ca9061481f565b8015611a175780601f106119ec57610100808354040283529160200191611a17565b820191906000526020600020905b8154815290600101906020018083116119fa57829003601f168201915b5050505050905090565b600d6020528060005260406000206000915090505481565b600f6020528060005260406000206000915090505481565b611a596125aa565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611ac7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611abe906151d0565b60405180910390fd5b8060056000611ad46125aa565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611b816125aa565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611bc69190613f31565b60405180910390a35050565b611be3611bdd6125aa565b83612a83565b611c22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1990614de0565b60405180910390fd5b611c2e84848484612e83565b50505050565b66957588590e500081565b600b5481565b6060611c508261253e565b611c8f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8690615262565b60405180910390fd5b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c87b56dd836040518263ffffffff1660e01b8152600401611cea91906141da565b600060405180830381865afa158015611d07573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611d309190615323565b9050919050565b600e6020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900460ff16908060000160029054906101000a900460ff16908060000160039054906101000a900460ff16908060000160049054906101000a900460ff16908060000160059054906101000a900460ff16908060000160069054906101000a900460ff16908060000160079054906101000a900460ff16908060000160089054906101000a900460ff16908060000160099054906101000a900460ff1690508a565b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611e6161154e565b15611ea1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9890614a53565b60405180910390fd5b6000611eab6125aa565b73ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614611f18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f0f90614abf565b60405180910390fd5b600b5483600c60009054906101000a900461ffff1661ffff16611f3b9190614b0e565b1015611f7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f73906153b8565b60405180910390fd5b600083118015611f8d575060048311155b611fcc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fc390614c1c565b60405180910390fd5b60005b8381101561201f57611fff81600c60009054906101000a900461ffff1661ffff16611ffa9190614b0e565b611001565b8261200a9190614b0e565b91508080612017906153d8565b915050611fcf565b506000603560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30336040518363ffffffff1660e01b815260040161207f929190615421565b602060405180830381865afa15801561209c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c09190614f07565b9050818110156121bb576000603560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b3306a01a784379d99db420000006040518363ffffffff1660e01b8152600401612134929190615485565b6020604051808303816000875af1158015612153573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121779190614f72565b9050806121b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121b0906154fa565b60405180910390fd5b505b603560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff1660e01b815260040161221a9392919061551a565b6020604051808303816000875af1158015612239573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225d9190614f72565b61229c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122939061559d565b60405180910390fd5b6122a6848461266b565b50505050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6123486125aa565b73ffffffffffffffffffffffffffffffffffffffff16612366611817565b73ffffffffffffffffffffffffffffffffffffffff16146123bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123b390614d4e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561242c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124239061562f565b60405180910390fd5b61243581612dbd565b50565b7f000000000000000000000000000000000000000000000000000000000000c35081565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061252757507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612537575061253682612edf565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff1661262583611565565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000816126c157600067ffffffffffffffff81111561268d5761268c6144ee565b5b6040519080825280602002602001820160405280156126bb5781602001602082028036833780820191505090505b5061270b565b8267ffffffffffffffff8111156126db576126da6144ee565b5b6040519080825280602002602001820160405280156127095781602001602082028036833780820191505090505b505b9050600080600090505b8481101561289a57600c600081819054906101000a900461ffff168092919061273d9061564f565b91906101000a81548161ffff021916908361ffff16021790555050612775600c60009054906101000a900461ffff1661ffff16612f49565b9150612795600c60009054906101000a900461ffff1661ffff1683612f8f565b5060006127a183613168565b90508415806127e357506127b36125aa565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b1561280b5761280681600c60009054906101000a900461ffff1661ffff166132a7565b612886565b61284b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600c60009054906101000a900461ffff1661ffff166132a7565b600c60009054906101000a900461ffff1684838151811061286f5761286e615031565b5b602002602001019061ffff16908161ffff16815250505b508080612892906153d8565b915050612715565b50821561293857603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fd260ad26128e76125aa565b846040518363ffffffff1660e01b8152600401612905929190615738565b600060405180830381600087803b15801561291f57600080fd5b505af1158015612933573d6000803e3d6000fd5b505050505b50505050565b61294661154e565b15612986576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161297d90614a53565b60405180910390fd5b6001600a60146101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586129ca6125aa565b6040516129d791906140ab565b60405180910390a1565b6129e961154e565b612a28576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a1f906157b4565b60405180910390fd5b6000600a60146101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612a6c6125aa565b604051612a7991906140ab565b60405180910390a1565b6000612a8e8261253e565b612acd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ac490615846565b60405180910390fd5b6000612ad883611565565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612b4757508373ffffffffffffffffffffffffffffffffffffffff16612b2f84610b06565b73ffffffffffffffffffffffffffffffffffffffff16145b80612b585750612b5781856122ac565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16612b8182611565565b73ffffffffffffffffffffffffffffffffffffffff1614612bd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bce906158d8565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612c47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c3e9061596a565b60405180910390fd5b612c528383836132c5565b612c5d6000826125b2565b6001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612cad919061598a565b925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612d049190614b0e565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b612e8e848484612b61565b612e9a848484846133d9565b612ed9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ed090615a30565b60405180910390fd5b50505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600032600143612f59919061598a565b404284604051602001612f6f9493929190615ae4565b6040516020818303038152906040528051906020012060001c9050919050565b612f97613e0d565b612fa082613561565b90506000600f6000612fb18461376e565b815260200190815260200160002054141561314d5780600e600085815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff021916908360ff16021790555060408201518160000160026101000a81548160ff021916908360ff16021790555060608201518160000160036101000a81548160ff021916908360ff16021790555060808201518160000160046101000a81548160ff021916908360ff16021790555060a08201518160000160056101000a81548160ff021916908360ff16021790555060c08201518160000160066101000a81548160ff021916908360ff16021790555060e08201518160000160076101000a81548160ff021916908360ff1602179055506101008201518160000160086101000a81548160ff021916908360ff1602179055506101208201518160000160096101000a81548160ff021916908360ff16021790555090505082600f60006131368461376e565b815260200190815260200160002081905550613162565b61315f8361315a84612f49565b612f8f565b90505b92915050565b6000600b54600c60009054906101000a900461ffff1661ffff161115806131a057506000600a60f584901c61319d9190615b32565b14155b156131b4576131ad6125aa565b90506132a2565b6000603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ff6aa2dd609085901c6040518263ffffffff1660e01b815260040161321591906141da565b602060405180830381865afa158015613232573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132569190615b78565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561329d576132956125aa565b9150506132a2565b809150505b919050565b6132c18282604051806020016040528060008152506137d7565b5050565b6132d0838383613832565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156133135761330e81613837565b613352565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614613351576133508382613880565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561339557613390816139ed565b6133d4565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146133d3576133d28282613abe565b5b5b505050565b60006133fa8473ffffffffffffffffffffffffffffffffffffffff16613b3d565b15613554578373ffffffffffffffffffffffffffffffffffffffff1663150b7a026134236125aa565b8786866040518563ffffffff1660e01b81526004016134459493929190615bfa565b6020604051808303816000875af192505050801561348157506040513d601f19601f8201168201806040525081019061347e9190615c5b565b60015b613504573d80600081146134b1576040519150601f19603f3d011682016040523d82523d6000602084013e6134b6565b606091505b506000815114156134fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016134f390615a30565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050613559565b600190505b949350505050565b613569613e0d565b6000600a61ffff841661357c9190615b32565b14158160000190151590811515815250506000816000015161359f5760096135a2565b60005b9050601083901c92506135c561ffff84168260006135c09190615c88565b613b50565b826020019060ff16908160ff1681525050601083901c92506135f761ffff84168260016135f29190615c88565b613b50565b826040019060ff16908160ff1681525050601083901c925061362961ffff84168260026136249190615c88565b613b50565b826060019060ff16908160ff1681525050601083901c925061365b61ffff84168260036136569190615c88565b613b50565b826080019060ff16908160ff1681525050601083901c925061368d61ffff84168260046136889190615c88565b613b50565b8260a0019060ff16908160ff1681525050601083901c92506136bf61ffff84168260056136ba9190615c88565b613b50565b8260c0019060ff16908160ff1681525050601083901c92506136f161ffff84168260066136ec9190615c88565b613b50565b8260e0019060ff16908160ff1681525050601083901c925061372361ffff841682600761371e9190615c88565b613b50565b82610100019060ff16908160ff1681525050601083901c925061375661ffff84168260086137519190615c88565b613b50565b82610120019060ff16908160ff168152505050919050565b600081600001518260200151836040015184608001518560c001518660e0015187606001518861010001518961012001516040516020016137b799989796959493929190615d1e565b6040516020818303038152906040528051906020012060001c9050919050565b6137e18383613c3f565b6137ee60008484846133d9565b61382d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161382490615a30565b60405180910390fd5b505050565b505050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b6000600161388d84611617565b613897919061598a565b905060006007600084815260200190815260200160002054905081811461397c576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b60006001600880549050613a01919061598a565b9050600060096000848152602001908152602001600020549050600060088381548110613a3157613a30615031565b5b906000526020600020015490508060088381548110613a5357613a52615031565b5b906000526020600020018190555081600960008381526020019081526020016000208190555060096000858152602001908152602001600020600090556008805480613aa257613aa1615dc1565b5b6001900381819060005260206000200160009055905550505050565b6000613ac983611617565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b600080823b905060008111915050919050565b60008060108360ff1660128110613b6a57613b69615031565b5b018054905084613b7a9190615df0565b905060108360ff1660128110613b9357613b92615031565b5b018160ff1681548110613ba957613ba8615031565b5b90600052602060002090602091828204019190069054906101000a900460ff1660ff1660088561ffff16901c61ffff161015613be85780915050613c39565b60228360ff1660128110613bff57613bfe615031565b5b018160ff1681548110613c1557613c14615031565b5b90600052602060002090602091828204019190069054906101000a900460ff169150505b92915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613caf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613ca690615e6d565b60405180910390fd5b613cb88161253e565b15613cf8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613cef90615ed9565b60405180910390fd5b613d04600083836132c5565b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613d549190614b0e565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b604051806101400160405280600015158152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff168152602001600060ff1681525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613ec681613e91565b8114613ed157600080fd5b50565b600081359050613ee381613ebd565b92915050565b600060208284031215613eff57613efe613e87565b5b6000613f0d84828501613ed4565b91505092915050565b60008115159050919050565b613f2b81613f16565b82525050565b6000602082019050613f466000830184613f22565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613f86578082015181840152602081019050613f6b565b83811115613f95576000848401525b50505050565b6000601f19601f8301169050919050565b6000613fb782613f4c565b613fc18185613f57565b9350613fd1818560208601613f68565b613fda81613f9b565b840191505092915050565b60006020820190508181036000830152613fff8184613fac565b905092915050565b6000819050919050565b61401a81614007565b811461402557600080fd5b50565b60008135905061403781614011565b92915050565b60006020828403121561405357614052613e87565b5b600061406184828501614028565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006140958261406a565b9050919050565b6140a58161408a565b82525050565b60006020820190506140c0600083018461409c565b92915050565b6140cf8161408a565b81146140da57600080fd5b50565b6000813590506140ec816140c6565b92915050565b6000806040838503121561410957614108613e87565b5b6000614117858286016140dd565b925050602061412885828601614028565b9150509250929050565b61413b81613f16565b811461414657600080fd5b50565b60008135905061415881614132565b92915050565b6000806040838503121561417557614174613e87565b5b600061418385828601614028565b925050602061419485828601614149565b9150509250929050565b6000602082840312156141b4576141b3613e87565b5b60006141c284828501614149565b91505092915050565b6141d481614007565b82525050565b60006020820190506141ef60008301846141cb565b92915050565b6000819050919050565b600061421a6142156142108461406a565b6141f5565b61406a565b9050919050565b600061422c826141ff565b9050919050565b600061423e82614221565b9050919050565b61424e81614233565b82525050565b60006020820190506142696000830184614245565b92915050565b60008060006060848603121561428857614287613e87565b5b6000614296868287016140dd565b93505060206142a7868287016140dd565b92505060406142b886828701614028565b9150509250925092565b600080604083850312156142d9576142d8613e87565b5b60006142e785828601614028565b92505060206142f885828601614028565b9150509250929050565b600060ff82169050919050565b61431881614302565b82525050565b6000602082019050614333600083018461430f565b92915050565b600061ffff82169050919050565b61435081614339565b82525050565b600060208201905061436b6000830184614347565b92915050565b60006020828403121561438757614386613e87565b5b6000614395848285016140dd565b91505092915050565b6143a781613f16565b82525050565b6143b681614302565b82525050565b610140820160008201516143d3600085018261439e565b5060208201516143e660208501826143ad565b5060408201516143f960408501826143ad565b50606082015161440c60608501826143ad565b50608082015161441f60808501826143ad565b5060a082015161443260a08501826143ad565b5060c082015161444560c08501826143ad565b5060e082015161445860e08501826143ad565b5061010082015161446d6101008501826143ad565b506101208201516144826101208501826143ad565b50505050565b60006101408201905061449e60008301846143bc565b92915050565b600080604083850312156144bb576144ba613e87565b5b60006144c9858286016140dd565b92505060206144da85828601614149565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61452682613f9b565b810181811067ffffffffffffffff82111715614545576145446144ee565b5b80604052505050565b6000614558613e7d565b9050614564828261451d565b919050565b600067ffffffffffffffff821115614584576145836144ee565b5b61458d82613f9b565b9050602081019050919050565b82818337600083830152505050565b60006145bc6145b784614569565b61454e565b9050828152602081018484840111156145d8576145d76144e9565b5b6145e384828561459a565b509392505050565b600082601f830112614600576145ff6144e4565b5b81356146108482602086016145a9565b91505092915050565b6000806000806080858703121561463357614632613e87565b5b6000614641878288016140dd565b9450506020614652878288016140dd565b935050604061466387828801614028565b925050606085013567ffffffffffffffff81111561468457614683613e8c565b5b614690878288016145eb565b91505092959194509250565b6000610140820190506146b2600083018d613f22565b6146bf602083018c61430f565b6146cc604083018b61430f565b6146d9606083018a61430f565b6146e6608083018961430f565b6146f360a083018861430f565b61470060c083018761430f565b61470d60e083018661430f565b61471b61010083018561430f565b61472961012083018461430f565b9b9a5050505050505050505050565b600061474382614221565b9050919050565b61475381614738565b82525050565b600060208201905061476e600083018461474a565b92915050565b600061477f82614221565b9050919050565b61478f81614774565b82525050565b60006020820190506147aa6000830184614786565b92915050565b600080604083850312156147c7576147c6613e87565b5b60006147d5858286016140dd565b92505060206147e6858286016140dd565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061483757607f821691505b6020821081141561484b5761484a6147f0565b5b50919050565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b60006148ad602c83613f57565b91506148b882614851565b604082019050919050565b600060208201905081810360008301526148dc816148a0565b9050919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b600061493f602183613f57565b915061494a826148e3565b604082019050919050565b6000602082019050818103600083015261496e81614932565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b60006149d1603883613f57565b91506149dc82614975565b604082019050919050565b60006020820190508181036000830152614a00816149c4565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b6000614a3d601083613f57565b9150614a4882614a07565b602082019050919050565b60006020820190508181036000830152614a6c81614a30565b9050919050565b7f4f6e6c7920454f41000000000000000000000000000000000000000000000000600082015250565b6000614aa9600883613f57565b9150614ab482614a73565b602082019050919050565b60006020820190508181036000830152614ad881614a9c565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614b1982614007565b9150614b2483614007565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614b5957614b58614adf565b5b828201905092915050565b7f416c6c20746f6b656e73206d696e746564000000000000000000000000000000600082015250565b6000614b9a601183613f57565b9150614ba582614b64565b602082019050919050565b60006020820190508181036000830152614bc981614b8d565b9050919050565b7f496e76616c6964206d696e7420616d6f756e7400000000000000000000000000600082015250565b6000614c06601383613f57565b9150614c1182614bd0565b602082019050919050565b60006020820190508181036000830152614c3581614bf9565b9050919050565b6000614c4782614007565b9150614c5283614007565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614c8b57614c8a614adf565b5b828202905092915050565b7f496e76616c6964207061796d656e7420616d6f756e7400000000000000000000600082015250565b6000614ccc601683613f57565b9150614cd782614c96565b602082019050919050565b60006020820190508181036000830152614cfb81614cbf565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614d38602083613f57565b9150614d4382614d02565b602082019050919050565b60006020820190508181036000830152614d6781614d2b565b9050919050565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b6000614dca603183613f57565b9150614dd582614d6e565b604082019050919050565b60006020820190508181036000830152614df981614dbd565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614e3a82614007565b9150614e4583614007565b925082614e5557614e54614e00565b5b828204905092915050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b6000614ebc602b83613f57565b9150614ec782614e60565b604082019050919050565b60006020820190508181036000830152614eeb81614eaf565b9050919050565b600081519050614f0181614011565b92915050565b600060208284031215614f1d57614f1c613e87565b5b6000614f2b84828501614ef2565b91505092915050565b6000604082019050614f49600083018561409c565b614f5660208301846141cb565b9392505050565b600081519050614f6c81614132565b92915050565b600060208284031215614f8857614f87613e87565b5b6000614f9684828501614f5d565b91505092915050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b6000614ffb602c83613f57565b915061500682614f9f565b604082019050919050565b6000602082019050818103600083015261502a81614fee565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b60006150bc602983613f57565b91506150c782615060565b604082019050919050565b600060208201905081810360008301526150eb816150af565b9050919050565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b600061514e602a83613f57565b9150615159826150f2565b604082019050919050565b6000602082019050818103600083015261517d81615141565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b60006151ba601983613f57565b91506151c582615184565b602082019050919050565b600060208201905081810360008301526151e9816151ad565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b600061524c602f83613f57565b9150615257826151f0565b604082019050919050565b6000602082019050818103600083015261527b8161523f565b9050919050565b600067ffffffffffffffff82111561529d5761529c6144ee565b5b6152a682613f9b565b9050602081019050919050565b60006152c66152c184615282565b61454e565b9050828152602081018484840111156152e2576152e16144e9565b5b6152ed848285613f68565b509392505050565b600082601f83011261530a576153096144e4565b5b815161531a8482602086016152b3565b91505092915050565b60006020828403121561533957615338613e87565b5b600082015167ffffffffffffffff81111561535757615356613e8c565b5b615363848285016152f5565b91505092915050565b7f4f6e6c7920776974682045544800000000000000000000000000000000000000600082015250565b60006153a2600d83613f57565b91506153ad8261536c565b602082019050919050565b600060208201905081810360008301526153d181615395565b9050919050565b60006153e382614007565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561541657615415614adf565b5b600182019050919050565b6000604082019050615436600083018561409c565b615443602083018461409c565b9392505050565b6000819050919050565b600061546f61546a6154658461544a565b6141f5565b614007565b9050919050565b61547f81615454565b82525050565b600060408201905061549a600083018561409c565b6154a76020830184615476565b9392505050565b7f43616e27742075736520796f7572204547475300000000000000000000000000600082015250565b60006154e4601383613f57565b91506154ef826154ae565b602082019050919050565b60006020820190508181036000830152615513816154d7565b9050919050565b600060608201905061552f600083018661409c565b61553c602083018561409c565b61554960408301846141cb565b949350505050565b7f4572726f722073656e64696e6720454747530000000000000000000000000000600082015250565b6000615587601283613f57565b915061559282615551565b602082019050919050565b600060208201905081810360008301526155b68161557a565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000615619602683613f57565b9150615624826155bd565b604082019050919050565b600060208201905081810360008301526156488161560c565b9050919050565b600061565a82614339565b915061ffff82141561566f5761566e614adf565b5b600182019050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6156af81614339565b82525050565b60006156c183836156a6565b60208301905092915050565b6000602082019050919050565b60006156e58261567a565b6156ef8185615685565b93506156fa83615696565b8060005b8381101561572b57815161571288826156b5565b975061571d836156cd565b9250506001810190506156fe565b5085935050505092915050565b600060408201905061574d600083018561409c565b818103602083015261575f81846156da565b90509392505050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b600061579e601483613f57565b91506157a982615768565b602082019050919050565b600060208201905081810360008301526157cd81615791565b9050919050565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b6000615830602c83613f57565b915061583b826157d4565b604082019050919050565b6000602082019050818103600083015261585f81615823565b9050919050565b7f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960008201527f73206e6f74206f776e0000000000000000000000000000000000000000000000602082015250565b60006158c2602983613f57565b91506158cd82615866565b604082019050919050565b600060208201905081810360008301526158f1816158b5565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000615954602483613f57565b915061595f826158f8565b604082019050919050565b6000602082019050818103600083015261598381615947565b9050919050565b600061599582614007565b91506159a083614007565b9250828210156159b3576159b2614adf565b5b828203905092915050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000615a1a603283613f57565b9150615a25826159be565b604082019050919050565b60006020820190508181036000830152615a4981615a0d565b9050919050565b60008160601b9050919050565b6000615a6882615a50565b9050919050565b6000615a7a82615a5d565b9050919050565b615a92615a8d8261408a565b615a6f565b82525050565b6000819050919050565b6000819050919050565b615abd615ab882615a98565b615aa2565b82525050565b6000819050919050565b615ade615ad982614007565b615ac3565b82525050565b6000615af08287615a81565b601482019150615b008286615aac565b602082019150615b108285615acd565b602082019150615b208284615acd565b60208201915081905095945050505050565b6000615b3d82614007565b9150615b4883614007565b925082615b5857615b57614e00565b5b828206905092915050565b600081519050615b72816140c6565b92915050565b600060208284031215615b8e57615b8d613e87565b5b6000615b9c84828501615b63565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000615bcc82615ba5565b615bd68185615bb0565b9350615be6818560208601613f68565b615bef81613f9b565b840191505092915050565b6000608082019050615c0f600083018761409c565b615c1c602083018661409c565b615c2960408301856141cb565b8181036060830152615c3b8184615bc1565b905095945050505050565b600081519050615c5581613ebd565b92915050565b600060208284031215615c7157615c70613e87565b5b6000615c7f84828501615c46565b91505092915050565b6000615c9382614302565b9150615c9e83614302565b92508260ff03821115615cb457615cb3614adf565b5b828201905092915050565b60008160f81b9050919050565b6000615cd782615cbf565b9050919050565b6000615ce982615ccc565b9050919050565b615d01615cfc82613f16565b615cde565b82525050565b615d18615d1382614302565b615ccc565b82525050565b6000615d2a828c615cf0565b600182019150615d3a828b615d07565b600182019150615d4a828a615d07565b600182019150615d5a8289615d07565b600182019150615d6a8288615d07565b600182019150615d7a8287615d07565b600182019150615d8a8286615d07565b600182019150615d9a8285615d07565b600182019150615daa8284615d07565b6001820191508190509a9950505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000615dfb82614302565b9150615e0683614302565b925082615e1657615e15614e00565b5b828206905092915050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b6000615e57602083613f57565b9150615e6282615e21565b602082019050919050565b60006020820190508181036000830152615e8681615e4a565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000615ec3601c83613f57565b9150615ece82615e8d565b602082019050919050565b60006020820190508181036000830152615ef281615eb6565b905091905056fea2646970667358221220ea37b8bb35257cd60ddb9c0481dfc6968f58f36ee347af832c5b2b87ff11c7c064736f6c634300080a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000053ae3a8f0bb81234314e058ad505fdbe8b1b5bc80000000000000000000000003d6c10351a1c695729f5ad257e6fdcc7590c427c000000000000000000000000000000000000000000000000000000000000c350
-----Decoded View---------------
Arg [0] : _eggs (address): 0x53ae3A8f0bb81234314e058aD505fdBE8b1b5Bc8
Arg [1] : _traits (address): 0x3d6c10351a1c695729f5aD257E6FDcC7590C427C
Arg [2] : _maxTokens (uint256): 50000
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000053ae3a8f0bb81234314e058ad505fdbe8b1b5bc8
Arg [1] : 0000000000000000000000003d6c10351a1c695729f5ad257e6fdcc7590c427c
Arg [2] : 000000000000000000000000000000000000000000000000000000000000c350
Deployed Bytecode Sourcemap
246:12146:7:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;937:224:6;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2426:100:5;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3985:221;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3508:411;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;5709:367:7;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;12037:108;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1577:113:6;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1424:17:7;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6616:387;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;6341:269;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1245:256:6;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1171:27:7;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;11869:101;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1330:26;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;11603:196;;;;;;;;;;;;;:::i;:::-;;11193:97;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5285:185:5;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;643:20:7;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1767:233:6;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1072:86:20;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2120:239:5;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1850:208;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1650:94:19;;;;;;;;;;;;;:::i;:::-;;11450:83:7;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;999:87:19;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;11053:134:7;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2595:104:5;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;693:41:7;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;985:55;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4278:295:5;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;5541:328;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;330:50:7;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;565:26;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;12170:215;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;810:51;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;1538:21;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1491:16;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4827:876;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;4644:164:5;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1899:192:19;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;453:35:7;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;937:224:6;1039:4;1078:35;1063:50;;;:11;:50;;;;:90;;;;1117:36;1141:11;1117:23;:36::i;:::-;1063:90;1056:97;;937:224;;;:::o;2426:100:5:-;2480:13;2513:5;2506:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2426:100;:::o;3985:221::-;4061:7;4089:16;4097:7;4089;:16::i;:::-;4081:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;4174:15;:24;4190:7;4174:24;;;;;;;;;;;;;;;;;;;;;4167:31;;3985:221;;;:::o;3508:411::-;3589:13;3605:23;3620:7;3605:14;:23::i;:::-;3589:39;;3653:5;3647:11;;:2;:11;;;;3639:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;3747:5;3731:21;;:12;:10;:12::i;:::-;:21;;;:62;;;;3756:37;3773:5;3780:12;:10;:12::i;:::-;3756:16;:37::i;:::-;3731:62;3709:168;;;;;;;;;;;;:::i;:::-;;;;;;;;;3890:21;3899:2;3903:7;3890:8;:21::i;:::-;3578:341;3508:411;;:::o;5709:367:7:-;1398:8:20;:6;:8::i;:::-;1397:9;1389:38;;;;;;;;;;;;:::i;:::-;;;;;;;;;5814:12:7::1;:10;:12::i;:::-;5801:25;;:9;:25;;;5793:46;;;;;;;;;;;;:::i;:::-;;;;;;;;;5873:11;;5863:6;5854;;;;;;;;;;;:15;;;;;;:::i;:::-;:30;;5846:60;;;;;;;;;;;;:::i;:::-;;;;;;;;;5930:1;5921:6;:10;:25;;;;;5945:1;5935:6;:11;;5921:25;5913:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;6008:9;367:13;5985:6;:19;;;;:::i;:::-;:32;5977:67;;;;;;;;;;;;:::i;:::-;;;;;;;;;6051:19;6056:6;6064:5;6051:4;:19::i;:::-;5709:367:::0;;:::o;12037:108::-;1230:12:19;:10;:12::i;:::-;1219:23;;:7;:5;:7::i;:::-;:23;;;1211:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;12100:7:7::1;12096:43;;;12109:8;:6;:8::i;:::-;12096:43;;;12129:10;:8;:10::i;:::-;12096:43;12037:108:::0;:::o;1577:113:6:-;1638:7;1665:10;:17;;;;1658:24;;1577:113;:::o;1424:17:7:-;;;;;;;;;;;;;:::o;6616:387::-;6845:4;;;;;;;;;;;6821:29;;:12;:10;:12::i;:::-;:29;;;6817:145;;6867:41;6886:12;:10;:12::i;:::-;6900:7;6867:18;:41::i;:::-;6859:103;;;;;;;;;;;;:::i;:::-;;;;;;;;;6817:145;6969:28;6979:4;6985:2;6989:7;6969:9;:28::i;:::-;6616:387;;;:::o;6341:269::-;6397:7;6428:11;;6417:7;:22;6413:46;;6448:11;6441:18;;;;6413:46;6498:1;6494;6481:10;:14;;;;:::i;:::-;:18;;;;:::i;:::-;6470:7;:29;6466:53;;6508:11;6501:18;;;;6466:53;6558:1;6554;6541:10;:14;;;;:::i;:::-;:18;;;;:::i;:::-;6530:7;:29;6526:53;;6568:11;6561:18;;;;6526:53;6593:11;6586:18;;6341:269;;;;:::o;1245:256:6:-;1342:7;1378:23;1395:5;1378:16;:23::i;:::-;1370:5;:31;1362:87;;;;;;;;;;;;:::i;:::-;;;;;;;;;1467:12;:19;1480:5;1467:19;;;;;;;;;;;;;;;:26;1487:5;1467:26;;;;;;;;;;;;1460:33;;1245:256;;;;:::o;1171:27:7:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;11869:101::-;1230:12:19;:10;:12::i;:::-;1219:23;;:7;:5;:7::i;:::-;:23;;;1211:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;11953:11:7::1;11939;:25;;;;11869:101:::0;:::o;1330:26::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;11603:196::-;1230:12:19;:10;:12::i;:::-;1219:23;;:7;:5;:7::i;:::-;:23;;;1211:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;11657:7:7::1;:5;:7::i;:::-;11649:25;;:48;11675:21;11649:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;11704:16;11723:4;;;;;;;;;;;:14;;;11746:4;11723:29;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;11704:48;;11759:4;;;;;;;;;;;:13;;;11773:7;:5;:7::i;:::-;11781:11;11759:34;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;11642:157;11603:196::o:0;11193:97::-;11250:7;11273:11;;11266:18;;11193:97;:::o;5285:185:5:-;5423:39;5440:4;5446:2;5450:7;5423:39;;;;;;;;;;;;:16;:39::i;:::-;5285:185;;;:::o;643:20:7:-;;;;;;;;;;;;;:::o;1767:233:6:-;1842:7;1878:30;:28;:30::i;:::-;1870:5;:38;1862:95;;;;;;;;;;;;:::i;:::-;;;;;;;;;1975:10;1986:5;1975:17;;;;;;;;:::i;:::-;;;;;;;;;;1968:24;;1767:233;;;:::o;1072:86:20:-;1119:4;1143:7;;;;;;;;;;;1136:14;;1072:86;:::o;2120:239:5:-;2192:7;2212:13;2228:7;:16;2236:7;2228:16;;;;;;;;;;;;;;;;;;;;;2212:32;;2280:1;2263:19;;:5;:19;;;;2255:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;2346:5;2339:12;;;2120:239;;;:::o;1850:208::-;1922:7;1967:1;1950:19;;:5;:19;;;;1942:74;;;;;;;;;;;;:::i;:::-;;;;;;;;;2034:9;:16;2044:5;2034:16;;;;;;;;;;;;;;;;2027:23;;1850:208;;;:::o;1650:94:19:-;1230:12;:10;:12::i;:::-;1219:23;;:7;:5;:7::i;:::-;:23;;;1211:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;1715:21:::1;1733:1;1715:9;:21::i;:::-;1650:94::o:0;11450:83:7:-;1230:12:19;:10;:12::i;:::-;1219:23;;:7;:5;:7::i;:::-;:23;;;1211:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;11521:5:7::1;11508:4;;:19;;;;;;;;;;;;;;;;;;11450:83:::0;:::o;999:87:19:-;1045:7;1072:6;;;;;;;;;;;1065:13;;999:87;:::o;11053:134:7:-;11126:19;;:::i;:::-;11161:11;:20;11173:7;11161:20;;;;;;;;;;;11154:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11053:134;;;:::o;2595:104:5:-;2651:13;2684:7;2677:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2595:104;:::o;693:41:7:-;;;;;;;;;;;;;;;;;:::o;985:55::-;;;;;;;;;;;;;;;;;:::o;4278:295:5:-;4393:12;:10;:12::i;:::-;4381:24;;:8;:24;;;;4373:62;;;;;;;;;;;;:::i;:::-;;;;;;;;;4493:8;4448:18;:32;4467:12;:10;:12::i;:::-;4448:32;;;;;;;;;;;;;;;:42;4481:8;4448:42;;;;;;;;;;;;;;;;:53;;;;;;;;;;;;;;;;;;4546:8;4517:48;;4532:12;:10;:12::i;:::-;4517:48;;;4556:8;4517:48;;;;;;:::i;:::-;;;;;;;;4278:295;;:::o;5541:328::-;5716:41;5735:12;:10;:12::i;:::-;5749:7;5716:18;:41::i;:::-;5708:103;;;;;;;;;;;;:::i;:::-;;;;;;;;;5822:39;5836:4;5842:2;5846:7;5855:5;5822:13;:39::i;:::-;5541:328;;;;:::o;330:50:7:-;367:13;330:50;:::o;565:26::-;;;;:::o;12170:215::-;12235:13;12265:16;12273:7;12265;:16::i;:::-;12257:76;;;;;;;;;;;;:::i;:::-;;;;;;;;;12353:6;;;;;;;;;;;:15;;;12369:7;12353:24;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12346:31;;12170:215;;;:::o;810:51::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1538:21::-;;;;;;;;;;;;;:::o;1491:16::-;;;;;;;;;;;;;:::o;4827:876::-;1398:8:20;:6;:8::i;:::-;1397:9;1389:38;;;;;;;;;;;;:::i;:::-;;;;;;;;;4904:21:7::1;4957:12;:10;:12::i;:::-;4944:25;;:9;:25;;;4936:46;;;;;;;;;;;;:::i;:::-;;;;;;;;;5016:11;;5006:6;4997;;;;;;;;;;;:15;;;;;;:::i;:::-;:30;;4989:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;5069:1;5060:6;:10;:25;;;;;5084:1;5074:6;:11;;5060:25;5052:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;5125:6;5120:130;5141:6;5137:1;:10;5120:130;;;5222:18;5238:1;5231:6;;;;;;;;;;;:8;;;;;;:::i;:::-;5222;:18::i;:::-;5205:35;;;;;:::i;:::-;;;5149:3;;;;;:::i;:::-;;;;5120:130;;;;5258:19;5303:4;;;;;;;;;;;:14;;;5326:4;5332:10;5303:40;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5286:57;;5373:13;5356:14;:30;5352:207;;;5399:17;5442:4;;;;;;;;;;;:12;;;5463:4;5469:25;5442:53;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5427:68;;5514:12;5506:43;;;;;;;;;;;;:::i;:::-;;;;;;;;;5388:171;5352:207;5575:4;;;;;;;;;;;:17;;;5593:10;5613:4;5620:13;5575:59;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5567:90;;;;;;;;;;;;:::i;:::-;;;;;;;;;5664:19;5669:6;5677:5;5664:4;:19::i;:::-;4897:806;;4827:876:::0;;:::o;4644:164:5:-;4741:4;4765:18;:25;4784:5;4765:25;;;;;;;;;;;;;;;:35;4791:8;4765:35;;;;;;;;;;;;;;;;;;;;;;;;;4758:42;;4644:164;;;;:::o;1899:192:19:-;1230:12;:10;:12::i;:::-;1219:23;;:7;:5;:7::i;:::-;:23;;;1211:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;2008:1:::1;1988:22;;:8;:22;;;;1980:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;2064:19;2074:8;2064:9;:19::i;:::-;1899:192:::0;:::o;453:35:7:-;;;:::o;1481:305:5:-;1583:4;1635:25;1620:40;;;:11;:40;;;;:105;;;;1692:33;1677:48;;;:11;:48;;;;1620:105;:158;;;;1742:36;1766:11;1742:23;:36::i;:::-;1620:158;1600:178;;1481:305;;;:::o;7379:127::-;7444:4;7496:1;7468:30;;:7;:16;7476:7;7468:16;;;;;;;;;;;;;;;;;;;;;:30;;;;7461:37;;7379:127;;;:::o;602:98:1:-;655:7;682:10;675:17;;602:98;:::o;11361:174:5:-;11463:2;11436:15;:24;11452:7;11436:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;11519:7;11515:2;11481:46;;11490:23;11505:7;11490:14;:23::i;:::-;11481:46;;;;;;;;;;;;11361:174;;:::o;4227:594:7:-;4284:24;4311:5;:46;;4355:1;4342:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4311:46;;;4332:6;4319:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4311:46;4284:73;;4364:12;4388:6;4397:1;4388:10;;4383:366;4404:6;4400:1;:10;4383:366;;;4426:6;;:8;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;4450:14;4457:6;;;;;;;;;;;4450:14;;:6;:14::i;:::-;4443:21;;4473:22;4482:6;;;;;;;;;;;4473:22;;4490:4;4473:8;:22::i;:::-;;4504:17;4524:21;4540:4;4524:15;:21::i;:::-;4504:41;;4559:5;4558:6;:35;;;;4581:12;:10;:12::i;:::-;4568:25;;:9;:25;;;;4558:35;4554:180;;;4606:28;4616:9;4627:6;;;;;;;;;;;4606:28;;:9;:28::i;:::-;4554:180;;;4661:32;4679:4;;;;;;;;;;;4686:6;;;;;;;;;;;4661:32;;:9;:32::i;:::-;4718:6;;;;;;;;;;;4704:8;4713:1;4704:11;;;;;;;;:::i;:::-;;;;;;;:20;;;;;;;;;;;4554:180;4417:332;4412:3;;;;;:::i;:::-;;;;4383:366;;;;4759:5;4755:60;;;4766:4;;;;;;;;;;;:25;;;4792:12;:10;:12::i;:::-;4806:8;4766:49;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4755:60;4277:544;;4227:594;;:::o;1872:118:20:-;1398:8;:6;:8::i;:::-;1397:9;1389:38;;;;;;;;;;;;:::i;:::-;;;;;;;;;1942:4:::1;1932:7;;:14;;;;;;;;;;;;;;;;;;1962:20;1969:12;:10;:12::i;:::-;1962:20;;;;;;:::i;:::-;;;;;;;;1872:118::o:0;2131:120::-;1675:8;:6;:8::i;:::-;1667:41;;;;;;;;;;;;:::i;:::-;;;;;;;;;2200:5:::1;2190:7;;:15;;;;;;;;;;;;;;;;;;2221:22;2230:12;:10;:12::i;:::-;2221:22;;;;;;:::i;:::-;;;;;;;;2131:120::o:0;7673:348:5:-;7766:4;7791:16;7799:7;7791;:16::i;:::-;7783:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;7867:13;7883:23;7898:7;7883:14;:23::i;:::-;7867:39;;7936:5;7925:16;;:7;:16;;;:51;;;;7969:7;7945:31;;:20;7957:7;7945:11;:20::i;:::-;:31;;;7925:51;:87;;;;7980:32;7997:5;8004:7;7980:16;:32::i;:::-;7925:87;7917:96;;;7673:348;;;;:::o;10665:578::-;10824:4;10797:31;;:23;10812:7;10797:14;:23::i;:::-;:31;;;10789:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;10907:1;10893:16;;:2;:16;;;;10885:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;10963:39;10984:4;10990:2;10994:7;10963:20;:39::i;:::-;11067:29;11084:1;11088:7;11067:8;:29::i;:::-;11128:1;11109:9;:15;11119:4;11109:15;;;;;;;;;;;;;;;;:20;;;;;;;:::i;:::-;;;;;;;;11157:1;11140:9;:13;11150:2;11140:13;;;;;;;;;;;;;;;;:18;;;;;;;:::i;:::-;;;;;;;;11188:2;11169:7;:16;11177:7;11169:16;;;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;11227:7;11223:2;11208:27;;11217:4;11208:27;;;;;;;;;;;;10665:578;;;:::o;2099:173:19:-;2155:16;2174:6;;;;;;;;;;;2155:25;;2200:8;2191:6;;:17;;;;;;;;;;;;;;;;;;2255:8;2224:40;;2245:8;2224:40;;;;;;;;;;;;2144:128;2099:173;:::o;6751:315:5:-;6908:28;6918:4;6924:2;6928:7;6908:9;:28::i;:::-;6955:48;6978:4;6984:2;6988:7;6997:5;6955:22;:48::i;:::-;6947:111;;;;;;;;;;;;:::i;:::-;;;;;;;;;6751:315;;;;:::o;787:157:3:-;872:4;911:25;896:40;;;:11;:40;;;;889:47;;787:157;;;:::o;10814:216:7:-;10867:7;10933:9;10976:1;10961:12;:16;;;;:::i;:::-;10951:27;10987:15;11011:4;10908:114;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;10898:125;;;;;;10890:134;;10883:141;;10814:216;;;:::o;7317:338::-;7384:21;;:::i;:::-;7418:18;7431:4;7418:12;:18::i;:::-;7414:22;;7488:1;7447:20;:37;7468:15;7481:1;7468:12;:15::i;:::-;7447:37;;;;;;;;;;;;:42;7443:162;;;7523:1;7500:11;:20;7512:7;7500:20;;;;;;;;;;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7573:7;7533:20;:37;7554:15;7567:1;7554:12;:15::i;:::-;7533:37;;;;;;;;;;;:47;;;;7589:8;;7443:162;7618:31;7627:7;7636:12;7643:4;7636:6;:12::i;:::-;7618:8;:31::i;:::-;7611:38;;7317:338;;;;;:::o;8628:361::-;8690:7;8720:11;;8710:6;;;;;;;;;;;:21;;;;:50;;;;8759:1;8752:2;8745:3;8737:4;:11;;8736:18;;;;:::i;:::-;8735:25;;8710:50;8706:75;;;8769:12;:10;:12::i;:::-;8762:19;;;;8706:75;8821:13;8837:4;;;;;;;;;;;:20;;;8866:3;8858:4;:11;;8837:33;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8821:49;;8939:3;8922:21;;:5;:21;;;8918:46;;;8952:12;:10;:12::i;:::-;8945:19;;;;;8918:46;8978:5;8971:12;;;8628:361;;;;:::o;8363:110:5:-;8439:26;8449:2;8453:7;8439:26;;;;;;;;;;;;:9;:26::i;:::-;8363:110;;:::o;2613:589:6:-;2757:45;2784:4;2790:2;2794:7;2757:26;:45::i;:::-;2835:1;2819:18;;:4;:18;;;2815:187;;;2854:40;2886:7;2854:31;:40::i;:::-;2815:187;;;2924:2;2916:10;;:4;:10;;;2912:90;;2943:47;2976:4;2982:7;2943:32;:47::i;:::-;2912:90;2815:187;3030:1;3016:16;;:2;:16;;;3012:183;;;3049:45;3086:7;3049:36;:45::i;:::-;3012:183;;;3122:4;3116:10;;:2;:10;;;3112:83;;3143:40;3171:2;3175:7;3143:27;:40::i;:::-;3112:83;3012:183;2613:589;;;:::o;12100:799:5:-;12255:4;12276:15;:2;:13;;;:15::i;:::-;12272:620;;;12328:2;12312:36;;;12349:12;:10;:12::i;:::-;12363:4;12369:7;12378:5;12312:72;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;12308:529;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12571:1;12554:6;:13;:18;12550:272;;;12597:60;;;;;;;;;;:::i;:::-;;;;;;;;12550:272;12772:6;12766:13;12757:6;12753:2;12749:15;12742:38;12308:529;12445:41;;;12435:51;;;:6;:51;;;;12428:58;;;;;12272:620;12876:4;12869:11;;12100:799;;;;;;;:::o;9207:897:7:-;9266:21;;:::i;:::-;9339:1;9333:2;9323:6;9316:4;:13;9315:20;;;;:::i;:::-;:25;;9300:1;:12;;:40;;;;;;;;;;;9347:11;9361:1;:12;;;:20;;9380:1;9361:20;;;9376:1;9361:20;9347:34;;9397:2;9388:11;;;;;9414:45;9440:6;9433:4;:13;9453:5;9449:1;:9;;;;:::i;:::-;9414:11;:45::i;:::-;9406:1;:5;;:53;;;;;;;;;;;9475:2;9466:11;;;;;9493:45;9519:6;9512:4;:13;9532:5;9528:1;:9;;;;:::i;:::-;9493:11;:45::i;:::-;9484:1;:6;;:54;;;;;;;;;;;9554:2;9545:11;;;;;9572:45;9598:6;9591:4;:13;9611:5;9607:1;:9;;;;:::i;:::-;9572:11;:45::i;:::-;9563:1;:6;;:54;;;;;;;;;;;9633:2;9624:11;;;;;9651:45;9677:6;9670:4;:13;9690:5;9686:1;:9;;;;:::i;:::-;9651:11;:45::i;:::-;9642:1;:6;;:54;;;;;;;;;;;9712:2;9703:11;;;;;9730:45;9756:6;9749:4;:13;9769:5;9765:1;:9;;;;:::i;:::-;9730:11;:45::i;:::-;9721:1;:6;;:54;;;;;;;;;;;9791:2;9782:11;;;;;9810:45;9836:6;9829:4;:13;9849:5;9845:1;:9;;;;:::i;:::-;9810:11;:45::i;:::-;9800:1;:7;;:55;;;;;;;;;;;9871:2;9862:11;;;;;9889:45;9915:6;9908:4;:13;9928:5;9924:1;:9;;;;:::i;:::-;9889:11;:45::i;:::-;9880:1;:6;;:54;;;;;;;;;;;9950:2;9941:11;;;;;9968:45;9994:6;9987:4;:13;10007:5;10003:1;:9;;;;:::i;:::-;9968:11;:45::i;:::-;9959:1;:6;;:54;;;;;;;;;;;10029:2;10020:11;;;;;10053:45;10079:6;10072:4;:13;10092:5;10088:1;:9;;;;:::i;:::-;10053:11;:45::i;:::-;10038:1;:12;;:60;;;;;;;;;;;9289:815;9207:897;;;:::o;10308:321::-;10376:7;10452:1;:12;;;10475:1;:5;;;10491:1;:6;;;10508:1;:6;;;10525:1;:7;;;10543:1;:6;;;10560:1;:6;;;10577:1;:6;;;10594:1;:12;;;10425:190;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;10407:215;;;;;;10399:224;;10392:231;;10308:321;;;:::o;8700::5:-;8830:18;8836:2;8840:7;8830:5;:18::i;:::-;8881:54;8912:1;8916:2;8920:7;8929:5;8881:22;:54::i;:::-;8859:154;;;;;;;;;;;;:::i;:::-;;;;;;;;;8700:321;;;:::o;13471:126::-;;;;:::o;3925:164:6:-;4029:10;:17;;;;4002:15;:24;4018:7;4002:24;;;;;;;;;;;:44;;;;4057:10;4073:7;4057:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3925:164;:::o;4716:988::-;4982:22;5032:1;5007:22;5024:4;5007:16;:22::i;:::-;:26;;;;:::i;:::-;4982:51;;5044:18;5065:17;:26;5083:7;5065:26;;;;;;;;;;;;5044:47;;5212:14;5198:10;:28;5194:328;;5243:19;5265:12;:18;5278:4;5265:18;;;;;;;;;;;;;;;:34;5284:14;5265:34;;;;;;;;;;;;5243:56;;5349:11;5316:12;:18;5329:4;5316:18;;;;;;;;;;;;;;;:30;5335:10;5316:30;;;;;;;;;;;:44;;;;5466:10;5433:17;:30;5451:11;5433:30;;;;;;;;;;;:43;;;;5228:294;5194:328;5618:17;:26;5636:7;5618:26;;;;;;;;;;;5611:33;;;5662:12;:18;5675:4;5662:18;;;;;;;;;;;;;;;:34;5681:14;5662:34;;;;;;;;;;;5655:41;;;4797:907;;4716:988;;:::o;5999:1079::-;6252:22;6297:1;6277:10;:17;;;;:21;;;;:::i;:::-;6252:46;;6309:18;6330:15;:24;6346:7;6330:24;;;;;;;;;;;;6309:45;;6681:19;6703:10;6714:14;6703:26;;;;;;;;:::i;:::-;;;;;;;;;;6681:48;;6767:11;6742:10;6753;6742:22;;;;;;;;:::i;:::-;;;;;;;;;:36;;;;6878:10;6847:15;:28;6863:11;6847:28;;;;;;;;;;;:41;;;;7019:15;:24;7035:7;7019:24;;;;;;;;;;;7012:31;;;7054:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;6070:1008;;;5999:1079;:::o;3503:221::-;3588:14;3605:20;3622:2;3605:16;:20::i;:::-;3588:37;;3663:7;3636:12;:16;3649:2;3636:16;;;;;;;;;;;;;;;:24;3653:6;3636:24;;;;;;;;;;;:34;;;;3710:6;3681:17;:26;3699:7;3681:26;;;;;;;;;;;:35;;;;3577:147;3503:221;;:::o;743:387:0:-;803:4;1011:12;1078:7;1066:20;1058:28;;1121:1;1114:4;:8;1107:15;;;743:387;;;:::o;8071:257:7:-;8145:5;8159:11;8193:8;8202:9;8193:19;;;;;;;;;:::i;:::-;;;:26;;;;8179:4;8173:47;;;;:::i;:::-;8159:61;;8243:8;8252:9;8243:19;;;;;;;;;:::i;:::-;;;8263:5;8243:26;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;8231:38;;8239:1;8231:4;:9;;;;:38;;;8227:56;;;8278:5;8271:12;;;;;8227:56;8297:7;8305:9;8297:18;;;;;;;;;:::i;:::-;;;8316:5;8297:25;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;8290:32;;;8071:257;;;;;:::o;9357:382:5:-;9451:1;9437:16;;:2;:16;;;;9429:61;;;;;;;;;;;;:::i;:::-;;;;;;;;;9510:16;9518:7;9510;:16::i;:::-;9509:17;9501:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;9572:45;9601:1;9605:2;9609:7;9572:20;:45::i;:::-;9647:1;9630:9;:13;9640:2;9630:13;;;;;;;;;;;;;;;;:18;;;;;;;:::i;:::-;;;;;;;;9678:2;9659:7;:16;9667:7;9659:16;;;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;9723:7;9719:2;9698:33;;9715:1;9698:33;;;;;;;;;;;;9357:382;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;7:75:23:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:99::-;1570:6;1604:5;1598:12;1588:22;;1518:99;;;:::o;1623:169::-;1707:11;1741:6;1736:3;1729:19;1781:4;1776:3;1772:14;1757:29;;1623:169;;;;:::o;1798:307::-;1866:1;1876:113;1890:6;1887:1;1884:13;1876:113;;;1975:1;1970:3;1966:11;1960:18;1956:1;1951:3;1947:11;1940:39;1912:2;1909:1;1905:10;1900:15;;1876:113;;;2007:6;2004:1;2001:13;1998:101;;;2087:1;2078:6;2073:3;2069:16;2062:27;1998:101;1847:258;1798:307;;;:::o;2111:102::-;2152:6;2203:2;2199:7;2194:2;2187:5;2183:14;2179:28;2169:38;;2111:102;;;:::o;2219:364::-;2307:3;2335:39;2368:5;2335:39;:::i;:::-;2390:71;2454:6;2449:3;2390:71;:::i;:::-;2383:78;;2470:52;2515:6;2510:3;2503:4;2496:5;2492:16;2470:52;:::i;:::-;2547:29;2569:6;2547:29;:::i;:::-;2542:3;2538:39;2531:46;;2311:272;2219:364;;;;:::o;2589:313::-;2702:4;2740:2;2729:9;2725:18;2717:26;;2789:9;2783:4;2779:20;2775:1;2764:9;2760:17;2753:47;2817:78;2890:4;2881:6;2817:78;:::i;:::-;2809:86;;2589:313;;;;:::o;2908:77::-;2945:7;2974:5;2963:16;;2908:77;;;:::o;2991:122::-;3064:24;3082:5;3064:24;:::i;:::-;3057:5;3054:35;3044:63;;3103:1;3100;3093:12;3044:63;2991:122;:::o;3119:139::-;3165:5;3203:6;3190:20;3181:29;;3219:33;3246:5;3219:33;:::i;:::-;3119:139;;;;:::o;3264:329::-;3323:6;3372:2;3360:9;3351:7;3347:23;3343:32;3340:119;;;3378:79;;:::i;:::-;3340:119;3498:1;3523:53;3568:7;3559:6;3548:9;3544:22;3523:53;:::i;:::-;3513:63;;3469:117;3264:329;;;;:::o;3599:126::-;3636:7;3676:42;3669:5;3665:54;3654:65;;3599:126;;;:::o;3731:96::-;3768:7;3797:24;3815:5;3797:24;:::i;:::-;3786:35;;3731:96;;;:::o;3833:118::-;3920:24;3938:5;3920:24;:::i;:::-;3915:3;3908:37;3833:118;;:::o;3957:222::-;4050:4;4088:2;4077:9;4073:18;4065:26;;4101:71;4169:1;4158:9;4154:17;4145:6;4101:71;:::i;:::-;3957:222;;;;:::o;4185:122::-;4258:24;4276:5;4258:24;:::i;:::-;4251:5;4248:35;4238:63;;4297:1;4294;4287:12;4238:63;4185:122;:::o;4313:139::-;4359:5;4397:6;4384:20;4375:29;;4413:33;4440:5;4413:33;:::i;:::-;4313:139;;;;:::o;4458:474::-;4526:6;4534;4583:2;4571:9;4562:7;4558:23;4554:32;4551:119;;;4589:79;;:::i;:::-;4551:119;4709:1;4734:53;4779:7;4770:6;4759:9;4755:22;4734:53;:::i;:::-;4724:63;;4680:117;4836:2;4862:53;4907:7;4898:6;4887:9;4883:22;4862:53;:::i;:::-;4852:63;;4807:118;4458:474;;;;;:::o;4938:116::-;5008:21;5023:5;5008:21;:::i;:::-;5001:5;4998:32;4988:60;;5044:1;5041;5034:12;4988:60;4938:116;:::o;5060:133::-;5103:5;5141:6;5128:20;5119:29;;5157:30;5181:5;5157:30;:::i;:::-;5060:133;;;;:::o;5199:468::-;5264:6;5272;5321:2;5309:9;5300:7;5296:23;5292:32;5289:119;;;5327:79;;:::i;:::-;5289:119;5447:1;5472:53;5517:7;5508:6;5497:9;5493:22;5472:53;:::i;:::-;5462:63;;5418:117;5574:2;5600:50;5642:7;5633:6;5622:9;5618:22;5600:50;:::i;:::-;5590:60;;5545:115;5199:468;;;;;:::o;5673:323::-;5729:6;5778:2;5766:9;5757:7;5753:23;5749:32;5746:119;;;5784:79;;:::i;:::-;5746:119;5904:1;5929:50;5971:7;5962:6;5951:9;5947:22;5929:50;:::i;:::-;5919:60;;5875:114;5673:323;;;;:::o;6002:118::-;6089:24;6107:5;6089:24;:::i;:::-;6084:3;6077:37;6002:118;;:::o;6126:222::-;6219:4;6257:2;6246:9;6242:18;6234:26;;6270:71;6338:1;6327:9;6323:17;6314:6;6270:71;:::i;:::-;6126:222;;;;:::o;6354:60::-;6382:3;6403:5;6396:12;;6354:60;;;:::o;6420:142::-;6470:9;6503:53;6521:34;6530:24;6548:5;6530:24;:::i;:::-;6521:34;:::i;:::-;6503:53;:::i;:::-;6490:66;;6420:142;;;:::o;6568:126::-;6618:9;6651:37;6682:5;6651:37;:::i;:::-;6638:50;;6568:126;;;:::o;6700:140::-;6764:9;6797:37;6828:5;6797:37;:::i;:::-;6784:50;;6700:140;;;:::o;6846:159::-;6947:51;6992:5;6947:51;:::i;:::-;6942:3;6935:64;6846:159;;:::o;7011:250::-;7118:4;7156:2;7145:9;7141:18;7133:26;;7169:85;7251:1;7240:9;7236:17;7227:6;7169:85;:::i;:::-;7011:250;;;;:::o;7267:619::-;7344:6;7352;7360;7409:2;7397:9;7388:7;7384:23;7380:32;7377:119;;;7415:79;;:::i;:::-;7377:119;7535:1;7560:53;7605:7;7596:6;7585:9;7581:22;7560:53;:::i;:::-;7550:63;;7506:117;7662:2;7688:53;7733:7;7724:6;7713:9;7709:22;7688:53;:::i;:::-;7678:63;;7633:118;7790:2;7816:53;7861:7;7852:6;7841:9;7837:22;7816:53;:::i;:::-;7806:63;;7761:118;7267:619;;;;;:::o;7892:474::-;7960:6;7968;8017:2;8005:9;7996:7;7992:23;7988:32;7985:119;;;8023:79;;:::i;:::-;7985:119;8143:1;8168:53;8213:7;8204:6;8193:9;8189:22;8168:53;:::i;:::-;8158:63;;8114:117;8270:2;8296:53;8341:7;8332:6;8321:9;8317:22;8296:53;:::i;:::-;8286:63;;8241:118;7892:474;;;;;:::o;8372:86::-;8407:7;8447:4;8440:5;8436:16;8425:27;;8372:86;;;:::o;8464:112::-;8547:22;8563:5;8547:22;:::i;:::-;8542:3;8535:35;8464:112;;:::o;8582:214::-;8671:4;8709:2;8698:9;8694:18;8686:26;;8722:67;8786:1;8775:9;8771:17;8762:6;8722:67;:::i;:::-;8582:214;;;;:::o;8802:89::-;8838:7;8878:6;8871:5;8867:18;8856:29;;8802:89;;;:::o;8897:115::-;8982:23;8999:5;8982:23;:::i;:::-;8977:3;8970:36;8897:115;;:::o;9018:218::-;9109:4;9147:2;9136:9;9132:18;9124:26;;9160:69;9226:1;9215:9;9211:17;9202:6;9160:69;:::i;:::-;9018:218;;;;:::o;9242:329::-;9301:6;9350:2;9338:9;9329:7;9325:23;9321:32;9318:119;;;9356:79;;:::i;:::-;9318:119;9476:1;9501:53;9546:7;9537:6;9526:9;9522:22;9501:53;:::i;:::-;9491:63;;9447:117;9242:329;;;;:::o;9577:99::-;9648:21;9663:5;9648:21;:::i;:::-;9643:3;9636:34;9577:99;;:::o;9682:102::-;9755:22;9771:5;9755:22;:::i;:::-;9750:3;9743:35;9682:102;;:::o;9852:1889::-;10009:6;10004:3;10000:16;10104:4;10097:5;10093:16;10087:23;10123:57;10174:4;10169:3;10165:14;10151:12;10123:57;:::i;:::-;10026:164;10271:4;10264:5;10260:16;10254:23;10290:59;10343:4;10338:3;10334:14;10320:12;10290:59;:::i;:::-;10200:159;10441:4;10434:5;10430:16;10424:23;10460:59;10513:4;10508:3;10504:14;10490:12;10460:59;:::i;:::-;10369:160;10611:4;10604:5;10600:16;10594:23;10630:59;10683:4;10678:3;10674:14;10660:12;10630:59;:::i;:::-;10539:160;10781:4;10774:5;10770:16;10764:23;10800:59;10853:4;10848:3;10844:14;10830:12;10800:59;:::i;:::-;10709:160;10951:4;10944:5;10940:16;10934:23;10970:59;11023:4;11018:3;11014:14;11000:12;10970:59;:::i;:::-;10879:160;11122:4;11115:5;11111:16;11105:23;11141:59;11194:4;11189:3;11185:14;11171:12;11141:59;:::i;:::-;11049:161;11292:4;11285:5;11281:16;11275:23;11311:59;11364:4;11359:3;11355:14;11341:12;11311:59;:::i;:::-;11220:160;11462:6;11455:5;11451:18;11445:25;11483:61;11536:6;11531:3;11527:16;11513:12;11483:61;:::i;:::-;11390:164;11642:6;11635:5;11631:18;11625:25;11663:61;11716:6;11711:3;11707:16;11693:12;11663:61;:::i;:::-;11564:170;9978:1763;9852:1889;;:::o;11747:343::-;11900:4;11938:3;11927:9;11923:19;11915:27;;11952:131;12080:1;12069:9;12065:17;12056:6;11952:131;:::i;:::-;11747:343;;;;:::o;12096:468::-;12161:6;12169;12218:2;12206:9;12197:7;12193:23;12189:32;12186:119;;;12224:79;;:::i;:::-;12186:119;12344:1;12369:53;12414:7;12405:6;12394:9;12390:22;12369:53;:::i;:::-;12359:63;;12315:117;12471:2;12497:50;12539:7;12530:6;12519:9;12515:22;12497:50;:::i;:::-;12487:60;;12442:115;12096:468;;;;;:::o;12570:117::-;12679:1;12676;12669:12;12693:117;12802:1;12799;12792:12;12816:180;12864:77;12861:1;12854:88;12961:4;12958:1;12951:15;12985:4;12982:1;12975:15;13002:281;13085:27;13107:4;13085:27;:::i;:::-;13077:6;13073:40;13215:6;13203:10;13200:22;13179:18;13167:10;13164:34;13161:62;13158:88;;;13226:18;;:::i;:::-;13158:88;13266:10;13262:2;13255:22;13045:238;13002:281;;:::o;13289:129::-;13323:6;13350:20;;:::i;:::-;13340:30;;13379:33;13407:4;13399:6;13379:33;:::i;:::-;13289:129;;;:::o;13424:307::-;13485:4;13575:18;13567:6;13564:30;13561:56;;;13597:18;;:::i;:::-;13561:56;13635:29;13657:6;13635:29;:::i;:::-;13627:37;;13719:4;13713;13709:15;13701:23;;13424:307;;;:::o;13737:154::-;13821:6;13816:3;13811;13798:30;13883:1;13874:6;13869:3;13865:16;13858:27;13737:154;;;:::o;13897:410::-;13974:5;13999:65;14015:48;14056:6;14015:48;:::i;:::-;13999:65;:::i;:::-;13990:74;;14087:6;14080:5;14073:21;14125:4;14118:5;14114:16;14163:3;14154:6;14149:3;14145:16;14142:25;14139:112;;;14170:79;;:::i;:::-;14139:112;14260:41;14294:6;14289:3;14284;14260:41;:::i;:::-;13980:327;13897:410;;;;;:::o;14326:338::-;14381:5;14430:3;14423:4;14415:6;14411:17;14407:27;14397:122;;14438:79;;:::i;:::-;14397:122;14555:6;14542:20;14580:78;14654:3;14646:6;14639:4;14631:6;14627:17;14580:78;:::i;:::-;14571:87;;14387:277;14326:338;;;;:::o;14670:943::-;14765:6;14773;14781;14789;14838:3;14826:9;14817:7;14813:23;14809:33;14806:120;;;14845:79;;:::i;:::-;14806:120;14965:1;14990:53;15035:7;15026:6;15015:9;15011:22;14990:53;:::i;:::-;14980:63;;14936:117;15092:2;15118:53;15163:7;15154:6;15143:9;15139:22;15118:53;:::i;:::-;15108:63;;15063:118;15220:2;15246:53;15291:7;15282:6;15271:9;15267:22;15246:53;:::i;:::-;15236:63;;15191:118;15376:2;15365:9;15361:18;15348:32;15407:18;15399:6;15396:30;15393:117;;;15429:79;;:::i;:::-;15393:117;15534:62;15588:7;15579:6;15568:9;15564:22;15534:62;:::i;:::-;15524:72;;15319:287;14670:943;;;;;;;:::o;15619:1135::-;15922:4;15960:3;15949:9;15945:19;15937:27;;15974:65;16036:1;16025:9;16021:17;16012:6;15974:65;:::i;:::-;16049:68;16113:2;16102:9;16098:18;16089:6;16049:68;:::i;:::-;16127;16191:2;16180:9;16176:18;16167:6;16127:68;:::i;:::-;16205;16269:2;16258:9;16254:18;16245:6;16205:68;:::i;:::-;16283:69;16347:3;16336:9;16332:19;16323:6;16283:69;:::i;:::-;16362;16426:3;16415:9;16411:19;16402:6;16362:69;:::i;:::-;16441;16505:3;16494:9;16490:19;16481:6;16441:69;:::i;:::-;16520;16584:3;16573:9;16569:19;16560:6;16520:69;:::i;:::-;16599;16663:3;16652:9;16648:19;16639:6;16599:69;:::i;:::-;16678;16742:3;16731:9;16727:19;16718:6;16678:69;:::i;:::-;15619:1135;;;;;;;;;;;;;:::o;16760:142::-;16826:9;16859:37;16890:5;16859:37;:::i;:::-;16846:50;;16760:142;;;:::o;16908:163::-;17011:53;17058:5;17011:53;:::i;:::-;17006:3;16999:66;16908:163;;:::o;17077:254::-;17186:4;17224:2;17213:9;17209:18;17201:26;;17237:87;17321:1;17310:9;17306:17;17297:6;17237:87;:::i;:::-;17077:254;;;;:::o;17337:138::-;17399:9;17432:37;17463:5;17432:37;:::i;:::-;17419:50;;17337:138;;;:::o;17481:155::-;17580:49;17623:5;17580:49;:::i;:::-;17575:3;17568:62;17481:155;;:::o;17642:246::-;17747:4;17785:2;17774:9;17770:18;17762:26;;17798:83;17878:1;17867:9;17863:17;17854:6;17798:83;:::i;:::-;17642:246;;;;:::o;17894:474::-;17962:6;17970;18019:2;18007:9;17998:7;17994:23;17990:32;17987:119;;;18025:79;;:::i;:::-;17987:119;18145:1;18170:53;18215:7;18206:6;18195:9;18191:22;18170:53;:::i;:::-;18160:63;;18116:117;18272:2;18298:53;18343:7;18334:6;18323:9;18319:22;18298:53;:::i;:::-;18288:63;;18243:118;17894:474;;;;;:::o;18374:180::-;18422:77;18419:1;18412:88;18519:4;18516:1;18509:15;18543:4;18540:1;18533:15;18560:320;18604:6;18641:1;18635:4;18631:12;18621:22;;18688:1;18682:4;18678:12;18709:18;18699:81;;18765:4;18757:6;18753:17;18743:27;;18699:81;18827:2;18819:6;18816:14;18796:18;18793:38;18790:84;;;18846:18;;:::i;:::-;18790:84;18611:269;18560:320;;;:::o;18886:231::-;19026:34;19022:1;19014:6;19010:14;19003:58;19095:14;19090:2;19082:6;19078:15;19071:39;18886:231;:::o;19123:366::-;19265:3;19286:67;19350:2;19345:3;19286:67;:::i;:::-;19279:74;;19362:93;19451:3;19362:93;:::i;:::-;19480:2;19475:3;19471:12;19464:19;;19123:366;;;:::o;19495:419::-;19661:4;19699:2;19688:9;19684:18;19676:26;;19748:9;19742:4;19738:20;19734:1;19723:9;19719:17;19712:47;19776:131;19902:4;19776:131;:::i;:::-;19768:139;;19495:419;;;:::o;19920:220::-;20060:34;20056:1;20048:6;20044:14;20037:58;20129:3;20124:2;20116:6;20112:15;20105:28;19920:220;:::o;20146:366::-;20288:3;20309:67;20373:2;20368:3;20309:67;:::i;:::-;20302:74;;20385:93;20474:3;20385:93;:::i;:::-;20503:2;20498:3;20494:12;20487:19;;20146:366;;;:::o;20518:419::-;20684:4;20722:2;20711:9;20707:18;20699:26;;20771:9;20765:4;20761:20;20757:1;20746:9;20742:17;20735:47;20799:131;20925:4;20799:131;:::i;:::-;20791:139;;20518:419;;;:::o;20943:243::-;21083:34;21079:1;21071:6;21067:14;21060:58;21152:26;21147:2;21139:6;21135:15;21128:51;20943:243;:::o;21192:366::-;21334:3;21355:67;21419:2;21414:3;21355:67;:::i;:::-;21348:74;;21431:93;21520:3;21431:93;:::i;:::-;21549:2;21544:3;21540:12;21533:19;;21192:366;;;:::o;21564:419::-;21730:4;21768:2;21757:9;21753:18;21745:26;;21817:9;21811:4;21807:20;21803:1;21792:9;21788:17;21781:47;21845:131;21971:4;21845:131;:::i;:::-;21837:139;;21564:419;;;:::o;21989:166::-;22129:18;22125:1;22117:6;22113:14;22106:42;21989:166;:::o;22161:366::-;22303:3;22324:67;22388:2;22383:3;22324:67;:::i;:::-;22317:74;;22400:93;22489:3;22400:93;:::i;:::-;22518:2;22513:3;22509:12;22502:19;;22161:366;;;:::o;22533:419::-;22699:4;22737:2;22726:9;22722:18;22714:26;;22786:9;22780:4;22776:20;22772:1;22761:9;22757:17;22750:47;22814:131;22940:4;22814:131;:::i;:::-;22806:139;;22533:419;;;:::o;22958:158::-;23098:10;23094:1;23086:6;23082:14;23075:34;22958:158;:::o;23122:365::-;23264:3;23285:66;23349:1;23344:3;23285:66;:::i;:::-;23278:73;;23360:93;23449:3;23360:93;:::i;:::-;23478:2;23473:3;23469:12;23462:19;;23122:365;;;:::o;23493:419::-;23659:4;23697:2;23686:9;23682:18;23674:26;;23746:9;23740:4;23736:20;23732:1;23721:9;23717:17;23710:47;23774:131;23900:4;23774:131;:::i;:::-;23766:139;;23493:419;;;:::o;23918:180::-;23966:77;23963:1;23956:88;24063:4;24060:1;24053:15;24087:4;24084:1;24077:15;24104:305;24144:3;24163:20;24181:1;24163:20;:::i;:::-;24158:25;;24197:20;24215:1;24197:20;:::i;:::-;24192:25;;24351:1;24283:66;24279:74;24276:1;24273:81;24270:107;;;24357:18;;:::i;:::-;24270:107;24401:1;24398;24394:9;24387:16;;24104:305;;;;:::o;24415:167::-;24555:19;24551:1;24543:6;24539:14;24532:43;24415:167;:::o;24588:366::-;24730:3;24751:67;24815:2;24810:3;24751:67;:::i;:::-;24744:74;;24827:93;24916:3;24827:93;:::i;:::-;24945:2;24940:3;24936:12;24929:19;;24588:366;;;:::o;24960:419::-;25126:4;25164:2;25153:9;25149:18;25141:26;;25213:9;25207:4;25203:20;25199:1;25188:9;25184:17;25177:47;25241:131;25367:4;25241:131;:::i;:::-;25233:139;;24960:419;;;:::o;25385:169::-;25525:21;25521:1;25513:6;25509:14;25502:45;25385:169;:::o;25560:366::-;25702:3;25723:67;25787:2;25782:3;25723:67;:::i;:::-;25716:74;;25799:93;25888:3;25799:93;:::i;:::-;25917:2;25912:3;25908:12;25901:19;;25560:366;;;:::o;25932:419::-;26098:4;26136:2;26125:9;26121:18;26113:26;;26185:9;26179:4;26175:20;26171:1;26160:9;26156:17;26149:47;26213:131;26339:4;26213:131;:::i;:::-;26205:139;;25932:419;;;:::o;26357:348::-;26397:7;26420:20;26438:1;26420:20;:::i;:::-;26415:25;;26454:20;26472:1;26454:20;:::i;:::-;26449:25;;26642:1;26574:66;26570:74;26567:1;26564:81;26559:1;26552:9;26545:17;26541:105;26538:131;;;26649:18;;:::i;:::-;26538:131;26697:1;26694;26690:9;26679:20;;26357:348;;;;:::o;26711:172::-;26851:24;26847:1;26839:6;26835:14;26828:48;26711:172;:::o;26889:366::-;27031:3;27052:67;27116:2;27111:3;27052:67;:::i;:::-;27045:74;;27128:93;27217:3;27128:93;:::i;:::-;27246:2;27241:3;27237:12;27230:19;;26889:366;;;:::o;27261:419::-;27427:4;27465:2;27454:9;27450:18;27442:26;;27514:9;27508:4;27504:20;27500:1;27489:9;27485:17;27478:47;27542:131;27668:4;27542:131;:::i;:::-;27534:139;;27261:419;;;:::o;27686:182::-;27826:34;27822:1;27814:6;27810:14;27803:58;27686:182;:::o;27874:366::-;28016:3;28037:67;28101:2;28096:3;28037:67;:::i;:::-;28030:74;;28113:93;28202:3;28113:93;:::i;:::-;28231:2;28226:3;28222:12;28215:19;;27874:366;;;:::o;28246:419::-;28412:4;28450:2;28439:9;28435:18;28427:26;;28499:9;28493:4;28489:20;28485:1;28474:9;28470:17;28463:47;28527:131;28653:4;28527:131;:::i;:::-;28519:139;;28246:419;;;:::o;28671:236::-;28811:34;28807:1;28799:6;28795:14;28788:58;28880:19;28875:2;28867:6;28863:15;28856:44;28671:236;:::o;28913:366::-;29055:3;29076:67;29140:2;29135:3;29076:67;:::i;:::-;29069:74;;29152:93;29241:3;29152:93;:::i;:::-;29270:2;29265:3;29261:12;29254:19;;28913:366;;;:::o;29285:419::-;29451:4;29489:2;29478:9;29474:18;29466:26;;29538:9;29532:4;29528:20;29524:1;29513:9;29509:17;29502:47;29566:131;29692:4;29566:131;:::i;:::-;29558:139;;29285:419;;;:::o;29710:180::-;29758:77;29755:1;29748:88;29855:4;29852:1;29845:15;29879:4;29876:1;29869:15;29896:185;29936:1;29953:20;29971:1;29953:20;:::i;:::-;29948:25;;29987:20;30005:1;29987:20;:::i;:::-;29982:25;;30026:1;30016:35;;30031:18;;:::i;:::-;30016:35;30073:1;30070;30066:9;30061:14;;29896:185;;;;:::o;30087:230::-;30227:34;30223:1;30215:6;30211:14;30204:58;30296:13;30291:2;30283:6;30279:15;30272:38;30087:230;:::o;30323:366::-;30465:3;30486:67;30550:2;30545:3;30486:67;:::i;:::-;30479:74;;30562:93;30651:3;30562:93;:::i;:::-;30680:2;30675:3;30671:12;30664:19;;30323:366;;;:::o;30695:419::-;30861:4;30899:2;30888:9;30884:18;30876:26;;30948:9;30942:4;30938:20;30934:1;30923:9;30919:17;30912:47;30976:131;31102:4;30976:131;:::i;:::-;30968:139;;30695:419;;;:::o;31120:143::-;31177:5;31208:6;31202:13;31193:22;;31224:33;31251:5;31224:33;:::i;:::-;31120:143;;;;:::o;31269:351::-;31339:6;31388:2;31376:9;31367:7;31363:23;31359:32;31356:119;;;31394:79;;:::i;:::-;31356:119;31514:1;31539:64;31595:7;31586:6;31575:9;31571:22;31539:64;:::i;:::-;31529:74;;31485:128;31269:351;;;;:::o;31626:332::-;31747:4;31785:2;31774:9;31770:18;31762:26;;31798:71;31866:1;31855:9;31851:17;31842:6;31798:71;:::i;:::-;31879:72;31947:2;31936:9;31932:18;31923:6;31879:72;:::i;:::-;31626:332;;;;;:::o;31964:137::-;32018:5;32049:6;32043:13;32034:22;;32065:30;32089:5;32065:30;:::i;:::-;31964:137;;;;:::o;32107:345::-;32174:6;32223:2;32211:9;32202:7;32198:23;32194:32;32191:119;;;32229:79;;:::i;:::-;32191:119;32349:1;32374:61;32427:7;32418:6;32407:9;32403:22;32374:61;:::i;:::-;32364:71;;32320:125;32107:345;;;;:::o;32458:231::-;32598:34;32594:1;32586:6;32582:14;32575:58;32667:14;32662:2;32654:6;32650:15;32643:39;32458:231;:::o;32695:366::-;32837:3;32858:67;32922:2;32917:3;32858:67;:::i;:::-;32851:74;;32934:93;33023:3;32934:93;:::i;:::-;33052:2;33047:3;33043:12;33036:19;;32695:366;;;:::o;33067:419::-;33233:4;33271:2;33260:9;33256:18;33248:26;;33320:9;33314:4;33310:20;33306:1;33295:9;33291:17;33284:47;33348:131;33474:4;33348:131;:::i;:::-;33340:139;;33067:419;;;:::o;33492:180::-;33540:77;33537:1;33530:88;33637:4;33634:1;33627:15;33661:4;33658:1;33651:15;33678:228;33818:34;33814:1;33806:6;33802:14;33795:58;33887:11;33882:2;33874:6;33870:15;33863:36;33678:228;:::o;33912:366::-;34054:3;34075:67;34139:2;34134:3;34075:67;:::i;:::-;34068:74;;34151:93;34240:3;34151:93;:::i;:::-;34269:2;34264:3;34260:12;34253:19;;33912:366;;;:::o;34284:419::-;34450:4;34488:2;34477:9;34473:18;34465:26;;34537:9;34531:4;34527:20;34523:1;34512:9;34508:17;34501:47;34565:131;34691:4;34565:131;:::i;:::-;34557:139;;34284:419;;;:::o;34709:229::-;34849:34;34845:1;34837:6;34833:14;34826:58;34918:12;34913:2;34905:6;34901:15;34894:37;34709:229;:::o;34944:366::-;35086:3;35107:67;35171:2;35166:3;35107:67;:::i;:::-;35100:74;;35183:93;35272:3;35183:93;:::i;:::-;35301:2;35296:3;35292:12;35285:19;;34944:366;;;:::o;35316:419::-;35482:4;35520:2;35509:9;35505:18;35497:26;;35569:9;35563:4;35559:20;35555:1;35544:9;35540:17;35533:47;35597:131;35723:4;35597:131;:::i;:::-;35589:139;;35316:419;;;:::o;35741:175::-;35881:27;35877:1;35869:6;35865:14;35858:51;35741:175;:::o;35922:366::-;36064:3;36085:67;36149:2;36144:3;36085:67;:::i;:::-;36078:74;;36161:93;36250:3;36161:93;:::i;:::-;36279:2;36274:3;36270:12;36263:19;;35922:366;;;:::o;36294:419::-;36460:4;36498:2;36487:9;36483:18;36475:26;;36547:9;36541:4;36537:20;36533:1;36522:9;36518:17;36511:47;36575:131;36701:4;36575:131;:::i;:::-;36567:139;;36294:419;;;:::o;36719:234::-;36859:34;36855:1;36847:6;36843:14;36836:58;36928:17;36923:2;36915:6;36911:15;36904:42;36719:234;:::o;36959:366::-;37101:3;37122:67;37186:2;37181:3;37122:67;:::i;:::-;37115:74;;37198:93;37287:3;37198:93;:::i;:::-;37316:2;37311:3;37307:12;37300:19;;36959:366;;;:::o;37331:419::-;37497:4;37535:2;37524:9;37520:18;37512:26;;37584:9;37578:4;37574:20;37570:1;37559:9;37555:17;37548:47;37612:131;37738:4;37612:131;:::i;:::-;37604:139;;37331:419;;;:::o;37756:308::-;37818:4;37908:18;37900:6;37897:30;37894:56;;;37930:18;;:::i;:::-;37894:56;37968:29;37990:6;37968:29;:::i;:::-;37960:37;;38052:4;38046;38042:15;38034:23;;37756:308;;;:::o;38070:421::-;38159:5;38184:66;38200:49;38242:6;38200:49;:::i;:::-;38184:66;:::i;:::-;38175:75;;38273:6;38266:5;38259:21;38311:4;38304:5;38300:16;38349:3;38340:6;38335:3;38331:16;38328:25;38325:112;;;38356:79;;:::i;:::-;38325:112;38446:39;38478:6;38473:3;38468;38446:39;:::i;:::-;38165:326;38070:421;;;;;:::o;38511:355::-;38578:5;38627:3;38620:4;38612:6;38608:17;38604:27;38594:122;;38635:79;;:::i;:::-;38594:122;38745:6;38739:13;38770:90;38856:3;38848:6;38841:4;38833:6;38829:17;38770:90;:::i;:::-;38761:99;;38584:282;38511:355;;;;:::o;38872:524::-;38952:6;39001:2;38989:9;38980:7;38976:23;38972:32;38969:119;;;39007:79;;:::i;:::-;38969:119;39148:1;39137:9;39133:17;39127:24;39178:18;39170:6;39167:30;39164:117;;;39200:79;;:::i;:::-;39164:117;39305:74;39371:7;39362:6;39351:9;39347:22;39305:74;:::i;:::-;39295:84;;39098:291;38872:524;;;;:::o;39402:163::-;39542:15;39538:1;39530:6;39526:14;39519:39;39402:163;:::o;39571:366::-;39713:3;39734:67;39798:2;39793:3;39734:67;:::i;:::-;39727:74;;39810:93;39899:3;39810:93;:::i;:::-;39928:2;39923:3;39919:12;39912:19;;39571:366;;;:::o;39943:419::-;40109:4;40147:2;40136:9;40132:18;40124:26;;40196:9;40190:4;40186:20;40182:1;40171:9;40167:17;40160:47;40224:131;40350:4;40224:131;:::i;:::-;40216:139;;39943:419;;;:::o;40368:233::-;40407:3;40430:24;40448:5;40430:24;:::i;:::-;40421:33;;40476:66;40469:5;40466:77;40463:103;;;40546:18;;:::i;:::-;40463:103;40593:1;40586:5;40582:13;40575:20;;40368:233;;;:::o;40607:332::-;40728:4;40766:2;40755:9;40751:18;40743:26;;40779:71;40847:1;40836:9;40832:17;40823:6;40779:71;:::i;:::-;40860:72;40928:2;40917:9;40913:18;40904:6;40860:72;:::i;:::-;40607:332;;;;;:::o;40945:109::-;41014:7;41043:5;41032:16;;40945:109;;;:::o;41060:206::-;41142:9;41175:85;41193:66;41202:56;41252:5;41202:56;:::i;:::-;41193:66;:::i;:::-;41175:85;:::i;:::-;41162:98;;41060:206;;;:::o;41272:195::-;41391:69;41454:5;41391:69;:::i;:::-;41386:3;41379:82;41272:195;;:::o;41473:396::-;41626:4;41664:2;41653:9;41649:18;41641:26;;41677:71;41745:1;41734:9;41730:17;41721:6;41677:71;:::i;:::-;41758:104;41858:2;41847:9;41843:18;41834:6;41758:104;:::i;:::-;41473:396;;;;;:::o;41875:169::-;42015:21;42011:1;42003:6;41999:14;41992:45;41875:169;:::o;42050:366::-;42192:3;42213:67;42277:2;42272:3;42213:67;:::i;:::-;42206:74;;42289:93;42378:3;42289:93;:::i;:::-;42407:2;42402:3;42398:12;42391:19;;42050:366;;;:::o;42422:419::-;42588:4;42626:2;42615:9;42611:18;42603:26;;42675:9;42669:4;42665:20;42661:1;42650:9;42646:17;42639:47;42703:131;42829:4;42703:131;:::i;:::-;42695:139;;42422:419;;;:::o;42847:442::-;42996:4;43034:2;43023:9;43019:18;43011:26;;43047:71;43115:1;43104:9;43100:17;43091:6;43047:71;:::i;:::-;43128:72;43196:2;43185:9;43181:18;43172:6;43128:72;:::i;:::-;43210;43278:2;43267:9;43263:18;43254:6;43210:72;:::i;:::-;42847:442;;;;;;:::o;43295:168::-;43435:20;43431:1;43423:6;43419:14;43412:44;43295:168;:::o;43469:366::-;43611:3;43632:67;43696:2;43691:3;43632:67;:::i;:::-;43625:74;;43708:93;43797:3;43708:93;:::i;:::-;43826:2;43821:3;43817:12;43810:19;;43469:366;;;:::o;43841:419::-;44007:4;44045:2;44034:9;44030:18;44022:26;;44094:9;44088:4;44084:20;44080:1;44069:9;44065:17;44058:47;44122:131;44248:4;44122:131;:::i;:::-;44114:139;;43841:419;;;:::o;44266:225::-;44406:34;44402:1;44394:6;44390:14;44383:58;44475:8;44470:2;44462:6;44458:15;44451:33;44266:225;:::o;44497:366::-;44639:3;44660:67;44724:2;44719:3;44660:67;:::i;:::-;44653:74;;44736:93;44825:3;44736:93;:::i;:::-;44854:2;44849:3;44845:12;44838:19;;44497:366;;;:::o;44869:419::-;45035:4;45073:2;45062:9;45058:18;45050:26;;45122:9;45116:4;45112:20;45108:1;45097:9;45093:17;45086:47;45150:131;45276:4;45150:131;:::i;:::-;45142:139;;44869:419;;;:::o;45294:171::-;45332:3;45355:23;45372:5;45355:23;:::i;:::-;45346:32;;45400:6;45393:5;45390:17;45387:43;;;45410:18;;:::i;:::-;45387:43;45457:1;45450:5;45446:13;45439:20;;45294:171;;;:::o;45471:113::-;45537:6;45571:5;45565:12;45555:22;;45471:113;;;:::o;45590:183::-;45688:11;45722:6;45717:3;45710:19;45762:4;45757:3;45753:14;45738:29;;45590:183;;;;:::o;45779:131::-;45845:4;45868:3;45860:11;;45898:4;45893:3;45889:14;45881:22;;45779:131;;;:::o;45916:105::-;45991:23;46008:5;45991:23;:::i;:::-;45986:3;45979:36;45916:105;;:::o;46027:175::-;46094:10;46115:44;46155:3;46147:6;46115:44;:::i;:::-;46191:4;46186:3;46182:14;46168:28;;46027:175;;;;:::o;46208:112::-;46277:4;46309;46304:3;46300:14;46292:22;;46208:112;;;:::o;46354:724::-;46471:3;46500:53;46547:5;46500:53;:::i;:::-;46569:85;46647:6;46642:3;46569:85;:::i;:::-;46562:92;;46678:55;46727:5;46678:55;:::i;:::-;46756:7;46787:1;46772:281;46797:6;46794:1;46791:13;46772:281;;;46873:6;46867:13;46900:61;46957:3;46942:13;46900:61;:::i;:::-;46893:68;;46984:59;47036:6;46984:59;:::i;:::-;46974:69;;46832:221;46819:1;46816;46812:9;46807:14;;46772:281;;;46776:14;47069:3;47062:10;;46476:602;;;46354:724;;;;:::o;47084:479::-;47253:4;47291:2;47280:9;47276:18;47268:26;;47304:71;47372:1;47361:9;47357:17;47348:6;47304:71;:::i;:::-;47422:9;47416:4;47412:20;47407:2;47396:9;47392:18;47385:48;47450:106;47551:4;47542:6;47450:106;:::i;:::-;47442:114;;47084:479;;;;;:::o;47569:170::-;47709:22;47705:1;47697:6;47693:14;47686:46;47569:170;:::o;47745:366::-;47887:3;47908:67;47972:2;47967:3;47908:67;:::i;:::-;47901:74;;47984:93;48073:3;47984:93;:::i;:::-;48102:2;48097:3;48093:12;48086:19;;47745:366;;;:::o;48117:419::-;48283:4;48321:2;48310:9;48306:18;48298:26;;48370:9;48364:4;48360:20;48356:1;48345:9;48341:17;48334:47;48398:131;48524:4;48398:131;:::i;:::-;48390:139;;48117:419;;;:::o;48542:231::-;48682:34;48678:1;48670:6;48666:14;48659:58;48751:14;48746:2;48738:6;48734:15;48727:39;48542:231;:::o;48779:366::-;48921:3;48942:67;49006:2;49001:3;48942:67;:::i;:::-;48935:74;;49018:93;49107:3;49018:93;:::i;:::-;49136:2;49131:3;49127:12;49120:19;;48779:366;;;:::o;49151:419::-;49317:4;49355:2;49344:9;49340:18;49332:26;;49404:9;49398:4;49394:20;49390:1;49379:9;49375:17;49368:47;49432:131;49558:4;49432:131;:::i;:::-;49424:139;;49151:419;;;:::o;49576:228::-;49716:34;49712:1;49704:6;49700:14;49693:58;49785:11;49780:2;49772:6;49768:15;49761:36;49576:228;:::o;49810:366::-;49952:3;49973:67;50037:2;50032:3;49973:67;:::i;:::-;49966:74;;50049:93;50138:3;50049:93;:::i;:::-;50167:2;50162:3;50158:12;50151:19;;49810:366;;;:::o;50182:419::-;50348:4;50386:2;50375:9;50371:18;50363:26;;50435:9;50429:4;50425:20;50421:1;50410:9;50406:17;50399:47;50463:131;50589:4;50463:131;:::i;:::-;50455:139;;50182:419;;;:::o;50607:223::-;50747:34;50743:1;50735:6;50731:14;50724:58;50816:6;50811:2;50803:6;50799:15;50792:31;50607:223;:::o;50836:366::-;50978:3;50999:67;51063:2;51058:3;50999:67;:::i;:::-;50992:74;;51075:93;51164:3;51075:93;:::i;:::-;51193:2;51188:3;51184:12;51177:19;;50836:366;;;:::o;51208:419::-;51374:4;51412:2;51401:9;51397:18;51389:26;;51461:9;51455:4;51451:20;51447:1;51436:9;51432:17;51425:47;51489:131;51615:4;51489:131;:::i;:::-;51481:139;;51208:419;;;:::o;51633:191::-;51673:4;51693:20;51711:1;51693:20;:::i;:::-;51688:25;;51727:20;51745:1;51727:20;:::i;:::-;51722:25;;51766:1;51763;51760:8;51757:34;;;51771:18;;:::i;:::-;51757:34;51816:1;51813;51809:9;51801:17;;51633:191;;;;:::o;51830:237::-;51970:34;51966:1;51958:6;51954:14;51947:58;52039:20;52034:2;52026:6;52022:15;52015:45;51830:237;:::o;52073:366::-;52215:3;52236:67;52300:2;52295:3;52236:67;:::i;:::-;52229:74;;52312:93;52401:3;52312:93;:::i;:::-;52430:2;52425:3;52421:12;52414:19;;52073:366;;;:::o;52445:419::-;52611:4;52649:2;52638:9;52634:18;52626:26;;52698:9;52692:4;52688:20;52684:1;52673:9;52669:17;52662:47;52726:131;52852:4;52726:131;:::i;:::-;52718:139;;52445:419;;;:::o;52870:94::-;52903:8;52951:5;52947:2;52943:14;52922:35;;52870:94;;;:::o;52970:::-;53009:7;53038:20;53052:5;53038:20;:::i;:::-;53027:31;;52970:94;;;:::o;53070:100::-;53109:7;53138:26;53158:5;53138:26;:::i;:::-;53127:37;;53070:100;;;:::o;53176:157::-;53281:45;53301:24;53319:5;53301:24;:::i;:::-;53281:45;:::i;:::-;53276:3;53269:58;53176:157;;:::o;53339:77::-;53376:7;53405:5;53394:16;;53339:77;;;:::o;53422:79::-;53461:7;53490:5;53479:16;;53422:79;;;:::o;53507:157::-;53612:45;53632:24;53650:5;53632:24;:::i;:::-;53612:45;:::i;:::-;53607:3;53600:58;53507:157;;:::o;53670:79::-;53709:7;53738:5;53727:16;;53670:79;;;:::o;53755:157::-;53860:45;53880:24;53898:5;53880:24;:::i;:::-;53860:45;:::i;:::-;53855:3;53848:58;53755:157;;:::o;53918:679::-;54114:3;54129:75;54200:3;54191:6;54129:75;:::i;:::-;54229:2;54224:3;54220:12;54213:19;;54242:75;54313:3;54304:6;54242:75;:::i;:::-;54342:2;54337:3;54333:12;54326:19;;54355:75;54426:3;54417:6;54355:75;:::i;:::-;54455:2;54450:3;54446:12;54439:19;;54468:75;54539:3;54530:6;54468:75;:::i;:::-;54568:2;54563:3;54559:12;54552:19;;54588:3;54581:10;;53918:679;;;;;;;:::o;54603:176::-;54635:1;54652:20;54670:1;54652:20;:::i;:::-;54647:25;;54686:20;54704:1;54686:20;:::i;:::-;54681:25;;54725:1;54715:35;;54730:18;;:::i;:::-;54715:35;54771:1;54768;54764:9;54759:14;;54603:176;;;;:::o;54785:143::-;54842:5;54873:6;54867:13;54858:22;;54889:33;54916:5;54889:33;:::i;:::-;54785:143;;;;:::o;54934:351::-;55004:6;55053:2;55041:9;55032:7;55028:23;55024:32;55021:119;;;55059:79;;:::i;:::-;55021:119;55179:1;55204:64;55260:7;55251:6;55240:9;55236:22;55204:64;:::i;:::-;55194:74;;55150:128;54934:351;;;;:::o;55291:98::-;55342:6;55376:5;55370:12;55360:22;;55291:98;;;:::o;55395:168::-;55478:11;55512:6;55507:3;55500:19;55552:4;55547:3;55543:14;55528:29;;55395:168;;;;:::o;55569:360::-;55655:3;55683:38;55715:5;55683:38;:::i;:::-;55737:70;55800:6;55795:3;55737:70;:::i;:::-;55730:77;;55816:52;55861:6;55856:3;55849:4;55842:5;55838:16;55816:52;:::i;:::-;55893:29;55915:6;55893:29;:::i;:::-;55888:3;55884:39;55877:46;;55659:270;55569:360;;;;:::o;55935:640::-;56130:4;56168:3;56157:9;56153:19;56145:27;;56182:71;56250:1;56239:9;56235:17;56226:6;56182:71;:::i;:::-;56263:72;56331:2;56320:9;56316:18;56307:6;56263:72;:::i;:::-;56345;56413:2;56402:9;56398:18;56389:6;56345:72;:::i;:::-;56464:9;56458:4;56454:20;56449:2;56438:9;56434:18;56427:48;56492:76;56563:4;56554:6;56492:76;:::i;:::-;56484:84;;55935:640;;;;;;;:::o;56581:141::-;56637:5;56668:6;56662:13;56653:22;;56684:32;56710:5;56684:32;:::i;:::-;56581:141;;;;:::o;56728:349::-;56797:6;56846:2;56834:9;56825:7;56821:23;56817:32;56814:119;;;56852:79;;:::i;:::-;56814:119;56972:1;56997:63;57052:7;57043:6;57032:9;57028:22;56997:63;:::i;:::-;56987:73;;56943:127;56728:349;;;;:::o;57083:237::-;57121:3;57140:18;57156:1;57140:18;:::i;:::-;57135:23;;57172:18;57188:1;57172:18;:::i;:::-;57167:23;;57262:1;57256:4;57252:12;57249:1;57246:19;57243:45;;;57268:18;;:::i;:::-;57243:45;57312:1;57309;57305:9;57298:16;;57083:237;;;;:::o;57326:96::-;57360:8;57409:5;57404:3;57400:15;57379:36;;57326:96;;;:::o;57428:93::-;57465:7;57494:21;57509:5;57494:21;:::i;:::-;57483:32;;57428:93;;;:::o;57527:95::-;57563:7;57592:24;57610:5;57592:24;:::i;:::-;57581:35;;57527:95;;;:::o;57628:145::-;57727:39;57744:21;57759:5;57744:21;:::i;:::-;57727:39;:::i;:::-;57722:3;57715:52;57628:145;;:::o;57779:149::-;57880:41;57898:22;57914:5;57898:22;:::i;:::-;57880:41;:::i;:::-;57875:3;57868:54;57779:149;;:::o;57934:1299::-;58232:3;58247:69;58312:3;58303:6;58247:69;:::i;:::-;58341:1;58336:3;58332:11;58325:18;;58353:71;58420:3;58411:6;58353:71;:::i;:::-;58449:1;58444:3;58440:11;58433:18;;58461:71;58528:3;58519:6;58461:71;:::i;:::-;58557:1;58552:3;58548:11;58541:18;;58569:71;58636:3;58627:6;58569:71;:::i;:::-;58665:1;58660:3;58656:11;58649:18;;58677:71;58744:3;58735:6;58677:71;:::i;:::-;58773:1;58768:3;58764:11;58757:18;;58785:71;58852:3;58843:6;58785:71;:::i;:::-;58881:1;58876:3;58872:11;58865:18;;58893:71;58960:3;58951:6;58893:71;:::i;:::-;58989:1;58984:3;58980:11;58973:18;;59001:71;59068:3;59059:6;59001:71;:::i;:::-;59097:1;59092:3;59088:11;59081:18;;59109:71;59176:3;59167:6;59109:71;:::i;:::-;59205:1;59200:3;59196:11;59189:18;;59224:3;59217:10;;57934:1299;;;;;;;;;;;;:::o;59239:180::-;59287:77;59284:1;59277:88;59384:4;59381:1;59374:15;59408:4;59405:1;59398:15;59425:170;59455:1;59472:18;59488:1;59472:18;:::i;:::-;59467:23;;59504:18;59520:1;59504:18;:::i;:::-;59499:23;;59541:1;59531:35;;59546:18;;:::i;:::-;59531:35;59587:1;59584;59580:9;59575:14;;59425:170;;;;:::o;59601:182::-;59741:34;59737:1;59729:6;59725:14;59718:58;59601:182;:::o;59789:366::-;59931:3;59952:67;60016:2;60011:3;59952:67;:::i;:::-;59945:74;;60028:93;60117:3;60028:93;:::i;:::-;60146:2;60141:3;60137:12;60130:19;;59789:366;;;:::o;60161:419::-;60327:4;60365:2;60354:9;60350:18;60342:26;;60414:9;60408:4;60404:20;60400:1;60389:9;60385:17;60378:47;60442:131;60568:4;60442:131;:::i;:::-;60434:139;;60161:419;;;:::o;60586:178::-;60726:30;60722:1;60714:6;60710:14;60703:54;60586:178;:::o;60770:366::-;60912:3;60933:67;60997:2;60992:3;60933:67;:::i;:::-;60926:74;;61009:93;61098:3;61009:93;:::i;:::-;61127:2;61122:3;61118:12;61111:19;;60770:366;;;:::o;61142:419::-;61308:4;61346:2;61335:9;61331:18;61323:26;;61395:9;61389:4;61385:20;61381:1;61370:9;61366:17;61359:47;61423:131;61549:4;61423:131;:::i;:::-;61415:139;;61142:419;;;:::o
Swarm Source
ipfs://ea37b8bb35257cd60ddb9c0481dfc6968f58f36ee347af832c5b2b87ff11c7c0
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.