Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Sponsored
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
StableSwapStateOracle
Compiler Version
v0.6.12+commit.27d51765
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2021-04-26 */ pragma solidity 0.6.12; // SPDX-License-Identifier: MIT AND Apache-2.0 // License: MIT /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Copied from: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/solc-0.6/contracts/math/SafeMath.sol */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) return 0; uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } } // License: Apache-2.0 /* * @author Hamdi Allam [email protected] * Please reach out with any questions or concerns */ library RLPReader { uint8 constant STRING_SHORT_START = 0x80; uint8 constant STRING_LONG_START = 0xb8; uint8 constant LIST_SHORT_START = 0xc0; uint8 constant LIST_LONG_START = 0xf8; uint8 constant WORD_SIZE = 32; struct RLPItem { uint len; uint memPtr; } struct Iterator { RLPItem item; // Item that's being iterated over. uint nextPtr; // Position of the next item in the list. } /* * @dev Returns the next element in the iteration. Reverts if it has not next element. * @param self The iterator. * @return The next element in the iteration. */ function next(Iterator memory self) internal pure returns (RLPItem memory) { require(hasNext(self)); uint ptr = self.nextPtr; uint itemLength = _itemLength(ptr); self.nextPtr = ptr + itemLength; return RLPItem(itemLength, ptr); } /* * @dev Returns true if the iteration has more elements. * @param self The iterator. * @return true if the iteration has more elements. */ function hasNext(Iterator memory self) internal pure returns (bool) { RLPItem memory item = self.item; return self.nextPtr < item.memPtr + item.len; } /* * @param item RLP encoded bytes */ function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) { uint memPtr; assembly { memPtr := add(item, 0x20) } return RLPItem(item.length, memPtr); } /* * @dev Create an iterator. Reverts if item is not a list. * @param self The RLP item. * @return An 'Iterator' over the item. */ function iterator(RLPItem memory self) internal pure returns (Iterator memory) { require(isList(self)); uint ptr = self.memPtr + _payloadOffset(self.memPtr); return Iterator(self, ptr); } /* * @param the RLP item. */ function rlpLen(RLPItem memory item) internal pure returns (uint) { return item.len; } /* * @param the RLP item. * @return (memPtr, len) pair: location of the item's payload in memory. */ function payloadLocation(RLPItem memory item) internal pure returns (uint, uint) { uint offset = _payloadOffset(item.memPtr); uint memPtr = item.memPtr + offset; uint len = item.len - offset; // data length return (memPtr, len); } /* * @param the RLP item. */ function payloadLen(RLPItem memory item) internal pure returns (uint) { (, uint len) = payloadLocation(item); return len; } /* * @param the RLP item containing the encoded list. */ function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) { require(isList(item)); uint items = numItems(item); RLPItem[] memory result = new RLPItem[](items); uint memPtr = item.memPtr + _payloadOffset(item.memPtr); uint dataLen; for (uint i = 0; i < items; i++) { dataLen = _itemLength(memPtr); result[i] = RLPItem(dataLen, memPtr); memPtr = memPtr + dataLen; } return result; } // @return indicator whether encoded payload is a list. negate this function call for isData. function isList(RLPItem memory item) internal pure returns (bool) { if (item.len == 0) return false; uint8 byte0; uint memPtr = item.memPtr; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < LIST_SHORT_START) return false; return true; } /* * @dev A cheaper version of keccak256(toRlpBytes(item)) that avoids copying memory. * @return keccak256 hash of RLP encoded bytes. */ function rlpBytesKeccak256(RLPItem memory item) internal pure returns (bytes32) { uint256 ptr = item.memPtr; uint256 len = item.len; bytes32 result; assembly { result := keccak256(ptr, len) } return result; } /* * @dev A cheaper version of keccak256(toBytes(item)) that avoids copying memory. * @return keccak256 hash of the item payload. */ function payloadKeccak256(RLPItem memory item) internal pure returns (bytes32) { (uint memPtr, uint len) = payloadLocation(item); bytes32 result; assembly { result := keccak256(memPtr, len) } return result; } /** RLPItem conversions into data types **/ // @returns raw rlp encoding in bytes function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) { bytes memory result = new bytes(item.len); if (result.length == 0) return result; uint ptr; assembly { ptr := add(0x20, result) } copy(item.memPtr, ptr, item.len); return result; } // any non-zero byte except "0x80" is considered true function toBoolean(RLPItem memory item) internal pure returns (bool) { require(item.len == 1); uint result; uint memPtr = item.memPtr; assembly { result := byte(0, mload(memPtr)) } // SEE Github Issue #5. // Summary: Most commonly used RLP libraries (i.e Geth) will encode // "0" as "0x80" instead of as "0". We handle this edge case explicitly // here. if (result == 0 || result == STRING_SHORT_START) { return false; } else { return true; } } function toAddress(RLPItem memory item) internal pure returns (address) { // 1 byte for the length prefix require(item.len == 21); return address(toUint(item)); } function toUint(RLPItem memory item) internal pure returns (uint) { require(item.len > 0 && item.len <= 33); (uint memPtr, uint len) = payloadLocation(item); uint result; assembly { result := mload(memPtr) // shfit to the correct location if neccesary if lt(len, 32) { result := div(result, exp(256, sub(32, len))) } } return result; } // enforces 32 byte length function toUintStrict(RLPItem memory item) internal pure returns (uint) { // one byte prefix require(item.len == 33); uint result; uint memPtr = item.memPtr + 1; assembly { result := mload(memPtr) } return result; } function toBytes(RLPItem memory item) internal pure returns (bytes memory) { require(item.len > 0); (uint memPtr, uint len) = payloadLocation(item); bytes memory result = new bytes(len); uint destPtr; assembly { destPtr := add(0x20, result) } copy(memPtr, destPtr, len); return result; } /* * Private Helpers */ // @return number of payload items inside an encoded list. function numItems(RLPItem memory item) private pure returns (uint) { if (item.len == 0) return 0; uint count = 0; uint currPtr = item.memPtr + _payloadOffset(item.memPtr); uint endPtr = item.memPtr + item.len; while (currPtr < endPtr) { currPtr = currPtr + _itemLength(currPtr); // skip over an item count++; } return count; } // @return entire rlp item byte length function _itemLength(uint memPtr) private pure returns (uint) { uint itemLen; uint byte0; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < STRING_SHORT_START) itemLen = 1; else if (byte0 < STRING_LONG_START) itemLen = byte0 - STRING_SHORT_START + 1; else if (byte0 < LIST_SHORT_START) { assembly { let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is memPtr := add(memPtr, 1) // skip over the first byte /* 32 byte word size */ let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len itemLen := add(dataLen, add(byteLen, 1)) } } else if (byte0 < LIST_LONG_START) { itemLen = byte0 - LIST_SHORT_START + 1; } else { assembly { let byteLen := sub(byte0, 0xf7) memPtr := add(memPtr, 1) let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length itemLen := add(dataLen, add(byteLen, 1)) } } return itemLen; } // @return number of bytes until the data function _payloadOffset(uint memPtr) private pure returns (uint) { uint byte0; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < STRING_SHORT_START) return 0; else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) return 1; else if (byte0 < LIST_SHORT_START) // being explicit return byte0 - (STRING_LONG_START - 1) + 1; else return byte0 - (LIST_LONG_START - 1) + 1; } /* * @param src Pointer to source * @param dest Pointer to destination * @param len Amount of memory to copy from the source */ function copy(uint src, uint dest, uint len) private pure { if (len == 0) return; // copy as many word sizes as possible for (; len >= WORD_SIZE; len -= WORD_SIZE) { assembly { mstore(dest, mload(src)) } src += WORD_SIZE; dest += WORD_SIZE; } // left over bytes. Mask is used to remove unwanted bytes from the word uint mask = 256 ** (WORD_SIZE - len) - 1; assembly { let srcpart := and(mload(src), not(mask)) // zero out src let destpart := and(mload(dest), mask) // retrieve the bytes mstore(dest, or(destpart, srcpart)) } } } // License: MIT /** * Copied from https://github.com/lorenzb/proveth/blob/c74b20e/onchain/ProvethVerifier.sol * with minor performance and code style-related modifications. */ library MerklePatriciaProofVerifier { using RLPReader for RLPReader.RLPItem; using RLPReader for bytes; /// @dev Validates a Merkle-Patricia-Trie proof. /// If the proof proves the inclusion of some key-value pair in the /// trie, the value is returned. Otherwise, i.e. if the proof proves /// the exclusion of a key from the trie, an empty byte array is /// returned. /// @param rootHash is the Keccak-256 hash of the root node of the MPT. /// @param path is the key of the node whose inclusion/exclusion we are /// proving. /// @param stack is the stack of MPT nodes (starting with the root) that /// need to be traversed during verification. /// @return value whose inclusion is proved or an empty byte array for /// a proof of exclusion function extractProofValue( bytes32 rootHash, bytes memory path, RLPReader.RLPItem[] memory stack ) internal pure returns (bytes memory value) { bytes memory mptKey = _decodeNibbles(path, 0); uint256 mptKeyOffset = 0; bytes32 nodeHashHash; bytes memory rlpNode; RLPReader.RLPItem[] memory node; RLPReader.RLPItem memory rlpValue; if (stack.length == 0) { // Root hash of empty Merkle-Patricia-Trie require(rootHash == 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421); return new bytes(0); } // Traverse stack of nodes starting at root. for (uint256 i = 0; i < stack.length; i++) { // We use the fact that an rlp encoded list consists of some // encoding of its length plus the concatenation of its // *rlp-encoded* items. // The root node is hashed with Keccak-256 ... if (i == 0 && rootHash != stack[i].rlpBytesKeccak256()) { revert(); } // ... whereas all other nodes are hashed with the MPT // hash function. if (i != 0 && nodeHashHash != _mptHashHash(stack[i])) { revert(); } // We verified that stack[i] has the correct hash, so we // may safely decode it. node = stack[i].toList(); if (node.length == 2) { // Extension or Leaf node bool isLeaf; bytes memory nodeKey; (isLeaf, nodeKey) = _merklePatriciaCompactDecode(node[0].toBytes()); uint256 prefixLength = _sharedPrefixLength(mptKeyOffset, mptKey, nodeKey); mptKeyOffset += prefixLength; if (prefixLength < nodeKey.length) { // Proof claims divergent extension or leaf. (Only // relevant for proofs of exclusion.) // An Extension/Leaf node is divergent iff it "skips" over // the point at which a Branch node should have been had the // excluded key been included in the trie. // Example: Imagine a proof of exclusion for path [1, 4], // where the current node is a Leaf node with // path [1, 3, 3, 7]. For [1, 4] to be included, there // should have been a Branch node at [1] with a child // at 3 and a child at 4. // Sanity check if (i < stack.length - 1) { // divergent node must come last in proof revert(); } return new bytes(0); } if (isLeaf) { // Sanity check if (i < stack.length - 1) { // leaf node must come last in proof revert(); } if (mptKeyOffset < mptKey.length) { return new bytes(0); } rlpValue = node[1]; return rlpValue.toBytes(); } else { // extension // Sanity check if (i == stack.length - 1) { // shouldn't be at last level revert(); } if (!node[1].isList()) { // rlp(child) was at least 32 bytes. node[1] contains // Keccak256(rlp(child)). nodeHashHash = node[1].payloadKeccak256(); } else { // rlp(child) was less than 32 bytes. node[1] contains // rlp(child). nodeHashHash = node[1].rlpBytesKeccak256(); } } } else if (node.length == 17) { // Branch node if (mptKeyOffset != mptKey.length) { // we haven't consumed the entire path, so we need to look at a child uint8 nibble = uint8(mptKey[mptKeyOffset]); mptKeyOffset += 1; if (nibble >= 16) { // each element of the path has to be a nibble revert(); } if (_isEmptyBytesequence(node[nibble])) { // Sanity if (i != stack.length - 1) { // leaf node should be at last level revert(); } return new bytes(0); } else if (!node[nibble].isList()) { nodeHashHash = node[nibble].payloadKeccak256(); } else { nodeHashHash = node[nibble].rlpBytesKeccak256(); } } else { // we have consumed the entire mptKey, so we need to look at what's contained in this node. // Sanity if (i != stack.length - 1) { // should be at last level revert(); } return node[16].toBytes(); } } } } /// @dev Computes the hash of the Merkle-Patricia-Trie hash of the RLP item. /// Merkle-Patricia-Tries use a weird "hash function" that outputs /// *variable-length* hashes: If the item is shorter than 32 bytes, /// the MPT hash is the item. Otherwise, the MPT hash is the /// Keccak-256 hash of the item. /// The easiest way to compare variable-length byte sequences is /// to compare their Keccak-256 hashes. /// @param item The RLP item to be hashed. /// @return Keccak-256(MPT-hash(item)) function _mptHashHash(RLPReader.RLPItem memory item) private pure returns (bytes32) { if (item.len < 32) { return item.rlpBytesKeccak256(); } else { return keccak256(abi.encodePacked(item.rlpBytesKeccak256())); } } function _isEmptyBytesequence(RLPReader.RLPItem memory item) private pure returns (bool) { if (item.len != 1) { return false; } uint8 b; uint256 memPtr = item.memPtr; assembly { b := byte(0, mload(memPtr)) } return b == 0x80 /* empty byte string */; } function _merklePatriciaCompactDecode(bytes memory compact) private pure returns (bool isLeaf, bytes memory nibbles) { require(compact.length > 0); uint256 first_nibble = uint8(compact[0]) >> 4 & 0xF; uint256 skipNibbles; if (first_nibble == 0) { skipNibbles = 2; isLeaf = false; } else if (first_nibble == 1) { skipNibbles = 1; isLeaf = false; } else if (first_nibble == 2) { skipNibbles = 2; isLeaf = true; } else if (first_nibble == 3) { skipNibbles = 1; isLeaf = true; } else { // Not supposed to happen! revert(); } return (isLeaf, _decodeNibbles(compact, skipNibbles)); } function _decodeNibbles(bytes memory compact, uint256 skipNibbles) private pure returns (bytes memory nibbles) { require(compact.length > 0); uint256 length = compact.length * 2; require(skipNibbles <= length); length -= skipNibbles; nibbles = new bytes(length); uint256 nibblesLength = 0; for (uint256 i = skipNibbles; i < skipNibbles + length; i += 1) { if (i % 2 == 0) { nibbles[nibblesLength] = bytes1((uint8(compact[i/2]) >> 4) & 0xF); } else { nibbles[nibblesLength] = bytes1((uint8(compact[i/2]) >> 0) & 0xF); } nibblesLength += 1; } assert(nibblesLength == nibbles.length); } function _sharedPrefixLength(uint256 xsOffset, bytes memory xs, bytes memory ys) private pure returns (uint256) { uint256 i; for (i = 0; i + xsOffset < xs.length && i < ys.length; i++) { if (xs[i + xsOffset] != ys[i]) { return i; } } return i; } } // License: MIT /** * @title A helper library for verification of Merkle Patricia account and state proofs. */ library Verifier { using RLPReader for RLPReader.RLPItem; using RLPReader for bytes; uint256 constant HEADER_STATE_ROOT_INDEX = 3; uint256 constant HEADER_NUMBER_INDEX = 8; uint256 constant HEADER_TIMESTAMP_INDEX = 11; struct BlockHeader { bytes32 hash; bytes32 stateRootHash; uint256 number; uint256 timestamp; } struct Account { bool exists; uint256 nonce; uint256 balance; bytes32 storageRoot; bytes32 codeHash; } struct SlotValue { bool exists; uint256 value; } /** * @notice Parses block header and verifies its presence onchain within the latest 256 blocks. * @param _headerRlpBytes RLP-encoded block header. */ function verifyBlockHeader(bytes memory _headerRlpBytes) internal view returns (BlockHeader memory) { BlockHeader memory header = parseBlockHeader(_headerRlpBytes); // ensure that the block is actually in the blockchain require(header.hash == blockhash(header.number), "blockhash mismatch"); return header; } /** * @notice Parses RLP-encoded block header. * @param _headerRlpBytes RLP-encoded block header. */ function parseBlockHeader(bytes memory _headerRlpBytes) internal pure returns (BlockHeader memory) { BlockHeader memory result; RLPReader.RLPItem[] memory headerFields = _headerRlpBytes.toRlpItem().toList(); result.stateRootHash = bytes32(headerFields[HEADER_STATE_ROOT_INDEX].toUint()); result.number = headerFields[HEADER_NUMBER_INDEX].toUint(); result.timestamp = headerFields[HEADER_TIMESTAMP_INDEX].toUint(); result.hash = keccak256(_headerRlpBytes); return result; } /** * @notice Verifies Merkle Patricia proof of an account and extracts the account fields. * * @param _addressHash Keccak256 hash of the address corresponding to the account. * @param _stateRootHash MPT root hash of the Ethereum state trie. */ function extractAccountFromProof( bytes32 _addressHash, // keccak256(abi.encodePacked(address)) bytes32 _stateRootHash, RLPReader.RLPItem[] memory _proof ) internal pure returns (Account memory) { bytes memory acctRlpBytes = MerklePatriciaProofVerifier.extractProofValue( _stateRootHash, abi.encodePacked(_addressHash), _proof ); Account memory account; if (acctRlpBytes.length == 0) { return account; } RLPReader.RLPItem[] memory acctFields = acctRlpBytes.toRlpItem().toList(); require(acctFields.length == 4); account.exists = true; account.nonce = acctFields[0].toUint(); account.balance = acctFields[1].toUint(); account.storageRoot = bytes32(acctFields[2].toUint()); account.codeHash = bytes32(acctFields[3].toUint()); return account; } /** * @notice Verifies Merkle Patricia proof of a slot and extracts the slot's value. * * @param _slotHash Keccak256 hash of the slot position. * @param _storageRootHash MPT root hash of the account's storage trie. */ function extractSlotValueFromProof( bytes32 _slotHash, bytes32 _storageRootHash, RLPReader.RLPItem[] memory _proof ) internal pure returns (SlotValue memory) { bytes memory valueRlpBytes = MerklePatriciaProofVerifier.extractProofValue( _storageRootHash, abi.encodePacked(_slotHash), _proof ); SlotValue memory value; if (valueRlpBytes.length != 0) { value.exists = true; value.value = valueRlpBytes.toRlpItem().toUint(); } return value; } } // License: MIT interface IPriceHelper { function get_dy( int128 i, int128 j, uint256 dx, uint256[2] memory xp, uint256 A, uint256 fee ) external pure returns (uint256); } interface IStableSwap { function fee() external view returns (uint256); function A_precise() external view returns (uint256); } /** * @title * A trustless oracle for the stETH/ETH Curve pool using Merkle Patricia * proofs of Ethereum state. * * @notice * The oracle currently assumes that the pool's fee and A (amplification * coefficient) values don't change between the time of proof generation * and submission. */ contract StableSwapStateOracle { using RLPReader for bytes; using RLPReader for RLPReader.RLPItem; using SafeMath for uint256; /** * @notice Logs the updated slot values of Curve pool and stETH contracts. */ event SlotValuesUpdated( uint256 timestamp, uint256 poolEthBalance, uint256 poolAdminEthBalance, uint256 poolAdminStethBalance, uint256 stethPoolShares, uint256 stethTotalShares, uint256 stethBeaconBalance, uint256 stethBufferedEther, uint256 stethDepositedValidators, uint256 stethBeaconValidators ); /** * @notice Logs the updated stETH and ETH pool balances and the calculated stETH/ETH price. */ event PriceUpdated( uint256 timestamp, uint256 etherBalance, uint256 stethBalance, uint256 stethPrice ); /** * @notice Logs the updated price update threshold percentage advised to offchain clients. */ event PriceUpdateThresholdChanged(uint256 threshold); /** * @notice * Logs the updated address having the right to change the advised price update threshold. */ event AdminChanged(address admin); /// @dev Reporting data that is more fresh than this number of blocks ago is prohibited uint256 constant public MIN_BLOCK_DELAY = 15; // Constants for offchain proof generation address constant public POOL_ADDRESS = 0xDC24316b9AE028F1497c275EB9192a3Ea0f67022; address constant public STETH_ADDRESS = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; /// @dev keccak256(abi.encodePacked(uint256(1))) bytes32 constant public POOL_ADMIN_BALANCES_0_POS = 0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6; /// @dev bytes32(uint256(POOL_ADMIN_BALANCES_0_POS) + 1) bytes32 constant public POOL_ADMIN_BALANCES_1_POS = 0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf7; /// @dev keccak256(uint256(0xdc24316b9ae028f1497c275eb9192a3ea0f67022) . uint256(0)) bytes32 constant public STETH_POOL_SHARES_POS = 0xae68078d7ee25b2b7bcb7d4b9fe9acf61f251fe08ff637df07889375d8385158; /// @dev keccak256("lido.StETH.totalShares") bytes32 constant public STETH_TOTAL_SHARES_POS = 0xe3b4b636e601189b5f4c6742edf2538ac12bb61ed03e6da26949d69838fa447e; /// @dev keccak256("lido.Lido.beaconBalance") bytes32 constant public STETH_BEACON_BALANCE_POS = 0xa66d35f054e68143c18f32c990ed5cb972bb68a68f500cd2dd3a16bbf3686483; /// @dev keccak256("lido.Lido.bufferedEther") bytes32 constant public STETH_BUFFERED_ETHER_POS = 0xed310af23f61f96daefbcd140b306c0bdbf8c178398299741687b90e794772b0; /// @dev keccak256("lido.Lido.depositedValidators") bytes32 constant public STETH_DEPOSITED_VALIDATORS_POS = 0xe6e35175eb53fc006520a2a9c3e9711a7c00de6ff2c32dd31df8c5a24cac1b5c; /// @dev keccak256("lido.Lido.beaconValidators") bytes32 constant public STETH_BEACON_VALIDATORS_POS = 0x9f70001d82b6ef54e9d3725b46581c3eb9ee3aa02b941b6aa54d678a9ca35b10; // Constants for onchain proof verification /// @dev keccak256(abi.encodePacked(POOL_ADDRESS)) bytes32 constant POOL_ADDRESS_HASH = 0xc70f76036d72b7bb865881e931082ea61bb4f13ec9faeb17f0591b18b6fafbd7; /// @dev keccak256(abi.encodePacked(STETH_ADDRESS)) bytes32 constant STETH_ADDRESS_HASH = 0x6c958a912fe86c83262fbd4973f6bd042cef76551aaf679968f98665979c35e7; /// @dev keccak256(abi.encodePacked(POOL_ADMIN_BALANCES_0_POS)) bytes32 constant POOL_ADMIN_BALANCES_0_HASH = 0xb5d9d894133a730aa651ef62d26b0ffa846233c74177a591a4a896adfda97d22; /// @dev keccak256(abi.encodePacked(POOL_ADMIN_BALANCES_1_POS) bytes32 constant POOL_ADMIN_BALANCES_1_HASH = 0xea7809e925a8989e20c901c4c1da82f0ba29b26797760d445a0ce4cf3c6fbd31; /// @dev keccak256(abi.encodePacked(STETH_POOL_SHARES_POS) bytes32 constant STETH_POOL_SHARES_HASH = 0xe841c8fb2710e169d6b63e1130fb8013d57558ced93619655add7aef8c60d4dc; /// @dev keccak256(abi.encodePacked(STETH_TOTAL_SHARES_POS) bytes32 constant STETH_TOTAL_SHARES_HASH = 0x4068b5716d4c00685289292c9cdc7e059e67159cd101476377efe51ba7ab8e9f; /// @dev keccak256(abi.encodePacked(STETH_BEACON_BALANCE_POS) bytes32 constant STETH_BEACON_BALANCE_HASH = 0xa6965d4729b36ed8b238f6ba55294196843f8be2850c5f63b6fb6d29181b50f8; /// @dev keccak256(abi.encodePacked(STETH_BUFFERED_ETHER_POS) bytes32 constant STETH_BUFFERED_ETHER_HASH = 0xa39079072910ef75f32ddc4f40104882abfc19580cc249c694e12b6de868ee1d; /// @dev keccak256(abi.encodePacked(STETH_DEPOSITED_VALIDATORS_POS) bytes32 constant STETH_DEPOSITED_VALIDATORS_HASH = 0x17216d3ffd8719eeee6d8052f7c1e6269bd92d2390d3e3fc4cde1f026e427fb3; /// @dev keccak256(abi.encodePacked(STETH_BEACON_VALIDATORS_POS) bytes32 constant STETH_BEACON_VALIDATORS_HASH = 0x6fd60d3960d8a32cbc1a708d6bf41bbce8152e61e72b2236d5e1ecede9c4cc72; uint256 constant internal STETH_DEPOSIT_SIZE = 32 ether; /** * @dev A helper contract for calculating stETH/ETH price from its stETH and ETH balances. */ IPriceHelper internal helper; /** * @notice The admin has the right to set the suggested price update threshold (see below). */ address public admin; /** * @notice * The price update threshold percentage advised to oracle clients. * Expressed in basis points: 10000 BP equal to 100%, 100 BP to 1%. * * @dev * If the current price in the pool differs less than this, the clients are advised to * skip updating the oracle. However, this threshold is not enforced, so clients are * free to update the oracle with any valid price. */ uint256 public priceUpdateThreshold; /** * @notice The timestamp of the proven pool state/price. */ uint256 public timestamp; /** * @notice The proven ETH balance of the pool. */ uint256 public etherBalance; /** * @notice The proven stETH balance of the pool. */ uint256 public stethBalance; /** * @notice The proven stETH/ETH price in the pool. */ uint256 public stethPrice; /** * @param _helper Address of the deployed instance of the StableSwapPriceHelper.vy contract. * @param _admin The address that has the right to set the suggested price update threshold. * @param _priceUpdateThreshold The initial value of the suggested price update threshold. * Expressed in basis points, 10000 BP corresponding to 100%. */ constructor(IPriceHelper _helper, address _admin, uint256 _priceUpdateThreshold) public { helper = _helper; _setAdmin(_admin); _setPriceUpdateThreshold(_priceUpdateThreshold); } /** * @notice Passes the right to set the suggested price update threshold to a new address. */ function setAdmin(address _admin) external { require(msg.sender == admin); _setAdmin(_admin); } /** * @notice Sets the suggested price update threshold. * * @param _priceUpdateThreshold The suggested price update threshold. * Expressed in basis points, 10000 BP corresponding to 100%. */ function setPriceUpdateThreshold(uint256 _priceUpdateThreshold) external { require(msg.sender == admin); _setPriceUpdateThreshold(_priceUpdateThreshold); } /** * @notice Retuens a set of values used by the clients for proof generation. */ function getProofParams() external view returns ( address poolAddress, address stethAddress, bytes32 poolAdminEtherBalancePos, bytes32 poolAdminCoinBalancePos, bytes32 stethPoolSharesPos, bytes32 stethTotalSharesPos, bytes32 stethBeaconBalancePos, bytes32 stethBufferedEtherPos, bytes32 stethDepositedValidatorsPos, bytes32 stethBeaconValidatorsPos, uint256 advisedPriceUpdateThreshold ) { return ( POOL_ADDRESS, STETH_ADDRESS, POOL_ADMIN_BALANCES_0_POS, POOL_ADMIN_BALANCES_1_POS, STETH_POOL_SHARES_POS, STETH_TOTAL_SHARES_POS, STETH_BEACON_BALANCE_POS, STETH_BUFFERED_ETHER_POS, STETH_DEPOSITED_VALIDATORS_POS, STETH_BEACON_VALIDATORS_POS, priceUpdateThreshold ); } /** * @return _timestamp The timestamp of the proven pool state/price. * @return _etherBalance The proven ETH balance of the pool. * @return _stethBalance The proven stETH balance of the pool. * @return _stethPrice The proven stETH/ETH price in the pool. */ function getState() external view returns ( uint256 _timestamp, uint256 _etherBalance, uint256 _stethBalance, uint256 _stethPrice ) { return (timestamp, etherBalance, stethBalance, stethPrice); } /** * @notice Used by the offchain clients to submit the proof. * * @dev Reverts unless: * - the block the submitted data corresponds to is in the chain; * - the block is at least `MIN_BLOCK_DELAY` blocks old; * - all submitted proofs are valid. * * @param _blockHeaderRlpBytes RLP-encoded block header. * * @param _proofRlpBytes RLP-encoded list of Merkle Patricia proofs: * 1. proof of the Curve pool contract account; * 2. proof of the stETH contract account; * 3. proof of the `admin_balances[0]` slot of the Curve pool contract; * 4. proof of the `admin_balances[1]` slot of the Curve pool contract; * 5. proof of the `shares[0xDC24316b9AE028F1497c275EB9192a3Ea0f67022]` slot of stETH contract; * 6. proof of the `keccak256("lido.StETH.totalShares")` slot of stETH contract; * 7. proof of the `keccak256("lido.Lido.beaconBalance")` slot of stETH contract; * 8. proof of the `keccak256("lido.Lido.bufferedEther")` slot of stETH contract; * 9. proof of the `keccak256("lido.Lido.depositedValidators")` slot of stETH contract; * 10. proof of the `keccak256("lido.Lido.beaconValidators")` slot of stETH contract. */ function submitState(bytes memory _blockHeaderRlpBytes, bytes memory _proofRlpBytes) external { Verifier.BlockHeader memory blockHeader = Verifier.verifyBlockHeader(_blockHeaderRlpBytes); { uint256 currentBlock = block.number; // ensure block finality require( currentBlock > blockHeader.number && currentBlock - blockHeader.number >= MIN_BLOCK_DELAY, "block too fresh" ); } require(blockHeader.timestamp > timestamp, "stale data"); RLPReader.RLPItem[] memory proofs = _proofRlpBytes.toRlpItem().toList(); require(proofs.length == 10, "total proofs"); Verifier.Account memory accountPool = Verifier.extractAccountFromProof( POOL_ADDRESS_HASH, blockHeader.stateRootHash, proofs[0].toList() ); require(accountPool.exists, "accountPool"); Verifier.Account memory accountSteth = Verifier.extractAccountFromProof( STETH_ADDRESS_HASH, blockHeader.stateRootHash, proofs[1].toList() ); require(accountSteth.exists, "accountSteth"); Verifier.SlotValue memory slotPoolAdminBalances0 = Verifier.extractSlotValueFromProof( POOL_ADMIN_BALANCES_0_HASH, accountPool.storageRoot, proofs[2].toList() ); require(slotPoolAdminBalances0.exists, "adminBalances0"); Verifier.SlotValue memory slotPoolAdminBalances1 = Verifier.extractSlotValueFromProof( POOL_ADMIN_BALANCES_1_HASH, accountPool.storageRoot, proofs[3].toList() ); require(slotPoolAdminBalances1.exists, "adminBalances1"); Verifier.SlotValue memory slotStethPoolShares = Verifier.extractSlotValueFromProof( STETH_POOL_SHARES_HASH, accountSteth.storageRoot, proofs[4].toList() ); require(slotStethPoolShares.exists, "poolShares"); Verifier.SlotValue memory slotStethTotalShares = Verifier.extractSlotValueFromProof( STETH_TOTAL_SHARES_HASH, accountSteth.storageRoot, proofs[5].toList() ); require(slotStethTotalShares.exists, "totalShares"); Verifier.SlotValue memory slotStethBeaconBalance = Verifier.extractSlotValueFromProof( STETH_BEACON_BALANCE_HASH, accountSteth.storageRoot, proofs[6].toList() ); require(slotStethBeaconBalance.exists, "beaconBalance"); Verifier.SlotValue memory slotStethBufferedEther = Verifier.extractSlotValueFromProof( STETH_BUFFERED_ETHER_HASH, accountSteth.storageRoot, proofs[7].toList() ); require(slotStethBufferedEther.exists, "bufferedEther"); Verifier.SlotValue memory slotStethDepositedValidators = Verifier.extractSlotValueFromProof( STETH_DEPOSITED_VALIDATORS_HASH, accountSteth.storageRoot, proofs[8].toList() ); require(slotStethDepositedValidators.exists, "depositedValidators"); Verifier.SlotValue memory slotStethBeaconValidators = Verifier.extractSlotValueFromProof( STETH_BEACON_VALIDATORS_HASH, accountSteth.storageRoot, proofs[9].toList() ); require(slotStethBeaconValidators.exists, "beaconValidators"); emit SlotValuesUpdated( blockHeader.timestamp, accountPool.balance, slotPoolAdminBalances0.value, slotPoolAdminBalances1.value, slotStethPoolShares.value, slotStethTotalShares.value, slotStethBeaconBalance.value, slotStethBufferedEther.value, slotStethDepositedValidators.value, slotStethBeaconValidators.value ); uint256 newEtherBalance = accountPool.balance.sub(slotPoolAdminBalances0.value); uint256 newStethBalance = _getStethBalanceByShares( slotStethPoolShares.value, slotStethTotalShares.value, slotStethBeaconBalance.value, slotStethBufferedEther.value, slotStethDepositedValidators.value, slotStethBeaconValidators.value ).sub(slotPoolAdminBalances1.value); uint256 newStethPrice = _calcPrice(newEtherBalance, newStethBalance); timestamp = blockHeader.timestamp; etherBalance = newEtherBalance; stethBalance = newStethBalance; stethPrice = newStethPrice; emit PriceUpdated(blockHeader.timestamp, newEtherBalance, newStethBalance, newStethPrice); } /** * @dev Given the values of stETH smart contract slots, calculates the amount of stETH owned * by the Curve pool by reproducing calculations performed in the stETH contract. */ function _getStethBalanceByShares( uint256 _shares, uint256 _totalShares, uint256 _beaconBalance, uint256 _bufferedEther, uint256 _depositedValidators, uint256 _beaconValidators ) internal pure returns (uint256) { // https://github.com/lidofinance/lido-dao/blob/v1.0.0/contracts/0.4.24/StETH.sol#L283 // https://github.com/lidofinance/lido-dao/blob/v1.0.0/contracts/0.4.24/Lido.sol#L719 // https://github.com/lidofinance/lido-dao/blob/v1.0.0/contracts/0.4.24/Lido.sol#L706 if (_totalShares == 0) { return 0; } uint256 transientBalance = _depositedValidators.sub(_beaconValidators).mul(STETH_DEPOSIT_SIZE); uint256 totalPooledEther = _bufferedEther.add(_beaconBalance).add(transientBalance); return _shares.mul(totalPooledEther).div(_totalShares); } /** * @dev Given the ETH and stETH balances of the Curve pool, calculates the corresponding * stETH/ETH price by reproducing calculations performed in the pool contract. */ function _calcPrice(uint256 _etherBalance, uint256 _stethBalance) internal view returns (uint256) { uint256 A = IStableSwap(POOL_ADDRESS).A_precise(); uint256 fee = IStableSwap(POOL_ADDRESS).fee(); return helper.get_dy(1, 0, 10**18, [_etherBalance, _stethBalance], A, fee); } function _setPriceUpdateThreshold(uint256 _priceUpdateThreshold) internal { require(_priceUpdateThreshold <= 10000); priceUpdateThreshold = _priceUpdateThreshold; emit PriceUpdateThresholdChanged(_priceUpdateThreshold); } function _setAdmin(address _admin) internal { require(_admin != address(0)); require(_admin != admin); admin = _admin; emit AdminChanged(_admin); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IPriceHelper","name":"_helper","type":"address"},{"internalType":"address","name":"_admin","type":"address"},{"internalType":"uint256","name":"_priceUpdateThreshold","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"PriceUpdateThresholdChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"etherBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stethBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stethPrice","type":"uint256"}],"name":"PriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"poolEthBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"poolAdminEthBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"poolAdminStethBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stethPoolShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stethTotalShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stethBeaconBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stethBufferedEther","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stethDepositedValidators","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stethBeaconValidators","type":"uint256"}],"name":"SlotValuesUpdated","type":"event"},{"inputs":[],"name":"MIN_BLOCK_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL_ADMIN_BALANCES_0_POS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL_ADMIN_BALANCES_1_POS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH_BEACON_BALANCE_POS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH_BEACON_VALIDATORS_POS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH_BUFFERED_ETHER_POS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH_DEPOSITED_VALIDATORS_POS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH_POOL_SHARES_POS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH_TOTAL_SHARES_POS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"etherBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProofParams","outputs":[{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"address","name":"stethAddress","type":"address"},{"internalType":"bytes32","name":"poolAdminEtherBalancePos","type":"bytes32"},{"internalType":"bytes32","name":"poolAdminCoinBalancePos","type":"bytes32"},{"internalType":"bytes32","name":"stethPoolSharesPos","type":"bytes32"},{"internalType":"bytes32","name":"stethTotalSharesPos","type":"bytes32"},{"internalType":"bytes32","name":"stethBeaconBalancePos","type":"bytes32"},{"internalType":"bytes32","name":"stethBufferedEtherPos","type":"bytes32"},{"internalType":"bytes32","name":"stethDepositedValidatorsPos","type":"bytes32"},{"internalType":"bytes32","name":"stethBeaconValidatorsPos","type":"bytes32"},{"internalType":"uint256","name":"advisedPriceUpdateThreshold","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"internalType":"uint256","name":"_timestamp","type":"uint256"},{"internalType":"uint256","name":"_etherBalance","type":"uint256"},{"internalType":"uint256","name":"_stethBalance","type":"uint256"},{"internalType":"uint256","name":"_stethPrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceUpdateThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_priceUpdateThreshold","type":"uint256"}],"name":"setPriceUpdateThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stethBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stethPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_blockHeaderRlpBytes","type":"bytes"},{"internalType":"bytes","name":"_proofRlpBytes","type":"bytes"}],"name":"submitState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"timestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b506040516200228c3803806200228c833981810160405260608110156200003757600080fd5b5080516020820151604090920151600080546001600160a01b0319166001600160a01b0384161790559091906200006e8262000082565b620000798162000106565b50505062000151565b6001600160a01b0381166200009657600080fd5b6001546001600160a01b0382811691161415620000b257600080fd5b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f7ce7ec0b50378fb6c0186ffb5f48325f6593fcb4ca4386f21861af3129188f5c9181900360200190a150565b6127108111156200011657600080fd5b60028190556040805182815290517fcc12cb94e5dfbb0c4c3e36e95f4c0facb68fa7d4d9c7b64f6fc62f66cce7790c9181900360200190a150565b61212b80620001616000396000f3fe608060405234801561001057600080fd5b50600436106101415760003560e01c806393676829116100b8578063c2465d801161007c578063c2465d801461035f578063e4fc333114610367578063e5df87ca14610384578063ec79aabf146103ee578063f851a440146103f6578063fe94df88146103fe57610141565b80639367682914610337578063a8284f2b1461033f578063ad66e52a14610347578063b80777ea1461034f578063bda093831461035757610141565b8063327313571161010a57806332731357146102e95780633a34c83f146102f15780633ebfccfe146102f957806358f0a631146103015780635ecf410214610309578063704b6c021461031157610141565b8062451d8b1461014657806301527c601461016a578063117559e714610299578063126f5c5e146102b35780631865c57d146102bb575b600080fd5b61014e610406565b604080516001600160a01b039092168252519081900360200190f35b6102976004803603604081101561018057600080fd5b81019060208101813564010000000081111561019b57600080fd5b8201836020820111156101ad57600080fd5b803590602001918460018302840111640100000000831117156101cf57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561022257600080fd5b82018360208201111561023457600080fd5b8035906020019184600183028401116401000000008311171561025657600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061041e945050505050565b005b6102a1610c43565b60408051918252519081900360200190f35b6102a1610c48565b6102c3610c4e565b604080519485526020850193909352838301919091526060830152519081900360800190f35b6102a1610c60565b6102a1610c84565b6102a1610c8a565b6102a1610cae565b6102a1610cd2565b6102976004803603602081101561032757600080fd5b50356001600160a01b0316610cf6565b6102a1610d19565b6102a1610d3d565b6102a1610d61565b6102a1610d67565b6102a1610d6d565b6102a1610d73565b6102976004803603602081101561037d57600080fd5b5035610d97565b61038c610db7565b604080516001600160a01b039c8d1681529a909b1660208b0152898b01989098526060890196909652608088019490945260a087019290925260c086015260e08501526101008401526101208301526101408201529051908190036101600190f35b6102a1610ef9565b61014e610f1d565b61014e610f2c565b73ae7ab96520de3a18e5e111b5eaab095312d7fe8481565b61042661204e565b61042f83610f44565b604081015190915043908111801561044e5750600f8260400151820310155b610491576040805162461bcd60e51b815260206004820152600f60248201526e0c4d8dec6d640e8dede40cce4cae6d608b1b604482015290519081900360640190fd5b506003548160600151116104d9576040805162461bcd60e51b815260206004820152600a6024820152697374616c65206461746160b01b604482015290519081900360640190fd5b60606104ec6104e784610fb7565b610fdc565b90508051600a14610533576040805162461bcd60e51b815260206004820152600c60248201526b746f74616c2070726f6f667360a01b604482015290519081900360640190fd5b61053b612075565b6105897fc70f76036d72b7bb865881e931082ea61bb4f13ec9faeb17f0591b18b6fafbd760001b84602001516105848560008151811061057757fe5b6020026020010151610fdc565b6110c4565b80519091506105cd576040805162461bcd60e51b815260206004820152600b60248201526a1858d8dbdd5b9d141bdbdb60aa1b604482015290519081900360640190fd5b6105d5612075565b6106117f6c958a912fe86c83262fbd4973f6bd042cef76551aaf679968f98665979c35e760001b85602001516105848660018151811061057757fe5b8051909150610656576040805162461bcd60e51b815260206004820152600c60248201526b0c2c6c6deeadce8a6e8cae8d60a31b604482015290519081900360640190fd5b61065e6120a3565b61069f7fb5d9d894133a730aa651ef62d26b0ffa846233c74177a591a4a896adfda97d2260001b846060015161069a8760028151811061057757fe5b6111aa565b80519091506106e6576040805162461bcd60e51b815260206004820152600e60248201526d061646d696e42616c616e636573360941b604482015290519081900360640190fd5b6106ee6120a3565b61072a7fea7809e925a8989e20c901c4c1da82f0ba29b26797760d445a0ce4cf3c6fbd3160001b856060015161069a8860038151811061057757fe5b8051909150610771576040805162461bcd60e51b815260206004820152600e60248201526d61646d696e42616c616e6365733160901b604482015290519081900360640190fd5b6107796120a3565b6107b57fe841c8fb2710e169d6b63e1130fb8013d57558ced93619655add7aef8c60d4dc60001b856060015161069a8960048151811061057757fe5b80519091506107f8576040805162461bcd60e51b815260206004820152600a602482015269706f6f6c53686172657360b01b604482015290519081900360640190fd5b6108006120a3565b61083c7f4068b5716d4c00685289292c9cdc7e059e67159cd101476377efe51ba7ab8e9f60001b866060015161069a8a60058151811061057757fe5b8051909150610880576040805162461bcd60e51b815260206004820152600b60248201526a746f74616c53686172657360a81b604482015290519081900360640190fd5b6108886120a3565b6108c47fa6965d4729b36ed8b238f6ba55294196843f8be2850c5f63b6fb6d29181b50f860001b876060015161069a8b60068151811061057757fe5b805190915061090a576040805162461bcd60e51b815260206004820152600d60248201526c626561636f6e42616c616e636560981b604482015290519081900360640190fd5b6109126120a3565b61094e7fa39079072910ef75f32ddc4f40104882abfc19580cc249c694e12b6de868ee1d60001b886060015161069a8c60078151811061057757fe5b8051909150610994576040805162461bcd60e51b815260206004820152600d60248201526c313ab33332b932b222ba3432b960991b604482015290519081900360640190fd5b61099c6120a3565b6109d87f17216d3ffd8719eeee6d8052f7c1e6269bd92d2390d3e3fc4cde1f026e427fb360001b896060015161069a8d60088151811061057757fe5b8051909150610a24576040805162461bcd60e51b81526020600482015260136024820152726465706f736974656456616c696461746f727360681b604482015290519081900360640190fd5b610a2c6120a3565b610a687f6fd60d3960d8a32cbc1a708d6bf41bbce8152e61e72b2236d5e1ecede9c4cc7260001b8a6060015161069a8e60098151811061057757fe5b8051909150610ab1576040805162461bcd60e51b815260206004820152601060248201526f626561636f6e56616c696461746f727360801b604482015290519081900360640190fd5b7fb6b6c016579d82594391e31e1937d6475ba7d95dad21cc2ce3596b0d9abcbad18c606001518b604001518a602001518a602001518a602001518a602001518a602001518a602001518a602001518a60200151604051808b81526020018a81526020018981526020018881526020018781526020018681526020018581526020018481526020018381526020018281526020019a505050505050505050505060405180910390a16000610b7589602001518c6040015161121390919063ffffffff16565b90506000610bad8960200151610ba78a602001518a602001518a602001518a602001518a602001518a60200151611275565b90611213565b90506000610bbb83836112e0565b90508e606001516003819055508260048190555081600581905550806006819055507fc6d3da45896ce1bca9d198309a2dbeea3c73a991748f8d88d796ffa06029de938f606001518484846040518085815260200184815260200183815260200182815260200194505050505060405180910390a15050505050505050505050505050505050565b600f81565b60055481565b60035460045460055460065490919293565b7fe6e35175eb53fc006520a2a9c3e9711a7c00de6ff2c32dd31df8c5a24cac1b5c81565b60025481565b7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf781565b7f9f70001d82b6ef54e9d3725b46581c3eb9ee3aa02b941b6aa54d678a9ca35b1081565b7fed310af23f61f96daefbcd140b306c0bdbf8c178398299741687b90e794772b081565b6001546001600160a01b03163314610d0d57600080fd5b610d16816114c9565b50565b7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf681565b7fae68078d7ee25b2b7bcb7d4b9fe9acf61f251fe08ff637df07889375d838515881565b60045481565b60035481565b60065481565b7fa66d35f054e68143c18f32c990ed5cb972bb68a68f500cd2dd3a16bbf368648381565b6001546001600160a01b03163314610dae57600080fd5b610d168161154b565b60025473dc24316b9ae028f1497c275eb9192a3ea0f670229173ae7ab96520de3a18e5e111b5eaab095312d7fe84917fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6917fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf7917fae68078d7ee25b2b7bcb7d4b9fe9acf61f251fe08ff637df07889375d8385158917fe3b4b636e601189b5f4c6742edf2538ac12bb61ed03e6da26949d69838fa447e917fa66d35f054e68143c18f32c990ed5cb972bb68a68f500cd2dd3a16bbf3686483917fed310af23f61f96daefbcd140b306c0bdbf8c178398299741687b90e794772b0917fe6e35175eb53fc006520a2a9c3e9711a7c00de6ff2c32dd31df8c5a24cac1b5c917f9f70001d82b6ef54e9d3725b46581c3eb9ee3aa02b941b6aa54d678a9ca35b109190565b7fe3b4b636e601189b5f4c6742edf2538ac12bb61ed03e6da26949d69838fa447e81565b6001546001600160a01b031681565b73dc24316b9ae028f1497c275eb9192a3ea0f6702281565b610f4c61204e565b610f5461204e565b610f5d83611595565b604081015181519192504014610faf576040805162461bcd60e51b81526020600482015260126024820152710c4d8dec6d6d0c2e6d040dad2e6dac2e8c6d60731b604482015290519081900360640190fd5b90505b919050565b610fbf6120ba565b506040805180820190915281518152602082810190820152919050565b6060610fe78261160b565b610ff057600080fd5b6000610ffb83611645565b905060608167ffffffffffffffff8111801561101657600080fd5b5060405190808252806020026020018201604052801561105057816020015b61103d6120ba565b8152602001906001900390816110355790505b5090506000611062856020015161169d565b60208601510190506000805b848110156110b95761107f83611700565b91506040518060400160405280838152602001848152508482815181106110a257fe5b60209081029190910101529181019160010161106e565b509195945050505050565b6110cc612075565b60606110f884866040516020018082815260200191505060405160208183030381529060405285611799565b9050611102612075565b81516111115791506111a39050565b606061111f6104e784610fb7565b9050805160041461112f57600080fd5b60018252805161115190829060009061114457fe5b6020026020010151611b1a565b60208301528051611169908290600190811061114457fe5b60408301528051611181908290600290811061114457fe5b60608301528051611199908290600390811061114457fe5b6080830152509150505b9392505050565b6111b26120a3565b60606111de84866040516020018082815260200191505060405160208183030381529060405285611799565b90506111e86120a3565b81511561120a57600181526112046111ff83610fb7565b611b1a565b60208201525b95945050505050565b60008282111561126a576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b600085611284575060006112d6565b60006112a36801bc16d674ec80000061129d8686611213565b90611b68565b905060006112bb826112b5888a611bc1565b90611bc1565b90506112d1886112cb8b84611b68565b90611c1b565b925050505b9695505050505050565b60008073dc24316b9ae028f1497c275eb9192a3ea0f670226001600160a01b03166376a2f0f06040518163ffffffff1660e01b815260040160206040518083038186803b15801561133057600080fd5b505afa158015611344573d6000803e3d6000fd5b505050506040513d602081101561135a57600080fd5b50516040805163ddca3f4360e01b8152905191925060009173dc24316b9ae028f1497c275eb9192a3ea0f670229163ddca3f43916004808301926020929190829003018186803b1580156113ad57600080fd5b505afa1580156113c1573d6000803e3d6000fd5b505050506040513d60208110156113d757600080fd5b505160008054604080518082018252898152602081018990528151634659f74760e11b815260016004820181815260248301879052670de0b6b3a7640000604484018190529798506001600160a01b0390951696638cb3ee8e96919591949093928a928a9290916064019085908083838b5b83811015611461578181015183820152602001611449565b50505050905001838152602001828152602001965050505050505060206040518083038186803b15801561149457600080fd5b505afa1580156114a8573d6000803e3d6000fd5b505050506040513d60208110156114be57600080fd5b505195945050505050565b6001600160a01b0381166114dc57600080fd5b6001546001600160a01b03828116911614156114f757600080fd5b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f7ce7ec0b50378fb6c0186ffb5f48325f6593fcb4ca4386f21861af3129188f5c9181900360200190a150565b61271081111561155a57600080fd5b60028190556040805182815290517fcc12cb94e5dfbb0c4c3e36e95f4c0facb68fa7d4d9c7b64f6fc62f66cce7790c9181900360200190a150565b61159d61204e565b6115a561204e565b60606115b36104e785610fb7565b90506115c58160038151811061114457fe5b602083015280516115dd908290600890811061114457fe5b604083015280516115f5908290600b90811061114457fe5b6060830152508251602084012081529050919050565b805160009061161c57506000610fb2565b6020820151805160001a9060c082101561163b57600092505050610fb2565b5060019392505050565b805160009061165657506000610fb2565b600080611666846020015161169d565b602085015185519181019250015b808210156116945761168582611700565b60019093019290910190611674565b50909392505050565b8051600090811a60808110156116b7576000915050610fb2565b60b88110806116d2575060c081108015906116d2575060f881105b156116e1576001915050610fb2565b60c08110156116f55760b519019050610fb2565b60f519019050610fb2565b80516000908190811a608081101561171b5760019150611792565b60b881101561173057607e1981019150611792565b60c081101561175d5760b78103600185019450806020036101000a85510460018201810193505050611792565b60f88110156117725760be1981019150611792565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b6060806117a7846000611c82565b90506000806060806117b76120ba565b8751611806577f56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218a146117e957600080fd5b505060408051600081526020810190915294506111a39350505050565b60005b8851811015611b0c578015801561183b575061183789828151811061182a57fe5b6020026020010151611dc1565b8b14155b1561184557600080fd5b801580159061186f575061186b89828151811061185e57fe5b6020026020010151611dcd565b8514155b1561187957600080fd5b61188889828151811061057757fe5b92508251600214156119fb57600060606118bd6118b8866000815181106118ab57fe5b6020026020010151611e22565b611e9f565b909250905060006118cf898b84611f35565b9050808901985081518110156119315760018c51038410156118f057600080fd5b6000805b506040519080825280601f01601f19166020018201604052801561191f576020820181803683370190505b509a50505050505050505050506111a3565b821561198a5760018c510384101561194857600080fd5b8951891015611959576000806118f4565b8560018151811061196657fe5b6020026020010151945061197985611e22565b9a50505050505050505050506111a3565b60018c510384141561199b57600080fd5b6119b8866001815181106119ab57fe5b602002602001015161160b565b6119e0576119d9866001815181106119cc57fe5b6020026020010151611fa2565b97506119f3565b6119f08660018151811061182a57fe5b97505b505050611b04565b825160111415611b045786518614611ad6576000878781518110611a1b57fe5b01602001516001979097019660f81c905060108110611a3957600080fd5b611a58848260ff1681518110611a4b57fe5b6020026020010151611fba565b15611a8c5760018a51038214611a6d57600080fd5b505060408051600081526020810190915296506111a395505050505050565b611a9e848260ff16815181106119ab57fe5b611abb57611ab4848260ff16815181106119cc57fe5b9550611ad0565b611acd848260ff168151811061182a57fe5b95505b50611b04565b60018951038114611ae657600080fd5b611af6836010815181106118ab57fe5b9750505050505050506111a3565b600101611809565b505050505050509392505050565b805160009015801590611b2f57508151602110155b611b3857600080fd5b600080611b4484611fdd565b815191935091506020821015611b605760208290036101000a90045b949350505050565b600082611b775750600061126f565b82820282848281611b8457fe5b04146111a35760405162461bcd60e51b81526004018080602001828103825260218152602001806120d56021913960400191505060405180910390fd5b6000828201838110156111a3576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000808211611c71576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611c7a57fe5b049392505050565b60606000835111611c9257600080fd5b825160020280831115611ca457600080fd5b8290038067ffffffffffffffff81118015611cbe57600080fd5b506040519080825280601f01601f191660200182016040528015611ce9576020820181803683370190505b5091506000835b828501811015611dae5760028106611d54576004866002830481518110611d1357fe5b602001015160f81c60f81b60f81c60ff16901c600f1660f81b848381518110611d3857fe5b60200101906001600160f81b031916908160001a905350611da2565b6000866002830481518110611d6557fe5b602001015160f81c60f81b60f81c60ff16901c600f1660f81b848381518110611d8a57fe5b60200101906001600160f81b031916908160001a9053505b60019182019101611cf0565b5082518114611db957fe5b505092915050565b60208101519051902090565b6000602082600001511015611dec57611de582611dc1565b9050610fb2565b611df582611dc1565b60405160200180828152602001915050604051602081830303815290604052805190602001209050610fb2565b8051606090611e3057600080fd5b600080611e3c84611fdd565b9150915060608167ffffffffffffffff81118015611e5957600080fd5b506040519080825280601f01601f191660200182016040528015611e84576020820181803683370190505b50905060208101611e96848285612003565b50949350505050565b600060606000835111611eb157600080fd5b6000600484600081518110611ec257fe5b60209101015160f81c901c600f169050600081611ee55750600092506002611f1f565b8160011415611efa5750600092506001611f1f565b8160021415611f0f5750600192506002611f1f565b8160031415610141575060019250825b83611f2a8683611c82565b935093505050915091565b6000805b8351858201108015611f4b5750825181105b15611b6057828181518110611f5c57fe5b602001015160f81c60f81b6001600160f81b0319168486830181518110611f7f57fe5b01602001516001600160f81b03191614611f9a5790506111a3565b600101611f39565b6000806000611fb084611fdd565b9020949350505050565b8051600090600114611fce57506000610fb2565b50602001515160001a60801490565b6000806000611fef846020015161169d565b602085015194519481019594039392505050565b8061200d57612049565b5b6020811061202d578251825260209283019290910190601f190161200e565b8251825160208390036101000a60001901801990921691161782525b505050565b60408051608081018252600080825260208201819052918101829052606081019190915290565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915290565b604080518082019091526000808252602082015290565b60405180604001604052806000815260200160008152509056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220095da2537f60d3d5845a4a76859503b83425e5f1d2b667b113624fbfc887af0364736f6c634300060c0033000000000000000000000000fef762dfdc87f79879aaef221a6a5d302833fe27000000000000000000000000e19fc582dd93fa876cf4061eb5456f310144f57b00000000000000000000000000000000000000000000000000000000000001f4
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101415760003560e01c806393676829116100b8578063c2465d801161007c578063c2465d801461035f578063e4fc333114610367578063e5df87ca14610384578063ec79aabf146103ee578063f851a440146103f6578063fe94df88146103fe57610141565b80639367682914610337578063a8284f2b1461033f578063ad66e52a14610347578063b80777ea1461034f578063bda093831461035757610141565b8063327313571161010a57806332731357146102e95780633a34c83f146102f15780633ebfccfe146102f957806358f0a631146103015780635ecf410214610309578063704b6c021461031157610141565b8062451d8b1461014657806301527c601461016a578063117559e714610299578063126f5c5e146102b35780631865c57d146102bb575b600080fd5b61014e610406565b604080516001600160a01b039092168252519081900360200190f35b6102976004803603604081101561018057600080fd5b81019060208101813564010000000081111561019b57600080fd5b8201836020820111156101ad57600080fd5b803590602001918460018302840111640100000000831117156101cf57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561022257600080fd5b82018360208201111561023457600080fd5b8035906020019184600183028401116401000000008311171561025657600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061041e945050505050565b005b6102a1610c43565b60408051918252519081900360200190f35b6102a1610c48565b6102c3610c4e565b604080519485526020850193909352838301919091526060830152519081900360800190f35b6102a1610c60565b6102a1610c84565b6102a1610c8a565b6102a1610cae565b6102a1610cd2565b6102976004803603602081101561032757600080fd5b50356001600160a01b0316610cf6565b6102a1610d19565b6102a1610d3d565b6102a1610d61565b6102a1610d67565b6102a1610d6d565b6102a1610d73565b6102976004803603602081101561037d57600080fd5b5035610d97565b61038c610db7565b604080516001600160a01b039c8d1681529a909b1660208b0152898b01989098526060890196909652608088019490945260a087019290925260c086015260e08501526101008401526101208301526101408201529051908190036101600190f35b6102a1610ef9565b61014e610f1d565b61014e610f2c565b73ae7ab96520de3a18e5e111b5eaab095312d7fe8481565b61042661204e565b61042f83610f44565b604081015190915043908111801561044e5750600f8260400151820310155b610491576040805162461bcd60e51b815260206004820152600f60248201526e0c4d8dec6d640e8dede40cce4cae6d608b1b604482015290519081900360640190fd5b506003548160600151116104d9576040805162461bcd60e51b815260206004820152600a6024820152697374616c65206461746160b01b604482015290519081900360640190fd5b60606104ec6104e784610fb7565b610fdc565b90508051600a14610533576040805162461bcd60e51b815260206004820152600c60248201526b746f74616c2070726f6f667360a01b604482015290519081900360640190fd5b61053b612075565b6105897fc70f76036d72b7bb865881e931082ea61bb4f13ec9faeb17f0591b18b6fafbd760001b84602001516105848560008151811061057757fe5b6020026020010151610fdc565b6110c4565b80519091506105cd576040805162461bcd60e51b815260206004820152600b60248201526a1858d8dbdd5b9d141bdbdb60aa1b604482015290519081900360640190fd5b6105d5612075565b6106117f6c958a912fe86c83262fbd4973f6bd042cef76551aaf679968f98665979c35e760001b85602001516105848660018151811061057757fe5b8051909150610656576040805162461bcd60e51b815260206004820152600c60248201526b0c2c6c6deeadce8a6e8cae8d60a31b604482015290519081900360640190fd5b61065e6120a3565b61069f7fb5d9d894133a730aa651ef62d26b0ffa846233c74177a591a4a896adfda97d2260001b846060015161069a8760028151811061057757fe5b6111aa565b80519091506106e6576040805162461bcd60e51b815260206004820152600e60248201526d061646d696e42616c616e636573360941b604482015290519081900360640190fd5b6106ee6120a3565b61072a7fea7809e925a8989e20c901c4c1da82f0ba29b26797760d445a0ce4cf3c6fbd3160001b856060015161069a8860038151811061057757fe5b8051909150610771576040805162461bcd60e51b815260206004820152600e60248201526d61646d696e42616c616e6365733160901b604482015290519081900360640190fd5b6107796120a3565b6107b57fe841c8fb2710e169d6b63e1130fb8013d57558ced93619655add7aef8c60d4dc60001b856060015161069a8960048151811061057757fe5b80519091506107f8576040805162461bcd60e51b815260206004820152600a602482015269706f6f6c53686172657360b01b604482015290519081900360640190fd5b6108006120a3565b61083c7f4068b5716d4c00685289292c9cdc7e059e67159cd101476377efe51ba7ab8e9f60001b866060015161069a8a60058151811061057757fe5b8051909150610880576040805162461bcd60e51b815260206004820152600b60248201526a746f74616c53686172657360a81b604482015290519081900360640190fd5b6108886120a3565b6108c47fa6965d4729b36ed8b238f6ba55294196843f8be2850c5f63b6fb6d29181b50f860001b876060015161069a8b60068151811061057757fe5b805190915061090a576040805162461bcd60e51b815260206004820152600d60248201526c626561636f6e42616c616e636560981b604482015290519081900360640190fd5b6109126120a3565b61094e7fa39079072910ef75f32ddc4f40104882abfc19580cc249c694e12b6de868ee1d60001b886060015161069a8c60078151811061057757fe5b8051909150610994576040805162461bcd60e51b815260206004820152600d60248201526c313ab33332b932b222ba3432b960991b604482015290519081900360640190fd5b61099c6120a3565b6109d87f17216d3ffd8719eeee6d8052f7c1e6269bd92d2390d3e3fc4cde1f026e427fb360001b896060015161069a8d60088151811061057757fe5b8051909150610a24576040805162461bcd60e51b81526020600482015260136024820152726465706f736974656456616c696461746f727360681b604482015290519081900360640190fd5b610a2c6120a3565b610a687f6fd60d3960d8a32cbc1a708d6bf41bbce8152e61e72b2236d5e1ecede9c4cc7260001b8a6060015161069a8e60098151811061057757fe5b8051909150610ab1576040805162461bcd60e51b815260206004820152601060248201526f626561636f6e56616c696461746f727360801b604482015290519081900360640190fd5b7fb6b6c016579d82594391e31e1937d6475ba7d95dad21cc2ce3596b0d9abcbad18c606001518b604001518a602001518a602001518a602001518a602001518a602001518a602001518a602001518a60200151604051808b81526020018a81526020018981526020018881526020018781526020018681526020018581526020018481526020018381526020018281526020019a505050505050505050505060405180910390a16000610b7589602001518c6040015161121390919063ffffffff16565b90506000610bad8960200151610ba78a602001518a602001518a602001518a602001518a602001518a60200151611275565b90611213565b90506000610bbb83836112e0565b90508e606001516003819055508260048190555081600581905550806006819055507fc6d3da45896ce1bca9d198309a2dbeea3c73a991748f8d88d796ffa06029de938f606001518484846040518085815260200184815260200183815260200182815260200194505050505060405180910390a15050505050505050505050505050505050565b600f81565b60055481565b60035460045460055460065490919293565b7fe6e35175eb53fc006520a2a9c3e9711a7c00de6ff2c32dd31df8c5a24cac1b5c81565b60025481565b7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf781565b7f9f70001d82b6ef54e9d3725b46581c3eb9ee3aa02b941b6aa54d678a9ca35b1081565b7fed310af23f61f96daefbcd140b306c0bdbf8c178398299741687b90e794772b081565b6001546001600160a01b03163314610d0d57600080fd5b610d16816114c9565b50565b7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf681565b7fae68078d7ee25b2b7bcb7d4b9fe9acf61f251fe08ff637df07889375d838515881565b60045481565b60035481565b60065481565b7fa66d35f054e68143c18f32c990ed5cb972bb68a68f500cd2dd3a16bbf368648381565b6001546001600160a01b03163314610dae57600080fd5b610d168161154b565b60025473dc24316b9ae028f1497c275eb9192a3ea0f670229173ae7ab96520de3a18e5e111b5eaab095312d7fe84917fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6917fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf7917fae68078d7ee25b2b7bcb7d4b9fe9acf61f251fe08ff637df07889375d8385158917fe3b4b636e601189b5f4c6742edf2538ac12bb61ed03e6da26949d69838fa447e917fa66d35f054e68143c18f32c990ed5cb972bb68a68f500cd2dd3a16bbf3686483917fed310af23f61f96daefbcd140b306c0bdbf8c178398299741687b90e794772b0917fe6e35175eb53fc006520a2a9c3e9711a7c00de6ff2c32dd31df8c5a24cac1b5c917f9f70001d82b6ef54e9d3725b46581c3eb9ee3aa02b941b6aa54d678a9ca35b109190565b7fe3b4b636e601189b5f4c6742edf2538ac12bb61ed03e6da26949d69838fa447e81565b6001546001600160a01b031681565b73dc24316b9ae028f1497c275eb9192a3ea0f6702281565b610f4c61204e565b610f5461204e565b610f5d83611595565b604081015181519192504014610faf576040805162461bcd60e51b81526020600482015260126024820152710c4d8dec6d6d0c2e6d040dad2e6dac2e8c6d60731b604482015290519081900360640190fd5b90505b919050565b610fbf6120ba565b506040805180820190915281518152602082810190820152919050565b6060610fe78261160b565b610ff057600080fd5b6000610ffb83611645565b905060608167ffffffffffffffff8111801561101657600080fd5b5060405190808252806020026020018201604052801561105057816020015b61103d6120ba565b8152602001906001900390816110355790505b5090506000611062856020015161169d565b60208601510190506000805b848110156110b95761107f83611700565b91506040518060400160405280838152602001848152508482815181106110a257fe5b60209081029190910101529181019160010161106e565b509195945050505050565b6110cc612075565b60606110f884866040516020018082815260200191505060405160208183030381529060405285611799565b9050611102612075565b81516111115791506111a39050565b606061111f6104e784610fb7565b9050805160041461112f57600080fd5b60018252805161115190829060009061114457fe5b6020026020010151611b1a565b60208301528051611169908290600190811061114457fe5b60408301528051611181908290600290811061114457fe5b60608301528051611199908290600390811061114457fe5b6080830152509150505b9392505050565b6111b26120a3565b60606111de84866040516020018082815260200191505060405160208183030381529060405285611799565b90506111e86120a3565b81511561120a57600181526112046111ff83610fb7565b611b1a565b60208201525b95945050505050565b60008282111561126a576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b600085611284575060006112d6565b60006112a36801bc16d674ec80000061129d8686611213565b90611b68565b905060006112bb826112b5888a611bc1565b90611bc1565b90506112d1886112cb8b84611b68565b90611c1b565b925050505b9695505050505050565b60008073dc24316b9ae028f1497c275eb9192a3ea0f670226001600160a01b03166376a2f0f06040518163ffffffff1660e01b815260040160206040518083038186803b15801561133057600080fd5b505afa158015611344573d6000803e3d6000fd5b505050506040513d602081101561135a57600080fd5b50516040805163ddca3f4360e01b8152905191925060009173dc24316b9ae028f1497c275eb9192a3ea0f670229163ddca3f43916004808301926020929190829003018186803b1580156113ad57600080fd5b505afa1580156113c1573d6000803e3d6000fd5b505050506040513d60208110156113d757600080fd5b505160008054604080518082018252898152602081018990528151634659f74760e11b815260016004820181815260248301879052670de0b6b3a7640000604484018190529798506001600160a01b0390951696638cb3ee8e96919591949093928a928a9290916064019085908083838b5b83811015611461578181015183820152602001611449565b50505050905001838152602001828152602001965050505050505060206040518083038186803b15801561149457600080fd5b505afa1580156114a8573d6000803e3d6000fd5b505050506040513d60208110156114be57600080fd5b505195945050505050565b6001600160a01b0381166114dc57600080fd5b6001546001600160a01b03828116911614156114f757600080fd5b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f7ce7ec0b50378fb6c0186ffb5f48325f6593fcb4ca4386f21861af3129188f5c9181900360200190a150565b61271081111561155a57600080fd5b60028190556040805182815290517fcc12cb94e5dfbb0c4c3e36e95f4c0facb68fa7d4d9c7b64f6fc62f66cce7790c9181900360200190a150565b61159d61204e565b6115a561204e565b60606115b36104e785610fb7565b90506115c58160038151811061114457fe5b602083015280516115dd908290600890811061114457fe5b604083015280516115f5908290600b90811061114457fe5b6060830152508251602084012081529050919050565b805160009061161c57506000610fb2565b6020820151805160001a9060c082101561163b57600092505050610fb2565b5060019392505050565b805160009061165657506000610fb2565b600080611666846020015161169d565b602085015185519181019250015b808210156116945761168582611700565b60019093019290910190611674565b50909392505050565b8051600090811a60808110156116b7576000915050610fb2565b60b88110806116d2575060c081108015906116d2575060f881105b156116e1576001915050610fb2565b60c08110156116f55760b519019050610fb2565b60f519019050610fb2565b80516000908190811a608081101561171b5760019150611792565b60b881101561173057607e1981019150611792565b60c081101561175d5760b78103600185019450806020036101000a85510460018201810193505050611792565b60f88110156117725760be1981019150611792565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b6060806117a7846000611c82565b90506000806060806117b76120ba565b8751611806577f56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218a146117e957600080fd5b505060408051600081526020810190915294506111a39350505050565b60005b8851811015611b0c578015801561183b575061183789828151811061182a57fe5b6020026020010151611dc1565b8b14155b1561184557600080fd5b801580159061186f575061186b89828151811061185e57fe5b6020026020010151611dcd565b8514155b1561187957600080fd5b61188889828151811061057757fe5b92508251600214156119fb57600060606118bd6118b8866000815181106118ab57fe5b6020026020010151611e22565b611e9f565b909250905060006118cf898b84611f35565b9050808901985081518110156119315760018c51038410156118f057600080fd5b6000805b506040519080825280601f01601f19166020018201604052801561191f576020820181803683370190505b509a50505050505050505050506111a3565b821561198a5760018c510384101561194857600080fd5b8951891015611959576000806118f4565b8560018151811061196657fe5b6020026020010151945061197985611e22565b9a50505050505050505050506111a3565b60018c510384141561199b57600080fd5b6119b8866001815181106119ab57fe5b602002602001015161160b565b6119e0576119d9866001815181106119cc57fe5b6020026020010151611fa2565b97506119f3565b6119f08660018151811061182a57fe5b97505b505050611b04565b825160111415611b045786518614611ad6576000878781518110611a1b57fe5b01602001516001979097019660f81c905060108110611a3957600080fd5b611a58848260ff1681518110611a4b57fe5b6020026020010151611fba565b15611a8c5760018a51038214611a6d57600080fd5b505060408051600081526020810190915296506111a395505050505050565b611a9e848260ff16815181106119ab57fe5b611abb57611ab4848260ff16815181106119cc57fe5b9550611ad0565b611acd848260ff168151811061182a57fe5b95505b50611b04565b60018951038114611ae657600080fd5b611af6836010815181106118ab57fe5b9750505050505050506111a3565b600101611809565b505050505050509392505050565b805160009015801590611b2f57508151602110155b611b3857600080fd5b600080611b4484611fdd565b815191935091506020821015611b605760208290036101000a90045b949350505050565b600082611b775750600061126f565b82820282848281611b8457fe5b04146111a35760405162461bcd60e51b81526004018080602001828103825260218152602001806120d56021913960400191505060405180910390fd5b6000828201838110156111a3576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000808211611c71576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611c7a57fe5b049392505050565b60606000835111611c9257600080fd5b825160020280831115611ca457600080fd5b8290038067ffffffffffffffff81118015611cbe57600080fd5b506040519080825280601f01601f191660200182016040528015611ce9576020820181803683370190505b5091506000835b828501811015611dae5760028106611d54576004866002830481518110611d1357fe5b602001015160f81c60f81b60f81c60ff16901c600f1660f81b848381518110611d3857fe5b60200101906001600160f81b031916908160001a905350611da2565b6000866002830481518110611d6557fe5b602001015160f81c60f81b60f81c60ff16901c600f1660f81b848381518110611d8a57fe5b60200101906001600160f81b031916908160001a9053505b60019182019101611cf0565b5082518114611db957fe5b505092915050565b60208101519051902090565b6000602082600001511015611dec57611de582611dc1565b9050610fb2565b611df582611dc1565b60405160200180828152602001915050604051602081830303815290604052805190602001209050610fb2565b8051606090611e3057600080fd5b600080611e3c84611fdd565b9150915060608167ffffffffffffffff81118015611e5957600080fd5b506040519080825280601f01601f191660200182016040528015611e84576020820181803683370190505b50905060208101611e96848285612003565b50949350505050565b600060606000835111611eb157600080fd5b6000600484600081518110611ec257fe5b60209101015160f81c901c600f169050600081611ee55750600092506002611f1f565b8160011415611efa5750600092506001611f1f565b8160021415611f0f5750600192506002611f1f565b8160031415610141575060019250825b83611f2a8683611c82565b935093505050915091565b6000805b8351858201108015611f4b5750825181105b15611b6057828181518110611f5c57fe5b602001015160f81c60f81b6001600160f81b0319168486830181518110611f7f57fe5b01602001516001600160f81b03191614611f9a5790506111a3565b600101611f39565b6000806000611fb084611fdd565b9020949350505050565b8051600090600114611fce57506000610fb2565b50602001515160001a60801490565b6000806000611fef846020015161169d565b602085015194519481019594039392505050565b8061200d57612049565b5b6020811061202d578251825260209283019290910190601f190161200e565b8251825160208390036101000a60001901801990921691161782525b505050565b60408051608081018252600080825260208201819052918101829052606081019190915290565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915290565b604080518082019091526000808252602082015290565b60405180604001604052806000815260200160008152509056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220095da2537f60d3d5845a4a76859503b83425e5f1d2b667b113624fbfc887af0364736f6c634300060c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000fef762dfdc87f79879aaef221a6a5d302833fe27000000000000000000000000e19fc582dd93fa876cf4061eb5456f310144f57b00000000000000000000000000000000000000000000000000000000000001f4
-----Decoded View---------------
Arg [0] : _helper (address): 0xfef762DFdc87f79879aaef221a6a5D302833FE27
Arg [1] : _admin (address): 0xe19fc582dd93FA876CF4061Eb5456F310144F57b
Arg [2] : _priceUpdateThreshold (uint256): 500
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000fef762dfdc87f79879aaef221a6a5d302833fe27
Arg [1] : 000000000000000000000000e19fc582dd93fa876cf4061eb5456f310144f57b
Arg [2] : 00000000000000000000000000000000000000000000000000000000000001f4
Deployed Bytecode Sourcemap
27671:17424:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29225:82;;;:::i;:::-;;;;-1:-1:-1;;;;;29225:82:0;;;;;;;;;;;;;;38135:4849;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;38135:4849:0;;;;;;;;-1:-1:-1;38135:4849:0;;-1:-1:-1;;38135:4849:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;38135:4849:0;;-1:-1:-1;38135:4849:0;;-1:-1:-1;;;;;38135:4849:0:i;:::-;;29034:44;;;:::i;:::-;;;;;;;;;;;;;;;;33840:27;;;:::i;36592:250::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30484:123;;;:::i;33505:35::-;;;:::i;29559:118::-;;;:::i;30670:120::-;;;:::i;30301:117::-;;;:::i;34702:118::-;;;;;;;;;;;;;;;;-1:-1:-1;34702:118:0;-1:-1:-1;;;;;34702:118:0;;:::i;29370:::-;;;:::i;29776:114::-;;;:::i;33732:27::-;;;:::i;33629:24::-;;;:::i;33950:25::-;;;:::i;30124:117::-;;;:::i;35064:178::-;;;;;;;;;;;;;;;;-1:-1:-1;35064:178:0;;:::i;35352:937::-;;;:::i;:::-;;;;-1:-1:-1;;;;;35352:937:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29949:115;;;:::i;33027:20::-;;;:::i;29137:81::-;;;:::i;29225:82::-;29265:42;29225:82;:::o;38135:4849::-;38254:39;;:::i;:::-;38296:48;38323:20;38296:26;:48::i;:::-;38501:18;;;;38254:90;;-1:-1:-1;38395:12:0;;38486:33;;:106;;;;;29076:2;38555:11;:18;;;38540:12;:33;:52;;38486:106;38460:183;;;;;-1:-1:-1;;;38460:183:0;;;;;;;;;;;;-1:-1:-1;;;38460:183:0;;;;;;;;;;;;;;;38135:4849;38699:9;;38675:11;:21;;;:33;38667:56;;;;;-1:-1:-1;;;38667:56:0;;;;;;;;;;;;-1:-1:-1;;;38667:56:0;;;;;;;;;;;;;;;38736:33;38772:35;:26;:14;:24;:26::i;:::-;:33;:35::i;:::-;38736:71;;38826:6;:13;38843:2;38826:19;38818:44;;;;;-1:-1:-1;;;38818:44:0;;;;;;;;;;;;-1:-1:-1;;;38818:44:0;;;;;;;;;;;;;;;38875:35;;:::i;:::-;38913:148;30943:66;38960:17;;38992:11;:25;;;39032:18;:6;39039:1;39032:9;;;;;;;;;;;;;;:16;:18::i;:::-;38913:32;:148::i;:::-;39082:18;;38875:186;;-1:-1:-1;39074:42:0;;;;;-1:-1:-1;;;39074:42:0;;;;;;;;;;;;-1:-1:-1;;;39074:42:0;;;;;;;;;;;;;;;39129:36;;:::i;:::-;39168:149;31113:66;39215:18;;39248:11;:25;;;39288:18;:6;39295:1;39288:9;;;;;;;39168:149;39338:19;;39129:188;;-1:-1:-1;39330:44:0;;;;;-1:-1:-1;;;39330:44:0;;;;;;;;;;;;-1:-1:-1;;;39330:44:0;;;;;;;;;;;;;;;39387:48;;:::i;:::-;39438:157;31303:66;39487:26;;39528:11;:23;;;39566:18;:6;39573:1;39566:9;;;;;;;:18;39438:34;:157::i;:::-;39616:29;;39387:208;;-1:-1:-1;39608:56:0;;;;;-1:-1:-1;;;39608:56:0;;;;;;;;;;;;-1:-1:-1;;;39608:56:0;;;;;;;;;;;;;;;39677:48;;:::i;:::-;39728:157;31492:66;39777:26;;39818:11;:23;;;39856:18;:6;39863:1;39856:9;;;;;;;39728:157;39906:29;;39677:208;;-1:-1:-1;39898:56:0;;;;;-1:-1:-1;;;39898:56:0;;;;;;;;;;;;-1:-1:-1;;;39898:56:0;;;;;;;;;;;;;;;39967:45;;:::i;:::-;40015:154;31673:66;40064:22;;40101:12;:24;;;40140:18;:6;40147:1;40140:9;;;;;;;40015:154;40190:26;;39967:202;;-1:-1:-1;40182:49:0;;;;;-1:-1:-1;;;40182:49:0;;;;;;;;;;;;-1:-1:-1;;;40182:49:0;;;;;;;;;;;;;;;40244:46;;:::i;:::-;40293:155;31856:66;40342:23;;40380:12;:24;;;40419:18;:6;40426:1;40419:9;;;;;;;40293:155;40469:27;;40244:204;;-1:-1:-1;40461:51:0;;;;;-1:-1:-1;;;40461:51:0;;;;;;;;;;;;-1:-1:-1;;;40461:51:0;;;;;;;;;;;;;;;40525:48;;:::i;:::-;40576:157;32043:66;40625:25;;40665:12;:24;;;40704:18;:6;40711:1;40704:9;;;;;;;40576:157;40754:29;;40525:208;;-1:-1:-1;40746:55:0;;;;;-1:-1:-1;;;40746:55:0;;;;;;;;;;;;-1:-1:-1;;;40746:55:0;;;;;;;;;;;;;;;40814:48;;:::i;:::-;40865:157;32230:66;40914:25;;40954:12;:24;;;40993:18;:6;41000:1;40993:9;;;;;;;40865:157;41043:29;;40814:208;;-1:-1:-1;41035:55:0;;;;;-1:-1:-1;;;41035:55:0;;;;;;;;;;;;-1:-1:-1;;;41035:55:0;;;;;;;;;;;;;;;41103:54;;:::i;:::-;41160:163;32429:66;41209:31;;41255:12;:24;;;41294:18;:6;41301:1;41294:9;;;;;;;41160:163;41344:35;;41103:220;;-1:-1:-1;41336:67:0;;;;;-1:-1:-1;;;41336:67:0;;;;;;;;;;;;-1:-1:-1;;;41336:67:0;;;;;;;;;;;;;;;41416:51;;:::i;:::-;41470:160;32622:66;41519:28;;41562:12;:24;;;41601:18;:6;41608:1;41601:9;;;;;;;41470:160;41651:32;;41416:214;;-1:-1:-1;41643:61:0;;;;;-1:-1:-1;;;41643:61:0;;;;;;;;;;;;-1:-1:-1;;;41643:61:0;;;;;;;;;;;;;;;41722:446;41754:11;:21;;;41790:11;:19;;;41824:22;:28;;;41867:22;:28;;;41910:19;:25;;;41950:20;:26;;;41991:22;:28;;;42034:22;:28;;;42077;:34;;;42126:25;:31;;;41722:446;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42181:23;42207:53;42231:22;:28;;;42207:11;:19;;;:23;;:53;;;;:::i;:::-;42181:79;;42271:23;42297:331;42599:22;:28;;;42297:297;42336:19;:25;;;42376:20;:26;;;42417:22;:28;;;42460:22;:28;;;42503;:34;;;42552:25;:31;;;42297:24;:297::i;:::-;:301;;:331::i;:::-;42271:357;;42641:21;42665:44;42676:15;42693;42665:10;:44::i;:::-;42641:68;;42734:11;:21;;;42722:9;:33;;;;42781:15;42766:12;:30;;;;42822:15;42807:12;:30;;;;42861:13;42848:10;:26;;;;42892:84;42905:11;:21;;;42928:15;42945;42962:13;42892:84;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38135:4849;;;;;;;;;;;;;;;;;:::o;29034:44::-;29076:2;29034:44;:::o;33840:27::-;;;;:::o;36592:250::-;36784:9;;36795:12;;36809;;36823:10;;36592:250;;;;:::o;30484:123::-;30541:66;30484:123;:::o;33505:35::-;;;;:::o;29559:118::-;29611:66;29559:118;:::o;30670:120::-;30724:66;30670:120;:::o;30301:117::-;30352:66;30301:117;:::o;34702:118::-;34778:5;;-1:-1:-1;;;;;34778:5:0;34764:10;:19;34756:28;;;;;;34795:17;34805:6;34795:9;:17::i;:::-;34702:118;:::o;29370:::-;29422:66;29370:118;:::o;29776:114::-;29824:66;29776:114;:::o;33732:27::-;;;;:::o;33629:24::-;;;;:::o;33950:25::-;;;;:::o;30124:117::-;30175:66;30124:117;:::o;35064:178::-;35170:5;;-1:-1:-1;;;;;35170:5:0;35156:10;:19;35148:28;;;;;;35187:47;35212:21;35187:24;:47::i;35352:937::-;36250:20;;29176:42;;29265;;29422:66;;29611;;29824;;29998;;30175;;30352;;30541;;30724;;36250:20;35352:937::o;29949:115::-;29998:66;29949:115;:::o;33027:20::-;;;-1:-1:-1;;;;;33027:20:0;;:::o;29137:81::-;29176:42;29137:81;:::o;23757:363::-;23846:18;;:::i;:::-;23882:25;;:::i;:::-;23910:33;23927:15;23910:16;:33::i;:::-;24051:13;;;;24026:11;;23882:61;;-1:-1:-1;24041:24:0;24026:39;24018:70;;;;;-1:-1:-1;;;24018:70:0;;;;;;;;;;;;-1:-1:-1;;;24018:70:0;;;;;;;;;;;;;;;24106:6;-1:-1:-1;23757:363:0;;;;:::o;3812:225::-;3873:14;;:::i;:::-;-1:-1:-1;4001:28:0;;;;;;;;;4009:11;;4001:28;;3966:4;3956:15;;;4001:28;;;;3812:225;;;:::o;5255:522::-;5315:16;5352:12;5359:4;5352:6;:12::i;:::-;5344:21;;;;;;5378:10;5391:14;5400:4;5391:8;:14::i;:::-;5378:27;;5416:23;5456:5;5442:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;5416:46;;5475:11;5503:27;5518:4;:11;;;5503:14;:27::i;:::-;5489:11;;;;:41;;-1:-1:-1;5541:12:0;;5564:180;5585:5;5581:1;:9;5564:180;;;5622:19;5634:6;5622:11;:19::i;:::-;5612:29;;5668:24;;;;;;;;5676:7;5668:24;;;;5685:6;5668:24;;;5656:6;5663:1;5656:9;;;;;;;;;;;;;;;;;:36;5716:16;;;;5592:3;;5564:180;;;-1:-1:-1;5763:6:0;;5255:522;-1:-1:-1;;;;;5255:522:0:o;25102:971::-;25322:14;;:::i;:::-;25354:25;25382:151;25442:14;25488:12;25471:30;;;;;;;;;;;;;;;;;;;;;;;;;25516:6;25382:45;:151::i;:::-;25354:179;;25546:22;;:::i;:::-;25585:19;;25581:71;;25633:7;-1:-1:-1;25626:14:0;;-1:-1:-1;25626:14:0;25581:71;25664:37;25704:33;:24;:12;:22;:24::i;:33::-;25664:73;;25756:10;:17;25777:1;25756:22;25748:31;;;;;;25809:4;25792:21;;25840:13;;:22;;:10;;25792:14;;25840:13;;;;;;;;;;:20;:22::i;:::-;25824:13;;;:38;25891:13;;:22;;:10;;25902:1;;25891:13;;;;;:22;25873:15;;;:40;25954:13;;:22;;:10;;25965:1;;25954:13;;;;;:22;25924:19;;;:53;26015:13;;:22;;:10;;26026:1;;26015:13;;;;;:22;25988:16;;;:50;-1:-1:-1;25988:7:0;-1:-1:-1;;25102:971:0;;;;;;:::o;26336:614::-;26517:16;;:::i;:::-;26551:26;26580:150;26640:16;26688:9;26671:27;;;;;;;;;;;;;;;;;;;;;;;;;26713:6;26580:45;:150::i;:::-;26551:179;;26743:22;;:::i;:::-;26782:20;;:25;26778:140;;26839:4;26824:19;;26872:34;:25;:13;:23;:25::i;:::-;:32;:34::i;:::-;26858:11;;;:48;26778:140;26937:5;26336:614;-1:-1:-1;;;;;26336:614:0:o;1037:158::-;1095:7;1128:1;1123;:6;;1115:49;;;;;-1:-1:-1;;;1115:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1182:5:0;;;1037:158;;;;;:::o;43202:911::-;43473:7;43788:17;43784:58;;-1:-1:-1;43829:1:0;43822:8;;43784:58;43852:24;43879:67;32744:8;43879:43;:20;43904:17;43879:24;:43::i;:::-;:47;;:67::i;:::-;43852:94;-1:-1:-1;43957:24:0;43984:56;43852:94;43984:34;:14;44003;43984:18;:34::i;:::-;:38;;:56::i;:::-;43957:83;-1:-1:-1;44058:47:0;44092:12;44058:29;:7;43957:83;44058:11;:29::i;:::-;:33;;:47::i;:::-;44051:54;;;;43202:911;;;;;;;;;:::o;44324:307::-;44413:7;44433:9;29176:42;-1:-1:-1;;;;;44445:35:0;;:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;44445:37:0;44507:31;;;-1:-1:-1;;;44507:31:0;;;;44445:37;;-1:-1:-1;44493:11:0;;29176:42;;44507:29;;:31;;;;;44445:37;;44507:31;;;;;;;29176:42;44507:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;44507:31:0;44556:6;;;:67;;;;;;;;;;;44507:31;44556:67;;;;;;;-1:-1:-1;;;44556:67:0;;:6;:67;;;;;;;;;;;;44576:6;44556:67;;;;;;44507:31;;-1:-1:-1;;;;;;44556:6:0;;;;:13;;:6;;;;44576;;44556:67;44616:1;;44507:31;;44556:67;;;;;;;;;;:6;:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;44556:67:0;;44324:307;-1:-1:-1;;;;;44324:307:0:o;44904:188::-;-1:-1:-1;;;;;44967:20:0;;44959:29;;;;;;45017:5;;-1:-1:-1;;;;;45007:15:0;;;45017:5;;45007:15;;44999:24;;;;;;45034:5;:14;;-1:-1:-1;;;;;45034:14:0;;-1:-1:-1;;;;;;45034:14:0;;;;;;;;45064:20;;;;;;;;;;;;;;;;44904:188;:::o;44641:253::-;44759:5;44734:21;:30;;44726:39;;;;;;44776:20;:44;;;44836:50;;;;;;;;;;;;;;;;;44641:253;:::o;24254:558::-;24342:18;;:::i;:::-;24378:25;;:::i;:::-;24414:39;24456:36;:27;:15;:25;:27::i;:36::-;24414:78;;24536:46;:12;23090:1;24536:37;;;;;;;:46;24505:20;;;:78;24610:33;;:42;;:12;;23137:1;;24610:33;;;;;:42;24594:13;;;:58;24682:36;;:45;;:12;;23187:2;;24682:36;;;;;:45;24663:16;;;:64;-1:-1:-1;24752:26:0;;;;;;24738:40;;24663:6;-1:-1:-1;24254:558:0;;;:::o;5884:342::-;5965:8;;5944:4;;5961:31;;-1:-1:-1;5987:5:0;5980:12;;5961:31;6041:11;;;;6104:13;;6005:11;6096:22;;2603:4;6145:24;;6141:55;;;6191:5;6184:12;;;;;;6141:55;-1:-1:-1;6214:4:0;;5884:342;-1:-1:-1;;;5884:342:0:o;9748:422::-;9830:8;;9809:4;;9826:27;;-1:-1:-1;9852:1:0;9845:8;;9826:27;9866:10;9891:12;9920:27;9935:4;:11;;;9920:14;:27::i;:::-;9906:11;;;;9986:8;;9906:41;;;;-1:-1:-1;9972:22:0;10005:133;10022:6;10012:7;:16;10005:133;;;10064:20;10076:7;10064:11;:20::i;:::-;10119:7;;;;;10054:30;;;;10005:133;;;-1:-1:-1;10157:5:0;;9748:422;-1:-1:-1;;;9748:422:0:o;11579:551::-;11717:13;;11638:4;;11709:22;;2509:4;11758:26;;11754:368;;;11806:1;11799:8;;;;;11754:368;2556:4;11827:25;;;:83;;-1:-1:-1;2603:4:0;11857:25;;;;;:52;;-1:-1:-1;2650:4:0;11886:23;;11857:52;11823:299;;;11932:1;11925:8;;;;;11823:299;2603:4;11953:24;;11949:173;;;-1:-1:-1;;12018:35:0;;-1:-1:-1;12011:42:0;;11949:173;-1:-1:-1;;12089:33:0;;-1:-1:-1;12082:40:0;;10222:1302;10380:13;;10278:4;;;;10372:22;;2509:4;10421:26;;10417:1073;;;10472:1;10462:11;;10417:1073;;;2556:4;10495:25;;10491:999;;;-1:-1:-1;;10545:30:0;;;-1:-1:-1;10491:999:0;;;2603:4;10597:24;;10593:897;;;10692:4;10685:5;10681:16;10772:1;10764:6;10760:14;10750:24;;10914:7;10910:2;10906:16;10901:3;10897:26;10888:6;10882:13;10878:46;11012:1;11003:7;10999:15;10990:7;10986:29;10975:40;;;;10647:383;;;2650:4;11062:23;;11058:432;;;-1:-1:-1;;11112:28:0;;;-1:-1:-1;11058:432:0;;;11238:4;11231:5;11227:16;11283:1;11275:6;11271:14;11261:24;;11356:7;11352:2;11348:16;11343:3;11339:26;11330:6;11324:13;11320:46;11461:1;11452:7;11448:15;11439:7;11435:29;11424:40;;;;11193:286;-1:-1:-1;11509:7:0;10222:1302;-1:-1:-1;;10222:1302:0:o;14065:5625::-;14220:18;14251:19;14273:23;14288:4;14294:1;14273:14;:23::i;:::-;14251:45;;14307:20;14344;14375;14406:31;14450:33;;:::i;:::-;14500:12;;14496:227;;14610:66;14598:78;;14590:87;;;;;;-1:-1:-1;;14699:12:0;;;14709:1;14699:12;;;;;;;;;-1:-1:-1;14692:19:0;;-1:-1:-1;;;;14692:19:0;14496:227;14794:9;14789:4894;14813:5;:12;14809:1;:16;14789:4894;;;15095:6;;:50;;;;;15117:28;:5;15123:1;15117:8;;;;;;;;;;;;;;:26;:28::i;:::-;15105:8;:40;;15095:50;15091:99;;;15166:8;;;15091:99;15307:6;;;;;:48;;;15333:22;15346:5;15352:1;15346:8;;;;;;;;;;;;;;15333:12;:22::i;:::-;15317:12;:38;;15307:48;15303:97;;;15376:8;;;15303:97;15529:17;:5;15535:1;15529:8;;;;;;;:17;15522:24;;15567:4;:11;15582:1;15567:16;15563:4109;;;15649:11;15679:20;15738:47;15767:17;:4;15772:1;15767:7;;;;;;;;;;;;;;:15;:17::i;:::-;15738:28;:47::i;:::-;15718:67;;-1:-1:-1;15718:67:0;-1:-1:-1;15806:20:0;15829:50;15849:12;15863:6;15718:67;15829:19;:50::i;:::-;15806:73;;15914:12;15898:28;;;;15966:7;:14;15951:12;:29;15947:1013;;;16768:1;16753:5;:12;:16;16749:1;:20;16745:152;;;16865:8;;;16745:152;16938:1;;16928:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;16928:12:0;;16921:19;;;;;;;;;;;;;;15947:1013;16984:6;16980:1184;;;17075:1;17060:5;:12;:16;17056:1;:20;17052:147;;;17167:8;;;17052:147;17242:6;:13;17227:12;:28;17223:104;;;17301:1;;17291:12;;17223:104;17362:4;17367:1;17362:7;;;;;;;;;;;;;;17351:18;;17399;:8;:16;:18::i;:::-;17392:25;;;;;;;;;;;;;;16980:1184;17540:1;17525:5;:12;:16;17520:1;:21;17516:141;;;17625:8;;;17516:141;17686:16;:4;17691:1;17686:7;;;;;;;;;;;;;;:14;:16::i;:::-;17681:464;;17876:26;:4;17881:1;17876:7;;;;;;;;;;;;;;:24;:26::i;:::-;17861:41;;17681:464;;;18094:27;:4;18099:1;18094:7;;;;;;;:27;18079:42;;17681:464;15563:4109;;;;;;18189:4;:11;18204:2;18189:17;18185:1487;;;18281:6;:13;18265:12;:29;18261:1396;;18410:12;18431:6;18438:12;18431:20;;;;;;;;;;;;18491:1;18475:17;;;;;18431:20;;;-1:-1:-1;18529:2:0;18519:12;;18515:149;;18632:8;;;18515:149;18692:34;18713:4;18718:6;18713:12;;;;;;;;;;;;;;;;18692:20;:34::i;:::-;18688:568;;;18814:1;18799:5;:12;:16;18794:1;:21;18790:160;;18914:8;;;18790:160;-1:-1:-1;;18985:12:0;;;18995:1;18985:12;;;;;;;;;-1:-1:-1;18978:19:0;;-1:-1:-1;;;;;;18978:19:0;18688:568;19032:21;:4;19037:6;19032:12;;;;;;;;;:21;19027:229;;19097:31;:4;19102:6;19097:12;;;;;;;;;:31;19082:46;;19027:229;;;19200:32;:4;19205:6;19200:12;;;;;;;;;:32;19185:47;;19027:229;18261:1396;;;;19474:1;19459:5;:12;:16;19454:1;:21;19450:138;;19556:8;;;19450:138;19619:18;:4;19624:2;19619:8;;;;;;;:18;19612:25;;;;;;;;;;;18261:1396;14827:3;;14789:4894;;;;14065:5625;;;;;;;;;;;:::o;8433:471::-;8518:8;;8493:4;;8518:12;;;;:30;;-1:-1:-1;8534:8:0;;8546:2;-1:-1:-1;8534:14:0;8518:30;8510:39;;;;;;8563:11;8576:8;8588:21;8604:4;8588:15;:21::i;:::-;8678:13;;8562:47;;-1:-1:-1;8562:47:0;-1:-1:-1;8777:2:0;8769:11;;8766:2;;;8835;8831:12;;;8826:3;8822:22;8810:35;;8766:2;8890:6;8433:471;-1:-1:-1;;;;8433:471:0:o;1454:220::-;1512:7;1536:6;1532:20;;-1:-1:-1;1551:1:0;1544:8;;1532:20;1575:5;;;1579:1;1575;:5;:1;1599:5;;;;;:10;1591:56;;;;-1:-1:-1;;;1591:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;575:179;633:7;665:5;;;689:6;;;;681:46;;;;;-1:-1:-1;;;681:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;2152:153;2210:7;2242:1;2238;:5;2230:44;;;;;-1:-1:-1;;;2230:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;2296:1;2292;:5;;;;;;;2152:153;-1:-1:-1;;;2152:153:0:o;21715:763::-;21804:20;21862:1;21845:7;:14;:18;21837:27;;;;;;21894:14;;21911:1;21894:18;21931:21;;;;21923:30;;;;;;21964:21;;;;22008:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;22008:17:0;-1:-1:-1;21998:27:0;-1:-1:-1;22036:21:0;22091:11;22074:345;22122:6;22108:11;:20;22104:1;:24;22074:345;;;22161:1;22157;:5;22153:222;;22244:1;22227:7;22237:1;22235;:3;22227:12;;;;;;;;;;;;;;;;22221:19;;:24;;;;22249:3;22220:32;22213:40;;22188:7;22196:13;22188:22;;;;;;;;;;;:65;-1:-1:-1;;;;;22188:65:0;;;;;;;;;22153:222;;;22350:1;22333:7;22343:1;22341;:3;22333:12;;;;;;;;;;;;;;;;22327:19;;:24;;;;22355:3;22326:32;22319:40;;22294:7;22302:13;22294:22;;;;;;;;;;;:65;-1:-1:-1;;;;;22294:65:0;;;;;;;;;22153:222;22406:1;22389:18;;;;22130:6;22074:345;;;;22455:7;:14;22438:13;:31;22431:39;;;;21715:763;;;;;;:::o;6394:280::-;6499:11;;;;6535:8;;6613:19;;;6394:280::o;20268:272::-;20343:7;20378:2;20367:4;:8;;;:13;20363:170;;;20404:24;:4;:22;:24::i;:::-;20397:31;;;;20363:170;20495:24;:4;:22;:24::i;:::-;20478:42;;;;;;;;;;;;;;;;;;;;;;;;;20468:53;;;;;;20461:60;;;;9252:383;9346:8;;9313:12;;9338:21;;;;;;9373:11;9386:8;9398:21;9414:4;9398:15;:21::i;:::-;9372:47;;;;9430:19;9462:3;9452:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;9452:14:0;-1:-1:-1;9430:36:0;-1:-1:-1;9541:4:0;9537:17;;9577:26;9582:6;9537:17;9599:3;9577:4;:26::i;:::-;-1:-1:-1;9621:6:0;9252:383;-1:-1:-1;;;;9252:383:0:o;20903:802::-;20985:11;20998:20;21056:1;21039:7;:14;:18;21031:27;;;;;;21069:20;21113:1;21098:7;21106:1;21098:10;;;;;;;;;;;;;;;21092:22;;21117:3;21092:28;;-1:-1:-1;21131:19:0;21092:28;21161:473;;-1:-1:-1;21238:5:0;;-1:-1:-1;21213:1:0;21161:473;;;21265:12;21281:1;21265:17;21261:373;;;-1:-1:-1;21338:5:0;;-1:-1:-1;21313:1:0;21261:373;;;21365:12;21381:1;21365:17;21361:273;;;-1:-1:-1;21438:4:0;;-1:-1:-1;21413:1:0;21361:273;;;21464:12;21480:1;21464:17;21460:174;;;-1:-1:-1;21512:1:0;;-1:-1:-1;21512:1:0;21460:174;21652:6;21660:36;21675:7;21684:11;21660:14;:36::i;:::-;21644:53;;;;;;20903:802;;;:::o;22488:329::-;22591:7;;22631:160;22658:2;:9;22647:8;22643:1;:12;:24;:41;;;;;22675:2;:9;22671:1;:13;22643:41;22631:160;;;22730:2;22733:1;22730:5;;;;;;;;;;;;;;;;-1:-1:-1;;;;;22710:25:0;;:2;22717:8;22713:1;:12;22710:16;;;;;;;;;;;;-1:-1:-1;;;;;;22710:16:0;:25;22706:74;;22763:1;-1:-1:-1;22756:8:0;;22706:74;22686:3;;22631:160;;6838:271;6908:7;6929:11;6942:8;6954:21;6970:4;6954:15;:21::i;:::-;7045:22;;;6838:271;-1:-1:-1;;;;6838:271:0:o;20548:345::-;20652:8;;20631:4;;20664:1;20652:13;20648:58;;-1:-1:-1;20689:5:0;20682:12;;20648:58;-1:-1:-1;20751:11:0;;;20810:13;20716:7;20802:22;20857:4;20852:9;;20548:345::o;4706:271::-;4775:4;4781;4798:11;4812:27;4827:4;:11;;;4812:14;:27::i;:::-;4864:11;;;;4906:8;;4864:20;;;;4906:17;;;4706:271;-1:-1:-1;;;4706:271:0:o;12291:717::-;12364:8;12360:21;;12374:7;;12360:21;12441:201;2688:2;12448:16;;12441:201;;12540:10;;12527:24;;2688:2;12582:16;;;;12613:17;;;;-1:-1:-1;;12466:16:0;12441:201;;;12829:10;;12901:11;;2688:2;12755:15;;;12747:3;:24;-1:-1:-1;;12747:28:0;12841:9;;12825:26;;;12897:22;;12968:21;12955:35;;12795:206;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o
Swarm Source
ipfs://095da2537f60d3d5845a4a76859503b83425e5f1d2b667b113624fbfc887af03
Loading...
Loading
Loading...
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.