Source Code
Overview
CELO Balance
0 CELO
More Info
ContractCreator
Multichain Info
N/A
Latest 13 internal transactions
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
20605756 | 403 days ago | 0 CELO | ||||
20605584 | 403 days ago | 0 CELO | ||||
20605579 | 403 days ago | 0 CELO | ||||
20605509 | 403 days ago | 0 CELO | ||||
20605253 | 403 days ago | 0 CELO | ||||
20605182 | 403 days ago | 0 CELO | ||||
20605140 | 403 days ago | 0 CELO | ||||
20605094 | 403 days ago | 0 CELO | ||||
20603904 | 403 days ago | 0 CELO | ||||
20603789 | 403 days ago | 0 CELO | ||||
20603743 | 403 days ago | 0 CELO | ||||
20603701 | 403 days ago | 0 CELO | ||||
20484048 | 410 days ago | 0 CELO |
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:
EscrowFactory
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import '@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol'; import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol'; import './interfaces/IStaking.sol'; import './Escrow.sol'; contract EscrowFactory is OwnableUpgradeable, UUPSUpgradeable { // all Escrows will have this duration. uint256 constant STANDARD_DURATION = 8640000; string constant ERROR_ZERO_ADDRESS = 'EscrowFactory: Zero Address'; uint256 public counter; mapping(address => uint256) public escrowCounters; address public lastEscrow; address public staking; event Launched(address token, address escrow); event LaunchedV2(address token, address escrow, string jobRequesterId); /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize(address _staking) external payable virtual initializer { __Ownable_init_unchained(); __EscrowFactory_init_unchained(_staking); } function __EscrowFactory_init_unchained( address _staking ) internal onlyInitializing { require(_staking != address(0), ERROR_ZERO_ADDRESS); staking = _staking; } function createEscrow( address token, address[] memory trustedHandlers, string memory jobRequesterId ) public returns (address) { bool hasAvailableStake = IStaking(staking).hasAvailableStake( msg.sender ); require( hasAvailableStake == true, 'Needs to stake HMT tokens to create an escrow.' ); Escrow escrow = new Escrow( token, msg.sender, payable(msg.sender), STANDARD_DURATION, trustedHandlers ); counter++; escrowCounters[address(escrow)] = counter; lastEscrow = address(escrow); emit LaunchedV2(token, lastEscrow, jobRequesterId); return lastEscrow; } function hasEscrow(address _address) public view returns (bool) { return escrowCounters[_address] != 0; } // solhint-disable-next-line no-empty-blocks function _authorizeUpgrade(address) internal override onlyOwner {} /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[46] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822ProxiableUpgradeable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.0; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.8.3._ */ interface IERC1967Upgradeable { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeaconUpgradeable { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeaconUpgradeable.sol"; import "../../interfaces/IERC1967Upgradeable.sol"; import "../../interfaces/draft-IERC1822Upgradeable.sol"; import "../../utils/AddressUpgradeable.sol"; import "../../utils/StorageSlotUpgradeable.sol"; import "../utils/Initializable.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ */ abstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable { function __ERC1967Upgrade_init() internal onlyInitializing { } function __ERC1967Upgrade_init_unchained() internal onlyInitializing { } // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { AddressUpgradeable.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data); } } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.0; import "../../interfaces/draft-IERC1822Upgradeable.sol"; import "../ERC1967/ERC1967UpgradeUpgradeable.sol"; import "./Initializable.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable { function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); _; } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeTo(address newImplementation) public virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or 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 { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 /// @solidity memory-safe-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/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlotUpgradeable { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); /** * @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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.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; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ 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)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ 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"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @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"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @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). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // 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 cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or 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 { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; import '@openzeppelin/contracts/security/ReentrancyGuard.sol'; import './interfaces/IEscrow.sol'; import './utils/SafeMath.sol'; contract Escrow is IEscrow, ReentrancyGuard { using SafeMath for uint256; bytes4 private constant FUNC_SELECTOR_BALANCE_OF = bytes4(keccak256('balanceOf(address)')); string constant ERROR_ZERO_ADDRESS = 'Escrow: zero address'; uint256 private constant BULK_MAX_VALUE = 1e9 * (10 ** 18); uint32 private constant BULK_MAX_COUNT = 100; event TrustedHandlerAdded(address _handler); event IntermediateStorage(string _url, string _hash); event Pending(string manifest, string hash); event BulkTransfer( uint256 indexed _txId, address[] _recipients, uint256[] _amounts, bool _isPartial ); event Cancelled(); event Completed(); EscrowStatuses public override status; address public reputationOracle; address public recordingOracle; address public exchangeOracle; address public launcher; address payable public canceler; address public escrowFactory; uint8 public reputationOracleFeePercentage; uint8 public recordingOracleFeePercentage; uint8 public exchangeOracleFeePercentage; address public token; string public manifestUrl; string public manifestHash; string public intermediateResultsUrl; string public finalResultsUrl; string public finalResultsHash; uint256 public duration; mapping(address => bool) public areTrustedHandlers; constructor( address _token, address _launcher, address payable _canceler, uint256 _duration, address[] memory _handlers ) { require(_token != address(0), ERROR_ZERO_ADDRESS); require(_canceler != address(0), ERROR_ZERO_ADDRESS); token = _token; status = EscrowStatuses.Launched; duration = _duration.add(block.timestamp); // solhint-disable-line not-rely-on-time launcher = _launcher; canceler = _canceler; escrowFactory = msg.sender; areTrustedHandlers[_launcher] = true; areTrustedHandlers[_canceler] = true; _addTrustedHandlers(_handlers); } function getBalance() public view returns (uint256) { (bool success, bytes memory returnData) = token.staticcall( abi.encodeWithSelector(FUNC_SELECTOR_BALANCE_OF, address(this)) ); if (success) { return abi.decode(returnData, (uint256)); } return 0; } function addTrustedHandlers( address[] memory _handlers ) public override trusted { _addTrustedHandlers(_handlers); } function _addTrustedHandlers(address[] memory _handlers) internal { for (uint256 i = 0; i < _handlers.length; i++) { require(_handlers[i] != address(0), ERROR_ZERO_ADDRESS); areTrustedHandlers[_handlers[i]] = true; emit TrustedHandlerAdded(_handlers[i]); } } // The escrower puts the Token in the contract without an agentless // and assigsn a reputation oracle to payout the bounty of size of the // amount specified function setup( address _reputationOracle, address _recordingOracle, address _exchangeOracle, uint8 _reputationOracleFeePercentage, uint8 _recordingOracleFeePercentage, uint8 _exchangeOracleFeePercentage, string memory _url, string memory _hash ) external override trusted notExpired { require( _reputationOracle != address(0), 'Invalid reputation oracle address' ); require( _recordingOracle != address(0), 'Invalid recording oracle address' ); require( _exchangeOracle != address(0), 'Invalid exchange oracle address' ); uint256 _totalFeePercentage = uint256(_reputationOracleFeePercentage) + uint256(_recordingOracleFeePercentage) + uint256(_exchangeOracleFeePercentage); require(_totalFeePercentage <= 100, 'Percentage out of bounds'); require( status == EscrowStatuses.Launched, 'Escrow not in Launched status state' ); reputationOracle = _reputationOracle; recordingOracle = _recordingOracle; exchangeOracle = _exchangeOracle; reputationOracleFeePercentage = _reputationOracleFeePercentage; recordingOracleFeePercentage = _recordingOracleFeePercentage; exchangeOracleFeePercentage = _exchangeOracleFeePercentage; manifestUrl = _url; manifestHash = _hash; status = EscrowStatuses.Pending; emit Pending(manifestUrl, manifestHash); } function abort() external override trusted notComplete notPaid { if (getBalance() != 0) { cancel(); } selfdestruct(canceler); } function cancel() public override trusted notBroke notComplete notPaid nonReentrant returns (bool) { _safeTransfer(canceler, getBalance()); status = EscrowStatuses.Cancelled; emit Cancelled(); return true; } function complete() external override notExpired trustedOrReputationOracle { require(status == EscrowStatuses.Paid, 'Escrow not in Paid state'); status = EscrowStatuses.Complete; emit Completed(); } function storeResults( string memory _url, string memory _hash ) external override trustedOrRecordingOracle notExpired { require( status == EscrowStatuses.Pending || status == EscrowStatuses.Partial, 'Escrow not in Pending or Partial status state' ); require(bytes(_url).length != 0, "URL can't be empty"); require(bytes(_hash).length != 0, "Hash can't be empty"); intermediateResultsUrl = _url; emit IntermediateStorage(_url, _hash); } /** * @dev Performs bulk payout to multiple workers * Escrow needs to be complted / cancelled, so that it can be paid out. * Every recipient is paid with the amount after reputation and recording oracle fees taken out. * If the amount is less than the fee, the recipient is not paid. * If the fee is zero, reputation, and recording oracle are not paid. * Payout will fail if any of the transaction fails. * If the escrow is fully paid out, meaning that the balance of the escrow is 0, it'll set as Paid. * If the escrow is partially paid out, meaning that the escrow still has remaining balance, it'll set as Partial. * This contract is only callable if the contract is not broke, not launched, not paid, not expired, by trusted parties. * * @param _recipients Array of recipients * @param _amounts Array of amounts to be paid to each recipient. * @param _url URL storing results as transaction details * @param _hash Hash of the results * @param _txId Transaction ID */ function bulkPayOut( address[] memory _recipients, uint256[] memory _amounts, string memory _url, string memory _hash, uint256 _txId ) external override trustedOrReputationOracle notBroke notLaunched notPaid notExpired nonReentrant { require( _recipients.length == _amounts.length, "Amount of recipients and values don't match" ); require(_amounts.length > 0, 'Amounts should not be empty'); require(_recipients.length < BULK_MAX_COUNT, 'Too many recipients'); require( status != EscrowStatuses.Complete && status != EscrowStatuses.Cancelled, 'Invalid status' ); uint256 balance = getBalance(); uint256 aggregatedBulkAmount = 0; for (uint256 i; i < _amounts.length; i++) { require(_amounts[i] > 0, 'Amount should be greater than zero'); aggregatedBulkAmount = aggregatedBulkAmount.add(_amounts[i]); } require(aggregatedBulkAmount < BULK_MAX_VALUE, 'Bulk value too high'); require(aggregatedBulkAmount <= balance, 'Not enough balance'); require(bytes(_url).length != 0, "URL can't be empty"); require(bytes(_hash).length != 0, "Hash can't be empty"); finalResultsUrl = _url; finalResultsHash = _hash; ( uint256[] memory finalAmounts, uint256 reputationOracleFee, uint256 recordingOracleFee, uint256 exchangeOracleFee ) = finalizePayouts(_amounts); for (uint256 i = 0; i < _recipients.length; ++i) { if (finalAmounts[i] > 0) { _safeTransfer(_recipients[i], finalAmounts[i]); } } if (reputationOracleFee > 0) { _safeTransfer(reputationOracle, reputationOracleFee); } if (recordingOracleFee > 0) { _safeTransfer(recordingOracle, recordingOracleFee); } if (exchangeOracleFee > 0) { _safeTransfer(exchangeOracle, exchangeOracleFee); } balance = getBalance(); bool isPartial; if (balance == 0) { status = EscrowStatuses.Paid; isPartial = false; } else { status = EscrowStatuses.Partial; isPartial = true; } emit BulkTransfer(_txId, _recipients, finalAmounts, isPartial); } function finalizePayouts( uint256[] memory _amounts ) internal view returns (uint256[] memory, uint256, uint256, uint256) { uint256[] memory finalAmounts = new uint256[](_amounts.length); uint256 reputationOracleFee = 0; uint256 recordingOracleFee = 0; uint256 exchangeOracleFee = 0; for (uint256 j; j < _amounts.length; j++) { uint256 amount = _amounts[j]; uint256 amountFee = 0; { uint256 singleReputationOracleFee = uint256( reputationOracleFeePercentage ).mul(amount).div(100); reputationOracleFee = reputationOracleFee.add( singleReputationOracleFee ); amountFee = amountFee.add(singleReputationOracleFee); } { uint256 singleRecordingOracleFee = uint256( recordingOracleFeePercentage ).mul(_amounts[j]).div(100); recordingOracleFee = recordingOracleFee.add( singleRecordingOracleFee ); amountFee = amountFee.add(singleRecordingOracleFee); } { uint256 singleExchangeOracleFee = uint256( exchangeOracleFeePercentage ).mul(_amounts[j]).div(100); exchangeOracleFee = exchangeOracleFee.add( singleExchangeOracleFee ); amountFee = amountFee.add(singleExchangeOracleFee); } finalAmounts[j] = amount.sub(amountFee); } return ( finalAmounts, reputationOracleFee, recordingOracleFee, exchangeOracleFee ); } function _safeTransfer(address to, uint256 value) internal { SafeERC20.safeTransfer(IERC20(token), to, value); } modifier trusted() { require(areTrustedHandlers[msg.sender], 'Address calling not trusted'); _; } modifier trustedOrReputationOracle() { require( areTrustedHandlers[msg.sender] || msg.sender == reputationOracle, 'Address calling not trusted' ); _; } modifier trustedOrRecordingOracle() { require( areTrustedHandlers[msg.sender] || msg.sender == recordingOracle, 'Address calling not trusted' ); _; } modifier notBroke() { require(getBalance() != 0, 'Token contract out of funds'); _; } modifier notComplete() { require( status != EscrowStatuses.Complete, 'Escrow in Complete status state' ); _; } modifier notPaid() { require(status != EscrowStatuses.Paid, 'Escrow in Paid status state'); _; } modifier notLaunched() { require( status != EscrowStatuses.Launched, 'Escrow in Launched status state' ); _; } modifier notExpired() { require(duration > block.timestamp, 'Contract expired'); // solhint-disable-line not-rely-on-time _; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; interface IEscrow { enum EscrowStatuses { Launched, Pending, Partial, Paid, Complete, Cancelled } function status() external view returns (EscrowStatuses); function addTrustedHandlers(address[] memory _handlers) external; function setup( address _reputationOracle, address _recordingOracle, address _exchangeOracle, uint8 _reputationOracleFeePercentage, uint8 _recordingOracleFeePercentage, uint8 _exchangeOracleFeePercentage, string memory _url, string memory _hash ) external; function abort() external; function cancel() external returns (bool); function complete() external; function storeResults(string memory _url, string memory _hash) external; function bulkPayOut( address[] memory _recipients, uint256[] memory _amounts, string memory _url, string memory _hash, uint256 _txId ) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import '../libs/Stakes.sol'; interface IStaking { /** * @dev Possible states an allocation can be * States: * - Null = Staker == address(0) * - Pending = not Null && tokens > 0 && escrowAddress status == Pending * - Active = Pending && escrowAddress status == Launched * - Closed = Active && closedAt != 0 * - Completed = Closed && closedAt && escrowAddress status == Complete */ enum AllocationState { Null, Pending, Active, Closed, Completed } /** * @dev Possible sort fields * Fields: * - None = Do not sort * - Stake = Sort by stake amount */ enum SortField { None, Stake } /** * @dev Allocate HMT tokens for the purpose of serving queries of a subgraph deployment * An allocation is created in the allocate() function and consumed in claim() */ struct Allocation { address escrowAddress; address staker; uint256 tokens; // Tokens allocated to a escrowAddress uint256 createdAt; // Time when allocation was created uint256 closedAt; // Time when allocation was closed } function rewardPool() external view returns (address); function setMinimumStake(uint256 _minimumStake) external; function setLockPeriod(uint32 _lockPeriod) external; function setRewardPool(address _rewardPool) external; function isAllocation(address _escrowAddress) external view returns (bool); function hasStake(address _indexer) external view returns (bool); function hasAvailableStake(address _indexer) external view returns (bool); function getAllocation( address _escrowAddress ) external view returns (Allocation memory); function getAllocationState( address _escrowAddress ) external view returns (AllocationState); function getStakedTokens(address _staker) external view returns (uint256); function getStaker( address _staker ) external view returns (Stakes.Staker memory); function stake(uint256 _tokens) external; function unstake(uint256 _tokens) external; function withdraw() external; function slash( address _slasher, address _staker, address _escrowAddress, uint256 _tokens ) external; function allocate(address escrowAddress, uint256 _tokens) external; function closeAllocation(address _escrowAddress) external; function getListOfStakers() external view returns (address[] memory, Stakes.Staker[] memory); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import '../utils/SafeMath.sol'; import '../utils/Math.sol'; /** * @title Structures, methods and data are available to manage the staker state. */ library Stakes { using SafeMath for uint256; using Stakes for Stakes.Staker; struct Staker { uint256 tokensStaked; // Tokens staked by the Staker uint256 tokensAllocated; // Tokens allocated for jobs uint256 tokensLocked; // Tokens locked for withdrawal uint256 tokensLockedUntil; // Tokens locked until time } /** * @dev Deposit tokens to the staker stake. * @param stake Staker struct * @param _tokens Amount of tokens to deposit */ function deposit(Stakes.Staker storage stake, uint256 _tokens) internal { stake.tokensStaked = stake.tokensStaked.add(_tokens); } /** * @dev Release tokens from the staker stake. * @param stake Staker struct * @param _tokens Amount of tokens to release */ function release(Stakes.Staker storage stake, uint256 _tokens) internal { stake.tokensStaked = stake.tokensStaked.sub(_tokens); } /** * @dev Add tokens from the main stack to tokensAllocated. * @param stake Staker struct * @param _tokens Amount of tokens to allocate */ function allocate(Stakes.Staker storage stake, uint256 _tokens) internal { stake.tokensAllocated = stake.tokensAllocated.add(_tokens); } /** * @dev Unallocate tokens from a escrowAddress back to the main stack. * @param stake Staker struct * @param _tokens Amount of tokens to unallocate */ function unallocate(Stakes.Staker storage stake, uint256 _tokens) internal { stake.tokensAllocated = stake.tokensAllocated.sub(_tokens); } /** * @dev Lock tokens until a lock period pass. * @param stake Staker struct * @param _tokens Amount of tokens to unstake * @param _period Period in blocks that need to pass before withdrawal */ function lockTokens( Stakes.Staker storage stake, uint256 _tokens, uint256 _period ) internal { uint256 lockingPeriod = _period; if (stake.tokensLocked > 0) { lockingPeriod = Math.weightedAverage( Math.diffOrZero(stake.tokensLockedUntil, block.number), // Remaining lock period stake.tokensLocked, _period, _tokens ); } stake.tokensLocked = stake.tokensLocked.add(_tokens); stake.tokensLockedUntil = block.number.add(lockingPeriod); } /** * @dev Unlock tokens. * @param stake Staker struct * @param _tokens Amount of tokens to unkock */ function unlockTokens( Stakes.Staker storage stake, uint256 _tokens ) internal { stake.tokensLocked = stake.tokensLocked.sub(_tokens); if (stake.tokensLocked == 0) { stake.tokensLockedUntil = 0; } } /** * @dev Return all tokens available for withdrawal. * @param stake Staker struct * @return Amount of tokens available for withdrawal */ function withdrawTokens( Stakes.Staker storage stake ) internal returns (uint256) { uint256 tokensToWithdraw = stake.tokensWithdrawable(); if (tokensToWithdraw > 0) { stake.unlockTokens(tokensToWithdraw); stake.release(tokensToWithdraw); } return tokensToWithdraw; } /** * @dev Return all tokens available in stake. * @param stake Staker struct * @return Token amount */ function tokensAvailable( Stakes.Staker memory stake ) internal pure returns (uint256) { return stake.tokensStaked.sub(stake.tokensUsed()); } /** * @dev Return all tokens used in allocations and locked for withdrawal. * @param stake Staker struct * @return Token amount */ function tokensUsed( Stakes.Staker memory stake ) internal pure returns (uint256) { return stake.tokensAllocated.add(stake.tokensLocked); } /** * @dev Return the amount of tokens staked which are not locked. * @param stake Staker struct * @return Token amount */ function tokensSecureStake( Stakes.Staker memory stake ) internal pure returns (uint256) { return stake.tokensStaked.sub(stake.tokensLocked); } /** * @dev Tokens available for withdrawal after lock period. * @param stake Staker struct * @return Token amount */ function tokensWithdrawable( Stakes.Staker memory stake ) internal view returns (uint256) { if ( stake.tokensLockedUntil == 0 || block.number < stake.tokensLockedUntil ) { return 0; } return stake.tokensLocked; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import './SafeMath.sol'; /** * @title Math Library * @notice A collection of functions to perform math operations */ library Math { using SafeMath for uint256; enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Calculates the weighted average of two values pondering each of these * values based on configured weights. The contribution of each value N is * weightN/(weightA + weightB). * @param valueA The amount for value A * @param weightA The weight to use for value A * @param valueB The amount for value B * @param weightB The weight to use for value B */ function weightedAverage( uint256 valueA, uint256 weightA, uint256 valueB, uint256 weightB ) internal pure returns (uint256) { return valueA.mul(weightA).add(valueB.mul(weightB)).div( weightA.add(weightB) ); } /** * @dev Returns the difference between two numbers or zero if negative. */ function diffOrZero(uint256 x, uint256 y) internal pure returns (uint256) { return (x > y) ? x.sub(y) : 0; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10( uint256 value, Rounding rounding ) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256( uint256 value, Rounding rounding ) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, 'SafeMath: addition overflow'); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, 'SafeMath: subtraction overflow'); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, 'SafeMath: multiplication overflow'); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, 'SafeMath: division by zero'); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, 'SafeMath: modulo by zero'); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
{ "optimizer": { "enabled": true, "runs": 1000000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"escrow","type":"address"}],"name":"Launched","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"escrow","type":"address"},{"indexed":false,"internalType":"string","name":"jobRequesterId","type":"string"}],"name":"LaunchedV2","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"counter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address[]","name":"trustedHandlers","type":"address[]"},{"internalType":"string","name":"jobRequesterId","type":"string"}],"name":"createEscrow","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"escrowCounters","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"hasEscrow","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staking","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"lastEscrow","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"staking","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
60a06040523060805234801561001457600080fd5b5061001d610022565b6100e1565b600054610100900460ff161561008e5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146100df576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6080516153236200011960003960008181610336015281816103ec01528181610549015281816105fb015261074b01526153236000f3fe608060405260043610620000e35760003560e01c806361bc221a11620000895780638da5cb5b11620000605780638da5cb5b1462000284578063979530e614620002b1578063c4d66de814620002e2578063f2fde38b14620002f957600080fd5b806361bc221a146200022f578063715018a614620002475780637e598797146200025f57600080fd5b80634f1ef28611620000be5780634f1ef286146200019757806352d1902d14620001ae57806358d276f714620001d557600080fd5b80633659cfe614620000e85780633cc3e58d146200010f5780634cf088d91462000168575b600080fd5b348015620000f557600080fd5b506200010d620001073660046200158c565b6200031e565b005b3480156200011c57600080fd5b5060cb546200013e9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156200017557600080fd5b5060cc546200013e9073ffffffffffffffffffffffffffffffffffffffff1681565b6200010d620001a8366004620016a7565b62000531565b348015620001bb57600080fd5b50620001c662000731565b6040519081526020016200015f565b348015620001e257600080fd5b506200021e620001f43660046200158c565b73ffffffffffffffffffffffffffffffffffffffff16600090815260ca6020526040902054151590565b60405190151581526020016200015f565b3480156200023c57600080fd5b50620001c660c95481565b3480156200025457600080fd5b506200010d6200081f565b3480156200026c57600080fd5b506200013e6200027e36600462001733565b62000837565b3480156200029157600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166200013e565b348015620002be57600080fd5b50620001c6620002d03660046200158c565b60ca6020526000908152604090205481565b6200010d620002f33660046200158c565b62000a8d565b3480156200030657600080fd5b506200010d620003183660046200158c565b62000c33565b3073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161415620003ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16620004607f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff161462000505576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401620003e1565b620005108162000ced565b604080516000808252602082019092526200052e9183919062000cf7565b50565b3073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161415620005f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401620003e1565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166200066f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff161462000714576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401620003e1565b6200071f8262000ced565b6200072d8282600162000cf7565b5050565b60003073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614620007fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401620003e1565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b6200082962000f17565b62000835600062000f9a565b565b60cc546040517f1af963aa000000000000000000000000000000000000000000000000000000008152336004820152600091829173ffffffffffffffffffffffffffffffffffffffff90911690631af963aa9060240160206040518083038186803b158015620008a657600080fd5b505afa158015620008bb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620008e1919062001826565b905060018115151462000977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4e6565647320746f207374616b6520484d5420746f6b656e7320746f2063726560448201527f61746520616e20657363726f772e0000000000000000000000000000000000006064820152608401620003e1565b60008533336283d600886040516200098f9062001554565b6200099f9594939291906200184a565b604051809103906000f080158015620009bc573d6000803e3d6000fd5b5060c980549192506000620009d183620018cd565b909155505060c95473ffffffffffffffffffffffffffffffffffffffff8216600081815260ca6020526040908190209290925560cb80547fffffffffffffffffffffffff0000000000000000000000000000000000000000168217905590517fde4a6895269de599430e1230956361cbe11b52ad149311a97123c73666c521419162000a62918991908890620019a9565b60405180910390a1505060cb5473ffffffffffffffffffffffffffffffffffffffff16949350505050565b600054610100900460ff161580801562000aae5750600054600160ff909116105b8062000aca5750303b15801562000aca575060005460ff166001145b62000b58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401620003e1565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801562000bb757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b62000bc162001011565b62000bcc82620010b5565b80156200072d57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b62000c3d62000f17565b73ffffffffffffffffffffffffffffffffffffffff811662000ce2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401620003e1565b6200052e8162000f9a565b6200052e62000f17565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161562000d325762000d2d836200121b565b505050565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b15801562000d7957600080fd5b505afa92505050801562000dca575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925262000dc791810190620019ed565b60015b62000e58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f7420555550530000000000000000000000000000000000006064820152608401620003e1565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc811462000f09576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c655555494400000000000000000000000000000000000000000000006064820152608401620003e1565b5062000d2d83838362001327565b60335473ffffffffffffffffffffffffffffffffffffffff16331462000835576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620003e1565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620010aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620003e1565b620008353362000f9a565b600054610100900460ff166200114e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620003e1565b60408051808201909152601b81527f457363726f77466163746f72793a205a65726f20416464726573730000000000602082015273ffffffffffffffffffffffffffffffffffffffff8216620011d3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003e1919062001a07565b5060cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff81163b620012c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401620003e1565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b620013328362001358565b600082511180620013405750805b1562000d2d57620013528383620013a7565b50505050565b62001363816200121b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060620013cf8383604051806060016040528060278152602001620052c760279139620013d6565b9392505050565b60606000808573ffffffffffffffffffffffffffffffffffffffff168560405162001402919062001a1c565b600060405180830381855af49150503d80600081146200143f576040519150601f19603f3d011682016040523d82523d6000602084013e62001444565b606091505b5091509150620014578683838762001461565b9695505050505050565b60608315620014f9578251620014f15773ffffffffffffffffffffffffffffffffffffffff85163b620014f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620003e1565b508162001505565b6200150583836200150d565b949350505050565b8151156200151e5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003e1919062001a07565b61388c8062001a3b83390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146200158757600080fd5b919050565b6000602082840312156200159f57600080fd5b620013cf8262001562565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715620016235762001623620015aa565b604052919050565b600067ffffffffffffffff831115620016485762001648620015aa565b6200167b60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f86011601620015d9565b90508281528383830111156200169057600080fd5b828260208301376000602084830101529392505050565b60008060408385031215620016bb57600080fd5b620016c68362001562565b9150602083013567ffffffffffffffff811115620016e357600080fd5b8301601f81018513620016f557600080fd5b62001706858235602084016200162b565b9150509250929050565b600082601f8301126200172257600080fd5b620013cf838335602085016200162b565b6000806000606084860312156200174957600080fd5b620017548462001562565b925060208085013567ffffffffffffffff808211156200177357600080fd5b818701915087601f8301126200178857600080fd5b8135818111156200179d576200179d620015aa565b8060051b620017ae858201620015d9565b918252838101850191858101908b841115620017c957600080fd5b948601945b83861015620017f257620017e28662001562565b82529486019490860190620017ce565b975050505060408701359250808311156200180c57600080fd5b50506200181c8682870162001710565b9150509250925092565b6000602082840312156200183957600080fd5b81518015158114620013cf57600080fd5b600060a0820173ffffffffffffffffffffffffffffffffffffffff8089168452602081891681860152818816604086015286606086015260a0608086015282865180855260c087019150828801945060005b81811015620018bc5785518516835294830194918301916001016200189c565b50909b9a5050505050505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141562001927577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b60005b838110156200194b57818101518382015260200162001931565b83811115620013525750506000910152565b60008151808452620019778160208601602086016200192e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600073ffffffffffffffffffffffffffffffffffffffff808616835280851660208401525060606040830152620019e460608301846200195d565b95945050505050565b60006020828403121562001a0057600080fd5b5051919050565b602081526000620013cf60208301846200195d565b6000825162001a308184602087016200192e565b919091019291505056fe60806040523480156200001157600080fd5b506040516200388c3803806200388c8339810160408190526200003491620003d7565b600160005560408051808201909152601481527f457363726f773a207a65726f206164647265737300000000000000000000000060208201526001600160a01b038616620000a05760405162461bcd60e51b8152600401620000979190620004f7565b60405180910390fd5b5060408051808201909152601481527f457363726f773a207a65726f206164647265737300000000000000000000000060208201526001600160a01b038416620000ff5760405162461bcd60e51b8152600401620000979190620004f7565b50600780546001600160a01b0319166001600160a01b0387161790556001805460ff191690556200013d8242620001be602090811b62001ebe17901c565b600d55600480546001600160a01b038087166001600160a01b0319928316811790935560058054918716918316821790556006805490921633179091556000918252600e6020526040808320805460ff199081166001908117909255928452922080549091169091179055620001b38162000228565b5050505050620005b4565b600080620001cd838562000565565b905083811015620002215760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015260640162000097565b9392505050565b60005b8151811015620003925760006001600160a01b031682828151811062000255576200025562000580565b60200260200101516001600160a01b031614156040518060400160405280601481526020017f457363726f773a207a65726f206164647265737300000000000000000000000081525090620002bf5760405162461bcd60e51b8152600401620000979190620004f7565b506001600e6000848481518110620002db57620002db62000580565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055507fad3769ac0c1a91ee9dcf369f6d2989f91572b6f876933bbc82ab85f6b969a07a82828151811062000350576200035062000580565b60200260200101516040516200037591906001600160a01b0391909116815260200190565b60405180910390a180620003898162000596565b9150506200022b565b5050565b6001600160a01b0381168114620003ac57600080fd5b50565b8051620003bc8162000396565b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600060a08688031215620003f057600080fd5b8551620003fd8162000396565b80955050602080870151620004128162000396565b6040880151909550620004258162000396565b6060880151608089015191955093506001600160401b03808211156200044a57600080fd5b818901915089601f8301126200045f57600080fd5b815181811115620004745762000474620003c1565b8060051b604051601f19603f830116810181811085821117156200049c576200049c620003c1565b60405291825284820192508381018501918c831115620004bb57600080fd5b938501935b82851015620004e457620004d485620003af565b84529385019392850192620004c0565b8096505050505050509295509295909350565b600060208083528351808285015260005b81811015620005265785810183015185820160400152820162000508565b8181111562000539576000604083870101525b50601f01601f1916929092016040019392505050565b634e487b7160e01b600052601160045260246000fd5b600082198211156200057b576200057b6200054f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600019821415620005ad57620005ad6200054f565b5060010190565b6132c880620005c46000396000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c8063992d454d116100ee578063bdd1daaa11610097578063f17171e911610071578063f17171e9146103d2578063f56679cf146103f5578063fad844c114610408578063fc0c546a1461042d57600080fd5b8063bdd1daaa14610375578063c479bbf814610395578063ea8a1af0146103ba57600080fd5b8063a05220ad116100c8578063a05220ad1461033a578063b63d1a001461035a578063ba5fed341461036d57600080fd5b8063992d454d146102ff5780639c48b1021461031f5780639eb262f31461032757600080fd5b8063337f3f321161015b578063522e117711610135578063522e11771461029e578063697e4b87146102a657806378c62420146102b95780639753e432146102df57600080fd5b8063337f3f321461028457806335a063b41461028c57806343aba9c21461029657600080fd5b806312065fe01161018c57806312065fe01461021d57806316eebd1e14610225578063200d2ed21461026a57600080fd5b80630ae9dfad146101b35780630f46c9aa146101f15780630fb5a6b414610206575b600080fd5b6006546101da90760100000000000000000000000000000000000000000000900460ff1681565b60405160ff90911681526020015b60405180910390f35b6101f961044d565b6040516101e89190612a0c565b61020f600d5481565b6040519081526020016101e8565b61020f6104db565b6004546102459073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101e8565b6001546102779060ff1681565b6040516101e89190612a4e565b6101f9610622565b61029461062f565b005b6101f96107e1565b6102946107ee565b6102946102b4366004612b9b565b6109cf565b6006546101da907501000000000000000000000000000000000000000000900460ff1681565b6002546102459073ffffffffffffffffffffffffffffffffffffffff1681565b6005546102459073ffffffffffffffffffffffffffffffffffffffff1681565b6101f9610cbc565b610294610335366004612cbe565b610cc9565b6003546102459073ffffffffffffffffffffffffffffffffffffffff1681565b610294610368366004612cf3565b610d4e565b6101f961168d565b6006546102459073ffffffffffffffffffffffffffffffffffffffff1681565b6006546101da9074010000000000000000000000000000000000000000900460ff1681565b6103c261169a565b60405190151581526020016101e8565b6103c26103e0366004612dfc565b600e6020526000908152604090205460ff1681565b610294610403366004612e28565b611919565b60015461024590610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6007546102459073ffffffffffffffffffffffffffffffffffffffff1681565b600c805461045a90612ef0565b80601f016020809104026020016040519081016040528092919081815260200182805461048690612ef0565b80156104d35780601f106104a8576101008083540402835291602001916104d3565b820191906000526020600020905b8154815290600101906020018083116104b657829003601f168201915b505050505081565b6007546040513060248201526000918291829173ffffffffffffffffffffffffffffffffffffffff16907f70a08231b98ef4ca268c9cc3f6b4590e4bfec28280db06bb5d45e689f2a360be90604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516105b39190612f44565b600060405180830381855afa9150503d80600081146105ee576040519150601f19603f3d011682016040523d82523d6000602084013e6105f3565b606091505b5091509150811561061957808060200190518101906106129190612f60565b9250505090565b60009250505090565b6009805461045a90612ef0565b336000908152600e602052604090205460ff166106ad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f416464726573732063616c6c696e67206e6f742074727573746564000000000060448201526064015b60405180910390fd5b600460015460ff1660058111156106c6576106c6612a1f565b141561072e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f457363726f7720696e20436f6d706c657465207374617475732073746174650060448201526064016106a4565b600360015460ff16600581111561074757610747612a1f565b14156107af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f457363726f7720696e205061696420737461747573207374617465000000000060448201526064016106a4565b6107b76104db565b156107c6576107c461169a565b505b60055473ffffffffffffffffffffffffffffffffffffffff16ff5b600b805461045a90612ef0565b42600d5411610859576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f436f6e747261637420657870697265640000000000000000000000000000000060448201526064016106a4565b336000908152600e602052604090205460ff16806108935750600154610100900473ffffffffffffffffffffffffffffffffffffffff1633145b6108f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f416464726573732063616c6c696e67206e6f742074727573746564000000000060448201526064016106a4565b600360015460ff16600581111561091257610912612a1f565b14610979576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f457363726f77206e6f7420696e2050616964207374617465000000000000000060448201526064016106a4565b600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660041790556040517fe06452d00b2b58f14a1fa6d499ea982ff93ea827ae700ea9ba03f4daddc94bc190600090a1565b336000908152600e602052604090205460ff1680610a04575060025473ffffffffffffffffffffffffffffffffffffffff1633145b610a6a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f416464726573732063616c6c696e67206e6f742074727573746564000000000060448201526064016106a4565b42600d5411610ad5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f436f6e747261637420657870697265640000000000000000000000000000000060448201526064016106a4565b6001805460ff166005811115610aed57610aed612a1f565b1480610b0f5750600260015460ff166005811115610b0d57610b0d612a1f565b145b610b9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f457363726f77206e6f7420696e2050656e64696e67206f72205061727469616c60448201527f207374617475732073746174650000000000000000000000000000000000000060648201526084016106a4565b8151610c03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f55524c2063616e277420626520656d707479000000000000000000000000000060448201526064016106a4565b8051610c6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f486173682063616e277420626520656d7074790000000000000000000000000060448201526064016106a4565b8151610c7e90600a9060208501906128f9565b507fb20e0717219840fd5684a80bec782e8babb56ea224f677561b791a61192605c18282604051610cb0929190612f79565b60405180910390a15050565b6008805461045a90612ef0565b336000908152600e602052604090205460ff16610d42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f416464726573732063616c6c696e67206e6f742074727573746564000000000060448201526064016106a4565b610d4b81611f40565b50565b336000908152600e602052604090205460ff1680610d885750600154610100900473ffffffffffffffffffffffffffffffffffffffff1633145b610dee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f416464726573732063616c6c696e67206e6f742074727573746564000000000060448201526064016106a4565b610df66104db565b610e5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f546f6b656e20636f6e7472616374206f7574206f662066756e6473000000000060448201526064016106a4565b600060015460ff166005811115610e7557610e75612a1f565b1415610edd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f457363726f7720696e204c61756e63686564207374617475732073746174650060448201526064016106a4565b600360015460ff166005811115610ef657610ef6612a1f565b1415610f5e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f457363726f7720696e205061696420737461747573207374617465000000000060448201526064016106a4565b42600d5411610fc9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f436f6e747261637420657870697265640000000000000000000000000000000060448201526064016106a4565b610fd16120f8565b8351855114611062576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f416d6f756e74206f6620726563697069656e747320616e642076616c7565732060448201527f646f6e2774206d6174636800000000000000000000000000000000000000000060648201526084016106a4565b60008451116110cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f416d6f756e74732073686f756c64206e6f7420626520656d707479000000000060448201526064016106a4565b8451606411611138576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f546f6f206d616e7920726563697069656e74730000000000000000000000000060448201526064016106a4565b600460015460ff16600581111561115157611151612a1f565b141580156111765750600560015460ff16600581111561117357611173612a1f565b14155b6111dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f496e76616c69642073746174757300000000000000000000000000000000000060448201526064016106a4565b60006111e66104db565b90506000805b86518110156112de57600087828151811061120957611209612f9e565b60200260200101511161129e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f416d6f756e742073686f756c642062652067726561746572207468616e207a6560448201527f726f00000000000000000000000000000000000000000000000000000000000060648201526084016106a4565b6112ca8782815181106112b3576112b3612f9e565b602002602001015183611ebe90919063ffffffff16565b9150806112d681612ffc565b9150506111ec565b506b033b2e3c9fd0803ce80000008110611354576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f42756c6b2076616c756520746f6f20686967680000000000000000000000000060448201526064016106a4565b818111156113be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4e6f7420656e6f7567682062616c616e6365000000000000000000000000000060448201526064016106a4565b8451611426576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f55524c2063616e277420626520656d707479000000000000000000000000000060448201526064016106a4565b835161148e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f486173682063616e277420626520656d7074790000000000000000000000000060448201526064016106a4565b84516114a190600b9060208801906128f9565b5083516114b590600c9060208701906128f9565b506000806000806114c58a61216c565b935093509350935060005b8b518110156115475760008582815181106114ed576114ed612f9e565b60200260200101511115611537576115378c828151811061151057611510612f9e565b602002602001015186838151811061152a5761152a612f9e565b6020026020010151612353565b61154081612ffc565b90506114d0565b5082156115765760015461157690610100900473ffffffffffffffffffffffffffffffffffffffff1684612353565b811561159f5760025461159f9073ffffffffffffffffffffffffffffffffffffffff1683612353565b80156115c8576003546115c89073ffffffffffffffffffffffffffffffffffffffff1682612353565b6115d06104db565b955060008661160c5750600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660031790556000611639565b50600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660021781555b877f776950576f5bac7433f5095f1490841528a48d38607deca7d6f270988ec32b8a8d878460405161166d93929190613035565b60405180910390a2505050505050506116866001600055565b5050505050565b600a805461045a90612ef0565b336000908152600e602052604081205460ff16611713576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f416464726573732063616c6c696e67206e6f742074727573746564000000000060448201526064016106a4565b61171b6104db565b611781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f546f6b656e20636f6e7472616374206f7574206f662066756e6473000000000060448201526064016106a4565b600460015460ff16600581111561179a5761179a612a1f565b1415611802576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f457363726f7720696e20436f6d706c657465207374617475732073746174650060448201526064016106a4565b600360015460ff16600581111561181b5761181b612a1f565b1415611883576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f457363726f7720696e205061696420737461747573207374617465000000000060448201526064016106a4565b61188b6120f8565b6005546118b59073ffffffffffffffffffffffffffffffffffffffff166118b06104db565b612353565b600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660051790556040517f63b958841f79ab97cb5456da181454b9932c0e15a3b17f1cbd27e2a8bc61043790600090a15060016119166001600055565b90565b336000908152600e602052604090205460ff16611992576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f416464726573732063616c6c696e67206e6f742074727573746564000000000060448201526064016106a4565b42600d54116119fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f436f6e747261637420657870697265640000000000000000000000000000000060448201526064016106a4565b73ffffffffffffffffffffffffffffffffffffffff8816611aa0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f496e76616c69642072657075746174696f6e206f7261636c652061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106a4565b73ffffffffffffffffffffffffffffffffffffffff8716611b1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f496e76616c6964207265636f7264696e67206f7261636c65206164647265737360448201526064016106a4565b73ffffffffffffffffffffffffffffffffffffffff8616611b9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c69642065786368616e6765206f7261636c6520616464726573730060448201526064016106a4565b60008360ff168560ff168760ff16611bb291906130cd565b611bbc91906130cd565b90506064811115611c29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f50657263656e74616765206f7574206f6620626f756e6473000000000000000060448201526064016106a4565b600060015460ff166005811115611c4257611c42612a1f565b14611ccf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f457363726f77206e6f7420696e204c61756e636865642073746174757320737460448201527f617465000000000000000000000000000000000000000000000000000000000060648201526084016106a4565b600180547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1661010073ffffffffffffffffffffffffffffffffffffffff8c81169190910291909117909155600280547fffffffffffffffffffffffff00000000000000000000000000000000000000009081168b84161790915560038054909116918916919091179055600680547fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000060ff898116919091027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1691909117750100000000000000000000000000000000000000000088831602177fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff16760100000000000000000000000000000000000000000000918716919091021790558251611e389060089060208601906128f9565b508151611e4c9060099060208501906128f9565b50600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016811790556040517f8ec464ac0c8e44e17130cd1ffb09967fa6f2c33339289678a59ea0112cfc2aa990611eab906008906009906131bc565b60405180910390a1505050505050505050565b600080611ecb83856130cd565b905083811015611f37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f77000000000060448201526064016106a4565b90505b92915050565b60005b81518110156120f457600073ffffffffffffffffffffffffffffffffffffffff16828281518110611f7657611f76612f9e565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280601481526020017f457363726f773a207a65726f206164647265737300000000000000000000000081525090612004576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a49190612a0c565b506001600e600084848151811061201d5761201d612f9e565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fad3769ac0c1a91ee9dcf369f6d2989f91572b6f876933bbc82ab85f6b969a07a8282815181106120a9576120a9612f9e565b60200260200101516040516120da919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180910390a1806120ec81612ffc565b915050611f43565b5050565b60026000541415612165576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016106a4565b6002600055565b6060600080600080855167ffffffffffffffff81111561218e5761218e612a8f565b6040519080825280602002602001820160405280156121b7578160200160208202803683370190505b5090506000806000805b89518110156123435760008a82815181106121de576121de612f9e565b6020026020010151905060008061221b606461221585600660149054906101000a900460ff1660ff1661237790919063ffffffff16565b9061242c565b90506122278782611ebe565b96506122338282611ebe565b915050600061228260646122158f878151811061225257612252612f9e565b60209081029190910101516006547501000000000000000000000000000000000000000000900460ff1690612377565b905061228e8682611ebe565b955061229a8282611ebe565b91505060006122ea60646122158f87815181106122b9576122b9612f9e565b6020908102919091010151600654760100000000000000000000000000000000000000000000900460ff1690612377565b90506122f68582611ebe565b94506123028282611ebe565b91506123109050828261246e565b87848151811061232257612322612f9e565b6020026020010181815250505050808061233b90612ffc565b9150506121c1565b5092989197509550909350915050565b6007546120f49073ffffffffffffffffffffffffffffffffffffffff1683836124b0565b60008261238657506000611f3a565b600061239283856131e1565b90508261239f858361321e565b14611f37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60448201527f770000000000000000000000000000000000000000000000000000000000000060648201526084016106a4565b6000611f3783836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612542565b6000611f3783836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612593565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261253d9084906125de565b505050565b6000818361257d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a49190612a0c565b50600061258a848661321e565b95945050505050565b600081848411156125d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a49190612a0c565b50600061258a8486613259565b6000612640826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126ed9092919063ffffffff16565b90508051600014806126615750808060200190518101906126619190613270565b61253d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016106a4565b60606126fc8484600085612704565b949350505050565b606082471015612796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016106a4565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516127bf9190612f44565b60006040518083038185875af1925050503d80600081146127fc576040519150601f19603f3d011682016040523d82523d6000602084013e612801565b606091505b50915091506128128783838761281d565b979650505050505050565b606083156128b05782516128a95773ffffffffffffffffffffffffffffffffffffffff85163b6128a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106a4565b50816126fc565b6126fc83838151156128c55781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a49190612a0c565b82805461290590612ef0565b90600052602060002090601f016020900481019282612927576000855561296d565b82601f1061294057805160ff191683800117855561296d565b8280016001018555821561296d579182015b8281111561296d578251825591602001919060010190612952565b5061297992915061297d565b5090565b5b80821115612979576000815560010161297e565b60005b838110156129ad578181015183820152602001612995565b838111156129bc576000848401525b50505050565b600081518084526129da816020860160208601612992565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611f3760208301846129c2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160068310612a89577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612b0557612b05612a8f565b604052919050565b600082601f830112612b1e57600080fd5b813567ffffffffffffffff811115612b3857612b38612a8f565b612b6960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612abe565b818152846020838601011115612b7e57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215612bae57600080fd5b823567ffffffffffffffff80821115612bc657600080fd5b612bd286838701612b0d565b93506020850135915080821115612be857600080fd5b50612bf585828601612b0d565b9150509250929050565b600067ffffffffffffffff821115612c1957612c19612a8f565b5060051b60200190565b803573ffffffffffffffffffffffffffffffffffffffff81168114612c4757600080fd5b919050565b600082601f830112612c5d57600080fd5b81356020612c72612c6d83612bff565b612abe565b82815260059290921b84018101918181019086841115612c9157600080fd5b8286015b84811015612cb357612ca681612c23565b8352918301918301612c95565b509695505050505050565b600060208284031215612cd057600080fd5b813567ffffffffffffffff811115612ce757600080fd5b6126fc84828501612c4c565b600080600080600060a08688031215612d0b57600080fd5b853567ffffffffffffffff80821115612d2357600080fd5b612d2f89838a01612c4c565b9650602091508188013581811115612d4657600080fd5b8801601f81018a13612d5757600080fd5b8035612d65612c6d82612bff565b81815260059190911b8201840190848101908c831115612d8457600080fd5b928501925b82841015612da257833582529285019290850190612d89565b98505050506040880135915080821115612dbb57600080fd5b612dc789838a01612b0d565b94506060880135915080821115612ddd57600080fd5b50612dea88828901612b0d565b95989497509295608001359392505050565b600060208284031215612e0e57600080fd5b611f3782612c23565b803560ff81168114612c4757600080fd5b600080600080600080600080610100898b031215612e4557600080fd5b612e4e89612c23565b9750612e5c60208a01612c23565b9650612e6a60408a01612c23565b9550612e7860608a01612e17565b9450612e8660808a01612e17565b9350612e9460a08a01612e17565b925060c089013567ffffffffffffffff80821115612eb157600080fd5b612ebd8c838d01612b0d565b935060e08b0135915080821115612ed357600080fd5b50612ee08b828c01612b0d565b9150509295985092959890939650565b600181811c90821680612f0457607f821691505b60208210811415612f3e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008251612f56818460208701612992565b9190910192915050565b600060208284031215612f7257600080fd5b5051919050565b604081526000612f8c60408301856129c2565b828103602084015261258a81856129c2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561302e5761302e612fcd565b5060010190565b606080825284519082018190526000906020906080840190828801845b8281101561308457815173ffffffffffffffffffffffffffffffffffffffff1684529284019290840190600101613052565b5050508381038285015285518082528683019183019060005b818110156130b95783518352928401929184019160010161309d565b5050851515604086015292506126fc915050565b600082198211156130e0576130e0612fcd565b500190565b8054600090600181811c90808316806130ff57607f831692505b602080841082141561313a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b838852602088018280156131555760018114613184576131af565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008716825282820197506131af565b60008981526020902060005b878110156131a957815484820152908601908401613190565b83019850505b5050505050505092915050565b6040815260006131cf60408301856130e5565b828103602084015261258a81856130e5565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561321957613219612fcd565b500290565b600082613254577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008282101561326b5761326b612fcd565b500390565b60006020828403121561328257600080fd5b81518015158114611f3757600080fdfea26469706673582212205081acc662e9c873833108cb5165d7086d03924a92145bbb4286a2b90256b8b664736f6c63430008090033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212209efb630075ff097beba24a7d047692f1c58e2a50e8eaf6dd2cb9ca4bc6a9441364736f6c63430008090033
Deployed Bytecode
0x608060405260043610620000e35760003560e01c806361bc221a11620000895780638da5cb5b11620000605780638da5cb5b1462000284578063979530e614620002b1578063c4d66de814620002e2578063f2fde38b14620002f957600080fd5b806361bc221a146200022f578063715018a614620002475780637e598797146200025f57600080fd5b80634f1ef28611620000be5780634f1ef286146200019757806352d1902d14620001ae57806358d276f714620001d557600080fd5b80633659cfe614620000e85780633cc3e58d146200010f5780634cf088d91462000168575b600080fd5b348015620000f557600080fd5b506200010d620001073660046200158c565b6200031e565b005b3480156200011c57600080fd5b5060cb546200013e9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156200017557600080fd5b5060cc546200013e9073ffffffffffffffffffffffffffffffffffffffff1681565b6200010d620001a8366004620016a7565b62000531565b348015620001bb57600080fd5b50620001c662000731565b6040519081526020016200015f565b348015620001e257600080fd5b506200021e620001f43660046200158c565b73ffffffffffffffffffffffffffffffffffffffff16600090815260ca6020526040902054151590565b60405190151581526020016200015f565b3480156200023c57600080fd5b50620001c660c95481565b3480156200025457600080fd5b506200010d6200081f565b3480156200026c57600080fd5b506200013e6200027e36600462001733565b62000837565b3480156200029157600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166200013e565b348015620002be57600080fd5b50620001c6620002d03660046200158c565b60ca6020526000908152604090205481565b6200010d620002f33660046200158c565b62000a8d565b3480156200030657600080fd5b506200010d620003183660046200158c565b62000c33565b3073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c90b43a5d576d9d8026c48904dfbaed50c15fa08161415620003ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f000000000000000000000000c90b43a5d576d9d8026c48904dfbaed50c15fa0873ffffffffffffffffffffffffffffffffffffffff16620004607f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff161462000505576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401620003e1565b620005108162000ced565b604080516000808252602082019092526200052e9183919062000cf7565b50565b3073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c90b43a5d576d9d8026c48904dfbaed50c15fa08161415620005f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401620003e1565b7f000000000000000000000000c90b43a5d576d9d8026c48904dfbaed50c15fa0873ffffffffffffffffffffffffffffffffffffffff166200066f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff161462000714576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401620003e1565b6200071f8262000ced565b6200072d8282600162000cf7565b5050565b60003073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c90b43a5d576d9d8026c48904dfbaed50c15fa081614620007fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401620003e1565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b6200082962000f17565b62000835600062000f9a565b565b60cc546040517f1af963aa000000000000000000000000000000000000000000000000000000008152336004820152600091829173ffffffffffffffffffffffffffffffffffffffff90911690631af963aa9060240160206040518083038186803b158015620008a657600080fd5b505afa158015620008bb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620008e1919062001826565b905060018115151462000977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4e6565647320746f207374616b6520484d5420746f6b656e7320746f2063726560448201527f61746520616e20657363726f772e0000000000000000000000000000000000006064820152608401620003e1565b60008533336283d600886040516200098f9062001554565b6200099f9594939291906200184a565b604051809103906000f080158015620009bc573d6000803e3d6000fd5b5060c980549192506000620009d183620018cd565b909155505060c95473ffffffffffffffffffffffffffffffffffffffff8216600081815260ca6020526040908190209290925560cb80547fffffffffffffffffffffffff0000000000000000000000000000000000000000168217905590517fde4a6895269de599430e1230956361cbe11b52ad149311a97123c73666c521419162000a62918991908890620019a9565b60405180910390a1505060cb5473ffffffffffffffffffffffffffffffffffffffff16949350505050565b600054610100900460ff161580801562000aae5750600054600160ff909116105b8062000aca5750303b15801562000aca575060005460ff166001145b62000b58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401620003e1565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801562000bb757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b62000bc162001011565b62000bcc82620010b5565b80156200072d57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b62000c3d62000f17565b73ffffffffffffffffffffffffffffffffffffffff811662000ce2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401620003e1565b6200052e8162000f9a565b6200052e62000f17565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161562000d325762000d2d836200121b565b505050565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b15801562000d7957600080fd5b505afa92505050801562000dca575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925262000dc791810190620019ed565b60015b62000e58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f7420555550530000000000000000000000000000000000006064820152608401620003e1565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc811462000f09576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c655555494400000000000000000000000000000000000000000000006064820152608401620003e1565b5062000d2d83838362001327565b60335473ffffffffffffffffffffffffffffffffffffffff16331462000835576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620003e1565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620010aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620003e1565b620008353362000f9a565b600054610100900460ff166200114e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620003e1565b60408051808201909152601b81527f457363726f77466163746f72793a205a65726f20416464726573730000000000602082015273ffffffffffffffffffffffffffffffffffffffff8216620011d3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003e1919062001a07565b5060cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff81163b620012c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401620003e1565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b620013328362001358565b600082511180620013405750805b1562000d2d57620013528383620013a7565b50505050565b62001363816200121b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060620013cf8383604051806060016040528060278152602001620052c760279139620013d6565b9392505050565b60606000808573ffffffffffffffffffffffffffffffffffffffff168560405162001402919062001a1c565b600060405180830381855af49150503d80600081146200143f576040519150601f19603f3d011682016040523d82523d6000602084013e62001444565b606091505b5091509150620014578683838762001461565b9695505050505050565b60608315620014f9578251620014f15773ffffffffffffffffffffffffffffffffffffffff85163b620014f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620003e1565b508162001505565b6200150583836200150d565b949350505050565b8151156200151e5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003e1919062001a07565b61388c8062001a3b83390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146200158757600080fd5b919050565b6000602082840312156200159f57600080fd5b620013cf8262001562565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715620016235762001623620015aa565b604052919050565b600067ffffffffffffffff831115620016485762001648620015aa565b6200167b60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f86011601620015d9565b90508281528383830111156200169057600080fd5b828260208301376000602084830101529392505050565b60008060408385031215620016bb57600080fd5b620016c68362001562565b9150602083013567ffffffffffffffff811115620016e357600080fd5b8301601f81018513620016f557600080fd5b62001706858235602084016200162b565b9150509250929050565b600082601f8301126200172257600080fd5b620013cf838335602085016200162b565b6000806000606084860312156200174957600080fd5b620017548462001562565b925060208085013567ffffffffffffffff808211156200177357600080fd5b818701915087601f8301126200178857600080fd5b8135818111156200179d576200179d620015aa565b8060051b620017ae858201620015d9565b918252838101850191858101908b841115620017c957600080fd5b948601945b83861015620017f257620017e28662001562565b82529486019490860190620017ce565b975050505060408701359250808311156200180c57600080fd5b50506200181c8682870162001710565b9150509250925092565b6000602082840312156200183957600080fd5b81518015158114620013cf57600080fd5b600060a0820173ffffffffffffffffffffffffffffffffffffffff8089168452602081891681860152818816604086015286606086015260a0608086015282865180855260c087019150828801945060005b81811015620018bc5785518516835294830194918301916001016200189c565b50909b9a5050505050505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141562001927577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b60005b838110156200194b57818101518382015260200162001931565b83811115620013525750506000910152565b60008151808452620019778160208601602086016200192e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600073ffffffffffffffffffffffffffffffffffffffff808616835280851660208401525060606040830152620019e460608301846200195d565b95945050505050565b60006020828403121562001a0057600080fd5b5051919050565b602081526000620013cf60208301846200195d565b6000825162001a308184602087016200192e565b919091019291505056fe60806040523480156200001157600080fd5b506040516200388c3803806200388c8339810160408190526200003491620003d7565b600160005560408051808201909152601481527f457363726f773a207a65726f206164647265737300000000000000000000000060208201526001600160a01b038616620000a05760405162461bcd60e51b8152600401620000979190620004f7565b60405180910390fd5b5060408051808201909152601481527f457363726f773a207a65726f206164647265737300000000000000000000000060208201526001600160a01b038416620000ff5760405162461bcd60e51b8152600401620000979190620004f7565b50600780546001600160a01b0319166001600160a01b0387161790556001805460ff191690556200013d8242620001be602090811b62001ebe17901c565b600d55600480546001600160a01b038087166001600160a01b0319928316811790935560058054918716918316821790556006805490921633179091556000918252600e6020526040808320805460ff199081166001908117909255928452922080549091169091179055620001b38162000228565b5050505050620005b4565b600080620001cd838562000565565b905083811015620002215760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015260640162000097565b9392505050565b60005b8151811015620003925760006001600160a01b031682828151811062000255576200025562000580565b60200260200101516001600160a01b031614156040518060400160405280601481526020017f457363726f773a207a65726f206164647265737300000000000000000000000081525090620002bf5760405162461bcd60e51b8152600401620000979190620004f7565b506001600e6000848481518110620002db57620002db62000580565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055507fad3769ac0c1a91ee9dcf369f6d2989f91572b6f876933bbc82ab85f6b969a07a82828151811062000350576200035062000580565b60200260200101516040516200037591906001600160a01b0391909116815260200190565b60405180910390a180620003898162000596565b9150506200022b565b5050565b6001600160a01b0381168114620003ac57600080fd5b50565b8051620003bc8162000396565b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600060a08688031215620003f057600080fd5b8551620003fd8162000396565b80955050602080870151620004128162000396565b6040880151909550620004258162000396565b6060880151608089015191955093506001600160401b03808211156200044a57600080fd5b818901915089601f8301126200045f57600080fd5b815181811115620004745762000474620003c1565b8060051b604051601f19603f830116810181811085821117156200049c576200049c620003c1565b60405291825284820192508381018501918c831115620004bb57600080fd5b938501935b82851015620004e457620004d485620003af565b84529385019392850192620004c0565b8096505050505050509295509295909350565b600060208083528351808285015260005b81811015620005265785810183015185820160400152820162000508565b8181111562000539576000604083870101525b50601f01601f1916929092016040019392505050565b634e487b7160e01b600052601160045260246000fd5b600082198211156200057b576200057b6200054f565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600019821415620005ad57620005ad6200054f565b5060010190565b6132c880620005c46000396000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c8063992d454d116100ee578063bdd1daaa11610097578063f17171e911610071578063f17171e9146103d2578063f56679cf146103f5578063fad844c114610408578063fc0c546a1461042d57600080fd5b8063bdd1daaa14610375578063c479bbf814610395578063ea8a1af0146103ba57600080fd5b8063a05220ad116100c8578063a05220ad1461033a578063b63d1a001461035a578063ba5fed341461036d57600080fd5b8063992d454d146102ff5780639c48b1021461031f5780639eb262f31461032757600080fd5b8063337f3f321161015b578063522e117711610135578063522e11771461029e578063697e4b87146102a657806378c62420146102b95780639753e432146102df57600080fd5b8063337f3f321461028457806335a063b41461028c57806343aba9c21461029657600080fd5b806312065fe01161018c57806312065fe01461021d57806316eebd1e14610225578063200d2ed21461026a57600080fd5b80630ae9dfad146101b35780630f46c9aa146101f15780630fb5a6b414610206575b600080fd5b6006546101da90760100000000000000000000000000000000000000000000900460ff1681565b60405160ff90911681526020015b60405180910390f35b6101f961044d565b6040516101e89190612a0c565b61020f600d5481565b6040519081526020016101e8565b61020f6104db565b6004546102459073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101e8565b6001546102779060ff1681565b6040516101e89190612a4e565b6101f9610622565b61029461062f565b005b6101f96107e1565b6102946107ee565b6102946102b4366004612b9b565b6109cf565b6006546101da907501000000000000000000000000000000000000000000900460ff1681565b6002546102459073ffffffffffffffffffffffffffffffffffffffff1681565b6005546102459073ffffffffffffffffffffffffffffffffffffffff1681565b6101f9610cbc565b610294610335366004612cbe565b610cc9565b6003546102459073ffffffffffffffffffffffffffffffffffffffff1681565b610294610368366004612cf3565b610d4e565b6101f961168d565b6006546102459073ffffffffffffffffffffffffffffffffffffffff1681565b6006546101da9074010000000000000000000000000000000000000000900460ff1681565b6103c261169a565b60405190151581526020016101e8565b6103c26103e0366004612dfc565b600e6020526000908152604090205460ff1681565b610294610403366004612e28565b611919565b60015461024590610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6007546102459073ffffffffffffffffffffffffffffffffffffffff1681565b600c805461045a90612ef0565b80601f016020809104026020016040519081016040528092919081815260200182805461048690612ef0565b80156104d35780601f106104a8576101008083540402835291602001916104d3565b820191906000526020600020905b8154815290600101906020018083116104b657829003601f168201915b505050505081565b6007546040513060248201526000918291829173ffffffffffffffffffffffffffffffffffffffff16907f70a08231b98ef4ca268c9cc3f6b4590e4bfec28280db06bb5d45e689f2a360be90604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516105b39190612f44565b600060405180830381855afa9150503d80600081146105ee576040519150601f19603f3d011682016040523d82523d6000602084013e6105f3565b606091505b5091509150811561061957808060200190518101906106129190612f60565b9250505090565b60009250505090565b6009805461045a90612ef0565b336000908152600e602052604090205460ff166106ad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f416464726573732063616c6c696e67206e6f742074727573746564000000000060448201526064015b60405180910390fd5b600460015460ff1660058111156106c6576106c6612a1f565b141561072e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f457363726f7720696e20436f6d706c657465207374617475732073746174650060448201526064016106a4565b600360015460ff16600581111561074757610747612a1f565b14156107af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f457363726f7720696e205061696420737461747573207374617465000000000060448201526064016106a4565b6107b76104db565b156107c6576107c461169a565b505b60055473ffffffffffffffffffffffffffffffffffffffff16ff5b600b805461045a90612ef0565b42600d5411610859576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f436f6e747261637420657870697265640000000000000000000000000000000060448201526064016106a4565b336000908152600e602052604090205460ff16806108935750600154610100900473ffffffffffffffffffffffffffffffffffffffff1633145b6108f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f416464726573732063616c6c696e67206e6f742074727573746564000000000060448201526064016106a4565b600360015460ff16600581111561091257610912612a1f565b14610979576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f457363726f77206e6f7420696e2050616964207374617465000000000000000060448201526064016106a4565b600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660041790556040517fe06452d00b2b58f14a1fa6d499ea982ff93ea827ae700ea9ba03f4daddc94bc190600090a1565b336000908152600e602052604090205460ff1680610a04575060025473ffffffffffffffffffffffffffffffffffffffff1633145b610a6a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f416464726573732063616c6c696e67206e6f742074727573746564000000000060448201526064016106a4565b42600d5411610ad5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f436f6e747261637420657870697265640000000000000000000000000000000060448201526064016106a4565b6001805460ff166005811115610aed57610aed612a1f565b1480610b0f5750600260015460ff166005811115610b0d57610b0d612a1f565b145b610b9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f457363726f77206e6f7420696e2050656e64696e67206f72205061727469616c60448201527f207374617475732073746174650000000000000000000000000000000000000060648201526084016106a4565b8151610c03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f55524c2063616e277420626520656d707479000000000000000000000000000060448201526064016106a4565b8051610c6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f486173682063616e277420626520656d7074790000000000000000000000000060448201526064016106a4565b8151610c7e90600a9060208501906128f9565b507fb20e0717219840fd5684a80bec782e8babb56ea224f677561b791a61192605c18282604051610cb0929190612f79565b60405180910390a15050565b6008805461045a90612ef0565b336000908152600e602052604090205460ff16610d42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f416464726573732063616c6c696e67206e6f742074727573746564000000000060448201526064016106a4565b610d4b81611f40565b50565b336000908152600e602052604090205460ff1680610d885750600154610100900473ffffffffffffffffffffffffffffffffffffffff1633145b610dee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f416464726573732063616c6c696e67206e6f742074727573746564000000000060448201526064016106a4565b610df66104db565b610e5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f546f6b656e20636f6e7472616374206f7574206f662066756e6473000000000060448201526064016106a4565b600060015460ff166005811115610e7557610e75612a1f565b1415610edd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f457363726f7720696e204c61756e63686564207374617475732073746174650060448201526064016106a4565b600360015460ff166005811115610ef657610ef6612a1f565b1415610f5e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f457363726f7720696e205061696420737461747573207374617465000000000060448201526064016106a4565b42600d5411610fc9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f436f6e747261637420657870697265640000000000000000000000000000000060448201526064016106a4565b610fd16120f8565b8351855114611062576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f416d6f756e74206f6620726563697069656e747320616e642076616c7565732060448201527f646f6e2774206d6174636800000000000000000000000000000000000000000060648201526084016106a4565b60008451116110cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f416d6f756e74732073686f756c64206e6f7420626520656d707479000000000060448201526064016106a4565b8451606411611138576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f546f6f206d616e7920726563697069656e74730000000000000000000000000060448201526064016106a4565b600460015460ff16600581111561115157611151612a1f565b141580156111765750600560015460ff16600581111561117357611173612a1f565b14155b6111dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f496e76616c69642073746174757300000000000000000000000000000000000060448201526064016106a4565b60006111e66104db565b90506000805b86518110156112de57600087828151811061120957611209612f9e565b60200260200101511161129e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f416d6f756e742073686f756c642062652067726561746572207468616e207a6560448201527f726f00000000000000000000000000000000000000000000000000000000000060648201526084016106a4565b6112ca8782815181106112b3576112b3612f9e565b602002602001015183611ebe90919063ffffffff16565b9150806112d681612ffc565b9150506111ec565b506b033b2e3c9fd0803ce80000008110611354576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f42756c6b2076616c756520746f6f20686967680000000000000000000000000060448201526064016106a4565b818111156113be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4e6f7420656e6f7567682062616c616e6365000000000000000000000000000060448201526064016106a4565b8451611426576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f55524c2063616e277420626520656d707479000000000000000000000000000060448201526064016106a4565b835161148e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f486173682063616e277420626520656d7074790000000000000000000000000060448201526064016106a4565b84516114a190600b9060208801906128f9565b5083516114b590600c9060208701906128f9565b506000806000806114c58a61216c565b935093509350935060005b8b518110156115475760008582815181106114ed576114ed612f9e565b60200260200101511115611537576115378c828151811061151057611510612f9e565b602002602001015186838151811061152a5761152a612f9e565b6020026020010151612353565b61154081612ffc565b90506114d0565b5082156115765760015461157690610100900473ffffffffffffffffffffffffffffffffffffffff1684612353565b811561159f5760025461159f9073ffffffffffffffffffffffffffffffffffffffff1683612353565b80156115c8576003546115c89073ffffffffffffffffffffffffffffffffffffffff1682612353565b6115d06104db565b955060008661160c5750600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660031790556000611639565b50600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660021781555b877f776950576f5bac7433f5095f1490841528a48d38607deca7d6f270988ec32b8a8d878460405161166d93929190613035565b60405180910390a2505050505050506116866001600055565b5050505050565b600a805461045a90612ef0565b336000908152600e602052604081205460ff16611713576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f416464726573732063616c6c696e67206e6f742074727573746564000000000060448201526064016106a4565b61171b6104db565b611781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f546f6b656e20636f6e7472616374206f7574206f662066756e6473000000000060448201526064016106a4565b600460015460ff16600581111561179a5761179a612a1f565b1415611802576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f457363726f7720696e20436f6d706c657465207374617475732073746174650060448201526064016106a4565b600360015460ff16600581111561181b5761181b612a1f565b1415611883576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f457363726f7720696e205061696420737461747573207374617465000000000060448201526064016106a4565b61188b6120f8565b6005546118b59073ffffffffffffffffffffffffffffffffffffffff166118b06104db565b612353565b600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660051790556040517f63b958841f79ab97cb5456da181454b9932c0e15a3b17f1cbd27e2a8bc61043790600090a15060016119166001600055565b90565b336000908152600e602052604090205460ff16611992576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f416464726573732063616c6c696e67206e6f742074727573746564000000000060448201526064016106a4565b42600d54116119fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f436f6e747261637420657870697265640000000000000000000000000000000060448201526064016106a4565b73ffffffffffffffffffffffffffffffffffffffff8816611aa0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f496e76616c69642072657075746174696f6e206f7261636c652061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106a4565b73ffffffffffffffffffffffffffffffffffffffff8716611b1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f496e76616c6964207265636f7264696e67206f7261636c65206164647265737360448201526064016106a4565b73ffffffffffffffffffffffffffffffffffffffff8616611b9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c69642065786368616e6765206f7261636c6520616464726573730060448201526064016106a4565b60008360ff168560ff168760ff16611bb291906130cd565b611bbc91906130cd565b90506064811115611c29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f50657263656e74616765206f7574206f6620626f756e6473000000000000000060448201526064016106a4565b600060015460ff166005811115611c4257611c42612a1f565b14611ccf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f457363726f77206e6f7420696e204c61756e636865642073746174757320737460448201527f617465000000000000000000000000000000000000000000000000000000000060648201526084016106a4565b600180547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1661010073ffffffffffffffffffffffffffffffffffffffff8c81169190910291909117909155600280547fffffffffffffffffffffffff00000000000000000000000000000000000000009081168b84161790915560038054909116918916919091179055600680547fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000060ff898116919091027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1691909117750100000000000000000000000000000000000000000088831602177fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff16760100000000000000000000000000000000000000000000918716919091021790558251611e389060089060208601906128f9565b508151611e4c9060099060208501906128f9565b50600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016811790556040517f8ec464ac0c8e44e17130cd1ffb09967fa6f2c33339289678a59ea0112cfc2aa990611eab906008906009906131bc565b60405180910390a1505050505050505050565b600080611ecb83856130cd565b905083811015611f37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f77000000000060448201526064016106a4565b90505b92915050565b60005b81518110156120f457600073ffffffffffffffffffffffffffffffffffffffff16828281518110611f7657611f76612f9e565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280601481526020017f457363726f773a207a65726f206164647265737300000000000000000000000081525090612004576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a49190612a0c565b506001600e600084848151811061201d5761201d612f9e565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fad3769ac0c1a91ee9dcf369f6d2989f91572b6f876933bbc82ab85f6b969a07a8282815181106120a9576120a9612f9e565b60200260200101516040516120da919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180910390a1806120ec81612ffc565b915050611f43565b5050565b60026000541415612165576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016106a4565b6002600055565b6060600080600080855167ffffffffffffffff81111561218e5761218e612a8f565b6040519080825280602002602001820160405280156121b7578160200160208202803683370190505b5090506000806000805b89518110156123435760008a82815181106121de576121de612f9e565b6020026020010151905060008061221b606461221585600660149054906101000a900460ff1660ff1661237790919063ffffffff16565b9061242c565b90506122278782611ebe565b96506122338282611ebe565b915050600061228260646122158f878151811061225257612252612f9e565b60209081029190910101516006547501000000000000000000000000000000000000000000900460ff1690612377565b905061228e8682611ebe565b955061229a8282611ebe565b91505060006122ea60646122158f87815181106122b9576122b9612f9e565b6020908102919091010151600654760100000000000000000000000000000000000000000000900460ff1690612377565b90506122f68582611ebe565b94506123028282611ebe565b91506123109050828261246e565b87848151811061232257612322612f9e565b6020026020010181815250505050808061233b90612ffc565b9150506121c1565b5092989197509550909350915050565b6007546120f49073ffffffffffffffffffffffffffffffffffffffff1683836124b0565b60008261238657506000611f3a565b600061239283856131e1565b90508261239f858361321e565b14611f37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60448201527f770000000000000000000000000000000000000000000000000000000000000060648201526084016106a4565b6000611f3783836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612542565b6000611f3783836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612593565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261253d9084906125de565b505050565b6000818361257d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a49190612a0c565b50600061258a848661321e565b95945050505050565b600081848411156125d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a49190612a0c565b50600061258a8486613259565b6000612640826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126ed9092919063ffffffff16565b90508051600014806126615750808060200190518101906126619190613270565b61253d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016106a4565b60606126fc8484600085612704565b949350505050565b606082471015612796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016106a4565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516127bf9190612f44565b60006040518083038185875af1925050503d80600081146127fc576040519150601f19603f3d011682016040523d82523d6000602084013e612801565b606091505b50915091506128128783838761281d565b979650505050505050565b606083156128b05782516128a95773ffffffffffffffffffffffffffffffffffffffff85163b6128a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106a4565b50816126fc565b6126fc83838151156128c55781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a49190612a0c565b82805461290590612ef0565b90600052602060002090601f016020900481019282612927576000855561296d565b82601f1061294057805160ff191683800117855561296d565b8280016001018555821561296d579182015b8281111561296d578251825591602001919060010190612952565b5061297992915061297d565b5090565b5b80821115612979576000815560010161297e565b60005b838110156129ad578181015183820152602001612995565b838111156129bc576000848401525b50505050565b600081518084526129da816020860160208601612992565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611f3760208301846129c2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160068310612a89577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612b0557612b05612a8f565b604052919050565b600082601f830112612b1e57600080fd5b813567ffffffffffffffff811115612b3857612b38612a8f565b612b6960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612abe565b818152846020838601011115612b7e57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215612bae57600080fd5b823567ffffffffffffffff80821115612bc657600080fd5b612bd286838701612b0d565b93506020850135915080821115612be857600080fd5b50612bf585828601612b0d565b9150509250929050565b600067ffffffffffffffff821115612c1957612c19612a8f565b5060051b60200190565b803573ffffffffffffffffffffffffffffffffffffffff81168114612c4757600080fd5b919050565b600082601f830112612c5d57600080fd5b81356020612c72612c6d83612bff565b612abe565b82815260059290921b84018101918181019086841115612c9157600080fd5b8286015b84811015612cb357612ca681612c23565b8352918301918301612c95565b509695505050505050565b600060208284031215612cd057600080fd5b813567ffffffffffffffff811115612ce757600080fd5b6126fc84828501612c4c565b600080600080600060a08688031215612d0b57600080fd5b853567ffffffffffffffff80821115612d2357600080fd5b612d2f89838a01612c4c565b9650602091508188013581811115612d4657600080fd5b8801601f81018a13612d5757600080fd5b8035612d65612c6d82612bff565b81815260059190911b8201840190848101908c831115612d8457600080fd5b928501925b82841015612da257833582529285019290850190612d89565b98505050506040880135915080821115612dbb57600080fd5b612dc789838a01612b0d565b94506060880135915080821115612ddd57600080fd5b50612dea88828901612b0d565b95989497509295608001359392505050565b600060208284031215612e0e57600080fd5b611f3782612c23565b803560ff81168114612c4757600080fd5b600080600080600080600080610100898b031215612e4557600080fd5b612e4e89612c23565b9750612e5c60208a01612c23565b9650612e6a60408a01612c23565b9550612e7860608a01612e17565b9450612e8660808a01612e17565b9350612e9460a08a01612e17565b925060c089013567ffffffffffffffff80821115612eb157600080fd5b612ebd8c838d01612b0d565b935060e08b0135915080821115612ed357600080fd5b50612ee08b828c01612b0d565b9150509295985092959890939650565b600181811c90821680612f0457607f821691505b60208210811415612f3e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008251612f56818460208701612992565b9190910192915050565b600060208284031215612f7257600080fd5b5051919050565b604081526000612f8c60408301856129c2565b828103602084015261258a81856129c2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561302e5761302e612fcd565b5060010190565b606080825284519082018190526000906020906080840190828801845b8281101561308457815173ffffffffffffffffffffffffffffffffffffffff1684529284019290840190600101613052565b5050508381038285015285518082528683019183019060005b818110156130b95783518352928401929184019160010161309d565b5050851515604086015292506126fc915050565b600082198211156130e0576130e0612fcd565b500190565b8054600090600181811c90808316806130ff57607f831692505b602080841082141561313a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b838852602088018280156131555760018114613184576131af565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008716825282820197506131af565b60008981526020902060005b878110156131a957815484820152908601908401613190565b83019850505b5050505050505092915050565b6040815260006131cf60408301856130e5565b828103602084015261258a81856130e5565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561321957613219612fcd565b500290565b600082613254577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008282101561326b5761326b612fcd565b500390565b60006020828403121561328257600080fd5b81518015158114611f3757600080fdfea26469706673582212205081acc662e9c873833108cb5165d7086d03924a92145bbb4286a2b90256b8b664736f6c63430008090033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212209efb630075ff097beba24a7d047692f1c58e2a50e8eaf6dd2cb9ca4bc6a9441364736f6c63430008090033
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.