Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 132 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Grant Allotment | 10795342 | 1665 days ago | IN | 0 ETH | 0.01931888 | ||||
Grant Allotment | 10795311 | 1665 days ago | IN | 0 ETH | 0.01894376 | ||||
Grant Allotment | 10795304 | 1665 days ago | IN | 0 ETH | 0.01856626 | ||||
Grant Allotment | 10794768 | 1665 days ago | IN | 0 ETH | 0.01594073 | ||||
Top Up | 10794550 | 1665 days ago | IN | 0 ETH | 0.00675975 | ||||
Grant Allotment | 10794466 | 1665 days ago | IN | 0 ETH | 0.01931641 | ||||
Grant Allotment | 10793117 | 1665 days ago | IN | 0 ETH | 0.01397158 | ||||
Top Up | 10792691 | 1665 days ago | IN | 0 ETH | 0.00781714 | ||||
Grant Allotment | 10791745 | 1665 days ago | IN | 0 ETH | 0.02100425 | ||||
Top Up | 10790895 | 1666 days ago | IN | 0 ETH | 0.00653317 | ||||
Top Up | 10789329 | 1666 days ago | IN | 0 ETH | 0.01744696 | ||||
Top Up | 10788496 | 1666 days ago | IN | 0 ETH | 0.01623852 | ||||
Grant Allotment | 10787598 | 1666 days ago | IN | 0 ETH | 0.02100425 | ||||
Grant Allotment | 10787358 | 1666 days ago | IN | 0 ETH | 0.02972096 | ||||
Grant Allotment | 10787350 | 1666 days ago | IN | 0 ETH | 0.03450257 | ||||
Top Up | 10787235 | 1666 days ago | IN | 0 ETH | 0.01484125 | ||||
Grant Allotment | 10787098 | 1666 days ago | IN | 0 ETH | 0.03825775 | ||||
Grant Allotment | 10787051 | 1666 days ago | IN | 0 ETH | 0.0375076 | ||||
Top Up | 10785543 | 1666 days ago | IN | 0 ETH | 0.01231106 | ||||
Top Up | 10783227 | 1667 days ago | IN | 0 ETH | 0.01857988 | ||||
Top Up | 10782149 | 1667 days ago | IN | 0 ETH | 0.01744696 | ||||
Top Up | 10781925 | 1667 days ago | IN | 0 ETH | 0.01616299 | ||||
Top Up | 10781925 | 1667 days ago | IN | 0 ETH | 0.01616299 | ||||
Top Up | 10777031 | 1668 days ago | IN | 0 ETH | 0.01842883 | ||||
Grant Allotment | 10777024 | 1668 days ago | IN | 0 ETH | 0.04575927 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
SatoshiAllotment
Compiler Version
v0.5.16+commit.9c3226ce
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-07-18 */ // SPDX-License-Identifier: Copyright@I AM Satoshi Global /** * * * ██|█|█|█| ██| ██|█|█|█|█| ██|█|█| ██|█|█|█| ██| █| ██| * ██| █ ██| █| ██| ██| █| ██| █ ██| █| ██| * ██| ██| █| ██| ██| █| ██| ██| █| ██| * ██|█|█|█| ██||█|█||█| ██| ██| █| ██|█|█|█| ██|█|█|█|█| ██| * ██| ██| █| ██| ██| █| ██| ██| █| ██| * █ ██| ██| █| ██| ██| █| █ ██| ██| █| ██| * ██|█|█|█| ██| █| ██| ██|█|█| ██|█|█|█| ██| █| ██| * * ██████ ██ ████ ████████ ██ ██ * ██ ██ ██ ██ ██ █ ██ ██ ██ * ██ ████ ██ ██ ██ ████████ ██ ██ ██ ██ * ██ ██ ██ ██ ██ ██ █ ██ ██ ██ * ██████ ████████ ████ ████████ ██ ██ ████████ * * * ███╗ ██████╗ * ██║ ██╔═══██╗ * ██║ ██║ ██║ * ██║ ██║ ██║ * ██║ ██╗ ╚██████╔╝ * ╚═╝ ╚═╝ ╚═════╝ * * URL: https://iamsatoshi.global * https://iamsatoshiglobal.io * */ // File: @openzeppelin/contracts/token/ERC20/IERC20.sol pragma solidity ^0.5.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ 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/math/SafeMath.sol pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @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) { // 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 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts 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. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts 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 mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message 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. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: @openzeppelin/contracts/utils/Address.sol pragma solidity ^0.5.5; /** * @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) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Converts an `address` into `address payable`. Note that this is * simply a type cast: the actual underlying value is not changed. * * _Available since v2.4.0._ */ function toPayable(address account) internal pure returns (address payable) { return address(uint160(account)); } /** * @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]. * * _Available since v2.4.0._ */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-call-value (bool success, ) = recipient.call.value(amount)(""); require(success, "Address: unable to send value, recipient may have reverted"); } } // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol pragma solidity ^0.5.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 ERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; 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)); } 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' // solhint-disable-next-line max-line-length 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).add(value); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 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. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. // solhint-disable-next-line max-line-length require(address(token).isContract(), "SafeERC20: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File: contracts/interfaces/ISatoshiToken.sol pragma solidity >=0.5.7 <0.7.0; interface ISatoshiToken{ /** * @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); function mint(address to, uint256 amount) external; function burn(uint256 amount) external; function burnFrom(address account, uint256 amount) external; function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); } // File: @openzeppelin/contracts/utils/EnumerableSet.sol pragma solidity ^0.5.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * As of v2.5.0, only `address` sets are supported. * * Include with `using EnumerableSet for EnumerableSet.AddressSet;`. * * _Available since v2.5.0._ * * @author Alberto Cuesta Cañada */ library EnumerableSet { struct AddressSet { // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping (address => uint256) index; address[] values; } /** * @dev Add a value to a set. O(1). * Returns false if the value was already in the set. */ function add(AddressSet storage set, address value) internal returns (bool) { if (!contains(set, value)){ set.index[value] = set.values.push(value); return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * Returns false if the value was not present in the set. */ function remove(AddressSet storage set, address value) internal returns (bool) { if (contains(set, value)){ uint256 toDeleteIndex = set.index[value] - 1; uint256 lastIndex = set.values.length - 1; // If the element we're deleting is the last one, we can just remove it without doing a swap if (lastIndex != toDeleteIndex) { address lastValue = set.values[lastIndex]; // Move the last value to the index where the deleted value is set.values[toDeleteIndex] = lastValue; // Update the index for the moved value set.index[lastValue] = toDeleteIndex + 1; // All indexes are 1-based } // Delete the index entry for the deleted value delete set.index[value]; // Delete the old entry for the moved value set.values.pop(); return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return set.index[value] != 0; } /** * @dev Returns an array with all values in the set. O(N). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * WARNING: This function may run out of gas on large sets: use {length} and * {get} instead in these cases. */ function enumerate(AddressSet storage set) internal view returns (address[] memory) { address[] memory output = new address[](set.values.length); for (uint256 i; i < set.values.length; i++){ output[i] = set.values[i]; } return output; } /** * @dev Returns the number of elements on the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return set.values.length; } /** @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function get(AddressSet storage set, uint256 index) internal view returns (address) { return set.values[index]; } } // File: @openzeppelin/contracts/GSN/Context.sol pragma solidity ^0.5.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 GSN 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. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File: contracts/dependencies/AccessControl.sol pragma solidity ^0.5.16; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ contract AccessControl is Context { using EnumerableSet for EnumerableSet.AddressSet; using Address for address; struct RoleData { EnumerableSet.AddressSet members; bytes32 adminRole; } mapping (bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view returns (bool) { return _roles[role].members.contains(account); } /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) public view returns (uint256) { return _roles[role].members.length(); } /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) public view returns (address) { return _roles[role].members.get(index); } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public { require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant"); _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public { require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke"); _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== */ function _setupRole(bytes32 role, address account) internal { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal { _roles[role].adminRole = adminRole; } function _grantRole(bytes32 role, address account) private { if (_roles[role].members.add(account)) { emit RoleGranted(role, account, _msgSender()); } } function _revokeRole(bytes32 role, address account) private { if (_roles[role].members.remove(account)) { emit RoleRevoked(role, account, _msgSender()); } } } // File: @openzeppelin/contracts/GSN/IRelayRecipient.sol pragma solidity ^0.5.0; /** * @dev Base interface for a contract that will be called via the GSN from {IRelayHub}. * * TIP: You don't need to write an implementation yourself! Inherit from {GSNRecipient} instead. */ interface IRelayRecipient { /** * @dev Returns the address of the {IRelayHub} instance this recipient interacts with. */ function getHubAddr() external view returns (address); /** * @dev Called by {IRelayHub} to validate if this recipient accepts being charged for a relayed call. Note that the * recipient will be charged regardless of the execution result of the relayed call (i.e. if it reverts or not). * * The relay request was originated by `from` and will be served by `relay`. `encodedFunction` is the relayed call * calldata, so its first four bytes are the function selector. The relayed call will be forwarded `gasLimit` gas, * and the transaction executed with a gas price of at least `gasPrice`. `relay`'s fee is `transactionFee`, and the * recipient will be charged at most `maxPossibleCharge` (in wei). `nonce` is the sender's (`from`) nonce for * replay attack protection in {IRelayHub}, and `approvalData` is a optional parameter that can be used to hold a signature * over all or some of the previous values. * * Returns a tuple, where the first value is used to indicate approval (0) or rejection (custom non-zero error code, * values 1 to 10 are reserved) and the second one is data to be passed to the other {IRelayRecipient} functions. * * {acceptRelayedCall} is called with 50k gas: if it runs out during execution, the request will be considered * rejected. A regular revert will also trigger a rejection. */ function acceptRelayedCall( address relay, address from, bytes calldata encodedFunction, uint256 transactionFee, uint256 gasPrice, uint256 gasLimit, uint256 nonce, bytes calldata approvalData, uint256 maxPossibleCharge ) external view returns (uint256, bytes memory); /** * @dev Called by {IRelayHub} on approved relay call requests, before the relayed call is executed. This allows to e.g. * pre-charge the sender of the transaction. * * `context` is the second value returned in the tuple by {acceptRelayedCall}. * * Returns a value to be passed to {postRelayedCall}. * * {preRelayedCall} is called with 100k gas: if it runs out during exection or otherwise reverts, the relayed call * will not be executed, but the recipient will still be charged for the transaction's cost. */ function preRelayedCall(bytes calldata context) external returns (bytes32); /** * @dev Called by {IRelayHub} on approved relay call requests, after the relayed call is executed. This allows to e.g. * charge the user for the relayed call costs, return any overcharges from {preRelayedCall}, or perform * contract-specific bookkeeping. * * `context` is the second value returned in the tuple by {acceptRelayedCall}. `success` is the execution status of * the relayed call. `actualCharge` is an estimate of how much the recipient will be charged for the transaction, * not including any gas used by {postRelayedCall} itself. `preRetVal` is {preRelayedCall}'s return value. * * * {postRelayedCall} is called with 100k gas: if it runs out during execution or otherwise reverts, the relayed call * and the call to {preRelayedCall} will be reverted retroactively, but the recipient will still be charged for the * transaction's cost. */ function postRelayedCall(bytes calldata context, bool success, uint256 actualCharge, bytes32 preRetVal) external; } // File: @openzeppelin/contracts/GSN/IRelayHub.sol pragma solidity ^0.5.0; /** * @dev Interface for `RelayHub`, the core contract of the GSN. Users should not need to interact with this contract * directly. * * See the https://github.com/OpenZeppelin/openzeppelin-gsn-helpers[OpenZeppelin GSN helpers] for more information on * how to deploy an instance of `RelayHub` on your local test network. */ interface IRelayHub { // Relay management /** * @dev Adds stake to a relay and sets its `unstakeDelay`. If the relay does not exist, it is created, and the caller * of this function becomes its owner. If the relay already exists, only the owner can call this function. A relay * cannot be its own owner. * * All Ether in this function call will be added to the relay's stake. * Its unstake delay will be assigned to `unstakeDelay`, but the new value must be greater or equal to the current one. * * Emits a {Staked} event. */ function stake(address relayaddr, uint256 unstakeDelay) external payable; /** * @dev Emitted when a relay's stake or unstakeDelay are increased */ event Staked(address indexed relay, uint256 stake, uint256 unstakeDelay); /** * @dev Registers the caller as a relay. * The relay must be staked for, and not be a contract (i.e. this function must be called directly from an EOA). * * This function can be called multiple times, emitting new {RelayAdded} events. Note that the received * `transactionFee` is not enforced by {relayCall}. * * Emits a {RelayAdded} event. */ function registerRelay(uint256 transactionFee, string calldata url) external; /** * @dev Emitted when a relay is registered or re-registerd. Looking at these events (and filtering out * {RelayRemoved} events) lets a client discover the list of available relays. */ event RelayAdded(address indexed relay, address indexed owner, uint256 transactionFee, uint256 stake, uint256 unstakeDelay, string url); /** * @dev Removes (deregisters) a relay. Unregistered (but staked for) relays can also be removed. * * Can only be called by the owner of the relay. After the relay's `unstakeDelay` has elapsed, {unstake} will be * callable. * * Emits a {RelayRemoved} event. */ function removeRelayByOwner(address relay) external; /** * @dev Emitted when a relay is removed (deregistered). `unstakeTime` is the time when unstake will be callable. */ event RelayRemoved(address indexed relay, uint256 unstakeTime); /** Deletes the relay from the system, and gives back its stake to the owner. * * Can only be called by the relay owner, after `unstakeDelay` has elapsed since {removeRelayByOwner} was called. * * Emits an {Unstaked} event. */ function unstake(address relay) external; /** * @dev Emitted when a relay is unstaked for, including the returned stake. */ event Unstaked(address indexed relay, uint256 stake); // States a relay can be in enum RelayState { Unknown, // The relay is unknown to the system: it has never been staked for Staked, // The relay has been staked for, but it is not yet active Registered, // The relay has registered itself, and is active (can relay calls) Removed // The relay has been removed by its owner and can no longer relay calls. It must wait for its unstakeDelay to elapse before it can unstake } /** * @dev Returns a relay's status. Note that relays can be deleted when unstaked or penalized, causing this function * to return an empty entry. */ function getRelay(address relay) external view returns (uint256 totalStake, uint256 unstakeDelay, uint256 unstakeTime, address payable owner, RelayState state); // Balance management /** * @dev Deposits Ether for a contract, so that it can receive (and pay for) relayed transactions. * * Unused balance can only be withdrawn by the contract itself, by calling {withdraw}. * * Emits a {Deposited} event. */ function depositFor(address target) external payable; /** * @dev Emitted when {depositFor} is called, including the amount and account that was funded. */ event Deposited(address indexed recipient, address indexed from, uint256 amount); /** * @dev Returns an account's deposits. These can be either a contracts's funds, or a relay owner's revenue. */ function balanceOf(address target) external view returns (uint256); /** * Withdraws from an account's balance, sending it back to it. Relay owners call this to retrieve their revenue, and * contracts can use it to reduce their funding. * * Emits a {Withdrawn} event. */ function withdraw(uint256 amount, address payable dest) external; /** * @dev Emitted when an account withdraws funds from `RelayHub`. */ event Withdrawn(address indexed account, address indexed dest, uint256 amount); // Relaying /** * @dev Checks if the `RelayHub` will accept a relayed operation. * Multiple things must be true for this to happen: * - all arguments must be signed for by the sender (`from`) * - the sender's nonce must be the current one * - the recipient must accept this transaction (via {acceptRelayedCall}) * * Returns a `PreconditionCheck` value (`OK` when the transaction can be relayed), or a recipient-specific error * code if it returns one in {acceptRelayedCall}. */ function canRelay( address relay, address from, address to, bytes calldata encodedFunction, uint256 transactionFee, uint256 gasPrice, uint256 gasLimit, uint256 nonce, bytes calldata signature, bytes calldata approvalData ) external view returns (uint256 status, bytes memory recipientContext); // Preconditions for relaying, checked by canRelay and returned as the corresponding numeric values. enum PreconditionCheck { OK, // All checks passed, the call can be relayed WrongSignature, // The transaction to relay is not signed by requested sender WrongNonce, // The provided nonce has already been used by the sender AcceptRelayedCallReverted, // The recipient rejected this call via acceptRelayedCall InvalidRecipientStatusCode // The recipient returned an invalid (reserved) status code } /** * @dev Relays a transaction. * * For this to succeed, multiple conditions must be met: * - {canRelay} must `return PreconditionCheck.OK` * - the sender must be a registered relay * - the transaction's gas price must be larger or equal to the one that was requested by the sender * - the transaction must have enough gas to not run out of gas if all internal transactions (calls to the * recipient) use all gas available to them * - the recipient must have enough balance to pay the relay for the worst-case scenario (i.e. when all gas is * spent) * * If all conditions are met, the call will be relayed and the recipient charged. {preRelayedCall}, the encoded * function and {postRelayedCall} will be called in that order. * * Parameters: * - `from`: the client originating the request * - `to`: the target {IRelayRecipient} contract * - `encodedFunction`: the function call to relay, including data * - `transactionFee`: fee (%) the relay takes over actual gas cost * - `gasPrice`: gas price the client is willing to pay * - `gasLimit`: gas to forward when calling the encoded function * - `nonce`: client's nonce * - `signature`: client's signature over all previous params, plus the relay and RelayHub addresses * - `approvalData`: dapp-specific data forwared to {acceptRelayedCall}. This value is *not* verified by the * `RelayHub`, but it still can be used for e.g. a signature. * * Emits a {TransactionRelayed} event. */ function relayCall( address from, address to, bytes calldata encodedFunction, uint256 transactionFee, uint256 gasPrice, uint256 gasLimit, uint256 nonce, bytes calldata signature, bytes calldata approvalData ) external; /** * @dev Emitted when an attempt to relay a call failed. * * This can happen due to incorrect {relayCall} arguments, or the recipient not accepting the relayed call. The * actual relayed call was not executed, and the recipient not charged. * * The `reason` parameter contains an error code: values 1-10 correspond to `PreconditionCheck` entries, and values * over 10 are custom recipient error codes returned from {acceptRelayedCall}. */ event CanRelayFailed(address indexed relay, address indexed from, address indexed to, bytes4 selector, uint256 reason); /** * @dev Emitted when a transaction is relayed. * Useful when monitoring a relay's operation and relayed calls to a contract * * Note that the actual encoded function might be reverted: this is indicated in the `status` parameter. * * `charge` is the Ether value deducted from the recipient's balance, paid to the relay's owner. */ event TransactionRelayed(address indexed relay, address indexed from, address indexed to, bytes4 selector, RelayCallStatus status, uint256 charge); // Reason error codes for the TransactionRelayed event enum RelayCallStatus { OK, // The transaction was successfully relayed and execution successful - never included in the event RelayedCallFailed, // The transaction was relayed, but the relayed call failed PreRelayedFailed, // The transaction was not relayed due to preRelatedCall reverting PostRelayedFailed, // The transaction was relayed and reverted due to postRelatedCall reverting RecipientBalanceChanged // The transaction was relayed and reverted due to the recipient's balance changing } /** * @dev Returns how much gas should be forwarded to a call to {relayCall}, in order to relay a transaction that will * spend up to `relayedCallStipend` gas. */ function requiredGas(uint256 relayedCallStipend) external view returns (uint256); /** * @dev Returns the maximum recipient charge, given the amount of gas forwarded, gas price and relay fee. */ function maxPossibleCharge(uint256 relayedCallStipend, uint256 gasPrice, uint256 transactionFee) external view returns (uint256); // Relay penalization. // Any account can penalize relays, removing them from the system immediately, and rewarding the // reporter with half of the relay's stake. The other half is burned so that, even if the relay penalizes itself, it // still loses half of its stake. /** * @dev Penalize a relay that signed two transactions using the same nonce (making only the first one valid) and * different data (gas price, gas limit, etc. may be different). * * The (unsigned) transaction data and signature for both transactions must be provided. */ function penalizeRepeatedNonce(bytes calldata unsignedTx1, bytes calldata signature1, bytes calldata unsignedTx2, bytes calldata signature2) external; /** * @dev Penalize a relay that sent a transaction that didn't target `RelayHub`'s {registerRelay} or {relayCall}. */ function penalizeIllegalTransaction(bytes calldata unsignedTx, bytes calldata signature) external; /** * @dev Emitted when a relay is penalized. */ event Penalized(address indexed relay, address sender, uint256 amount); /** * @dev Returns an account's nonce in `RelayHub`. */ function getNonce(address from) external view returns (uint256); } // File: @openzeppelin/contracts/GSN/GSNRecipient.sol pragma solidity ^0.5.0; /** * @dev Base GSN recipient contract: includes the {IRelayRecipient} interface * and enables GSN support on all contracts in the inheritance tree. * * TIP: This contract is abstract. The functions {IRelayRecipient-acceptRelayedCall}, * {_preRelayedCall}, and {_postRelayedCall} are not implemented and must be * provided by derived contracts. See the * xref:ROOT:gsn-strategies.adoc#gsn-strategies[GSN strategies] for more * information on how to use the pre-built {GSNRecipientSignature} and * {GSNRecipientERC20Fee}, or how to write your own. */ contract GSNRecipient is IRelayRecipient, Context { // Default RelayHub address, deployed on mainnet and all testnets at the same address address private _relayHub = 0xD216153c06E857cD7f72665E0aF1d7D82172F494; uint256 constant private RELAYED_CALL_ACCEPTED = 0; uint256 constant private RELAYED_CALL_REJECTED = 11; // How much gas is forwarded to postRelayedCall uint256 constant internal POST_RELAYED_CALL_MAX_GAS = 100000; /** * @dev Emitted when a contract changes its {IRelayHub} contract to a new one. */ event RelayHubChanged(address indexed oldRelayHub, address indexed newRelayHub); /** * @dev Returns the address of the {IRelayHub} contract for this recipient. */ function getHubAddr() public view returns (address) { return _relayHub; } /** * @dev Switches to a new {IRelayHub} instance. This method is added for future-proofing: there's no reason to not * use the default instance. * * IMPORTANT: After upgrading, the {GSNRecipient} will no longer be able to receive relayed calls from the old * {IRelayHub} instance. Additionally, all funds should be previously withdrawn via {_withdrawDeposits}. */ function _upgradeRelayHub(address newRelayHub) internal { address currentRelayHub = _relayHub; require(newRelayHub != address(0), "GSNRecipient: new RelayHub is the zero address"); require(newRelayHub != currentRelayHub, "GSNRecipient: new RelayHub is the current one"); emit RelayHubChanged(currentRelayHub, newRelayHub); _relayHub = newRelayHub; } /** * @dev Returns the version string of the {IRelayHub} for which this recipient implementation was built. If * {_upgradeRelayHub} is used, the new {IRelayHub} instance should be compatible with this version. */ // This function is view for future-proofing, it may require reading from // storage in the future. function relayHubVersion() public view returns (string memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return "1.0.0"; } /** * @dev Withdraws the recipient's deposits in `RelayHub`. * * Derived contracts should expose this in an external interface with proper access control. */ function _withdrawDeposits(uint256 amount, address payable payee) internal { IRelayHub(_relayHub).withdraw(amount, payee); } // Overrides for Context's functions: when called from RelayHub, sender and // data require some pre-processing: the actual sender is stored at the end // of the call data, which in turns means it needs to be removed from it // when handling said data. /** * @dev Replacement for msg.sender. Returns the actual sender of a transaction: msg.sender for regular transactions, * and the end-user for GSN relayed calls (where msg.sender is actually `RelayHub`). * * IMPORTANT: Contracts derived from {GSNRecipient} should never use `msg.sender`, and use {_msgSender} instead. */ function _msgSender() internal view returns (address payable) { if (msg.sender != _relayHub) { return msg.sender; } else { return _getRelayedCallSender(); } } /** * @dev Replacement for msg.data. Returns the actual calldata of a transaction: msg.data for regular transactions, * and a reduced version for GSN relayed calls (where msg.data contains additional information). * * IMPORTANT: Contracts derived from {GSNRecipient} should never use `msg.data`, and use {_msgData} instead. */ function _msgData() internal view returns (bytes memory) { if (msg.sender != _relayHub) { return msg.data; } else { return _getRelayedCallData(); } } // Base implementations for pre and post relayedCall: only RelayHub can invoke them, and data is forwarded to the // internal hook. /** * @dev See `IRelayRecipient.preRelayedCall`. * * This function should not be overriden directly, use `_preRelayedCall` instead. * * * Requirements: * * - the caller must be the `RelayHub` contract. */ function preRelayedCall(bytes calldata context) external returns (bytes32) { require(msg.sender == getHubAddr(), "GSNRecipient: caller is not RelayHub"); return _preRelayedCall(context); } /** * @dev See `IRelayRecipient.preRelayedCall`. * * Called by `GSNRecipient.preRelayedCall`, which asserts the caller is the `RelayHub` contract. Derived contracts * must implement this function with any relayed-call preprocessing they may wish to do. * */ function _preRelayedCall(bytes memory context) internal returns (bytes32); /** * @dev See `IRelayRecipient.postRelayedCall`. * * This function should not be overriden directly, use `_postRelayedCall` instead. * * * Requirements: * * - the caller must be the `RelayHub` contract. */ function postRelayedCall(bytes calldata context, bool success, uint256 actualCharge, bytes32 preRetVal) external { require(msg.sender == getHubAddr(), "GSNRecipient: caller is not RelayHub"); _postRelayedCall(context, success, actualCharge, preRetVal); } /** * @dev See `IRelayRecipient.postRelayedCall`. * * Called by `GSNRecipient.postRelayedCall`, which asserts the caller is the `RelayHub` contract. Derived contracts * must implement this function with any relayed-call postprocessing they may wish to do. * */ function _postRelayedCall(bytes memory context, bool success, uint256 actualCharge, bytes32 preRetVal) internal; /** * @dev Return this in acceptRelayedCall to proceed with the execution of a relayed call. Note that this contract * will be charged a fee by RelayHub */ function _approveRelayedCall() internal pure returns (uint256, bytes memory) { return _approveRelayedCall(""); } /** * @dev See `GSNRecipient._approveRelayedCall`. * * This overload forwards `context` to _preRelayedCall and _postRelayedCall. */ function _approveRelayedCall(bytes memory context) internal pure returns (uint256, bytes memory) { return (RELAYED_CALL_ACCEPTED, context); } /** * @dev Return this in acceptRelayedCall to impede execution of a relayed call. No fees will be charged. */ function _rejectRelayedCall(uint256 errorCode) internal pure returns (uint256, bytes memory) { return (RELAYED_CALL_REJECTED + errorCode, ""); } /* * @dev Calculates how much RelayHub will charge a recipient for using `gas` at a `gasPrice`, given a relayer's * `serviceFee`. */ function _computeCharge(uint256 gas, uint256 gasPrice, uint256 serviceFee) internal pure returns (uint256) { // The fee is expressed as a percentage. E.g. a value of 40 stands for a 40% fee, so the recipient will be // charged for 1.4 times the spent amount. return (gas * gasPrice * (100 + serviceFee)) / 100; } function _getRelayedCallSender() private pure returns (address payable result) { // We need to read 20 bytes (an address) located at array index msg.data.length - 20. In memory, the array // is prefixed with a 32-byte length value, so we first add 32 to get the memory read index. However, doing // so would leave the address in the upper 20 bytes of the 32-byte word, which is inconvenient and would // require bit shifting. We therefore subtract 12 from the read index so the address lands on the lower 20 // bytes. This can always be done due to the 32-byte prefix. // The final memory read index is msg.data.length - 20 + 32 - 12 = msg.data.length. Using inline assembly is the // easiest/most-efficient way to perform this operation. // These fields are not accessible from assembly bytes memory array = msg.data; uint256 index = msg.data.length; // solhint-disable-next-line no-inline-assembly assembly { // Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those. result := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff) } return result; } function _getRelayedCallData() private pure returns (bytes memory) { // RelayHub appends the sender address at the end of the calldata, so in order to retrieve the actual msg.data, // we must strip the last 20 bytes (length of an address type) from it. uint256 actualDataLength = msg.data.length - 20; bytes memory actualData = new bytes(actualDataLength); for (uint256 i = 0; i < actualDataLength; ++i) { actualData[i] = msg.data[i]; } return actualData; } } // File: @openzeppelin/contracts/cryptography/ECDSA.sol pragma solidity ^0.5.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 { /** * @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. * * NOTE: This call _does not revert_ if the signature is invalid, or * if the signer is otherwise unable to be retrieved. In those scenarios, * the zero address is returned. * * 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) { // Check the signature length if (signature.length != 65) { return (address(0)); } // Divide the signature in r, s and v variables bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. // solhint-disable-next-line no-inline-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } // 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 (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): 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); } if (v != 27 && v != 28) { return address(0); } // If the signature is valid (and not malleable), return the signer address return ecrecover(hash, v, r, s); } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * replicates the behavior of the * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`] * JSON-RPC method. * * 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)); } } // File: contracts/dependencies/GSNRecipientSignature.sol pragma solidity ^0.5.16; /** * @dev A xref:ROOT:gsn-strategies.adoc#gsn-strategies[GSN strategy] that allows relayed transactions through when they are * accompanied by the signature of a trusted signer. The intent is for this signature to be generated by a server that * performs validations off-chain. Note that nothing is charged to the user in this scheme. Thus, the server should make * sure to account for this in their economic and threat model. */ contract GSNRecipientSignature is GSNRecipient { using ECDSA for bytes32; address private _trustedSigner; enum GSNRecipientSignatureErrorCodes { INVALID_SIGNER } /** * @dev Sets the trusted signer that is going to be producing signatures to approve relayed calls. */ constructor(address trustedSigner) public { require(trustedSigner != address(0), "GSNRecipientSignature: trusted signer is the zero address"); _trustedSigner = trustedSigner; } /** * @dev Sets the trusted signer that is going to be producing signatures to approve relayed calls. */ function setTrustedSigner(address trustedSigner) public { require(trustedSigner != address(0), "GSNRecipientSignature: trusted signer is the zero address"); _trustedSigner = trustedSigner; } /** * @dev Ensures that only transactions with a trusted signature can be relayed through the GSN. */ function acceptRelayedCall( address relay, address from, bytes calldata encodedFunction, uint256 transactionFee, uint256 gasPrice, uint256 gasLimit, uint256 nonce, bytes calldata approvalData, uint256 ) external view returns (uint256, bytes memory) { bytes memory blob = abi.encodePacked( relay, from, encodedFunction, transactionFee, gasPrice, gasLimit, nonce, // Prevents replays on RelayHub getHubAddr(), // Prevents replays in multiple RelayHubs address(this) // Prevents replays in multiple recipients ); if (keccak256(blob).toEthSignedMessageHash().recover(approvalData) == _trustedSigner) { return _approveRelayedCall(); } else { return _rejectRelayedCall(uint256(GSNRecipientSignatureErrorCodes.INVALID_SIGNER)); } } function _preRelayedCall(bytes memory) internal returns (bytes32) { // solhint-disable-previous-line no-empty-blocks } function _postRelayedCall(bytes memory, bool, uint256, bytes32) internal { // solhint-disable-previous-line no-empty-blocks } } // File: contracts/dependencies/SafeMath64.sol pragma solidity ^0.5.16; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath64 { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint64 a, uint64 b) internal pure returns (uint64) { uint64 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint64 a, uint64 b) internal pure returns (uint64) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint64 a, uint64 b, string memory errorMessage) internal pure returns (uint64) { require(b <= a, errorMessage); uint64 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint64 a, uint64 b) internal pure returns (uint64) { // 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 0; } uint64 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts 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(uint64 a, uint64 b) internal pure returns (uint64) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts 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(uint64 a, uint64 b, string memory errorMessage) internal pure returns (uint64) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint64 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts 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(uint64 a, uint64 b) internal pure returns (uint64) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message 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(uint64 a, uint64 b, string memory errorMessage) internal pure returns (uint64) { require(b != 0, errorMessage); return a % b; } } // File: contracts/SatoshiAllotment.sol pragma solidity ^0.5.16; pragma experimental ABIEncoderV2; /** * @dev This contract handles allotment of Satoshi Token either thru direct buying * or approved grants from platform */ contract SatoshiAllotment is AccessControl, GSNRecipientSignature { using SafeERC20 for ISatoshiToken; using SafeMath for uint256; using SafeMath64 for uint64; // Alloter role who has permission to allot satoshi tokens bytes32 public constant ALLOTER_ROLE = keccak256("ALLOTER_ROLE"); // Allotment request details struct AllotmentRequest { // Id of the allotment uint64 id; uint64 start; uint64 cliff; uint64 duration; // Total amount of alloted tokens to be released uint256 amount; // Amount Released uint256 amountReleased; } // Allotment response for get functions struct AllotmentResponse { // Id of the allotment uint64 id; uint64 start; uint64 cliff; uint64 duration; // Total amount of alloted tokens to be released uint256 amount; // Amount Released uint256 amountReleased; // Amount available uint256 amountAvailable; } // Allotment plan details struct AllotmentPlan { uint64 id; bool isValid; uint64 cliffDuration; uint64 duration; } struct TopUpData { address account; uint64 id; uint256 amount; } // Satoshi token Contract ISatoshiToken private _satoshiToken; // Allotment plans array AllotmentPlan[] private _allotmentPlans; // Allotment Requests mapping mapping(address => AllotmentRequest[]) private _allotmentRequests; // Event definitions event TokenContractChanged(address indexed newAddress); event GrantedAllotment(address indexed account, uint256 id, uint256 amount, uint256 indexed timestamp); event TopUpAdded(address indexed account, uint256 indexed id, uint256 amount, uint256 indexed timestamp); event PlanAdded(uint256 indexed id, uint64 cliffDuration, uint64 duration); event PlanRemoved(uint256 indexed id); event ReleasedAmount(address indexed account, uint64[] ids, uint256[] amounts, uint256 indexed timestamp); /** * @dev Initialize the contract with Satoshi token address, * cliff and duration for default plan. * * @param satoshiToken - Satoshi Token address * @param cliffDuration - Additional cliff after the allotment start date * @param duration - Duration of the allotment, i.e. say 100 days * @param trustedSigner - Trusted signer for GSN */ constructor( address satoshiToken, uint64 cliffDuration, uint64 duration, address trustedSigner ) public GSNRecipientSignature(trustedSigner) { require(satoshiToken != address(0), "SatoshiAllotment: token is zero address"); require(cliffDuration <= duration, "SatoshiAllotment: cliff is longer than duration"); require(duration > 0, "SatoshiAllotment: duration is 0"); _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); _setupRole(ALLOTER_ROLE, _msgSender()); // Set Satoshi ERC20 token Contract _satoshiToken = ISatoshiToken(satoshiToken); // Add allotment plan _allotmentPlans.push(AllotmentPlan({ id: 0, isValid: true, cliffDuration: cliffDuration, duration: duration })); emit PlanAdded(_allotmentPlans.length.sub(1), cliffDuration, duration); } /** * @dev Sets the trusted signer that is going to be producing signatures to approve relayed calls. * * @param trustedSigner - Address of the trusted signer for GSN * * Requirements: * * - the caller must have the `DEFAULT_ADMIN_ROLE` */ function setTrustedSigner(address trustedSigner) public { require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "SatoshiToken: must have admin role to change trustedSigner"); super.setTrustedSigner(trustedSigner); } /** * @dev Get Satoshi token contract address. * * @return account - Address of Satoshi Token contract */ function getSatoshiTokenContract() public view returns (address) { return address(_satoshiToken); } /** * @dev Get allotment plans * * @param cursor - Cursor index to start * @param maxLength - Max length of allotments to retrieve * * @return AllotmentPlan[] - Allotment plan array * uint256 - Count of responses */ function getAllotmentPlans( uint256 cursor, uint256 maxLength) public view returns (AllotmentPlan[] memory, uint256){ uint256 length = maxLength; if (length > _allotmentPlans.length) length = _allotmentPlans.length; AllotmentPlan[] memory responses = new AllotmentPlan[](length); uint256 idCounter = 0; for (uint256 i = cursor; i < _allotmentPlans.length; i++) { AllotmentPlan memory plan = _allotmentPlans[i]; if (true == plan.isValid) { // Fill response responses[idCounter].id = plan.id; responses[idCounter].isValid = plan.isValid; responses[idCounter].cliffDuration = plan.cliffDuration; responses[idCounter].duration = plan.duration; idCounter++; // Check for requested length if (idCounter >= length) break; } } return (responses, idCounter); } /** * @dev Is allotment plan valid * * @param id - Allotment plan ID * * @return bool - Plan valid or not */ function isAllotmentPlanValid(uint64 id) public view returns (bool) { return _allotmentPlans[id].isValid; } /** * @dev Get allotment plan details for an ID * * @param id - Allotment plan ID * * @return AllotmentPlan - Plan details */ function getAllotmentPlanById(uint64 id) public view returns (AllotmentPlan memory) { return _allotmentPlans[id]; } /** * @dev Calculates the releasable amount that has already vested but * hasn't been released yet. * * @param request - Allotment request details * * @return uint256 - releasable amount */ function _releasableAmount(AllotmentRequest memory request) private view returns (uint256) { return _allottedAmount(request).sub(request.amountReleased); } /** * @dev Calculates the amount that has already allotted. * * @param request - Allotment request details * * @return uint256 - allotted amount */ function _allottedAmount(AllotmentRequest memory request) private view returns (uint256) { uint256 totalBalance = request.amount; if (block.timestamp < request.cliff) { return 0; } else if (block.timestamp >= (request.start.add(request.duration))) { return totalBalance; } else { uint256 timeDiff = block.timestamp.sub((uint256)(request.start)); return totalBalance.mul(timeDiff).div((uint256)(request.duration)); } } /** * @dev Get allotment details per account * * @param account - Address of the user * @param cursor - Cursor index to start * @param maxLength - Max length of allotments to retrieve * * @return AllotmentResponse[] - Allotment details array of the user * uint256 - Count of allotments */ function getAllotmentsByAccount( address account, uint256 cursor, uint256 maxLength, bool includeUpcoming, bool includeAll) public view returns (AllotmentResponse[] memory, uint256){ AllotmentRequest[] memory requests = _allotmentRequests[account]; uint256 allotmentLen = requests.length; uint256 length = maxLength; if (length > allotmentLen) length = allotmentLen; AllotmentResponse[] memory responses = new AllotmentResponse[](length); uint256 idCounter = 0; for (uint256 i = cursor; i < allotmentLen; i++) { uint256 releasableAmount; AllotmentRequest memory request = requests[i]; if (block.timestamp >= request.cliff) { releasableAmount = _releasableAmount(request); } if ((releasableAmount > 0) || ((true == includeUpcoming) && (block.timestamp < request.cliff)) || (true == includeAll)) { // Fill response responses[idCounter].id = request.id; responses[idCounter].amount = request.amount; responses[idCounter].start = request.start; responses[idCounter].cliff = request.cliff; responses[idCounter].duration = request.duration; responses[idCounter].amountReleased = request.amountReleased; responses[idCounter].amountAvailable = releasableAmount; idCounter++; // Check for requested length if (idCounter >= length) break; } } return (responses, idCounter); } /** * @dev Get allotment details by ID * * @param account - Address of the user * @param id - Allotment ID * * @return AllotmentResponse - Details of an allotment ID */ function getAllotmentById(address account, uint64 id) public view returns (AllotmentResponse memory) { AllotmentRequest memory request = _allotmentRequests[account][id]; uint256 releasableAmount = _releasableAmount(request); return (AllotmentResponse({ id: request.id, amount: request.amount, start: request.start, cliff: request.cliff, duration: request.duration, amountReleased: request.amountReleased, amountAvailable: releasableAmount })); } /** * @dev Change the Satoshi Token contract * * @param newAddress New Address of the token * Requirements: * * - the caller must have the admin role. */ function changeSatoshiTokenContract(address newAddress) external { require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "SatoshiAllotment: must have admin role to change satoshi token contract" ); // Change Satoshi ERC20 token Contract _satoshiToken = ISatoshiToken(newAddress); emit TokenContractChanged(newAddress); } /** * @dev Grant alloter role. * @param account - Address of the alloter to be granted * Requirements: * * - the caller must have the admin role. */ function grantAlloterRole(address account) external { require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "SatoshiAllotment: sender must be an admin to grant"); super.grantRole(ALLOTER_ROLE, account); } /** * @dev Add an allotment plan. * * @param cliffDuration - Additional cliff after the allotment start date * @param duration - Duration of the allotment, i.e. say 100 days * * Requirements: * * - the caller must have the admin role. */ function addAllotmentPlan(uint64 cliffDuration, uint64 duration) external { require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "SatoshiAllotment: must have admin role to add plan" ); require(cliffDuration <= duration, "SatoshiAllotment: cliff is longer than duration"); require(duration > 0, "SatoshiAllotment: duration is 0"); uint256 length = _allotmentPlans.length; _allotmentPlans.push(AllotmentPlan({ id: (uint64)(length), isValid: true, cliffDuration: cliffDuration, duration: duration })); emit PlanAdded(length, cliffDuration, duration); } /** * @dev Remove an existing allotment plan. * * @param id - Pland ID to be removed. * * Requirements: * * - the caller must have the admin role. */ function removeAllotmentPlan(uint256 id) external { require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "SatoshiAllotment: must have admin role to remove plan" ); require(_allotmentPlans[id].isValid == true, "SatoshiAllotment: deleted plan"); delete(_allotmentPlans[id]); emit PlanRemoved(id); } /** * @dev Grant an allotment to user. * * @param account - Address of user to be allotted * @param start - Start timestamp of the allotment * @param planId - Allotment plan ID. * * @return (uint64) - ID of the allotment * * Requirements: * * - the caller must have the alloter role. * - account cannot be zero address * - start time should be greater than or equal to block timestamp * - plan id should be a valid plan * - max id limit shouldn't have been reached */ function grantAllotment(address account, uint256 amount, uint64 start, uint256 planId) external returns (uint64) { require(hasRole(ALLOTER_ROLE, _msgSender()), "SatoshiAllotment: must have alloter role to allot tokens" ); require(account != address(0), "SatoshiAllotment: account is zero address"); require(start >= block.timestamp, "SatoshiAllotment: start < now"); // Get allotment plan details, verify the same AllotmentPlan memory plan = _allotmentPlans[planId]; require(plan.isValid == true, "SatoshiAllotment: deleted plan"); uint256 id = _allotmentRequests[account].length; require(id < (uint256)(~uint64(0)), "SatoshiAllotment: Max allotment IDs reached"); _allotmentRequests[account].push(AllotmentRequest({ id: (uint64)(id), start: start, cliff: start.add(plan.cliffDuration), duration: plan.duration, amount: amount, amountReleased: 0 })); emit GrantedAllotment(account, (uint64)(id), amount, block.timestamp); return (uint64)(id); } /** * @dev Topup existing allotments. * * @param accounts[] - Address of user to be allotted * @param ids[] - Allotment ID * @param amounts[] - Amount to be topped-up * * Requirements: * * - the caller must have the alloter role * - length of accounts, ids, amounts should be same * - accounts cannot be zero address * - allotments should be valid */ function topUp(address[] calldata accounts, uint64[] calldata ids, uint256[] calldata amounts) external { require(hasRole(ALLOTER_ROLE, _msgSender()), "SatoshiAllotment: must have alloter role to topup allotment tokens" ); require(accounts.length == ids.length, "SatoshiAllotment: accounts length doesn't match with ids length"); require(ids.length == amounts.length, "SatoshiAllotment: ids length doesn't match with amounts length"); for (uint256 i = 0; i < accounts.length; i++) { require(accounts[i] != address(0), "SatoshiAllotment: account is zero address"); require(amounts[i] > 0, "SatoshiAllotment: amount is zero"); AllotmentRequest storage requestPointer = _allotmentRequests[accounts[i]][ids[i]]; // Check for validity of the allotment require(requestPointer.start.add(requestPointer.duration) > block.timestamp, "SatoshiAllotment: allotment has expired"); // Add the topup amount to the existing amount requestPointer.amount += amounts[i]; emit TopUpAdded(accounts[i], ids[i], amounts[i], block.timestamp); } } /** * @dev Release available tokens from requested allotment ids * * @param account - Address of the allottee * @param ids - Array of allotment ids * */ function release(address account, uint64[] calldata ids) external { require(account != address(0), "SatoshiAllotment: account is zero address"); require(ids.length > 0, "SatoshiAllotment: Ids are empty"); uint256 amountToBeReleased = 0; uint256 totalAmountToBeReleased = 0; // Access the allotments of an account AllotmentRequest[] storage requests = _allotmentRequests[account]; uint256 allotmentLen = requests.length; uint256 maxLength = ids.length; // Amounts released as part of Response uint256[] memory amountsReleased = new uint256[](maxLength); if (maxLength > allotmentLen) maxLength = allotmentLen; for (uint256 i = 0; i < maxLength; i++) { // Verify whether id is within max allotments require (ids[i] < allotmentLen, "SatoshiAllotment: invalid allotment id"); // Get request storage pointer to update the amount released AllotmentRequest storage requestPointer = requests[ids[i]]; // Copy the content of allotment request into memory to save gas AllotmentRequest memory request = requests[ids[i]]; if (block.timestamp >= request.cliff) { amountToBeReleased = _releasableAmount(request); totalAmountToBeReleased = totalAmountToBeReleased.add(amountToBeReleased); amountsReleased[i] = amountToBeReleased; // Delete when allotment is completed if ((request.amountReleased.add(amountToBeReleased)) >= request.amount) delete(requests[ids[i]]); else // Update released amount requestPointer.amountReleased = request.amountReleased.add(amountToBeReleased); } } // Mint Satoshi for the account address if (totalAmountToBeReleased > 0) _satoshiToken.mint(account, totalAmountToBeReleased); emit ReleasedAmount(account, ids, amountsReleased, block.timestamp); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"satoshiToken","type":"address"},{"internalType":"uint64","name":"cliffDuration","type":"uint64"},{"internalType":"uint64","name":"duration","type":"uint64"},{"internalType":"address","name":"trustedSigner","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"GrantedAllotment","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"cliffDuration","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"duration","type":"uint64"}],"name":"PlanAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"PlanRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldRelayHub","type":"address"},{"indexed":true,"internalType":"address","name":"newRelayHub","type":"address"}],"name":"RelayHubChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint64[]","name":"ids","type":"uint64[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"indexed":true,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ReleasedAmount","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newAddress","type":"address"}],"name":"TokenContractChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"TopUpAdded","type":"event"},{"constant":true,"inputs":[],"name":"ALLOTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"relay","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"bytes","name":"encodedFunction","type":"bytes"},{"internalType":"uint256","name":"transactionFee","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"approvalData","type":"bytes"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"acceptRelayedCall","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint64","name":"cliffDuration","type":"uint64"},{"internalType":"uint64","name":"duration","type":"uint64"}],"name":"addAllotmentPlan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newAddress","type":"address"}],"name":"changeSatoshiTokenContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint64","name":"id","type":"uint64"}],"name":"getAllotmentById","outputs":[{"components":[{"internalType":"uint64","name":"id","type":"uint64"},{"internalType":"uint64","name":"start","type":"uint64"},{"internalType":"uint64","name":"cliff","type":"uint64"},{"internalType":"uint64","name":"duration","type":"uint64"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"amountReleased","type":"uint256"},{"internalType":"uint256","name":"amountAvailable","type":"uint256"}],"internalType":"struct SatoshiAllotment.AllotmentResponse","name":"","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint64","name":"id","type":"uint64"}],"name":"getAllotmentPlanById","outputs":[{"components":[{"internalType":"uint64","name":"id","type":"uint64"},{"internalType":"bool","name":"isValid","type":"bool"},{"internalType":"uint64","name":"cliffDuration","type":"uint64"},{"internalType":"uint64","name":"duration","type":"uint64"}],"internalType":"struct SatoshiAllotment.AllotmentPlan","name":"","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"cursor","type":"uint256"},{"internalType":"uint256","name":"maxLength","type":"uint256"}],"name":"getAllotmentPlans","outputs":[{"components":[{"internalType":"uint64","name":"id","type":"uint64"},{"internalType":"bool","name":"isValid","type":"bool"},{"internalType":"uint64","name":"cliffDuration","type":"uint64"},{"internalType":"uint64","name":"duration","type":"uint64"}],"internalType":"struct SatoshiAllotment.AllotmentPlan[]","name":"","type":"tuple[]"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"cursor","type":"uint256"},{"internalType":"uint256","name":"maxLength","type":"uint256"},{"internalType":"bool","name":"includeUpcoming","type":"bool"},{"internalType":"bool","name":"includeAll","type":"bool"}],"name":"getAllotmentsByAccount","outputs":[{"components":[{"internalType":"uint64","name":"id","type":"uint64"},{"internalType":"uint64","name":"start","type":"uint64"},{"internalType":"uint64","name":"cliff","type":"uint64"},{"internalType":"uint64","name":"duration","type":"uint64"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"amountReleased","type":"uint256"},{"internalType":"uint256","name":"amountAvailable","type":"uint256"}],"internalType":"struct SatoshiAllotment.AllotmentResponse[]","name":"","type":"tuple[]"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getHubAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getSatoshiTokenContract","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"grantAlloterRole","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"start","type":"uint64"},{"internalType":"uint256","name":"planId","type":"uint256"}],"name":"grantAllotment","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint64","name":"id","type":"uint64"}],"name":"isAllotmentPlanValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"context","type":"bytes"},{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"actualCharge","type":"uint256"},{"internalType":"bytes32","name":"preRetVal","type":"bytes32"}],"name":"postRelayedCall","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"context","type":"bytes"}],"name":"preRelayedCall","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"relayHubVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint64[]","name":"ids","type":"uint64[]"}],"name":"release","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeAllotmentPlan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"trustedSigner","type":"address"}],"name":"setTrustedSigner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint64[]","name":"ids","type":"uint64[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"topUp","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080604052600180546001600160a01b03191673d216153c06e857cd7f72665e0af1d7d82172f4941790553480156200003757600080fd5b506040516200433e3803806200433e8339810160408190526200005a9162000525565b806001600160a01b0381166200008d5760405162461bcd60e51b815260040162000084906200079a565b60405180910390fd5b600280546001600160a01b0319166001600160a01b039283161790558416620000ca5760405162461bcd60e51b8152600401620000849062000776565b816001600160401b0316836001600160401b03161115620000ff5760405162461bcd60e51b8152600401620000849062000764565b6000826001600160401b0316116200012b5760405162461bcd60e51b8152600401620000849062000788565b620001536000620001446001600160e01b03620002d916565b6001600160e01b036200031016565b62000181604051620001659062000744565b604051908190039020620001446001600160e01b03620002d916565b600380546001600160a01b0319166001600160a01b038616179055604080516080810182526000808252600160208084018281526001600160401b03898116968601968752888116606087019081526004805480870182559681905296517f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b90960180549351985191516001600160401b03199094169683169690961760ff60401b1916680100000000000000009815159890980297909717600160481b600160881b03191669010000000000000000009782169790970296909617600160881b600160c81b031916600160881b9190961602949094179091559054620002949290919062000329811b6200207017901c565b7ffdb3f4239e63a710b156cf2985b3245a1edacb1068995d387544981dc77e80008484604051620002c7929190620007ac565b60405180910390a2505050506200085d565b6001546000906001600160a01b03163314620002f75750336200030d565b6200030a6001600160e01b036200037c16565b90505b90565b6200032582826001600160e01b03620003c916565b5050565b60006200037383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506200044b60201b60201c565b90505b92915050565b600060606000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031692915050565b600082815260208181526040909120620003ee918390620020ff6200047f821b17901c565b156200032557620004076001600160e01b03620002d916565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008184841115620004725760405162461bcd60e51b815260040162000084919062000751565b50508183035b9392505050565b60006200049683836001600160e01b03620004ed16565b620004e45750600182810180548083018083556000928352602080842090920180546001600160a01b0319166001600160a01b03871690811790915583529085905260409091205562000376565b50600062000376565b6001600160a01b031660009081526020919091526040902054151590565b8051620003768162000838565b8051620003768162000852565b600080600080608085870312156200053c57600080fd5b60006200054a87876200050b565b94505060206200055d8782880162000518565b9350506040620005708782880162000518565b925050606062000583878288016200050b565b91505092959194509250565b60006200059c82620007cb565b620005a88185620007cf565b9350620005ba818560208601620007fb565b620005c5816200082e565b9093019392505050565b6000620005de602f83620007cf565b7f5361746f736869416c6c6f746d656e743a20636c696666206973206c6f6e676581526e39103a3430b710323ab930ba34b7b760891b602082015260400192915050565b600062000631602783620007cf565b7f5361746f736869416c6c6f746d656e743a20746f6b656e206973207a65726f208152666164647265737360c81b602082015260400192915050565b60006200067c601f83620007cf565b7f5361746f736869416c6c6f746d656e743a206475726174696f6e206973203000815260200192915050565b6000620006b7603983620007cf565b7f47534e526563697069656e745369676e61747572653a2074727573746564207381527f69676e657220697320746865207a65726f206164647265737300000000000000602082015260400192915050565b600062000718600c83620007d8565b6b414c4c4f5445525f524f4c4560a01b8152600c0192915050565b6200073e81620007ef565b82525050565b6000620003768262000709565b602080825281016200037381846200058f565b602080825281016200037681620005cf565b60208082528101620003768162000622565b6020808252810162000376816200066d565b602080825281016200037681620006a8565b60408101620007bc828562000733565b62000478602083018462000733565b5190565b90815260200190565b919050565b60006001600160a01b03821662000376565b6001600160401b031690565b60005b8381101562000818578181015183820152602001620007fe565b8381111562000828576000848401525b50505050565b601f01601f191690565b6200084381620007dd565b81146200084f57600080fd5b50565b6200084381620007ef565b613ad1806200086d6000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c806391d14854116100f9578063bc41e5a211610097578063d547741f11610071578063d547741f146103dc578063e06e0e22146103ef578063f798a8bf14610402578063fb3db46b14610423576101c4565b8063bc41e5a214610396578063bd26204f146103b6578063ca15c873146103c9576101c4565b8063a217fddf116100d3578063a217fddf14610346578063ad61ccd51461034e578063b0b9e84914610363578063b2d0056f14610383576101c4565b806391d14854146102fe5780639377d7551461031e57806398ad554d14610326576101c4565b806340e4f4eb1161016657806374e861d61161014057806374e861d6146102a257806380274db7146102b757806383947ea0146102ca5780639010d07c146102eb576101c4565b806340e4f4eb1461027457806346dd86031461027c57806356a1c7011461028f576101c4565b80632f2ff15d116101a25780632f2ff15d1461022857806332b2b5af1461023b57806334e580621461024e57806336568abe14610261576101c4565b806307116084146101c95780630bb9afbd146101f3578063248a9ca314610208575b600080fd5b6101dc6101d736600461263c565b610436565b6040516101ea9291906136f5565b60405180910390f35b6102066102013660046124c2565b610741565b005b61021b6102163660046127ed565b6107ca565b6040516101ea9190613743565b61020661023636600461280b565b6107e2565b61020661024936600461274c565b61082a565b61020661025c3660046125e6565b610adf565b61020661026f36600461280b565b610e8a565b61021b610ecc565b61020661028a3660046127ed565b610ee3565b61020661029d3660046124c2565b610fbc565b6102aa610ff1565b6040516101ea91906136ac565b61021b6102c536600461286b565b611001565b6102dd6102d83660046124e8565b611083565b6040516101ea929190613953565b6102aa6102f936600461283b565b61115a565b61031161030c36600461280b565b611178565b6040516101ea9190613735565b6102aa611196565b6103396103343660046126b1565b6111a5565b6040516101ea9190613973565b61021b6114e9565b6103566114ee565b6040516101ea9190613786565b610376610371366004612712565b611525565b6040516101ea9190613945565b61020661039136600461293b565b61166e565b6103a96103a436600461291d565b611866565b6040516101ea9190613937565b6102066103c43660046124c2565b6118fe565b61021b6103d73660046127ed565b611944565b6102066103ea36600461280b565b61195b565b6102066103fd3660046128ad565b611995565b61041561041036600461283b565b611a18565b6040516101ea9291906136d5565b61031161043136600461291d565b611bf9565b6001600160a01b03851660009081526005602090815260408083208054825181850281018501909352808352606094938593929190859084015b828210156105055760008481526020908190206040805160c08101825260038602909201805467ffffffffffffffff80821685526801000000000000000082048116858701527001000000000000000000000000000000008204811693850193909352600160c01b90049091166060830152600180820154608084015260029091015460a08301529083529092019101610470565b50508251929350889150508181111561051b5750805b60608160405190808252806020026020018201604052801561055757816020015b61054461237a565b81526020019060019003908161053c5790505b50905060008a5b8481101561072f5760006105706123b6565b87838151811061057c57fe5b60200260200101519050806040015167ffffffffffffffff1642106105a7576105a481611c33565b91505b60008211806105d0575060018c15151480156105d05750806040015167ffffffffffffffff1642105b806105dd575060018b1515145b156107255780600001518585815181106105f357fe5b602090810291909101015167ffffffffffffffff90911690526080810151855186908690811061061f57fe5b60200260200101516080018181525050806020015185858151811061064057fe5b60200260200101516020019067ffffffffffffffff16908167ffffffffffffffff1681525050806040015185858151811061067757fe5b60200260200101516040019067ffffffffffffffff16908167ffffffffffffffff168152505080606001518585815181106106ae57fe5b60200260200101516060019067ffffffffffffffff16908167ffffffffffffffff16815250508060a001518585815181106106e557fe5b602002602001015160a00181815250508185858151811061070257fe5b602090810291909101015160c0015260019093019285841061072557505061072f565b505060010161055e565b50909b909a5098505050505050505050565b61074e600061030c611c52565b6107735760405162461bcd60e51b815260040161076a906137b7565b60405180910390fd5b6003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517fe89f98a27789c8313baa22de83cdb921b7026d66af0ee02973c97d45f952b6be90600090a250565b6000818152602081905260409020600201545b919050565b6000828152602081905260409020600201546108009061030c611c52565b61081c5760405162461bcd60e51b815260040161076a90613797565b6108268282611c7d565b5050565b610849604051610839906136a1565b604051809103902061030c611c52565b6108655760405162461bcd60e51b815260040161076a90613907565b8483146108845760405162461bcd60e51b815260040161076a906137c7565b8281146108a35760405162461bcd60e51b815260040161076a90613877565b60005b85811015610ad65760008787838181106108bc57fe5b90506020020160206108d191908101906124c2565b6001600160a01b031614156108f85760405162461bcd60e51b815260040161076a90613827565b600083838381811061090657fe5b905060200201351161092a5760405162461bcd60e51b815260040161076a906137a7565b60006005600089898581811061093c57fe5b905060200201602061095191908101906124c2565b6001600160a01b03166001600160a01b0316815260200190815260200160002086868481811061097d57fe5b9050602002016020610992919081019061291d565b67ffffffffffffffff16815481106109a657fe5b60009182526020909120600390910201805490915042906109e69067ffffffffffffffff680100000000000000008204811691600160c01b900416611cec565b67ffffffffffffffff1611610a0d5760405162461bcd60e51b815260040161076a906138c7565b838383818110610a1957fe5b60018401805460209092029390930135019091555042868684818110610a3b57fe5b9050602002016020610a50919081019061291d565b67ffffffffffffffff16898985818110610a6657fe5b9050602002016020610a7b91908101906124c2565b6001600160a01b03167f440af7ff0e45fb4c92207c7b36d2da0fa3692fab39d4e882cb16fcec02ab2334878787818110610ab157fe5b90506020020135604051610ac59190613743565b60405180910390a4506001016108a6565b50505050505050565b6001600160a01b038316610b055760405162461bcd60e51b815260040161076a90613827565b80610b225760405162461bcd60e51b815260040161076a906137f7565b6001600160a01b038316600090815260056020908152604080832080548251868152868502810190940190925283929091908590606090828015610b70578160200160208202803883390190505b50905082821115610b7f578291505b60005b82811015610db45783898983818110610b9757fe5b9050602002016020610bac919081019061291d565b67ffffffffffffffff1610610bd35760405162461bcd60e51b815260040161076a906138a7565b6000858a8a84818110610be257fe5b9050602002016020610bf7919081019061291d565b67ffffffffffffffff1681548110610c0b57fe5b90600052602060002090600302019050610c236123b6565b868b8b85818110610c3057fe5b9050602002016020610c45919081019061291d565b67ffffffffffffffff1681548110610c5957fe5b60009182526020918290206040805160c0810182526003909302909101805467ffffffffffffffff808216855268010000000000000000820481169585019590955270010000000000000000000000000000000081048516928401839052600160c01b900490931660608301526001830154608083015260029092015460a082015291504210610daa57610cec81611c33565b9850610cfe888a63ffffffff611d1e16565b975088848481518110610d0d57fe5b6020908102919091010152608081015160a0820151610d32908b63ffffffff611d1e16565b10610d8f57868b8b85818110610d4457fe5b9050602002016020610d59919081019061291d565b67ffffffffffffffff1681548110610d6d57fe5b6000918252602082206003909102018181556001810182905560020155610daa565b60a0810151610da4908a63ffffffff611d1e16565b60028301555b5050600101610b82565b508415610e39576003546040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906340c10f1990610e06908c9089906004016136ba565b600060405180830381600087803b158015610e2057600080fd5b505af1158015610e34573d6000803e3d6000fd5b505050505b42896001600160a01b03167f659ca3a19db5c915ad98330931f7f486226eeb4cb4fa5e8256628a91fed1b30f8a8a85604051610e7793929190613706565b60405180910390a3505050505050505050565b610e92611c52565b6001600160a01b0316816001600160a01b031614610ec25760405162461bcd60e51b815260040161076a90613917565b6108268282611d43565b604051610ed8906136a1565b604051809103902081565b610ef0600061030c611c52565b610f0c5760405162461bcd60e51b815260040161076a90613837565b60048181548110610f1957fe5b60009182526020909120015468010000000000000000900460ff161515600114610f555760405162461bcd60e51b815260040161076a90613817565b60048181548110610f6257fe5b6000918252602082200180547fffffffffffffff0000000000000000000000000000000000000000000000000016905560405182917e4c797e6739331fc6d5c1ebdf112d63e6a68297fdfd28f35f54561e28fd868d91a250565b610fc9600061030c611c52565b610fe55760405162461bcd60e51b815260040161076a906138e7565b610fee81611db2565b50565b6001546001600160a01b03165b90565b600061100b610ff1565b6001600160a01b0316336001600160a01b03161461103b5760405162461bcd60e51b815260040161076a906138d7565b61107a83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e0792505050565b90505b92915050565b60006060808d8d8d8d8d8d8d8d611098610ff1565b306040516020016110b29a999897969594939291906135e6565b60408051601f198184030181526002546020601f8a018190048102850181019093528884529093506001600160a01b03169161111f918990899081908401838280828437600092019190915250508551602087012061111392509050611e0d565b9063ffffffff611e3d16565b6001600160a01b0316141561114057611136611f19565b925092505061114a565b6111366000611f3d565b9b509b9950505050505050505050565b600082815260208190526040812061107a908363ffffffff611f5516565b600082815260208190526040812061107a908363ffffffff611f8216565b6003546001600160a01b031690565b60006111b6604051610839906136a1565b6111d25760405162461bcd60e51b815260040161076a90613927565b6001600160a01b0385166111f85760405162461bcd60e51b815260040161076a90613827565b428367ffffffffffffffff1610156112225760405162461bcd60e51b815260040161076a90613807565b61122a6123eb565b6004838154811061123757fe5b600091825260209182902060408051608081018252929091015467ffffffffffffffff808216845268010000000000000000820460ff1615159484018590526901000000000000000000820481169284019290925271010000000000000000000000000000000000900416606082015291506001146112c85760405162461bcd60e51b815260040161076a90613817565b6001600160a01b03861660009081526005602052604090205467ffffffffffffffff81106113085760405162461bcd60e51b815260040161076a90613897565b60056000886001600160a01b03166001600160a01b031681526020019081526020016000206040518060c001604052808367ffffffffffffffff1681526020018767ffffffffffffffff16815260200161137985604001518967ffffffffffffffff16611cec90919063ffffffff16565b67ffffffffffffffff9081168252606086810151821660208085019190915260408085018d90526000948301859052865460018082018955978652948290208651600390960201805492870151878301519488015167ffffffffffffffff19909416968616969096177fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000096861696909602959095177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16700100000000000000000000000000000000938516939093029290921777ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b919093160291909117825560808301519382019390935560a0909101516002909101555142906001600160a01b038916907f8479528817e11fd7e1edcbc79cb3977a74b265fff29ec17816a6c8e18dc230c3906114d79085908b90613981565b60405180910390a39695505050505050565b600081565b60408051808201909152600581527f312e302e30000000000000000000000000000000000000000000000000000000602082015290565b61152d61237a565b6115356123b6565b6001600160a01b0384166000908152600560205260409020805467ffffffffffffffff851690811061156357fe5b600091825260208083206040805160c0810182526003909402909101805467ffffffffffffffff80821686526801000000000000000082048116948601949094527001000000000000000000000000000000008104841692850192909252600160c01b9091049091166060830152600181015460808301526002015460a082015291506115ef82611c33565b90506040518060e00160405280836000015167ffffffffffffffff168152602001836020015167ffffffffffffffff168152602001836040015167ffffffffffffffff168152602001836060015167ffffffffffffffff168152602001836080015181526020018360a001518152602001828152509250505092915050565b61167b600061030c611c52565b6116975760405162461bcd60e51b815260040161076a906138f7565b8067ffffffffffffffff168267ffffffffffffffff1611156116cb5760405162461bcd60e51b815260040161076a906137d7565b60008167ffffffffffffffff16116116f55760405162461bcd60e51b815260040161076a90613857565b600480546040805160808101825267ffffffffffffffff808416825260016020830181815288831684860190815288841660608601908152928701885560009790975292517f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b8601805494519751925167ffffffffffffffff19909516918416919091177fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff166801000000000000000097151597909702969096177fffffffffffffffffffffffffffffff0000000000000000ffffffffffffffffff16690100000000000000000091831691909102177fffffffffffffff0000000000000000ffffffffffffffffffffffffffffffffff1671010000000000000000000000000000000000929091169190910217909255905181907ffdb3f4239e63a710b156cf2985b3245a1edacb1068995d387544981dc77e800090611859908690869061398f565b60405180910390a2505050565b61186e6123eb565b60048267ffffffffffffffff168154811061188557fe5b600091825260209182902060408051608081018252929091015467ffffffffffffffff808216845268010000000000000000820460ff1615159484019490945269010000000000000000008104841691830191909152710100000000000000000000000000000000009004909116606082015292915050565b61190b600061030c611c52565b6119275760405162461bcd60e51b815260040161076a90613867565b610fee604051611936906136a1565b6040518091039020826107e2565b600081815260208190526040812061107d90611fa0565b6000828152602081905260409020600201546119799061030c611c52565b610ec25760405162461bcd60e51b815260040161076a90613847565b61199d610ff1565b6001600160a01b0316336001600160a01b0316146119cd5760405162461bcd60e51b815260040161076a906138d7565b611a1185858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250879250869150859050611fa7565b5050505050565b6004546060906000908390811115611a2f57506004545b606081604051908082528060200260200182016040528015611a6b57816020015b611a586123eb565b815260200190600190039081611a505790505b5090506000865b600454811015611bea57611a846123eb565b60048281548110611a9157fe5b600091825260209182902060408051608081018252929091015467ffffffffffffffff808216845268010000000000000000820460ff16151594840185905269010000000000000000008204811692840192909252710100000000000000000000000000000000009004166060820152915060011415611be1578060000151848481518110611b1c57fe5b60200260200101516000019067ffffffffffffffff16908167ffffffffffffffff16815250508060200151848481518110611b5357fe5b602002602001015160200190151590811515815250508060400151848481518110611b7a57fe5b60200260200101516040019067ffffffffffffffff16908167ffffffffffffffff16815250508060600151848481518110611bb157fe5b602090810291909101015167ffffffffffffffff909116606090910152600190920191848310611be15750611bea565b50600101611a72565b509093509150505b9250929050565b600060048267ffffffffffffffff1681548110611c1257fe5b60009182526020909120015468010000000000000000900460ff1692915050565b600061107d8260a00151611c4684611fad565b9063ffffffff61207016565b6001546000906001600160a01b03163314611c6e575033610ffe565b611c766120b2565b9050610ffe565b6000828152602081905260409020611c9b908263ffffffff6120ff16565b1561082657611ca8611c52565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600082820167ffffffffffffffff808516908216101561107a5760405162461bcd60e51b815260040161076a906137e7565b60008282018381101561107a5760405162461bcd60e51b815260040161076a906137e7565b6000828152602081905260409020611d61908263ffffffff61216c16565b1561082657611d6e611c52565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b6001600160a01b038116611dd85760405162461bcd60e51b815260040161076a906138b7565b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b50600090565b600081604051602001611e209190613681565b604051602081830303815290604052805190602001209050919050565b60008151604114611e505750600061107d565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611e96576000935050505061107d565b8060ff16601b14158015611eae57508060ff16601c14155b15611ebf576000935050505061107d565b60018682858560405160008152602001604052604051611ee29493929190613751565b6020604051602081039080840390855afa158015611f04573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b60006060611f3560405180602001604052806000815250612291565b915091509091565b604080516020810190915260008152600b9190910191565b6000826001018281548110611f6657fe5b6000918252602090912001546001600160a01b03169392505050565b6001600160a01b031660009081526020919091526040902054151590565b6001015490565b50505050565b608081015160408201516000919067ffffffffffffffff16421015611fd65760009150506107dd565b611ffb8360600151846020015167ffffffffffffffff16611cec90919063ffffffff16565b67ffffffffffffffff1642106120125790506107dd565b6000612035846020015167ffffffffffffffff164261207090919063ffffffff16565b60608501519091506120679067ffffffffffffffff1661205b848463ffffffff61229616565b9063ffffffff6122d016565b925050506107dd565b600061107a83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612312565b600060606000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031692915050565b600061210b8383611f82565b61216457506001828101805480830180835560009283526020808420909201805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03871690811790915583529085905260409091205561107d565b50600061107d565b60006121788383611f82565b15612164576001600160a01b038216600090815260208490526040902054600184015460001991820191018082146122305760008560010182815481106121bb57fe5b6000918252602090912001546001870180546001600160a01b0390921692508291859081106121e657fe5b6000918252602080832091909101805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0394851617905592909116815290869052604090206001830190555b6001600160a01b0384166000908152602086905260408120556001850180548061225657fe5b6000828152602090208101600019908101805473ffffffffffffffffffffffffffffffffffffffff19169055019055506001915061107d9050565b600091565b6000826122a55750600061107d565b828202828482816122b257fe5b041461107a5760405162461bcd60e51b815260040161076a90613887565b600061107a83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612343565b600081848411156123365760405162461bcd60e51b815260040161076a9190613786565b50508183035b9392505050565b600081836123645760405162461bcd60e51b815260040161076a9190613786565b50600083858161237057fe5b0495945050505050565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60408051608081018252600080825260208201819052918101829052606081019190915290565b803561107d81613a5f565b60008083601f84011261242f57600080fd5b50813567ffffffffffffffff81111561244757600080fd5b602083019150836020820283011115611bf257600080fd5b803561107d81613a73565b803561107d81613a7c565b60008083601f84011261248757600080fd5b50813567ffffffffffffffff81111561249f57600080fd5b602083019150836001820283011115611bf257600080fd5b803561107d81613a85565b6000602082840312156124d457600080fd5b60006124e08484612412565b949350505050565b60008060008060008060008060008060006101208c8e03121561250a57600080fd5b60006125168e8e612412565b9b505060206125278e828f01612412565b9a505060408c013567ffffffffffffffff81111561254457600080fd5b6125508e828f01612475565b995099505060606125638e828f0161246a565b97505060806125748e828f0161246a565b96505060a06125858e828f0161246a565b95505060c06125968e828f0161246a565b94505060e08c013567ffffffffffffffff8111156125b357600080fd5b6125bf8e828f01612475565b93509350506101006125d38e828f0161246a565b9150509295989b509295989b9093969950565b6000806000604084860312156125fb57600080fd5b60006126078686612412565b935050602084013567ffffffffffffffff81111561262457600080fd5b6126308682870161241d565b92509250509250925092565b600080600080600060a0868803121561265457600080fd5b60006126608888612412565b95505060206126718882890161246a565b94505060406126828882890161246a565b93505060606126938882890161245f565b92505060806126a48882890161245f565b9150509295509295909350565b600080600080608085870312156126c757600080fd5b60006126d38787612412565b94505060206126e48782880161246a565b93505060406126f5878288016124b7565b92505060606127068782880161246a565b91505092959194509250565b6000806040838503121561272557600080fd5b60006127318585612412565b9250506020612742858286016124b7565b9150509250929050565b6000806000806000806060878903121561276557600080fd5b863567ffffffffffffffff81111561277c57600080fd5b61278889828a0161241d565b9650965050602087013567ffffffffffffffff8111156127a757600080fd5b6127b389828a0161241d565b9450945050604087013567ffffffffffffffff8111156127d257600080fd5b6127de89828a0161241d565b92509250509295509295509295565b6000602082840312156127ff57600080fd5b60006124e0848461246a565b6000806040838503121561281e57600080fd5b600061282a858561246a565b925050602061274285828601612412565b6000806040838503121561284e57600080fd5b600061285a858561246a565b92505060206127428582860161246a565b6000806020838503121561287e57600080fd5b823567ffffffffffffffff81111561289557600080fd5b6128a185828601612475565b92509250509250929050565b6000806000806000608086880312156128c557600080fd5b853567ffffffffffffffff8111156128dc57600080fd5b6128e888828901612475565b955095505060206128fb8882890161245f565b935050604061290c8882890161246a565b92505060606126a48882890161246a565b60006020828403121561292f57600080fd5b60006124e084846124b7565b6000806040838503121561294e57600080fd5b600061273185856124b7565b600061296683836134fe565b505060800190565b600061297a8383613548565b505060e00190565b600061298e8383612b0d565b505060200190565b600061298e83836135d4565b6129ab816139cc565b82525050565b6129ab6129bd826139cc565b613a3e565b60006129cd826139b0565b6129d781856139b4565b93506129e2836139aa565b8060005b83811015612a105781516129fa888261295a565b9750612a05836139aa565b9250506001016129e6565b509495945050505050565b6000612a26826139b0565b612a3081856139b4565b9350612a3b836139aa565b8060005b83811015612a10578151612a53888261296e565b9750612a5e836139aa565b925050600101612a3f565b6000612a74826139b0565b612a7e81856139b4565b9350612a89836139aa565b8060005b83811015612a10578151612aa18882612982565b9750612aac836139aa565b925050600101612a8d565b6000612ac383856139b4565b9350612ace82610ffe565b8060005b85811015612a1057612ae482846139bd565b612aee8882612996565b9750612af9836139aa565b925050600101612ad2565b6129ab816139d7565b6129ab81610ffe565b6129ab612b2282610ffe565b610ffe565b6000612b3383856107dd565b9350612b40838584613a06565b50500190565b6000612b51826139b0565b612b5b81856139b4565b9350612b6b818560208601613a12565b612b7481613a4f565b9093019392505050565b6000612b8b602f836139b4565b7f416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e81527f2061646d696e20746f206772616e740000000000000000000000000000000000602082015260400192915050565b6000612bea6020836139b4565b7f5361746f736869416c6c6f746d656e743a20616d6f756e74206973207a65726f815260200192915050565b6000612c23601c836107dd565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c0192915050565b6000612c5c6047836139b4565b7f5361746f736869416c6c6f746d656e743a206d75737420686176652061646d6981527f6e20726f6c6520746f206368616e6765207361746f73686920746f6b656e206360208201527f6f6e747261637400000000000000000000000000000000000000000000000000604082015260600192915050565b6000612ce1603f836139b4565b7f5361746f736869416c6c6f746d656e743a206163636f756e7473206c656e677481527f6820646f65736e2774206d61746368207769746820696473206c656e67746800602082015260400192915050565b6000612d40602f836139b4565b7f5361746f736869416c6c6f746d656e743a20636c696666206973206c6f6e676581527f72207468616e206475726174696f6e0000000000000000000000000000000000602082015260400192915050565b6000612d9f601b836139b4565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b6000612dd8601f836139b4565b7f5361746f736869416c6c6f746d656e743a204964732061726520656d70747900815260200192915050565b6000612e11601d836139b4565b7f5361746f736869416c6c6f746d656e743a207374617274203c206e6f77000000815260200192915050565b6000612e4a601e836139b4565b7f5361746f736869416c6c6f746d656e743a2064656c6574656420706c616e0000815260200192915050565b6000612e836029836139b4565b7f5361746f736869416c6c6f746d656e743a206163636f756e74206973207a657281527f6f20616464726573730000000000000000000000000000000000000000000000602082015260400192915050565b6000612ee26035836139b4565b7f5361746f736869416c6c6f746d656e743a206d75737420686176652061646d6981527f6e20726f6c6520746f2072656d6f766520706c616e0000000000000000000000602082015260400192915050565b6000612f416030836139b4565b7f416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e81527f2061646d696e20746f207265766f6b6500000000000000000000000000000000602082015260400192915050565b6000612fa0601f836139b4565b7f5361746f736869416c6c6f746d656e743a206475726174696f6e206973203000815260200192915050565b6000612fd96032836139b4565b7f5361746f736869416c6c6f746d656e743a2073656e646572206d75737420626581527f20616e2061646d696e20746f206772616e740000000000000000000000000000602082015260400192915050565b6000613038603e836139b4565b7f5361746f736869416c6c6f746d656e743a20696473206c656e67746820646f6581527f736e2774206d61746368207769746820616d6f756e7473206c656e6774680000602082015260400192915050565b60006130976021836139b4565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f81527f7700000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b60006130f6602b836139b4565b7f5361746f736869416c6c6f746d656e743a204d617820616c6c6f746d656e742081527f4944732072656163686564000000000000000000000000000000000000000000602082015260400192915050565b60006131556026836139b4565b7f5361746f736869416c6c6f746d656e743a20696e76616c696420616c6c6f746d81527f656e742069640000000000000000000000000000000000000000000000000000602082015260400192915050565b60006131b46039836139b4565b7f47534e526563697069656e745369676e61747572653a2074727573746564207381527f69676e657220697320746865207a65726f206164647265737300000000000000602082015260400192915050565b60006132136027836139b4565b7f5361746f736869416c6c6f746d656e743a20616c6c6f746d656e74206861732081527f6578706972656400000000000000000000000000000000000000000000000000602082015260400192915050565b60006132726024836139b4565b7f47534e526563697069656e743a2063616c6c6572206973206e6f742052656c6181527f7948756200000000000000000000000000000000000000000000000000000000602082015260400192915050565b60006132d1603a836139b4565b7f5361746f736869546f6b656e3a206d75737420686176652061646d696e20726f81527f6c6520746f206368616e676520747275737465645369676e6572000000000000602082015260400192915050565b60006133306032836139b4565b7f5361746f736869416c6c6f746d656e743a206d75737420686176652061646d6981527f6e20726f6c6520746f2061646420706c616e0000000000000000000000000000602082015260400192915050565b600061338f600c836107dd565b7f414c4c4f5445525f524f4c4500000000000000000000000000000000000000008152600c0192915050565b60006133c86042836139b4565b7f5361746f736869416c6c6f746d656e743a206d757374206861766520616c6c6f81527f74657220726f6c6520746f20746f70757020616c6c6f746d656e7420746f6b6560208201527f6e73000000000000000000000000000000000000000000000000000000000000604082015260600192915050565b600061344d602f836139b4565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636581527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015260400192915050565b60006134ac6038836139b4565b7f5361746f736869416c6c6f746d656e743a206d757374206861766520616c6c6f81527f74657220726f6c6520746f20616c6c6f7420746f6b656e730000000000000000602082015260400192915050565b8051608083019061350f84826135d4565b5060208201516135226020850182612b04565b50604082015161353560408501826135d4565b506060820151611fa760608501826135d4565b805160e083019061355984826135d4565b50602082015161356c60208501826135d4565b50604082015161357f60408501826135d4565b50606082015161359260608501826135d4565b5060808201516135a56080850182612b0d565b5060a08201516135b860a0850182612b0d565b5060c0820151611fa760c0850182612b0d565b6129ab816139fb565b6129ab816139e8565b6129ab816139f5565b60006135f2828d6129b1565b601482019150613602828c6129b1565b601482019150613613828a8c612b27565b915061361f8289612b16565b60208201915061362f8288612b16565b60208201915061363f8287612b16565b60208201915061364f8286612b16565b60208201915061365f82856129b1565b60148201915061366f82846129b1565b506014019a9950505050505050505050565b600061368c82612c16565b91506136988284612b16565b50602001919050565b600061107d82613382565b6020810161107d82846129a2565b604081016136c882856129a2565b61233c6020830184612b0d565b604080825281016136e681856129c2565b905061233c6020830184612b0d565b604080825281016136e68185612a1b565b60408082528101613718818587612ab7565b9050818103602083015261372c8184612a69565b95945050505050565b6020810161107d8284612b04565b6020810161107d8284612b0d565b6080810161375f8287612b0d565b61376c60208301866135dd565b6137796040830185612b0d565b61372c6060830184612b0d565b6020808252810161107a8184612b46565b6020808252810161107d81612b7e565b6020808252810161107d81612bdd565b6020808252810161107d81612c4f565b6020808252810161107d81612cd4565b6020808252810161107d81612d33565b6020808252810161107d81612d92565b6020808252810161107d81612dcb565b6020808252810161107d81612e04565b6020808252810161107d81612e3d565b6020808252810161107d81612e76565b6020808252810161107d81612ed5565b6020808252810161107d81612f34565b6020808252810161107d81612f93565b6020808252810161107d81612fcc565b6020808252810161107d8161302b565b6020808252810161107d8161308a565b6020808252810161107d816130e9565b6020808252810161107d81613148565b6020808252810161107d816131a7565b6020808252810161107d81613206565b6020808252810161107d81613265565b6020808252810161107d816132c4565b6020808252810161107d81613323565b6020808252810161107d816133bb565b6020808252810161107d81613440565b6020808252810161107d8161349f565b6080810161107d82846134fe565b60e0810161107d8284613548565b604081016139618285612b0d565b81810360208301526124e08184612b46565b6020810161107d82846135d4565b604081016136c882856135cb565b6040810161399d82856135d4565b61233c60208301846135d4565b60200190565b5190565b90815260200190565b600061107a60208401846124b7565b600061107d826139dc565b151590565b6001600160a01b031690565b67ffffffffffffffff1690565b60ff1690565b600061107d826139e8565b82818337506000910152565b60005b83811015613a2d578181015183820152602001613a15565b83811115611fa75750506000910152565b600061107d82600061107d82613a59565b601f01601f191690565b60601b90565b613a68816139cc565b8114610fee57600080fd5b613a68816139d7565b613a6881610ffe565b613a68816139e856fea365627a7a72315820c9c4ee1b8720b1046f03191ba2378241876574b2524c7789219aad9afa6c239a6c6578706572696d656e74616cf564736f6c63430005100040000000000000000000000000787d6335e033fe9dec59db61a6a936b4cebbe839000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000020f5800000000000000000000000000919cbb0be55ba996a567107ea13f417be74e477a
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101c45760003560e01c806391d14854116100f9578063bc41e5a211610097578063d547741f11610071578063d547741f146103dc578063e06e0e22146103ef578063f798a8bf14610402578063fb3db46b14610423576101c4565b8063bc41e5a214610396578063bd26204f146103b6578063ca15c873146103c9576101c4565b8063a217fddf116100d3578063a217fddf14610346578063ad61ccd51461034e578063b0b9e84914610363578063b2d0056f14610383576101c4565b806391d14854146102fe5780639377d7551461031e57806398ad554d14610326576101c4565b806340e4f4eb1161016657806374e861d61161014057806374e861d6146102a257806380274db7146102b757806383947ea0146102ca5780639010d07c146102eb576101c4565b806340e4f4eb1461027457806346dd86031461027c57806356a1c7011461028f576101c4565b80632f2ff15d116101a25780632f2ff15d1461022857806332b2b5af1461023b57806334e580621461024e57806336568abe14610261576101c4565b806307116084146101c95780630bb9afbd146101f3578063248a9ca314610208575b600080fd5b6101dc6101d736600461263c565b610436565b6040516101ea9291906136f5565b60405180910390f35b6102066102013660046124c2565b610741565b005b61021b6102163660046127ed565b6107ca565b6040516101ea9190613743565b61020661023636600461280b565b6107e2565b61020661024936600461274c565b61082a565b61020661025c3660046125e6565b610adf565b61020661026f36600461280b565b610e8a565b61021b610ecc565b61020661028a3660046127ed565b610ee3565b61020661029d3660046124c2565b610fbc565b6102aa610ff1565b6040516101ea91906136ac565b61021b6102c536600461286b565b611001565b6102dd6102d83660046124e8565b611083565b6040516101ea929190613953565b6102aa6102f936600461283b565b61115a565b61031161030c36600461280b565b611178565b6040516101ea9190613735565b6102aa611196565b6103396103343660046126b1565b6111a5565b6040516101ea9190613973565b61021b6114e9565b6103566114ee565b6040516101ea9190613786565b610376610371366004612712565b611525565b6040516101ea9190613945565b61020661039136600461293b565b61166e565b6103a96103a436600461291d565b611866565b6040516101ea9190613937565b6102066103c43660046124c2565b6118fe565b61021b6103d73660046127ed565b611944565b6102066103ea36600461280b565b61195b565b6102066103fd3660046128ad565b611995565b61041561041036600461283b565b611a18565b6040516101ea9291906136d5565b61031161043136600461291d565b611bf9565b6001600160a01b03851660009081526005602090815260408083208054825181850281018501909352808352606094938593929190859084015b828210156105055760008481526020908190206040805160c08101825260038602909201805467ffffffffffffffff80821685526801000000000000000082048116858701527001000000000000000000000000000000008204811693850193909352600160c01b90049091166060830152600180820154608084015260029091015460a08301529083529092019101610470565b50508251929350889150508181111561051b5750805b60608160405190808252806020026020018201604052801561055757816020015b61054461237a565b81526020019060019003908161053c5790505b50905060008a5b8481101561072f5760006105706123b6565b87838151811061057c57fe5b60200260200101519050806040015167ffffffffffffffff1642106105a7576105a481611c33565b91505b60008211806105d0575060018c15151480156105d05750806040015167ffffffffffffffff1642105b806105dd575060018b1515145b156107255780600001518585815181106105f357fe5b602090810291909101015167ffffffffffffffff90911690526080810151855186908690811061061f57fe5b60200260200101516080018181525050806020015185858151811061064057fe5b60200260200101516020019067ffffffffffffffff16908167ffffffffffffffff1681525050806040015185858151811061067757fe5b60200260200101516040019067ffffffffffffffff16908167ffffffffffffffff168152505080606001518585815181106106ae57fe5b60200260200101516060019067ffffffffffffffff16908167ffffffffffffffff16815250508060a001518585815181106106e557fe5b602002602001015160a00181815250508185858151811061070257fe5b602090810291909101015160c0015260019093019285841061072557505061072f565b505060010161055e565b50909b909a5098505050505050505050565b61074e600061030c611c52565b6107735760405162461bcd60e51b815260040161076a906137b7565b60405180910390fd5b6003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517fe89f98a27789c8313baa22de83cdb921b7026d66af0ee02973c97d45f952b6be90600090a250565b6000818152602081905260409020600201545b919050565b6000828152602081905260409020600201546108009061030c611c52565b61081c5760405162461bcd60e51b815260040161076a90613797565b6108268282611c7d565b5050565b610849604051610839906136a1565b604051809103902061030c611c52565b6108655760405162461bcd60e51b815260040161076a90613907565b8483146108845760405162461bcd60e51b815260040161076a906137c7565b8281146108a35760405162461bcd60e51b815260040161076a90613877565b60005b85811015610ad65760008787838181106108bc57fe5b90506020020160206108d191908101906124c2565b6001600160a01b031614156108f85760405162461bcd60e51b815260040161076a90613827565b600083838381811061090657fe5b905060200201351161092a5760405162461bcd60e51b815260040161076a906137a7565b60006005600089898581811061093c57fe5b905060200201602061095191908101906124c2565b6001600160a01b03166001600160a01b0316815260200190815260200160002086868481811061097d57fe5b9050602002016020610992919081019061291d565b67ffffffffffffffff16815481106109a657fe5b60009182526020909120600390910201805490915042906109e69067ffffffffffffffff680100000000000000008204811691600160c01b900416611cec565b67ffffffffffffffff1611610a0d5760405162461bcd60e51b815260040161076a906138c7565b838383818110610a1957fe5b60018401805460209092029390930135019091555042868684818110610a3b57fe5b9050602002016020610a50919081019061291d565b67ffffffffffffffff16898985818110610a6657fe5b9050602002016020610a7b91908101906124c2565b6001600160a01b03167f440af7ff0e45fb4c92207c7b36d2da0fa3692fab39d4e882cb16fcec02ab2334878787818110610ab157fe5b90506020020135604051610ac59190613743565b60405180910390a4506001016108a6565b50505050505050565b6001600160a01b038316610b055760405162461bcd60e51b815260040161076a90613827565b80610b225760405162461bcd60e51b815260040161076a906137f7565b6001600160a01b038316600090815260056020908152604080832080548251868152868502810190940190925283929091908590606090828015610b70578160200160208202803883390190505b50905082821115610b7f578291505b60005b82811015610db45783898983818110610b9757fe5b9050602002016020610bac919081019061291d565b67ffffffffffffffff1610610bd35760405162461bcd60e51b815260040161076a906138a7565b6000858a8a84818110610be257fe5b9050602002016020610bf7919081019061291d565b67ffffffffffffffff1681548110610c0b57fe5b90600052602060002090600302019050610c236123b6565b868b8b85818110610c3057fe5b9050602002016020610c45919081019061291d565b67ffffffffffffffff1681548110610c5957fe5b60009182526020918290206040805160c0810182526003909302909101805467ffffffffffffffff808216855268010000000000000000820481169585019590955270010000000000000000000000000000000081048516928401839052600160c01b900490931660608301526001830154608083015260029092015460a082015291504210610daa57610cec81611c33565b9850610cfe888a63ffffffff611d1e16565b975088848481518110610d0d57fe5b6020908102919091010152608081015160a0820151610d32908b63ffffffff611d1e16565b10610d8f57868b8b85818110610d4457fe5b9050602002016020610d59919081019061291d565b67ffffffffffffffff1681548110610d6d57fe5b6000918252602082206003909102018181556001810182905560020155610daa565b60a0810151610da4908a63ffffffff611d1e16565b60028301555b5050600101610b82565b508415610e39576003546040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906340c10f1990610e06908c9089906004016136ba565b600060405180830381600087803b158015610e2057600080fd5b505af1158015610e34573d6000803e3d6000fd5b505050505b42896001600160a01b03167f659ca3a19db5c915ad98330931f7f486226eeb4cb4fa5e8256628a91fed1b30f8a8a85604051610e7793929190613706565b60405180910390a3505050505050505050565b610e92611c52565b6001600160a01b0316816001600160a01b031614610ec25760405162461bcd60e51b815260040161076a90613917565b6108268282611d43565b604051610ed8906136a1565b604051809103902081565b610ef0600061030c611c52565b610f0c5760405162461bcd60e51b815260040161076a90613837565b60048181548110610f1957fe5b60009182526020909120015468010000000000000000900460ff161515600114610f555760405162461bcd60e51b815260040161076a90613817565b60048181548110610f6257fe5b6000918252602082200180547fffffffffffffff0000000000000000000000000000000000000000000000000016905560405182917e4c797e6739331fc6d5c1ebdf112d63e6a68297fdfd28f35f54561e28fd868d91a250565b610fc9600061030c611c52565b610fe55760405162461bcd60e51b815260040161076a906138e7565b610fee81611db2565b50565b6001546001600160a01b03165b90565b600061100b610ff1565b6001600160a01b0316336001600160a01b03161461103b5760405162461bcd60e51b815260040161076a906138d7565b61107a83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e0792505050565b90505b92915050565b60006060808d8d8d8d8d8d8d8d611098610ff1565b306040516020016110b29a999897969594939291906135e6565b60408051601f198184030181526002546020601f8a018190048102850181019093528884529093506001600160a01b03169161111f918990899081908401838280828437600092019190915250508551602087012061111392509050611e0d565b9063ffffffff611e3d16565b6001600160a01b0316141561114057611136611f19565b925092505061114a565b6111366000611f3d565b9b509b9950505050505050505050565b600082815260208190526040812061107a908363ffffffff611f5516565b600082815260208190526040812061107a908363ffffffff611f8216565b6003546001600160a01b031690565b60006111b6604051610839906136a1565b6111d25760405162461bcd60e51b815260040161076a90613927565b6001600160a01b0385166111f85760405162461bcd60e51b815260040161076a90613827565b428367ffffffffffffffff1610156112225760405162461bcd60e51b815260040161076a90613807565b61122a6123eb565b6004838154811061123757fe5b600091825260209182902060408051608081018252929091015467ffffffffffffffff808216845268010000000000000000820460ff1615159484018590526901000000000000000000820481169284019290925271010000000000000000000000000000000000900416606082015291506001146112c85760405162461bcd60e51b815260040161076a90613817565b6001600160a01b03861660009081526005602052604090205467ffffffffffffffff81106113085760405162461bcd60e51b815260040161076a90613897565b60056000886001600160a01b03166001600160a01b031681526020019081526020016000206040518060c001604052808367ffffffffffffffff1681526020018767ffffffffffffffff16815260200161137985604001518967ffffffffffffffff16611cec90919063ffffffff16565b67ffffffffffffffff9081168252606086810151821660208085019190915260408085018d90526000948301859052865460018082018955978652948290208651600390960201805492870151878301519488015167ffffffffffffffff19909416968616969096177fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000096861696909602959095177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16700100000000000000000000000000000000938516939093029290921777ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b919093160291909117825560808301519382019390935560a0909101516002909101555142906001600160a01b038916907f8479528817e11fd7e1edcbc79cb3977a74b265fff29ec17816a6c8e18dc230c3906114d79085908b90613981565b60405180910390a39695505050505050565b600081565b60408051808201909152600581527f312e302e30000000000000000000000000000000000000000000000000000000602082015290565b61152d61237a565b6115356123b6565b6001600160a01b0384166000908152600560205260409020805467ffffffffffffffff851690811061156357fe5b600091825260208083206040805160c0810182526003909402909101805467ffffffffffffffff80821686526801000000000000000082048116948601949094527001000000000000000000000000000000008104841692850192909252600160c01b9091049091166060830152600181015460808301526002015460a082015291506115ef82611c33565b90506040518060e00160405280836000015167ffffffffffffffff168152602001836020015167ffffffffffffffff168152602001836040015167ffffffffffffffff168152602001836060015167ffffffffffffffff168152602001836080015181526020018360a001518152602001828152509250505092915050565b61167b600061030c611c52565b6116975760405162461bcd60e51b815260040161076a906138f7565b8067ffffffffffffffff168267ffffffffffffffff1611156116cb5760405162461bcd60e51b815260040161076a906137d7565b60008167ffffffffffffffff16116116f55760405162461bcd60e51b815260040161076a90613857565b600480546040805160808101825267ffffffffffffffff808416825260016020830181815288831684860190815288841660608601908152928701885560009790975292517f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b8601805494519751925167ffffffffffffffff19909516918416919091177fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff166801000000000000000097151597909702969096177fffffffffffffffffffffffffffffff0000000000000000ffffffffffffffffff16690100000000000000000091831691909102177fffffffffffffff0000000000000000ffffffffffffffffffffffffffffffffff1671010000000000000000000000000000000000929091169190910217909255905181907ffdb3f4239e63a710b156cf2985b3245a1edacb1068995d387544981dc77e800090611859908690869061398f565b60405180910390a2505050565b61186e6123eb565b60048267ffffffffffffffff168154811061188557fe5b600091825260209182902060408051608081018252929091015467ffffffffffffffff808216845268010000000000000000820460ff1615159484019490945269010000000000000000008104841691830191909152710100000000000000000000000000000000009004909116606082015292915050565b61190b600061030c611c52565b6119275760405162461bcd60e51b815260040161076a90613867565b610fee604051611936906136a1565b6040518091039020826107e2565b600081815260208190526040812061107d90611fa0565b6000828152602081905260409020600201546119799061030c611c52565b610ec25760405162461bcd60e51b815260040161076a90613847565b61199d610ff1565b6001600160a01b0316336001600160a01b0316146119cd5760405162461bcd60e51b815260040161076a906138d7565b611a1185858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250879250869150859050611fa7565b5050505050565b6004546060906000908390811115611a2f57506004545b606081604051908082528060200260200182016040528015611a6b57816020015b611a586123eb565b815260200190600190039081611a505790505b5090506000865b600454811015611bea57611a846123eb565b60048281548110611a9157fe5b600091825260209182902060408051608081018252929091015467ffffffffffffffff808216845268010000000000000000820460ff16151594840185905269010000000000000000008204811692840192909252710100000000000000000000000000000000009004166060820152915060011415611be1578060000151848481518110611b1c57fe5b60200260200101516000019067ffffffffffffffff16908167ffffffffffffffff16815250508060200151848481518110611b5357fe5b602002602001015160200190151590811515815250508060400151848481518110611b7a57fe5b60200260200101516040019067ffffffffffffffff16908167ffffffffffffffff16815250508060600151848481518110611bb157fe5b602090810291909101015167ffffffffffffffff909116606090910152600190920191848310611be15750611bea565b50600101611a72565b509093509150505b9250929050565b600060048267ffffffffffffffff1681548110611c1257fe5b60009182526020909120015468010000000000000000900460ff1692915050565b600061107d8260a00151611c4684611fad565b9063ffffffff61207016565b6001546000906001600160a01b03163314611c6e575033610ffe565b611c766120b2565b9050610ffe565b6000828152602081905260409020611c9b908263ffffffff6120ff16565b1561082657611ca8611c52565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600082820167ffffffffffffffff808516908216101561107a5760405162461bcd60e51b815260040161076a906137e7565b60008282018381101561107a5760405162461bcd60e51b815260040161076a906137e7565b6000828152602081905260409020611d61908263ffffffff61216c16565b1561082657611d6e611c52565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b6001600160a01b038116611dd85760405162461bcd60e51b815260040161076a906138b7565b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b50600090565b600081604051602001611e209190613681565b604051602081830303815290604052805190602001209050919050565b60008151604114611e505750600061107d565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611e96576000935050505061107d565b8060ff16601b14158015611eae57508060ff16601c14155b15611ebf576000935050505061107d565b60018682858560405160008152602001604052604051611ee29493929190613751565b6020604051602081039080840390855afa158015611f04573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b60006060611f3560405180602001604052806000815250612291565b915091509091565b604080516020810190915260008152600b9190910191565b6000826001018281548110611f6657fe5b6000918252602090912001546001600160a01b03169392505050565b6001600160a01b031660009081526020919091526040902054151590565b6001015490565b50505050565b608081015160408201516000919067ffffffffffffffff16421015611fd65760009150506107dd565b611ffb8360600151846020015167ffffffffffffffff16611cec90919063ffffffff16565b67ffffffffffffffff1642106120125790506107dd565b6000612035846020015167ffffffffffffffff164261207090919063ffffffff16565b60608501519091506120679067ffffffffffffffff1661205b848463ffffffff61229616565b9063ffffffff6122d016565b925050506107dd565b600061107a83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612312565b600060606000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031692915050565b600061210b8383611f82565b61216457506001828101805480830180835560009283526020808420909201805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03871690811790915583529085905260409091205561107d565b50600061107d565b60006121788383611f82565b15612164576001600160a01b038216600090815260208490526040902054600184015460001991820191018082146122305760008560010182815481106121bb57fe5b6000918252602090912001546001870180546001600160a01b0390921692508291859081106121e657fe5b6000918252602080832091909101805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0394851617905592909116815290869052604090206001830190555b6001600160a01b0384166000908152602086905260408120556001850180548061225657fe5b6000828152602090208101600019908101805473ffffffffffffffffffffffffffffffffffffffff19169055019055506001915061107d9050565b600091565b6000826122a55750600061107d565b828202828482816122b257fe5b041461107a5760405162461bcd60e51b815260040161076a90613887565b600061107a83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612343565b600081848411156123365760405162461bcd60e51b815260040161076a9190613786565b50508183035b9392505050565b600081836123645760405162461bcd60e51b815260040161076a9190613786565b50600083858161237057fe5b0495945050505050565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60408051608081018252600080825260208201819052918101829052606081019190915290565b803561107d81613a5f565b60008083601f84011261242f57600080fd5b50813567ffffffffffffffff81111561244757600080fd5b602083019150836020820283011115611bf257600080fd5b803561107d81613a73565b803561107d81613a7c565b60008083601f84011261248757600080fd5b50813567ffffffffffffffff81111561249f57600080fd5b602083019150836001820283011115611bf257600080fd5b803561107d81613a85565b6000602082840312156124d457600080fd5b60006124e08484612412565b949350505050565b60008060008060008060008060008060006101208c8e03121561250a57600080fd5b60006125168e8e612412565b9b505060206125278e828f01612412565b9a505060408c013567ffffffffffffffff81111561254457600080fd5b6125508e828f01612475565b995099505060606125638e828f0161246a565b97505060806125748e828f0161246a565b96505060a06125858e828f0161246a565b95505060c06125968e828f0161246a565b94505060e08c013567ffffffffffffffff8111156125b357600080fd5b6125bf8e828f01612475565b93509350506101006125d38e828f0161246a565b9150509295989b509295989b9093969950565b6000806000604084860312156125fb57600080fd5b60006126078686612412565b935050602084013567ffffffffffffffff81111561262457600080fd5b6126308682870161241d565b92509250509250925092565b600080600080600060a0868803121561265457600080fd5b60006126608888612412565b95505060206126718882890161246a565b94505060406126828882890161246a565b93505060606126938882890161245f565b92505060806126a48882890161245f565b9150509295509295909350565b600080600080608085870312156126c757600080fd5b60006126d38787612412565b94505060206126e48782880161246a565b93505060406126f5878288016124b7565b92505060606127068782880161246a565b91505092959194509250565b6000806040838503121561272557600080fd5b60006127318585612412565b9250506020612742858286016124b7565b9150509250929050565b6000806000806000806060878903121561276557600080fd5b863567ffffffffffffffff81111561277c57600080fd5b61278889828a0161241d565b9650965050602087013567ffffffffffffffff8111156127a757600080fd5b6127b389828a0161241d565b9450945050604087013567ffffffffffffffff8111156127d257600080fd5b6127de89828a0161241d565b92509250509295509295509295565b6000602082840312156127ff57600080fd5b60006124e0848461246a565b6000806040838503121561281e57600080fd5b600061282a858561246a565b925050602061274285828601612412565b6000806040838503121561284e57600080fd5b600061285a858561246a565b92505060206127428582860161246a565b6000806020838503121561287e57600080fd5b823567ffffffffffffffff81111561289557600080fd5b6128a185828601612475565b92509250509250929050565b6000806000806000608086880312156128c557600080fd5b853567ffffffffffffffff8111156128dc57600080fd5b6128e888828901612475565b955095505060206128fb8882890161245f565b935050604061290c8882890161246a565b92505060606126a48882890161246a565b60006020828403121561292f57600080fd5b60006124e084846124b7565b6000806040838503121561294e57600080fd5b600061273185856124b7565b600061296683836134fe565b505060800190565b600061297a8383613548565b505060e00190565b600061298e8383612b0d565b505060200190565b600061298e83836135d4565b6129ab816139cc565b82525050565b6129ab6129bd826139cc565b613a3e565b60006129cd826139b0565b6129d781856139b4565b93506129e2836139aa565b8060005b83811015612a105781516129fa888261295a565b9750612a05836139aa565b9250506001016129e6565b509495945050505050565b6000612a26826139b0565b612a3081856139b4565b9350612a3b836139aa565b8060005b83811015612a10578151612a53888261296e565b9750612a5e836139aa565b925050600101612a3f565b6000612a74826139b0565b612a7e81856139b4565b9350612a89836139aa565b8060005b83811015612a10578151612aa18882612982565b9750612aac836139aa565b925050600101612a8d565b6000612ac383856139b4565b9350612ace82610ffe565b8060005b85811015612a1057612ae482846139bd565b612aee8882612996565b9750612af9836139aa565b925050600101612ad2565b6129ab816139d7565b6129ab81610ffe565b6129ab612b2282610ffe565b610ffe565b6000612b3383856107dd565b9350612b40838584613a06565b50500190565b6000612b51826139b0565b612b5b81856139b4565b9350612b6b818560208601613a12565b612b7481613a4f565b9093019392505050565b6000612b8b602f836139b4565b7f416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e81527f2061646d696e20746f206772616e740000000000000000000000000000000000602082015260400192915050565b6000612bea6020836139b4565b7f5361746f736869416c6c6f746d656e743a20616d6f756e74206973207a65726f815260200192915050565b6000612c23601c836107dd565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c0192915050565b6000612c5c6047836139b4565b7f5361746f736869416c6c6f746d656e743a206d75737420686176652061646d6981527f6e20726f6c6520746f206368616e6765207361746f73686920746f6b656e206360208201527f6f6e747261637400000000000000000000000000000000000000000000000000604082015260600192915050565b6000612ce1603f836139b4565b7f5361746f736869416c6c6f746d656e743a206163636f756e7473206c656e677481527f6820646f65736e2774206d61746368207769746820696473206c656e67746800602082015260400192915050565b6000612d40602f836139b4565b7f5361746f736869416c6c6f746d656e743a20636c696666206973206c6f6e676581527f72207468616e206475726174696f6e0000000000000000000000000000000000602082015260400192915050565b6000612d9f601b836139b4565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b6000612dd8601f836139b4565b7f5361746f736869416c6c6f746d656e743a204964732061726520656d70747900815260200192915050565b6000612e11601d836139b4565b7f5361746f736869416c6c6f746d656e743a207374617274203c206e6f77000000815260200192915050565b6000612e4a601e836139b4565b7f5361746f736869416c6c6f746d656e743a2064656c6574656420706c616e0000815260200192915050565b6000612e836029836139b4565b7f5361746f736869416c6c6f746d656e743a206163636f756e74206973207a657281527f6f20616464726573730000000000000000000000000000000000000000000000602082015260400192915050565b6000612ee26035836139b4565b7f5361746f736869416c6c6f746d656e743a206d75737420686176652061646d6981527f6e20726f6c6520746f2072656d6f766520706c616e0000000000000000000000602082015260400192915050565b6000612f416030836139b4565b7f416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e81527f2061646d696e20746f207265766f6b6500000000000000000000000000000000602082015260400192915050565b6000612fa0601f836139b4565b7f5361746f736869416c6c6f746d656e743a206475726174696f6e206973203000815260200192915050565b6000612fd96032836139b4565b7f5361746f736869416c6c6f746d656e743a2073656e646572206d75737420626581527f20616e2061646d696e20746f206772616e740000000000000000000000000000602082015260400192915050565b6000613038603e836139b4565b7f5361746f736869416c6c6f746d656e743a20696473206c656e67746820646f6581527f736e2774206d61746368207769746820616d6f756e7473206c656e6774680000602082015260400192915050565b60006130976021836139b4565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f81527f7700000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b60006130f6602b836139b4565b7f5361746f736869416c6c6f746d656e743a204d617820616c6c6f746d656e742081527f4944732072656163686564000000000000000000000000000000000000000000602082015260400192915050565b60006131556026836139b4565b7f5361746f736869416c6c6f746d656e743a20696e76616c696420616c6c6f746d81527f656e742069640000000000000000000000000000000000000000000000000000602082015260400192915050565b60006131b46039836139b4565b7f47534e526563697069656e745369676e61747572653a2074727573746564207381527f69676e657220697320746865207a65726f206164647265737300000000000000602082015260400192915050565b60006132136027836139b4565b7f5361746f736869416c6c6f746d656e743a20616c6c6f746d656e74206861732081527f6578706972656400000000000000000000000000000000000000000000000000602082015260400192915050565b60006132726024836139b4565b7f47534e526563697069656e743a2063616c6c6572206973206e6f742052656c6181527f7948756200000000000000000000000000000000000000000000000000000000602082015260400192915050565b60006132d1603a836139b4565b7f5361746f736869546f6b656e3a206d75737420686176652061646d696e20726f81527f6c6520746f206368616e676520747275737465645369676e6572000000000000602082015260400192915050565b60006133306032836139b4565b7f5361746f736869416c6c6f746d656e743a206d75737420686176652061646d6981527f6e20726f6c6520746f2061646420706c616e0000000000000000000000000000602082015260400192915050565b600061338f600c836107dd565b7f414c4c4f5445525f524f4c4500000000000000000000000000000000000000008152600c0192915050565b60006133c86042836139b4565b7f5361746f736869416c6c6f746d656e743a206d757374206861766520616c6c6f81527f74657220726f6c6520746f20746f70757020616c6c6f746d656e7420746f6b6560208201527f6e73000000000000000000000000000000000000000000000000000000000000604082015260600192915050565b600061344d602f836139b4565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636581527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015260400192915050565b60006134ac6038836139b4565b7f5361746f736869416c6c6f746d656e743a206d757374206861766520616c6c6f81527f74657220726f6c6520746f20616c6c6f7420746f6b656e730000000000000000602082015260400192915050565b8051608083019061350f84826135d4565b5060208201516135226020850182612b04565b50604082015161353560408501826135d4565b506060820151611fa760608501826135d4565b805160e083019061355984826135d4565b50602082015161356c60208501826135d4565b50604082015161357f60408501826135d4565b50606082015161359260608501826135d4565b5060808201516135a56080850182612b0d565b5060a08201516135b860a0850182612b0d565b5060c0820151611fa760c0850182612b0d565b6129ab816139fb565b6129ab816139e8565b6129ab816139f5565b60006135f2828d6129b1565b601482019150613602828c6129b1565b601482019150613613828a8c612b27565b915061361f8289612b16565b60208201915061362f8288612b16565b60208201915061363f8287612b16565b60208201915061364f8286612b16565b60208201915061365f82856129b1565b60148201915061366f82846129b1565b506014019a9950505050505050505050565b600061368c82612c16565b91506136988284612b16565b50602001919050565b600061107d82613382565b6020810161107d82846129a2565b604081016136c882856129a2565b61233c6020830184612b0d565b604080825281016136e681856129c2565b905061233c6020830184612b0d565b604080825281016136e68185612a1b565b60408082528101613718818587612ab7565b9050818103602083015261372c8184612a69565b95945050505050565b6020810161107d8284612b04565b6020810161107d8284612b0d565b6080810161375f8287612b0d565b61376c60208301866135dd565b6137796040830185612b0d565b61372c6060830184612b0d565b6020808252810161107a8184612b46565b6020808252810161107d81612b7e565b6020808252810161107d81612bdd565b6020808252810161107d81612c4f565b6020808252810161107d81612cd4565b6020808252810161107d81612d33565b6020808252810161107d81612d92565b6020808252810161107d81612dcb565b6020808252810161107d81612e04565b6020808252810161107d81612e3d565b6020808252810161107d81612e76565b6020808252810161107d81612ed5565b6020808252810161107d81612f34565b6020808252810161107d81612f93565b6020808252810161107d81612fcc565b6020808252810161107d8161302b565b6020808252810161107d8161308a565b6020808252810161107d816130e9565b6020808252810161107d81613148565b6020808252810161107d816131a7565b6020808252810161107d81613206565b6020808252810161107d81613265565b6020808252810161107d816132c4565b6020808252810161107d81613323565b6020808252810161107d816133bb565b6020808252810161107d81613440565b6020808252810161107d8161349f565b6080810161107d82846134fe565b60e0810161107d8284613548565b604081016139618285612b0d565b81810360208301526124e08184612b46565b6020810161107d82846135d4565b604081016136c882856135cb565b6040810161399d82856135d4565b61233c60208301846135d4565b60200190565b5190565b90815260200190565b600061107a60208401846124b7565b600061107d826139dc565b151590565b6001600160a01b031690565b67ffffffffffffffff1690565b60ff1690565b600061107d826139e8565b82818337506000910152565b60005b83811015613a2d578181015183820152602001613a15565b83811115611fa75750506000910152565b600061107d82600061107d82613a59565b601f01601f191690565b60601b90565b613a68816139cc565b8114610fee57600080fd5b613a68816139d7565b613a6881610ffe565b613a68816139e856fea365627a7a72315820c9c4ee1b8720b1046f03191ba2378241876574b2524c7789219aad9afa6c239a6c6578706572696d656e74616cf564736f6c63430005100040
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000787d6335e033fe9dec59db61a6a936b4cebbe839000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000020f5800000000000000000000000000919cbb0be55ba996a567107ea13f417be74e477a
-----Decoded View---------------
Arg [0] : satoshiToken (address): 0x787d6335E033fE9Dec59Db61A6A936B4CebbE839
Arg [1] : cliffDuration (uint64): 30
Arg [2] : duration (uint64): 34560000
Arg [3] : trustedSigner (address): 0x919CbB0be55ba996A567107EA13f417Be74e477A
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000787d6335e033fe9dec59db61a6a936b4cebbe839
Arg [1] : 000000000000000000000000000000000000000000000000000000000000001e
Arg [2] : 00000000000000000000000000000000000000000000000000000000020f5800
Arg [3] : 000000000000000000000000919cbb0be55ba996a567107ea13f417be74e477a
Deployed Bytecode Sourcemap
71425:18646:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;71425:18646:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79173:1766;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;81944:382;;;;;;;;;:::i;:::-;;29897:114;;;;;;;;;:::i;:::-;;;;;;;;30273:219;;;;;;;;;:::i;86544:1210::-;;;;;;;;;:::i;87956:2112::-;;;;;;;;;:::i;31466:201::-;;;;;;;;;:::i;71671:64::-;;;:::i;83972:357::-;;;;;;;;;:::i;75245:248::-;;;;;;;;;:::i;50687:87::-;;;:::i;:::-;;;;;;;;54350:211;;;;;;;;;:::i;64505:1035::-;;;;;;;;;:::i;:::-;;;;;;;;;29569:139;;;;;;;;;:::i;28530:::-;;;;;;;;;:::i;:::-;;;;;;;;75636:113;;;:::i;84906:1196::-;;;;;;;;;:::i;:::-;;;;;;;;27698:49;;;:::i;51945:230::-;;;:::i;:::-;;;;;;;;81163:579;;;;;;;;;:::i;:::-;;;;;;;;83066:695;;;;;;;;;:::i;77546:129::-;;;;;;;;;:::i;:::-;;;;;;;;82524:237;;;;;;;;;:::i;28843:127::-;;;;;;;;;:::i;30737:222::-;;;;;;;;;:::i;55210:277::-;;;;;;;;;:::i;76034:1058::-;;;;;;;;;:::i;:::-;;;;;;;;;77250:121;;;;;;;;;:::i;79173:1766::-;-1:-1:-1;;;;;79449:27:0;;79391:7;79449:27;;;:18;:27;;;;;;;;79412:64;;;;;;;;;;;;;;;;;79363:26;;79391:7;79363:26;;79412:64;79449:27;79412:64;79391:7;;79412:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;79412:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;79510:15:0;;79412:64;;-1:-1:-1;79555:9:0;;-1:-1:-1;;79581:21:0;;;79577:61;;;-1:-1:-1;79626:12:0;79577:61;79651:36;79714:6;79690:31;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;79651:70:0;-1:-1:-1;79734:17:0;79785:6;79768:1124;79797:12;79793:1;:16;79768:1124;;;79831:24;79872:31;;:::i;:::-;79906:8;79915:1;79906:11;;;;;;;;;;;;;;79872:45;;79957:7;:13;;;79938:32;;:15;:32;79934:118;;80010:26;80028:7;80010:17;:26::i;:::-;79991:45;;79934:118;80092:1;80073:16;:20;80072:107;;;-1:-1:-1;80117:4:0;:23;;;;80116:62;;;;;80164:7;:13;;;80146:31;;:15;:31;80116:62;80072:148;;;-1:-1:-1;80201:4:0;:18;;;;80072:148;80068:813;;;80301:7;:10;;;80275:9;80285;80275:20;;;;;;;;;;;;;;;;;;:36;;;;;;80360:14;;;;80330:20;;:9;;80340;;80330:20;;;;;;;;;;;;:27;;:44;;;;;80422:7;:13;;;80393:9;80403;80393:20;;;;;;;;;;;;;;:26;;:42;;;;;;;;;;;80483:7;:13;;;80454:9;80464;80454:20;;;;;;;;;;;;;;:26;;:42;;;;;;;;;;;80547:7;:16;;;80515:9;80525;80515:20;;;;;;;;;;;;;;:29;;:48;;;;;;;;;;;80620:7;:22;;;80582:9;80592;80582:20;;;;;;;;;;;;;;:35;;:60;;;;;80700:16;80661:9;80671;80661:20;;;;;;;;;;;;;;;;;;:36;;:55;80737:11;;;;;80818:19;;;80814:51;;80860:5;;;;80814:51;-1:-1:-1;;79811:3:0;;79768:1124;;;-1:-1:-1;80910:9:0;;;;-1:-1:-1;79173:1766:0;-1:-1:-1;;;;;;;;;79173:1766:0:o;81944:382::-;82028:41;27743:4;82056:12;:10;:12::i;82028:41::-;82020:148;;;;-1:-1:-1;;;82020:148:0;;;;;;;;;;;;;;;;;82227:13;:41;;-1:-1:-1;;82227:41:0;-1:-1:-1;;;;;82227:41:0;;;;;;;;82286:32;;;;-1:-1:-1;;82286:32:0;81944:382;:::o;29897:114::-;29954:7;29981:12;;;;;;;;;;:22;;;29897:114;;;;:::o;30273:219::-;30357:6;:12;;;;;;;;;;:22;;;30349:45;;30381:12;:10;:12::i;30349:45::-;30341:105;;;;-1:-1:-1;;;30341:105:0;;;;;;;;;30459:25;30470:4;30476:7;30459:10;:25::i;:::-;30273:219;;:::o;86544:1210::-;86667:35;71710:25;;;;;;;;;;;;;;86689:12;:10;:12::i;86667:35::-;86659:137;;;;-1:-1:-1;;;86659:137:0;;;;;;;;;86817:29;;;86809:105;;;;-1:-1:-1;;;86809:105:0;;;;;;;;;86933:28;;;86925:103;;;;-1:-1:-1;;;86925:103:0;;;;;;;;;87046:9;87041:706;87061:19;;;87041:706;;;87133:1;87110:8;;87119:1;87110:11;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;87110:25:0;;;87102:79;;;;-1:-1:-1;;;87102:79:0;;;;;;;;;87217:1;87204:7;;87212:1;87204:10;;;;;;;;;;;;;:14;87196:59;;;;-1:-1:-1;;;87196:59:0;;;;;;;;;87272:39;87314:18;:31;87333:8;;87342:1;87333:11;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;87314:31:0;-1:-1:-1;;;;;87314:31:0;;;;;;;;;;;;87346:3;;87350:1;87346:6;;;;;;;;;;;;;;;;;;;;;;87314:39;;;;;;;;;;;;;;;;;;;;;;;87455:23;;87314:39;;-1:-1:-1;87482:15:0;;87430:49;;87455:23;87430:20;;;;;;-1:-1:-1;;;87455:23:0;;;87430:24;:49::i;:::-;:67;;;87422:119;;;;-1:-1:-1;;;87422:119:0;;;;;;;;;87643:7;;87651:1;87643:10;;;;;;;87618:21;;;:35;;87643:10;;;;;;;;;87618:35;;;;-1:-1:-1;87719:15:0;87699:3;;87703:1;87699:6;;;;;;;;;;;;;;;;;;;;;;87675:60;;87686:8;;87695:1;87686:11;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;87675:60:0;;87707:7;;87715:1;87707:10;;;;;;;;;;;;;87675:60;;;;;;;;;;;;;;;-1:-1:-1;87082:3:0;;87041:706;;;;86544:1210;;;;;;:::o;87956:2112::-;-1:-1:-1;;;;;88041:21:0;;88033:75;;;;-1:-1:-1;;;88033:75:0;;;;;;;;;88127:14;88119:58;;;;-1:-1:-1;;;88119:58:0;;;;;;;;;-1:-1:-1;;;;;88363:27:0;;88188:26;88363:27;;;:18;:27;;;;;;;;88426:15;;88579:24;;;;;;;;;;;;;;;;88188:26;;88363:27;;88426:15;88472:3;;88544:32;;88472:3;88579:24;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;88579:24:0;;88544:59;;88632:12;88620:9;:24;88616:67;;;88671:12;88659:24;;88616:67;88701:9;88696:1125;88720:9;88716:1;:13;88696:1125;;;88828:12;88819:3;;88823:1;88819:6;;;;;;;;;;;;;;;;;;;;;;:21;;;88810:73;;;;-1:-1:-1;;;88810:73:0;;;;;;;;;88974:39;89016:8;89025:3;;89029:1;89025:6;;;;;;;;;;;;;;;;;;;;;;89016:16;;;;;;;;;;;;;;;;;;;;88974:58;;89127:31;;:::i;:::-;89161:8;89170:3;;89174:1;89170:6;;;;;;;;;;;;;;;;;;;;;;89161:16;;;;;;;;;;;;;;;;;;;89127:50;;;;;;;;89161:16;;;;;;;89127:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;89127:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;89198:15:0;:32;89194:616;;89272:26;89290:7;89272:17;:26::i;:::-;89251:47;-1:-1:-1;89345:47:0;:23;89251:47;89345;:27;:47;:::i;:::-;89319:73;;89434:18;89413:15;89429:1;89413:18;;;;;;;;;;;;;;;;;:39;89584:14;;;;89533:22;;;;:46;;89560:18;89533:46;:26;:46;:::i;:::-;89532:66;89528:266;;89628:8;89637:3;;89641:1;89637:6;;;;;;;;;;;;;;;;;;;;;;89628:16;;;;;;;;;;;;;;;;;;;;;;89621:24;;;;;;;;;;;;89528:266;;;89748:22;;;;:46;;89775:18;89748:46;:26;:46;:::i;:::-;89716:29;;;:78;89528:266;-1:-1:-1;;88731:3:0;;88696:1125;;;-1:-1:-1;89886:27:0;;89882:98;;89928:13;;:52;;;;;-1:-1:-1;;;;;89928:13:0;;;;:18;;:52;;89947:7;;89956:23;;89928:52;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;89928:52:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;89928:52:0;;;;89882:98;90044:15;90013:7;-1:-1:-1;;;;;89998:62:0;;90022:3;;90027:15;89998:62;;;;;;;;;;;;;;;;;87956:2112;;;;;;;;;:::o;31466:201::-;31556:12;:10;:12::i;:::-;-1:-1:-1;;;;;31545:23:0;:7;-1:-1:-1;;;;;31545:23:0;;31537:83;;;;-1:-1:-1;;;31537:83:0;;;;;;;;;31633:26;31645:4;31651:7;31633:11;:26::i;71671:64::-;71710:25;;;;;;;;;;;;;;71671:64;:::o;83972:357::-;84041:41;27743:4;84069:12;:10;:12::i;84041:41::-;84033:130;;;;-1:-1:-1;;;84033:130:0;;;;;;;;;84182:15;84198:2;84182:19;;;;;;;;;;;;;;;;;:27;;;;;;:35;;84213:4;84182:35;84174:78;;;;-1:-1:-1;;;84174:78:0;;;;;;;;;84270:15;84286:2;84270:19;;;;;;;;;;;;;;;;84263:27;;;;;;84306:15;;84318:2;;84306:15;;;83972:357;:::o;75245:248::-;75320:41;27743:4;75348:12;:10;:12::i;75320:41::-;75312:125;;;;-1:-1:-1;;;75312:125:0;;;;;;;;;75448:37;75471:13;75448:22;:37::i;:::-;75245:248;:::o;50687:87::-;50757:9;;-1:-1:-1;;;;;50757:9:0;50687:87;;:::o;54350:211::-;54416:7;54458:12;:10;:12::i;:::-;-1:-1:-1;;;;;54444:26:0;:10;-1:-1:-1;;;;;54444:26:0;;54436:75;;;;-1:-1:-1;;;54436:75:0;;;;;;;;;54529:24;54545:7;;54529:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;54529:15:0;;-1:-1:-1;;;54529:24:0:i;:::-;54522:31;;54350:211;;;;;:::o;64505:1035::-;64844:7;64853:12;64883:17;64934:5;64954:4;64973:15;;65003:14;65032:8;65055;65078:5;65130:12;:10;:12::i;:::-;65207:4;64903:363;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;65347:14:0;;49:4:-1;65281:62:0;;;;;;;;;;;;;;;;;;64903:363;;-1:-1:-1;;;;;;65347:14:0;;65281:62;;65330:12;;;;;;65281:62;;65330:12;;;;65281:62;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;65281:15:0;;;;;;:40;;-1:-1:-1;65281:15:0;-1:-1:-1;65281:38:0;:40::i;:::-;:48;:62;:48;:62;:::i;:::-;-1:-1:-1;;;;;65281:80:0;;65277:256;;;65385:21;:19;:21::i;:::-;65378:28;;;;;;;65277:256;65446:75;65473:46;65446:18;:75::i;64505:1035::-;;;;;;;;;;;;;;;:::o;29569:139::-;29642:7;29669:12;;;;;;;;;;:31;;29694:5;29669:31;:24;:31;:::i;28530:139::-;28599:4;28623:12;;;;;;;;;;:38;;28653:7;28623:38;:29;:38;:::i;75636:113::-;75727:13;;-1:-1:-1;;;;;75727:13:0;75636:113;:::o;84906:1196::-;85038:6;85067:35;71710:25;;;;;;85067:35;85059:127;;;;-1:-1:-1;;;85059:127:0;;;;;;;;;-1:-1:-1;;;;;85205:21:0;;85197:75;;;;-1:-1:-1;;;85197:75:0;;;;;;;;;85300:15;85291:5;:24;;;;85283:66;;;;-1:-1:-1;;;85283:66:0;;;;;;;;;85418:25;;:::i;:::-;85446:15;85462:6;85446:23;;;;;;;;;;;;;;;;;85418:51;;;;;;;;85446:23;;;;85418:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85418:51:0;85488:20;85480:63;;;;-1:-1:-1;;;85480:63:0;;;;;;;;;-1:-1:-1;;;;;85569:27:0;;85556:10;85569:27;;;:18;:27;;;;;:34;85627:21;85622:26;;85614:82;;;;-1:-1:-1;;;85614:82:0;;;;;;;;;85709:18;:27;85728:7;-1:-1:-1;;;;;85709:27:0;-1:-1:-1;;;;;85709:27:0;;;;;;;;;;;;85742:237;;;;;;;;85787:2;85742:237;;;;;;85812:5;85742:237;;;;;;85839:29;85849:4;:18;;;85839:5;:9;;;;:29;;;;:::i;:::-;85742:237;;;;;;85893:13;;;;;85742:237;;;;;;;;;;-1:-1:-1;85742:237:0;;;;;;-1:-1:-1;85742:237:0;;;;;;27:10:-1;;39:1;23:18;;;45:23;;85709:271:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;85709:271:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;85709:271:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85998:64;86046:15;;-1:-1:-1;;;;;85998:64:0;;;;;;;86033:2;;85742:237;;85998:64;;;;;;;;;;86091:2;84906:1196;-1:-1:-1;;;;;;84906:1196:0:o;27698:49::-;27743:4;27698:49;:::o;51945:230::-;52153:14;;;;;;;;;;;;;;;;;51945:230;:::o;81163:579::-;81238:24;;:::i;:::-;81275:31;;:::i;:::-;-1:-1:-1;;;;;81309:27:0;;;;;;:18;:27;;;;;:31;;;;;;;;;;;;;;;;;;;;81275:65;;;;;;;;81309:31;;;;;;;81275:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;81275:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;81378:26:0;81275:65;81378:17;:26::i;:::-;81351:53;;81425:308;;;;;;;;81462:7;:10;;;81425:308;;;;;;81531:7;:13;;;81425:308;;;;;;81566:7;:13;;;81425:308;;;;;;81604:7;:16;;;81425:308;;;;;;81495:7;:14;;;81425:308;;;;81651:7;:22;;;81425:308;;;;81705:16;81425:308;;;81417:317;;;;81163:579;;;;:::o;83066:695::-;83159:41;27743:4;83187:12;:10;:12::i;83159:41::-;83151:127;;;;-1:-1:-1;;;83151:127:0;;;;;;;;;83316:8;83299:25;;:13;:25;;;;83291:85;;;;-1:-1:-1;;;83291:85:0;;;;;;;;;83406:1;83395:8;:12;;;83387:56;;;;-1:-1:-1;;;83387:56:0;;;;;;;;;83473:15;:22;;83529:165;;;;;;;;;;;;;;83602:4;83529:165;;;;;;;;;;;;;;;;;;;;;;;;23:18:-1;;;45:23;;-1:-1;83508:187:0;;;;;;;;;;;;;;;;;-1:-1:-1;;83508:187:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83711:42;;83473:22;;83711:42;;;;83529:165;;;;83711:42;;;;;;;;;;83066:695;;;:::o;77546:129::-;77608:20;;:::i;:::-;77648:15;77664:2;77648:19;;;;;;;;;;;;;;;;;;;77641:26;;;;;;;;77648:19;;;;77641:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77546:129;-1:-1:-1;;77546:129:0:o;82524:237::-;82595:41;27743:4;82623:12;:10;:12::i;82595:41::-;82587:117;;;;-1:-1:-1;;;82587:117:0;;;;;;;;;82715:38;71710:25;;;;;;;;;;;;;;82745:7;82715:15;:38::i;28843:127::-;28906:7;28933:12;;;;;;;;;;:29;;:27;:29::i;30737:222::-;30822:6;:12;;;;;;;;;;:22;;;30814:45;;30846:12;:10;:12::i;30814:45::-;30806:106;;;;-1:-1:-1;;;30806:106:0;;;;;;;;55210:277;55356:12;:10;:12::i;:::-;-1:-1:-1;;;;;55342:26:0;:10;-1:-1:-1;;;;;55342:26:0;;55334:75;;;;-1:-1:-1;;;55334:75:0;;;;;;;;;55420:59;55437:7;;55420:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;55446:7:0;;-1:-1:-1;55455:12:0;;-1:-1:-1;55469:9:0;;-1:-1:-1;55420:16:0;:59::i;:::-;55210:277;;;;;:::o;76034:1058::-;76231:15;:22;76136;;76160:7;;76198:9;;76222:31;;76218:81;;;-1:-1:-1;76277:15:0;:22;76218:81;76312:32;76367:6;76347:27;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;76312:62:0;-1:-1:-1;76387:17:0;76438:6;76421:624;76450:15;:22;76446:26;;76421:624;;;76494:25;;:::i;:::-;76522:15;76538:1;76522:18;;;;;;;;;;;;;;;;;76494:46;;;;;;;;76522:18;;;;76494:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;76494:46:0;76561:20;76557:477;;;76662:4;:7;;;76636:9;76646;76636:20;;;;;;;;;;;;;;:23;;:33;;;;;;;;;;;76719:4;:12;;;76688:9;76698;76688:20;;;;;;;;;;;;;;:28;;:43;;;;;;;;;;;76787:4;:18;;;76750:9;76760;76750:20;;;;;;;;;;;;;;:34;;:55;;;;;;;;;;;76856:4;:13;;;76824:9;76834;76824:20;;;;;;;;;;;;;;;;;;:45;;;;:29;;;;:45;76890:11;;;;;76971:19;;;76967:51;;77013:5;;;76967:51;-1:-1:-1;76474:3:0;;76421:624;;;-1:-1:-1;77063:9:0;;-1:-1:-1;77074:9:0;-1:-1:-1;;76034:1058:0;;;;;;:::o;77250:121::-;77312:4;77336:15;77352:2;77336:19;;;;;;;;;;;;;;;;;;;:27;;;;;;;77250:121;-1:-1:-1;;77250:121:0:o;77920:169::-;78002:7;78029:52;78058:7;:22;;;78029:24;78045:7;78029:15;:24::i;:::-;:28;:52;:28;:52;:::i;53147:216::-;53238:9;;53192:15;;-1:-1:-1;;;;;53238:9:0;53224:10;:23;53220:136;;-1:-1:-1;53271:10:0;53264:17;;53220:136;53321:23;:21;:23::i;:::-;53314:30;;;;32562:188;32636:6;:12;;;;;;;;;;:33;;32661:7;32636:33;:24;:33;:::i;:::-;32632:111;;;32718:12;:10;:12::i;:::-;-1:-1:-1;;;;;32691:40:0;32709:7;-1:-1:-1;;;;;32691:40:0;32703:4;32691:40;;;;;;;;;;32562:188;;:::o;66746:177::-;66802:6;66832:5;;;66856:6;;;;;;;;;66848:46;;;;-1:-1:-1;;;66848:46:0;;;;;;;;6094:181;6152:7;6184:5;;;6208:6;;;;6200:46;;;;-1:-1:-1;;;6200:46:0;;;;;;;;32758:192;32833:6;:12;;;;;;;;;;:36;;32861:7;32833:36;:27;:36;:::i;:::-;32829:114;;;32918:12;:10;:12::i;:::-;-1:-1:-1;;;;;32891:40:0;32909:7;-1:-1:-1;;;;;32891:40:0;32903:4;32891:40;;;;;;;;;;32758:192;;:::o;64165:213::-;-1:-1:-1;;;;;64240:27:0;;64232:97;;;;-1:-1:-1;;;64232:97:0;;;;;;;;;64340:14;:30;;-1:-1:-1;;64340:30:0;-1:-1:-1;;;;;64340:30:0;;;;;;;;;;64165:213::o;65548:132::-;-1:-1:-1;65605:7:0;;65548:132::o;62701:269::-;62770:7;62956:4;62903:58;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;62903:58:0;;;62893:69;;;;;;62886:76;;62701:269;;;:::o;60497:1930::-;60575:7;60638:9;:16;60658:2;60638:22;60634:74;;-1:-1:-1;60693:1:0;60677:19;;60634:74;61069:4;61054:20;;61048:27;61115:4;61100:20;;61094:27;61169:4;61154:20;;61148:27;60777:9;61140:36;62099:66;62086:79;;62082:129;;;62197:1;62182:17;;;;;;;62082:129;62227:1;:7;;62232:2;62227:7;;:18;;;;;62238:1;:7;;62243:2;62238:7;;62227:18;62223:68;;;62277:1;62262:17;;;;;;;62223:68;62395:24;62405:4;62411:1;62414;62417;62395:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;62395:24:0;;-1:-1:-1;;62395:24:0;;;60497:1930;-1:-1:-1;;;;;;;60497:1930:0:o;56096:126::-;56150:7;56159:12;56191:23;;;;;;;;;;;;;:19;:23::i;:::-;56184:30;;;;56096:126;;:::o;56682:158::-;56786:46;;;;;;;;;-1:-1:-1;56786:46:0;;50265:2;56794:33;;;;;56682:158::o;24651:159::-;24753:7;24785:3;:10;;24796:5;24785:17;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;24785:17:0;;24651:159;-1:-1:-1;;;24651:159:0:o;23234:165::-;-1:-1:-1;;;;;23370:16:0;23341:4;23370:16;;;;;;;;;;;;:21;;;23234:165::o;24172:147::-;24294:10;;:17;;24172:147::o;65688:139::-;;;;;:::o;78286:523::-;78409:14;;;;78458:13;;;;78366:7;;78409:14;78440:31;;:15;:31;78436:366;;;78495:1;78488:8;;;;;78436:366;78538:35;78556:7;:16;;;78538:7;:13;;;:17;;;;:35;;;;:::i;:::-;78518:56;;:15;:56;78514:288;;78598:12;-1:-1:-1;78591:19:0;;78514:288;78643:16;78662:45;78692:7;:13;;;78682:24;;78662:15;:19;;:45;;;;:::i;:::-;78772:16;;;;78643:64;;-1:-1:-1;78731:59:0;;78762:27;;78731:26;:12;78643:64;78731:26;:16;:26;:::i;:::-;:30;:59;:30;:59;:::i;:::-;78724:66;;;;;;6550:136;6608:7;6635:43;6639:1;6642;6635:43;;;;;;;;;;;;;;;;;:3;:43::i;57356:1270::-;57411:22;58229:18;58250:8;;58229:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;;;;58285:8:0;58521:17;58515:24;-1:-1:-1;;;;;58511:73:0;;57356:1270;-1:-1:-1;;57356:1270:0:o;21683:282::-;21771:4;21798:20;21807:3;21812:5;21798:8;:20::i;:::-;21793:165;;-1:-1:-1;21853:10:0;;;;27::-1;;23:18;;;45:23;;;-1:-1;21853:22:0;;;;;;;;;;;;-1:-1:-1;;21853:22:0;-1:-1:-1;;;;;21853:22:0;;;;;;;;21834:16;;;;;;;;;;:41;21890:11;;21793:165;-1:-1:-1;21941:5:0;21934:12;;22101:1047;22192:4;22218:20;22227:3;22232:5;22218:8;:20::i;:::-;22214:927;;;-1:-1:-1;;;;;22278:16:0;;22254:21;22278:16;;;;;;;;;;;22297:1;22333:10;;:17;-1:-1:-1;;22278:20:0;;;;22333:21;22481:26;;;22477:389;;22528:17;22548:3;:10;;22559:9;22548:21;;;;;;;;;;;;;;;;;;;22670:10;;:25;;-1:-1:-1;;;;;22548:21:0;;;;-1:-1:-1;22548:21:0;;22681:13;;22670:25;;;;;;;;;;;;;;;;;;:37;;-1:-1:-1;;22670:37:0;-1:-1:-1;;;;;22670:37:0;;;;;;22783:20;;;;;;;;;;;;;-1:-1:-1;22806:17:0;;22783:40;;22477:389;-1:-1:-1;;;;;22950:16:0;;:9;:16;;;;;;;;;;22943:23;23040:10;;;:16;;;;;;;;;;;;;;;;-1:-1:-1;;23040:16:0;;;;;-1:-1:-1;;23040:16:0;;;;;;-1:-1:-1;23040:16:0;;-1:-1:-1;23073:11:0;;-1:-1:-1;23073:11:0;56391:155;56465:7;;56391:155::o;7466:471::-;7524:7;7769:6;7765:47;;-1:-1:-1;7799:1:0;7792:8;;7765:47;7836:5;;;7840:1;7836;:5;:1;7860:5;;;;;:10;7852:56;;;;-1:-1:-1;;;7852:56:0;;;;;;;;8405:132;8463:7;8490:39;8494:1;8497;8490:39;;;;;;;;;;;;;;;;;:3;:39::i;7023:192::-;7109:7;7145:12;7137:6;;;;7129:29;;;;-1:-1:-1;;;7129:29:0;;;;;;;;;;-1:-1:-1;;7181:5:0;;;7023:192;;;;;;:::o;9067:345::-;9153:7;9255:12;9248:5;9240:28;;;;-1:-1:-1;;;9240:28:0;;;;;;;;;;;9279:9;9295:1;9291;:5;;;;;;;9067:345;-1:-1:-1;;;;;9067:345:0:o;71425:18646::-;;;;;;;;;-1:-1:-1;71425:18646:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;-1:-1:-1;71425:18646:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;-1:-1:-1;71425:18646:0;;;;;;;;;;;;;;;;;;;;;;;:::o;5:130:-1:-;72:20;;97:33;72:20;97:33;;160:352;;;290:3;283:4;275:6;271:17;267:27;257:2;;308:1;305;298:12;257:2;-1:-1;328:20;;368:18;357:30;;354:2;;;400:1;397;390:12;354:2;434:4;426:6;422:17;410:29;;485:3;477:4;469:6;465:17;455:8;451:32;448:41;445:2;;;502:1;499;492:12;1274:124;1338:20;;1363:30;1338:20;1363:30;;1405:130;1472:20;;1497:33;1472:20;1497:33;;1556:336;;;1670:3;1663:4;1655:6;1651:17;1647:27;1637:2;;1688:1;1685;1678:12;1637:2;-1:-1;1708:20;;1748:18;1737:30;;1734:2;;;1780:1;1777;1770:12;1734:2;1814:4;1806:6;1802:17;1790:29;;1865:3;1857:4;1849:6;1845:17;1835:8;1831:32;1828:41;1825:2;;;1882:1;1879;1872:12;2037:128;2103:20;;2128:32;2103:20;2128:32;;2172:241;;2276:2;2264:9;2255:7;2251:23;2247:32;2244:2;;;2292:1;2289;2282:12;2244:2;2327:1;2344:53;2389:7;2369:9;2344:53;;;2334:63;2238:175;-1:-1;;;;2238:175;2420:1497;;;;;;;;;;;;2699:3;2687:9;2678:7;2674:23;2670:33;2667:2;;;2716:1;2713;2706:12;2667:2;2751:1;2768:53;2813:7;2793:9;2768:53;;;2758:63;;2730:97;2858:2;2876:53;2921:7;2912:6;2901:9;2897:22;2876:53;;;2866:63;;2837:98;2994:2;2983:9;2979:18;2966:32;3018:18;3010:6;3007:30;3004:2;;;3050:1;3047;3040:12;3004:2;3078:64;3134:7;3125:6;3114:9;3110:22;3078:64;;;3068:74;;;;2945:203;3179:2;3197:53;3242:7;3233:6;3222:9;3218:22;3197:53;;;3187:63;;3158:98;3287:3;3306:53;3351:7;3342:6;3331:9;3327:22;3306:53;;;3296:63;;3266:99;3396:3;3415:53;3460:7;3451:6;3440:9;3436:22;3415:53;;;3405:63;;3375:99;3505:3;3524:53;3569:7;3560:6;3549:9;3545:22;3524:53;;;3514:63;;3484:99;3642:3;3631:9;3627:19;3614:33;3667:18;3659:6;3656:30;3653:2;;;3699:1;3696;3689:12;3653:2;3727:64;3783:7;3774:6;3763:9;3759:22;3727:64;;;3717:74;;;;3593:204;3828:3;3848:53;3893:7;3884:6;3873:9;3869:22;3848:53;;;3837:64;;3807:100;2661:1256;;;;;;;;;;;;;;;3924:520;;;;4079:2;4067:9;4058:7;4054:23;4050:32;4047:2;;;4095:1;4092;4085:12;4047:2;4130:1;4147:53;4192:7;4172:9;4147:53;;;4137:63;;4109:97;4265:2;4254:9;4250:18;4237:32;4289:18;4281:6;4278:30;4275:2;;;4321:1;4318;4311:12;4275:2;4349:79;4420:7;4411:6;4400:9;4396:22;4349:79;;;4339:89;;;;4216:218;4041:403;;;;;;4451:731;;;;;;4617:3;4605:9;4596:7;4592:23;4588:33;4585:2;;;4634:1;4631;4624:12;4585:2;4669:1;4686:53;4731:7;4711:9;4686:53;;;4676:63;;4648:97;4776:2;4794:53;4839:7;4830:6;4819:9;4815:22;4794:53;;;4784:63;;4755:98;4884:2;4902:53;4947:7;4938:6;4927:9;4923:22;4902:53;;;4892:63;;4863:98;4992:2;5010:50;5052:7;5043:6;5032:9;5028:22;5010:50;;;5000:60;;4971:95;5097:3;5116:50;5158:7;5149:6;5138:9;5134:22;5116:50;;;5106:60;;5076:96;4579:603;;;;;;;;;5189:615;;;;;5343:3;5331:9;5322:7;5318:23;5314:33;5311:2;;;5360:1;5357;5350:12;5311:2;5395:1;5412:53;5457:7;5437:9;5412:53;;;5402:63;;5374:97;5502:2;5520:53;5565:7;5556:6;5545:9;5541:22;5520:53;;;5510:63;;5481:98;5610:2;5628:52;5672:7;5663:6;5652:9;5648:22;5628:52;;;5618:62;;5589:97;5717:2;5735:53;5780:7;5771:6;5760:9;5756:22;5735:53;;;5725:63;;5696:98;5305:499;;;;;;;;5811:364;;;5931:2;5919:9;5910:7;5906:23;5902:32;5899:2;;;5947:1;5944;5937:12;5899:2;5982:1;5999:53;6044:7;6024:9;5999:53;;;5989:63;;5961:97;6089:2;6107:52;6151:7;6142:6;6131:9;6127:22;6107:52;;;6097:62;;6068:97;5893:282;;;;;;6182:957;;;;;;;6424:2;6412:9;6403:7;6399:23;6395:32;6392:2;;;6440:1;6437;6430:12;6392:2;6475:31;;6526:18;6515:30;;6512:2;;;6558:1;6555;6548:12;6512:2;6586:80;6658:7;6649:6;6638:9;6634:22;6586:80;;;6576:90;;;;6454:218;6731:2;6720:9;6716:18;6703:32;6755:18;6747:6;6744:30;6741:2;;;6787:1;6784;6777:12;6741:2;6815:79;6886:7;6877:6;6866:9;6862:22;6815:79;;;6805:89;;;;6682:218;6959:2;6948:9;6944:18;6931:32;6983:18;6975:6;6972:30;6969:2;;;7015:1;7012;7005:12;6969:2;7043:80;7115:7;7106:6;7095:9;7091:22;7043:80;;;7033:90;;;;6910:219;6386:753;;;;;;;;;7146:241;;7250:2;7238:9;7229:7;7225:23;7221:32;7218:2;;;7266:1;7263;7256:12;7218:2;7301:1;7318:53;7363:7;7343:9;7318:53;;7394:366;;;7515:2;7503:9;7494:7;7490:23;7486:32;7483:2;;;7531:1;7528;7521:12;7483:2;7566:1;7583:53;7628:7;7608:9;7583:53;;;7573:63;;7545:97;7673:2;7691:53;7736:7;7727:6;7716:9;7712:22;7691:53;;7767:366;;;7888:2;7876:9;7867:7;7863:23;7859:32;7856:2;;;7904:1;7901;7894:12;7856:2;7939:1;7956:53;8001:7;7981:9;7956:53;;;7946:63;;7918:97;8046:2;8064:53;8109:7;8100:6;8089:9;8085:22;8064:53;;8140:365;;;8263:2;8251:9;8242:7;8238:23;8234:32;8231:2;;;8279:1;8276;8269:12;8231:2;8314:31;;8365:18;8354:30;;8351:2;;;8397:1;8394;8387:12;8351:2;8425:64;8481:7;8472:6;8461:9;8457:22;8425:64;;;8415:74;;;;8293:202;8225:280;;;;;;8512:735;;;;;;8683:3;8671:9;8662:7;8658:23;8654:33;8651:2;;;8700:1;8697;8690:12;8651:2;8735:31;;8786:18;8775:30;;8772:2;;;8818:1;8815;8808:12;8772:2;8846:64;8902:7;8893:6;8882:9;8878:22;8846:64;;;8836:74;;;;8714:202;8947:2;8965:50;9007:7;8998:6;8987:9;8983:22;8965:50;;;8955:60;;8926:95;9052:2;9070:53;9115:7;9106:6;9095:9;9091:22;9070:53;;;9060:63;;9031:98;9160:2;9178:53;9223:7;9214:6;9203:9;9199:22;9178:53;;9875:239;;9978:2;9966:9;9957:7;9953:23;9949:32;9946:2;;;9994:1;9991;9984:12;9946:2;10029:1;10046:52;10090:7;10070:9;10046:52;;10121:362;;;10240:2;10228:9;10219:7;10215:23;10211:32;10208:2;;;10256:1;10253;10246:12;10208:2;10291:1;10308:52;10352:7;10332:9;10308:52;;10491:285;;10632:104;10732:3;10724:6;10632:104;;;-1:-1;;10765:4;10756:14;;10625:151;10785:301;;10934:112;11042:3;11034:6;10934:112;;;-1:-1;;11075:4;11066:14;;10927:159;11095:173;;11182:46;11224:3;11216:6;11182:46;;;-1:-1;;11257:4;11248:14;;11175:93;11277:169;;11362:44;11402:3;11394:6;11362:44;;11454:113;11537:24;11555:5;11537:24;;;11532:3;11525:37;11519:48;;;11574:152;11675:45;11695:24;11713:5;11695:24;;;11675:45;;11824:906;;12023:81;12098:5;12023:81;;;12117:113;12223:6;12218:3;12117:113;;;12110:120;;12251:83;12328:5;12251:83;;;12354:7;12382:1;12367:341;12392:6;12389:1;12386:13;12367:341;;;12459:6;12453:13;12480:117;12593:3;12578:13;12480:117;;;12473:124;;12614:87;12694:6;12614:87;;;12604:97;-1:-1;;12414:1;12407:9;12367:341;;;-1:-1;12721:3;;12002:728;-1:-1;;;;;12002:728;12837:938;;13044:85;13123:5;13044:85;;;13142:117;13252:6;13247:3;13142:117;;;13135:124;;13280:87;13361:5;13280:87;;;13387:7;13415:1;13400:353;13425:6;13422:1;13419:13;13400:353;;;13492:6;13486:13;13513:125;13634:3;13619:13;13513:125;;;13506:132;;13655:91;13739:6;13655:91;;;13645:101;-1:-1;;13447:1;13440:9;13400:353;;13814:690;;13959:54;14007:5;13959:54;;;14026:86;14105:6;14100:3;14026:86;;;14019:93;;14133:56;14183:5;14133:56;;;14209:7;14237:1;14222:260;14247:6;14244:1;14241:13;14222:260;;;14314:6;14308:13;14335:63;14394:3;14379:13;14335:63;;;14328:70;;14415:60;14468:6;14415:60;;;14405:70;-1:-1;;14269:1;14262:9;14222:260;;14541:657;;14693:85;14771:6;14766:3;14693:85;;;14686:92;;14799:57;14850:5;14799:57;;;14876:7;14904:1;14889:287;14914:6;14911:1;14908:13;14889:287;;;14975:41;15009:6;15000:7;14975:41;;;15030:61;15087:3;15072:13;15030:61;;;15023:68;;15108:61;15162:6;15108:61;;;15098:71;-1:-1;;14936:1;14929:9;14889:287;;15206:94;15273:21;15288:5;15273:21;;15418:113;15501:24;15519:5;15501:24;;15538:152;15639:45;15659:24;15677:5;15659:24;;;15639:45;;15720:310;;15852:88;15933:6;15928:3;15852:88;;;15845:95;;15952:43;15988:6;15983:3;15976:5;15952:43;;;-1:-1;;16008:16;;15838:192;16038:343;;16148:38;16180:5;16148:38;;;16198:70;16261:6;16256:3;16198:70;;;16191:77;;16273:52;16318:6;16313:3;16306:4;16299:5;16295:16;16273:52;;;16346:29;16368:6;16346:29;;;16337:39;;;;16128:253;-1:-1;;;16128:253;16743:384;;16903:67;16967:2;16962:3;16903:67;;;17003:34;16983:55;;17072:17;17067:2;17058:12;;17051:39;17118:2;17109:12;;16889:238;-1:-1;;16889:238;17136:332;;17296:67;17360:2;17355:3;17296:67;;;17396:34;17376:55;;17459:2;17450:12;;17282:186;-1:-1;;17282:186;17477:400;;17655:85;17737:2;17732:3;17655:85;;;17773:66;17753:87;;17868:2;17859:12;;17641:236;-1:-1;;17641:236;17886:445;;18046:67;18110:2;18105:3;18046:67;;;18146:34;18126:55;;18215:34;18210:2;18201:12;;18194:56;18284:9;18279:2;18270:12;;18263:31;18322:2;18313:12;;18032:299;-1:-1;;18032:299;18340:400;;18500:67;18564:2;18559:3;18500:67;;;18600:34;18580:55;;18669:33;18664:2;18655:12;;18648:55;18731:2;18722:12;;18486:254;-1:-1;;18486:254;18749:384;;18909:67;18973:2;18968:3;18909:67;;;19009:34;18989:55;;19078:17;19073:2;19064:12;;19057:39;19124:2;19115:12;;18895:238;-1:-1;;18895:238;19142:327;;19302:67;19366:2;19361:3;19302:67;;;19402:29;19382:50;;19460:2;19451:12;;19288:181;-1:-1;;19288:181;19478:331;;19638:67;19702:2;19697:3;19638:67;;;19738:33;19718:54;;19800:2;19791:12;;19624:185;-1:-1;;19624:185;19818:329;;19978:67;20042:2;20037:3;19978:67;;;20078:31;20058:52;;20138:2;20129:12;;19964:183;-1:-1;;19964:183;20156:330;;20316:67;20380:2;20375:3;20316:67;;;20416:32;20396:53;;20477:2;20468:12;;20302:184;-1:-1;;20302:184;20495:378;;20655:67;20719:2;20714:3;20655:67;;;20755:34;20735:55;;20824:11;20819:2;20810:12;;20803:33;20864:2;20855:12;;20641:232;-1:-1;;20641:232;20882:390;;21042:67;21106:2;21101:3;21042:67;;;21142:34;21122:55;;21211:23;21206:2;21197:12;;21190:45;21263:2;21254:12;;21028:244;-1:-1;;21028:244;21281:385;;21441:67;21505:2;21500:3;21441:67;;;21541:34;21521:55;;21610:18;21605:2;21596:12;;21589:40;21657:2;21648:12;;21427:239;-1:-1;;21427:239;21675:331;;21835:67;21899:2;21894:3;21835:67;;;21935:33;21915:54;;21997:2;21988:12;;21821:185;-1:-1;;21821:185;22015:387;;22175:67;22239:2;22234:3;22175:67;;;22275:34;22255:55;;22344:20;22339:2;22330:12;;22323:42;22393:2;22384:12;;22161:241;-1:-1;;22161:241;22411:399;;22571:67;22635:2;22630:3;22571:67;;;22671:34;22651:55;;22740:32;22735:2;22726:12;;22719:54;22801:2;22792:12;;22557:253;-1:-1;;22557:253;22819:370;;22979:67;23043:2;23038:3;22979:67;;;23079:34;23059:55;;23148:3;23143:2;23134:12;;23127:25;23180:2;23171:12;;22965:224;-1:-1;;22965:224;23198:380;;23358:67;23422:2;23417:3;23358:67;;;23458:34;23438:55;;23527:13;23522:2;23513:12;;23506:35;23569:2;23560:12;;23344:234;-1:-1;;23344:234;23587:375;;23747:67;23811:2;23806:3;23747:67;;;23847:34;23827:55;;23916:8;23911:2;23902:12;;23895:30;23953:2;23944:12;;23733:229;-1:-1;;23733:229;23971:394;;24131:67;24195:2;24190:3;24131:67;;;24231:34;24211:55;;24300:27;24295:2;24286:12;;24279:49;24356:2;24347:12;;24117:248;-1:-1;;24117:248;24374:376;;24534:67;24598:2;24593:3;24534:67;;;24634:34;24614:55;;24703:9;24698:2;24689:12;;24682:31;24741:2;24732:12;;24520:230;-1:-1;;24520:230;24759:373;;24919:67;24983:2;24978:3;24919:67;;;25019:34;24999:55;;25088:6;25083:2;25074:12;;25067:28;25123:2;25114:12;;24905:227;-1:-1;;24905:227;25141:395;;25301:67;25365:2;25360:3;25301:67;;;25401:34;25381:55;;25470:28;25465:2;25456:12;;25449:50;25527:2;25518:12;;25287:249;-1:-1;;25287:249;25545:387;;25705:67;25769:2;25764:3;25705:67;;;25805:34;25785:55;;25874:20;25869:2;25860:12;;25853:42;25923:2;25914:12;;25691:241;-1:-1;;25691:241;25941:348;;26119:85;26201:2;26196:3;26119:85;;;26237:14;26217:35;;26280:2;26271:12;;26105:184;-1:-1;;26105:184;26298:440;;26458:67;26522:2;26517:3;26458:67;;;26558:34;26538:55;;26627:34;26622:2;26613:12;;26606:56;26696:4;26691:2;26682:12;;26675:26;26729:2;26720:12;;26444:294;-1:-1;;26444:294;26747:384;;26907:67;26971:2;26966:3;26907:67;;;27007:34;26987:55;;27076:17;27071:2;27062:12;;27055:39;27122:2;27113:12;;26893:238;-1:-1;;26893:238;27140:393;;27300:67;27364:2;27359:3;27300:67;;;27400:34;27380:55;;27469:26;27464:2;27455:12;;27448:48;27524:2;27515:12;;27286:247;-1:-1;;27286:247;27626:798;27845:23;;27781:4;27772:14;;;27874:61;27776:3;27845:23;27874:61;;;27801:140;28017:4;28010:5;28006:16;28000:23;28029:57;28080:4;28075:3;28071:14;28057:12;28029:57;;;27951:141;28174:4;28167:5;28163:16;28157:23;28186:61;28241:4;28236:3;28232:14;28218:12;28186:61;;;28102:151;28330:4;28323:5;28319:16;28313:23;28342:61;28397:4;28392:3;28388:14;28374:12;28342:61;;29400:1285;29627:23;;29563:4;29554:14;;;29656:61;29558:3;29627:23;29656:61;;;29583:140;29797:4;29790:5;29786:16;29780:23;29809:61;29864:4;29859:3;29855:14;29841:12;29809:61;;;29733:143;29950:4;29943:5;29939:16;29933:23;29962:61;30017:4;30012:3;30008:14;29994:12;29962:61;;;29886:143;30106:4;30099:5;30095:16;30089:23;30118:61;30173:4;30168:3;30164:14;30150:12;30118:61;;;30039:146;30260:4;30253:5;30249:16;30243:23;30272:63;30329:4;30324:3;30320:14;30306:12;30272:63;;;30195:146;30424:4;30417:5;30413:16;30407:23;30436:63;30493:4;30488:3;30484:14;30470:12;30436:63;;;30351:154;30589:4;30582:5;30578:16;30572:23;30601:63;30658:4;30653:3;30649:14;30635:12;30601:63;;32452:124;32534:36;32564:5;32534:36;;32583:100;32654:23;32671:5;32654:23;;32807:107;32886:22;32902:5;32886:22;;32921:1394;;33292:75;33363:3;33354:6;33292:75;;;33389:2;33384:3;33380:12;33373:19;;33403:75;33474:3;33465:6;33403:75;;;33500:2;33495:3;33491:12;33484:19;;33521:103;33620:3;33611:6;33603;33521:103;;;33514:110;;33635:75;33706:3;33697:6;33635:75;;;33732:2;33727:3;33723:12;33716:19;;33746:75;33817:3;33808:6;33746:75;;;33843:2;33838:3;33834:12;33827:19;;33857:75;33928:3;33919:6;33857:75;;;33954:2;33949:3;33945:12;33938:19;;33968:75;34039:3;34030:6;33968:75;;;34065:2;34060:3;34056:12;34049:19;;34079:75;34150:3;34141:6;34079:75;;;34176:2;34171:3;34167:12;34160:19;;34190:75;34261:3;34252:6;34190:75;;;-1:-1;34287:2;34278:12;;33280:1035;-1:-1;;;;;;;;;;33280:1035;34322:511;;34549:148;34693:3;34549:148;;;34542:155;;34708:75;34779:3;34770:6;34708:75;;;-1:-1;34805:2;34796:12;;34530:303;-1:-1;34530:303;34840:372;;35039:148;35183:3;35039:148;;35219:213;35337:2;35322:18;;35351:71;35326:9;35395:6;35351:71;;35439:324;35585:2;35570:18;;35599:71;35574:9;35643:6;35599:71;;;35681:72;35749:2;35738:9;35734:18;35725:6;35681:72;;35770:580;36020:2;36034:47;;;36005:18;;36095:162;36005:18;36243:6;36095:162;;;36087:170;;36268:72;36336:2;36325:9;36321:18;36312:6;36268:72;;36357:596;36615:2;36629:47;;;36600:18;;36690:170;36600:18;36846:6;36690:170;;36960:636;37214:2;37228:47;;;37199:18;;37289:116;37199:18;37391:6;37383;37289:116;;;37281:124;;37453:9;37447:4;37443:20;37438:2;37427:9;37423:18;37416:48;37478:108;37581:4;37572:6;37478:108;;;37470:116;37185:411;-1:-1;;;;;37185:411;37603:201;37715:2;37700:18;;37729:65;37704:9;37767:6;37729:65;;37811:213;37929:2;37914:18;;37943:71;37918:9;37987:6;37943:71;;38031:539;38229:3;38214:19;;38244:71;38218:9;38288:6;38244:71;;;38326:68;38390:2;38379:9;38375:18;38366:6;38326:68;;;38405:72;38473:2;38462:9;38458:18;38449:6;38405:72;;;38488;38556:2;38545:9;38541:18;38532:6;38488:72;;38577:301;38715:2;38729:47;;;38700:18;;38790:78;38700:18;38854:6;38790:78;;38885:407;39076:2;39090:47;;;39061:18;;39151:131;39061:18;39151:131;;39299:407;39490:2;39504:47;;;39475:18;;39565:131;39475:18;39565:131;;39713:407;39904:2;39918:47;;;39889:18;;39979:131;39889:18;39979:131;;40127:407;40318:2;40332:47;;;40303:18;;40393:131;40303:18;40393:131;;40541:407;40732:2;40746:47;;;40717:18;;40807:131;40717:18;40807:131;;40955:407;41146:2;41160:47;;;41131:18;;41221:131;41131:18;41221:131;;41369:407;41560:2;41574:47;;;41545:18;;41635:131;41545:18;41635:131;;41783:407;41974:2;41988:47;;;41959:18;;42049:131;41959:18;42049:131;;42197:407;42388:2;42402:47;;;42373:18;;42463:131;42373:18;42463:131;;42611:407;42802:2;42816:47;;;42787:18;;42877:131;42787:18;42877:131;;43025:407;43216:2;43230:47;;;43201:18;;43291:131;43201:18;43291:131;;43439:407;43630:2;43644:47;;;43615:18;;43705:131;43615:18;43705:131;;43853:407;44044:2;44058:47;;;44029:18;;44119:131;44029:18;44119:131;;44267:407;44458:2;44472:47;;;44443:18;;44533:131;44443:18;44533:131;;44681:407;44872:2;44886:47;;;44857:18;;44947:131;44857:18;44947:131;;45095:407;45286:2;45300:47;;;45271:18;;45361:131;45271:18;45361:131;;45509:407;45700:2;45714:47;;;45685:18;;45775:131;45685:18;45775:131;;45923:407;46114:2;46128:47;;;46099:18;;46189:131;46099:18;46189:131;;46337:407;46528:2;46542:47;;;46513:18;;46603:131;46513:18;46603:131;;46751:407;46942:2;46956:47;;;46927:18;;47017:131;46927:18;47017:131;;47165:407;47356:2;47370:47;;;47341:18;;47431:131;47341:18;47431:131;;47579:407;47770:2;47784:47;;;47755:18;;47845:131;47755:18;47845:131;;47993:407;48184:2;48198:47;;;48169:18;;48259:131;48169:18;48259:131;;48407:407;48598:2;48612:47;;;48583:18;;48673:131;48583:18;48673:131;;48821:407;49012:2;49026:47;;;48997:18;;49087:131;48997:18;49087:131;;49235:407;49426:2;49440:47;;;49411:18;;49501:131;49411:18;49501:131;;49649:338;49829:3;49814:19;;49844:133;49818:9;49950:6;49844:133;;49994:354;50182:3;50167:19;;50197:141;50171:9;50311:6;50197:141;;50575:408;50739:2;50724:18;;50753:71;50728:9;50797:6;50753:71;;;50872:9;50866:4;50862:20;50857:2;50846:9;50842:18;50835:48;50897:76;50968:4;50959:6;50897:76;;50990:209;51106:2;51091:18;;51120:69;51095:9;51162:6;51120:69;;51206:322;51351:2;51336:18;;51365:70;51340:9;51408:6;51365:70;;51535:316;51677:2;51662:18;;51691:69;51666:9;51733:6;51691:69;;;51771:70;51837:2;51826:9;51822:18;51813:6;51771:70;;51858:178;52009:4;52000:14;;51957:79;52514:164;52644:12;;52615:63;53781:205;53926:19;;;53975:4;53966:14;;53919:67;55236:117;;55309:38;55343:2;55338:3;55334:12;55329:3;55309:38;;55361:91;;55423:24;55441:5;55423:24;;55459:85;55525:13;55518:21;;55501:43;55630:121;-1:-1;;;;;55692:54;;55675:76;55837:96;55909:18;55898:30;;55881:52;55940:81;56011:4;56000:16;;55983:38;56028:106;;56106:23;56123:5;56106:23;;56142:145;56223:6;56218:3;56213;56200:30;-1:-1;56279:1;56261:16;;56254:27;56193:94;56296:268;56361:1;56368:101;56382:6;56379:1;56376:13;56368:101;;;56449:11;;;56443:18;56430:11;;;56423:39;56404:2;56397:10;56368:101;;;56484:6;56481:1;56478:13;56475:2;;;-1:-1;;56549:1;56531:16;;56524:27;56345:219;56572:95;;56636:26;56656:5;56755:89;56819:20;56833:5;56819:20;;56932:97;57020:2;57000:14;-1:-1;;56996:28;;56980:49;57037:94;57111:2;57107:14;;57079:52;57139:117;57208:24;57226:5;57208:24;;;57201:5;57198:35;57188:2;;57247:1;57244;57237:12;57263:111;57329:21;57344:5;57329:21;;57381:117;57450:24;57468:5;57450:24;;57629:115;57697:23;57714:5;57697:23;
Swarm Source
bzzr://c9c4ee1b8720b1046f03191ba2378241876574b2524c7789219aad9afa6c239a
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.