More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 5,164 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Submit Logic Cal... | 21771309 | 4 days ago | IN | 0 ETH | 0.00326404 | ||||
Submit Logic Cal... | 21771304 | 4 days ago | IN | 0 ETH | 0.00313302 | ||||
Send To Cosmos | 21760334 | 5 days ago | IN | 0 ETH | 0.00092848 | ||||
Submit Logic Cal... | 21755821 | 6 days ago | IN | 0 ETH | 0.00393195 | ||||
Submit Batch | 21753853 | 6 days ago | IN | 0 ETH | 0.00065456 | ||||
Submit Batch | 21751752 | 6 days ago | IN | 0 ETH | 0.0004553 | ||||
Submit Batch | 21750977 | 7 days ago | IN | 0 ETH | 0.00037117 | ||||
Update Valset | 21740788 | 8 days ago | IN | 0 ETH | 0.00043193 | ||||
Submit Batch | 21731270 | 9 days ago | IN | 0 ETH | 0.00110263 | ||||
Submit Batch | 21729531 | 10 days ago | IN | 0 ETH | 0.00038322 | ||||
Submit Logic Cal... | 21725740 | 10 days ago | IN | 0 ETH | 0.00151207 | ||||
Submit Logic Cal... | 21725728 | 10 days ago | IN | 0 ETH | 0.00150309 | ||||
Submit Logic Cal... | 21725644 | 10 days ago | IN | 0 ETH | 0.01808213 | ||||
Submit Logic Cal... | 21725560 | 10 days ago | IN | 0 ETH | 0.01255556 | ||||
Submit Batch | 21723282 | 10 days ago | IN | 0 ETH | 0.0009168 | ||||
Send To Cosmos | 21723091 | 10 days ago | IN | 0 ETH | 0.00026006 | ||||
Submit Batch | 21719216 | 11 days ago | IN | 0 ETH | 0.00101465 | ||||
Submit Batch | 21716196 | 11 days ago | IN | 0 ETH | 0.00289468 | ||||
Submit Logic Cal... | 21709834 | 12 days ago | IN | 0 ETH | 0.01914868 | ||||
Submit Logic Cal... | 21707625 | 13 days ago | IN | 0 ETH | 0.00805374 | ||||
Submit Logic Cal... | 21705928 | 13 days ago | IN | 0 ETH | 0.00726695 | ||||
Submit Logic Cal... | 21705898 | 13 days ago | IN | 0 ETH | 0.00776267 | ||||
Send To Cosmos | 21703283 | 13 days ago | IN | 0 ETH | 0.00033688 | ||||
Submit Batch | 21693854 | 14 days ago | IN | 0 ETH | 0.00350059 | ||||
Submit Logic Cal... | 21686005 | 16 days ago | IN | 0 ETH | 0.00775741 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
14083639 | 1108 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Gravity
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2022-01-27 */ // File @openzeppelin/contracts/utils/math/[email protected] // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @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) { return a + b; } /** * @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) { 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) { return a * b; } /** * @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. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. 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 mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message 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, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. 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 mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } } // File @openzeppelin/contracts/token/ERC20/[email protected] pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File @openzeppelin/contracts/utils/[email protected] pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File @openzeppelin/contracts/token/ERC20/utils/[email protected] pragma solidity ^0.8.0; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File @openzeppelin/contracts/security/[email protected] pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } // File @openzeppelin/contracts/utils/cryptography/[email protected] pragma solidity ^0.8.0; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } else if (error == RecoverError.InvalidSignatureV) { revert("ECDSA: invalid signature 'v' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { // Check the signature length // - case 65: r,s,v signature (standard) // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._ if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else if (signature.length == 64) { bytes32 r; bytes32 vs; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) vs := mload(add(signature, 0x40)) } return tryRecover(hash, r, vs); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s; uint8 v; assembly { s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) v := add(shr(255, vs), 27) } return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } if (v != 27 && v != 28) { return (address(0), RecoverError.InvalidSignatureV); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } } // File @openzeppelin/contracts/token/ERC20/extensions/[email protected] pragma solidity ^0.8.0; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } // File @openzeppelin/contracts/utils/[email protected] pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } } // File @openzeppelin/contracts/token/ERC20/[email protected] pragma solidity ^0.8.0; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); unchecked { _approve(sender, _msgSender(), currentAllowance - amount); } return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(_msgSender(), spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `sender` to `recipient`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[sender] = senderBalance - amount; } _balances[recipient] += amount; emit Transfer(sender, recipient, amount); _afterTokenTransfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} } // File contracts/CosmosToken.sol pragma solidity ^0.8.10; contract CosmosERC20 is ERC20 { uint256 private MAX_UINT = 2**256 - 1; address public gravity; uint8 private cosmosDecimals; mapping(address => mapping(address => uint256)) private _allowances; modifier onlyGravity() { require(msg.sender == gravity, "Not gravity"); _; } constructor( address _gravityAddress, string memory _name, string memory _symbol, uint8 _decimals ) public ERC20(_name, _symbol) { cosmosDecimals = _decimals; gravity = _gravityAddress; _mint(_gravityAddress, MAX_UINT); } // This is not an accurate total supply. Instead this is the total supply // of the given cosmos asset on Ethereum at this moment in time. Keeping // a totally accurate supply would require constant updates from the Cosmos // side, while in theory this could be piggy-backed on some existing bridge // operation it's a lot of complextiy to add so we chose to forgoe it. /** * @dev Returns the number of tokens not currently held by the gravity address * */ function totalSupply() public view virtual override returns (uint256) { return MAX_UINT - balanceOf(gravity); } /** * @dev Sets the gravity contract to a new address. * * Requirements: * * - `msg.sender` must be the current gravity contract */ function setGravityContract(address _gravityAddress) external onlyGravity { gravity = _gravityAddress; } /** * @dev Overrides the decimal function in the base ERC20 contract. * This override is needed to Ethereum wallets display tokens consistently * with how Cosmos wallets display the native version of the token. */ function decimals()public view override returns (uint8){ return cosmosDecimals; } } // File contracts/Gravity.sol pragma solidity 0.8.10; error InvalidSignature(); error InvalidValsetNonce(uint256 newNonce, uint256 currentNonce); error InvalidBatchNonce(uint256 newNonce, uint256 currentNonce); error InvalidLogicCallNonce(uint256 newNonce, uint256 currentNonce); error InvalidLogicCallTransfers(); error InvalidLogicCallFees(); error InvalidSendToCosmos(); error IncorrectCheckpoint(); error MalformedNewValidatorSet(); error MalformedCurrentValidatorSet(); error MalformedBatch(); error InsufficientPower(uint256 cumulativePower, uint256 powerThreshold); error BatchTimedOut(); error LogicCallTimedOut(); // This is being used purely to avoid stack too deep errors struct LogicCallArgs { // Transfers out to the logic contract uint256[] transferAmounts; address[] transferTokenContracts; // The fees (transferred to msg.sender) uint256[] feeAmounts; address[] feeTokenContracts; // The arbitrary logic call address logicContractAddress; bytes payload; // Invalidation metadata uint256 timeOut; bytes32 invalidationId; uint256 invalidationNonce; } // This is used purely to avoid stack too deep errors // represents everything about a given validator set struct ValsetArgs { // the validators in this set, represented by an Ethereum address address[] validators; // the powers of the given validators in the same order as above uint256[] powers; // the nonce of this validator set uint256 valsetNonce; // the reward amount denominated in the below reward token, can be // set to zero uint256 rewardAmount; // the reward token, should be set to the zero address if not being used address rewardToken; } struct ValSignature { uint8 v; bytes32 r; bytes32 s; } contract Gravity is ReentrancyGuard { using SafeMath for uint256; using SafeERC20 for IERC20; // These are updated often bytes32 public state_lastValsetCheckpoint; mapping(address => uint256) public state_lastBatchNonces; mapping(bytes32 => uint256) public state_invalidationMapping; uint256 public state_lastValsetNonce = 0; // event nonce zero is reserved by the Cosmos module as a special // value indicating that no events have yet been submitted uint256 public state_lastEventNonce = 1; // These are set once at initialization uint256 public state_powerThreshold; // This is set once at initialization bytes32 public immutable state_gravityId; // TransactionBatchExecutedEvent and SendToCosmosEvent both include the field _eventNonce. // This is incremented every time one of these events is emitted. It is checked by the // Cosmos module to ensure that all events are received in order, and that none are lost. // // ValsetUpdatedEvent does not include the field _eventNonce because it is never submitted to the Cosmos // module. It is purely for the use of relayers to allow them to successfully submit batches. event TransactionBatchExecutedEvent( uint256 indexed _batchNonce, address indexed _token, uint256 _eventNonce ); event SendToCosmosEvent( address indexed _tokenContract, address indexed _sender, bytes32 indexed _destination, uint256 _amount, uint256 _eventNonce ); event ERC20DeployedEvent( // FYI: Can't index on a string without doing a bunch of weird stuff string _cosmosDenom, address indexed _tokenContract, string _name, string _symbol, uint8 _decimals, uint256 _eventNonce ); event ValsetUpdatedEvent( uint256 indexed _newValsetNonce, uint256 _eventNonce, uint256 _rewardAmount, address _rewardToken, address[] _validators, uint256[] _powers ); event LogicCallEvent( bytes32 _invalidationId, uint256 _invalidationNonce, bytes _returnData, uint256 _eventNonce ); // TEST FIXTURES // These are here to make it easier to measure gas usage. They should be removed before production function testMakeCheckpoint(ValsetArgs calldata _valsetArgs, bytes32 _gravityId) external pure { makeCheckpoint(_valsetArgs, _gravityId); } function testCheckValidatorSignatures( ValsetArgs calldata _currentValset, ValSignature[] calldata _sigs, bytes32 _theHash, uint256 _powerThreshold ) external pure { checkValidatorSignatures(_currentValset, _sigs, _theHash, _powerThreshold); } // END TEST FIXTURES function lastBatchNonce(address _erc20Address) external view returns (uint256) { return state_lastBatchNonces[_erc20Address]; } function lastLogicCallNonce(bytes32 _invalidation_id) external view returns (uint256) { return state_invalidationMapping[_invalidation_id]; } // Utility function to verify geth style signatures function verifySig( address _signer, bytes32 _theHash, ValSignature calldata _sig ) private pure returns (bool) { bytes32 messageDigest = keccak256( abi.encodePacked("\x19Ethereum Signed Message:\n32", _theHash) ); return _signer == ECDSA.recover(messageDigest, _sig.v, _sig.r, _sig.s); } // Utility function to determine that a validator set and signatures are well formed function validateValset(ValsetArgs calldata _valset, ValSignature[] calldata _sigs) private pure { // Check that current validators, powers, and signatures (v,r,s) set is well-formed if ( _valset.validators.length != _valset.powers.length || _valset.validators.length != _sigs.length ) { revert MalformedCurrentValidatorSet(); } } // Make a new checkpoint from the supplied validator set // A checkpoint is a hash of all relevant information about the valset. This is stored by the contract, // instead of storing the information directly. This saves on storage and gas. // The format of the checkpoint is: // h(gravityId, "checkpoint", valsetNonce, validators[], powers[]) // Where h is the keccak256 hash function. // The validator powers must be decreasing or equal. This is important for checking the signatures on the // next valset, since it allows the caller to stop verifying signatures once a quorum of signatures have been verified. function makeCheckpoint(ValsetArgs memory _valsetArgs, bytes32 _gravityId) private pure returns (bytes32) { // bytes32 encoding of the string "checkpoint" bytes32 methodName = 0x636865636b706f696e7400000000000000000000000000000000000000000000; bytes32 checkpoint = keccak256( abi.encode( _gravityId, methodName, _valsetArgs.valsetNonce, _valsetArgs.validators, _valsetArgs.powers, _valsetArgs.rewardAmount, _valsetArgs.rewardToken ) ); return checkpoint; } function checkValidatorSignatures( // The current validator set and their powers ValsetArgs calldata _currentValset, // The current validator's signatures ValSignature[] calldata _sigs, // This is what we are checking they have signed bytes32 _theHash, uint256 _powerThreshold ) private pure { uint256 cumulativePower = 0; for (uint256 i = 0; i < _currentValset.validators.length; i++) { // If v is set to 0, this signifies that it was not possible to get a signature from this validator and we skip evaluation // (In a valid signature, it is either 27 or 28) if (_sigs[i].v != 0) { // Check that the current validator has signed off on the hash if (!verifySig(_currentValset.validators[i], _theHash, _sigs[i])) { revert InvalidSignature(); } // Sum up cumulative power cumulativePower = cumulativePower + _currentValset.powers[i]; // Break early to avoid wasting gas if (cumulativePower > _powerThreshold) { break; } } } // Check that there was enough power if (cumulativePower <= _powerThreshold) { revert InsufficientPower(cumulativePower, _powerThreshold); } // Success } // This updates the valset by checking that the validators in the current valset have signed off on the // new valset. The signatures supplied are the signatures of the current valset over the checkpoint hash // generated from the new valset. // Anyone can call this function, but they must supply valid signatures of state_powerThreshold of the current valset over // the new valset. function updateValset( // The new version of the validator set ValsetArgs calldata _newValset, // The current validators that approve the change ValsetArgs calldata _currentValset, // These are arrays of the parts of the current validator's signatures ValSignature[] calldata _sigs ) external { // CHECKS // Check that the valset nonce is greater than the old one if (_newValset.valsetNonce <= _currentValset.valsetNonce) { revert InvalidValsetNonce({ newNonce: _newValset.valsetNonce, currentNonce: _currentValset.valsetNonce }); } // Check that the valset nonce is less than a million nonces forward from the old one // this makes it difficult for an attacker to lock out the contract by getting a single // bad validator set through with uint256 max nonce if (_newValset.valsetNonce > _currentValset.valsetNonce + 1000000) { revert InvalidValsetNonce({ newNonce: _newValset.valsetNonce, currentNonce: _currentValset.valsetNonce }); } // Check that new validators and powers set is well-formed if ( _newValset.validators.length != _newValset.powers.length || _newValset.validators.length == 0 ) { revert MalformedNewValidatorSet(); } // Check that current validators, powers, and signatures (v,r,s) set is well-formed validateValset(_currentValset, _sigs); // Check cumulative power to ensure the contract has sufficient power to actually // pass a vote uint256 cumulativePower = 0; for (uint256 i = 0; i < _newValset.powers.length; i++) { cumulativePower = cumulativePower + _newValset.powers[i]; if (cumulativePower > state_powerThreshold) { break; } } if (cumulativePower <= state_powerThreshold) { revert InsufficientPower({ cumulativePower: cumulativePower, powerThreshold: state_powerThreshold }); } // Check that the supplied current validator set matches the saved checkpoint if (makeCheckpoint(_currentValset, state_gravityId) != state_lastValsetCheckpoint) { revert IncorrectCheckpoint(); } // Check that enough current validators have signed off on the new validator set bytes32 newCheckpoint = makeCheckpoint(_newValset, state_gravityId); checkValidatorSignatures(_currentValset, _sigs, newCheckpoint, state_powerThreshold); // ACTIONS // Stored to be used next time to validate that the valset // supplied by the caller is correct. state_lastValsetCheckpoint = newCheckpoint; // Store new nonce state_lastValsetNonce = _newValset.valsetNonce; // Send submission reward to msg.sender if reward token is a valid value if (_newValset.rewardToken != address(0) && _newValset.rewardAmount != 0) { IERC20(_newValset.rewardToken).safeTransfer(msg.sender, _newValset.rewardAmount); } // LOGS state_lastEventNonce = state_lastEventNonce + 1; emit ValsetUpdatedEvent( _newValset.valsetNonce, state_lastEventNonce, _newValset.rewardAmount, _newValset.rewardToken, _newValset.validators, _newValset.powers ); } // submitBatch processes a batch of Cosmos -> Ethereum transactions by sending the tokens in the transactions // to the destination addresses. It is approved by the current Cosmos validator set. // Anyone can call this function, but they must supply valid signatures of state_powerThreshold of the current valset over // the batch. function submitBatch( // The validators that approve the batch ValsetArgs calldata _currentValset, // These are arrays of the parts of the validators signatures ValSignature[] calldata _sigs, // The batch of transactions uint256[] calldata _amounts, address[] calldata _destinations, uint256[] calldata _fees, uint256 _batchNonce, address _tokenContract, // a block height beyond which this batch is not valid // used to provide a fee-free timeout uint256 _batchTimeout ) external nonReentrant { // CHECKS scoped to reduce stack depth { // Check that the batch nonce is higher than the last nonce for this token if (_batchNonce <= state_lastBatchNonces[_tokenContract]) { revert InvalidBatchNonce({ newNonce: _batchNonce, currentNonce: state_lastBatchNonces[_tokenContract] }); } // Check that the batch nonce is less than one million nonces forward from the old one // this makes it difficult for an attacker to lock out the contract by getting a single // bad batch through with uint256 max nonce if (_batchNonce > state_lastBatchNonces[_tokenContract] + 1000000) { revert InvalidBatchNonce({ newNonce: _batchNonce, currentNonce: state_lastBatchNonces[_tokenContract] }); } // Check that the block height is less than the timeout height if (block.number >= _batchTimeout) { revert BatchTimedOut(); } // Check that current validators, powers, and signatures (v,r,s) set is well-formed validateValset(_currentValset, _sigs); // Check that the supplied current validator set matches the saved checkpoint if (makeCheckpoint(_currentValset, state_gravityId) != state_lastValsetCheckpoint) { revert IncorrectCheckpoint(); } // Check that the transaction batch is well-formed if (_amounts.length != _destinations.length || _amounts.length != _fees.length) { revert MalformedBatch(); } // Check that enough current validators have signed off on the transaction batch and valset checkValidatorSignatures( _currentValset, _sigs, // Get hash of the transaction batch and checkpoint keccak256( abi.encode( state_gravityId, // bytes32 encoding of "transactionBatch" 0x7472616e73616374696f6e426174636800000000000000000000000000000000, _amounts, _destinations, _fees, _batchNonce, _tokenContract, _batchTimeout ) ), state_powerThreshold ); // ACTIONS // Store batch nonce state_lastBatchNonces[_tokenContract] = _batchNonce; { // Send transaction amounts to destinations uint256 totalFee; for (uint256 i = 0; i < _amounts.length; i++) { IERC20(_tokenContract).safeTransfer(_destinations[i], _amounts[i]); totalFee = totalFee + _fees[i]; } // Send transaction fees to msg.sender IERC20(_tokenContract).safeTransfer(msg.sender, totalFee); } } // LOGS scoped to reduce stack depth { state_lastEventNonce = state_lastEventNonce + 1; emit TransactionBatchExecutedEvent(_batchNonce, _tokenContract, state_lastEventNonce); } } // This makes calls to contracts that execute arbitrary logic // First, it gives the logic contract some tokens // Then, it gives msg.senders tokens for fees // Then, it calls an arbitrary function on the logic contract // invalidationId and invalidationNonce are used for replay prevention. // They can be used to implement a per-token nonce by setting the token // address as the invalidationId and incrementing the nonce each call. // They can be used for nonce-free replay prevention by using a different invalidationId // for each call. function submitLogicCall( // The validators that approve the call ValsetArgs calldata _currentValset, // These are arrays of the parts of the validators signatures ValSignature[] calldata _sigs, LogicCallArgs memory _args ) external nonReentrant { // CHECKS scoped to reduce stack depth { // Check that the call has not timed out if (block.number >= _args.timeOut) { revert LogicCallTimedOut(); } // Check that the invalidation nonce is higher than the last nonce for this invalidation Id if (state_invalidationMapping[_args.invalidationId] >= _args.invalidationNonce) { revert InvalidLogicCallNonce({ newNonce: _args.invalidationNonce, currentNonce: state_invalidationMapping[_args.invalidationId] }); } // note the lack of nonce skipping check, it's not needed here since an attacker // will never be able to fill the invalidationId space, therefore a nonce lockout // is simply not possible // Check that current validators, powers, and signatures (v,r,s) set is well-formed validateValset(_currentValset, _sigs); // Check that the supplied current validator set matches the saved checkpoint if (makeCheckpoint(_currentValset, state_gravityId) != state_lastValsetCheckpoint) { revert IncorrectCheckpoint(); } if (_args.transferAmounts.length != _args.transferTokenContracts.length) { revert InvalidLogicCallTransfers(); } if (_args.feeAmounts.length != _args.feeTokenContracts.length) { revert InvalidLogicCallFees(); } } { bytes32 argsHash = keccak256( abi.encode( state_gravityId, // bytes32 encoding of "logicCall" 0x6c6f67696343616c6c0000000000000000000000000000000000000000000000, _args.transferAmounts, _args.transferTokenContracts, _args.feeAmounts, _args.feeTokenContracts, _args.logicContractAddress, _args.payload, _args.timeOut, _args.invalidationId, _args.invalidationNonce ) ); // Check that enough current validators have signed off on the transaction batch and valset checkValidatorSignatures( _currentValset, _sigs, // Get hash of the transaction batch and checkpoint argsHash, state_powerThreshold ); } // ACTIONS // Update invaldiation nonce state_invalidationMapping[_args.invalidationId] = _args.invalidationNonce; // Send tokens to the logic contract for (uint256 i = 0; i < _args.transferAmounts.length; i++) { IERC20(_args.transferTokenContracts[i]).safeTransfer( _args.logicContractAddress, _args.transferAmounts[i] ); } // Make call to logic contract bytes memory returnData = Address.functionCall(_args.logicContractAddress, _args.payload); // Send fees to msg.sender for (uint256 i = 0; i < _args.feeAmounts.length; i++) { IERC20(_args.feeTokenContracts[i]).safeTransfer(msg.sender, _args.feeAmounts[i]); } // LOGS scoped to reduce stack depth { state_lastEventNonce = state_lastEventNonce + 1; emit LogicCallEvent( _args.invalidationId, _args.invalidationNonce, returnData, state_lastEventNonce ); } } function sendToCosmos( address _tokenContract, bytes32 _destination, uint256 _amount ) public nonReentrant { // we snapshot our current balance of this token uint256 ourStartingBalance = IERC20(_tokenContract).balanceOf(address(this)); // attempt to transfer the user specified amount IERC20(_tokenContract).safeTransferFrom(msg.sender, address(this), _amount); // check what this particular ERC20 implementation actually gave us, since it doesn't // have to be at all related to the _amount uint256 ourEndingBalance = IERC20(_tokenContract).balanceOf(address(this)); // a very strange ERC20 may trigger this condition, if we didn't have this we would // underflow, so it's mostly just an error message printer if (ourEndingBalance <= ourStartingBalance) { revert InvalidSendToCosmos(); } state_lastEventNonce = state_lastEventNonce + 1; // emit to Cosmos the actual amount our balance has changed, rather than the user // provided amount. This protects against a small set of wonky ERC20 behavior, like // burning on send but not tokens that for example change every users balance every day. emit SendToCosmosEvent( _tokenContract, msg.sender, _destination, ourEndingBalance - ourStartingBalance, state_lastEventNonce ); } function deployERC20( string calldata _cosmosDenom, string calldata _name, string calldata _symbol, uint8 _decimals ) external { // Deploy an ERC20 with entire supply granted to Gravity.sol CosmosERC20 erc20 = new CosmosERC20(address(this), _name, _symbol, _decimals); // Fire an event to let the Cosmos module know state_lastEventNonce = state_lastEventNonce.add(1); emit ERC20DeployedEvent( _cosmosDenom, address(erc20), _name, _symbol, _decimals, state_lastEventNonce ); } constructor( // A unique identifier for this gravity instance to use in signatures bytes32 _gravityId, // How much voting power is needed to approve operations uint256 _powerThreshold, // The validator set address[] memory _validators, uint256[] memory _powers ) public { // CHECKS // Check that validators, powers, and signatures (v,r,s) set is well-formed if (_validators.length != _powers.length) { revert MalformedCurrentValidatorSet(); } // Check cumulative power to ensure the contract has sufficient power to actually // pass a vote uint256 cumulativePower = 0; for (uint256 i = 0; i < _powers.length; i++) { cumulativePower = cumulativePower + _powers[i]; if (cumulativePower > _powerThreshold) { break; } } if (cumulativePower <= _powerThreshold) { revert InsufficientPower({ cumulativePower: cumulativePower, powerThreshold: _powerThreshold }); } ValsetArgs memory _valset; _valset = ValsetArgs(_validators, _powers, 0, 0, address(0)); bytes32 newCheckpoint = makeCheckpoint(_valset, _gravityId); // ACTIONS state_gravityId = _gravityId; state_powerThreshold = _powerThreshold; state_lastValsetCheckpoint = newCheckpoint; // LOGS emit ValsetUpdatedEvent( state_lastValsetNonce, state_lastEventNonce, 0, address(0), _validators, _powers ); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"bytes32","name":"_gravityId","type":"bytes32"},{"internalType":"uint256","name":"_powerThreshold","type":"uint256"},{"internalType":"address[]","name":"_validators","type":"address[]"},{"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BatchTimedOut","type":"error"},{"inputs":[],"name":"IncorrectCheckpoint","type":"error"},{"inputs":[{"internalType":"uint256","name":"cumulativePower","type":"uint256"},{"internalType":"uint256","name":"powerThreshold","type":"uint256"}],"name":"InsufficientPower","type":"error"},{"inputs":[{"internalType":"uint256","name":"newNonce","type":"uint256"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidBatchNonce","type":"error"},{"inputs":[],"name":"InvalidLogicCallFees","type":"error"},{"inputs":[{"internalType":"uint256","name":"newNonce","type":"uint256"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidLogicCallNonce","type":"error"},{"inputs":[],"name":"InvalidLogicCallTransfers","type":"error"},{"inputs":[],"name":"InvalidSendToCosmos","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"newNonce","type":"uint256"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidValsetNonce","type":"error"},{"inputs":[],"name":"LogicCallTimedOut","type":"error"},{"inputs":[],"name":"MalformedBatch","type":"error"},{"inputs":[],"name":"MalformedCurrentValidatorSet","type":"error"},{"inputs":[],"name":"MalformedNewValidatorSet","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"_cosmosDenom","type":"string"},{"indexed":true,"internalType":"address","name":"_tokenContract","type":"address"},{"indexed":false,"internalType":"string","name":"_name","type":"string"},{"indexed":false,"internalType":"string","name":"_symbol","type":"string"},{"indexed":false,"internalType":"uint8","name":"_decimals","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"_eventNonce","type":"uint256"}],"name":"ERC20DeployedEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_invalidationId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_invalidationNonce","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"_returnData","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"_eventNonce","type":"uint256"}],"name":"LogicCallEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_tokenContract","type":"address"},{"indexed":true,"internalType":"address","name":"_sender","type":"address"},{"indexed":true,"internalType":"bytes32","name":"_destination","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_eventNonce","type":"uint256"}],"name":"SendToCosmosEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_batchNonce","type":"uint256"},{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_eventNonce","type":"uint256"}],"name":"TransactionBatchExecutedEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_newValsetNonce","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_eventNonce","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_rewardAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"_rewardToken","type":"address"},{"indexed":false,"internalType":"address[]","name":"_validators","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"ValsetUpdatedEvent","type":"event"},{"inputs":[{"internalType":"string","name":"_cosmosDenom","type":"string"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint8","name":"_decimals","type":"uint8"}],"name":"deployERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_erc20Address","type":"address"}],"name":"lastBatchNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_invalidation_id","type":"bytes32"}],"name":"lastLogicCallNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenContract","type":"address"},{"internalType":"bytes32","name":"_destination","type":"bytes32"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"sendToCosmos","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"state_gravityId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"state_invalidationMapping","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"state_lastBatchNonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state_lastEventNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state_lastValsetCheckpoint","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state_lastValsetNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state_powerThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address[]","name":"validators","type":"address[]"},{"internalType":"uint256[]","name":"powers","type":"uint256[]"},{"internalType":"uint256","name":"valsetNonce","type":"uint256"},{"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"internalType":"address","name":"rewardToken","type":"address"}],"internalType":"struct ValsetArgs","name":"_currentValset","type":"tuple"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct ValSignature[]","name":"_sigs","type":"tuple[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"address[]","name":"_destinations","type":"address[]"},{"internalType":"uint256[]","name":"_fees","type":"uint256[]"},{"internalType":"uint256","name":"_batchNonce","type":"uint256"},{"internalType":"address","name":"_tokenContract","type":"address"},{"internalType":"uint256","name":"_batchTimeout","type":"uint256"}],"name":"submitBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address[]","name":"validators","type":"address[]"},{"internalType":"uint256[]","name":"powers","type":"uint256[]"},{"internalType":"uint256","name":"valsetNonce","type":"uint256"},{"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"internalType":"address","name":"rewardToken","type":"address"}],"internalType":"struct ValsetArgs","name":"_currentValset","type":"tuple"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct ValSignature[]","name":"_sigs","type":"tuple[]"},{"components":[{"internalType":"uint256[]","name":"transferAmounts","type":"uint256[]"},{"internalType":"address[]","name":"transferTokenContracts","type":"address[]"},{"internalType":"uint256[]","name":"feeAmounts","type":"uint256[]"},{"internalType":"address[]","name":"feeTokenContracts","type":"address[]"},{"internalType":"address","name":"logicContractAddress","type":"address"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"uint256","name":"timeOut","type":"uint256"},{"internalType":"bytes32","name":"invalidationId","type":"bytes32"},{"internalType":"uint256","name":"invalidationNonce","type":"uint256"}],"internalType":"struct LogicCallArgs","name":"_args","type":"tuple"}],"name":"submitLogicCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address[]","name":"validators","type":"address[]"},{"internalType":"uint256[]","name":"powers","type":"uint256[]"},{"internalType":"uint256","name":"valsetNonce","type":"uint256"},{"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"internalType":"address","name":"rewardToken","type":"address"}],"internalType":"struct ValsetArgs","name":"_currentValset","type":"tuple"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct ValSignature[]","name":"_sigs","type":"tuple[]"},{"internalType":"bytes32","name":"_theHash","type":"bytes32"},{"internalType":"uint256","name":"_powerThreshold","type":"uint256"}],"name":"testCheckValidatorSignatures","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"address[]","name":"validators","type":"address[]"},{"internalType":"uint256[]","name":"powers","type":"uint256[]"},{"internalType":"uint256","name":"valsetNonce","type":"uint256"},{"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"internalType":"address","name":"rewardToken","type":"address"}],"internalType":"struct ValsetArgs","name":"_valsetArgs","type":"tuple"},{"internalType":"bytes32","name":"_gravityId","type":"bytes32"}],"name":"testMakeCheckpoint","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"address[]","name":"validators","type":"address[]"},{"internalType":"uint256[]","name":"powers","type":"uint256[]"},{"internalType":"uint256","name":"valsetNonce","type":"uint256"},{"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"internalType":"address","name":"rewardToken","type":"address"}],"internalType":"struct ValsetArgs","name":"_newValset","type":"tuple"},{"components":[{"internalType":"address[]","name":"validators","type":"address[]"},{"internalType":"uint256[]","name":"powers","type":"uint256[]"},{"internalType":"uint256","name":"valsetNonce","type":"uint256"},{"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"internalType":"address","name":"rewardToken","type":"address"}],"internalType":"struct ValsetArgs","name":"_currentValset","type":"tuple"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct ValSignature[]","name":"_sigs","type":"tuple[]"}],"name":"updateValset","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a0604052600060045560016005553480156200001b57600080fd5b5060405162003b5e38038062003b5e8339810160408190526200003e916200031d565b60016000558051825114620000665760405163c6617b7b60e01b815260040160405180910390fd5b6000805b8251811015620000c45782818151811062000089576200008962000410565b6020026020010151826200009e91906200043c565b915084821115620000af57620000c4565b80620000bb8162000457565b9150506200006a565b50838111620000f35760405162bfb6ab60e01b8152600481018290526024810185905260440160405180910390fd5b6200012f6040518060a001604052806060815260200160608152602001600081526020016000815260200160006001600160a01b031681525090565b506040805160a081018252848152602081018490526000918101829052606081018290526080810182905290620001678288620001cf565b60808890526006879055600181905560045460055460405192935090917f76d08978c024a4bf8cbb30c67fd78fcaa1827cbc533e4e175f36d07e64ccf96a91620001ba9160009081908b908b90620004ed565b60405180910390a2505050505050506200059c565b6000806918da1958dadc1bda5b9d60b21b60001b90506000838286604001518760000151886020015189606001518a608001516040516020016200021a97969594939291906200053c565b60408051808303601f19018152919052805160209091012095945050505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156200027c576200027c6200023b565b604052919050565b60006001600160401b03821115620002a057620002a06200023b565b5060051b60200190565b600082601f830112620002bc57600080fd5b81516020620002d5620002cf8362000284565b62000251565b82815260059290921b84018101918181019086841115620002f557600080fd5b8286015b84811015620003125780518352918301918301620002f9565b509695505050505050565b600080600080608085870312156200033457600080fd5b845160208087015160408801519296509450906001600160401b03808211156200035d57600080fd5b818801915088601f8301126200037257600080fd5b815162000383620002cf8262000284565b81815260059190911b8301840190848101908b831115620003a357600080fd5b938501935b82851015620003da5784516001600160a01b0381168114620003ca5760008081fd5b82529385019390850190620003a8565b60608b01519097509450505080831115620003f457600080fd5b50506200040487828801620002aa565b91505092959194509250565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000821982111562000452576200045262000426565b500190565b60006000198214156200046e576200046e62000426565b5060010190565b600081518084526020808501945080840160005b83811015620004b05781516001600160a01b03168752958201959082019060010162000489565b509495945050505050565b600081518084526020808501945080840160005b83811015620004b057815187529582019590820190600101620004cf565b85815284602082015260018060a01b038416604082015260a0606082015260006200051c60a083018562000475565b8281036080840152620005308185620004bb565b98975050505050505050565b87815286602082015285604082015260e0606082015260006200056360e083018762000475565b8281036080840152620005778187620004bb565b60a084019590955250506001600160a01b039190911660c09091015295945050505050565b608051613591620005cd60003960008181610220015281816105700152818161060b01526109c501526135916000f3fe60806040523480156200001157600080fd5b5060043610620001145760003560e01c8063aca6b1c111620000a3578063df97174b116200006e578063df97174b1462000265578063e5a2b5d21462000288578063f2b533071462000292578063f7955637146200029c57600080fd5b8063aca6b1c114620001f9578063b56561fe1462000210578063bdda81d4146200021a578063c9d194d5146200024257600080fd5b80636941db9311620000e45780636941db93146200019e57806373b2054714620001b55780637dfb6f8614620001bf5780638690ff9814620001e257600080fd5b80629011531462000119578063010315251462000132578063011b217414620001495780631ffbe7f91462000187575b600080fd5b620001306200012a366004620018aa565b620002b3565b005b62000130620001433660046200192b565b620002c9565b620001756200015a36600462001990565b6001600160a01b031660009081526002602052604090205490565b60405190815260200160405180910390f35b6200013062000198366004620019ae565b620002e4565b62000130620001af36600462001bd3565b620004a2565b6200017560055481565b62000175620001d036600462001d6f565b60036020526000908152604090205481565b62000130620001f336600462001dd0565b62000835565b620001306200020a36600462001f09565b62000b88565b6200017560045481565b620001757f000000000000000000000000000000000000000000000000000000000000000081565b620001756200025336600462001d6f565b60009081526003602052604090205490565b620001756200027636600462001990565b60026020526000908152604090205481565b6200017560065481565b6200017560015481565b62000130620002ad36600462001ff3565b62000e72565b620002c2858585858562000f2a565b5050505050565b620002df620002d883620020a9565b8262001084565b505050565b60026000541415620003135760405162461bcd60e51b81526004016200030a906200215f565b60405180910390fd5b600260009081556040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa1580156200035f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000385919062002196565b90506200039e6001600160a01b038516333085620010f0565b6040516370a0823160e01b81523060048201526000906001600160a01b038616906370a0823190602401602060405180830381865afa158015620003e6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200040c919062002196565b90508181116200042f576040516321739d9b60e01b815260040160405180910390fd5b6005546200043f906001620021c6565b60055583336001600160a01b0387167fd7767894d73c589daeca9643f445f03d7be61aad2950c117e7cbff4176fca7e46200047b8686620021e1565b6005546040805192835260208301919091520160405180910390a450506001600055505050565b60026000541415620004c85760405162461bcd60e51b81526004016200030a906200215f565b600260005560c08101514310620004f25760405163bcf37c2560e01b815260040160405180910390fd5b61010081015160e0820151600090815260036020526040902054106200054f5761010081015160e082015160009081526003602052604090819020549051629427e960e11b8152600481019290925260248201526044016200030a565b6200055c84848462001163565b600154620005956200056e86620020a9565b7f000000000000000000000000000000000000000000000000000000000000000062001084565b14620005b45760405163723a340360e01b815260040160405180910390fd5b60208101515181515114620005dc57604051634298a95160e11b815260040160405180910390fd5b806060015151816040015151146200060757604051634829247960e01b815260040160405180910390fd5b60007f0000000000000000000000000000000000000000000000000000000000000000681b1bd9da58d0d85b1b60ba1b836000015184602001518560400151866060015187608001518860a001518960c001518a60e001518b6101000151604051602001620006819b9a99989796959493929190620022d0565b604051602081830303815290604052805190602001209050620006aa8585858460065462000f2a565b5061010081015160e08201516000908152600360205260408120919091555b8151518110156200074d5762000738826080015183600001518381518110620006f657620006f662002380565b60200260200101518460200151848151811062000717576200071762002380565b60200260200101516001600160a01b0316620011bc9092919063ffffffff16565b80620007448162002396565b915050620006c9565b5060006200076482608001518360a00151620011ee565b905060005b826040015151811015620007cb57620007b6338460400151838151811062000795576200079562002380565b60200260200101518560600151848151811062000717576200071762002380565b80620007c28162002396565b91505062000769565b50600554620007dc906001620021c6565b600581905560e08301516101008401516040517f7c2bb24f8e1b3725cb613d7f11ef97d9745cc97a0e40f730621c052d684077a19362000821939291869190620023b4565b60405180910390a150506001600055505050565b600260005414156200085b5760405162461bcd60e51b81526004016200030a906200215f565b600260008181556001600160a01b038416815260209190915260409020548311620008bf576001600160a01b0382166000908152600260205260409081902054905163f7f920ad60e01b81526200030a918591600401918252602082015260400190565b6001600160a01b038216600090815260026020526040902054620008e790620f4240620021c6565b8311156200092e576001600160a01b0382166000908152600260205260409081902054905163f7f920ad60e01b81526200030a918591600401918252602082015260400190565b8043106200094f576040516308b9266360e11b815260040160405180910390fd5b6200095c8c8c8c62001163565b6001546200096e6200056e8e620020a9565b146200098d5760405163723a340360e01b815260040160405180910390fd5b87861415806200099d5750878414155b15620009bc5760405163c1f97e3560e01b815260040160405180910390fd5b62000a3c8c8c8c7f00000000000000000000000000000000000000000000000000000000000000006f0e8e4c2dce6c2c6e8d2dedc84c2e8c6d60831b8e8e8e8e8e8e8e8e8e60405160200162000a1d9b9a999897969594939291906200245d565b6040516020818303038152906040528051906020012060065462000f2a565b6001600160a01b0382166000908152600260205260408120849055805b8981101562000b085762000ac889898381811062000a7b5762000a7b62002380565b905060200201602081019062000a92919062001990565b8c8c8481811062000aa75762000aa762002380565b90506020020135866001600160a01b0316620011bc9092919063ffffffff16565b86868281811062000add5762000add62002380565b905060200201358262000af19190620021c6565b91508062000aff8162002396565b91505062000a59565b5062000b1f6001600160a01b0384163383620011bc565b5060055462000b30906001620021c6565b60058190556040519081526001600160a01b0383169084907f02c7e81975f8edb86e2a0c038b7b86a49c744236abf0f6177ff5afc6986ab7089060200160405180910390a35050600160005550505050505050505050565b826040013584604001351162000bc1576040805163e0e8edf360e01b81528186013560048201529084013560248201526044016200030a565b62000bd46040840135620f4240620021c6565b8460400135111562000c09576040805163e0e8edf360e01b81528186013560048201529084013560248201526044016200030a565b62000c186020850185620024db565b905062000c268580620024db565b905014158062000c41575062000c3d8480620024db565b1590505b1562000c605760405163c01ba0ab60e01b815260040160405180910390fd5b62000c6d83838362001163565b6000805b62000c806020870187620024db565b905081101562000ce85762000c996020870187620024db565b8281811062000cac5762000cac62002380565b905060200201358262000cc09190620021c6565b915060065482111562000cd35762000ce8565b8062000cdf8162002396565b91505062000c71565b50600654811162000d1a5760065460405162bfb6ab60e01b81526200030a918391600401918252602082015260400190565b60015462000d2c6200056e86620020a9565b1462000d4b5760405163723a340360e01b815260040160405180910390fd5b600062000d5c6200056e87620020a9565b905062000d6f8585858460065462000f2a565b60018190556040860135600455600062000d9060a088016080890162001990565b6001600160a01b03161415801562000dab5750606086013515155b1562000dde5762000dde33606088013562000dcd60a08a0160808b0162001990565b6001600160a01b03169190620011bc565b60055462000dee906001620021c6565b60058190556040870135907f76d08978c024a4bf8cbb30c67fd78fcaa1827cbc533e4e175f36d07e64ccf96a90606089013562000e3260a08b0160808c0162001990565b62000e3e8b80620024db565b62000e4d60208e018e620024db565b60405162000e62979695949392919062002527565b60405180910390a2505050505050565b600030868686868660405162000e889062001835565b62000e9996959493929190620025a3565b604051809103906000f08015801562000eb6573d6000803e3d6000fd5b5060055490915062000eca90600162001239565b60058190556040516001600160a01b038316917f82fe3a4fa49c6382d0c085746698ddbbafe6c2bf61285b19410644b5b26287c79162000f18918c918c918c918c918c918c918c91620025f6565b60405180910390a25050505050505050565b6000805b62000f3a8780620024db565b9050811015620010505785858281811062000f595762000f5962002380565b62000f71926020606090920201908101915062002653565b60ff16156200103b5762000fd662000f8a8880620024db565b8381811062000f9d5762000f9d62002380565b905060200201602081019062000fb4919062001990565b8588888581811062000fca5762000fca62002380565b90506060020162001247565b62000ff457604051638baa579f60e01b815260040160405180910390fd5b620010036020880188620024db565b8281811062001016576200101662002380565b90506020020135826200102a9190620021c6565b9150828211156200103b5762001050565b80620010478162002396565b91505062000f2e565b508181116200107c5760405162bfb6ab60e01b815260048101829052602481018390526044016200030a565b505050505050565b6000806918da1958dadc1bda5b9d60b21b60001b90506000838286604001518760000151886020015189606001518a60800151604051602001620010cf979695949392919062002671565b60408051808303601f19018152919052805160209091012095945050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526200115d9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152620012dc565b50505050565b620011726020840184620024db565b9050620011808480620024db565b90501415806200119d575080620011988480620024db565b905014155b15620002df5760405163c6617b7b60e01b815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052620002df90849063a9059cbb60e01b9060640162001125565b60606200123283836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250620013b5565b9392505050565b6000620012328284620021c6565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018390526000908190605c0160408051601f1981840301815291905280516020918201209150620012be908290620012ae9086018662002653565b85602001358660400135620013ce565b6001600160a01b0316856001600160a01b0316149150509392505050565b600062001333826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620013b59092919063ffffffff16565b805190915015620002df5780806020019051810190620013549190620026d1565b620002df5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016200030a565b6060620013c68484600085620013fa565b949350505050565b6000806000620013e1878787876200152c565b91509150620013f08162001621565b5095945050505050565b6060824710156200145d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016200030a565b843b620014ad5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016200030a565b600080866001600160a01b03168587604051620014cb9190620026f5565b60006040518083038185875af1925050503d80600081146200150a576040519150601f19603f3d011682016040523d82523d6000602084013e6200150f565b606091505b509150915062001521828286620017f7565b979650505050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111562001565575060009050600362001618565b8460ff16601b141580156200157e57508460ff16601c14155b1562001591575060009050600462001618565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015620015e6573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116620016115760006001925092505062001618565b9150600090505b94509492505050565b600081600481111562001638576200163862002713565b1415620016425750565b600181600481111562001659576200165962002713565b1415620016a95760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016200030a565b6002816004811115620016c057620016c062002713565b1415620017105760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016200030a565b600381600481111562001727576200172762002713565b1415620017825760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016200030a565b600481600481111562001799576200179962002713565b1415620017f45760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b60648201526084016200030a565b50565b606083156200180857508162001232565b825115620018195782518084602001fd5b8160405162461bcd60e51b81526004016200030a919062002729565b610e1d806200273f83390190565b600060a082840312156200185657600080fd5b50919050565b60008083601f8401126200186f57600080fd5b5081356001600160401b038111156200188757600080fd5b602083019150836020606083028501011115620018a357600080fd5b9250929050565b600080600080600060808688031215620018c357600080fd5b85356001600160401b0380821115620018db57600080fd5b620018e989838a0162001843565b965060208801359150808211156200190057600080fd5b506200190f888289016200185c565b9699909850959660408101359660609091013595509350505050565b600080604083850312156200193f57600080fd5b82356001600160401b038111156200195657600080fd5b620019648582860162001843565b95602094909401359450505050565b80356001600160a01b03811681146200198b57600080fd5b919050565b600060208284031215620019a357600080fd5b620012328262001973565b600080600060608486031215620019c457600080fd5b620019cf8462001973565b95602085013595506040909401359392505050565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b038111828210171562001a205762001a20620019e4565b60405290565b604051601f8201601f191681016001600160401b038111828210171562001a515762001a51620019e4565b604052919050565b60006001600160401b0382111562001a755762001a75620019e4565b5060051b60200190565b600082601f83011262001a9157600080fd5b8135602062001aaa62001aa48362001a59565b62001a26565b82815260059290921b8401810191818101908684111562001aca57600080fd5b8286015b8481101562001ae7578035835291830191830162001ace565b509695505050505050565b600082601f83011262001b0457600080fd5b8135602062001b1762001aa48362001a59565b82815260059290921b8401810191818101908684111562001b3757600080fd5b8286015b8481101562001ae75762001b4f8162001973565b835291830191830162001b3b565b600082601f83011262001b6f57600080fd5b81356001600160401b0381111562001b8b5762001b8b620019e4565b62001ba0601f8201601f191660200162001a26565b81815284602083860101111562001bb657600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806060858703121562001bea57600080fd5b84356001600160401b038082111562001c0257600080fd5b62001c108883890162001843565b9550602087013591508082111562001c2757600080fd5b62001c35888389016200185c565b9095509350604087013591508082111562001c4f57600080fd5b90860190610120828903121562001c6557600080fd5b62001c6f620019fa565b82358281111562001c7f57600080fd5b62001c8d8a82860162001a7f565b82525060208301358281111562001ca357600080fd5b62001cb18a82860162001af2565b60208301525060408301358281111562001cca57600080fd5b62001cd88a82860162001a7f565b60408301525060608301358281111562001cf157600080fd5b62001cff8a82860162001af2565b60608301525062001d136080840162001973565b608082015260a08301358281111562001d2b57600080fd5b62001d398a82860162001b5d565b60a08301525060c083013560c082015260e083013560e08201526101009150818301358282015280935050505092959194509250565b60006020828403121562001d8257600080fd5b5035919050565b60008083601f84011262001d9c57600080fd5b5081356001600160401b0381111562001db457600080fd5b6020830191508360208260051b8501011115620018a357600080fd5b6000806000806000806000806000806000806101008d8f03121562001df457600080fd5b6001600160401b038d35111562001e0a57600080fd5b62001e198e8e358f0162001843565b9b506001600160401b0360208e0135111562001e3457600080fd5b62001e468e60208f01358f016200185c565b909b5099506001600160401b0360408e0135111562001e6457600080fd5b62001e768e60408f01358f0162001d89565b90995097506001600160401b0360608e0135111562001e9457600080fd5b62001ea68e60608f01358f0162001d89565b90975095506001600160401b0360808e0135111562001ec457600080fd5b62001ed68e60808f01358f0162001d89565b909550935060a08d0135925062001ef060c08e0162001973565b915060e08d013590509295989b509295989b509295989b565b6000806000806060858703121562001f2057600080fd5b84356001600160401b038082111562001f3857600080fd5b62001f468883890162001843565b9550602087013591508082111562001f5d57600080fd5b62001f6b8883890162001843565b9450604087013591508082111562001f8257600080fd5b5062001f91878288016200185c565b95989497509550505050565b60008083601f84011262001fb057600080fd5b5081356001600160401b0381111562001fc857600080fd5b602083019150836020828501011115620018a357600080fd5b803560ff811681146200198b57600080fd5b60008060008060008060006080888a0312156200200f57600080fd5b87356001600160401b03808211156200202757600080fd5b620020358b838c0162001f9d565b909950975060208a01359150808211156200204f57600080fd5b6200205d8b838c0162001f9d565b909750955060408a01359150808211156200207757600080fd5b50620020868a828b0162001f9d565b90945092506200209b90506060890162001fe1565b905092959891949750929550565b600060a08236031215620020bc57600080fd5b60405160a081016001600160401b038282108183111715620020e257620020e2620019e4565b816040528435915080821115620020f857600080fd5b620021063683870162001af2565b835260208501359150808211156200211d57600080fd5b506200212c3682860162001a7f565b6020830152506040830135604082015260608301356060820152620021546080840162001973565b608082015292915050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b600060208284031215620021a957600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115620021dc57620021dc620021b0565b500190565b600082821015620021f657620021f6620021b0565b500390565b600081518084526020808501945080840160005b838110156200222d578151875295820195908201906001016200220f565b509495945050505050565b600081518084526020808501945080840160005b838110156200222d5781516001600160a01b0316875295820195908201906001016200224c565b60005b838110156200229057818101518382015260200162002276565b838111156200115d5750506000910152565b60008151808452620022bc81602086016020860162002273565b601f01601f19169290920160200192915050565b60006101608d83528c6020840152806040840152620022f28184018d620021fb565b9050828103606084015262002308818c62002238565b905082810360808401526200231e818b620021fb565b905082810360a084015262002334818a62002238565b6001600160a01b03891660c085015283810360e08501529050620023598188620022a2565b61010084019690965250506101208101929092526101409091015298975050505050505050565b634e487b7160e01b600052603260045260246000fd5b6000600019821415620023ad57620023ad620021b0565b5060010190565b848152836020820152608060408201526000620023d56080830185620022a2565b905082606083015295945050505050565b81835260006001600160fb1b038311156200240057600080fd5b8260051b8083602087013760009401602001938452509192915050565b8183526000602080850194508260005b858110156200222d576001600160a01b03620024498362001973565b16875295820195908201906001016200242d565b60006101008d83528c6020840152806040840152620024808184018c8e620023e6565b9050828103606084015262002497818a8c6200241d565b90508281036080840152620024ae81888a620023e6565b60a084019690965250506001600160a01b039290921660c083015260e09091015298975050505050505050565b6000808335601e19843603018112620024f357600080fd5b8301803591506001600160401b038211156200250e57600080fd5b6020019150600581901b3603821315620018a357600080fd5b87815286602082015260018060a01b038616604082015260a0606082015260006200255760a0830186886200241d565b82810360808401526200256c818587620023e6565b9a9950505050505050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0387168152608060208201819052600090620025ca90830187896200257a565b8281036040840152620025df8186886200257a565b91505060ff83166060830152979650505050505050565b60a0815260006200260c60a083018a8c6200257a565b82810360208401526200262181898b6200257a565b90508281036040840152620026388187896200257a565b60ff9590951660608401525050608001529695505050505050565b6000602082840312156200266657600080fd5b620012328262001fe1565b87815286602082015285604082015260e0606082015260006200269860e083018762002238565b8281036080840152620026ac8187620021fb565b60a084019590955250506001600160a01b039190911660c09091015295945050505050565b600060208284031215620026e457600080fd5b815180151581146200123257600080fd5b600082516200270981846020870162002273565b9190910192915050565b634e487b7160e01b600052602160045260246000fd5b602081526000620012326020830184620022a256fe60806040526000196005553480156200001757600080fd5b5060405162000e1d38038062000e1d8339810160408190526200003a9162000311565b825183908390620000539060039060208501906200019e565b508051620000699060049060208401906200019e565b5050600680546001600160a81b031916600160a01b60ff8516026001600160a01b031916176001600160a01b03871617905550600554620000ac908590620000b6565b5050505062000419565b6001600160a01b038216620001115760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640160405180910390fd5b8060026000828254620001259190620003b5565b90915550506001600160a01b0382166000908152602081905260408120805483929062000154908490620003b5565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b828054620001ac90620003dc565b90600052602060002090601f016020900481019282620001d057600085556200021b565b82601f10620001eb57805160ff19168380011785556200021b565b828001600101855582156200021b579182015b828111156200021b578251825591602001919060010190620001fe565b50620002299291506200022d565b5090565b5b808211156200022957600081556001016200022e565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200026c57600080fd5b81516001600160401b038082111562000289576200028962000244565b604051601f8301601f19908116603f01168101908282118183101715620002b457620002b462000244565b81604052838152602092508683858801011115620002d157600080fd5b600091505b83821015620002f55785820183015181830184015290820190620002d6565b83821115620003075760008385830101525b9695505050505050565b600080600080608085870312156200032857600080fd5b84516001600160a01b03811681146200034057600080fd5b60208601519094506001600160401b03808211156200035e57600080fd5b6200036c888389016200025a565b945060408701519150808211156200038357600080fd5b5062000392878288016200025a565b925050606085015160ff81168114620003aa57600080fd5b939692955090935050565b60008219821115620003d757634e487b7160e01b600052601160045260246000fd5b500190565b600181811c90821680620003f157607f821691505b602082108114156200041357634e487b7160e01b600052602260045260246000fd5b50919050565b6109f480620004296000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c80635fd130a91161008c578063a457c2d711610066578063a457c2d7146101b6578063a9059cbb146101c9578063cbf0a64e146101dc578063dd62ed3e1461020757600080fd5b80635fd130a91461017057806370a082311461018557806395d89b41146101ae57600080fd5b806306fdde03146100d4578063095ea7b3146100f257806318160ddd1461011557806323b872dd1461012b578063313ce5671461013e578063395093511461015d575b600080fd5b6100dc610240565b6040516100e99190610812565b60405180910390f35b610105610100366004610883565b6102d2565b60405190151581526020016100e9565b61011d6102e8565b6040519081526020016100e9565b6101056101393660046108ad565b610315565b600654600160a01b900460ff1660405160ff90911681526020016100e9565b61010561016b366004610883565b6103c4565b61018361017e3660046108e9565b610400565b005b61011d6101933660046108e9565b6001600160a01b031660009081526020819052604090205490565b6100dc61046a565b6101056101c4366004610883565b610479565b6101056101d7366004610883565b610512565b6006546101ef906001600160a01b031681565b6040516001600160a01b0390911681526020016100e9565b61011d61021536600461090b565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60606003805461024f9061093e565b80601f016020809104026020016040519081016040528092919081815260200182805461027b9061093e565b80156102c85780601f1061029d576101008083540402835291602001916102c8565b820191906000526020600020905b8154815290600101906020018083116102ab57829003601f168201915b5050505050905090565b60006102df33848461051f565b50600192915050565b6006546001600160a01b0316600090815260208190526040812054600554610310919061098f565b905090565b6000610322848484610643565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156103ac5760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b6103b9853385840361051f565b506001949350505050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916102df9185906103fb9086906109a6565b61051f565b6006546001600160a01b031633146104485760405162461bcd60e51b815260206004820152600b60248201526a4e6f74206772617669747960a81b60448201526064016103a3565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b60606004805461024f9061093e565b3360009081526001602090815260408083206001600160a01b0386168452909152812054828110156104fb5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016103a3565b610508338585840361051f565b5060019392505050565b60006102df338484610643565b6001600160a01b0383166105815760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016103a3565b6001600160a01b0382166105e25760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016103a3565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0383166106a75760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016103a3565b6001600160a01b0382166107095760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016103a3565b6001600160a01b038316600090815260208190526040902054818110156107815760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016103a3565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906107b89084906109a6565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161080491815260200190565b60405180910390a350505050565b600060208083528351808285015260005b8181101561083f57858101830151858201604001528201610823565b81811115610851576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461087e57600080fd5b919050565b6000806040838503121561089657600080fd5b61089f83610867565b946020939093013593505050565b6000806000606084860312156108c257600080fd5b6108cb84610867565b92506108d960208501610867565b9150604084013590509250925092565b6000602082840312156108fb57600080fd5b61090482610867565b9392505050565b6000806040838503121561091e57600080fd5b61092783610867565b915061093560208401610867565b90509250929050565b600181811c9082168061095257607f821691505b6020821081141561097357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156109a1576109a1610979565b500390565b600082198211156109b9576109b9610979565b50019056fea264697066735822122010756c7691f24fa76ef182760b9f99a094a8bf02470a418707f1de88a7d8d7b364736f6c634300080a0033a2646970667358221220e0cc737c893f4f801f620d372b01df0f8d6fe82c9585b72e83600f517f252d7a64736f6c634300080a0033736f6d6d656c6965722d3300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a8f5c28f00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000700000000000000000000000021c1e236688fc78580371cae42e0e22fc9a9696f000000000000000000000000b369b35bcf48257f5cc0ad688350dae80bbc994a0000000000000000000000005299d547188b9351ad7e479e1eb2343e4557807200000000000000000000000087e454966552f7e5c675b7ec5fdb3489b81c6c51000000000000000000000000ebbb780845f68920a805f1d69ab4af7d0efc7df5000000000000000000000000fba500406fce5e9c6bf394d2701dcfc3845d4b6d00000000000000000000000009e8e999459728b20be51e8be9eda6ac04cb93ee000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000b7d4878600000000000000000000000000000000000000000000000000000000186b431e0000000000000000000000000000000000000000000000000000000010429b0c0000000000000000000000000000000000000000000000000000000008ba9a470000000000000000000000000000000000000000000000000000000008ba9a470000000000000000000000000000000000000000000000000000000008ba9a4700000000000000000000000000000000000000000000000000000000054dcb77
Deployed Bytecode
0x60806040523480156200001157600080fd5b5060043610620001145760003560e01c8063aca6b1c111620000a3578063df97174b116200006e578063df97174b1462000265578063e5a2b5d21462000288578063f2b533071462000292578063f7955637146200029c57600080fd5b8063aca6b1c114620001f9578063b56561fe1462000210578063bdda81d4146200021a578063c9d194d5146200024257600080fd5b80636941db9311620000e45780636941db93146200019e57806373b2054714620001b55780637dfb6f8614620001bf5780638690ff9814620001e257600080fd5b80629011531462000119578063010315251462000132578063011b217414620001495780631ffbe7f91462000187575b600080fd5b620001306200012a366004620018aa565b620002b3565b005b62000130620001433660046200192b565b620002c9565b620001756200015a36600462001990565b6001600160a01b031660009081526002602052604090205490565b60405190815260200160405180910390f35b6200013062000198366004620019ae565b620002e4565b62000130620001af36600462001bd3565b620004a2565b6200017560055481565b62000175620001d036600462001d6f565b60036020526000908152604090205481565b62000130620001f336600462001dd0565b62000835565b620001306200020a36600462001f09565b62000b88565b6200017560045481565b620001757f736f6d6d656c6965722d3300000000000000000000000000000000000000000081565b620001756200025336600462001d6f565b60009081526003602052604090205490565b620001756200027636600462001990565b60026020526000908152604090205481565b6200017560065481565b6200017560015481565b62000130620002ad36600462001ff3565b62000e72565b620002c2858585858562000f2a565b5050505050565b620002df620002d883620020a9565b8262001084565b505050565b60026000541415620003135760405162461bcd60e51b81526004016200030a906200215f565b60405180910390fd5b600260009081556040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa1580156200035f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000385919062002196565b90506200039e6001600160a01b038516333085620010f0565b6040516370a0823160e01b81523060048201526000906001600160a01b038616906370a0823190602401602060405180830381865afa158015620003e6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200040c919062002196565b90508181116200042f576040516321739d9b60e01b815260040160405180910390fd5b6005546200043f906001620021c6565b60055583336001600160a01b0387167fd7767894d73c589daeca9643f445f03d7be61aad2950c117e7cbff4176fca7e46200047b8686620021e1565b6005546040805192835260208301919091520160405180910390a450506001600055505050565b60026000541415620004c85760405162461bcd60e51b81526004016200030a906200215f565b600260005560c08101514310620004f25760405163bcf37c2560e01b815260040160405180910390fd5b61010081015160e0820151600090815260036020526040902054106200054f5761010081015160e082015160009081526003602052604090819020549051629427e960e11b8152600481019290925260248201526044016200030a565b6200055c84848462001163565b600154620005956200056e86620020a9565b7f736f6d6d656c6965722d3300000000000000000000000000000000000000000062001084565b14620005b45760405163723a340360e01b815260040160405180910390fd5b60208101515181515114620005dc57604051634298a95160e11b815260040160405180910390fd5b806060015151816040015151146200060757604051634829247960e01b815260040160405180910390fd5b60007f736f6d6d656c6965722d33000000000000000000000000000000000000000000681b1bd9da58d0d85b1b60ba1b836000015184602001518560400151866060015187608001518860a001518960c001518a60e001518b6101000151604051602001620006819b9a99989796959493929190620022d0565b604051602081830303815290604052805190602001209050620006aa8585858460065462000f2a565b5061010081015160e08201516000908152600360205260408120919091555b8151518110156200074d5762000738826080015183600001518381518110620006f657620006f662002380565b60200260200101518460200151848151811062000717576200071762002380565b60200260200101516001600160a01b0316620011bc9092919063ffffffff16565b80620007448162002396565b915050620006c9565b5060006200076482608001518360a00151620011ee565b905060005b826040015151811015620007cb57620007b6338460400151838151811062000795576200079562002380565b60200260200101518560600151848151811062000717576200071762002380565b80620007c28162002396565b91505062000769565b50600554620007dc906001620021c6565b600581905560e08301516101008401516040517f7c2bb24f8e1b3725cb613d7f11ef97d9745cc97a0e40f730621c052d684077a19362000821939291869190620023b4565b60405180910390a150506001600055505050565b600260005414156200085b5760405162461bcd60e51b81526004016200030a906200215f565b600260008181556001600160a01b038416815260209190915260409020548311620008bf576001600160a01b0382166000908152600260205260409081902054905163f7f920ad60e01b81526200030a918591600401918252602082015260400190565b6001600160a01b038216600090815260026020526040902054620008e790620f4240620021c6565b8311156200092e576001600160a01b0382166000908152600260205260409081902054905163f7f920ad60e01b81526200030a918591600401918252602082015260400190565b8043106200094f576040516308b9266360e11b815260040160405180910390fd5b6200095c8c8c8c62001163565b6001546200096e6200056e8e620020a9565b146200098d5760405163723a340360e01b815260040160405180910390fd5b87861415806200099d5750878414155b15620009bc5760405163c1f97e3560e01b815260040160405180910390fd5b62000a3c8c8c8c7f736f6d6d656c6965722d330000000000000000000000000000000000000000006f0e8e4c2dce6c2c6e8d2dedc84c2e8c6d60831b8e8e8e8e8e8e8e8e8e60405160200162000a1d9b9a999897969594939291906200245d565b6040516020818303038152906040528051906020012060065462000f2a565b6001600160a01b0382166000908152600260205260408120849055805b8981101562000b085762000ac889898381811062000a7b5762000a7b62002380565b905060200201602081019062000a92919062001990565b8c8c8481811062000aa75762000aa762002380565b90506020020135866001600160a01b0316620011bc9092919063ffffffff16565b86868281811062000add5762000add62002380565b905060200201358262000af19190620021c6565b91508062000aff8162002396565b91505062000a59565b5062000b1f6001600160a01b0384163383620011bc565b5060055462000b30906001620021c6565b60058190556040519081526001600160a01b0383169084907f02c7e81975f8edb86e2a0c038b7b86a49c744236abf0f6177ff5afc6986ab7089060200160405180910390a35050600160005550505050505050505050565b826040013584604001351162000bc1576040805163e0e8edf360e01b81528186013560048201529084013560248201526044016200030a565b62000bd46040840135620f4240620021c6565b8460400135111562000c09576040805163e0e8edf360e01b81528186013560048201529084013560248201526044016200030a565b62000c186020850185620024db565b905062000c268580620024db565b905014158062000c41575062000c3d8480620024db565b1590505b1562000c605760405163c01ba0ab60e01b815260040160405180910390fd5b62000c6d83838362001163565b6000805b62000c806020870187620024db565b905081101562000ce85762000c996020870187620024db565b8281811062000cac5762000cac62002380565b905060200201358262000cc09190620021c6565b915060065482111562000cd35762000ce8565b8062000cdf8162002396565b91505062000c71565b50600654811162000d1a5760065460405162bfb6ab60e01b81526200030a918391600401918252602082015260400190565b60015462000d2c6200056e86620020a9565b1462000d4b5760405163723a340360e01b815260040160405180910390fd5b600062000d5c6200056e87620020a9565b905062000d6f8585858460065462000f2a565b60018190556040860135600455600062000d9060a088016080890162001990565b6001600160a01b03161415801562000dab5750606086013515155b1562000dde5762000dde33606088013562000dcd60a08a0160808b0162001990565b6001600160a01b03169190620011bc565b60055462000dee906001620021c6565b60058190556040870135907f76d08978c024a4bf8cbb30c67fd78fcaa1827cbc533e4e175f36d07e64ccf96a90606089013562000e3260a08b0160808c0162001990565b62000e3e8b80620024db565b62000e4d60208e018e620024db565b60405162000e62979695949392919062002527565b60405180910390a2505050505050565b600030868686868660405162000e889062001835565b62000e9996959493929190620025a3565b604051809103906000f08015801562000eb6573d6000803e3d6000fd5b5060055490915062000eca90600162001239565b60058190556040516001600160a01b038316917f82fe3a4fa49c6382d0c085746698ddbbafe6c2bf61285b19410644b5b26287c79162000f18918c918c918c918c918c918c918c91620025f6565b60405180910390a25050505050505050565b6000805b62000f3a8780620024db565b9050811015620010505785858281811062000f595762000f5962002380565b62000f71926020606090920201908101915062002653565b60ff16156200103b5762000fd662000f8a8880620024db565b8381811062000f9d5762000f9d62002380565b905060200201602081019062000fb4919062001990565b8588888581811062000fca5762000fca62002380565b90506060020162001247565b62000ff457604051638baa579f60e01b815260040160405180910390fd5b620010036020880188620024db565b8281811062001016576200101662002380565b90506020020135826200102a9190620021c6565b9150828211156200103b5762001050565b80620010478162002396565b91505062000f2e565b508181116200107c5760405162bfb6ab60e01b815260048101829052602481018390526044016200030a565b505050505050565b6000806918da1958dadc1bda5b9d60b21b60001b90506000838286604001518760000151886020015189606001518a60800151604051602001620010cf979695949392919062002671565b60408051808303601f19018152919052805160209091012095945050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526200115d9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152620012dc565b50505050565b620011726020840184620024db565b9050620011808480620024db565b90501415806200119d575080620011988480620024db565b905014155b15620002df5760405163c6617b7b60e01b815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052620002df90849063a9059cbb60e01b9060640162001125565b60606200123283836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250620013b5565b9392505050565b6000620012328284620021c6565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018390526000908190605c0160408051601f1981840301815291905280516020918201209150620012be908290620012ae9086018662002653565b85602001358660400135620013ce565b6001600160a01b0316856001600160a01b0316149150509392505050565b600062001333826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620013b59092919063ffffffff16565b805190915015620002df5780806020019051810190620013549190620026d1565b620002df5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016200030a565b6060620013c68484600085620013fa565b949350505050565b6000806000620013e1878787876200152c565b91509150620013f08162001621565b5095945050505050565b6060824710156200145d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016200030a565b843b620014ad5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016200030a565b600080866001600160a01b03168587604051620014cb9190620026f5565b60006040518083038185875af1925050503d80600081146200150a576040519150601f19603f3d011682016040523d82523d6000602084013e6200150f565b606091505b509150915062001521828286620017f7565b979650505050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111562001565575060009050600362001618565b8460ff16601b141580156200157e57508460ff16601c14155b1562001591575060009050600462001618565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015620015e6573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116620016115760006001925092505062001618565b9150600090505b94509492505050565b600081600481111562001638576200163862002713565b1415620016425750565b600181600481111562001659576200165962002713565b1415620016a95760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016200030a565b6002816004811115620016c057620016c062002713565b1415620017105760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016200030a565b600381600481111562001727576200172762002713565b1415620017825760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016200030a565b600481600481111562001799576200179962002713565b1415620017f45760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b60648201526084016200030a565b50565b606083156200180857508162001232565b825115620018195782518084602001fd5b8160405162461bcd60e51b81526004016200030a919062002729565b610e1d806200273f83390190565b600060a082840312156200185657600080fd5b50919050565b60008083601f8401126200186f57600080fd5b5081356001600160401b038111156200188757600080fd5b602083019150836020606083028501011115620018a357600080fd5b9250929050565b600080600080600060808688031215620018c357600080fd5b85356001600160401b0380821115620018db57600080fd5b620018e989838a0162001843565b965060208801359150808211156200190057600080fd5b506200190f888289016200185c565b9699909850959660408101359660609091013595509350505050565b600080604083850312156200193f57600080fd5b82356001600160401b038111156200195657600080fd5b620019648582860162001843565b95602094909401359450505050565b80356001600160a01b03811681146200198b57600080fd5b919050565b600060208284031215620019a357600080fd5b620012328262001973565b600080600060608486031215620019c457600080fd5b620019cf8462001973565b95602085013595506040909401359392505050565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b038111828210171562001a205762001a20620019e4565b60405290565b604051601f8201601f191681016001600160401b038111828210171562001a515762001a51620019e4565b604052919050565b60006001600160401b0382111562001a755762001a75620019e4565b5060051b60200190565b600082601f83011262001a9157600080fd5b8135602062001aaa62001aa48362001a59565b62001a26565b82815260059290921b8401810191818101908684111562001aca57600080fd5b8286015b8481101562001ae7578035835291830191830162001ace565b509695505050505050565b600082601f83011262001b0457600080fd5b8135602062001b1762001aa48362001a59565b82815260059290921b8401810191818101908684111562001b3757600080fd5b8286015b8481101562001ae75762001b4f8162001973565b835291830191830162001b3b565b600082601f83011262001b6f57600080fd5b81356001600160401b0381111562001b8b5762001b8b620019e4565b62001ba0601f8201601f191660200162001a26565b81815284602083860101111562001bb657600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806060858703121562001bea57600080fd5b84356001600160401b038082111562001c0257600080fd5b62001c108883890162001843565b9550602087013591508082111562001c2757600080fd5b62001c35888389016200185c565b9095509350604087013591508082111562001c4f57600080fd5b90860190610120828903121562001c6557600080fd5b62001c6f620019fa565b82358281111562001c7f57600080fd5b62001c8d8a82860162001a7f565b82525060208301358281111562001ca357600080fd5b62001cb18a82860162001af2565b60208301525060408301358281111562001cca57600080fd5b62001cd88a82860162001a7f565b60408301525060608301358281111562001cf157600080fd5b62001cff8a82860162001af2565b60608301525062001d136080840162001973565b608082015260a08301358281111562001d2b57600080fd5b62001d398a82860162001b5d565b60a08301525060c083013560c082015260e083013560e08201526101009150818301358282015280935050505092959194509250565b60006020828403121562001d8257600080fd5b5035919050565b60008083601f84011262001d9c57600080fd5b5081356001600160401b0381111562001db457600080fd5b6020830191508360208260051b8501011115620018a357600080fd5b6000806000806000806000806000806000806101008d8f03121562001df457600080fd5b6001600160401b038d35111562001e0a57600080fd5b62001e198e8e358f0162001843565b9b506001600160401b0360208e0135111562001e3457600080fd5b62001e468e60208f01358f016200185c565b909b5099506001600160401b0360408e0135111562001e6457600080fd5b62001e768e60408f01358f0162001d89565b90995097506001600160401b0360608e0135111562001e9457600080fd5b62001ea68e60608f01358f0162001d89565b90975095506001600160401b0360808e0135111562001ec457600080fd5b62001ed68e60808f01358f0162001d89565b909550935060a08d0135925062001ef060c08e0162001973565b915060e08d013590509295989b509295989b509295989b565b6000806000806060858703121562001f2057600080fd5b84356001600160401b038082111562001f3857600080fd5b62001f468883890162001843565b9550602087013591508082111562001f5d57600080fd5b62001f6b8883890162001843565b9450604087013591508082111562001f8257600080fd5b5062001f91878288016200185c565b95989497509550505050565b60008083601f84011262001fb057600080fd5b5081356001600160401b0381111562001fc857600080fd5b602083019150836020828501011115620018a357600080fd5b803560ff811681146200198b57600080fd5b60008060008060008060006080888a0312156200200f57600080fd5b87356001600160401b03808211156200202757600080fd5b620020358b838c0162001f9d565b909950975060208a01359150808211156200204f57600080fd5b6200205d8b838c0162001f9d565b909750955060408a01359150808211156200207757600080fd5b50620020868a828b0162001f9d565b90945092506200209b90506060890162001fe1565b905092959891949750929550565b600060a08236031215620020bc57600080fd5b60405160a081016001600160401b038282108183111715620020e257620020e2620019e4565b816040528435915080821115620020f857600080fd5b620021063683870162001af2565b835260208501359150808211156200211d57600080fd5b506200212c3682860162001a7f565b6020830152506040830135604082015260608301356060820152620021546080840162001973565b608082015292915050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b600060208284031215620021a957600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115620021dc57620021dc620021b0565b500190565b600082821015620021f657620021f6620021b0565b500390565b600081518084526020808501945080840160005b838110156200222d578151875295820195908201906001016200220f565b509495945050505050565b600081518084526020808501945080840160005b838110156200222d5781516001600160a01b0316875295820195908201906001016200224c565b60005b838110156200229057818101518382015260200162002276565b838111156200115d5750506000910152565b60008151808452620022bc81602086016020860162002273565b601f01601f19169290920160200192915050565b60006101608d83528c6020840152806040840152620022f28184018d620021fb565b9050828103606084015262002308818c62002238565b905082810360808401526200231e818b620021fb565b905082810360a084015262002334818a62002238565b6001600160a01b03891660c085015283810360e08501529050620023598188620022a2565b61010084019690965250506101208101929092526101409091015298975050505050505050565b634e487b7160e01b600052603260045260246000fd5b6000600019821415620023ad57620023ad620021b0565b5060010190565b848152836020820152608060408201526000620023d56080830185620022a2565b905082606083015295945050505050565b81835260006001600160fb1b038311156200240057600080fd5b8260051b8083602087013760009401602001938452509192915050565b8183526000602080850194508260005b858110156200222d576001600160a01b03620024498362001973565b16875295820195908201906001016200242d565b60006101008d83528c6020840152806040840152620024808184018c8e620023e6565b9050828103606084015262002497818a8c6200241d565b90508281036080840152620024ae81888a620023e6565b60a084019690965250506001600160a01b039290921660c083015260e09091015298975050505050505050565b6000808335601e19843603018112620024f357600080fd5b8301803591506001600160401b038211156200250e57600080fd5b6020019150600581901b3603821315620018a357600080fd5b87815286602082015260018060a01b038616604082015260a0606082015260006200255760a0830186886200241d565b82810360808401526200256c818587620023e6565b9a9950505050505050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0387168152608060208201819052600090620025ca90830187896200257a565b8281036040840152620025df8186886200257a565b91505060ff83166060830152979650505050505050565b60a0815260006200260c60a083018a8c6200257a565b82810360208401526200262181898b6200257a565b90508281036040840152620026388187896200257a565b60ff9590951660608401525050608001529695505050505050565b6000602082840312156200266657600080fd5b620012328262001fe1565b87815286602082015285604082015260e0606082015260006200269860e083018762002238565b8281036080840152620026ac8187620021fb565b60a084019590955250506001600160a01b039190911660c09091015295945050505050565b600060208284031215620026e457600080fd5b815180151581146200123257600080fd5b600082516200270981846020870162002273565b9190910192915050565b634e487b7160e01b600052602160045260246000fd5b602081526000620012326020830184620022a256fe60806040526000196005553480156200001757600080fd5b5060405162000e1d38038062000e1d8339810160408190526200003a9162000311565b825183908390620000539060039060208501906200019e565b508051620000699060049060208401906200019e565b5050600680546001600160a81b031916600160a01b60ff8516026001600160a01b031916176001600160a01b03871617905550600554620000ac908590620000b6565b5050505062000419565b6001600160a01b038216620001115760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640160405180910390fd5b8060026000828254620001259190620003b5565b90915550506001600160a01b0382166000908152602081905260408120805483929062000154908490620003b5565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b828054620001ac90620003dc565b90600052602060002090601f016020900481019282620001d057600085556200021b565b82601f10620001eb57805160ff19168380011785556200021b565b828001600101855582156200021b579182015b828111156200021b578251825591602001919060010190620001fe565b50620002299291506200022d565b5090565b5b808211156200022957600081556001016200022e565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200026c57600080fd5b81516001600160401b038082111562000289576200028962000244565b604051601f8301601f19908116603f01168101908282118183101715620002b457620002b462000244565b81604052838152602092508683858801011115620002d157600080fd5b600091505b83821015620002f55785820183015181830184015290820190620002d6565b83821115620003075760008385830101525b9695505050505050565b600080600080608085870312156200032857600080fd5b84516001600160a01b03811681146200034057600080fd5b60208601519094506001600160401b03808211156200035e57600080fd5b6200036c888389016200025a565b945060408701519150808211156200038357600080fd5b5062000392878288016200025a565b925050606085015160ff81168114620003aa57600080fd5b939692955090935050565b60008219821115620003d757634e487b7160e01b600052601160045260246000fd5b500190565b600181811c90821680620003f157607f821691505b602082108114156200041357634e487b7160e01b600052602260045260246000fd5b50919050565b6109f480620004296000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c80635fd130a91161008c578063a457c2d711610066578063a457c2d7146101b6578063a9059cbb146101c9578063cbf0a64e146101dc578063dd62ed3e1461020757600080fd5b80635fd130a91461017057806370a082311461018557806395d89b41146101ae57600080fd5b806306fdde03146100d4578063095ea7b3146100f257806318160ddd1461011557806323b872dd1461012b578063313ce5671461013e578063395093511461015d575b600080fd5b6100dc610240565b6040516100e99190610812565b60405180910390f35b610105610100366004610883565b6102d2565b60405190151581526020016100e9565b61011d6102e8565b6040519081526020016100e9565b6101056101393660046108ad565b610315565b600654600160a01b900460ff1660405160ff90911681526020016100e9565b61010561016b366004610883565b6103c4565b61018361017e3660046108e9565b610400565b005b61011d6101933660046108e9565b6001600160a01b031660009081526020819052604090205490565b6100dc61046a565b6101056101c4366004610883565b610479565b6101056101d7366004610883565b610512565b6006546101ef906001600160a01b031681565b6040516001600160a01b0390911681526020016100e9565b61011d61021536600461090b565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60606003805461024f9061093e565b80601f016020809104026020016040519081016040528092919081815260200182805461027b9061093e565b80156102c85780601f1061029d576101008083540402835291602001916102c8565b820191906000526020600020905b8154815290600101906020018083116102ab57829003601f168201915b5050505050905090565b60006102df33848461051f565b50600192915050565b6006546001600160a01b0316600090815260208190526040812054600554610310919061098f565b905090565b6000610322848484610643565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156103ac5760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b6103b9853385840361051f565b506001949350505050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916102df9185906103fb9086906109a6565b61051f565b6006546001600160a01b031633146104485760405162461bcd60e51b815260206004820152600b60248201526a4e6f74206772617669747960a81b60448201526064016103a3565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b60606004805461024f9061093e565b3360009081526001602090815260408083206001600160a01b0386168452909152812054828110156104fb5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016103a3565b610508338585840361051f565b5060019392505050565b60006102df338484610643565b6001600160a01b0383166105815760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016103a3565b6001600160a01b0382166105e25760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016103a3565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0383166106a75760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016103a3565b6001600160a01b0382166107095760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016103a3565b6001600160a01b038316600090815260208190526040902054818110156107815760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016103a3565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906107b89084906109a6565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161080491815260200190565b60405180910390a350505050565b600060208083528351808285015260005b8181101561083f57858101830151858201604001528201610823565b81811115610851576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461087e57600080fd5b919050565b6000806040838503121561089657600080fd5b61089f83610867565b946020939093013593505050565b6000806000606084860312156108c257600080fd5b6108cb84610867565b92506108d960208501610867565b9150604084013590509250925092565b6000602082840312156108fb57600080fd5b61090482610867565b9392505050565b6000806040838503121561091e57600080fd5b61092783610867565b915061093560208401610867565b90509250929050565b600181811c9082168061095257607f821691505b6020821081141561097357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156109a1576109a1610979565b500390565b600082198211156109b9576109b9610979565b50019056fea264697066735822122010756c7691f24fa76ef182760b9f99a094a8bf02470a418707f1de88a7d8d7b364736f6c634300080a0033a2646970667358221220e0cc737c893f4f801f620d372b01df0f8d6fe82c9585b72e83600f517f252d7a64736f6c634300080a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
736f6d6d656c6965722d3300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a8f5c28f00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000700000000000000000000000021c1e236688fc78580371cae42e0e22fc9a9696f000000000000000000000000b369b35bcf48257f5cc0ad688350dae80bbc994a0000000000000000000000005299d547188b9351ad7e479e1eb2343e4557807200000000000000000000000087e454966552f7e5c675b7ec5fdb3489b81c6c51000000000000000000000000ebbb780845f68920a805f1d69ab4af7d0efc7df5000000000000000000000000fba500406fce5e9c6bf394d2701dcfc3845d4b6d00000000000000000000000009e8e999459728b20be51e8be9eda6ac04cb93ee000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000b7d4878600000000000000000000000000000000000000000000000000000000186b431e0000000000000000000000000000000000000000000000000000000010429b0c0000000000000000000000000000000000000000000000000000000008ba9a470000000000000000000000000000000000000000000000000000000008ba9a470000000000000000000000000000000000000000000000000000000008ba9a4700000000000000000000000000000000000000000000000000000000054dcb77
-----Decoded View---------------
Arg [0] : _gravityId (bytes32): 0x736f6d6d656c6965722d33000000000000000000000000000000000000000000
Arg [1] : _powerThreshold (uint256): 2834678415
Arg [2] : _validators (address[]): 0x21c1E236688fC78580371cAe42e0E22Fc9A9696F,0xb369b35BCf48257f5cc0AD688350dAe80bbc994A,0x5299d547188B9351aD7e479E1eb2343e45578072,0x87e454966552f7E5c675b7Ec5FDB3489b81c6c51,0xeBbb780845F68920a805f1D69aB4Af7d0eFC7DF5,0xfbA500406FcE5e9C6bf394D2701DcFC3845D4B6d,0x09E8E999459728b20be51e8be9Eda6Ac04cB93EE
Arg [3] : _powers (uint256[]): 3084158854,409682718,272800524,146446919,146446919,146446919,88984439
-----Encoded View---------------
20 Constructor Arguments found :
Arg [0] : 736f6d6d656c6965722d33000000000000000000000000000000000000000000
Arg [1] : 00000000000000000000000000000000000000000000000000000000a8f5c28f
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000180
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [5] : 00000000000000000000000021c1e236688fc78580371cae42e0e22fc9a9696f
Arg [6] : 000000000000000000000000b369b35bcf48257f5cc0ad688350dae80bbc994a
Arg [7] : 0000000000000000000000005299d547188b9351ad7e479e1eb2343e45578072
Arg [8] : 00000000000000000000000087e454966552f7e5c675b7ec5fdb3489b81c6c51
Arg [9] : 000000000000000000000000ebbb780845f68920a805f1d69ab4af7d0efc7df5
Arg [10] : 000000000000000000000000fba500406fce5e9c6bf394d2701dcfc3845d4b6d
Arg [11] : 00000000000000000000000009e8e999459728b20be51e8be9eda6ac04cb93ee
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [13] : 00000000000000000000000000000000000000000000000000000000b7d48786
Arg [14] : 00000000000000000000000000000000000000000000000000000000186b431e
Arg [15] : 0000000000000000000000000000000000000000000000000000000010429b0c
Arg [16] : 0000000000000000000000000000000000000000000000000000000008ba9a47
Arg [17] : 0000000000000000000000000000000000000000000000000000000008ba9a47
Arg [18] : 0000000000000000000000000000000000000000000000000000000008ba9a47
Arg [19] : 00000000000000000000000000000000000000000000000000000000054dcb77
Deployed Bytecode Sourcemap
50720:20218:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53022:262;;;;;;:::i;:::-;;:::i;:::-;;52873:144;;;;;;:::i;:::-;;:::i;53314:132::-;;;;;;:::i;:::-;-1:-1:-1;;;;;53405:36:0;53384:7;53405:36;;;:21;:36;;;;;;;53314:132;;;;2417:25:1;;;2405:2;2390:18;53314:132:0;;;;;;;67650:1321;;;;;;:::i;:::-;;:::i;64416:3229::-;;;;;;:::i;:::-;;:::i;51193:39::-;;;;;;50956:60;;;;;;:::i;:::-;;;;;;;;;;;;;;60639:3211;;;;;;:::i;:::-;;:::i;57193:3101::-;;;;;;:::i;:::-;;:::i;51020:40::-;;;;;;51359;;;;;53451:146;;;;;;:::i;:::-;53528:7;53549:43;;;:25;:43;;;;;;;53451:146;50896:56;;;;;;:::i;:::-;;;;;;;;;;;;;;51280:35;;;;;;50851:41;;;;;;68976:535;;;;;;:::i;:::-;;:::i;53022:262::-;53205:74;53230:14;53246:5;;53253:8;53263:15;53205:24;:74::i;:::-;53022:262;;;;;:::o;52873:144::-;52973:39;;52988:11;52973:39;:::i;:::-;53001:10;52973:14;:39::i;:::-;;52873:144;;:::o;67650:1321::-;23614:1;24210:7;;:19;;24202:63;;;;-1:-1:-1;;;24202:63:0;;;;;;;:::i;:::-;;;;;;;;;23614:1;24343:7;:18;;;67854:47:::1;::::0;-1:-1:-1;;;67854:47:0;;67895:4:::1;67854:47;::::0;::::1;14524:51:1::0;-1:-1:-1;;;;;67854:32:0;::::1;::::0;::::1;::::0;14497:18:1;;67854:47:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67825:76:::0;-1:-1:-1;67960:75:0::1;-1:-1:-1::0;;;;;67960:39:0;::::1;68000:10;68020:4;68027:7:::0;67960:39:::1;:75::i;:::-;68205:47;::::0;-1:-1:-1;;;68205:47:0;;68246:4:::1;68205:47;::::0;::::1;14524:51:1::0;68178:24:0::1;::::0;-1:-1:-1;;;;;68205:32:0;::::1;::::0;::::1;::::0;14497:18:1;;68205:47:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68178:74;;68432:18;68412:16;:38;68408:84;;68465:21;;-1:-1:-1::0;;;68465:21:0::1;;;;;;;;;;;68408:84;68521:20;::::0;:24:::1;::::0;68544:1:::1;68521:24;:::i;:::-;68498:20;:47:::0;68880:12;68864:10:::1;-1:-1:-1::0;;;;;68821:145:0;::::1;;68898:37;68917:18:::0;68898:16;:37:::1;:::i;:::-;68941:20;::::0;68821:145:::1;::::0;;15344:25:1;;;15400:2;15385:18;;15378:34;;;;15317:18;68821:145:0::1;;;;;;;-1:-1:-1::0;;23570:1:0;24522:7;:22;-1:-1:-1;;;67650:1321:0:o;64416:3229::-;23614:1;24210:7;;:19;;24202:63;;;;-1:-1:-1;;;24202:63:0;;;;;;;:::i;:::-;23614:1;24343:7;:18;64797:13:::1;::::0;::::1;::::0;64781:12:::1;:29;64777:75;;64826:19;;-1:-1:-1::0;;;64826:19:0::1;;;;;;;;;;;64777:75;65010:23;::::0;::::1;::::0;64985:20:::1;::::0;::::1;::::0;64959:47:::1;::::0;;;:25:::1;:47;::::0;;;;;:74:::1;64955:241;;65089:23;::::0;::::1;::::0;65160:20:::1;::::0;::::1;::::0;65134:47:::1;::::0;;;:25:::1;:47;::::0;;;;;;;65049:140;;-1:-1:-1;;;65049:140:0;;::::1;::::0;::::1;15344:25:1::0;;;;15385:18;;;15378:34;15317:18;;65049:140:0::1;15170:248:1::0;64955:241:0::1;65494:37;65509:14;65525:5;;65494:14;:37::i;:::-;65676:26;::::0;65625:47:::1;;65640:14:::0;65625:47:::1;:::i;:::-;65656:15;65625:14;:47::i;:::-;:77;65621:125;;65718:21;;-1:-1:-1::0;;;65718:21:0::1;;;;;;;;;;;65621:125;65789:28;::::0;::::1;::::0;:35;65757:21;;:28;:67:::1;65753:121;;65840:27;;-1:-1:-1::0;;;65840:27:0::1;;;;;;;;;;;65753:121;65912:5;:23;;;:30;65885:5;:16;;;:23;:57;65881:106;;65958:22;;-1:-1:-1::0;;;65958:22:0::1;;;;;;;;;;;65881:106;66002:16;66055:15;-1:-1:-1::0;;;66193:5:0::1;:21;;;66222:5;:28;;;66258:5;:16;;;66282:5;:23;;;66313:5;:26;;;66347:5;:13;;;66368:5;:13;;;66389:5;:20;;;66417:5;:23;;;66037:410;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;66021:432;;;;;;66002:451;;66557:162;66588:14;66609:5;;66678:8;66693:20;;66557:24;:162::i;:::-;-1:-1:-1::0;66829:23:0::1;::::0;::::1;::::0;66805:20:::1;::::0;::::1;::::0;66779:47:::1;::::0;;;:25:::1;:47;::::0;;;;:73;;;;66899:193:::1;66923:21:::0;;:28;66919:32;::::1;66899:193;;;66964:122;67023:5;:26;;;67056:5;:21;;;67078:1;67056:24;;;;;;;;:::i;:::-;;;;;;;66971:5;:28;;;67000:1;66971:31;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1::0;;;;;66964:52:0::1;;;:122;;;;;:::i;:::-;66953:3:::0;::::1;::::0;::::1;:::i;:::-;;;;66899:193;;;;67132:23;67158:63;67179:5;:26;;;67207:5;:13;;;67158:20;:63::i;:::-;67132:89;;67263:9;67258:146;67282:5;:16;;;:23;67278:1;:27;67258:146;;;67318:80;67366:10;67378:5;:16;;;67395:1;67378:19;;;;;;;;:::i;:::-;;;;;;;67325:5;:23;;;67349:1;67325:26;;;;;;;;:::i;67318:80::-;67307:3:::0;::::1;::::0;::::1;:::i;:::-;;;;67258:146;;;-1:-1:-1::0;67479:20:0::1;::::0;:24:::1;::::0;67502:1:::1;67479:24;:::i;:::-;67456:20;:47:::0;;;67535:20:::1;::::0;::::1;::::0;67562:23:::1;::::0;::::1;::::0;67514:121:::1;::::0;::::1;::::0;::::1;::::0;67535:20;67562:23;67592:10;;67456:47;67514:121:::1;:::i;:::-;;;;;;;;-1:-1:-1::0;;23570:1:0;24522:7;:22;-1:-1:-1;;;64416:3229:0:o;60639:3211::-;23614:1;24210:7;;:19;;24202:63;;;;-1:-1:-1;;;24202:63:0;;;;;;;:::i;:::-;23614:1;24343:7;:18;;;-1:-1:-1;;;;;61325:37:0;::::1;::::0;;::::1;::::0;;;;;;;;61310:52;::::1;61306:193;;-1:-1:-1::0;;;;;61447:37:0;::::1;;::::0;;;:21:::1;:37;::::0;;;;;;;61378:114;;-1:-1:-1;;;61378:114:0;;::::1;::::0;61414:11;;61378:114:::1;;15344:25:1::0;;;15400:2;15385:18;;15378:34;15332:2;15317:18;;15170:248;61306:193:0::1;-1:-1:-1::0;;;;;61755:37:0;::::1;;::::0;;;:21:::1;:37;::::0;;;;;:47:::1;::::0;61795:7:::1;61755:47;:::i;:::-;61741:11;:61;61737:202;;;-1:-1:-1::0;;;;;61887:37:0;::::1;;::::0;;;:21:::1;:37;::::0;;;;;;;61818:114;;-1:-1:-1;;;61818:114:0;;::::1;::::0;61854:11;;61818:114:::1;;15344:25:1::0;;;15400:2;15385:18;;15378:34;15332:2;15317:18;;15170:248;61737:202:0::1;62033:13;62017:12;:29;62013:71;;62062:15;;-1:-1:-1::0;;;62062:15:0::1;;;;;;;;;;;62013:71;62179:37;62194:14;62210:5;;62179:14;:37::i;:::-;62361:26;::::0;62310:47:::1;;62325:14:::0;62310:47:::1;:::i;:::-;:77;62306:125;;62403:21;;-1:-1:-1::0;;;62403:21:0::1;;;;;;;;;;;62306:125;62497:39:::0;;::::1;;::::0;:74:::1;;-1:-1:-1::0;62540:31:0;;::::1;;62497:74;62493:117;;;62587:16;;-1:-1:-1::0;;;62587:16:0::1;;;;;;;;;;;62493:117;62713:462;62744:14;62765:5;;62870:15;-1:-1:-1::0;;;63018:8:0::1;;63035:13;;63057:5;;63071:11;63091:14;63114:13;62851:284;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;62834:308;;;;;;63149:20;;62713:24;:462::i;:::-;-1:-1:-1::0;;;;;63225:37:0;::::1;;::::0;;;:21:::1;:37;::::0;;;;:51;;;:37;63363:166:::1;63383:19:::0;;::::1;63363:166;;;63417:66;63453:13;;63467:1;63453:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;63471:8;;63480:1;63471:11;;;;;;;:::i;:::-;;;;;;;63424:14;-1:-1:-1::0;;;;;63417:35:0::1;;;:66;;;;;:::i;:::-;63513:5;;63519:1;63513:8;;;;;;;:::i;:::-;;;;;;;63502;:19;;;;:::i;:::-;63491:30:::0;-1:-1:-1;63404:3:0;::::1;::::0;::::1;:::i;:::-;;;;63363:166;;;-1:-1:-1::0;63581:57:0::1;-1:-1:-1::0;;;;;63581:35:0;::::1;63617:10;63629:8:::0;63581:35:::1;:57::i;:::-;-1:-1:-1::0;63725:20:0::1;::::0;:24:::1;::::0;63748:1:::1;63725:24;:::i;:::-;63702:20;:47:::0;;;63760:80:::1;::::0;2417:25:1;;;-1:-1:-1;;;;;63760:80:0;::::1;::::0;63790:11;;63760:80:::1;::::0;2405:2:1;2390:18;63760:80:0::1;;;;;;;-1:-1:-1::0;;23570:1:0;24522:7;:22;-1:-1:-1;;;;;;;;;;60639:3211:0:o;57193:3101::-;57618:14;:26;;;57592:10;:22;;;:52;57588:189;;57695:22;57659:112;;-1:-1:-1;;;57659:112:0;;57695:22;;;;57659:112;;;15344:25:1;57738:26:0;;;;15385:18:1;;;15378:34;15317:18;;57659:112:0;15170:248:1;57588:189:0;58047:36;:26;;;;58076:7;58047:36;:::i;:::-;58022:10;:22;;;:61;58018:198;;;58134:22;58098:112;;-1:-1:-1;;;58098:112:0;;58134:22;;;;58098:112;;;15344:25:1;58177:26:0;;;;15385:18:1;;;15378:34;15317:18;;58098:112:0;15170:248:1;58018:198:0;58325:17;;;;:10;:17;:::i;:::-;:24;-1:-1:-1;58293:21:0;:10;;:21;:::i;:::-;:28;;:56;;:97;;;-1:-1:-1;58357:21:0;:10;;:21;:::i;:::-;:33;;-1:-1:-1;58293:97:0;58284:157;;;58409:26;;-1:-1:-1;;;58409:26:0;;;;;;;;;;;58284:157;58534:37;58549:14;58565:5;;58534:14;:37::i;:::-;58681:23;58718:9;58713:191;58737:17;;;;:10;:17;:::i;:::-;:24;;58733:1;:28;58713:191;;;58810:17;;;;:10;:17;:::i;:::-;58828:1;58810:20;;;;;;;:::i;:::-;;;;;;;58792:15;:38;;;;:::i;:::-;58774:56;;58858:20;;58840:15;:38;58836:63;;;58887:5;;58836:63;58763:3;;;;:::i;:::-;;;;58713:191;;;;58931:20;;58912:15;:39;58908:171;;59046:20;;58966:107;;-1:-1:-1;;;58966:107:0;;;;59008:15;;58966:107;;15344:25:1;;;15400:2;15385:18;;15378:34;15332:2;15317:18;;15170:248;58908:171:0;59221:26;;59170:47;;59185:14;59170:47;:::i;:::-;:77;59166:123;;59262:21;;-1:-1:-1;;;59262:21:0;;;;;;;;;;;59166:123;59379:21;59403:43;;59418:10;59403:43;:::i;:::-;59379:67;;59453:84;59478:14;59494:5;;59501:13;59516:20;;59453:24;:84::i;:::-;59663:26;:42;;;59758:22;;;;59734:21;:46;-1:-1:-1;59867:22:0;;;;;;;;:::i;:::-;-1:-1:-1;;;;;59867:36:0;;;:68;;;;-1:-1:-1;59907:23:0;;;;:28;;59867:68;59863:166;;;59943:80;59987:10;59999:23;;;;59950:22;;;;;;;;:::i;:::-;-1:-1:-1;;;;;59943:43:0;;:80;:43;:80::i;:::-;60071:20;;:24;;60094:1;60071:24;:::i;:::-;60048:20;:47;;;60129:22;;;;;60105:184;;60183:23;;;;60212:22;;;;;;;;:::i;:::-;60240:21;:10;;:21;:::i;:::-;60267:17;;;;:10;:17;:::i;:::-;60105:184;;;;;;;;;;;;:::i;:::-;;;;;;;;57506:2788;;57193:3101;;;;:::o;68976:535::-;69186:17;69230:4;69237:5;;69244:7;;69253:9;69206:57;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;69343:20:0;;69186:77;;-1:-1:-1;69343:27:0;;69368:1;69343:24;:27::i;:::-;69320:20;:50;;;69380:126;;-1:-1:-1;;;;;69380:126:0;;;;;;;69404:12;;;;69442:5;;;;69453:7;;;;69466:9;;69380:126;:::i;:::-;;;;;;;;69117:394;68976:535;;;;;;;:::o;55595:1201::-;55915:23;55954:9;55949:673;55973:25;:14;;:25;:::i;:::-;:32;;55969:1;:36;55949:673;;;56202:5;;56208:1;56202:8;;;;;;;:::i;:::-;:10;;;:8;;;;;:10;;;;-1:-1:-1;56202:10:0;:::i;:::-;:15;;;56198:419;;56299:59;56309:25;:14;;:25;:::i;:::-;56335:1;56309:28;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;56339:8;56349:5;;56355:1;56349:8;;;;;;;:::i;:::-;;;;;;56299:9;:59::i;:::-;56294:107;;56375:18;;-1:-1:-1;;;56375:18:0;;;;;;;;;;;56294:107;56477:21;;;;:14;:21;:::i;:::-;56499:1;56477:24;;;;;;;:::i;:::-;;;;;;;56459:15;:42;;;;:::i;:::-;56441:60;;56573:15;56555;:33;56551:60;;;56598:5;;56551:60;56007:3;;;;:::i;:::-;;;;55949:673;;;;56691:15;56672;:34;56668:110;;56721:51;;-1:-1:-1;;;56721:51:0;;;;;15344:25:1;;;15385:18;;;15378:34;;;15317:18;;56721:51:0;15170:248:1;56668:110:0;55910:886;55595:1201;;;;;:::o;55057:531::-;55163:7;55229:18;-1:-1:-1;;;55229:87:0;;;;55323:18;55376:10;55393;55410:11;:23;;;55440:11;:22;;;55469:11;:18;;;55494:11;:24;;;55525:11;:23;;;55359:195;;;;;;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;55359:195:0;;;;;;55344:215;;55359:195;55344:215;;;;;55057:531;-1:-1:-1;;;;;55057:531:0:o;18786:248::-;18957:68;;-1:-1:-1;;;;;26069:15:1;;;18957:68:0;;;26051:34:1;26121:15;;26101:18;;;26094:43;26153:18;;;26146:34;;;18930:96:0;;18950:5;;-1:-1:-1;;;18980:27:0;25986:18:1;;18957:68:0;;;;-1:-1:-1;;18957:68:0;;;;;;;;;;;;;;-1:-1:-1;;;;;18957:68:0;-1:-1:-1;;;;;;18957:68:0;;;;;;;;;;18930:19;:96::i;:::-;18786:248;;;;:::o;54064:356::-;54291:14;;;;:7;:14;:::i;:::-;:21;-1:-1:-1;54262:18:0;:7;;:18;:::i;:::-;:25;;:50;;:99;;;-1:-1:-1;54349:5:0;54320:18;:7;;:18;:::i;:::-;:25;;:41;;54262:99;54253:163;;;54380:30;;-1:-1:-1;;;54380:30:0;;;;;;;;;;;18567:211;18711:58;;-1:-1:-1;;;;;26383:32:1;;18711:58:0;;;26365:51:1;26432:18;;;26425:34;;;18684:86:0;;18704:5;;-1:-1:-1;;;18734:23:0;26338:18:1;;18711:58:0;26191:274:1;13006:175:0;13081:12;13113:60;13126:6;13134:4;13113:60;;;;;;;;;;;;;;;;;:12;:60::i;:::-;13106:67;13006:175;-1:-1:-1;;;13006:175:0:o;2829:98::-;2887:7;2914:5;2918:1;2914;:5;:::i;53656:314::-;53823:62;;26712:66:1;53823:62:0;;;26700:79:1;26795:12;;;26788:28;;;53773:4:0;;;;26832:12:1;;53823:62:0;;;-1:-1:-1;;53823:62:0;;;;;;;;;53808:82;;53823:62;53808:82;;;;;-1:-1:-1;53913:52:0;;53808:82;;53942:6;;;;:4;:6;:::i;:::-;53950:4;:6;;;53958:4;:6;;;53913:13;:52::i;:::-;-1:-1:-1;;;;;53902:63:0;:7;-1:-1:-1;;;;;53902:63:0;;53895:70;;;53656:314;;;;;:::o;21140:716::-;21564:23;21590:69;21618:4;21590:69;;;;;;;;;;;;;;;;;21598:5;-1:-1:-1;;;;;21590:27:0;;;:69;;;;;:::i;:::-;21674:17;;21564:95;;-1:-1:-1;21674:21:0;21670:179;;21771:10;21760:30;;;;;;;;;;;;:::i;:::-;21752:85;;;;-1:-1:-1;;;21752:85:0;;27339:2:1;21752:85:0;;;27321:21:1;27378:2;27358:18;;;27351:30;27417:34;27397:18;;;27390:62;-1:-1:-1;;;27468:18:1;;;27461:40;27518:19;;21752:85:0;27137:406:1;13411:229:0;13548:12;13580:52;13602:6;13610:4;13616:1;13619:12;13580:21;:52::i;:::-;13573:59;13411:229;-1:-1:-1;;;;13411:229:0:o;32168:279::-;32296:7;32317:17;32336:18;32358:25;32369:4;32375:1;32378;32381;32358:10;:25::i;:::-;32316:67;;;;32394:18;32406:5;32394:11;:18::i;:::-;-1:-1:-1;32430:9:0;32168:279;-1:-1:-1;;;;;32168:279:0:o;14531:510::-;14701:12;14759:5;14734:21;:30;;14726:81;;;;-1:-1:-1;;;14726:81:0;;27750:2:1;14726:81:0;;;27732:21:1;27789:2;27769:18;;;27762:30;27828:34;27808:18;;;27801:62;-1:-1:-1;;;27879:18:1;;;27872:36;27925:19;;14726:81:0;27548:402:1;14726:81:0;10928:20;;14818:60;;;;-1:-1:-1;;;14818:60:0;;28157:2:1;14818:60:0;;;28139:21:1;28196:2;28176:18;;;28169:30;28235:31;28215:18;;;28208:59;28284:18;;14818:60:0;27955:353:1;14818:60:0;14892:12;14906:23;14933:6;-1:-1:-1;;;;;14933:11:0;14952:5;14959:4;14933:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14891:73;;;;14982:51;14999:7;15008:10;15020:12;14982:16;:51::i;:::-;14975:58;14531:510;-1:-1:-1;;;;;;;14531:510:0:o;30397:1632::-;30528:7;;31462:66;31449:79;;31445:163;;;-1:-1:-1;31561:1:0;;-1:-1:-1;31565:30:0;31545:51;;31445:163;31622:1;:7;;31627:2;31622:7;;:18;;;;;31633:1;:7;;31638:2;31633:7;;31622:18;31618:102;;;-1:-1:-1;31673:1:0;;-1:-1:-1;31677:30:0;31657:51;;31618:102;31834:24;;;31817:14;31834:24;;;;;;;;;28819:25:1;;;28892:4;28880:17;;28860:18;;;28853:45;;;;28914:18;;;28907:34;;;28957:18;;;28950:34;;;31834:24:0;;28791:19:1;;31834:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;31834:24:0;;-1:-1:-1;;31834:24:0;;;-1:-1:-1;;;;;;;31873:20:0;;31869:103;;31926:1;31930:29;31910:50;;;;;;;31869:103;31992:6;-1:-1:-1;32000:20:0;;-1:-1:-1;30397:1632:0;;;;;;;;:::o;25059:643::-;25137:20;25128:5;:29;;;;;;;;:::i;:::-;;25124:571;;;25059:643;:::o;25124:571::-;25235:29;25226:5;:38;;;;;;;;:::i;:::-;;25222:473;;;25281:34;;-1:-1:-1;;;25281:34:0;;29329:2:1;25281:34:0;;;29311:21:1;29368:2;29348:18;;;29341:30;29407:26;29387:18;;;29380:54;29451:18;;25281:34:0;29127:348:1;25222:473:0;25346:35;25337:5;:44;;;;;;;;:::i;:::-;;25333:362;;;25398:41;;-1:-1:-1;;;25398:41:0;;29682:2:1;25398:41:0;;;29664:21:1;29721:2;29701:18;;;29694:30;29760:33;29740:18;;;29733:61;29811:18;;25398:41:0;29480:355:1;25333:362:0;25470:30;25461:5;:39;;;;;;;;:::i;:::-;;25457:238;;;25517:44;;-1:-1:-1;;;25517:44:0;;30042:2:1;25517:44:0;;;30024:21:1;30081:2;30061:18;;;30054:30;30120:34;30100:18;;;30093:62;-1:-1:-1;;;30171:18:1;;;30164:32;30213:19;;25517:44:0;29840:398:1;25457:238:0;25592:30;25583:5;:39;;;;;;;;:::i;:::-;;25579:116;;;25639:44;;-1:-1:-1;;;25639:44:0;;30445:2:1;25639:44:0;;;30427:21:1;30484:2;30464:18;;;30457:30;30523:34;30503:18;;;30496:62;-1:-1:-1;;;30574:18:1;;;30567:32;30616:19;;25639:44:0;30243:398:1;25579:116:0;25059:643;:::o;17217:712::-;17367:12;17396:7;17392:530;;;-1:-1:-1;17427:10:0;17420:17;;17392:530;17541:17;;:21;17537:374;;17739:10;17733:17;17800:15;17787:10;17783:2;17779:19;17772:44;17537:374;17882:12;17875:20;;-1:-1:-1;;;17875:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;:::o;14:159:1:-;77:5;122:3;113:6;108:3;104:16;100:26;97:46;;;139:1;136;129:12;97:46;-1:-1:-1;161:6:1;14:159;-1:-1:-1;14:159:1:o;178:391::-;262:8;272:6;326:3;319:4;311:6;307:17;303:27;293:55;;344:1;341;334:12;293:55;-1:-1:-1;367:20:1;;-1:-1:-1;;;;;399:30:1;;396:50;;;442:1;439;432:12;396:50;479:4;471:6;467:17;455:29;;542:3;535:4;527;519:6;515:17;507:6;503:30;499:41;496:50;493:70;;;559:1;556;549:12;493:70;178:391;;;;;:::o;574:888::-;749:6;757;765;773;781;834:3;822:9;813:7;809:23;805:33;802:53;;;851:1;848;841:12;802:53;891:9;878:23;-1:-1:-1;;;;;961:2:1;953:6;950:14;947:34;;;977:1;974;967:12;947:34;1000:70;1062:7;1053:6;1042:9;1038:22;1000:70;:::i;:::-;990:80;;1123:2;1112:9;1108:18;1095:32;1079:48;;1152:2;1142:8;1139:16;1136:36;;;1168:1;1165;1158:12;1136:36;;1207:93;1292:7;1281:8;1270:9;1266:24;1207:93;:::i;:::-;574:888;;1319:8;;-1:-1:-1;1181:119:1;;1401:2;1386:18;;1373:32;;1452:2;1437:18;;;1424:32;;-1:-1:-1;574:888:1;-1:-1:-1;;;;574:888:1:o;1467:430::-;1565:6;1573;1626:2;1614:9;1605:7;1601:23;1597:32;1594:52;;;1642:1;1639;1632:12;1594:52;1682:9;1669:23;-1:-1:-1;;;;;1707:6:1;1704:30;1701:50;;;1747:1;1744;1737:12;1701:50;1770:70;1832:7;1823:6;1812:9;1808:22;1770:70;:::i;:::-;1760:80;1887:2;1872:18;;;;1859:32;;-1:-1:-1;;;;1467:430:1:o;1902:173::-;1970:20;;-1:-1:-1;;;;;2019:31:1;;2009:42;;1999:70;;2065:1;2062;2055:12;1999:70;1902:173;;;:::o;2080:186::-;2139:6;2192:2;2180:9;2171:7;2167:23;2163:32;2160:52;;;2208:1;2205;2198:12;2160:52;2231:29;2250:9;2231:29;:::i;2453:322::-;2530:6;2538;2546;2599:2;2587:9;2578:7;2574:23;2570:32;2567:52;;;2615:1;2612;2605:12;2567:52;2638:29;2657:9;2638:29;:::i;:::-;2628:39;2714:2;2699:18;;2686:32;;-1:-1:-1;2765:2:1;2750:18;;;2737:32;;2453:322;-1:-1:-1;;;2453:322:1:o;2780:127::-;2841:10;2836:3;2832:20;2829:1;2822:31;2872:4;2869:1;2862:15;2896:4;2893:1;2886:15;2912:255;2984:2;2978:9;3026:6;3014:19;;-1:-1:-1;;;;;3048:34:1;;3084:22;;;3045:62;3042:88;;;3110:18;;:::i;:::-;3146:2;3139:22;2912:255;:::o;3172:275::-;3243:2;3237:9;3308:2;3289:13;;-1:-1:-1;;3285:27:1;3273:40;;-1:-1:-1;;;;;3328:34:1;;3364:22;;;3325:62;3322:88;;;3390:18;;:::i;:::-;3426:2;3419:22;3172:275;;-1:-1:-1;3172:275:1:o;3452:183::-;3512:4;-1:-1:-1;;;;;3537:6:1;3534:30;3531:56;;;3567:18;;:::i;:::-;-1:-1:-1;3612:1:1;3608:14;3624:4;3604:25;;3452:183::o;3640:662::-;3694:5;3747:3;3740:4;3732:6;3728:17;3724:27;3714:55;;3765:1;3762;3755:12;3714:55;3801:6;3788:20;3827:4;3851:60;3867:43;3907:2;3867:43;:::i;:::-;3851:60;:::i;:::-;3945:15;;;4031:1;4027:10;;;;4015:23;;4011:32;;;3976:12;;;;4055:15;;;4052:35;;;4083:1;4080;4073:12;4052:35;4119:2;4111:6;4107:15;4131:142;4147:6;4142:3;4139:15;4131:142;;;4213:17;;4201:30;;4251:12;;;;4164;;4131:142;;;-1:-1:-1;4291:5:1;3640:662;-1:-1:-1;;;;;;3640:662:1:o;4307:668::-;4361:5;4414:3;4407:4;4399:6;4395:17;4391:27;4381:55;;4432:1;4429;4422:12;4381:55;4468:6;4455:20;4494:4;4518:60;4534:43;4574:2;4534:43;:::i;4518:60::-;4612:15;;;4698:1;4694:10;;;;4682:23;;4678:32;;;4643:12;;;;4722:15;;;4719:35;;;4750:1;4747;4740:12;4719:35;4786:2;4778:6;4774:15;4798:148;4814:6;4809:3;4806:15;4798:148;;;4880:23;4899:3;4880:23;:::i;:::-;4868:36;;4924:12;;;;4831;;4798:148;;4980:530;5022:5;5075:3;5068:4;5060:6;5056:17;5052:27;5042:55;;5093:1;5090;5083:12;5042:55;5129:6;5116:20;-1:-1:-1;;;;;5151:2:1;5148:26;5145:52;;;5177:18;;:::i;:::-;5221:55;5264:2;5245:13;;-1:-1:-1;;5241:27:1;5270:4;5237:38;5221:55;:::i;:::-;5301:2;5292:7;5285:19;5347:3;5340:4;5335:2;5327:6;5323:15;5319:26;5316:35;5313:55;;;5364:1;5361;5354:12;5313:55;5429:2;5422:4;5414:6;5410:17;5403:4;5394:7;5390:18;5377:55;5477:1;5452:16;;;5470:4;5448:27;5441:38;;;;5456:7;4980:530;-1:-1:-1;;;4980:530:1:o;5515:2228::-;5712:6;5720;5728;5736;5789:2;5777:9;5768:7;5764:23;5760:32;5757:52;;;5805:1;5802;5795:12;5757:52;5845:9;5832:23;-1:-1:-1;;;;;5915:2:1;5907:6;5904:14;5901:34;;;5931:1;5928;5921:12;5901:34;5954:70;6016:7;6007:6;5996:9;5992:22;5954:70;:::i;:::-;5944:80;;6077:2;6066:9;6062:18;6049:32;6033:48;;6106:2;6096:8;6093:16;6090:36;;;6122:1;6119;6112:12;6090:36;6161:93;6246:7;6235:8;6224:9;6220:24;6161:93;:::i;:::-;6273:8;;-1:-1:-1;6135:119:1;-1:-1:-1;6361:2:1;6346:18;;6333:32;;-1:-1:-1;6377:16:1;;;6374:36;;;6406:1;6403;6396:12;6374:36;6429:24;;;;6487:6;6469:16;;;6465:29;6462:49;;;6507:1;6504;6497:12;6462:49;6533:22;;:::i;:::-;6593:2;6580:16;6621:2;6611:8;6608:16;6605:36;;;6637:1;6634;6627:12;6605:36;6664:56;6712:7;6701:8;6697:2;6693:17;6664:56;:::i;:::-;6657:5;6650:71;;6767:2;6763;6759:11;6746:25;6796:2;6786:8;6783:16;6780:36;;;6812:1;6809;6802:12;6780:36;6848:56;6896:7;6885:8;6881:2;6877:17;6848:56;:::i;:::-;6843:2;6836:5;6832:14;6825:80;;6951:2;6947;6943:11;6930:25;6980:2;6970:8;6967:16;6964:36;;;6996:1;6993;6986:12;6964:36;7032:56;7080:7;7069:8;7065:2;7061:17;7032:56;:::i;:::-;7027:2;7020:5;7016:14;7009:80;;7135:2;7131;7127:11;7114:25;7164:2;7154:8;7151:16;7148:36;;;7180:1;7177;7170:12;7148:36;7216:56;7264:7;7253:8;7249:2;7245:17;7216:56;:::i;:::-;7211:2;7204:5;7200:14;7193:80;;7306:32;7333:3;7329:2;7325:12;7306:32;:::i;:::-;7300:3;7293:5;7289:15;7282:57;7385:3;7381:2;7377:12;7364:26;7415:2;7405:8;7402:16;7399:36;;;7431:1;7428;7421:12;7399:36;7468:44;7504:7;7493:8;7489:2;7485:17;7468:44;:::i;:::-;7462:3;7455:5;7451:15;7444:69;;7567:3;7563:2;7559:12;7546:26;7540:3;7533:5;7529:15;7522:51;7627:3;7623:2;7619:12;7606:26;7600:3;7593:5;7589:15;7582:51;7652:3;7642:13;;7708:2;7704;7700:11;7687:25;7682:2;7675:5;7671:14;7664:49;7732:5;7722:15;;;;;5515:2228;;;;;;;:::o;7748:180::-;7807:6;7860:2;7848:9;7839:7;7835:23;7831:32;7828:52;;;7876:1;7873;7866:12;7828:52;-1:-1:-1;7899:23:1;;7748:180;-1:-1:-1;7748:180:1:o;7933:367::-;7996:8;8006:6;8060:3;8053:4;8045:6;8041:17;8037:27;8027:55;;8078:1;8075;8068:12;8027:55;-1:-1:-1;8101:20:1;;-1:-1:-1;;;;;8133:30:1;;8130:50;;;8176:1;8173;8166:12;8130:50;8213:4;8205:6;8201:17;8189:29;;8273:3;8266:4;8256:6;8253:1;8249:14;8241:6;8237:27;8233:38;8230:47;8227:67;;;8290:1;8287;8280:12;8305:1911;8597:6;8605;8613;8621;8629;8637;8645;8653;8661;8669;8677:7;8686;8740:3;8728:9;8719:7;8715:23;8711:33;8708:53;;;8757:1;8754;8747:12;8708:53;-1:-1:-1;;;;;8789:9:1;8776:23;8773:47;8770:67;;;8833:1;8830;8823:12;8770:67;8856:87;8935:7;8922:9;8909:23;8898:9;8894:39;8856:87;:::i;:::-;8846:97;;-1:-1:-1;;;;;8986:2:1;8975:9;8971:18;8958:32;8955:56;8952:76;;;9024:1;9021;9014:12;8952:76;9063:117;9172:7;9165:2;9154:9;9150:18;9137:32;9126:9;9122:48;9063:117;:::i;:::-;9199:8;;-1:-1:-1;9226:8:1;-1:-1:-1;;;;;;9277:2:1;9262:18;;9249:32;9246:56;9243:76;;;9315:1;9312;9305:12;9243:76;9354:96;9442:7;9435:2;9424:9;9420:18;9407:32;9396:9;9392:48;9354:96;:::i;:::-;9469:8;;-1:-1:-1;9496:8:1;-1:-1:-1;;;;;;9547:2:1;9532:18;;9519:32;9516:56;9513:76;;;9585:1;9582;9575:12;9513:76;9624:96;9712:7;9705:2;9694:9;9690:18;9677:32;9666:9;9662:48;9624:96;:::i;:::-;9739:8;;-1:-1:-1;9766:8:1;-1:-1:-1;;;;;;9817:3:1;9802:19;;9789:33;9786:57;9783:77;;;9856:1;9853;9846:12;9783:77;9895:97;9984:7;9976:3;9965:9;9961:19;9948:33;9937:9;9933:49;9895:97;:::i;:::-;10011:8;;-1:-1:-1;10038:8:1;-1:-1:-1;10093:3:1;10078:19;;10065:33;;-1:-1:-1;10118:39:1;10152:3;10137:19;;10118:39;:::i;:::-;10107:50;;10205:3;10194:9;10190:19;10177:33;10166:44;;8305:1911;;;;;;;;;;;;;;:::o;10221:991::-;10417:6;10425;10433;10441;10494:2;10482:9;10473:7;10469:23;10465:32;10462:52;;;10510:1;10507;10500:12;10462:52;10550:9;10537:23;-1:-1:-1;;;;;10620:2:1;10612:6;10609:14;10606:34;;;10636:1;10633;10626:12;10606:34;10659:70;10721:7;10712:6;10701:9;10697:22;10659:70;:::i;:::-;10649:80;;10782:2;10771:9;10767:18;10754:32;10738:48;;10811:2;10801:8;10798:16;10795:36;;;10827:1;10824;10817:12;10795:36;10850:72;10914:7;10903:8;10892:9;10888:24;10850:72;:::i;:::-;10840:82;;10975:2;10964:9;10960:18;10947:32;10931:48;;11004:2;10994:8;10991:16;10988:36;;;11020:1;11017;11010:12;10988:36;;11059:93;11144:7;11133:8;11122:9;11118:24;11059:93;:::i;:::-;10221:991;;;;-1:-1:-1;11171:8:1;-1:-1:-1;;;;10221:991:1:o;11399:348::-;11451:8;11461:6;11515:3;11508:4;11500:6;11496:17;11492:27;11482:55;;11533:1;11530;11523:12;11482:55;-1:-1:-1;11556:20:1;;-1:-1:-1;;;;;11588:30:1;;11585:50;;;11631:1;11628;11621:12;11585:50;11668:4;11660:6;11656:17;11644:29;;11720:3;11713:4;11704:6;11696;11692:19;11688:30;11685:39;11682:59;;;11737:1;11734;11727:12;11752:156;11818:20;;11878:4;11867:16;;11857:27;;11847:55;;11898:1;11895;11888:12;11913:1081;12033:6;12041;12049;12057;12065;12073;12081;12134:3;12122:9;12113:7;12109:23;12105:33;12102:53;;;12151:1;12148;12141:12;12102:53;12191:9;12178:23;-1:-1:-1;;;;;12261:2:1;12253:6;12250:14;12247:34;;;12277:1;12274;12267:12;12247:34;12316:59;12367:7;12358:6;12347:9;12343:22;12316:59;:::i;:::-;12394:8;;-1:-1:-1;12290:85:1;-1:-1:-1;12482:2:1;12467:18;;12454:32;;-1:-1:-1;12498:16:1;;;12495:36;;;12527:1;12524;12517:12;12495:36;12566:61;12619:7;12608:8;12597:9;12593:24;12566:61;:::i;:::-;12646:8;;-1:-1:-1;12540:87:1;-1:-1:-1;12734:2:1;12719:18;;12706:32;;-1:-1:-1;12750:16:1;;;12747:36;;;12779:1;12776;12769:12;12747:36;;12818:61;12871:7;12860:8;12849:9;12845:24;12818:61;:::i;:::-;12898:8;;-1:-1:-1;12792:87:1;-1:-1:-1;12952:36:1;;-1:-1:-1;12984:2:1;12969:18;;12952:36;:::i;:::-;12942:46;;11913:1081;;;;;;;;;;:::o;12999:1014::-;13107:9;13166:4;13158:5;13142:14;13138:26;13134:37;13131:57;;;13184:1;13181;13174:12;13131:57;13217:2;13211:9;13259:4;13251:6;13247:17;-1:-1:-1;;;;;13351:6:1;13339:10;13336:22;13331:2;13319:10;13316:18;13313:46;13310:72;;;13362:18;;:::i;:::-;13402:10;13398:2;13391:22;13449:5;13436:19;13422:33;;13478:2;13470:6;13467:14;13464:34;;;13494:1;13491;13484:12;13464:34;13522:64;13571:14;13562:6;13555:5;13551:18;13522:64;:::i;:::-;13514:6;13507:80;13636:2;13629:5;13625:14;13612:28;13596:44;;13665:2;13655:8;13652:16;13649:36;;;13681:1;13678;13671:12;13649:36;;13718:66;13769:14;13758:8;13751:5;13747:20;13718:66;:::i;:::-;13713:2;13705:6;13701:15;13694:91;;13842:2;13835:5;13831:14;13818:28;13813:2;13805:6;13801:15;13794:53;13904:2;13897:5;13893:14;13880:28;13875:2;13867:6;13863:15;13856:53;13943:35;13973:3;13966:5;13962:15;13943:35;:::i;:::-;13937:3;13925:16;;13918:61;13929:6;12999:1014;-1:-1:-1;;12999:1014:1:o;14018:355::-;14220:2;14202:21;;;14259:2;14239:18;;;14232:30;14298:33;14293:2;14278:18;;14271:61;14364:2;14349:18;;14018:355::o;14586:184::-;14656:6;14709:2;14697:9;14688:7;14684:23;14680:32;14677:52;;;14725:1;14722;14715:12;14677:52;-1:-1:-1;14748:16:1;;14586:184;-1:-1:-1;14586:184:1:o;14775:127::-;14836:10;14831:3;14827:20;14824:1;14817:31;14867:4;14864:1;14857:15;14891:4;14888:1;14881:15;14907:128;14947:3;14978:1;14974:6;14971:1;14968:13;14965:39;;;14984:18;;:::i;:::-;-1:-1:-1;15020:9:1;;14907:128::o;15040:125::-;15080:4;15108:1;15105;15102:8;15099:34;;;15113:18;;:::i;:::-;-1:-1:-1;15150:9:1;;15040:125::o;15423:435::-;15476:3;15514:5;15508:12;15541:6;15536:3;15529:19;15567:4;15596:2;15591:3;15587:12;15580:19;;15633:2;15626:5;15622:14;15654:1;15664:169;15678:6;15675:1;15672:13;15664:169;;;15739:13;;15727:26;;15773:12;;;;15808:15;;;;15700:1;15693:9;15664:169;;;-1:-1:-1;15849:3:1;;15423:435;-1:-1:-1;;;;;15423:435:1:o;15863:461::-;15916:3;15954:5;15948:12;15981:6;15976:3;15969:19;16007:4;16036:2;16031:3;16027:12;16020:19;;16073:2;16066:5;16062:14;16094:1;16104:195;16118:6;16115:1;16112:13;16104:195;;;16183:13;;-1:-1:-1;;;;;16179:39:1;16167:52;;16239:12;;;;16274:15;;;;16215:1;16133:9;16104:195;;16329:258;16401:1;16411:113;16425:6;16422:1;16419:13;16411:113;;;16501:11;;;16495:18;16482:11;;;16475:39;16447:2;16440:10;16411:113;;;16542:6;16539:1;16536:13;16533:48;;;-1:-1:-1;;16577:1:1;16559:16;;16552:27;16329:258::o;16592:257::-;16633:3;16671:5;16665:12;16698:6;16693:3;16686:19;16714:63;16770:6;16763:4;16758:3;16754:14;16747:4;16740:5;16736:16;16714:63;:::i;:::-;16831:2;16810:15;-1:-1:-1;;16806:29:1;16797:39;;;;16838:4;16793:50;;16592:257;-1:-1:-1;;16592:257:1:o;16854:1600::-;17529:4;17558:3;17588:6;17577:9;17570:25;17631:6;17626:2;17615:9;17611:18;17604:34;17674:2;17669;17658:9;17654:18;17647:30;17700:56;17752:2;17741:9;17737:18;17729:6;17700:56;:::i;:::-;17686:70;;17804:9;17796:6;17792:22;17787:2;17776:9;17772:18;17765:50;17838:44;17875:6;17867;17838:44;:::i;:::-;17824:58;;17931:9;17923:6;17919:22;17913:3;17902:9;17898:19;17891:51;17965:44;18002:6;17994;17965:44;:::i;:::-;17951:58;;18058:9;18050:6;18046:22;18040:3;18029:9;18025:19;18018:51;18092:44;18129:6;18121;18092:44;:::i;:::-;-1:-1:-1;;;;;18173:32:1;;18167:3;18152:19;;18145:61;18243:22;;;18237:3;18222:19;;18215:51;18078:58;-1:-1:-1;18283:32:1;18078:58;18300:6;18283:32;:::i;:::-;18346:3;18331:19;;18324:35;;;;-1:-1:-1;;18390:3:1;18375:19;;18368:35;;;;18434:3;18419:19;;;18412:36;18275:40;16854:1600;-1:-1:-1;;;;;;;;16854:1600:1:o;18459:127::-;18520:10;18515:3;18511:20;18508:1;18501:31;18551:4;18548:1;18541:15;18575:4;18572:1;18565:15;18591:135;18630:3;-1:-1:-1;;18651:17:1;;18648:43;;;18671:18;;:::i;:::-;-1:-1:-1;18718:1:1;18707:13;;18591:135::o;18731:432::-;18962:6;18951:9;18944:25;19005:6;19000:2;18989:9;18985:18;18978:34;19048:3;19043:2;19032:9;19028:18;19021:31;18925:4;19069:45;19109:3;19098:9;19094:19;19086:6;19069:45;:::i;:::-;19061:53;;19150:6;19145:2;19134:9;19130:18;19123:34;18731:432;;;;;;;:::o;19168:354::-;19256:19;;;19238:3;-1:-1:-1;;;;;19287:31:1;;19284:51;;;19331:1;19328;19321:12;19284:51;19367:6;19364:1;19360:14;19419:8;19412:5;19405:4;19400:3;19396:14;19383:45;19496:1;19451:18;;19471:4;19447:29;19485:13;;;-1:-1:-1;19447:29:1;;19168:354;-1:-1:-1;;19168:354:1:o;19527:447::-;19627:6;19622:3;19615:19;19597:3;19653:4;19682:2;19677:3;19673:12;19666:19;;19708:5;19731:1;19741:208;19755:6;19752:1;19749:13;19741:208;;;-1:-1:-1;;;;;19820:26:1;19839:6;19820:26;:::i;:::-;19816:52;19804:65;;19889:12;;;;19924:15;;;;19777:1;19770:9;19741:208;;19979:1243;20532:4;20561:3;20591:6;20580:9;20573:25;20634:6;20629:2;20618:9;20614:18;20607:34;20677:2;20672;20661:9;20657:18;20650:30;20703:73;20772:2;20761:9;20757:18;20749:6;20741;20703:73;:::i;:::-;20689:87;;20824:9;20816:6;20812:22;20807:2;20796:9;20792:18;20785:50;20858:61;20912:6;20904;20896;20858:61;:::i;:::-;20844:75;;20968:9;20960:6;20956:22;20950:3;20939:9;20935:19;20928:51;20996:61;21050:6;21042;21034;20996:61;:::i;:::-;21088:3;21073:19;;21066:35;;;;-1:-1:-1;;;;;;;21138:32:1;;;;21132:3;21117:19;;21110:61;21202:3;21187:19;;;21180:36;20988:69;19979:1243;-1:-1:-1;;;;;;;;19979:1243:1:o;21227:545::-;21320:4;21326:6;21386:11;21373:25;21480:2;21476:7;21465:8;21449:14;21445:29;21441:43;21421:18;21417:68;21407:96;;21499:1;21496;21489:12;21407:96;21526:33;;21578:20;;;-1:-1:-1;;;;;;21610:30:1;;21607:50;;;21653:1;21650;21643:12;21607:50;21686:4;21674:17;;-1:-1:-1;21737:1:1;21733:14;;;21717;21713:35;21703:46;;21700:66;;;21762:1;21759;21752:12;22327:761;22688:6;22677:9;22670:25;22731:6;22726:2;22715:9;22711:18;22704:34;22803:1;22799;22794:3;22790:11;22786:19;22778:6;22774:32;22769:2;22758:9;22754:18;22747:60;22843:3;22838:2;22827:9;22823:18;22816:31;22651:4;22870:74;22939:3;22928:9;22924:19;22916:6;22908;22870:74;:::i;:::-;22993:9;22985:6;22981:22;22975:3;22964:9;22960:19;22953:51;23021:61;23075:6;23067;23059;23021:61;:::i;:::-;23013:69;22327:761;-1:-1:-1;;;;;;;;;;22327:761:1:o;23093:267::-;23182:6;23177:3;23170:19;23234:6;23227:5;23220:4;23215:3;23211:14;23198:43;-1:-1:-1;23286:1:1;23261:16;;;23279:4;23257:27;;;23250:38;;;;23342:2;23321:15;;;-1:-1:-1;;23317:29:1;23308:39;;;23304:50;;23093:267::o;23365:614::-;-1:-1:-1;;;;;23634:32:1;;23616:51;;23703:3;23698:2;23683:18;;23676:31;;;-1:-1:-1;;23730:63:1;;23773:19;;23765:6;23757;23730:63;:::i;:::-;23841:9;23833:6;23829:22;23824:2;23813:9;23809:18;23802:50;23869;23912:6;23904;23896;23869:50;:::i;:::-;23861:58;;;23967:4;23959:6;23955:17;23950:2;23939:9;23935:18;23928:45;23365:614;;;;;;;;;:::o;23984:779::-;24311:3;24300:9;24293:22;24274:4;24338:63;24396:3;24385:9;24381:19;24373:6;24365;24338:63;:::i;:::-;24449:9;24441:6;24437:22;24432:2;24421:9;24417:18;24410:50;24483;24526:6;24518;24510;24483:50;:::i;:::-;24469:64;;24581:9;24573:6;24569:22;24564:2;24553:9;24549:18;24542:50;24609;24652:6;24644;24636;24609:50;:::i;:::-;24707:4;24695:17;;;;24690:2;24675:18;;24668:45;-1:-1:-1;;24744:3:1;24729:19;24722:35;24601:58;23984:779;-1:-1:-1;;;;;;23984:779:1:o;24768:182::-;24825:6;24878:2;24866:9;24857:7;24853:23;24849:32;24846:52;;;24894:1;24891;24884:12;24846:52;24917:27;24934:9;24917:27;:::i;24955:851::-;25352:6;25341:9;25334:25;25395:6;25390:2;25379:9;25375:18;25368:34;25438:6;25433:2;25422:9;25418:18;25411:34;25481:3;25476:2;25465:9;25461:18;25454:31;25315:4;25508:57;25560:3;25549:9;25545:19;25537:6;25508:57;:::i;:::-;25614:9;25606:6;25602:22;25596:3;25585:9;25581:19;25574:51;25642:44;25679:6;25671;25642:44;:::i;:::-;25717:3;25702:19;;25695:35;;;;-1:-1:-1;;;;;;;25767:32:1;;;;25761:3;25746:19;;;25739:61;25634:52;24955:851;-1:-1:-1;;;;;24955:851:1:o;26855:277::-;26922:6;26975:2;26963:9;26954:7;26950:23;26946:32;26943:52;;;26991:1;26988;26981:12;26943:52;27023:9;27017:16;27076:5;27069:13;27062:21;27055:5;27052:32;27042:60;;27098:1;27095;27088:12;28313:274;28442:3;28480:6;28474:13;28496:53;28542:6;28537:3;28530:4;28522:6;28518:17;28496:53;:::i;:::-;28565:16;;;;;28313:274;-1:-1:-1;;28313:274:1:o;28995:127::-;29056:10;29051:3;29047:20;29044:1;29037:31;29087:4;29084:1;29077:15;29111:4;29108:1;29101:15;30646:219;30795:2;30784:9;30777:21;30758:4;30815:44;30855:2;30844:9;30840:18;30832:6;30815:44;:::i
Swarm Source
ipfs://e0cc737c893f4f801f620d372b01df0f8d6fe82c9585b72e83600f517f252d7a
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.