Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Initialize | 14929784 | 1041 days ago | IN | 0 ETH | 0.03522975 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
GraphTokenLockWallet
Compiler Version
v0.7.3+commit.9bfce1f6
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.7.3; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import "./GraphTokenLock.sol"; import "./IGraphTokenLockManager.sol"; /** * @title GraphTokenLockWallet * @notice This contract is built on top of the base GraphTokenLock functionality. * It allows wallet beneficiaries to use the deposited funds to perform specific function calls * on specific contracts. * * The idea is that supporters with locked tokens can participate in the protocol * but disallow any release before the vesting/lock schedule. * The beneficiary can issue authorized function calls to this contract that will * get forwarded to a target contract. A target contract is any of our protocol contracts. * The function calls allowed are queried to the GraphTokenLockManager, this way * the same configuration can be shared for all the created lock wallet contracts. * * NOTE: Contracts used as target must have its function signatures checked to avoid collisions * with any of this contract functions. * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience * the maximum amount of tokens is authorized. */ contract GraphTokenLockWallet is GraphTokenLock { using SafeMath for uint256; using SafeERC20 for IERC20; // -- State -- IGraphTokenLockManager public manager; uint256 public usedAmount; uint256 private constant MAX_UINT256 = 2**256 - 1; // -- Events -- event ManagerUpdated(address indexed _oldManager, address indexed _newManager); event TokenDestinationsApproved(); event TokenDestinationsRevoked(); // Initializer function initialize( address _manager, address _owner, address _beneficiary, address _token, uint256 _managedAmount, uint256 _startTime, uint256 _endTime, uint256 _periods, uint256 _releaseStartTime, uint256 _vestingCliffTime, Revocability _revocable ) external { _initialize( _owner, _beneficiary, _token, _managedAmount, _startTime, _endTime, _periods, _releaseStartTime, _vestingCliffTime, _revocable ); _setManager(_manager); } // -- Admin -- /** * @notice Sets a new manager for this contract * @param _newManager Address of the new manager */ function setManager(address _newManager) external onlyOwner { _setManager(_newManager); } /** * @dev Sets a new manager for this contract * @param _newManager Address of the new manager */ function _setManager(address _newManager) private { require(_newManager != address(0), "Manager cannot be empty"); require(Address.isContract(_newManager), "Manager must be a contract"); address oldManager = address(manager); manager = IGraphTokenLockManager(_newManager); emit ManagerUpdated(oldManager, _newManager); } // -- Beneficiary -- /** * @notice Approves protocol access of the tokens managed by this contract * @dev Approves all token destinations registered in the manager to pull tokens */ function approveProtocol() external onlyBeneficiary { address[] memory dstList = manager.getTokenDestinations(); for (uint256 i = 0; i < dstList.length; i++) { token.safeApprove(dstList[i], MAX_UINT256); } emit TokenDestinationsApproved(); } /** * @notice Revokes protocol access of the tokens managed by this contract * @dev Revokes approval to all token destinations in the manager to pull tokens */ function revokeProtocol() external onlyBeneficiary { address[] memory dstList = manager.getTokenDestinations(); for (uint256 i = 0; i < dstList.length; i++) { token.safeApprove(dstList[i], 0); } emit TokenDestinationsRevoked(); } /** * @notice Forward authorized contract calls to protocol contracts * @dev Fallback function can be called by the beneficiary only if function call is allowed */ fallback() external payable { // Only beneficiary can forward calls require(msg.sender == beneficiary, "Unauthorized caller"); // Function call validation address _target = manager.getAuthFunctionCallTarget(msg.sig); require(_target != address(0), "Unauthorized function"); uint256 oldBalance = currentBalance(); // Call function with data Address.functionCall(_target, msg.data); // Tracked used tokens in the protocol // We do this check after balances were updated by the forwarded call // Check is only enforced for revocable contracts to save some gas if (revocable == Revocability.Enabled) { // Track contract balance change uint256 newBalance = currentBalance(); if (newBalance < oldBalance) { // Outflow uint256 diff = oldBalance.sub(newBalance); usedAmount = usedAmount.add(diff); } else { // Inflow: We can receive profits from the protocol, that could make usedAmount to // underflow. We set it to zero in that case. uint256 diff = newBalance.sub(oldBalance); usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff); } require(usedAmount <= vestedAmount(), "Cannot use more tokens than vested amount"); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.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. */ 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. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 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. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./IERC20.sol"; import "../../math/SafeMath.sol"; import "../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using 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)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // 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. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.3; import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import "./Ownable.sol"; import "./MathUtils.sol"; import "./IGraphTokenLock.sol"; /** * @title GraphTokenLock * @notice Contract that manages an unlocking schedule of tokens. * @dev The contract lock manage a number of tokens deposited into the contract to ensure that * they can only be released under certain time conditions. * * This contract implements a release scheduled based on periods and tokens are released in steps * after each period ends. It can be configured with one period in which case it is like a plain TimeLock. * It also supports revocation to be used for vesting schedules. * * The contract supports receiving extra funds than the managed tokens ones that can be * withdrawn by the beneficiary at any time. * * A releaseStartTime parameter is included to override the default release schedule and * perform the first release on the configured time. After that it will continue with the * default schedule. */ abstract contract GraphTokenLock is Ownable, IGraphTokenLock { using SafeMath for uint256; using SafeERC20 for IERC20; uint256 private constant MIN_PERIOD = 1; // -- State -- IERC20 public token; address public beneficiary; // Configuration // Amount of tokens managed by the contract schedule uint256 public managedAmount; uint256 public startTime; // Start datetime (in unixtimestamp) uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp) uint256 public periods; // Number of vesting/release periods // First release date for tokens (in unixtimestamp) // If set, no tokens will be released before releaseStartTime ignoring // the amount to release each period uint256 public releaseStartTime; // A cliff set a date to which a beneficiary needs to get to vest // all preceding periods uint256 public vestingCliffTime; Revocability public revocable; // Whether to use vesting for locked funds // State bool public isRevoked; bool public isInitialized; uint256 public releasedAmount; // -- Events -- event TokensReleased(address indexed beneficiary, uint256 amount); event TokensWithdrawn(address indexed beneficiary, uint256 amount); event TokensRevoked(address indexed beneficiary, uint256 amount); /** * @dev Only allow calls from the beneficiary of the contract */ modifier onlyBeneficiary() { require(msg.sender == beneficiary, "!auth"); _; } /** * @notice Initializes the contract * @param _owner Address of the contract owner * @param _beneficiary Address of the beneficiary of locked tokens * @param _managedAmount Amount of tokens to be managed by the lock contract * @param _startTime Start time of the release schedule * @param _endTime End time of the release schedule * @param _periods Number of periods between start time and end time * @param _releaseStartTime Override time for when the releases start * @param _vestingCliffTime Override time for when the vesting start * @param _revocable Whether the contract is revocable */ function _initialize( address _owner, address _beneficiary, address _token, uint256 _managedAmount, uint256 _startTime, uint256 _endTime, uint256 _periods, uint256 _releaseStartTime, uint256 _vestingCliffTime, Revocability _revocable ) internal { require(!isInitialized, "Already initialized"); require(_owner != address(0), "Owner cannot be zero"); require(_beneficiary != address(0), "Beneficiary cannot be zero"); require(_token != address(0), "Token cannot be zero"); require(_managedAmount > 0, "Managed tokens cannot be zero"); require(_startTime != 0, "Start time must be set"); require(_startTime < _endTime, "Start time > end time"); require(_periods >= MIN_PERIOD, "Periods cannot be below minimum"); require(_revocable != Revocability.NotSet, "Must set a revocability option"); require(_releaseStartTime < _endTime, "Release start time must be before end time"); require(_vestingCliffTime < _endTime, "Cliff time must be before end time"); isInitialized = true; Ownable.initialize(_owner); beneficiary = _beneficiary; token = IERC20(_token); managedAmount = _managedAmount; startTime = _startTime; endTime = _endTime; periods = _periods; // Optionals releaseStartTime = _releaseStartTime; vestingCliffTime = _vestingCliffTime; revocable = _revocable; } // -- Balances -- /** * @notice Returns the amount of tokens currently held by the contract * @return Tokens held in the contract */ function currentBalance() public override view returns (uint256) { return token.balanceOf(address(this)); } // -- Time & Periods -- /** * @notice Returns the current block timestamp * @return Current block timestamp */ function currentTime() public override view returns (uint256) { return block.timestamp; } /** * @notice Gets duration of contract from start to end in seconds * @return Amount of seconds from contract startTime to endTime */ function duration() public override view returns (uint256) { return endTime.sub(startTime); } /** * @notice Gets time elapsed since the start of the contract * @dev Returns zero if called before conctract starTime * @return Seconds elapsed from contract startTime */ function sinceStartTime() public override view returns (uint256) { uint256 current = currentTime(); if (current <= startTime) { return 0; } return current.sub(startTime); } /** * @notice Returns amount available to be released after each period according to schedule * @return Amount of tokens available after each period */ function amountPerPeriod() public override view returns (uint256) { return managedAmount.div(periods); } /** * @notice Returns the duration of each period in seconds * @return Duration of each period in seconds */ function periodDuration() public override view returns (uint256) { return duration().div(periods); } /** * @notice Gets the current period based on the schedule * @return A number that represents the current period */ function currentPeriod() public override view returns (uint256) { return sinceStartTime().div(periodDuration()).add(MIN_PERIOD); } /** * @notice Gets the number of periods that passed since the first period * @return A number of periods that passed since the schedule started */ function passedPeriods() public override view returns (uint256) { return currentPeriod().sub(MIN_PERIOD); } // -- Locking & Release Schedule -- /** * @notice Gets the currently available token according to the schedule * @dev Implements the step-by-step schedule based on periods for available tokens * @return Amount of tokens available according to the schedule */ function availableAmount() public override view returns (uint256) { uint256 current = currentTime(); // Before contract start no funds are available if (current < startTime) { return 0; } // After contract ended all funds are available if (current > endTime) { return managedAmount; } // Get available amount based on period return passedPeriods().mul(amountPerPeriod()); } /** * @notice Gets the amount of currently vested tokens * @dev Similar to available amount, but is fully vested when contract is non-revocable * @return Amount of tokens already vested */ function vestedAmount() public override view returns (uint256) { // If non-revocable it is fully vested if (revocable == Revocability.Disabled) { return managedAmount; } // Vesting cliff is activated and it has not passed means nothing is vested yet if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) { return 0; } return availableAmount(); } /** * @notice Gets tokens currently available for release * @dev Considers the schedule and takes into account already released tokens * @return Amount of tokens ready to be released */ function releasableAmount() public override view returns (uint256) { // If a release start time is set no tokens are available for release before this date // If not set it follows the default schedule and tokens are available on // the first period passed if (releaseStartTime > 0 && currentTime() < releaseStartTime) { return 0; } // Vesting cliff is activated and it has not passed means nothing is vested yet // so funds cannot be released if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) { return 0; } // A beneficiary can never have more releasable tokens than the contract balance uint256 releasable = availableAmount().sub(releasedAmount); return MathUtils.min(currentBalance(), releasable); } /** * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime * @dev Does not consider schedule but just global amounts tracked * @return Amount of outstanding tokens for the lifetime of the contract */ function totalOutstandingAmount() public override view returns (uint256) { return managedAmount.sub(releasedAmount); } /** * @notice Gets surplus amount in the contract based on outstanding amount to release * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary * @return Amount of tokens considered as surplus */ function surplusAmount() public override view returns (uint256) { uint256 balance = currentBalance(); uint256 outstandingAmount = totalOutstandingAmount(); if (balance > outstandingAmount) { return balance.sub(outstandingAmount); } return 0; } // -- Value Transfer -- /** * @notice Releases tokens based on the configured schedule * @dev All available releasable tokens are transferred to beneficiary */ function release() external override onlyBeneficiary { uint256 amountToRelease = releasableAmount(); require(amountToRelease > 0, "No available releasable amount"); releasedAmount = releasedAmount.add(amountToRelease); token.safeTransfer(beneficiary, amountToRelease); emit TokensReleased(beneficiary, amountToRelease); } /** * @notice Withdraws surplus, unmanaged tokens from the contract * @dev Tokens in the contract over outstanding amount are considered as surplus * @param _amount Amount of tokens to withdraw */ function withdrawSurplus(uint256 _amount) external override onlyBeneficiary { require(_amount > 0, "Amount cannot be zero"); require(surplusAmount() >= _amount, "Amount requested > surplus available"); token.safeTransfer(beneficiary, _amount); emit TokensWithdrawn(beneficiary, _amount); } /** * @notice Revokes a vesting schedule and return the unvested tokens to the owner * @dev Vesting schedule is always calculated based on managed tokens */ function revoke() external override onlyOwner { require(revocable == Revocability.Enabled, "Contract is non-revocable"); require(isRevoked == false, "Already revoked"); uint256 unvestedAmount = managedAmount.sub(vestedAmount()); require(unvestedAmount > 0, "No available unvested amount"); isRevoked = true; token.safeTransfer(owner(), unvestedAmount); emit TokensRevoked(beneficiary, unvestedAmount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.3; pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./IGraphTokenLock.sol"; interface IGraphTokenLockManager { // -- Factory -- function setMasterCopy(address _masterCopy) external; function createTokenLockWallet( address _owner, address _beneficiary, uint256 _managedAmount, uint256 _startTime, uint256 _endTime, uint256 _periods, uint256 _releaseStartTime, uint256 _vestingCliffTime, IGraphTokenLock.Revocability _revocable ) external; // -- Funds Management -- function token() external returns (IERC20); function deposit(uint256 _amount) external; function withdraw(uint256 _amount) external; // -- Allowed Funds Destinations -- function addTokenDestination(address _dst) external; function removeTokenDestination(address _dst) external; function isTokenDestination(address _dst) external view returns (bool); function getTokenDestinations() external view returns (address[] memory); // -- Function Call Authorization -- function setAuthFunctionCall(string calldata _signature, address _target) external; function unsetAuthFunctionCall(string calldata _signature) external; function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external; function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address); function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.3; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The owner account will be passed on initialization of the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function initialize(address owner) internal { _owner = owner; emit OwnershipTransferred(address(0), owner); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(_owner == msg.sender, "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() external virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) external virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.3; library MathUtils { function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.3; pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IGraphTokenLock { enum Revocability { NotSet, Enabled, Disabled } // -- Balances -- function currentBalance() external view returns (uint256); // -- Time & Periods -- function currentTime() external view returns (uint256); function duration() external view returns (uint256); function sinceStartTime() external view returns (uint256); function amountPerPeriod() external view returns (uint256); function periodDuration() external view returns (uint256); function currentPeriod() external view returns (uint256); function passedPeriods() external view returns (uint256); // -- Locking & Release Schedule -- function availableAmount() external view returns (uint256); function vestedAmount() external view returns (uint256); function releasableAmount() external view returns (uint256); function totalOutstandingAmount() external view returns (uint256); function surplusAmount() external view returns (uint256); // -- Value Transfer -- function release() external; function withdrawSurplus(uint256 _amount) external; function revoke() external; }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_oldManager","type":"address"},{"indexed":true,"internalType":"address","name":"_newManager","type":"address"}],"name":"ManagerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[],"name":"TokenDestinationsApproved","type":"event"},{"anonymous":false,"inputs":[],"name":"TokenDestinationsRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensReleased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensWithdrawn","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"amountPerPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"approveProtocol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"availableAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"beneficiary","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"duration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_beneficiary","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_managedAmount","type":"uint256"},{"internalType":"uint256","name":"_startTime","type":"uint256"},{"internalType":"uint256","name":"_endTime","type":"uint256"},{"internalType":"uint256","name":"_periods","type":"uint256"},{"internalType":"uint256","name":"_releaseStartTime","type":"uint256"},{"internalType":"uint256","name":"_vestingCliffTime","type":"uint256"},{"internalType":"enum IGraphTokenLock.Revocability","name":"_revocable","type":"uint8"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isRevoked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"managedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"manager","outputs":[{"internalType":"contract IGraphTokenLockManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"passedPeriods","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periods","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"releasableAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"release","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"releaseStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"releasedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revocable","outputs":[{"internalType":"enum IGraphTokenLock.Revocability","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"revoke","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revokeProtocol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newManager","type":"address"}],"name":"setManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sinceStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"surplusAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalOutstandingAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vestedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vestingCliffTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawSurplus","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5061384c806100206000396000f3fe60806040526004361061021e5760003560e01c806386d00e0211610123578063bc0163c1116100ab578063e8dda6f51161006f578063e8dda6f514610c51578063e97d87d514610c7c578063ebbab99214610ca7578063f2fde38b14610cd2578063fc0c546a14610d235761021f565b8063bc0163c114610a84578063bd896dcb14610aaf578063ce845d1d14610baa578063d0ebdbe714610bd5578063d18e81b314610c265761021f565b806391f7cfb9116100f257806391f7cfb9146109b1578063a4caeb42146109dc578063b0d1818c14610a07578063b470aade14610a42578063b6549f7514610a6d5761021f565b806386d00e02146108f857806386d1a69f14610923578063872a78101461093a5780638da5cb5b146109705761021f565b8063398057a3116101a65780635b940081116101755780635b9400811461084957806360e7994414610874578063715018a61461088b57806378e97925146108a25780637bdf05af146108cd5761021f565b8063398057a31461078757806344b1231f146107b257806345d30a17146107dd578063481c6a75146108085761021f565b80632a627814116101ed5780632a627814146106aa5780632bc9ed02146106c15780633197cbb6146106ee57806338af3eed14610719578063392e53cd1461075a5761021f565b8063029c6c9f146105fe57806306040618146106295780630dff24d5146106545780630fb5a6b41461067f5761021f565b5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146102e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f556e617574686f72697a65642063616c6c65720000000000000000000000000081525060200191505060405180910390fd5b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b815260040180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060206040518083038186803b15801561039a57600080fd5b505afa1580156103ae573d6000803e3d6000fd5b505050506040513d60208110156103c457600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561047a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f556e617574686f72697a65642066756e6374696f6e000000000000000000000081525060200191505060405180910390fd5b6000610484610d64565b90506104d5826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610e2f565b50600160028111156104e357fe5b600960009054906101000a900460ff1660028111156104fe57fe5b14156105fa57600061050e610d64565b90508181101561055057600061052d8284610e7990919063ffffffff16565b905061054481600c54610ec390919063ffffffff16565b600c8190555050610596565b60006105658383610e7990919063ffffffff16565b9050600c5481101561058b5761058681600c54610e7990919063ffffffff16565b61058e565b60005b600c81905550505b61059e610f4b565b600c5411156105f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061371f6029913960400191505060405180910390fd5b505b5050005b34801561060a57600080fd5b50610613610fba565b6040518082815260200191505060405180910390f35b34801561063557600080fd5b5061063e610fd8565b6040518082815260200191505060405180910390f35b34801561066057600080fd5b50610669611013565b6040518082815260200191505060405180910390f35b34801561068b57600080fd5b5061069461105a565b6040518082815260200191505060405180910390f35b3480156106b657600080fd5b506106bf611078565b005b3480156106cd57600080fd5b506106d6611345565b60405180821515815260200191505060405180910390f35b3480156106fa57600080fd5b50610703611358565b6040518082815260200191505060405180910390f35b34801561072557600080fd5b5061072e61135e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561076657600080fd5b5061076f611384565b60405180821515815260200191505060405180910390f35b34801561079357600080fd5b5061079c611397565b6040518082815260200191505060405180910390f35b3480156107be57600080fd5b506107c7610f4b565b6040518082815260200191505060405180910390f35b3480156107e957600080fd5b506107f261139d565b6040518082815260200191505060405180910390f35b34801561081457600080fd5b5061081d6113a3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561085557600080fd5b5061085e6113c9565b6040518082815260200191505060405180910390f35b34801561088057600080fd5b50610889611483565b005b34801561089757600080fd5b506108a0611731565b005b3480156108ae57600080fd5b506108b76118b0565b6040518082815260200191505060405180910390f35b3480156108d957600080fd5b506108e26118b6565b6040518082815260200191505060405180910390f35b34801561090457600080fd5b5061090d6118f2565b6040518082815260200191505060405180910390f35b34801561092f57600080fd5b506109386118f8565b005b34801561094657600080fd5b5061094f611b3a565b6040518082600281111561095f57fe5b815260200191505060405180910390f35b34801561097c57600080fd5b50610985611b4d565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156109bd57600080fd5b506109c6611b76565b6040518082815260200191505060405180910390f35b3480156109e857600080fd5b506109f1611bd4565b6040518082815260200191505060405180910390f35b348015610a1357600080fd5b50610a4060048036036020811015610a2a57600080fd5b8101908080359060200190929190505050611bda565b005b348015610a4e57600080fd5b50610a57611e55565b6040518082815260200191505060405180910390f35b348015610a7957600080fd5b50610a82611e78565b005b348015610a9057600080fd5b50610a996121d5565b6040518082815260200191505060405180910390f35b348015610abb57600080fd5b50610ba86004803603610160811015610ad357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803560ff1690602001909291905050506121f3565b005b348015610bb657600080fd5b50610bbf610d64565b6040518082815260200191505060405180910390f35b348015610be157600080fd5b50610c2460048036036020811015610bf857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061221b565b005b348015610c3257600080fd5b50610c3b6122e8565b6040518082815260200191505060405180910390f35b348015610c5d57600080fd5b50610c666122f0565b6040518082815260200191505060405180910390f35b348015610c8857600080fd5b50610c916122f6565b6040518082815260200191505060405180910390f35b348015610cb357600080fd5b50610cbc6122fc565b6040518082815260200191505060405180910390f35b348015610cde57600080fd5b50610d2160048036036020811015610cf557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061231e565b005b348015610d2f57600080fd5b50610d38612522565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610def57600080fd5b505afa158015610e03573d6000803e3d6000fd5b505050506040513d6020811015610e1957600080fd5b8101908080519060200190929190505050905090565b6060610e7183836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612548565b905092915050565b6000610ebb83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612560565b905092915050565b600080828401905083811015610f41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000600280811115610f5957fe5b600960009054906101000a900460ff166002811115610f7457fe5b1415610f84576003549050610fb7565b6000600854118015610f9e5750600854610f9c6122e8565b105b15610fac5760009050610fb7565b610fb4611b76565b90505b90565b6000610fd360065460035461262090919063ffffffff16565b905090565b600061100e6001611000610fea611e55565b610ff26118b6565b61262090919063ffffffff16565b610ec390919063ffffffff16565b905090565b60008061101e610d64565b9050600061102a6121d5565b905080821115611050576110478183610e7990919063ffffffff16565b92505050611057565b6000925050505b90565b6000611073600454600554610e7990919063ffffffff16565b905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461113b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156111a557600080fd5b505afa1580156111b9573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156111e357600080fd5b810190808051604051939291908464010000000082111561120357600080fd5b8382019150602082018581111561121957600080fd5b825186602082028301116401000000008211171561123657600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561126d578082015181840152602081019050611252565b50505050905001604052505050905060005b81518110156113155761130882828151811061129757fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661266a9092919063ffffffff16565b808060010191505061127f565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b600960019054906101000a900460ff1681565b60055481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960029054906101000a900460ff1681565b60035481565b600a5481565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806007541180156113e457506007546113e26122e8565b105b156113f25760009050611480565b600160028111156113ff57fe5b600960009054906101000a900460ff16600281111561141a57fe5b14801561142957506000600854115b801561143d575060085461143b6122e8565b105b1561144b5760009050611480565b6000611469600a5461145b611b76565b610e7990919063ffffffff16565b905061147c611476610d64565b8261282f565b9150505b90565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611546576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156115b057600080fd5b505afa1580156115c4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156115ee57600080fd5b810190808051604051939291908464010000000082111561160e57600080fd5b8382019150602082018581111561162457600080fd5b825186602082028301116401000000008211171561164157600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561167857808201518184015260208101905061165d565b50505050905001604052505050905060005b8151811015611701576116f48282815181106116a257fe5b60200260200101516000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661266a9092919063ffffffff16565b808060010191505061168a565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146117f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60045481565b6000806118c16122e8565b905060045481116118d65760009150506118ef565b6118eb60045482610e7990919063ffffffff16565b9150505b90565b60085481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146119bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006119c56113c9565b905060008111611a3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e74000081525060200191505060405180910390fd5b611a5281600a54610ec390919063ffffffff16565b600a81905550611ac7600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166128489092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df93179826040518082815260200191505060405180910390a250565b600960009054906101000a900460ff1681565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611b816122e8565b9050600454811015611b97576000915050611bd1565b600554811115611bac57600354915050611bd1565b611bcd611bb7610fba565b611bbf6122fc565b6128ea90919063ffffffff16565b9150505b90565b60065481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c9d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60008111611d13576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f416d6f756e742063616e6e6f74206265207a65726f000000000000000000000081525060200191505060405180910390fd5b80611d1c611013565b1015611d73576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806137696024913960400191505060405180910390fd5b611de2600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166128489092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040518082815260200191505060405180910390a250565b6000611e73600654611e6561105a565b61262090919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611f39576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60016002811115611f4657fe5b600960009054906101000a900460ff166002811115611f6157fe5b14611fd4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f436f6e7472616374206973206e6f6e2d7265766f6361626c650000000000000081525060200191505060405180910390fd5b60001515600960019054906101000a900460ff1615151461205d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f416c7265616479207265766f6b6564000000000000000000000000000000000081525060200191505060405180910390fd5b600061207b61206a610f4b565b600354610e7990919063ffffffff16565b9050600081116120f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f20617661696c61626c6520756e76657374656420616d6f756e740000000081525060200191505060405180910390fd5b6001600960016101000a81548160ff021916908315150217905550612162612119611b4d565b82600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166128489092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040518082815260200191505060405180910390a250565b60006121ee600a54600354610e7990919063ffffffff16565b905090565b6122058a8a8a8a8a8a8a8a8a8a612970565b61220e8b612ff1565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146122dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6122e581612ff1565b50565b600042905090565b600c5481565b60075481565b6000612319600161230b610fd8565b610e7990919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612465576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806136d36026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b606061255784846000856131d5565b90509392505050565b600083831115829061260d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156125d25780820151818401526020810190506125b7565b50505050905090810190601f1680156125ff5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600061266283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061337e565b905092915050565b6000811480612738575060008373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b1580156126fb57600080fd5b505afa15801561270f573d6000803e3d6000fd5b505050506040513d602081101561272557600080fd5b8101908080519060200190929190505050145b61278d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806137e16036913960400191505060405180910390fd5b61282a8363095ea7b360e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613444565b505050565b600081831061283e5781612840565b825b905092915050565b6128e58363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613444565b505050565b6000808314156128fd576000905061296a565b600082840290508284828161290e57fe5b0414612965576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806137486021913960400191505060405180910390fd5b809150505b92915050565b600960029054906101000a900460ff16156129f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f416c726561647920696e697469616c697a65640000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415612a96576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4f776e65722063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415612b39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f42656e65666963696172792063616e6e6f74206265207a65726f00000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415612bdc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f546f6b656e2063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b60008711612c52576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f00000081525060200191505060405180910390fd5b6000861415612cc9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f53746172742074696d65206d757374206265207365740000000000000000000081525060200191505060405180910390fd5b848610612d3e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f53746172742074696d65203e20656e642074696d65000000000000000000000081525060200191505060405180910390fd5b6001841015612db5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d0081525060200191505060405180910390fd5b60006002811115612dc257fe5b816002811115612dce57fe5b1415612e42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4d757374207365742061207265766f636162696c697479206f7074696f6e000081525060200191505060405180910390fd5b848310612e9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a81526020018061378d602a913960400191505060405180910390fd5b848210612ef2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806136b16022913960400191505060405180910390fd5b6001600960026101000a81548160ff021916908315150217905550612f168a613533565b88600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600381905550856004819055508460058190555083600681905550826007819055508160088190555080600960006101000a81548160ff02191690836002811115612fe057fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613094576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f4d616e616765722063616e6e6f7420626520656d70747900000000000000000081525060200191505060405180910390fd5b61309d816135d1565b61310f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4d616e61676572206d757374206265206120636f6e747261637400000000000081525060200191505060405180910390fd5b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b606082471015613230576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806136f96026913960400191505060405180910390fd5b613239856135d1565b6132ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b602083106132fb57805182526020820191506020810190506020830392506132d8565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811461335d576040519150601f19603f3d011682016040523d82523d6000602084013e613362565b606091505b50915091506133728282866135e4565b92505050949350505050565b6000808311829061342a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156133ef5780820151818401526020810190506133d4565b50505050905090810190601f16801561341c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161343657fe5b049050809150509392505050565b60606134a6826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125489092919063ffffffff16565b905060008151111561352e578080602001905160208110156134c757600080fd5b810190808051906020019092919050505061352d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001806137b7602a913960400191505060405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b606083156135f4578290506136a9565b6000835111156136075782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561366e578082015181840152602081019050613653565b50505050905090810190601f16801561369b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b939250505056fe436c6966662074696d65206d757374206265206265666f726520656e642074696d654f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c43616e6e6f7420757365206d6f726520746f6b656e73207468616e2076657374656420616d6f756e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77416d6f756e7420726571756573746564203e20737572706c757320617661696c61626c6552656c656173652073746172742074696d65206d757374206265206265666f726520656e642074696d655361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220568a2fe9dc70706737374723ca77697bf133d14dda9ad40e2b8f6f167a7ec56264736f6c63430007030033
Deployed Bytecode
0x60806040526004361061021e5760003560e01c806386d00e0211610123578063bc0163c1116100ab578063e8dda6f51161006f578063e8dda6f514610c51578063e97d87d514610c7c578063ebbab99214610ca7578063f2fde38b14610cd2578063fc0c546a14610d235761021f565b8063bc0163c114610a84578063bd896dcb14610aaf578063ce845d1d14610baa578063d0ebdbe714610bd5578063d18e81b314610c265761021f565b806391f7cfb9116100f257806391f7cfb9146109b1578063a4caeb42146109dc578063b0d1818c14610a07578063b470aade14610a42578063b6549f7514610a6d5761021f565b806386d00e02146108f857806386d1a69f14610923578063872a78101461093a5780638da5cb5b146109705761021f565b8063398057a3116101a65780635b940081116101755780635b9400811461084957806360e7994414610874578063715018a61461088b57806378e97925146108a25780637bdf05af146108cd5761021f565b8063398057a31461078757806344b1231f146107b257806345d30a17146107dd578063481c6a75146108085761021f565b80632a627814116101ed5780632a627814146106aa5780632bc9ed02146106c15780633197cbb6146106ee57806338af3eed14610719578063392e53cd1461075a5761021f565b8063029c6c9f146105fe57806306040618146106295780630dff24d5146106545780630fb5a6b41461067f5761021f565b5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146102e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f556e617574686f72697a65642063616c6c65720000000000000000000000000081525060200191505060405180910390fd5b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b815260040180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060206040518083038186803b15801561039a57600080fd5b505afa1580156103ae573d6000803e3d6000fd5b505050506040513d60208110156103c457600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561047a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f556e617574686f72697a65642066756e6374696f6e000000000000000000000081525060200191505060405180910390fd5b6000610484610d64565b90506104d5826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610e2f565b50600160028111156104e357fe5b600960009054906101000a900460ff1660028111156104fe57fe5b14156105fa57600061050e610d64565b90508181101561055057600061052d8284610e7990919063ffffffff16565b905061054481600c54610ec390919063ffffffff16565b600c8190555050610596565b60006105658383610e7990919063ffffffff16565b9050600c5481101561058b5761058681600c54610e7990919063ffffffff16565b61058e565b60005b600c81905550505b61059e610f4b565b600c5411156105f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061371f6029913960400191505060405180910390fd5b505b5050005b34801561060a57600080fd5b50610613610fba565b6040518082815260200191505060405180910390f35b34801561063557600080fd5b5061063e610fd8565b6040518082815260200191505060405180910390f35b34801561066057600080fd5b50610669611013565b6040518082815260200191505060405180910390f35b34801561068b57600080fd5b5061069461105a565b6040518082815260200191505060405180910390f35b3480156106b657600080fd5b506106bf611078565b005b3480156106cd57600080fd5b506106d6611345565b60405180821515815260200191505060405180910390f35b3480156106fa57600080fd5b50610703611358565b6040518082815260200191505060405180910390f35b34801561072557600080fd5b5061072e61135e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561076657600080fd5b5061076f611384565b60405180821515815260200191505060405180910390f35b34801561079357600080fd5b5061079c611397565b6040518082815260200191505060405180910390f35b3480156107be57600080fd5b506107c7610f4b565b6040518082815260200191505060405180910390f35b3480156107e957600080fd5b506107f261139d565b6040518082815260200191505060405180910390f35b34801561081457600080fd5b5061081d6113a3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561085557600080fd5b5061085e6113c9565b6040518082815260200191505060405180910390f35b34801561088057600080fd5b50610889611483565b005b34801561089757600080fd5b506108a0611731565b005b3480156108ae57600080fd5b506108b76118b0565b6040518082815260200191505060405180910390f35b3480156108d957600080fd5b506108e26118b6565b6040518082815260200191505060405180910390f35b34801561090457600080fd5b5061090d6118f2565b6040518082815260200191505060405180910390f35b34801561092f57600080fd5b506109386118f8565b005b34801561094657600080fd5b5061094f611b3a565b6040518082600281111561095f57fe5b815260200191505060405180910390f35b34801561097c57600080fd5b50610985611b4d565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156109bd57600080fd5b506109c6611b76565b6040518082815260200191505060405180910390f35b3480156109e857600080fd5b506109f1611bd4565b6040518082815260200191505060405180910390f35b348015610a1357600080fd5b50610a4060048036036020811015610a2a57600080fd5b8101908080359060200190929190505050611bda565b005b348015610a4e57600080fd5b50610a57611e55565b6040518082815260200191505060405180910390f35b348015610a7957600080fd5b50610a82611e78565b005b348015610a9057600080fd5b50610a996121d5565b6040518082815260200191505060405180910390f35b348015610abb57600080fd5b50610ba86004803603610160811015610ad357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803560ff1690602001909291905050506121f3565b005b348015610bb657600080fd5b50610bbf610d64565b6040518082815260200191505060405180910390f35b348015610be157600080fd5b50610c2460048036036020811015610bf857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061221b565b005b348015610c3257600080fd5b50610c3b6122e8565b6040518082815260200191505060405180910390f35b348015610c5d57600080fd5b50610c666122f0565b6040518082815260200191505060405180910390f35b348015610c8857600080fd5b50610c916122f6565b6040518082815260200191505060405180910390f35b348015610cb357600080fd5b50610cbc6122fc565b6040518082815260200191505060405180910390f35b348015610cde57600080fd5b50610d2160048036036020811015610cf557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061231e565b005b348015610d2f57600080fd5b50610d38612522565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610def57600080fd5b505afa158015610e03573d6000803e3d6000fd5b505050506040513d6020811015610e1957600080fd5b8101908080519060200190929190505050905090565b6060610e7183836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612548565b905092915050565b6000610ebb83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612560565b905092915050565b600080828401905083811015610f41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000600280811115610f5957fe5b600960009054906101000a900460ff166002811115610f7457fe5b1415610f84576003549050610fb7565b6000600854118015610f9e5750600854610f9c6122e8565b105b15610fac5760009050610fb7565b610fb4611b76565b90505b90565b6000610fd360065460035461262090919063ffffffff16565b905090565b600061100e6001611000610fea611e55565b610ff26118b6565b61262090919063ffffffff16565b610ec390919063ffffffff16565b905090565b60008061101e610d64565b9050600061102a6121d5565b905080821115611050576110478183610e7990919063ffffffff16565b92505050611057565b6000925050505b90565b6000611073600454600554610e7990919063ffffffff16565b905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461113b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156111a557600080fd5b505afa1580156111b9573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156111e357600080fd5b810190808051604051939291908464010000000082111561120357600080fd5b8382019150602082018581111561121957600080fd5b825186602082028301116401000000008211171561123657600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561126d578082015181840152602081019050611252565b50505050905001604052505050905060005b81518110156113155761130882828151811061129757fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661266a9092919063ffffffff16565b808060010191505061127f565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b600960019054906101000a900460ff1681565b60055481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960029054906101000a900460ff1681565b60035481565b600a5481565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806007541180156113e457506007546113e26122e8565b105b156113f25760009050611480565b600160028111156113ff57fe5b600960009054906101000a900460ff16600281111561141a57fe5b14801561142957506000600854115b801561143d575060085461143b6122e8565b105b1561144b5760009050611480565b6000611469600a5461145b611b76565b610e7990919063ffffffff16565b905061147c611476610d64565b8261282f565b9150505b90565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611546576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156115b057600080fd5b505afa1580156115c4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156115ee57600080fd5b810190808051604051939291908464010000000082111561160e57600080fd5b8382019150602082018581111561162457600080fd5b825186602082028301116401000000008211171561164157600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561167857808201518184015260208101905061165d565b50505050905001604052505050905060005b8151811015611701576116f48282815181106116a257fe5b60200260200101516000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661266a9092919063ffffffff16565b808060010191505061168a565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146117f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60045481565b6000806118c16122e8565b905060045481116118d65760009150506118ef565b6118eb60045482610e7990919063ffffffff16565b9150505b90565b60085481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146119bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006119c56113c9565b905060008111611a3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e74000081525060200191505060405180910390fd5b611a5281600a54610ec390919063ffffffff16565b600a81905550611ac7600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166128489092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df93179826040518082815260200191505060405180910390a250565b600960009054906101000a900460ff1681565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611b816122e8565b9050600454811015611b97576000915050611bd1565b600554811115611bac57600354915050611bd1565b611bcd611bb7610fba565b611bbf6122fc565b6128ea90919063ffffffff16565b9150505b90565b60065481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c9d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60008111611d13576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f416d6f756e742063616e6e6f74206265207a65726f000000000000000000000081525060200191505060405180910390fd5b80611d1c611013565b1015611d73576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806137696024913960400191505060405180910390fd5b611de2600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166128489092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040518082815260200191505060405180910390a250565b6000611e73600654611e6561105a565b61262090919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611f39576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60016002811115611f4657fe5b600960009054906101000a900460ff166002811115611f6157fe5b14611fd4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f436f6e7472616374206973206e6f6e2d7265766f6361626c650000000000000081525060200191505060405180910390fd5b60001515600960019054906101000a900460ff1615151461205d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f416c7265616479207265766f6b6564000000000000000000000000000000000081525060200191505060405180910390fd5b600061207b61206a610f4b565b600354610e7990919063ffffffff16565b9050600081116120f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f20617661696c61626c6520756e76657374656420616d6f756e740000000081525060200191505060405180910390fd5b6001600960016101000a81548160ff021916908315150217905550612162612119611b4d565b82600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166128489092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040518082815260200191505060405180910390a250565b60006121ee600a54600354610e7990919063ffffffff16565b905090565b6122058a8a8a8a8a8a8a8a8a8a612970565b61220e8b612ff1565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146122dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6122e581612ff1565b50565b600042905090565b600c5481565b60075481565b6000612319600161230b610fd8565b610e7990919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612465576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806136d36026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b606061255784846000856131d5565b90509392505050565b600083831115829061260d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156125d25780820151818401526020810190506125b7565b50505050905090810190601f1680156125ff5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600061266283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061337e565b905092915050565b6000811480612738575060008373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b1580156126fb57600080fd5b505afa15801561270f573d6000803e3d6000fd5b505050506040513d602081101561272557600080fd5b8101908080519060200190929190505050145b61278d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806137e16036913960400191505060405180910390fd5b61282a8363095ea7b360e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613444565b505050565b600081831061283e5781612840565b825b905092915050565b6128e58363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613444565b505050565b6000808314156128fd576000905061296a565b600082840290508284828161290e57fe5b0414612965576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806137486021913960400191505060405180910390fd5b809150505b92915050565b600960029054906101000a900460ff16156129f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f416c726561647920696e697469616c697a65640000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415612a96576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4f776e65722063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415612b39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f42656e65666963696172792063616e6e6f74206265207a65726f00000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415612bdc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f546f6b656e2063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b60008711612c52576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f00000081525060200191505060405180910390fd5b6000861415612cc9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f53746172742074696d65206d757374206265207365740000000000000000000081525060200191505060405180910390fd5b848610612d3e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f53746172742074696d65203e20656e642074696d65000000000000000000000081525060200191505060405180910390fd5b6001841015612db5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d0081525060200191505060405180910390fd5b60006002811115612dc257fe5b816002811115612dce57fe5b1415612e42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4d757374207365742061207265766f636162696c697479206f7074696f6e000081525060200191505060405180910390fd5b848310612e9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a81526020018061378d602a913960400191505060405180910390fd5b848210612ef2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806136b16022913960400191505060405180910390fd5b6001600960026101000a81548160ff021916908315150217905550612f168a613533565b88600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600381905550856004819055508460058190555083600681905550826007819055508160088190555080600960006101000a81548160ff02191690836002811115612fe057fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613094576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f4d616e616765722063616e6e6f7420626520656d70747900000000000000000081525060200191505060405180910390fd5b61309d816135d1565b61310f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4d616e61676572206d757374206265206120636f6e747261637400000000000081525060200191505060405180910390fd5b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b606082471015613230576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806136f96026913960400191505060405180910390fd5b613239856135d1565b6132ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b602083106132fb57805182526020820191506020810190506020830392506132d8565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811461335d576040519150601f19603f3d011682016040523d82523d6000602084013e613362565b606091505b50915091506133728282866135e4565b92505050949350505050565b6000808311829061342a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156133ef5780820151818401526020810190506133d4565b50505050905090810190601f16801561341c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161343657fe5b049050809150509392505050565b60606134a6826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125489092919063ffffffff16565b905060008151111561352e578080602001905160208110156134c757600080fd5b810190808051906020019092919050505061352d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001806137b7602a913960400191505060405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b606083156135f4578290506136a9565b6000835111156136075782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561366e578082015181840152602081019050613653565b50505050905090810190601f16801561369b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b939250505056fe436c6966662074696d65206d757374206265206265666f726520656e642074696d654f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c43616e6e6f7420757365206d6f726520746f6b656e73207468616e2076657374656420616d6f756e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77416d6f756e7420726571756573746564203e20737572706c757320617661696c61626c6552656c656173652073746172742074696d65206d757374206265206265666f726520656e642074696d655361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220568a2fe9dc70706737374723ca77697bf133d14dda9ad40e2b8f6f167a7ec56264736f6c63430007030033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 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.