Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Ops
Compiler Version
v0.8.14+commit.80d49f37
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.14; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import {Gelatofied} from "./vendor/gelato/Gelatofied.sol"; import {GelatoBytes} from "./vendor/gelato/GelatoBytes.sol"; import {Proxied} from "./vendor/proxy/EIP173/Proxied.sol"; import {OpsStorage} from "./OpsStorage.sol"; import {LibDataTypes} from "./libraries/LibDataTypes.sol"; import {LibEvents} from "./libraries/LibEvents.sol"; import {LibLegacyTask} from "./libraries/LibLegacyTask.sol"; import {LibTaskId} from "./libraries/LibTaskId.sol"; import {LibTaskModule} from "./libraries/LibTaskModule.sol"; import { ITaskTreasuryUpgradable } from "./interfaces/ITaskTreasuryUpgradable.sol"; import {IOps} from "./interfaces/IOps.sol"; /** * @notice Ops enables everyone to have Gelato monitor and execute transactions. * @notice ExecAddress refers to the contract that has the function which Gelato will call. * @notice Modules allow users to customise conditions and specifications when creating a task. */ contract Ops is Gelatofied, Proxied, OpsStorage, IOps { using GelatoBytes for bytes; using EnumerableSet for EnumerableSet.Bytes32Set; // solhint-disable const-name-snakecase string public constant version = "5"; ITaskTreasuryUpgradable public immutable override taskTreasury; constructor(address payable _gelato, ITaskTreasuryUpgradable _taskTreasury) Gelatofied(_gelato) { taskTreasury = _taskTreasury; } // prettier-ignore fallback(bytes calldata _callData) external returns(bytes memory returnData){ returnData = _handleLegacyTaskCreation(_callData); } ///@inheritdoc IOps function createTask( address _execAddress, bytes calldata _execDataOrSelector, LibDataTypes.ModuleData calldata _moduleData, address _feeToken ) external override returns (bytes32 taskId) { address taskCreator; (taskCreator, _execAddress) = LibTaskModule.preCreateTask( msg.sender, _execAddress, taskModuleAddresses ); taskId = _createTask( taskCreator, _execAddress, _execDataOrSelector, _moduleData, _feeToken ); } ///@inheritdoc IOps function cancelTask(bytes32 _taskId) external { address _taskCreator = LibTaskModule.preCancelTask( _taskId, msg.sender, taskModuleAddresses ); _cancelTask(_taskCreator, _taskId); } ///@inheritdoc IOps function exec( address _taskCreator, address _execAddress, bytes memory _execData, LibDataTypes.ModuleData calldata _moduleData, uint256 _txFee, address _feeToken, bool _useTaskTreasuryFunds, bool _revertOnFailure ) external onlyGelato { bytes32 taskId = LibTaskId.getTaskId( _taskCreator, _execAddress, _execData.memorySliceSelector(), _moduleData, _useTaskTreasuryFunds ? address(0) : _feeToken ); _exec( taskId, _taskCreator, _execAddress, _execData, _moduleData.modules, _txFee, _feeToken, _useTaskTreasuryFunds, _revertOnFailure ); } ///@inheritdoc IOps function setModule( LibDataTypes.Module[] calldata _modules, address[] calldata _moduleAddresses ) external onlyProxyAdmin { uint256 length = _modules.length; for (uint256 i; i < length; i++) { taskModuleAddresses[_modules[i]] = _moduleAddresses[i]; } } ///@inheritdoc IOps function getFeeDetails() external view returns (uint256, address) { return (fee, feeToken); } ///@inheritdoc IOps function getTaskIdsByUser(address _taskCreator) external view returns (bytes32[] memory) { bytes32[] memory taskIds = _createdTasks[_taskCreator].values(); return taskIds; } ///@inheritdoc IOps function getTaskId( address taskCreator, address execAddress, bytes4 execSelector, LibDataTypes.ModuleData memory moduleData, address feeToken ) external pure returns (bytes32 taskId) { taskId = LibTaskId.getTaskId( taskCreator, execAddress, execSelector, moduleData, feeToken ); } ///@inheritdoc IOps function getTaskId( address taskCreator, address execAddress, bytes4 execSelector, bool useTaskTreasuryFunds, address feeToken, bytes32 resolverHash ) external pure returns (bytes32 taskId) { taskId = LibTaskId.getLegacyTaskId( taskCreator, execAddress, execSelector, useTaskTreasuryFunds, feeToken, resolverHash ); } function _createTask( address _taskCreator, address _execAddress, bytes memory _execDataOrSelector, LibDataTypes.ModuleData memory _moduleData, address _feeToken ) private returns (bytes32 taskId) { taskId = LibTaskId.getTaskId( _taskCreator, _execAddress, _execDataOrSelector.memorySliceSelector(), _moduleData, _feeToken ); require( !_createdTasks[_taskCreator].contains(taskId), "Ops.createTask: Duplicate task" ); LibTaskModule.onCreateTask( taskId, _taskCreator, _execAddress, _execDataOrSelector, _moduleData, taskModuleAddresses ); _createdTasks[_taskCreator].add(taskId); emit LibEvents.TaskCreated( _taskCreator, _execAddress, _execDataOrSelector, _moduleData, _feeToken, taskId ); } function _cancelTask(address _taskCreator, bytes32 _taskId) private { require( _createdTasks[_taskCreator].contains(_taskId), "Ops.cancelTask: Task not found" ); _createdTasks[_taskCreator].remove(_taskId); emit LibEvents.TaskCancelled(_taskId, _taskCreator); } // solhint-disable function-max-lines function _exec( bytes32 _taskId, address _taskCreator, address _execAddress, bytes memory _execData, LibDataTypes.Module[] memory _modules, uint256 _txFee, address _feeToken, bool _useTaskTreasuryFunds, bool _revertOnFailure ) private { require( _createdTasks[_taskCreator].contains(_taskId), "Ops.exec: Task not found" ); if (!_useTaskTreasuryFunds) { fee = _txFee; feeToken = _feeToken; } bool success = LibTaskModule.onExecTask( _taskId, _taskCreator, _execAddress, _execData, _modules, _revertOnFailure, taskModuleAddresses ); if (_useTaskTreasuryFunds) { taskTreasury.useFunds(_taskCreator, _feeToken, _txFee); } else { delete fee; delete feeToken; } emit LibEvents.ExecSuccess( _txFee, _feeToken, _execAddress, _execData, _taskId, success ); } function _handleLegacyTaskCreation(bytes calldata _callData) private returns (bytes memory returnData) { bytes4 funcSig = _callData.calldataSliceSelector(); ( address execAddress, bytes memory execData, LibDataTypes.ModuleData memory moduleData, address feeToken_ ) = LibLegacyTask.getCreateTaskArg(funcSig, _callData); bytes32 taskId = _createTask( msg.sender, execAddress, execData, moduleData, feeToken_ ); returnData = abi.encodePacked(taskId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, 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 `from` to `to` 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 from, address to, 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 // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.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 Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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 * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly { result := store } return result; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.12; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import {LibDataTypes} from "./libraries/LibDataTypes.sol"; /** * @notice Storage layout of Ops smart contract. */ // solhint-disable max-states-count abstract contract OpsStorage { mapping(bytes32 => address) public taskCreator; ///@dev Deprecated mapping(bytes32 => address) public execAddresses; ///@dev Deprecated mapping(address => EnumerableSet.Bytes32Set) internal _createdTasks; uint256 public fee; address public feeToken; ///@dev Appended State mapping(bytes32 => LibDataTypes.Time) public timedTask; mapping(LibDataTypes.Module => address) public taskModuleAddresses; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; import {GelatoBytes} from "../vendor/gelato/GelatoBytes.sol"; // solhint-disable private-vars-leading-underscore // solhint-disable func-visibility function _call( address _add, bytes memory _data, uint256 _value, bool _revertOnFailure, string memory _tracingInfo ) returns (bool success, bytes memory returnData) { (success, returnData) = _add.call{value: _value}(_data); if (!success && _revertOnFailure) GelatoBytes.revertWithError(returnData, _tracingInfo); } function _delegateCall( address _add, bytes memory _data, string memory _tracingInfo ) returns (bool success, bytes memory returnData) { (success, returnData) = _add.delegatecall(_data); if (!success) GelatoBytes.revertWithError(returnData, _tracingInfo); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.12; import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; address constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; // solhint-disable private-vars-leading-underscore // solhint-disable func-visibility function _transfer( address payable _to, address _paymentToken, uint256 _amount ) { if (_paymentToken == ETH) { (bool success, ) = _to.call{value: _amount}(""); require(success, "_transfer: ETH transfer failed"); } else { SafeERC20.safeTransfer(IERC20(_paymentToken), _to, _amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {ITaskTreasuryUpgradable} from "./ITaskTreasuryUpgradable.sol"; /** * @notice Legacy Ops interface with individual create task function for each task type. * @notice These function signatures are still supported via fallback. {See Ops.sol-fallback} */ interface ILegacyOps { function createTask( address _execAddress, bytes4 _execSelector, address _resolverAddress, bytes calldata _resolverData ) external returns (bytes32 taskId); function createTaskNoPrepayment( address _execAddress, bytes4 _execSelector, address _resolverAddress, bytes calldata _resolverData, address _feeToken ) external returns (bytes32 taskId); function createTimedTask( uint128 _startTime, uint128 _interval, address _execAddress, bytes4 _execSelector, address _resolverAddress, bytes calldata _resolverData, address _feeToken, bool _useTreasury ) external returns (bytes32 taskId); function cancelTask(bytes32 _taskId) external; function exec( uint256 _txFee, address _feeToken, address _taskCreator, bool _useTaskTreasuryFunds, bool _revertOnFailure, bytes32 _resolverHash, address _execAddress, bytes calldata _execData ) external; function getFeeDetails() external view returns (uint256, address); function getTaskIdsByUser(address _taskCreator) external view returns (bytes32[] memory); function taskTreasury() external view returns (ITaskTreasuryUpgradable); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {LibDataTypes} from "../libraries/LibDataTypes.sol"; import {ITaskTreasuryUpgradable} from "./ITaskTreasuryUpgradable.sol"; // solhint-disable max-line-length interface IOps { /** * @notice Initiates a task with conditions which Gelato will monitor and execute when conditions are met. * * @param execAddress Address of contract that should be called by Gelato. * @param execData Execution data to be called with / function selector if execution data is yet to be determined. * @param moduleData Conditional modules that will be used. {See LibDataTypes-ModuleData} * @param feeToken Address of token to be used as payment. Use address(0) if TaskTreasury is being used, 0xeeeeee... for ETH or native tokens. * * @return taskId Unique hash of the task created. */ function createTask( address execAddress, bytes calldata execData, LibDataTypes.ModuleData calldata moduleData, address feeToken ) external returns (bytes32 taskId); /** * @notice Terminates a task that was created and Gelato can no longer execute it. * * @param taskId Unique hash of the task that is being cancelled. {See LibTaskId-getTaskId} */ function cancelTask(bytes32 taskId) external; /** * @notice Execution API called by Gelato. * * @param taskCreator The address which created the task. * @param execAddress Address of contract that should be called by Gelato. * @param execData Execution data to be called with / function selector if execution data is yet to be determined. * @param moduleData Conditional modules that will be used. {See LibDataTypes-ModuleData} * @param txFee Fee paid to Gelato for execution, deducted on the TaskTreasury or transfered to Gelato. * @param feeToken Token used to pay for the execution. ETH = 0xeeeeee... * @param useTaskTreasuryFunds If taskCreator's balance on TaskTreasury should pay for the tx. * @param revertOnFailure To revert or not if call to execAddress fails. (Used for off-chain simulations) */ function exec( address taskCreator, address execAddress, bytes memory execData, LibDataTypes.ModuleData calldata moduleData, uint256 txFee, address feeToken, bool useTaskTreasuryFunds, bool revertOnFailure ) external; /** * @notice Sets the address of task modules. Only callable by proxy admin. * * @param modules List of modules to be set * @param moduleAddresses List of addresses for respective modules. */ function setModule( LibDataTypes.Module[] calldata modules, address[] calldata moduleAddresses ) external; /** * @notice Helper function to query fee and feeToken to be used for payment. (For executions which pays itself) * * @return uint256 Fee amount to be paid. * @return address Token to be paid. (Determined and passed by taskCreator during createTask) */ function getFeeDetails() external view returns (uint256, address); /** * @notice Helper func to query all open tasks by a task creator. * * @param taskCreator Address of task creator to query. * * @return bytes32[] List of taskIds created. */ function getTaskIdsByUser(address taskCreator) external view returns (bytes32[] memory); /** * @notice Helper function to compute task id with module arguments * * @param taskCreator The address which created the task. * @param execAddress Address of contract that will be called by Gelato. * @param execSelector Signature of the function which will be called by Gelato. * @param moduleData Conditional modules that will be used. {See LibDataTypes-ModuleData} * @param feeToken Address of token to be used as payment. Use address(0) if TaskTreasury is being used, 0xeeeeee... for ETH or native tokens. */ function getTaskId( address taskCreator, address execAddress, bytes4 execSelector, LibDataTypes.ModuleData memory moduleData, address feeToken ) external pure returns (bytes32 taskId); /** * @notice (Legacy) Helper function to compute task id. * * @param taskCreator The address which created the task. * @param execAddress Address of contract that will be called by Gelato. * @param execSelector Signature of the function which will be called by Gelato. * @param useTaskTreasuryFunds Wether fee should be deducted from TaskTreasury. * @param feeToken Address of token to be used as payment. Use address(0) if TaskTreasury is being used, 0xeeeeee... for ETH or native tokens. * @param resolverHash Hash of resolverAddress and resolverData {See getResolverHash} */ function getTaskId( address taskCreator, address execAddress, bytes4 execSelector, bool useTaskTreasuryFunds, address feeToken, bytes32 resolverHash ) external pure returns (bytes32); /** * @notice TaskTreasury contract where user deposit funds to be used for fee payments. * * @return ITaskTreasuryUpgradable TaskTreasury contract interface */ function taskTreasury() external view returns (ITaskTreasuryUpgradable); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; // solhint-disable max-line-length interface ITaskModule { /** * @notice Called before generating taskId. * @dev Modules can override execAddress or taskCreator. {See ProxyModule-preCreateTask} * * @param taskCreator The address which created the task. * @param execAddress Address of contract that should be called. * * @return address Overriden or original taskCreator. * @return address Overriden or original execAddress. */ function preCreateTask(address taskCreator, address execAddress) external returns (address, address); /** * @notice Initiates task module whenever `createTask` is being called. * * @param taskId Unique hash of the task created. * @param taskCreator The address which created the task. * @param execAddress Address of contract that should be called. * @param execData Execution data to be called with / function selector if execution data is yet to be determined. * @param initModuleArg Encoded arguments for module if any. */ function onCreateTask( bytes32 taskId, address taskCreator, address execAddress, bytes calldata execData, bytes calldata initModuleArg ) external; /** * @notice Called before taskId is removed from _createdTasks[]. * @dev Modules can override taskCreator. * * @param taskId Unique hash of the task created. * @param taskCreator The address which created the task. * * @return address Overriden or original taskCreator. */ function preCancelTask(bytes32 taskId, address taskCreator) external returns (address); /** * @notice Called during `exec` and before execAddress is called. * * @param taskId Unique hash of the task created. * @param taskCreator The address which created the task. * @param execAddress Address of contract that should be called. * @param execData Execution data to be called with / function selector if execution data is yet to be determined. * * @return address Overriden or original execution address. * @return bytes Overriden or original execution data. */ function preExecCall( bytes32 taskId, address taskCreator, address execAddress, bytes calldata execData ) external returns (address, bytes memory); /** * @notice Called during `exec` and after execAddress is called. * * @param taskId Unique hash of the task created. * @param taskCreator The address which created the task. * @param execAddress Address of contract that should be called. * @param execData Execution data to be called with / function selector if execution data is yet to be determined. */ function postExecCall( bytes32 taskId, address taskCreator, address execAddress, bytes calldata execData ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ITaskTreasuryUpgradable { /// @notice Events /// event FundsDeposited( address indexed sender, address indexed token, uint256 indexed amount ); event FundsWithdrawn( address indexed receiver, address indexed initiator, address indexed token, uint256 amount ); event LogDeductFees( address indexed user, address indexed executor, address indexed token, uint256 fees, address service ); event UpdatedService(address indexed service, bool add); event UpdatedMaxFee(uint256 indexed maxFee); /// @notice External functions /// function depositFunds( address receiver, address token, uint256 amount ) external payable; function withdrawFunds( address payable receiver, address token, uint256 amount ) external; function useFunds( address user, address token, uint256 amount ) external; function updateMaxFee(uint256 _newMaxFee) external; function updateWhitelistedService(address service, bool isWhitelist) external; /// @notice External view functions /// function getCreditTokensByUser(address user) external view returns (address[] memory); function getTotalCreditTokensByUser(address user) external view returns (address[] memory); function getWhitelistedServices() external view returns (address[] memory); function totalUserTokenBalance(address user, address token) external view returns (uint256); function userTokenBalance(address user, address token) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; // solhint-disable max-line-length library LibDataTypes { /** * @notice Whitelisted modules that are available for users to customise conditions and specifications of their tasks. * * @param RESOLVER Use dynamic condition & input data for execution. {See ResolverModule.sol} * @param TIME Repeated execution of task at a specified timing and interval. {See TimeModule.sol} * @param PROXY Creates a dedicated caller (msg.sender) to be used when executing the task. {See ProxyModule.sol} * @param SINGLE_EXEC Task is cancelled after one execution. {See SingleExecModule.sol} */ enum Module { RESOLVER, TIME, PROXY, SINGLE_EXEC } /** * @notice Struct to contain modules and their relative arguments that are used for task creation. * * @param modules List of selected modules. * @param args Arguments of modules if any. Pass "0x" for modules which does not require args {See encodeModuleArg} */ struct ModuleData { Module[] modules; bytes[] args; } /** * @notice Struct for time module. * * @param nextExec Time when the next execution should occur. * @param interval Time interval between each execution. */ struct Time { uint128 nextExec; uint128 interval; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; import {LibDataTypes} from "./LibDataTypes.sol"; library LibEvents { /** * @notice Emitted when `createTask` is called. * * @param taskCreator The address which created the task. * @param execAddress Address of contract that is called by Gelato. * @param execDataOrSelector Execution data / function selector. * @param moduleData Conditional modules used. {See LibDataTypes-ModuleData} * @param feeToken Token used to pay for the execution. ETH = 0xeeeeee... * @param taskId Unique hash of the task. {See LibTaskId-getTaskId} */ event TaskCreated( address indexed taskCreator, address indexed execAddress, bytes execDataOrSelector, LibDataTypes.ModuleData moduleData, address feeToken, bytes32 indexed taskId ); /** * @notice Emitted when `cancelTask` is called. * * @param taskId Unique hash of the task. {See LibTaskId-getTaskId} * @param taskCreator The address which owned the task. */ event TaskCancelled(bytes32 taskId, address taskCreator); /** * @notice Emitted when `exec` is called. * * @param txFee Fee paid to Gelato for execution * @param feeToken Token used to pay for the execution. ETH = 0xeeeeee... * @param execAddress Address of contract that will be called by Gelato. * @param execData Execution data / function selector. * @param taskId Unique hash of the task. {See LibTaskId-getTaskId} * @param callSuccess Status of the call to execAddress. */ event ExecSuccess( uint256 indexed txFee, address indexed feeToken, address indexed execAddress, bytes execData, bytes32 taskId, bool callSuccess ); /** * @notice Emitted when TimeModule is initialised. * * @param taskId Unique hash of the task. {See LibTaskId-getTaskId} * @param nextExec Time when the next execution will occur. * @param interval Time interval between each execution. */ event TimerSet( bytes32 indexed taskId, uint128 indexed nextExec, uint128 indexed interval ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; import {LibDataTypes} from "./LibDataTypes.sol"; import {ILegacyOps} from "../interfaces/ILegacyOps.sol"; /** * @notice Library to keep task creation methods backwards compatible. * @notice Legacy create task methods can be found in ILegacyOps.sol */ library LibLegacyTask { /** * @notice Use legacy ops create task calldata to construct * arguments that conforms to current create task format. * * @param _funcSig Function signature of calldata. * @param _callData Calldata that was passed from fallback function. */ function getCreateTaskArg(bytes4 _funcSig, bytes calldata _callData) internal pure returns ( address execAddress, bytes memory execData, LibDataTypes.ModuleData memory moduleData, address feeToken ) { if (_funcSig == ILegacyOps.createTask.selector) { (execAddress, execData, moduleData, feeToken) = _resolveCreateTask( _callData[4:] ); } else if (_funcSig == ILegacyOps.createTaskNoPrepayment.selector) { ( execAddress, execData, moduleData, feeToken ) = _resolveCreateTaskNoPrepayment(_callData[4:]); } else if (_funcSig == ILegacyOps.createTimedTask.selector) { ( execAddress, execData, moduleData, feeToken ) = _resolveCreateTimedTask(_callData[4:]); } else revert("Ops.createTask: Function not found"); } function _resolveCreateTask(bytes calldata _callDataSliced) private pure returns ( address execAddress, bytes memory execData, LibDataTypes.ModuleData memory moduleData, address feeToken ) { bytes4 execSelector; address resolverAddress; bytes memory resolverData; (execAddress, execSelector, resolverAddress, resolverData) = abi.decode( _callDataSliced, (address, bytes4, address, bytes) ); LibDataTypes.Module[] memory modules = new LibDataTypes.Module[](1); modules[0] = LibDataTypes.Module.RESOLVER; bytes[] memory args = new bytes[](1); args[0] = abi.encode(resolverAddress, resolverData); moduleData = LibDataTypes.ModuleData(modules, args); execData = abi.encodePacked(execSelector); feeToken = address(0); } function _resolveCreateTaskNoPrepayment(bytes calldata _callDataSliced) private pure returns ( address execAddress, bytes memory execData, LibDataTypes.ModuleData memory moduleData, address feeToken ) { bytes4 execSelector; address resolverAddress; bytes memory resolverData; ( execAddress, execSelector, resolverAddress, resolverData, feeToken ) = abi.decode( _callDataSliced, (address, bytes4, address, bytes, address) ); LibDataTypes.Module[] memory modules = new LibDataTypes.Module[](1); modules[0] = LibDataTypes.Module.RESOLVER; bytes[] memory args = new bytes[](1); args[0] = abi.encode(resolverAddress, resolverData); moduleData = LibDataTypes.ModuleData(modules, args); execData = abi.encodePacked(execSelector); } function _resolveCreateTimedTask(bytes calldata _callDataSliced) private pure returns ( address execAddress, bytes memory execData, LibDataTypes.ModuleData memory moduleData, address feeToken ) { bytes memory resolverModuleArgs; bytes memory timeModuleArgs; ( execAddress, execData, feeToken, resolverModuleArgs, timeModuleArgs ) = _decodeTimedTaskCallData(_callDataSliced); LibDataTypes.Module[] memory modules = new LibDataTypes.Module[](2); modules[0] = LibDataTypes.Module.RESOLVER; modules[1] = LibDataTypes.Module.TIME; bytes[] memory args = new bytes[](2); args[0] = resolverModuleArgs; args[1] = timeModuleArgs; moduleData = LibDataTypes.ModuleData(modules, args); } function _decodeTimedTaskCallData(bytes calldata _callDataSliced) private pure returns ( address, bytes memory, address, bytes memory, bytes memory ) { ( uint128 startTime, uint128 interval, address execAddress, bytes4 execSelector, address resolverAddress, bytes memory resolverData, address feeToken, bool useTreasury ) = abi.decode( _callDataSliced, ( uint128, uint128, address, bytes4, address, bytes, address, bool ) ); return ( execAddress, abi.encodePacked(execSelector), feeToken = useTreasury ? address(0) : feeToken, abi.encode(resolverAddress, resolverData), abi.encode(startTime, interval) ); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import {LibDataTypes} from "./LibDataTypes.sol"; /** * @notice Library to compute taskId of legacy and current tasks. */ // solhint-disable max-line-length library LibTaskId { /** * @notice Returns taskId of taskCreator. * @notice To maintain the taskId of legacy tasks, if * resolver module or resolver and time module is used, * we will compute task id the legacy way. * * @param taskCreator The address which created the task. * @param execAddress Address of contract that will be called by Gelato. * @param execSelector Signature of the function which will be called by Gelato. * @param moduleData Conditional modules that will be used. {See LibDataTypes-ModuleData} * @param feeToken Address of token to be used as payment. Use address(0) if TaskTreasury is being used, 0xeeeeee... for ETH or native tokens. */ function getTaskId( address taskCreator, address execAddress, bytes4 execSelector, LibDataTypes.ModuleData memory moduleData, address feeToken ) internal pure returns (bytes32 taskId) { if (_shouldGetLegacyTaskId(moduleData.modules)) { bytes32 resolverHash = _getResolverHash(moduleData.args[0]); taskId = getLegacyTaskId( taskCreator, execAddress, execSelector, feeToken == address(0), feeToken, resolverHash ); } else { taskId = keccak256( abi.encode( taskCreator, execAddress, execSelector, moduleData, feeToken ) ); } } /** * @notice Returns taskId of taskCreator. * @notice Legacy way of computing taskId. * * @param taskCreator The address which created the task. * @param execAddress Address of contract that will be called by Gelato. * @param execSelector Signature of the function which will be called by Gelato. * @param useTaskTreasuryFunds Wether fee should be deducted from TaskTreasury. * @param feeToken Address of token to be used as payment. Use address(0) if TaskTreasury is being used, 0xeeeeee... for ETH or native tokens. * @param resolverHash Hash of resolverAddress and resolverData {See getResolverHash} */ function getLegacyTaskId( address taskCreator, address execAddress, bytes4 execSelector, bool useTaskTreasuryFunds, address feeToken, bytes32 resolverHash ) internal pure returns (bytes32) { return keccak256( abi.encode( taskCreator, execAddress, execSelector, useTaskTreasuryFunds, feeToken, resolverHash ) ); } /** * @dev For legacy tasks, resolvers are compulsory. Time tasks were also introduced. * The sequence of Module is enforced in {LibTaskModule-_validModules} */ function _shouldGetLegacyTaskId(LibDataTypes.Module[] memory _modules) private pure returns (bool) { uint256 length = _modules.length; if ( (length == 1 && _modules[0] == LibDataTypes.Module.RESOLVER) || (length == 2 && _modules[0] == LibDataTypes.Module.RESOLVER && _modules[1] == LibDataTypes.Module.TIME) ) return true; return false; } /** * @dev Acquire resolverHash which is required to compute legacyTaskId. * * @param _resolverModuleArg Encoded value of resolverAddress and resolverData */ function _getResolverHash(bytes memory _resolverModuleArg) private pure returns (bytes32) { return keccak256(_resolverModuleArg); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; import {_call, _delegateCall} from "../functions/FExec.sol"; import {LibDataTypes} from "./LibDataTypes.sol"; import {LibTaskModuleConfig} from "./LibTaskModuleConfig.sol"; import {ITaskModule} from "../interfaces/ITaskModule.sol"; /** * @notice Library to call task modules on task creation and execution. */ library LibTaskModule { using LibTaskModuleConfig for LibDataTypes.Module; /** * @notice Delegate calls task modules before generating taskId. * * @param _execAddress Address of contract that will be called by Gelato. * @param _taskCreator The address which created the task. * @param taskModuleAddresses The storage reference to the mapping of modules to their address. */ function preCreateTask( address _taskCreator, address _execAddress, mapping(LibDataTypes.Module => address) storage taskModuleAddresses ) internal returns (address, address) { uint256 length = uint256(type(LibDataTypes.Module).max); for (uint256 i; i <= length; i++) { LibDataTypes.Module module = LibDataTypes.Module(i); if (!module.requirePreCreate()) continue; address moduleAddress = taskModuleAddresses[module]; _moduleInitialised(moduleAddress); bytes memory delegatecallData = abi.encodeWithSelector( ITaskModule.preCreateTask.selector, _taskCreator, _execAddress ); (, bytes memory returnData) = _delegateCall( moduleAddress, delegatecallData, "Ops.preCreateTask: " ); (_taskCreator, _execAddress) = abi.decode( returnData, (address, address) ); } return (_taskCreator, _execAddress); } /** * @notice Delegate calls task modules on create task to initialise them. * * @param _taskId Unique hash of the task. {See LibTaskId-getTaskId} * @param _taskCreator The address which created the task. * @param _execAddress Address of contract that will be called by Gelato. * @param _execData Execution data to be called with / function selector. * @param _moduleData Modules that will be used for the task. {See LibDataTypes-ModuleData} * @param taskModuleAddresses The storage reference to the mapping of modules to their address. */ function onCreateTask( bytes32 _taskId, address _taskCreator, address _execAddress, bytes memory _execData, LibDataTypes.ModuleData memory _moduleData, mapping(LibDataTypes.Module => address) storage taskModuleAddresses ) internal { uint256 length = _moduleData.modules.length; _validModules(length, _moduleData.modules); for (uint256 i; i < length; i++) { LibDataTypes.Module module = _moduleData.modules[i]; if (!module.requireOnCreate()) continue; address moduleAddress = taskModuleAddresses[module]; _moduleInitialised(moduleAddress); bytes memory delegatecallData = abi.encodeWithSelector( ITaskModule.onCreateTask.selector, _taskId, _taskCreator, _execAddress, _execData, _moduleData.args[i] ); _delegateCall( moduleAddress, delegatecallData, "Ops.onCreateTask: " ); } } /** * @notice Delegate calls task modules before removing task. * * @param _taskId Unique hash of the task. {See LibTaskId-getTaskId} * @param _taskCreator The address which created the task. * @param taskModuleAddresses The storage reference to the mapping of modules to their address. */ function preCancelTask( bytes32 _taskId, address _taskCreator, mapping(LibDataTypes.Module => address) storage taskModuleAddresses ) internal returns (address) { uint256 length = uint256(type(LibDataTypes.Module).max); for (uint256 i; i <= length; i++) { LibDataTypes.Module module = LibDataTypes.Module(i); if (!module.requirePreCancel()) continue; address moduleAddress = taskModuleAddresses[module]; _moduleInitialised(moduleAddress); bytes memory delegatecallData = abi.encodeWithSelector( ITaskModule.preCancelTask.selector, _taskId, _taskCreator ); (, bytes memory returnData) = _delegateCall( moduleAddress, delegatecallData, "Ops.preCancelTask: " ); (_taskCreator) = abi.decode(returnData, (address)); } return _taskCreator; } /** * @notice Delegate calls task modules on exec. * * @param _taskId Unique hash of the task. {See LibTaskId-getTaskId} * @param _taskCreator The address which created the task. * @param _execAddress Address of contract that will be called by Gelato. * @param _execData Execution data to be called with / function selector. * @param _modules Modules that is used for the task. {See LibDataTypes-Module} * @param _revertOnFailure To revert or not if call to execAddress fails. * @param taskModuleAddresses The storage reference to the mapping of modules to their address. */ function onExecTask( bytes32 _taskId, address _taskCreator, address _execAddress, bytes memory _execData, LibDataTypes.Module[] memory _modules, bool _revertOnFailure, mapping(LibDataTypes.Module => address) storage taskModuleAddresses ) internal returns (bool callSuccess) { address[] memory moduleAddresses = _getModuleAddresses( _modules, taskModuleAddresses ); (_execAddress, _execData) = _preExecCall( _taskId, _taskCreator, _execAddress, _execData, _modules, moduleAddresses ); (callSuccess, ) = _call( _execAddress, abi.encodePacked(_execData, _taskCreator), 0, _revertOnFailure, "Ops.exec: " ); _postExecCall( _taskId, _taskCreator, _execAddress, _execData, _modules, moduleAddresses ); } function _preExecCall( bytes32 _taskId, address _taskCreator, address _execAddress, bytes memory _execData, LibDataTypes.Module[] memory _modules, address[] memory _moduleAddresses ) private returns (address, bytes memory) { uint256 length = _modules.length; for (uint256 i; i < length; i++) { if (!_modules[i].requirePreExec()) continue; bytes memory delegatecallData = abi.encodeWithSelector( ITaskModule.preExecCall.selector, _taskId, _taskCreator, _execAddress, _execData ); (, bytes memory returnData) = _delegateCall( _moduleAddresses[i], delegatecallData, "Ops.preExecCall: " ); (_execAddress, _execData) = abi.decode( returnData, (address, bytes) ); } return (_execAddress, _execData); } function _postExecCall( bytes32 _taskId, address _taskCreator, address _execAddress, bytes memory _execData, LibDataTypes.Module[] memory _modules, address[] memory _moduleAddresses ) private { uint256 length = _moduleAddresses.length; for (uint256 i; i < length; i++) { if (!_modules[i].requirePostExec()) continue; bytes memory delegatecallData = abi.encodeWithSelector( ITaskModule.postExecCall.selector, _taskId, _taskCreator, _execAddress, _execData ); _delegateCall( _moduleAddresses[i], delegatecallData, "Ops.postExecCall: " ); } } function _getModuleAddresses( LibDataTypes.Module[] memory _modules, mapping(LibDataTypes.Module => address) storage taskModuleAddresses ) private view returns (address[] memory) { uint256 length = _modules.length; address[] memory moduleAddresses = new address[](length); for (uint256 i; i < length; i++) { moduleAddresses[i] = taskModuleAddresses[_modules[i]]; } return moduleAddresses; } function _moduleInitialised(address _moduleAddress) private pure { require( _moduleAddress != address(0), "Ops._moduleInitialised: Not init" ); } ///@dev Check for duplicate modules. function _validModules( uint256 _length, LibDataTypes.Module[] memory _modules ) private pure { if (_length > 1) for (uint256 i; i < _length - 1; i++) require( _modules[i + 1] > _modules[i], "Ops._validModules: Asc only" ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; import {LibDataTypes} from "./LibDataTypes.sol"; /** * @notice Library to determine wether to call task modules to reduce unnecessary calls. */ library LibTaskModuleConfig { function requirePreCreate(LibDataTypes.Module _module) internal pure returns (bool) { if (_module == LibDataTypes.Module.PROXY) return true; return false; } function requirePreCancel(LibDataTypes.Module _module) internal pure returns (bool) { if ( _module == LibDataTypes.Module.TIME || _module == LibDataTypes.Module.PROXY ) return true; return false; } function requireOnCreate(LibDataTypes.Module _module) internal pure returns (bool) { if ( _module == LibDataTypes.Module.TIME || _module == LibDataTypes.Module.PROXY ) return true; return false; } function requirePreExec(LibDataTypes.Module _module) internal pure returns (bool) { if ( _module == LibDataTypes.Module.TIME || _module == LibDataTypes.Module.PROXY ) return true; return false; } function requirePostExec(LibDataTypes.Module _module) internal pure returns (bool) { if (_module == LibDataTypes.Module.SINGLE_EXEC) return true; return false; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.12; library GelatoBytes { function calldataSliceSelector(bytes calldata _bytes) internal pure returns (bytes4 selector) { selector = _bytes[0] | (bytes4(_bytes[1]) >> 8) | (bytes4(_bytes[2]) >> 16) | (bytes4(_bytes[3]) >> 24); } function memorySliceSelector(bytes memory _bytes) internal pure returns (bytes4 selector) { selector = _bytes[0] | (bytes4(_bytes[1]) >> 8) | (bytes4(_bytes[2]) >> 16) | (bytes4(_bytes[3]) >> 24); } function revertWithError(bytes memory _bytes, string memory _tracingInfo) internal pure { // 68: 32-location, 32-length, 4-ErrorSelector, UTF-8 err if (_bytes.length % 32 == 4) { bytes4 selector; assembly { selector := mload(add(0x20, _bytes)) } if (selector == 0x08c379a0) { // Function selector for Error(string) assembly { _bytes := add(_bytes, 68) } revert(string(abi.encodePacked(_tracingInfo, string(_bytes)))); } else { revert( string(abi.encodePacked(_tracingInfo, "NoErrorSelector")) ); } } else { revert( string(abi.encodePacked(_tracingInfo, "UnexpectedReturndata")) ); } } function returnError(bytes memory _bytes, string memory _tracingInfo) internal pure returns (string memory) { // 68: 32-location, 32-length, 4-ErrorSelector, UTF-8 err if (_bytes.length % 32 == 4) { bytes4 selector; assembly { selector := mload(add(0x20, _bytes)) } if (selector == 0x08c379a0) { // Function selector for Error(string) assembly { _bytes := add(_bytes, 68) } return string(abi.encodePacked(_tracingInfo, string(_bytes))); } else { return string(abi.encodePacked(_tracingInfo, "NoErrorSelector")); } } else { return string(abi.encodePacked(_tracingInfo, "UnexpectedReturndata")); } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.12; import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {_transfer, ETH} from "../../functions/FUtils.sol"; abstract contract Gelatofied { address payable public immutable gelato; modifier gelatofy(uint256 _amount, address _paymentToken) { require(msg.sender == gelato, "Gelatofied: Only gelato"); _; _transfer(gelato, _paymentToken, _amount); } modifier onlyGelato() { require(msg.sender == gelato, "Gelatofied: Only gelato"); _; } constructor(address payable _gelato) { gelato = _gelato; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; abstract contract Proxied { /// @notice to be used by initialisation / postUpgrade function so that only the proxy's admin can execute them /// It also allows these functions to be called inside a contructor /// even if the contract is meant to be used without proxy modifier proxied() { address proxyAdminAddress = _proxyAdmin(); // With hardhat-deploy proxies // the proxyAdminAddress is zero only for the implementation contract // if the implementation contract want to be used as a standalone/immutable contract // it simply has to execute the `proxied` function // This ensure the proxyAdminAddress is never zero post deployment // And allow you to keep the same code for both proxied contract and immutable contract if (proxyAdminAddress == address(0)) { // ensure can not be called twice when used outside of proxy : no admin // solhint-disable-next-line security/no-inline-assembly assembly { sstore( 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ) } } else { require(msg.sender == proxyAdminAddress); } _; } modifier onlyProxyAdmin() { require(msg.sender == _proxyAdmin(), "NOT_AUTHORIZED"); _; } function _proxyAdmin() internal view returns (address adminAddress) { // solhint-disable-next-line security/no-inline-assembly assembly { adminAddress := sload( 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103 ) } } }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": false, "runs": 200 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address payable","name":"_gelato","type":"address"},{"internalType":"contract ITaskTreasuryUpgradable","name":"_taskTreasury","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[{"internalType":"bytes32","name":"_taskId","type":"bytes32"}],"name":"cancelTask","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_execAddress","type":"address"},{"internalType":"bytes","name":"_execDataOrSelector","type":"bytes"},{"components":[{"internalType":"enum LibDataTypes.Module[]","name":"modules","type":"uint8[]"},{"internalType":"bytes[]","name":"args","type":"bytes[]"}],"internalType":"struct LibDataTypes.ModuleData","name":"_moduleData","type":"tuple"},{"internalType":"address","name":"_feeToken","type":"address"}],"name":"createTask","outputs":[{"internalType":"bytes32","name":"taskId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_taskCreator","type":"address"},{"internalType":"address","name":"_execAddress","type":"address"},{"internalType":"bytes","name":"_execData","type":"bytes"},{"components":[{"internalType":"enum LibDataTypes.Module[]","name":"modules","type":"uint8[]"},{"internalType":"bytes[]","name":"args","type":"bytes[]"}],"internalType":"struct LibDataTypes.ModuleData","name":"_moduleData","type":"tuple"},{"internalType":"uint256","name":"_txFee","type":"uint256"},{"internalType":"address","name":"_feeToken","type":"address"},{"internalType":"bool","name":"_useTaskTreasuryFunds","type":"bool"},{"internalType":"bool","name":"_revertOnFailure","type":"bool"}],"name":"exec","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"execAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gelato","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFeeDetails","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"taskCreator","type":"address"},{"internalType":"address","name":"execAddress","type":"address"},{"internalType":"bytes4","name":"execSelector","type":"bytes4"},{"components":[{"internalType":"enum LibDataTypes.Module[]","name":"modules","type":"uint8[]"},{"internalType":"bytes[]","name":"args","type":"bytes[]"}],"internalType":"struct LibDataTypes.ModuleData","name":"moduleData","type":"tuple"},{"internalType":"address","name":"feeToken","type":"address"}],"name":"getTaskId","outputs":[{"internalType":"bytes32","name":"taskId","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"taskCreator","type":"address"},{"internalType":"address","name":"execAddress","type":"address"},{"internalType":"bytes4","name":"execSelector","type":"bytes4"},{"internalType":"bool","name":"useTaskTreasuryFunds","type":"bool"},{"internalType":"address","name":"feeToken","type":"address"},{"internalType":"bytes32","name":"resolverHash","type":"bytes32"}],"name":"getTaskId","outputs":[{"internalType":"bytes32","name":"taskId","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_taskCreator","type":"address"}],"name":"getTaskIdsByUser","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum LibDataTypes.Module[]","name":"_modules","type":"uint8[]"},{"internalType":"address[]","name":"_moduleAddresses","type":"address[]"}],"name":"setModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"taskCreator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum LibDataTypes.Module","name":"","type":"uint8"}],"name":"taskModuleAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taskTreasury","outputs":[{"internalType":"contract ITaskTreasuryUpgradable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"timedTask","outputs":[{"internalType":"uint128","name":"nextExec","type":"uint128"},{"internalType":"uint128","name":"interval","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c06040523480156200001157600080fd5b5060405162004e6238038062004e6283398181016040528101906200003791906200016c565b818073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1681525050508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250505050620001b3565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620000db82620000ae565b9050919050565b620000ed81620000ce565b8114620000f957600080fd5b50565b6000815190506200010d81620000e2565b92915050565b60006200012082620000ae565b9050919050565b6000620001348262000113565b9050919050565b620001468162000127565b81146200015257600080fd5b50565b60008151905062000166816200013b565b92915050565b60008060408385031215620001865762000185620000a9565b5b60006200019685828601620000fc565b9250506020620001a98582860162000155565b9150509250929050565b60805160a051614c7b620001e76000396000818161096701526113dc01526000818161057901526107790152614c7b6000f3fe608060405234801561001057600080fd5b506004361061010f5760003560e01c80637b4e45e9116100a2578063b81cd86611610071578063b81cd866146102fd578063cd3d4fb91461032e578063ddca3f431461035e578063e60a32131461037c578063ee8ca3b51461039a57610110565b80637b4e45e914610276578063813785e6146102a6578063ad558ab9146102c2578063b810c636146102de57610110565b806354fd4d50116100de57806354fd4d50146101ec578063573ea5751461020a578063647846a5146102285780636d2dd29f1461024657610110565b80630407145c1461012c5780632e6e0bd01461015c5780633140576e1461018c5780633323b467146101bc57610110565b5b600036606061011f83836103b6565b9050915050805190602001f35b61014660048036038101906101419190612dda565b61041e565b6040516101539190612ecf565b60405180910390f35b61017660048036038101906101719190612f1d565b610474565b6040516101839190612f59565b60405180910390f35b6101a660048036038101906101a19190613372565b6104a7565b6040516101b39190613418565b60405180910390f35b6101d660048036038101906101d191906134b2565b6104c1565b6040516101e39190613418565b60405180910390f35b6101f461053e565b60405161020191906135de565b60405180910390f35b610212610577565b60405161021f9190613621565b60405180910390f35b61023061059b565b60405161023d9190612f59565b60405180910390f35b610260600480360381019061025b9190612f1d565b6105c1565b60405161026d9190612f59565b60405180910390f35b610290600480360381019061028b9190613674565b6105f4565b60405161029d9190613418565b60405180910390f35b6102c060048036038101906102bb91906137ad565b610610565b005b6102dc60048036038101906102d79190613864565b610777565b005b6102e661089f565b6040516102f4929190613961565b60405180910390f35b61031760048036038101906103129190612f1d565b6108d0565b6040516103259291906139b5565b60405180910390f35b610348600480360381019061034391906139de565b61092c565b6040516103559190612f59565b60405180910390f35b61036661095f565b6040516103739190613a0b565b60405180910390f35b610384610965565b6040516103919190613a85565b60405180910390f35b6103b460048036038101906103af9190612f1d565b610989565b005b606060006103c484846109a7565b90506000806000806103d7858989610b1d565b935093509350935060006103ee3386868686610ce5565b9050806040516020016104019190613ac1565b604051602081830303815290604052965050505050505092915050565b60606000610469600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020610e63565b905080915050919050565b60006020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006104b68686868686610e78565b905095945050505050565b6000806104d033886006610f38565b8098508192505050610532818888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508761052c90613adc565b87610ce5565b91505095945050505050565b6040518060400160405280600181526020017f350000000000000000000000000000000000000000000000000000000000000081525081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000610604878787878787611101565b90509695505050505050565b610618611140565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610685576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067c90613b3b565b60405180910390fd5b600084849050905060005b8181101561076f578383828181106106ab576106aa613b5b565b5b90506020020160208101906106c09190612dda565b600660008888858181106106d7576106d6613b5b565b5b90506020020160208101906106ec91906139de565b60038111156106fe576106fd613b8a565b5b60038111156107105761070f613b8a565b5b815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808061076790613be8565b915050610690565b505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610805576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107fc90613c7c565b60405180910390fd5b600061083289896108158a611169565b8961081f90613adc565b8761082a578861082d565b60005b610e78565b9050610894818a8a8a8a806000019061084b9190613cab565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508a8a8a8a6112e2565b505050505050505050565b600080600354600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915091509091565b60056020528060005260406000206000915090508060000160009054906101000a90046fffffffffffffffffffffffffffffffff16908060000160109054906101000a90046fffffffffffffffffffffffffffffffff16905082565b60066020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60035481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600061099782336006611510565b90506109a381836116cd565b5050565b60006018838360038181106109bf576109be613b5b565b5b9050013560f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c601084846002818110610a2257610a21613b5b565b5b9050013560f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c600885856001818110610a8557610a84613b5b565b5b9050013560f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c85856000818110610ae657610ae5613b5b565b5b9050013560f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916171717905092915050565b60006060610b29612d4e565b6000638b92696a60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916877bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610ba757610b9286866004908092610b8d93929190613d18565b6117ec565b80945081955082965083975050505050610cdc565b63b9f45adb60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916877bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610c2357610c0e86866004908092610c0993929190613d18565b611993565b80945081955082965083975050505050610cdb565b63a873882560e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916877bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610c9f57610c8a86866004908092610c8593929190613d18565b611b3a565b80945081955082965083975050505050610cda565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cd190613dc5565b60405180910390fd5b5b5b93509350935093565b6000610cfc8686610cf587611169565b8686610e78565b9050610d4f81600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611cfe90919063ffffffff16565b15610d8f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d8690613e31565b60405180910390fd5b610d9e81878787876006611d15565b610def81600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611ee790919063ffffffff16565b50808573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f73f079427211e7b93db86024054de0b3c4a076a36cf0f86d2c4bf0d112eb7f1d878787604051610e52939291906140ed565b60405180910390a495945050505050565b6060610e7182600001611efe565b9050919050565b6000610e878360000151611f5a565b15610efd576000610eb68460200151600081518110610ea957610ea8613b5b565b5b602002602001015161206b565b9050610ef5878787600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16148786611101565b915050610f2f565b8585858585604051602001610f16959493929190614141565b6040516020818303038152906040528051906020012090505b95945050505050565b6000806000600380811115610f5057610f4f613b8a565b5b905060005b8181116110f1576000816003811115610f7157610f70613b8a565b5b9050610f8e816003811115610f8957610f88613b8a565b5b61207c565b610f9857506110de565b6000866000836003811115610fb057610faf613b8a565b5b6003811115610fc257610fc1613b8a565b5b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050610ffc816120bd565b60006376474e6a60e01b8a8a60405160240161101992919061419b565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006110ba83836040518060400160405280601381526020017f4f70732e7072654372656174655461736b3a200000000000000000000000000081525061212f565b915050808060200190518101906110d191906141f0565b809b50819c505050505050505b80806110e990613be8565b915050610f55565b5085859250925050935093915050565b600086868686868660405160200161111e9695949392919061423f565b6040516020818303038152906040528051906020012090509695505050505050565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610354905090565b600060188260038151811061118157611180613b5b565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c6010836002815181106111e5576111e4613b5b565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c60088460018151811061124957611248613b5b565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c846000815181106112ab576112aa613b5b565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161717179050919050565b61133389600260008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611cfe90919063ffffffff16565b611372576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611369906142ec565b60405180910390fd5b816113c0578360038190555082600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b60006113d28a8a8a8a8a8760066121b9565b9050821561146e577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a3f1233e8a86886040518463ffffffff1660e01b81526004016114379392919061430c565b600060405180830381600087803b15801561145157600080fd5b505af1158015611465573d6000803e3d6000fd5b5050505061149a565b600360009055600460006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555b8773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16867fa458375b1282695a972870cbfbc4891a9d856b79d563d17667d171d87e0c527a8a8e866040516114fc93929190614343565b60405180910390a450505050505050505050565b60008060038081111561152657611525613b8a565b5b905060005b8181116116c157600081600381111561154757611546613b8a565b5b905061156481600381111561155f5761155e613b8a565b5b612261565b61156e57506116ae565b600085600083600381111561158657611585613b8a565b5b600381111561159857611597613b8a565b5b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506115d2816120bd565b60006314ae992660e01b89896040516024016115ef929190614381565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600061169083836040518060400160405280601381526020017f4f70732e70726543616e63656c5461736b3a200000000000000000000000000081525061212f565b915050808060200190518101906116a791906143aa565b9850505050505b80806116b990613be8565b91505061152b565b50839150509392505050565b61171e81600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611cfe90919063ffffffff16565b61175d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161175490614423565b60405180910390fd5b6117ae81600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206122d290919063ffffffff16565b507f44d83729a43f9c6046446df014d073dd242e0ad672071e9b292f31b669c25b0981836040516117e0929190614381565b60405180910390a15050565b600060606117f8612d4e565b60008060006060888881019061180e9190614458565b809450819550829650839a50505050506000600167ffffffffffffffff81111561183b5761183a612fe2565b5b6040519080825280602002602001820160405280156118695781602001602082028036833780820191505090505b50905060008160008151811061188257611881613b5b565b5b6020026020010190600381111561189c5761189b613b8a565b5b908160038111156118b0576118af613b8a565b5b815250506000600167ffffffffffffffff8111156118d1576118d0612fe2565b5b60405190808252806020026020018201604052801561190457816020015b60608152602001906001900390816118ef5790505b509050838360405160200161191a9291906144db565b6040516020818303038152906040528160008151811061193d5761193c613b5b565b5b6020026020010181905250604051806040016040528083815260200182815250965084604051602001611970919061452c565b604051602081830303815290604052975060009550505050505092959194509250565b6000606061199f612d4e565b6000806000606088888101906119b59190614547565b809850819550829650839750849b5050505050506000600167ffffffffffffffff8111156119e6576119e5612fe2565b5b604051908082528060200260200182016040528015611a145781602001602082028036833780820191505090505b509050600081600081518110611a2d57611a2c613b5b565b5b60200260200101906003811115611a4757611a46613b8a565b5b90816003811115611a5b57611a5a613b8a565b5b815250506000600167ffffffffffffffff811115611a7c57611a7b612fe2565b5b604051908082528060200260200182016040528015611aaf57816020015b6060815260200190600190039081611a9a5790505b5090508383604051602001611ac59291906144db565b60405160208183030381529060405281600081518110611ae857611ae7613b5b565b5b6020026020010181905250604051806040016040528083815260200182815250965084604051602001611b1b919061452c565b6040516020818303038152906040529750505050505092959194509250565b60006060611b46612d4e565b6000606080611b5588886122e9565b809550819650829750839950849a5050505050506000600267ffffffffffffffff811115611b8657611b85612fe2565b5b604051908082528060200260200182016040528015611bb45781602001602082028036833780820191505090505b509050600081600081518110611bcd57611bcc613b5b565b5b60200260200101906003811115611be757611be6613b8a565b5b90816003811115611bfb57611bfa613b8a565b5b81525050600181600181518110611c1557611c14613b5b565b5b60200260200101906003811115611c2f57611c2e613b8a565b5b90816003811115611c4357611c42613b8a565b5b815250506000600267ffffffffffffffff811115611c6457611c63612fe2565b5b604051908082528060200260200182016040528015611c9757816020015b6060815260200190600190039081611c825790505b5090508381600081518110611caf57611cae613b5b565b5b60200260200101819052508281600181518110611ccf57611cce613b5b565b5b602002602001018190525060405180604001604052808381526020018281525095505050505092959194509250565b6000611d0d83600001836123af565b905092915050565b60008260000151519050611d2d8184600001516123d2565b60005b81811015611edd57600084600001518281518110611d5157611d50613b5b565b5b60200260200101519050611d76816003811115611d7157611d70613b8a565b5b6124b1565b611d805750611eca565b6000846000836003811115611d9857611d97613b8a565b5b6003811115611daa57611da9613b8a565b5b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050611de4816120bd565b600063b0ccbdf060e01b8b8b8b8b8b602001518981518110611e0957611e08613b5b565b5b6020026020010151604051602401611e259594939291906145de565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050611ec482826040518060400160405280601281526020017f4f70732e6f6e4372656174655461736b3a20000000000000000000000000000081525061212f565b50505050505b8080611ed590613be8565b915050611d30565b5050505050505050565b6000611ef68360000183612522565b905092915050565b606081600001805480602002602001604051908101604052809291908181526020018280548015611f4e57602002820191906000526020600020905b815481526020019060010190808311611f3a575b50505050509050919050565b60008082519050600181148015611fb0575060006003811115611f8057611f7f613b8a565b5b83600081518110611f9457611f93613b5b565b5b60200260200101516003811115611fae57611fad613b8a565b5b145b806120515750600281148015612005575060006003811115611fd557611fd4613b8a565b5b83600081518110611fe957611fe8613b5b565b5b6020026020010151600381111561200357612002613b8a565b5b145b80156120505750600160038111156120205761201f613b8a565b5b8360018151811061203457612033613b5b565b5b6020026020010151600381111561204e5761204d613b8a565b5b145b5b15612060576001915050612066565b60009150505b919050565b600081805190602001209050919050565b60006002600381111561209257612091613b8a565b5b8260038111156120a5576120a4613b8a565b5b036120b357600190506120b8565b600090505b919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361212c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121239061468b565b60405180910390fd5b50565b600060608473ffffffffffffffffffffffffffffffffffffffff168460405161215891906146e7565b600060405180830381855af49150503d8060008114612193576040519150601f19603f3d011682016040523d82523d6000602084013e612198565b606091505b508092508193505050816121b1576121b08184612592565b5b935093915050565b6000806121c685846126f9565b90506121d6898989898986612836565b809750819850505061224287878a6040516020016121f5929190614746565b6040516020818303038152906040526000876040518060400160405280600a81526020017f4f70732e657865633a20000000000000000000000000000000000000000000008152506129a9565b5080925050612255898989898986612a43565b50979650505050505050565b60006001600381111561227757612276613b8a565b5b82600381111561228a57612289613b8a565b5b14806122ba5750600260038111156122a5576122a4613b8a565b5b8260038111156122b8576122b7613b8a565b5b145b156122c857600190506122cd565b600090505b919050565b60006122e18360000183612b89565b905092915050565b6000606060006060806000806000806000806000808e8e81019061230d919061479a565b97509750975097509750975097509750858560405160200161232f919061452c565b60405160208183030381529060405282612349578361234c565b60005b93508386866040516020016123629291906144db565b6040516020818303038152906040528b8b6040516020016123849291906139b5565b6040516020818303038152906040529c509c509c509c509c5050505050505050509295509295909350565b600080836001016000848152602001908152602001600020541415905092915050565b60018211156124ad5760005b6001836123eb919061486c565b8110156124ab5781818151811061240557612404613b5b565b5b6020026020010151600381111561241f5761241e613b8a565b5b8260018361242d91906148a0565b8151811061243e5761243d613b5b565b5b6020026020010151600381111561245857612457613b8a565b5b11612498576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161248f90614942565b60405180910390fd5b80806124a390613be8565b9150506123de565b505b5050565b6000600160038111156124c7576124c6613b8a565b5b8260038111156124da576124d9613b8a565b5b148061250a5750600260038111156124f5576124f4613b8a565b5b82600381111561250857612507613b8a565b5b145b15612518576001905061251d565b600090505b919050565b600061252e83836123af565b61258757826000018290806001815401808255809150506001900390600052602060002001600090919091909150558260000180549050836001016000848152602001908152602001600020819055506001905061258c565b600090505b92915050565b6004602083516125a29190614991565b0361269d576000826020015190506308c379a060e01b817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036126415760448301925081836040516020016125f69291906149fe565b6040516020818303038152906040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161263891906135de565b60405180910390fd5b816040516020016126529190614a6e565b6040516020818303038152906040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161269491906135de565b60405180910390fd5b806040516020016126ae9190614adc565b6040516020818303038152906040526040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126f091906135de565b60405180910390fd5b606060008351905060008167ffffffffffffffff81111561271d5761271c612fe2565b5b60405190808252806020026020018201604052801561274b5781602001602082028036833780820191505090505b50905060005b8281101561282a5784600087838151811061276f5761276e613b5b565b5b6020026020010151600381111561278957612788613b8a565b5b600381111561279b5761279a613b8a565b5b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168282815181106127dd576127dc613b5b565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050808061282290613be8565b915050612751565b50809250505092915050565b6000606060008451905060005b818110156129965761288086828151811061286157612860613b5b565b5b6020026020010151600381111561287b5761287a613b8a565b5b612c9d565b1561298357600063c10304f760e01b8b8b8b8b6040516024016128a69493929190614afe565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600061296187848151811061291d5761291c613b5b565b5b6020026020010151836040518060400160405280601181526020017f4f70732e7072654578656343616c6c3a2000000000000000000000000000000081525061212f565b915050808060200190518101906129789190614bba565b809a50819b50505050505b808061298e90613be8565b915050612843565b5086869250925050965096945050505050565b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516129d391906146e7565b60006040518083038185875af1925050503d8060008114612a10576040519150601f19603f3d011682016040523d82523d6000602084013e612a15565b606091505b50809250819350505081158015612a295750835b15612a3957612a388184612592565b5b9550959350505050565b60008151905060005b81811015612b7f57612a89848281518110612a6a57612a69613b5b565b5b60200260200101516003811115612a8457612a83613b8a565b5b612d0e565b15612b6c57600063b2db0b4160e01b89898989604051602401612aaf9493929190614afe565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050612b68848381518110612b2457612b23613b5b565b5b6020026020010151826040518060400160405280601281526020017f4f70732e706f73744578656343616c6c3a20000000000000000000000000000081525061212f565b5050505b8080612b7790613be8565b915050612a4c565b5050505050505050565b60008083600101600084815260200190815260200160002054905060008114612c91576000600182612bbb919061486c565b9050600060018660000180549050612bd3919061486c565b9050818114612c42576000866000018281548110612bf457612bf3613b5b565b5b9060005260206000200154905080876000018481548110612c1857612c17613b5b565b5b90600052602060002001819055508387600101600083815260200190815260200160002081905550505b85600001805480612c5657612c55614c16565b5b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050612c97565b60009150505b92915050565b600060016003811115612cb357612cb2613b8a565b5b826003811115612cc657612cc5613b8a565b5b1480612cf6575060026003811115612ce157612ce0613b8a565b5b826003811115612cf457612cf3613b8a565b5b145b15612d045760019050612d09565b600090505b919050565b6000600380811115612d2357612d22613b8a565b5b826003811115612d3657612d35613b8a565b5b03612d445760019050612d49565b600090505b919050565b604051806040016040528060608152602001606081525090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612da782612d7c565b9050919050565b612db781612d9c565b8114612dc257600080fd5b50565b600081359050612dd481612dae565b92915050565b600060208284031215612df057612def612d72565b5b6000612dfe84828501612dc5565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b612e4681612e33565b82525050565b6000612e588383612e3d565b60208301905092915050565b6000602082019050919050565b6000612e7c82612e07565b612e868185612e12565b9350612e9183612e23565b8060005b83811015612ec2578151612ea98882612e4c565b9750612eb483612e64565b925050600181019050612e95565b5085935050505092915050565b60006020820190508181036000830152612ee98184612e71565b905092915050565b612efa81612e33565b8114612f0557600080fd5b50565b600081359050612f1781612ef1565b92915050565b600060208284031215612f3357612f32612d72565b5b6000612f4184828501612f08565b91505092915050565b612f5381612d9c565b82525050565b6000602082019050612f6e6000830184612f4a565b92915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612fa981612f74565b8114612fb457600080fd5b50565b600081359050612fc681612fa0565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61301a82612fd1565b810181811067ffffffffffffffff8211171561303957613038612fe2565b5b80604052505050565b600061304c612d68565b90506130588282613011565b919050565b600080fd5b600080fd5b600067ffffffffffffffff82111561308257613081612fe2565b5b602082029050602081019050919050565b600080fd5b600481106130a557600080fd5b50565b6000813590506130b781613098565b92915050565b60006130d06130cb84613067565b613042565b905080838252602082019050602084028301858111156130f3576130f2613093565b5b835b8181101561311c578061310888826130a8565b8452602084019350506020810190506130f5565b5050509392505050565b600082601f83011261313b5761313a613062565b5b813561314b8482602086016130bd565b91505092915050565b600067ffffffffffffffff82111561316f5761316e612fe2565b5b602082029050602081019050919050565b600080fd5b600067ffffffffffffffff8211156131a05761319f612fe2565b5b6131a982612fd1565b9050602081019050919050565b82818337600083830152505050565b60006131d86131d384613185565b613042565b9050828152602081018484840111156131f4576131f3613180565b5b6131ff8482856131b6565b509392505050565b600082601f83011261321c5761321b613062565b5b813561322c8482602086016131c5565b91505092915050565b600061324861324384613154565b613042565b9050808382526020820190506020840283018581111561326b5761326a613093565b5b835b818110156132b257803567ffffffffffffffff8111156132905761328f613062565b5b80860161329d8982613207565b8552602085019450505060208101905061326d565b5050509392505050565b600082601f8301126132d1576132d0613062565b5b81356132e1848260208601613235565b91505092915050565b600060408284031215613300576132ff612fcc565b5b61330a6040613042565b9050600082013567ffffffffffffffff81111561332a5761332961305d565b5b61333684828501613126565b600083015250602082013567ffffffffffffffff81111561335a5761335961305d565b5b613366848285016132bc565b60208301525092915050565b600080600080600060a0868803121561338e5761338d612d72565b5b600061339c88828901612dc5565b95505060206133ad88828901612dc5565b94505060406133be88828901612fb7565b935050606086013567ffffffffffffffff8111156133df576133de612d77565b5b6133eb888289016132ea565b92505060806133fc88828901612dc5565b9150509295509295909350565b61341281612e33565b82525050565b600060208201905061342d6000830184613409565b92915050565b600080fd5b60008083601f84011261344e5761344d613062565b5b8235905067ffffffffffffffff81111561346b5761346a613433565b5b60208301915083600182028301111561348757613486613093565b5b9250929050565b600080fd5b6000604082840312156134a9576134a861348e565b5b81905092915050565b6000806000806000608086880312156134ce576134cd612d72565b5b60006134dc88828901612dc5565b955050602086013567ffffffffffffffff8111156134fd576134fc612d77565b5b61350988828901613438565b9450945050604086013567ffffffffffffffff81111561352c5761352b612d77565b5b61353888828901613493565b925050606061354988828901612dc5565b9150509295509295909350565b600081519050919050565b600082825260208201905092915050565b60005b83811015613590578082015181840152602081019050613575565b8381111561359f576000848401525b50505050565b60006135b082613556565b6135ba8185613561565b93506135ca818560208601613572565b6135d381612fd1565b840191505092915050565b600060208201905081810360008301526135f881846135a5565b905092915050565b600061360b82612d7c565b9050919050565b61361b81613600565b82525050565b60006020820190506136366000830184613612565b92915050565b60008115159050919050565b6136518161363c565b811461365c57600080fd5b50565b60008135905061366e81613648565b92915050565b60008060008060008060c0878903121561369157613690612d72565b5b600061369f89828a01612dc5565b96505060206136b089828a01612dc5565b95505060406136c189828a01612fb7565b94505060606136d289828a0161365f565b93505060806136e389828a01612dc5565b92505060a06136f489828a01612f08565b9150509295509295509295565b60008083601f84011261371757613716613062565b5b8235905067ffffffffffffffff81111561373457613733613433565b5b6020830191508360208202830111156137505761374f613093565b5b9250929050565b60008083601f84011261376d5761376c613062565b5b8235905067ffffffffffffffff81111561378a57613789613433565b5b6020830191508360208202830111156137a6576137a5613093565b5b9250929050565b600080600080604085870312156137c7576137c6612d72565b5b600085013567ffffffffffffffff8111156137e5576137e4612d77565b5b6137f187828801613701565b9450945050602085013567ffffffffffffffff81111561381457613813612d77565b5b61382087828801613757565b925092505092959194509250565b6000819050919050565b6138418161382e565b811461384c57600080fd5b50565b60008135905061385e81613838565b92915050565b600080600080600080600080610100898b03121561388557613884612d72565b5b60006138938b828c01612dc5565b98505060206138a48b828c01612dc5565b975050604089013567ffffffffffffffff8111156138c5576138c4612d77565b5b6138d18b828c01613207565b965050606089013567ffffffffffffffff8111156138f2576138f1612d77565b5b6138fe8b828c01613493565b955050608061390f8b828c0161384f565b94505060a06139208b828c01612dc5565b93505060c06139318b828c0161365f565b92505060e06139428b828c0161365f565b9150509295985092959890939650565b61395b8161382e565b82525050565b60006040820190506139766000830185613952565b6139836020830184612f4a565b9392505050565b60006fffffffffffffffffffffffffffffffff82169050919050565b6139af8161398a565b82525050565b60006040820190506139ca60008301856139a6565b6139d760208301846139a6565b9392505050565b6000602082840312156139f4576139f3612d72565b5b6000613a02848285016130a8565b91505092915050565b6000602082019050613a206000830184613952565b92915050565b6000819050919050565b6000613a4b613a46613a4184612d7c565b613a26565b612d7c565b9050919050565b6000613a5d82613a30565b9050919050565b6000613a6f82613a52565b9050919050565b613a7f81613a64565b82525050565b6000602082019050613a9a6000830184613a76565b92915050565b6000819050919050565b613abb613ab682612e33565b613aa0565b82525050565b6000613acd8284613aaa565b60208201915081905092915050565b6000613ae836836132ea565b9050919050565b7f4e4f545f415554484f52495a4544000000000000000000000000000000000000600082015250565b6000613b25600e83613561565b9150613b3082613aef565b602082019050919050565b60006020820190508181036000830152613b5481613b18565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613bf38261382e565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613c2557613c24613bb9565b5b600182019050919050565b7f47656c61746f666965643a204f6e6c792067656c61746f000000000000000000600082015250565b6000613c66601783613561565b9150613c7182613c30565b602082019050919050565b60006020820190508181036000830152613c9581613c59565b9050919050565b600080fd5b600080fd5b600080fd5b60008083356001602003843603038112613cc857613cc7613c9c565b5b80840192508235915067ffffffffffffffff821115613cea57613ce9613ca1565b5b602083019250602082023603831315613d0657613d05613ca6565b5b509250929050565b600080fd5b600080fd5b60008085851115613d2c57613d2b613d0e565b5b83861115613d3d57613d3c613d13565b5b6001850283019150848603905094509492505050565b7f4f70732e6372656174655461736b3a2046756e6374696f6e206e6f7420666f7560008201527f6e64000000000000000000000000000000000000000000000000000000000000602082015250565b6000613daf602283613561565b9150613dba82613d53565b604082019050919050565b60006020820190508181036000830152613dde81613da2565b9050919050565b7f4f70732e6372656174655461736b3a204475706c6963617465207461736b0000600082015250565b6000613e1b601e83613561565b9150613e2682613de5565b602082019050919050565b60006020820190508181036000830152613e4a81613e0e565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000613e7882613e51565b613e828185613e5c565b9350613e92818560208601613572565b613e9b81612fd1565b840191505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60048110613ee357613ee2613b8a565b5b50565b6000819050613ef482613ed2565b919050565b6000613f0482613ee6565b9050919050565b613f1481613ef9565b82525050565b6000613f268383613f0b565b60208301905092915050565b6000602082019050919050565b6000613f4a82613ea6565b613f548185613eb1565b9350613f5f83613ec2565b8060005b83811015613f90578151613f778882613f1a565b9750613f8283613f32565b925050600181019050613f63565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b6000613fe582613e51565b613fef8185613fc9565b9350613fff818560208601613572565b61400881612fd1565b840191505092915050565b600061401f8383613fda565b905092915050565b6000602082019050919050565b600061403f82613f9d565b6140498185613fa8565b93508360208202850161405b85613fb9565b8060005b8581101561409757848403895281516140788582614013565b945061408383614027565b925060208a0199505060018101905061405f565b50829750879550505050505092915050565b600060408301600083015184820360008601526140c68282613f3f565b915050602083015184820360208601526140e08282614034565b9150508091505092915050565b600060608201905081810360008301526141078186613e6d565b9050818103602083015261411b81856140a9565b905061412a6040830184612f4a565b949350505050565b61413b81612f74565b82525050565b600060a0820190506141566000830188612f4a565b6141636020830187612f4a565b6141706040830186614132565b818103606083015261418281856140a9565b90506141916080830184612f4a565b9695505050505050565b60006040820190506141b06000830185612f4a565b6141bd6020830184612f4a565b9392505050565b6141cd81613600565b81146141d857600080fd5b50565b6000815190506141ea816141c4565b92915050565b6000806040838503121561420757614206612d72565b5b6000614215858286016141db565b9250506020614226858286016141db565b9150509250929050565b6142398161363c565b82525050565b600060c0820190506142546000830189612f4a565b6142616020830188612f4a565b61426e6040830187614132565b61427b6060830186614230565b6142886080830185612f4a565b61429560a0830184613409565b979650505050505050565b7f4f70732e657865633a205461736b206e6f7420666f756e640000000000000000600082015250565b60006142d6601883613561565b91506142e1826142a0565b602082019050919050565b60006020820190508181036000830152614305816142c9565b9050919050565b60006060820190506143216000830186612f4a565b61432e6020830185612f4a565b61433b6040830184613952565b949350505050565b6000606082019050818103600083015261435d8186613e6d565b905061436c6020830185613409565b6143796040830184614230565b949350505050565b60006040820190506143966000830185613409565b6143a36020830184612f4a565b9392505050565b6000602082840312156143c0576143bf612d72565b5b60006143ce848285016141db565b91505092915050565b7f4f70732e63616e63656c5461736b3a205461736b206e6f7420666f756e640000600082015250565b600061440d601e83613561565b9150614418826143d7565b602082019050919050565b6000602082019050818103600083015261443c81614400565b9050919050565b600081359050614452816141c4565b92915050565b6000806000806080858703121561447257614471612d72565b5b600061448087828801614443565b945050602061449187828801612fb7565b93505060406144a287828801614443565b925050606085013567ffffffffffffffff8111156144c3576144c2612d77565b5b6144cf87828801613207565b91505092959194509250565b60006040820190506144f06000830185612f4a565b81810360208301526145028184613e6d565b90509392505050565b6000819050919050565b61452661452182612f74565b61450b565b82525050565b60006145388284614515565b60048201915081905092915050565b600080600080600060a0868803121561456357614562612d72565b5b600061457188828901614443565b955050602061458288828901612fb7565b945050604061459388828901614443565b935050606086013567ffffffffffffffff8111156145b4576145b3612d77565b5b6145c088828901613207565b92505060806145d188828901614443565b9150509295509295909350565b600060a0820190506145f36000830188613409565b6146006020830187612f4a565b61460d6040830186612f4a565b818103606083015261461f8185613e6d565b905081810360808301526146338184613e6d565b90509695505050505050565b7f4f70732e5f6d6f64756c65496e697469616c697365643a204e6f7420696e6974600082015250565b6000614675602083613561565b91506146808261463f565b602082019050919050565b600060208201905081810360008301526146a481614668565b9050919050565b600081905092915050565b60006146c182613e51565b6146cb81856146ab565b93506146db818560208601613572565b80840191505092915050565b60006146f382846146b6565b915081905092915050565b60008160601b9050919050565b6000614716826146fe565b9050919050565b60006147288261470b565b9050919050565b61474061473b82612d9c565b61471d565b82525050565b600061475282856146b6565b915061475e828461472f565b6014820191508190509392505050565b6147778161398a565b811461478257600080fd5b50565b6000813590506147948161476e565b92915050565b600080600080600080600080610100898b0312156147bb576147ba612d72565b5b60006147c98b828c01614785565b98505060206147da8b828c01614785565b97505060406147eb8b828c01614443565b96505060606147fc8b828c01612fb7565b955050608061480d8b828c01614443565b94505060a089013567ffffffffffffffff81111561482e5761482d612d77565b5b61483a8b828c01613207565b93505060c061484b8b828c01614443565b92505060e061485c8b828c0161365f565b9150509295985092959890939650565b60006148778261382e565b91506148828361382e565b92508282101561489557614894613bb9565b5b828203905092915050565b60006148ab8261382e565b91506148b68361382e565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156148eb576148ea613bb9565b5b828201905092915050565b7f4f70732e5f76616c69644d6f64756c65733a20417363206f6e6c790000000000600082015250565b600061492c601b83613561565b9150614937826148f6565b602082019050919050565b6000602082019050818103600083015261495b8161491f565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061499c8261382e565b91506149a78361382e565b9250826149b7576149b6614962565b5b828206905092915050565b600081905092915050565b60006149d882613556565b6149e281856149c2565b93506149f2818560208601613572565b80840191505092915050565b6000614a0a82856149cd565b9150614a1682846149cd565b91508190509392505050565b7f4e6f4572726f7253656c6563746f720000000000000000000000000000000000600082015250565b6000614a58600f836149c2565b9150614a6382614a22565b600f82019050919050565b6000614a7a82846149cd565b9150614a8582614a4b565b915081905092915050565b7f556e657870656374656452657475726e64617461000000000000000000000000600082015250565b6000614ac66014836149c2565b9150614ad182614a90565b601482019050919050565b6000614ae882846149cd565b9150614af382614ab9565b915081905092915050565b6000608082019050614b136000830187613409565b614b206020830186612f4a565b614b2d6040830185612f4a565b8181036060830152614b3f8184613e6d565b905095945050505050565b6000614b5d614b5884613185565b613042565b905082815260208101848484011115614b7957614b78613180565b5b614b84848285613572565b509392505050565b600082601f830112614ba157614ba0613062565b5b8151614bb1848260208601614b4a565b91505092915050565b60008060408385031215614bd157614bd0612d72565b5b6000614bdf858286016141db565b925050602083015167ffffffffffffffff811115614c0057614bff612d77565b5b614c0c85828601614b8c565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220798174a7019cfbba358b2c4e8e70f4aa3e3b9721532742d957737708a0bbf8c364736f6c634300080e00330000000000000000000000003caca7b48d0573d793d3b0279b5f0029180e83b60000000000000000000000002807b4ae232b624023f87d0e237a3b1bf200fd99
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061010f5760003560e01c80637b4e45e9116100a2578063b81cd86611610071578063b81cd866146102fd578063cd3d4fb91461032e578063ddca3f431461035e578063e60a32131461037c578063ee8ca3b51461039a57610110565b80637b4e45e914610276578063813785e6146102a6578063ad558ab9146102c2578063b810c636146102de57610110565b806354fd4d50116100de57806354fd4d50146101ec578063573ea5751461020a578063647846a5146102285780636d2dd29f1461024657610110565b80630407145c1461012c5780632e6e0bd01461015c5780633140576e1461018c5780633323b467146101bc57610110565b5b600036606061011f83836103b6565b9050915050805190602001f35b61014660048036038101906101419190612dda565b61041e565b6040516101539190612ecf565b60405180910390f35b61017660048036038101906101719190612f1d565b610474565b6040516101839190612f59565b60405180910390f35b6101a660048036038101906101a19190613372565b6104a7565b6040516101b39190613418565b60405180910390f35b6101d660048036038101906101d191906134b2565b6104c1565b6040516101e39190613418565b60405180910390f35b6101f461053e565b60405161020191906135de565b60405180910390f35b610212610577565b60405161021f9190613621565b60405180910390f35b61023061059b565b60405161023d9190612f59565b60405180910390f35b610260600480360381019061025b9190612f1d565b6105c1565b60405161026d9190612f59565b60405180910390f35b610290600480360381019061028b9190613674565b6105f4565b60405161029d9190613418565b60405180910390f35b6102c060048036038101906102bb91906137ad565b610610565b005b6102dc60048036038101906102d79190613864565b610777565b005b6102e661089f565b6040516102f4929190613961565b60405180910390f35b61031760048036038101906103129190612f1d565b6108d0565b6040516103259291906139b5565b60405180910390f35b610348600480360381019061034391906139de565b61092c565b6040516103559190612f59565b60405180910390f35b61036661095f565b6040516103739190613a0b565b60405180910390f35b610384610965565b6040516103919190613a85565b60405180910390f35b6103b460048036038101906103af9190612f1d565b610989565b005b606060006103c484846109a7565b90506000806000806103d7858989610b1d565b935093509350935060006103ee3386868686610ce5565b9050806040516020016104019190613ac1565b604051602081830303815290604052965050505050505092915050565b60606000610469600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020610e63565b905080915050919050565b60006020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006104b68686868686610e78565b905095945050505050565b6000806104d033886006610f38565b8098508192505050610532818888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508761052c90613adc565b87610ce5565b91505095945050505050565b6040518060400160405280600181526020017f350000000000000000000000000000000000000000000000000000000000000081525081565b7f0000000000000000000000003caca7b48d0573d793d3b0279b5f0029180e83b681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000610604878787878787611101565b90509695505050505050565b610618611140565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610685576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067c90613b3b565b60405180910390fd5b600084849050905060005b8181101561076f578383828181106106ab576106aa613b5b565b5b90506020020160208101906106c09190612dda565b600660008888858181106106d7576106d6613b5b565b5b90506020020160208101906106ec91906139de565b60038111156106fe576106fd613b8a565b5b60038111156107105761070f613b8a565b5b815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808061076790613be8565b915050610690565b505050505050565b7f0000000000000000000000003caca7b48d0573d793d3b0279b5f0029180e83b673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610805576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107fc90613c7c565b60405180910390fd5b600061083289896108158a611169565b8961081f90613adc565b8761082a578861082d565b60005b610e78565b9050610894818a8a8a8a806000019061084b9190613cab565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508a8a8a8a6112e2565b505050505050505050565b600080600354600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915091509091565b60056020528060005260406000206000915090508060000160009054906101000a90046fffffffffffffffffffffffffffffffff16908060000160109054906101000a90046fffffffffffffffffffffffffffffffff16905082565b60066020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60035481565b7f0000000000000000000000002807b4ae232b624023f87d0e237a3b1bf200fd9981565b600061099782336006611510565b90506109a381836116cd565b5050565b60006018838360038181106109bf576109be613b5b565b5b9050013560f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c601084846002818110610a2257610a21613b5b565b5b9050013560f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c600885856001818110610a8557610a84613b5b565b5b9050013560f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c85856000818110610ae657610ae5613b5b565b5b9050013560f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916171717905092915050565b60006060610b29612d4e565b6000638b92696a60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916877bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610ba757610b9286866004908092610b8d93929190613d18565b6117ec565b80945081955082965083975050505050610cdc565b63b9f45adb60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916877bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610c2357610c0e86866004908092610c0993929190613d18565b611993565b80945081955082965083975050505050610cdb565b63a873882560e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916877bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610c9f57610c8a86866004908092610c8593929190613d18565b611b3a565b80945081955082965083975050505050610cda565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cd190613dc5565b60405180910390fd5b5b5b93509350935093565b6000610cfc8686610cf587611169565b8686610e78565b9050610d4f81600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611cfe90919063ffffffff16565b15610d8f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d8690613e31565b60405180910390fd5b610d9e81878787876006611d15565b610def81600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611ee790919063ffffffff16565b50808573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f73f079427211e7b93db86024054de0b3c4a076a36cf0f86d2c4bf0d112eb7f1d878787604051610e52939291906140ed565b60405180910390a495945050505050565b6060610e7182600001611efe565b9050919050565b6000610e878360000151611f5a565b15610efd576000610eb68460200151600081518110610ea957610ea8613b5b565b5b602002602001015161206b565b9050610ef5878787600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16148786611101565b915050610f2f565b8585858585604051602001610f16959493929190614141565b6040516020818303038152906040528051906020012090505b95945050505050565b6000806000600380811115610f5057610f4f613b8a565b5b905060005b8181116110f1576000816003811115610f7157610f70613b8a565b5b9050610f8e816003811115610f8957610f88613b8a565b5b61207c565b610f9857506110de565b6000866000836003811115610fb057610faf613b8a565b5b6003811115610fc257610fc1613b8a565b5b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050610ffc816120bd565b60006376474e6a60e01b8a8a60405160240161101992919061419b565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006110ba83836040518060400160405280601381526020017f4f70732e7072654372656174655461736b3a200000000000000000000000000081525061212f565b915050808060200190518101906110d191906141f0565b809b50819c505050505050505b80806110e990613be8565b915050610f55565b5085859250925050935093915050565b600086868686868660405160200161111e9695949392919061423f565b6040516020818303038152906040528051906020012090509695505050505050565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610354905090565b600060188260038151811061118157611180613b5b565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c6010836002815181106111e5576111e4613b5b565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c60088460018151811061124957611248613b5b565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c846000815181106112ab576112aa613b5b565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161717179050919050565b61133389600260008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611cfe90919063ffffffff16565b611372576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611369906142ec565b60405180910390fd5b816113c0578360038190555082600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b60006113d28a8a8a8a8a8760066121b9565b9050821561146e577f0000000000000000000000002807b4ae232b624023f87d0e237a3b1bf200fd9973ffffffffffffffffffffffffffffffffffffffff1663a3f1233e8a86886040518463ffffffff1660e01b81526004016114379392919061430c565b600060405180830381600087803b15801561145157600080fd5b505af1158015611465573d6000803e3d6000fd5b5050505061149a565b600360009055600460006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555b8773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16867fa458375b1282695a972870cbfbc4891a9d856b79d563d17667d171d87e0c527a8a8e866040516114fc93929190614343565b60405180910390a450505050505050505050565b60008060038081111561152657611525613b8a565b5b905060005b8181116116c157600081600381111561154757611546613b8a565b5b905061156481600381111561155f5761155e613b8a565b5b612261565b61156e57506116ae565b600085600083600381111561158657611585613b8a565b5b600381111561159857611597613b8a565b5b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506115d2816120bd565b60006314ae992660e01b89896040516024016115ef929190614381565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600061169083836040518060400160405280601381526020017f4f70732e70726543616e63656c5461736b3a200000000000000000000000000081525061212f565b915050808060200190518101906116a791906143aa565b9850505050505b80806116b990613be8565b91505061152b565b50839150509392505050565b61171e81600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611cfe90919063ffffffff16565b61175d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161175490614423565b60405180910390fd5b6117ae81600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206122d290919063ffffffff16565b507f44d83729a43f9c6046446df014d073dd242e0ad672071e9b292f31b669c25b0981836040516117e0929190614381565b60405180910390a15050565b600060606117f8612d4e565b60008060006060888881019061180e9190614458565b809450819550829650839a50505050506000600167ffffffffffffffff81111561183b5761183a612fe2565b5b6040519080825280602002602001820160405280156118695781602001602082028036833780820191505090505b50905060008160008151811061188257611881613b5b565b5b6020026020010190600381111561189c5761189b613b8a565b5b908160038111156118b0576118af613b8a565b5b815250506000600167ffffffffffffffff8111156118d1576118d0612fe2565b5b60405190808252806020026020018201604052801561190457816020015b60608152602001906001900390816118ef5790505b509050838360405160200161191a9291906144db565b6040516020818303038152906040528160008151811061193d5761193c613b5b565b5b6020026020010181905250604051806040016040528083815260200182815250965084604051602001611970919061452c565b604051602081830303815290604052975060009550505050505092959194509250565b6000606061199f612d4e565b6000806000606088888101906119b59190614547565b809850819550829650839750849b5050505050506000600167ffffffffffffffff8111156119e6576119e5612fe2565b5b604051908082528060200260200182016040528015611a145781602001602082028036833780820191505090505b509050600081600081518110611a2d57611a2c613b5b565b5b60200260200101906003811115611a4757611a46613b8a565b5b90816003811115611a5b57611a5a613b8a565b5b815250506000600167ffffffffffffffff811115611a7c57611a7b612fe2565b5b604051908082528060200260200182016040528015611aaf57816020015b6060815260200190600190039081611a9a5790505b5090508383604051602001611ac59291906144db565b60405160208183030381529060405281600081518110611ae857611ae7613b5b565b5b6020026020010181905250604051806040016040528083815260200182815250965084604051602001611b1b919061452c565b6040516020818303038152906040529750505050505092959194509250565b60006060611b46612d4e565b6000606080611b5588886122e9565b809550819650829750839950849a5050505050506000600267ffffffffffffffff811115611b8657611b85612fe2565b5b604051908082528060200260200182016040528015611bb45781602001602082028036833780820191505090505b509050600081600081518110611bcd57611bcc613b5b565b5b60200260200101906003811115611be757611be6613b8a565b5b90816003811115611bfb57611bfa613b8a565b5b81525050600181600181518110611c1557611c14613b5b565b5b60200260200101906003811115611c2f57611c2e613b8a565b5b90816003811115611c4357611c42613b8a565b5b815250506000600267ffffffffffffffff811115611c6457611c63612fe2565b5b604051908082528060200260200182016040528015611c9757816020015b6060815260200190600190039081611c825790505b5090508381600081518110611caf57611cae613b5b565b5b60200260200101819052508281600181518110611ccf57611cce613b5b565b5b602002602001018190525060405180604001604052808381526020018281525095505050505092959194509250565b6000611d0d83600001836123af565b905092915050565b60008260000151519050611d2d8184600001516123d2565b60005b81811015611edd57600084600001518281518110611d5157611d50613b5b565b5b60200260200101519050611d76816003811115611d7157611d70613b8a565b5b6124b1565b611d805750611eca565b6000846000836003811115611d9857611d97613b8a565b5b6003811115611daa57611da9613b8a565b5b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050611de4816120bd565b600063b0ccbdf060e01b8b8b8b8b8b602001518981518110611e0957611e08613b5b565b5b6020026020010151604051602401611e259594939291906145de565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050611ec482826040518060400160405280601281526020017f4f70732e6f6e4372656174655461736b3a20000000000000000000000000000081525061212f565b50505050505b8080611ed590613be8565b915050611d30565b5050505050505050565b6000611ef68360000183612522565b905092915050565b606081600001805480602002602001604051908101604052809291908181526020018280548015611f4e57602002820191906000526020600020905b815481526020019060010190808311611f3a575b50505050509050919050565b60008082519050600181148015611fb0575060006003811115611f8057611f7f613b8a565b5b83600081518110611f9457611f93613b5b565b5b60200260200101516003811115611fae57611fad613b8a565b5b145b806120515750600281148015612005575060006003811115611fd557611fd4613b8a565b5b83600081518110611fe957611fe8613b5b565b5b6020026020010151600381111561200357612002613b8a565b5b145b80156120505750600160038111156120205761201f613b8a565b5b8360018151811061203457612033613b5b565b5b6020026020010151600381111561204e5761204d613b8a565b5b145b5b15612060576001915050612066565b60009150505b919050565b600081805190602001209050919050565b60006002600381111561209257612091613b8a565b5b8260038111156120a5576120a4613b8a565b5b036120b357600190506120b8565b600090505b919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361212c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121239061468b565b60405180910390fd5b50565b600060608473ffffffffffffffffffffffffffffffffffffffff168460405161215891906146e7565b600060405180830381855af49150503d8060008114612193576040519150601f19603f3d011682016040523d82523d6000602084013e612198565b606091505b508092508193505050816121b1576121b08184612592565b5b935093915050565b6000806121c685846126f9565b90506121d6898989898986612836565b809750819850505061224287878a6040516020016121f5929190614746565b6040516020818303038152906040526000876040518060400160405280600a81526020017f4f70732e657865633a20000000000000000000000000000000000000000000008152506129a9565b5080925050612255898989898986612a43565b50979650505050505050565b60006001600381111561227757612276613b8a565b5b82600381111561228a57612289613b8a565b5b14806122ba5750600260038111156122a5576122a4613b8a565b5b8260038111156122b8576122b7613b8a565b5b145b156122c857600190506122cd565b600090505b919050565b60006122e18360000183612b89565b905092915050565b6000606060006060806000806000806000806000808e8e81019061230d919061479a565b97509750975097509750975097509750858560405160200161232f919061452c565b60405160208183030381529060405282612349578361234c565b60005b93508386866040516020016123629291906144db565b6040516020818303038152906040528b8b6040516020016123849291906139b5565b6040516020818303038152906040529c509c509c509c509c5050505050505050509295509295909350565b600080836001016000848152602001908152602001600020541415905092915050565b60018211156124ad5760005b6001836123eb919061486c565b8110156124ab5781818151811061240557612404613b5b565b5b6020026020010151600381111561241f5761241e613b8a565b5b8260018361242d91906148a0565b8151811061243e5761243d613b5b565b5b6020026020010151600381111561245857612457613b8a565b5b11612498576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161248f90614942565b60405180910390fd5b80806124a390613be8565b9150506123de565b505b5050565b6000600160038111156124c7576124c6613b8a565b5b8260038111156124da576124d9613b8a565b5b148061250a5750600260038111156124f5576124f4613b8a565b5b82600381111561250857612507613b8a565b5b145b15612518576001905061251d565b600090505b919050565b600061252e83836123af565b61258757826000018290806001815401808255809150506001900390600052602060002001600090919091909150558260000180549050836001016000848152602001908152602001600020819055506001905061258c565b600090505b92915050565b6004602083516125a29190614991565b0361269d576000826020015190506308c379a060e01b817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036126415760448301925081836040516020016125f69291906149fe565b6040516020818303038152906040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161263891906135de565b60405180910390fd5b816040516020016126529190614a6e565b6040516020818303038152906040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161269491906135de565b60405180910390fd5b806040516020016126ae9190614adc565b6040516020818303038152906040526040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126f091906135de565b60405180910390fd5b606060008351905060008167ffffffffffffffff81111561271d5761271c612fe2565b5b60405190808252806020026020018201604052801561274b5781602001602082028036833780820191505090505b50905060005b8281101561282a5784600087838151811061276f5761276e613b5b565b5b6020026020010151600381111561278957612788613b8a565b5b600381111561279b5761279a613b8a565b5b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168282815181106127dd576127dc613b5b565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050808061282290613be8565b915050612751565b50809250505092915050565b6000606060008451905060005b818110156129965761288086828151811061286157612860613b5b565b5b6020026020010151600381111561287b5761287a613b8a565b5b612c9d565b1561298357600063c10304f760e01b8b8b8b8b6040516024016128a69493929190614afe565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600061296187848151811061291d5761291c613b5b565b5b6020026020010151836040518060400160405280601181526020017f4f70732e7072654578656343616c6c3a2000000000000000000000000000000081525061212f565b915050808060200190518101906129789190614bba565b809a50819b50505050505b808061298e90613be8565b915050612843565b5086869250925050965096945050505050565b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516129d391906146e7565b60006040518083038185875af1925050503d8060008114612a10576040519150601f19603f3d011682016040523d82523d6000602084013e612a15565b606091505b50809250819350505081158015612a295750835b15612a3957612a388184612592565b5b9550959350505050565b60008151905060005b81811015612b7f57612a89848281518110612a6a57612a69613b5b565b5b60200260200101516003811115612a8457612a83613b8a565b5b612d0e565b15612b6c57600063b2db0b4160e01b89898989604051602401612aaf9493929190614afe565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050612b68848381518110612b2457612b23613b5b565b5b6020026020010151826040518060400160405280601281526020017f4f70732e706f73744578656343616c6c3a20000000000000000000000000000081525061212f565b5050505b8080612b7790613be8565b915050612a4c565b5050505050505050565b60008083600101600084815260200190815260200160002054905060008114612c91576000600182612bbb919061486c565b9050600060018660000180549050612bd3919061486c565b9050818114612c42576000866000018281548110612bf457612bf3613b5b565b5b9060005260206000200154905080876000018481548110612c1857612c17613b5b565b5b90600052602060002001819055508387600101600083815260200190815260200160002081905550505b85600001805480612c5657612c55614c16565b5b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050612c97565b60009150505b92915050565b600060016003811115612cb357612cb2613b8a565b5b826003811115612cc657612cc5613b8a565b5b1480612cf6575060026003811115612ce157612ce0613b8a565b5b826003811115612cf457612cf3613b8a565b5b145b15612d045760019050612d09565b600090505b919050565b6000600380811115612d2357612d22613b8a565b5b826003811115612d3657612d35613b8a565b5b03612d445760019050612d49565b600090505b919050565b604051806040016040528060608152602001606081525090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612da782612d7c565b9050919050565b612db781612d9c565b8114612dc257600080fd5b50565b600081359050612dd481612dae565b92915050565b600060208284031215612df057612def612d72565b5b6000612dfe84828501612dc5565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b612e4681612e33565b82525050565b6000612e588383612e3d565b60208301905092915050565b6000602082019050919050565b6000612e7c82612e07565b612e868185612e12565b9350612e9183612e23565b8060005b83811015612ec2578151612ea98882612e4c565b9750612eb483612e64565b925050600181019050612e95565b5085935050505092915050565b60006020820190508181036000830152612ee98184612e71565b905092915050565b612efa81612e33565b8114612f0557600080fd5b50565b600081359050612f1781612ef1565b92915050565b600060208284031215612f3357612f32612d72565b5b6000612f4184828501612f08565b91505092915050565b612f5381612d9c565b82525050565b6000602082019050612f6e6000830184612f4a565b92915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612fa981612f74565b8114612fb457600080fd5b50565b600081359050612fc681612fa0565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61301a82612fd1565b810181811067ffffffffffffffff8211171561303957613038612fe2565b5b80604052505050565b600061304c612d68565b90506130588282613011565b919050565b600080fd5b600080fd5b600067ffffffffffffffff82111561308257613081612fe2565b5b602082029050602081019050919050565b600080fd5b600481106130a557600080fd5b50565b6000813590506130b781613098565b92915050565b60006130d06130cb84613067565b613042565b905080838252602082019050602084028301858111156130f3576130f2613093565b5b835b8181101561311c578061310888826130a8565b8452602084019350506020810190506130f5565b5050509392505050565b600082601f83011261313b5761313a613062565b5b813561314b8482602086016130bd565b91505092915050565b600067ffffffffffffffff82111561316f5761316e612fe2565b5b602082029050602081019050919050565b600080fd5b600067ffffffffffffffff8211156131a05761319f612fe2565b5b6131a982612fd1565b9050602081019050919050565b82818337600083830152505050565b60006131d86131d384613185565b613042565b9050828152602081018484840111156131f4576131f3613180565b5b6131ff8482856131b6565b509392505050565b600082601f83011261321c5761321b613062565b5b813561322c8482602086016131c5565b91505092915050565b600061324861324384613154565b613042565b9050808382526020820190506020840283018581111561326b5761326a613093565b5b835b818110156132b257803567ffffffffffffffff8111156132905761328f613062565b5b80860161329d8982613207565b8552602085019450505060208101905061326d565b5050509392505050565b600082601f8301126132d1576132d0613062565b5b81356132e1848260208601613235565b91505092915050565b600060408284031215613300576132ff612fcc565b5b61330a6040613042565b9050600082013567ffffffffffffffff81111561332a5761332961305d565b5b61333684828501613126565b600083015250602082013567ffffffffffffffff81111561335a5761335961305d565b5b613366848285016132bc565b60208301525092915050565b600080600080600060a0868803121561338e5761338d612d72565b5b600061339c88828901612dc5565b95505060206133ad88828901612dc5565b94505060406133be88828901612fb7565b935050606086013567ffffffffffffffff8111156133df576133de612d77565b5b6133eb888289016132ea565b92505060806133fc88828901612dc5565b9150509295509295909350565b61341281612e33565b82525050565b600060208201905061342d6000830184613409565b92915050565b600080fd5b60008083601f84011261344e5761344d613062565b5b8235905067ffffffffffffffff81111561346b5761346a613433565b5b60208301915083600182028301111561348757613486613093565b5b9250929050565b600080fd5b6000604082840312156134a9576134a861348e565b5b81905092915050565b6000806000806000608086880312156134ce576134cd612d72565b5b60006134dc88828901612dc5565b955050602086013567ffffffffffffffff8111156134fd576134fc612d77565b5b61350988828901613438565b9450945050604086013567ffffffffffffffff81111561352c5761352b612d77565b5b61353888828901613493565b925050606061354988828901612dc5565b9150509295509295909350565b600081519050919050565b600082825260208201905092915050565b60005b83811015613590578082015181840152602081019050613575565b8381111561359f576000848401525b50505050565b60006135b082613556565b6135ba8185613561565b93506135ca818560208601613572565b6135d381612fd1565b840191505092915050565b600060208201905081810360008301526135f881846135a5565b905092915050565b600061360b82612d7c565b9050919050565b61361b81613600565b82525050565b60006020820190506136366000830184613612565b92915050565b60008115159050919050565b6136518161363c565b811461365c57600080fd5b50565b60008135905061366e81613648565b92915050565b60008060008060008060c0878903121561369157613690612d72565b5b600061369f89828a01612dc5565b96505060206136b089828a01612dc5565b95505060406136c189828a01612fb7565b94505060606136d289828a0161365f565b93505060806136e389828a01612dc5565b92505060a06136f489828a01612f08565b9150509295509295509295565b60008083601f84011261371757613716613062565b5b8235905067ffffffffffffffff81111561373457613733613433565b5b6020830191508360208202830111156137505761374f613093565b5b9250929050565b60008083601f84011261376d5761376c613062565b5b8235905067ffffffffffffffff81111561378a57613789613433565b5b6020830191508360208202830111156137a6576137a5613093565b5b9250929050565b600080600080604085870312156137c7576137c6612d72565b5b600085013567ffffffffffffffff8111156137e5576137e4612d77565b5b6137f187828801613701565b9450945050602085013567ffffffffffffffff81111561381457613813612d77565b5b61382087828801613757565b925092505092959194509250565b6000819050919050565b6138418161382e565b811461384c57600080fd5b50565b60008135905061385e81613838565b92915050565b600080600080600080600080610100898b03121561388557613884612d72565b5b60006138938b828c01612dc5565b98505060206138a48b828c01612dc5565b975050604089013567ffffffffffffffff8111156138c5576138c4612d77565b5b6138d18b828c01613207565b965050606089013567ffffffffffffffff8111156138f2576138f1612d77565b5b6138fe8b828c01613493565b955050608061390f8b828c0161384f565b94505060a06139208b828c01612dc5565b93505060c06139318b828c0161365f565b92505060e06139428b828c0161365f565b9150509295985092959890939650565b61395b8161382e565b82525050565b60006040820190506139766000830185613952565b6139836020830184612f4a565b9392505050565b60006fffffffffffffffffffffffffffffffff82169050919050565b6139af8161398a565b82525050565b60006040820190506139ca60008301856139a6565b6139d760208301846139a6565b9392505050565b6000602082840312156139f4576139f3612d72565b5b6000613a02848285016130a8565b91505092915050565b6000602082019050613a206000830184613952565b92915050565b6000819050919050565b6000613a4b613a46613a4184612d7c565b613a26565b612d7c565b9050919050565b6000613a5d82613a30565b9050919050565b6000613a6f82613a52565b9050919050565b613a7f81613a64565b82525050565b6000602082019050613a9a6000830184613a76565b92915050565b6000819050919050565b613abb613ab682612e33565b613aa0565b82525050565b6000613acd8284613aaa565b60208201915081905092915050565b6000613ae836836132ea565b9050919050565b7f4e4f545f415554484f52495a4544000000000000000000000000000000000000600082015250565b6000613b25600e83613561565b9150613b3082613aef565b602082019050919050565b60006020820190508181036000830152613b5481613b18565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613bf38261382e565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613c2557613c24613bb9565b5b600182019050919050565b7f47656c61746f666965643a204f6e6c792067656c61746f000000000000000000600082015250565b6000613c66601783613561565b9150613c7182613c30565b602082019050919050565b60006020820190508181036000830152613c9581613c59565b9050919050565b600080fd5b600080fd5b600080fd5b60008083356001602003843603038112613cc857613cc7613c9c565b5b80840192508235915067ffffffffffffffff821115613cea57613ce9613ca1565b5b602083019250602082023603831315613d0657613d05613ca6565b5b509250929050565b600080fd5b600080fd5b60008085851115613d2c57613d2b613d0e565b5b83861115613d3d57613d3c613d13565b5b6001850283019150848603905094509492505050565b7f4f70732e6372656174655461736b3a2046756e6374696f6e206e6f7420666f7560008201527f6e64000000000000000000000000000000000000000000000000000000000000602082015250565b6000613daf602283613561565b9150613dba82613d53565b604082019050919050565b60006020820190508181036000830152613dde81613da2565b9050919050565b7f4f70732e6372656174655461736b3a204475706c6963617465207461736b0000600082015250565b6000613e1b601e83613561565b9150613e2682613de5565b602082019050919050565b60006020820190508181036000830152613e4a81613e0e565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000613e7882613e51565b613e828185613e5c565b9350613e92818560208601613572565b613e9b81612fd1565b840191505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60048110613ee357613ee2613b8a565b5b50565b6000819050613ef482613ed2565b919050565b6000613f0482613ee6565b9050919050565b613f1481613ef9565b82525050565b6000613f268383613f0b565b60208301905092915050565b6000602082019050919050565b6000613f4a82613ea6565b613f548185613eb1565b9350613f5f83613ec2565b8060005b83811015613f90578151613f778882613f1a565b9750613f8283613f32565b925050600181019050613f63565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b6000613fe582613e51565b613fef8185613fc9565b9350613fff818560208601613572565b61400881612fd1565b840191505092915050565b600061401f8383613fda565b905092915050565b6000602082019050919050565b600061403f82613f9d565b6140498185613fa8565b93508360208202850161405b85613fb9565b8060005b8581101561409757848403895281516140788582614013565b945061408383614027565b925060208a0199505060018101905061405f565b50829750879550505050505092915050565b600060408301600083015184820360008601526140c68282613f3f565b915050602083015184820360208601526140e08282614034565b9150508091505092915050565b600060608201905081810360008301526141078186613e6d565b9050818103602083015261411b81856140a9565b905061412a6040830184612f4a565b949350505050565b61413b81612f74565b82525050565b600060a0820190506141566000830188612f4a565b6141636020830187612f4a565b6141706040830186614132565b818103606083015261418281856140a9565b90506141916080830184612f4a565b9695505050505050565b60006040820190506141b06000830185612f4a565b6141bd6020830184612f4a565b9392505050565b6141cd81613600565b81146141d857600080fd5b50565b6000815190506141ea816141c4565b92915050565b6000806040838503121561420757614206612d72565b5b6000614215858286016141db565b9250506020614226858286016141db565b9150509250929050565b6142398161363c565b82525050565b600060c0820190506142546000830189612f4a565b6142616020830188612f4a565b61426e6040830187614132565b61427b6060830186614230565b6142886080830185612f4a565b61429560a0830184613409565b979650505050505050565b7f4f70732e657865633a205461736b206e6f7420666f756e640000000000000000600082015250565b60006142d6601883613561565b91506142e1826142a0565b602082019050919050565b60006020820190508181036000830152614305816142c9565b9050919050565b60006060820190506143216000830186612f4a565b61432e6020830185612f4a565b61433b6040830184613952565b949350505050565b6000606082019050818103600083015261435d8186613e6d565b905061436c6020830185613409565b6143796040830184614230565b949350505050565b60006040820190506143966000830185613409565b6143a36020830184612f4a565b9392505050565b6000602082840312156143c0576143bf612d72565b5b60006143ce848285016141db565b91505092915050565b7f4f70732e63616e63656c5461736b3a205461736b206e6f7420666f756e640000600082015250565b600061440d601e83613561565b9150614418826143d7565b602082019050919050565b6000602082019050818103600083015261443c81614400565b9050919050565b600081359050614452816141c4565b92915050565b6000806000806080858703121561447257614471612d72565b5b600061448087828801614443565b945050602061449187828801612fb7565b93505060406144a287828801614443565b925050606085013567ffffffffffffffff8111156144c3576144c2612d77565b5b6144cf87828801613207565b91505092959194509250565b60006040820190506144f06000830185612f4a565b81810360208301526145028184613e6d565b90509392505050565b6000819050919050565b61452661452182612f74565b61450b565b82525050565b60006145388284614515565b60048201915081905092915050565b600080600080600060a0868803121561456357614562612d72565b5b600061457188828901614443565b955050602061458288828901612fb7565b945050604061459388828901614443565b935050606086013567ffffffffffffffff8111156145b4576145b3612d77565b5b6145c088828901613207565b92505060806145d188828901614443565b9150509295509295909350565b600060a0820190506145f36000830188613409565b6146006020830187612f4a565b61460d6040830186612f4a565b818103606083015261461f8185613e6d565b905081810360808301526146338184613e6d565b90509695505050505050565b7f4f70732e5f6d6f64756c65496e697469616c697365643a204e6f7420696e6974600082015250565b6000614675602083613561565b91506146808261463f565b602082019050919050565b600060208201905081810360008301526146a481614668565b9050919050565b600081905092915050565b60006146c182613e51565b6146cb81856146ab565b93506146db818560208601613572565b80840191505092915050565b60006146f382846146b6565b915081905092915050565b60008160601b9050919050565b6000614716826146fe565b9050919050565b60006147288261470b565b9050919050565b61474061473b82612d9c565b61471d565b82525050565b600061475282856146b6565b915061475e828461472f565b6014820191508190509392505050565b6147778161398a565b811461478257600080fd5b50565b6000813590506147948161476e565b92915050565b600080600080600080600080610100898b0312156147bb576147ba612d72565b5b60006147c98b828c01614785565b98505060206147da8b828c01614785565b97505060406147eb8b828c01614443565b96505060606147fc8b828c01612fb7565b955050608061480d8b828c01614443565b94505060a089013567ffffffffffffffff81111561482e5761482d612d77565b5b61483a8b828c01613207565b93505060c061484b8b828c01614443565b92505060e061485c8b828c0161365f565b9150509295985092959890939650565b60006148778261382e565b91506148828361382e565b92508282101561489557614894613bb9565b5b828203905092915050565b60006148ab8261382e565b91506148b68361382e565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156148eb576148ea613bb9565b5b828201905092915050565b7f4f70732e5f76616c69644d6f64756c65733a20417363206f6e6c790000000000600082015250565b600061492c601b83613561565b9150614937826148f6565b602082019050919050565b6000602082019050818103600083015261495b8161491f565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061499c8261382e565b91506149a78361382e565b9250826149b7576149b6614962565b5b828206905092915050565b600081905092915050565b60006149d882613556565b6149e281856149c2565b93506149f2818560208601613572565b80840191505092915050565b6000614a0a82856149cd565b9150614a1682846149cd565b91508190509392505050565b7f4e6f4572726f7253656c6563746f720000000000000000000000000000000000600082015250565b6000614a58600f836149c2565b9150614a6382614a22565b600f82019050919050565b6000614a7a82846149cd565b9150614a8582614a4b565b915081905092915050565b7f556e657870656374656452657475726e64617461000000000000000000000000600082015250565b6000614ac66014836149c2565b9150614ad182614a90565b601482019050919050565b6000614ae882846149cd565b9150614af382614ab9565b915081905092915050565b6000608082019050614b136000830187613409565b614b206020830186612f4a565b614b2d6040830185612f4a565b8181036060830152614b3f8184613e6d565b905095945050505050565b6000614b5d614b5884613185565b613042565b905082815260208101848484011115614b7957614b78613180565b5b614b84848285613572565b509392505050565b600082601f830112614ba157614ba0613062565b5b8151614bb1848260208601614b4a565b91505092915050565b60008060408385031215614bd157614bd0612d72565b5b6000614bdf858286016141db565b925050602083015167ffffffffffffffff811115614c0057614bff612d77565b5b614c0c85828601614b8c565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220798174a7019cfbba358b2c4e8e70f4aa3e3b9721532742d957737708a0bbf8c364736f6c634300080e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000003caca7b48d0573d793d3b0279b5f0029180e83b60000000000000000000000002807b4ae232b624023f87d0e237a3b1bf200fd99
-----Decoded View---------------
Arg [0] : _gelato (address): 0x3CACa7b48D0573D793d3b0279b5F0029180E83b6
Arg [1] : _taskTreasury (address): 0x2807B4aE232b624023f87d0e237A3B1bf200Fd99
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000003caca7b48d0573d793d3b0279b5f0029180e83b6
Arg [1] : 0000000000000000000000002807b4ae232b624023f87d0e237a3b1bf200fd99
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
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.