Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
MultiUserSmartAccountFactory
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; import "@openzeppelin/contracts/utils/Create2.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import "./MultiUserSmartAccount.sol"; /** * A sample factory contract for SimpleAccount * A UserOperations "initCode" holds the address of the factory, and a method call (to createAccount, in this sample factory). * The factory's createAccount returns the target account address even if it is already installed. * This way, the entryPoint.getSenderAddress() can be called either before or after the account is created. */ contract MultiUserSmartAccountFactory { MultiUserSmartAccount public immutable accountImplementation; constructor(IAlchemyEntryPoint _entryPoint) { accountImplementation = new MultiUserSmartAccount(_entryPoint); } /** * create an account, and return its address. * returns the address even if the account is already deployed. * Note that during UserOperation execution, this method is called only if the account is not deployed. * This method returns an existing account address so that entryPoint.getSenderAddress() would work even after account creation */ function createAccount(address owner, bytes32 salt) public returns (MultiUserSmartAccount ret) { address addr = getAddress(owner, salt); uint codeSize = addr.code.length; if (codeSize > 0) { return MultiUserSmartAccount(payable(addr)); } ret = MultiUserSmartAccount(payable(new ERC1967Proxy{salt : salt}( address(accountImplementation), abi.encodeCall(MultiUserSmartAccount.initialize, (owner)) ))); } /** * calculate the counterfactual address of this account as it would be returned by createAccount() */ function getAddress(address owner, bytes32 salt) public view returns (address) { return Create2.computeAddress(salt, keccak256(abi.encodePacked( type(ERC1967Proxy).creationCode, abi.encode( address(accountImplementation), abi.encodeCall(MultiUserSmartAccount.initialize, (owner)) ) ))); } }
// 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 IERC1822Proxiable { /** * @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 IERC1967 { /** * @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 IBeacon { /** * @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.7.0) (proxy/ERC1967/ERC1967Proxy.sol) pragma solidity ^0.8.0; import "../Proxy.sol"; import "./ERC1967Upgrade.sol"; /** * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an * implementation address that can be changed. This address is stored in storage in the location specified by * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the * implementation behind the proxy. */ contract ERC1967Proxy is Proxy, ERC1967Upgrade { /** * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`. * * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded * function call, and allows initializing the storage of the proxy like a Solidity constructor. */ constructor(address _logic, bytes memory _data) payable { _upgradeToAndCall(_logic, _data, false); } /** * @dev Returns the current implementation address. */ function _implementation() internal view virtual override returns (address impl) { return ERC1967Upgrade._getImplementation(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeacon.sol"; import "../../interfaces/IERC1967.sol"; import "../../interfaces/draft-IERC1822.sol"; import "../../utils/Address.sol"; import "../../utils/StorageSlot.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 ERC1967Upgrade is IERC1967 { // 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 StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.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) { Address.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 (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822Proxiable(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 StorageSlot.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"); StorageSlot.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 StorageSlot.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlot.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) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol) pragma solidity ^0.8.0; /** * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to * be specified by overriding the virtual {_implementation} function. * * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a * different contract through the {_delegate} function. * * The success and return data of the delegated call will be returned back to the caller of the proxy. */ abstract contract Proxy { /** * @dev Delegates the current call to `implementation`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _delegate(address implementation) internal virtual { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /** * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function * and {_fallback} should delegate. */ function _implementation() internal view virtual returns (address); /** * @dev Delegates the current call to the address returned by `_implementation()`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _fallback() internal virtual { _beforeFallback(); _delegate(_implementation()); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other * function in the contract matches the call data. */ fallback() external payable virtual { _fallback(); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data * is empty. */ receive() external payable virtual { _fallback(); } /** * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback` * call, or as part of the Solidity `fallback` or `receive` functions. * * If overridden should call `super._beforeFallback()`. */ function _beforeFallback() internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/Address.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) || (!Address.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-IERC1822.sol"; import "../ERC1967/ERC1967Upgrade.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 IERC1822Proxiable, ERC1967Upgrade { /// @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; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC777/IERC777Recipient.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC777TokensRecipient standard as defined in the EIP. * * Accounts can be notified of {IERC777} tokens being sent to them by having a * contract implement this interface (contract holders can be their own * implementer) and registering it on the * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry]. * * See {IERC1820Registry} and {ERC1820Implementer}. */ interface IERC777Recipient { /** * @dev Called by an {IERC777} token contract whenever tokens are being * moved or created into a registered account (`to`). The type of operation * is conveyed by `from` being the zero address or not. * * This call occurs _after_ the token contract's state is updated, so * {IERC777-balanceOf}, etc., can be used to query the post-operation state. * * This function may revert to prevent the operation from being executed. */ function tokensReceived( address operator, address from, address to, uint256 amount, bytes calldata userData, bytes calldata operatorData ) external; }
// 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 // OpenZeppelin Contracts (last updated v4.9.0) (utils/Create2.sol) pragma solidity ^0.8.0; /** * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer. * `CREATE2` can be used to compute in advance the address where a smart * contract will be deployed, which allows for interesting new mechanisms known * as 'counterfactual interactions'. * * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more * information. */ library Create2 { /** * @dev Deploys a contract using `CREATE2`. The address where the contract * will be deployed can be known in advance via {computeAddress}. * * The bytecode for a contract can be obtained from Solidity with * `type(contractName).creationCode`. * * Requirements: * * - `bytecode` must not be empty. * - `salt` must have not been used for `bytecode` already. * - the factory must have a balance of at least `amount`. * - if `amount` is non-zero, `bytecode` must have a `payable` constructor. */ function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) { require(address(this).balance >= amount, "Create2: insufficient balance"); require(bytecode.length != 0, "Create2: bytecode length is zero"); /// @solidity memory-safe-assembly assembly { addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt) } require(addr != address(0), "Create2: Failed on deploy"); } /** * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the * `bytecodeHash` or `salt` will result in a new destination address. */ function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) { return computeAddress(salt, bytecodeHash, address(this)); } /** * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}. */ function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) // Get free memory pointer // | | ↓ ptr ... ↓ ptr + 0x0B (start) ... ↓ ptr + 0x20 ... ↓ ptr + 0x40 ... | // |-------------------|---------------------------------------------------------------------------| // | bytecodeHash | CCCCCCCCCCCCC...CC | // | salt | BBBBBBBBBBBBB...BB | // | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA | // | 0xFF | FF | // |-------------------|---------------------------------------------------------------------------| // | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC | // | keccak(start, 85) | ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ | mstore(add(ptr, 0x40), bytecodeHash) mstore(add(ptr, 0x20), salt) mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff mstore8(start, 0xff) addr := keccak256(start, 85) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) { // 32 is the length in bytes of hash, // enforced by the type signature above /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") mstore(0x1c, hash) message := keccak256(0x00, 0x3c) } } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, "\x19\x01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) data := keccak256(ptr, 0x42) } } /** * @dev Returns an Ethereum Signed Data with intended validator, created from a * `validator` and `data` according to the version 0 of EIP-191. * * See {recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x00", validator, data)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { 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 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; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @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 256, 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 << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// 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 StorageSlot { 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) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; import "./UserOperation.sol"; /** * Aggregated Signatures validator. */ interface IAggregator { /** * validate aggregated signature. * revert if the aggregated signature does not match the given list of operations. */ function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view; /** * validate signature of a single userOp * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps. * @param userOp the userOperation received from the user. * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps. * (usually empty, unless account and aggregator support some kind of "multisig" */ function validateUserOpSignature(UserOperation calldata userOp) external view returns (bytes memory sigForUserOp); /** * aggregate multiple signatures into a single value. * This method is called off-chain to calculate the signature to pass with handleOps() * bundler MAY use optimized custom code perform this aggregation * @param userOps array of UserOperations to collect the signatures from. * @return aggregatedSignature the aggregated signature */ function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.12; /** * manage deposits and stakes. * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account) * stake is value locked for at least "unstakeDelay" by the staked entity. */ interface IStakeManager { event Deposited( address indexed account, uint256 totalDeposit ); event Withdrawn( address indexed account, address withdrawAddress, uint256 amount ); /// Emitted when stake or unstake delay are modified event StakeLocked( address indexed account, uint256 totalStaked, uint256 unstakeDelaySec ); /// Emitted once a stake is scheduled for withdrawal event StakeUnlocked( address indexed account, uint256 withdrawTime ); event StakeWithdrawn( address indexed account, address withdrawAddress, uint256 amount ); /** * @param deposit the entity's deposit * @param staked true if this entity is staked. * @param stake actual amount of ether staked for this entity. * @param unstakeDelaySec minimum delay to withdraw the stake. * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps) * and the rest fit into a 2nd cell. * 112 bit allows for 10^15 eth * 48 bit for full timestamp * 32 bit allows 150 years for unstake delay */ struct DepositInfo { uint112 deposit; bool staked; uint112 stake; uint32 unstakeDelaySec; uint48 withdrawTime; } //API struct used by getStakeInfo and simulateValidation struct StakeInfo { uint256 stake; uint256 unstakeDelaySec; } /// @return info - full deposit information of given account function getDepositInfo(address account) external view returns (DepositInfo memory info); /// @return the deposit (for gas payment) of the account function balanceOf(address account) external view returns (uint256); /** * add to the deposit of the given account */ function depositTo(address account) external payable; /** * add to the account's stake - amount and delay * any pending unstake is first cancelled. * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn. */ function addStake(uint32 _unstakeDelaySec) external payable; /** * attempt to unlock the stake. * the value can be withdrawn (using withdrawStake) after the unstake delay. */ function unlockStake() external; /** * withdraw from the (unlocked) stake. * must first call unlockStake and wait for the unstakeDelay to pass * @param withdrawAddress the address to send withdrawn value. */ function withdrawStake(address payable withdrawAddress) external; /** * withdraw from the deposit. * @param withdrawAddress the address to send withdrawn value. * @param withdrawAmount the amount to withdraw. */ function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; /* solhint-disable no-inline-assembly */ /** * User Operation struct * @param sender the sender account of this request. * @param nonce unique value the sender uses to verify it is not a replay. * @param initCode if set, the account contract will be created by this constructor/ * @param callData the method call to execute on this account. * @param callGasLimit the gas limit passed to the callData method call. * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp. * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead. * @param maxFeePerGas same as EIP-1559 gas parameter. * @param maxPriorityFeePerGas same as EIP-1559 gas parameter. * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender. * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID. */ struct UserOperation { address sender; uint256 nonce; bytes initCode; bytes callData; uint256 callGasLimit; uint256 verificationGasLimit; uint256 preVerificationGas; uint256 maxFeePerGas; uint256 maxPriorityFeePerGas; bytes paymasterAndData; bytes signature; } /** * Utility functions helpful when working with UserOperation structs. */ library UserOperationLib { function getSender(UserOperation calldata userOp) internal pure returns (address) { address data; //read sender from userOp, which is first userOp member (saves 800 gas...) assembly {data := calldataload(userOp)} return address(uint160(data)); } function gasPrice(UserOperation calldata userOp) internal view returns (uint256) { unchecked { uint256 maxFeePerGas = userOp.maxFeePerGas; uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas; if (maxFeePerGas == maxPriorityFeePerGas) { //legacy mode (for networks that don't support basefee opcode) return maxFeePerGas; } return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee); } } function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) { //lighter signature scheme. must match UserOp.ts#packUserOp bytes calldata sig = userOp.signature; // copy directly the userOp from calldata up to (but not including) the signature. // this encoding depends on the ABI encoding of calldata, but is much lighter to copy // than referencing each field separately. assembly { let ofs := userOp let len := sub(sub(sig.offset, ofs), 32) ret := mload(0x40) mstore(0x40, add(ret, add(len, 32))) mstore(ret, len) calldatacopy(add(ret, 32), ofs, len) } } function hash(UserOperation calldata userOp) internal pure returns (bytes32) { return keccak256(pack(userOp)); } function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; /* solhint-disable no-empty-blocks */ import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import "@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; /** * Token callback handler. * Handles supported tokens' callbacks, allowing account receiving these tokens. */ contract TokenCallbackHandler is IERC777Recipient, IERC721Receiver, IERC1155Receiver { function tokensReceived( address, address, address, uint256, bytes calldata, bytes calldata ) external pure override { } function onERC721Received( address, address, uint256, bytes calldata ) external pure override returns (bytes4) { return IERC721Receiver.onERC721Received.selector; } function onERC1155Received( address, address, uint256, uint256, bytes calldata ) external pure override returns (bytes4) { return IERC1155Receiver.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] calldata, uint256[] calldata, bytes calldata ) external pure override returns (bytes4) { return IERC1155Receiver.onERC1155BatchReceived.selector; } function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) { return interfaceId == type(IERC721Receiver).interfaceId || interfaceId == type(IERC1155Receiver).interfaceId || interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; /* solhint-disable avoid-low-level-calls */ /* solhint-disable no-empty-blocks */ import "../interfaces/IAlchemyAccount.sol"; import "../interfaces/IAlchemyEntryPoint.sol"; import "./AlchemyHelpers.sol"; /** * Basic account implementation. * this contract provides the basic logic for implementing the IAccount interface - validateUserOp * specific account implementation should inherit it and provide the account-specific logic */ abstract contract AlchemyBaseAccount is IAlchemyAccount { using AlchemyUserOperationLib for AlchemyUserOperation; //return value in case of signature failure, with no time-range. // equivalent to _packValidationData(true,0,0); uint256 constant internal SIG_VALIDATION_FAILED = 1; /** * Return the account nonce. * This method returns the next sequential nonce. * For a nonce of a specific key, use `entrypoint.getNonce(account, key)` */ function getNonce() public view virtual returns (uint256) { return entryPoint().getNonce(address(this), 0); } /** * return the entryPoint used by this account. * subclass should return the current entryPoint used by this account. */ function entryPoint() public view virtual returns (IAlchemyEntryPoint); /** * Validate user's signature and nonce. * subclass doesn't need to override this method. Instead, it should override the specific internal validation methods. */ function validateUserOp(AlchemyUserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds) external override virtual returns (uint256 validationData) { _requireFromEntryPoint(); validationData = _validateSignature(userOp, userOpHash); _validateNonce(userOp.nonce); _payPrefund(missingAccountFunds); } /** * ensure the request comes from the known entrypoint. */ function _requireFromEntryPoint() internal virtual view { require(msg.sender == address(entryPoint()), "account: not from EntryPoint"); } /** * validate the signature is valid for this message. * @param userOp validate the userOp.signature field * @param userOpHash convenient field: the hash of the request, to check the signature against * (also hashes the entrypoint and chain id) * @return validationData signature and time-range of this operation * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure, * otherwise, an address of an "authorizer" contract. * <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite" * <6-byte> validAfter - first timestamp this operation is valid * If the account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure. * Note that the validation code cannot use block.timestamp (or block.number) directly. */ function _validateSignature(AlchemyUserOperation calldata userOp, bytes32 userOpHash) internal virtual returns (uint256 validationData); /** * Validate the nonce of the UserOperation. * This method may validate the nonce requirement of this account. * e.g. * To limit the nonce to use sequenced UserOps only (no "out of order" UserOps): * `require(nonce < type(uint64).max)` * For a hypothetical account that *requires* the nonce to be out-of-order: * `require(nonce & type(uint64).max == 0)` * * The actual nonce uniqueness is managed by the EntryPoint, and thus no other * action is needed by the account itself. * * @param nonce to validate * * solhint-disable-next-line no-empty-blocks */ function _validateNonce(uint256 nonce) internal view virtual { } /** * sends to the entrypoint (msg.sender) the missing funds for this transaction. * subclass MAY override this method for better funds management * (e.g. send to the entryPoint more than the minimum required, so that in future transactions * it will not be required to send again) * @param missingAccountFunds the minimum value this method should send the entrypoint. * this value MAY be zero, in case there is enough deposit, or the userOp has a paymaster. */ function _payPrefund(uint256 missingAccountFunds) internal virtual { if (missingAccountFunds != 0) { (bool success,) = payable(msg.sender).call{value : missingAccountFunds, gas : type(uint256).max}(""); (success); //ignore failure (its EntryPoint's job to verify, not account.) } } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; /* solhint-disable no-inline-assembly */ /** * returned data from validateUserOp. * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData` * @param aggregator - address(0) - the account validated the signature by itself. * address(1) - the account failed to validate the signature. * otherwise - this is an address of a signature aggregator that must be used to validate the signature. * @param validAfter - this UserOp is valid only after this timestamp. * @param validaUntil - this UserOp is valid only up to this timestamp. */ struct ValidationData { address aggregator; uint48 validAfter; uint48 validUntil; } //extract sigFailed, validAfter, validUntil. // also convert zero validUntil to type(uint48).max function _parseValidationData(uint validationData) pure returns (ValidationData memory data) { address aggregator = address(uint160(validationData)); uint48 validUntil = uint48(validationData >> 160); if (validUntil == 0) { validUntil = type(uint48).max; } uint48 validAfter = uint48(validationData >> (48 + 160)); return ValidationData(aggregator, validAfter, validUntil); } // intersect account and paymaster ranges. function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) { ValidationData memory accountValidationData = _parseValidationData(validationData); ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData); address aggregator = accountValidationData.aggregator; if (aggregator == address(0)) { aggregator = pmValidationData.aggregator; } uint48 validAfter = accountValidationData.validAfter; uint48 validUntil = accountValidationData.validUntil; uint48 pmValidAfter = pmValidationData.validAfter; uint48 pmValidUntil = pmValidationData.validUntil; if (validAfter < pmValidAfter) validAfter = pmValidAfter; if (validUntil > pmValidUntil) validUntil = pmValidUntil; return ValidationData(aggregator, validAfter, validUntil); } /** * helper to pack the return value for validateUserOp * @param data - the ValidationData to pack */ function _packValidationData(ValidationData memory data) pure returns (uint256) { return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48)); } /** * helper to pack the return value for validateUserOp, when not using an aggregator * @param sigFailed - true for signature failure, false for success * @param validUntil last timestamp this UserOperation is valid (or zero for infinite) * @param validAfter first timestamp this UserOperation is valid */ function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) { return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48)); } /** * keccak function over calldata. * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it. */ function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) { assembly { let mem := mload(0x40) let len := data.length calldatacopy(mem, data.offset, len) ret := keccak256(mem, len) } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; /* solhint-disable no-inline-assembly */ import {calldataKeccak} from "../core/AlchemyHelpers.sol"; /** * User Operation struct * @param sender the sender account of this request. * @param nonce unique value the sender uses to verify it is not a replay. * @param initCode if set, the account contract will be created by this constructor/ * @param callData the method call to execute on this account. * @param callGasLimit the gas limit passed to the callData method call. * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp. * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead. * @param maxFeePerGas same as EIP-1559 gas parameter. * @param maxPriorityFeePerGas same as EIP-1559 gas parameter. * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender. * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID. */ struct AlchemyUserOperation { address sender; uint256 nonce; bytes initCode; bytes callData; uint256 callGasLimit; uint256 verificationGasLimit; uint256 preVerificationGas; uint256 maxFeePerGas; uint256 maxPriorityFeePerGas; bytes paymasterAndData; bytes signature; } /** * Utility functions helpful when working with UserOperation structs. */ library AlchemyUserOperationLib { function getSender(AlchemyUserOperation calldata userOp) internal pure returns (address) { address data; //read sender from userOp, which is first userOp member (saves 800 gas...) assembly {data := calldataload(userOp)} return address(uint160(data)); } //relayer/block builder might submit the TX with higher priorityFee, but the user should not // pay above what he signed for. function gasPrice(AlchemyUserOperation calldata userOp) internal view returns (uint256) { unchecked { uint256 maxFeePerGas = userOp.maxFeePerGas; uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas; if (maxFeePerGas == maxPriorityFeePerGas) { //legacy mode (for networks that don't support basefee opcode) return maxFeePerGas; } return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee); } } function pack(AlchemyUserOperation calldata userOp) internal pure returns (bytes memory ret) { address sender = getSender(userOp); uint256 nonce = userOp.nonce; bytes32 hashInitCode = calldataKeccak(userOp.initCode); bytes32 hashCallData = calldataKeccak(userOp.callData); uint256 callGasLimit = userOp.callGasLimit; uint256 verificationGasLimit = userOp.verificationGasLimit; uint256 preVerificationGas = userOp.preVerificationGas; uint256 maxFeePerGas = userOp.maxFeePerGas; uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas; bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData); return abi.encode( sender, nonce, hashInitCode, hashCallData, callGasLimit, verificationGasLimit, preVerificationGas, maxFeePerGas, maxPriorityFeePerGas, hashPaymasterAndData ); } function hash(AlchemyUserOperation calldata userOp) internal pure returns (bytes32) { return keccak256(pack(userOp)); } function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; import "./AlchemyUserOperation.sol"; interface IAlchemyAccount { /** * Validate user's signature and nonce * the entryPoint will make the call to the recipient only if this validation call returns successfully. * signature failure should be reported by returning SIG_VALIDATION_FAILED (1). * This allows making a "simulation call" without a valid signature * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure. * * @dev Must validate caller is the entryPoint. * Must validate the signature and nonce * @param userOp the operation that is about to be executed. * @param userOpHash hash of the user's request data. can be used as the basis for signature. * @param missingAccountFunds missing funds on the account's deposit in the entrypoint. * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call. * The excess is left as a deposit in the entrypoint, for future calls. * can be withdrawn anytime using "entryPoint.withdrawTo()" * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero. * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure, * otherwise, an address of an "authorizer" contract. * <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite" * <6-byte> validAfter - first timestamp this operation is valid * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure. * Note that the validation code cannot use block.timestamp (or block.number) directly. */ function validateUserOp(AlchemyUserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds) external returns (uint256 validationData); }
/** ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation. ** Only one instance required on each chain. **/ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; /* solhint-disable avoid-low-level-calls */ /* solhint-disable no-inline-assembly */ /* solhint-disable reason-string */ import "../../../account-abstraction/interfaces/IStakeManager.sol"; import "../../../account-abstraction/interfaces/IAggregator.sol"; import "./AlchemyUserOperation.sol"; import "./IAlchemyNonceManager.sol"; interface IAlchemyEntryPoint is IStakeManager, IAlchemyNonceManager { /*** * An event emitted after each successful request * @param userOpHash - unique identifier for the request (hash its entire content, except signature). * @param sender - the account that generates this request. * @param paymaster - if non-null, the paymaster that pays for this request. * @param nonce - the nonce value from the request. * @param success - true if the sender transaction succeeded, false if reverted. * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation. * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution). */ event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed); /** * account "sender" was deployed. * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow. * @param sender the account that is deployed * @param factory the factory used to deploy this account (in the initCode) * @param paymaster the paymaster used by this UserOp */ event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster); /** * An event emitted if the UserOperation "callData" reverted with non-zero length * @param userOpHash the request unique identifier. * @param sender the sender of this request * @param nonce the nonce used in the request * @param revertReason - the return bytes from the (reverted) call to "callData". */ event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason); /** * an event emitted by handleOps(), before starting the execution loop. * any event emitted before this event, is part of the validation. */ event BeforeExecution(); /** * signature aggregator used by the following UserOperationEvents within this bundle. */ event SignatureAggregatorChanged(address indexed aggregator); /** * a custom revert error of handleOps, to identify the offending op. * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it. * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero) * @param reason - revert reason * The string starts with a unique code "AAmn", where "m" is "1" for factory, "2" for account and "3" for paymaster issues, * so a failure can be attributed to the correct entity. * Should be caught in off-chain handleOps simulation and not happen on-chain. * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts. */ error FailedOp(uint256 opIndex, string reason); /** * error case when a signature aggregator fails to verify the aggregated signature it had created. */ error SignatureValidationFailed(address aggregator); /** * Successful result from simulateValidation. * @param returnInfo gas and time-range returned values * @param senderInfo stake information about the sender * @param factoryInfo stake information about the factory (if any) * @param paymasterInfo stake information about the paymaster (if any) */ error ValidationResult(ReturnInfo returnInfo, StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo); /** * Successful result from simulateValidation, if the account returns a signature aggregator * @param returnInfo gas and time-range returned values * @param senderInfo stake information about the sender * @param factoryInfo stake information about the factory (if any) * @param paymasterInfo stake information about the paymaster (if any) * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator) * bundler MUST use it to verify the signature, or reject the UserOperation */ error ValidationResultWithAggregation(ReturnInfo returnInfo, StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo, AggregatorStakeInfo aggregatorInfo); /** * return value of getSenderAddress */ error SenderAddressResult(address sender); /** * return value of simulateHandleOp */ error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult); //UserOps handled, per aggregator struct UserOpsPerAggregator { AlchemyUserOperation[] userOps; // aggregator address IAggregator aggregator; // aggregated signature bytes signature; } /** * Execute a batch of UserOperation. * no signature aggregator is used. * if any account requires an aggregator (that is, it returned an aggregator when * performing simulateValidation), then handleAggregatedOps() must be used instead. * @param ops the operations to execute * @param beneficiary the address to receive the fees */ function handleOps(AlchemyUserOperation[] calldata ops, address payable beneficiary) external; /** * Execute a batch of UserOperation with Aggregators * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts) * @param beneficiary the address to receive the fees */ function handleAggregatedOps( UserOpsPerAggregator[] calldata opsPerAggregator, address payable beneficiary ) external; /** * generate a request Id - unique identifier for this request. * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid. */ function getUserOpHash(AlchemyUserOperation calldata userOp) external view returns (bytes32); /** * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp. * @dev this method always revert. Successful result is ValidationResult error. other errors are failures. * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data. * @param userOp the user operation to validate. */ function simulateValidation(AlchemyUserOperation calldata userOp) external; /** * gas and return values during simulation * @param preOpGas the gas used for validation (including preValidationGas) * @param prefund the required prefund for this operation * @param sigFailed validateUserOp's (or paymaster's) signature check failed * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range) * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range) * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp) */ struct ReturnInfo { uint256 preOpGas; uint256 prefund; bool sigFailed; uint48 validAfter; uint48 validUntil; bytes paymasterContext; } /** * returned aggregated signature info. * the aggregator returned by the account, and its current stake. */ struct AggregatorStakeInfo { address aggregator; StakeInfo stakeInfo; } /** * Get counterfactual sender address. * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. * this method always revert, and returns the address in SenderAddressResult error * @param initCode the constructor code to be passed into the UserOperation. */ function getSenderAddress(bytes memory initCode) external; /** * simulate full execution of a UserOperation (including both validation and target execution) * this method will always revert with "ExecutionResult". * it performs full validation of the UserOperation, but ignores signature error. * an optional target address is called after the userop succeeds, and its value is returned * (before the entire call is reverted) * Note that in order to collect the the success/failure of the target call, it must be executed * with trace enabled to track the emitted events. * @param op the UserOperation to simulate * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult * are set to the return from that call. * @param targetCallData callData to pass to target address */ function simulateHandleOp(AlchemyUserOperation calldata op, address target, bytes calldata targetCallData) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; interface IAlchemyNonceManager { /** * Return the next nonce for this sender. * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop) * But UserOp with different keys can come with arbitrary order. * * @param sender the account address * @param key the high 192 bit of the nonce * @return nonce a full nonce to pass for next UserOp with this sender. */ function getNonce(address sender, uint192 key) external view returns (uint256 nonce); /** * Manually increment the nonce of the sender. * This method is exposed just for completeness.. * Account does NOT need to call it, neither during validation, nor elsewhere, * as the EntryPoint will update the nonce regardless. * Possible use-case is call it with various keys to "initialize" their nonces to one, so that future * UserOperations will not pay extra for the first transaction with a given key. */ function incrementNonce(uint192 key) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; /* solhint-disable avoid-low-level-calls */ /* solhint-disable no-inline-assembly */ /* solhint-disable reason-string */ import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; import "../../../account-impl/callback/TokenCallbackHandler.sol"; import "../../MultiOwnable.sol"; import "../../account-abstraction/core/AlchemyBaseAccount.sol"; /** * minimal account. * this is sample minimal account. * has execute, eth handling methods * has a single signer that can send requests through the entryPoint. */ contract MultiUserSmartAccount is MultiOwnable, AlchemyBaseAccount, TokenCallbackHandler, UUPSUpgradeable, Initializable { using ECDSA for bytes32; IAlchemyEntryPoint private immutable _entryPoint; event MultiUserInitialized(IAlchemyEntryPoint indexed entryPoint, address indexed owner); /// @inheritdoc AlchemyBaseAccount function entryPoint() public view virtual override returns (IAlchemyEntryPoint) { return _entryPoint; } // solhint-disable-next-line no-empty-blocks receive() external payable {} constructor(IAlchemyEntryPoint anEntryPoint) { _entryPoint = anEntryPoint; _disableInitializers(); } function _onlyOwner() internal override view { //directly from EOA owner, or through the account itself (which gets redirected through execute()) require(owners[msg.sender]|| msg.sender == address(this), "only owner"); } function isOwner(address addr) internal view returns (bool) { return owners[addr]; } /** * execute a transaction (called directly from owner, or by entryPoint) */ function execute(address dest, uint256 value, bytes calldata func) external { _requireFromEntryPointOrOwner(); _call(dest, value, func); } /** * execute a sequence of transactions */ function executeBatch(address[] calldata dest, bytes[] calldata func) external { _requireFromEntryPointOrOwner(); require(dest.length == func.length, "wrong array lengths"); for (uint256 i = 0; i < dest.length; i++) { _call(dest[i], 0, func[i]); } } /** * @dev The _entryPoint member is immutable, to reduce gas consumption. To upgrade EntryPoint, * a new implementation of SimpleAccount must be deployed with the new EntryPoint address, then upgrading * the implementation by calling `upgradeTo()` */ function initialize(address anOwner) public virtual initializer { _initialize(anOwner); } function _initialize(address anOwner) internal virtual { owners[anOwner] = true; emit MultiUserInitialized(_entryPoint, anOwner); } // Require the function call went through EntryPoint or owner function _requireFromEntryPointOrOwner() internal view { require(msg.sender == address(entryPoint()) || isOwner(msg.sender), "account: not Owner or EntryPoint"); } /// implement template method of BaseAccount function _validateSignature(AlchemyUserOperation calldata userOp, bytes32 userOpHash) internal override virtual returns (uint256 validationData) { bytes32 hash = userOpHash.toEthSignedMessageHash(); address recovered = hash.recover(userOp.signature); if (!isOwner(recovered)) return SIG_VALIDATION_FAILED; return 0; } function _call(address target, uint256 value, bytes memory data) internal { (bool success, bytes memory result) = target.call{value : value}(data); if (!success) { assembly { revert(add(result, 32), mload(result)) } } } /** * check current account deposit in the entryPoint */ function getDeposit() public view returns (uint256) { return entryPoint().balanceOf(address(this)); } /** * deposit more funds for this account in the entryPoint */ function addDeposit() public payable { entryPoint().depositTo{value : msg.value}(address(this)); } /** * withdraw value from the account's deposit * @param withdrawAddress target to send to * @param amount to withdraw */ function withdrawDepositTo(address payable withdrawAddress, uint256 amount) public onlyOwner { entryPoint().withdrawTo(withdrawAddress, amount); } function _authorizeUpgrade(address newImplementation) internal view override { (newImplementation); _onlyOwner(); } /** * check ERC-1271 signature. We support both eth_sign and raw signatures * @param _hash hash to be signed * @param _signature signature */ function isValidSignature( bytes32 _hash, bytes memory _signature ) public view returns (bytes4) { if(isOwner(ECDSA.recover(_hash, _signature))) { return 0x1626ba7e; } bytes32 hash = ECDSA.toEthSignedMessageHash(_hash); address recovered = ECDSA.recover(hash, _signature); // Validate signatures if (isOwner(recovered)) { return 0x1626ba7e; } else { return 0xffffffff; } } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; /* solhint-disable reason-string */ abstract contract MultiOwnable { // Events event OwnershipGranted(address newOwner); event OwnershipRevoked(address revokedOwner); mapping(address account => bool) public owners; modifier onlyOwner() { _onlyOwner(); _; } function _onlyOwner() internal virtual view { require(owners[msg.sender], "only owner"); } function grantOwnership(address newOwner) public onlyOwner { owners[newOwner] = true; emit OwnershipGranted(newOwner); } function revokeOwnership(address owner) public onlyOwner { owners[owner] = false; emit OwnershipRevoked(owner); } }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
[{"inputs":[{"internalType":"contract IAlchemyEntryPoint","name":"_entryPoint","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"accountImplementation","outputs":[{"internalType":"contract MultiUserSmartAccount","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"createAccount","outputs":[{"internalType":"contract MultiUserSmartAccount","name":"ret","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"getAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a060405234801561001057600080fd5b50604051620048cd380380620048cd83398181016040528101906100349190610124565b80604051610041906100a1565b61004b91906101b0565b604051809103906000f080158015610067573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1681525050506101cb565b61380080620010cd83390190565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100df826100b4565b9050919050565b60006100f1826100d4565b9050919050565b610101816100e6565b811461010c57600080fd5b50565b60008151905061011e816100f8565b92915050565b60006020828403121561013a576101396100af565b5b60006101488482850161010f565b91505092915050565b6000819050919050565b600061017661017161016c846100b4565b610151565b6100b4565b9050919050565b60006101888261015b565b9050919050565b600061019a8261017d565b9050919050565b6101aa8161018f565b82525050565b60006020820190506101c560008301846101a1565b92915050565b608051610ed9620001f46000396000818160db0152818161012c01526102410152610ed96000f3fe60806040523480156200001157600080fd5b5060043610620000465760003560e01c806311464fbe146200004b5780637ac4ed64146200006d578063f14ddffc14620000a3575b600080fd5b62000055620000d9565b604051620000649190620003db565b60405180910390f35b6200008b60048036038101906200008591906200047d565b620000fd565b6040516200009a9190620004d5565b60405180910390f35b620000c16004803603810190620000bb91906200047d565b620001fc565b604051620000d09190620003db565b60405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b6000620001f48260405180602001620001169062000342565b6020820181038252601f19601f820116604052507f0000000000000000000000000000000000000000000000000000000000000000866040516024016200015e9190620004d5565b60405160208183030381529060405263c4d66de860e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051602001620001b69291906200058c565b604051602081830303815290604052604051602001620001d892919062000602565b6040516020818303038152906040528051906020012062000300565b905092915050565b6000806200020b8484620000fd565b905060008173ffffffffffffffffffffffffffffffffffffffff163b905060008111156200023e578192505050620002fa565b837f000000000000000000000000000000000000000000000000000000000000000086604051602401620002739190620004d5565b60405160208183030381529060405263c4d66de860e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051620002c69062000342565b620002d39291906200058c565b8190604051809103906000f5905080158015620002f4573d6000803e3d6000fd5b50925050505b92915050565b60006200030f83833062000317565b905092915050565b6000604051836040820152846020820152828152600b810160ff815360558120925050509392505050565b610879806200062b83390190565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006200039b620003956200038f8462000350565b62000370565b62000350565b9050919050565b6000620003af826200037a565b9050919050565b6000620003c382620003a2565b9050919050565b620003d581620003b6565b82525050565b6000602082019050620003f26000830184620003ca565b92915050565b600080fd5b60006200040a8262000350565b9050919050565b6200041c81620003fd565b81146200042857600080fd5b50565b6000813590506200043c8162000411565b92915050565b6000819050919050565b620004578162000442565b81146200046357600080fd5b50565b60008135905062000477816200044c565b92915050565b60008060408385031215620004975762000496620003f8565b5b6000620004a7858286016200042b565b9250506020620004ba8582860162000466565b9150509250929050565b620004cf81620003fd565b82525050565b6000602082019050620004ec6000830184620004c4565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156200052e57808201518184015260208101905062000511565b60008484015250505050565b6000601f19601f8301169050919050565b60006200055882620004f2565b620005648185620004fd565b9350620005768185602086016200050e565b62000581816200053a565b840191505092915050565b6000604082019050620005a36000830185620004c4565b8181036020830152620005b781846200054b565b90509392505050565b600081905092915050565b6000620005d882620004f2565b620005e48185620005c0565b9350620005f68185602086016200050e565b80840191505092915050565b6000620006108285620005cb565b91506200061e8284620005cb565b9150819050939250505056fe608060405260405161087938038061087983398181016040528101906100259190610520565b6100378282600061003e60201b60201c565b505061074f565b61004d8361007660201b60201c565b60008251118061005a5750805b156100715761006f83836100cb60201b60201c565b505b505050565b610085816100fe60201b60201c565b8073ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a250565b60606100f68383604051806060016040528060278152602001610852602791396101c360201b60201c565b905092915050565b61010d8161024f60201b60201c565b61014c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610143906105ff565b60405180910390fd5b8061017f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61027260201b60201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516101ed9190610666565b600060405180830381855af49150503d8060008114610228576040519150601f19603f3d011682016040523d82523d6000602084013e61022d565b606091505b50915091506102448683838761027c60201b60201c565b925050509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000819050919050565b606083156102e45760008351036102dc5761029c8561024f60201b60201c565b6102db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d2906106c9565b60405180910390fd5b5b8290506102f5565b6102f483836102fd60201b60201c565b5b949350505050565b6000825111156103105781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610344919061072d565b60405180910390fd5b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061038c82610361565b9050919050565b61039c81610381565b81146103a757600080fd5b50565b6000815190506103b981610393565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610412826103c9565b810181811067ffffffffffffffff82111715610431576104306103da565b5b80604052505050565b600061044461034d565b90506104508282610409565b919050565b600067ffffffffffffffff8211156104705761046f6103da565b5b610479826103c9565b9050602081019050919050565b60005b838110156104a4578082015181840152602081019050610489565b60008484015250505050565b60006104c36104be84610455565b61043a565b9050828152602081018484840111156104df576104de6103c4565b5b6104ea848285610486565b509392505050565b600082601f830112610507576105066103bf565b5b81516105178482602086016104b0565b91505092915050565b6000806040838503121561053757610536610357565b5b6000610545858286016103aa565b925050602083015167ffffffffffffffff8111156105665761056561035c565b5b610572858286016104f2565b9150509250929050565b600082825260208201905092915050565b7f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60008201527f6f74206120636f6e747261637400000000000000000000000000000000000000602082015250565b60006105e9602d8361057c565b91506105f48261058d565b604082019050919050565b60006020820190508181036000830152610618816105dc565b9050919050565b600081519050919050565b600081905092915050565b60006106408261061f565b61064a818561062a565b935061065a818560208601610486565b80840191505092915050565b60006106728284610635565b915081905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b60006106b3601d8361057c565b91506106be8261067d565b602082019050919050565b600060208201905081810360008301526106e2816106a6565b9050919050565b600081519050919050565b60006106ff826106e9565b610709818561057c565b9350610719818560208601610486565b610722816103c9565b840191505092915050565b6000602082019050818103600083015261074781846106f4565b905092915050565b60f58061075d6000396000f3fe608060405236601057600e6018565b005b60166018565b005b601e602c565b602a6026602e565b603b565b565b565b600060366060565b905090565b3660008037600080366000845af43d6000803e8060008114605b573d6000f35b3d6000fd5b6000608c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b60b5565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600081905091905056fea2646970667358221220404231478476d0836c45ca1dd9071786393ae16c95f87363908750439632ebf164736f6c63430008130033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212205c277caf5f702b53138288783289754c0aad4e2df0e37c160bbe76e8a080b08964736f6c6343000813003360c06040523073ffffffffffffffffffffffffffffffffffffffff1660809073ffffffffffffffffffffffffffffffffffffffff168152503480156200004457600080fd5b50604051620038003803806200380083398181016040528101906200006a9190620001fa565b8073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1681525050620000ae620000b560201b60201c565b5062000310565b60018054906101000a900460ff161562000106576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000fd90620002b3565b60405180910390fd5b60ff8016600160009054906101000a900460ff1660ff16146200017a5760ff600160006101000a81548160ff021916908360ff1602179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860ff604051620001719190620002f3565b60405180910390a15b565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620001ae8262000181565b9050919050565b6000620001c282620001a1565b9050919050565b620001d481620001b5565b8114620001e057600080fd5b50565b600081519050620001f481620001c9565b92915050565b6000602082840312156200021357620002126200017c565b5b60006200022384828501620001e3565b91505092915050565b600082825260208201905092915050565b7f496e697469616c697a61626c653a20636f6e747261637420697320696e69746960008201527f616c697a696e6700000000000000000000000000000000000000000000000000602082015250565b60006200029b6027836200022c565b9150620002a8826200023d565b604082019050919050565b60006020820190508181036000830152620002ce816200028c565b9050919050565b600060ff82169050919050565b620002ed81620002d5565b82525050565b60006020820190506200030a6000830184620002e2565b92915050565b60805160a0516134a76200035960003960008181610dd901526117710152600081816108000152818161088e01528181610ab001528181610b3e0152610bee01526134a76000f3fe60806040526004361061012d5760003560e01c80634f1ef286116100ab578063b61d27f61161006f578063b61d27f6146103dc578063bc197c8114610405578063c399ec8814610442578063c4d66de81461046d578063d087d28814610496578063f23a6e61146104c157610134565b80634f1ef2861461031857806352d1902d1461033457806383cfbd7f1461035f578063acfd82f214610388578063b0d691fe146103b157610134565b806318dfb3c7116100f257806318dfb3c7146102565780633659cfe61461027f5780633a871cdd146102a85780634a58db19146102e55780634d44560d146102ef57610134565b806223de291461013957806301ffc9a714610162578063022914a71461019f578063150b7a02146101dc5780631626ba7e1461021957610134565b3661013457005b600080fd5b34801561014557600080fd5b50610160600480360381019061015b9190611e3b565b6104fe565b005b34801561016e57600080fd5b5061018960048036038101906101849190611f62565b610508565b6040516101969190611faa565b60405180910390f35b3480156101ab57600080fd5b506101c660048036038101906101c19190611fc5565b610642565b6040516101d39190611faa565b60405180910390f35b3480156101e857600080fd5b5061020360048036038101906101fe9190611ff2565b610662565b6040516102109190612089565b60405180910390f35b34801561022557600080fd5b50610240600480360381019061023b919061221b565b610677565b60405161024d9190612089565b60405180910390f35b34801561026257600080fd5b5061027d60048036038101906102789190612323565b6106ec565b005b34801561028b57600080fd5b506102a660048036038101906102a19190611fc5565b6107fe565b005b3480156102b457600080fd5b506102cf60048036038101906102ca91906123c9565b610986565b6040516102dc9190612447565b60405180910390f35b6102ed6109b9565b005b3480156102fb57600080fd5b50610316600480360381019061031191906124a0565b610a2e565b005b610332600480360381019061032d91906124e0565b610aae565b005b34801561034057600080fd5b50610349610bea565b604051610356919061254b565b60405180910390f35b34801561036b57600080fd5b5061038660048036038101906103819190611fc5565b610ca3565b005b34801561039457600080fd5b506103af60048036038101906103aa9190611fc5565b610d3c565b005b3480156103bd57600080fd5b506103c6610dd5565b6040516103d391906125c5565b60405180910390f35b3480156103e857600080fd5b5061040360048036038101906103fe91906125e0565b610dfd565b005b34801561041157600080fd5b5061042c600480360381019061042791906126aa565b610e5a565b6040516104399190612089565b60405180910390f35b34801561044e57600080fd5b50610457610e72565b6040516104649190612447565b60405180910390f35b34801561047957600080fd5b50610494600480360381019061048f9190611fc5565b610efa565b005b3480156104a257600080fd5b506104ab61103a565b6040516104b89190612447565b60405180910390f35b3480156104cd57600080fd5b506104e860048036038101906104e39190612786565b6110c5565b6040516104f59190612089565b60405180910390f35b5050505050505050565b60007f150b7a02000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806105d357507f4e2312e0000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061063b57507f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60006020528060005260406000206000915054906101000a900460ff1681565b600063150b7a0260e01b905095945050505050565b600061068b61068684846110db565b611102565b1561069f57631626ba7e60e01b90506106e6565b60006106aa84611157565b905060006106b882856110db565b90506106c381611102565b156106d957631626ba7e60e01b925050506106e6565b63ffffffff60e01b925050505b92915050565b6106f461118d565b81819050848490501461073c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107339061287d565b60405180910390fd5b60005b848490508110156107f7576107e48585838181106107605761075f61289d565b5b90506020020160208101906107759190611fc5565b600085858581811061078a5761078961289d565b5b905060200281019061079c91906128db565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611214565b80806107ef9061296d565b91505061073f565b5050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff160361088c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161088390612a27565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166108cb611298565b73ffffffffffffffffffffffffffffffffffffffff1614610921576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161091890612ab9565b60405180910390fd5b61092a816112ef565b61098381600067ffffffffffffffff811115610949576109486120f0565b5b6040519080825280601f01601f19166020018201604052801561097b5781602001600182028036833780820191505090505b5060006112fa565b50565b6000610990611468565b61099a84846114df565b90506109a9846020013561157c565b6109b28261157f565b9392505050565b6109c1610dd5565b73ffffffffffffffffffffffffffffffffffffffff1663b760faf934306040518363ffffffff1660e01b81526004016109fa9190612ae8565b6000604051808303818588803b158015610a1357600080fd5b505af1158015610a27573d6000803e3d6000fd5b5050505050565b610a3661161b565b610a3e610dd5565b73ffffffffffffffffffffffffffffffffffffffff1663205c287883836040518363ffffffff1660e01b8152600401610a78929190612b12565b600060405180830381600087803b158015610a9257600080fd5b505af1158015610aa6573d6000803e3d6000fd5b505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1603610b3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3390612a27565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610b7b611298565b73ffffffffffffffffffffffffffffffffffffffff1614610bd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bc890612ab9565b60405180910390fd5b610bda826112ef565b610be6828260016112fa565b5050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1614610c7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c7190612bad565b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b905090565b610cab61161b565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507f0d715ebedf3d01353f62c2245e0afc27d98f1bc0fb99512f42873fb9879f023981604051610d319190612ae8565b60405180910390a150565b610d4461161b565b60016000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507f24fef68333a009942a0d4864d8fdf2266e208a96399f135b05c1dc92c3c31f9281604051610dca9190612ae8565b60405180910390a150565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b610e0561118d565b610e54848484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611214565b50505050565b600063bc197c8160e01b905098975050505050505050565b6000610e7c610dd5565b73ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610eb49190612ae8565b602060405180830381865afa158015610ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef59190612be2565b905090565b600060018054906101000a900460ff16159050808015610f2b575060018060009054906101000a900460ff1660ff16105b80610f595750610f3a306116de565b158015610f58575060018060009054906101000a900460ff1660ff16145b5b610f98576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8f90612c81565b60405180910390fd5b60018060006101000a81548160ff021916908360ff1602179055508015610fd45760018060016101000a81548160ff0219169083151502179055505b610fdd82611701565b80156110365760006001806101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498600160405161102d9190612ce9565b60405180910390a15b5050565b6000611044610dd5565b73ffffffffffffffffffffffffffffffffffffffff166335567e1a3060006040518363ffffffff1660e01b815260040161107f929190612d63565b602060405180830381865afa15801561109c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110c09190612be2565b905090565b600063f23a6e6160e01b90509695505050505050565b60008060006110ea85856117d5565b915091506110f781611826565b819250505092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60007f19457468657265756d205369676e6564204d6573736167653a0a33320000000060005281601c52603c6000209050919050565b611195610dd5565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806111d357506111d233611102565b5b611212576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120990612dd8565b60405180910390fd5b565b6000808473ffffffffffffffffffffffffffffffffffffffff16848460405161123d9190612e69565b60006040518083038185875af1925050503d806000811461127a576040519150601f19603f3d011682016040523d82523d6000602084013e61127f565b606091505b50915091508161129157805160208201fd5b5050505050565b60006112c67f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61198c565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6112f761161b565b50565b6113267f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd914360001b611996565b60000160009054906101000a900460ff161561134a57611345836119a0565b611463565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156113b257506040513d601f19601f820116820180604052508101906113af9190612e95565b60015b6113f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113e890612f34565b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b8114611456576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144d90612fc6565b60405180910390fd5b50611462838383611a59565b5b505050565b611470610dd5565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146114dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114d490613032565b60405180910390fd5b565b6000806114eb83611157565b905060006115558580610140019061150391906128db565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050836110db90919063ffffffff16565b905061156081611102565b61156f57600192505050611576565b6000925050505b92915050565b50565b600081146116185760003373ffffffffffffffffffffffffffffffffffffffff16827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff906040516115cf90613078565b600060405180830381858888f193505050503d806000811461160d576040519150601f19603f3d011682016040523d82523d6000602084013e611612565b606091505b50509050505b50565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff168061169d57503073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6116dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d3906130d9565b60405180910390fd5b565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60016000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167fa538af1dc71cf863394ad275bb0d79fc56e3c210413eaf1e2960c6c29653c9fb60405160405180910390a350565b60008060418351036118165760008060006020860151925060408601519150606086015160001a905061180a87828585611a85565b9450945050505061181f565b60006002915091505b9250929050565b6000600481111561183a576118396130f9565b5b81600481111561184d5761184c6130f9565b5b03156119895760016004811115611867576118666130f9565b5b81600481111561187a576118796130f9565b5b036118ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118b190613174565b60405180910390fd5b600260048111156118ce576118cd6130f9565b5b8160048111156118e1576118e06130f9565b5b03611921576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611918906131e0565b60405180910390fd5b60036004811115611935576119346130f9565b5b816004811115611948576119476130f9565b5b03611988576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197f90613272565b60405180910390fd5b5b50565b6000819050919050565b6000819050919050565b6119a9816116de565b6119e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119df90613304565b60405180910390fd5b80611a157f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61198c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b611a6283611b67565b600082511180611a6f5750805b15611a8057611a7e8383611bb6565b505b505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c1115611ac0576000600391509150611b5e565b600060018787878760405160008152602001604052604051611ae59493929190613333565b6020604051602081039080840390855afa158015611b07573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611b5557600060019250925050611b5e565b80600092509250505b94509492505050565b611b70816119a0565b8073ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a250565b6060611bdb838360405180606001604052806027815260200161344b60279139611be3565b905092915050565b60606000808573ffffffffffffffffffffffffffffffffffffffff1685604051611c0d9190612e69565b600060405180830381855af49150503d8060008114611c48576040519150601f19603f3d011682016040523d82523d6000602084013e611c4d565b606091505b5091509150611c5e86838387611c69565b925050509392505050565b60608315611ccb576000835103611cc357611c83856116de565b611cc2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cb9906133c4565b60405180910390fd5b5b829050611cd6565b611cd58383611cde565b5b949350505050565b600082511115611cf15781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d259190613428565b60405180910390fd5b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000611d6d82611d42565b9050919050565b611d7d81611d62565b8114611d8857600080fd5b50565b600081359050611d9a81611d74565b92915050565b6000819050919050565b611db381611da0565b8114611dbe57600080fd5b50565b600081359050611dd081611daa565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112611dfb57611dfa611dd6565b5b8235905067ffffffffffffffff811115611e1857611e17611ddb565b5b602083019150836001820283011115611e3457611e33611de0565b5b9250929050565b60008060008060008060008060c0898b031215611e5b57611e5a611d38565b5b6000611e698b828c01611d8b565b9850506020611e7a8b828c01611d8b565b9750506040611e8b8b828c01611d8b565b9650506060611e9c8b828c01611dc1565b955050608089013567ffffffffffffffff811115611ebd57611ebc611d3d565b5b611ec98b828c01611de5565b945094505060a089013567ffffffffffffffff811115611eec57611eeb611d3d565b5b611ef88b828c01611de5565b92509250509295985092959890939650565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611f3f81611f0a565b8114611f4a57600080fd5b50565b600081359050611f5c81611f36565b92915050565b600060208284031215611f7857611f77611d38565b5b6000611f8684828501611f4d565b91505092915050565b60008115159050919050565b611fa481611f8f565b82525050565b6000602082019050611fbf6000830184611f9b565b92915050565b600060208284031215611fdb57611fda611d38565b5b6000611fe984828501611d8b565b91505092915050565b60008060008060006080868803121561200e5761200d611d38565b5b600061201c88828901611d8b565b955050602061202d88828901611d8b565b945050604061203e88828901611dc1565b935050606086013567ffffffffffffffff81111561205f5761205e611d3d565b5b61206b88828901611de5565b92509250509295509295909350565b61208381611f0a565b82525050565b600060208201905061209e600083018461207a565b92915050565b6000819050919050565b6120b7816120a4565b81146120c257600080fd5b50565b6000813590506120d4816120ae565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612128826120df565b810181811067ffffffffffffffff82111715612147576121466120f0565b5b80604052505050565b600061215a611d2e565b9050612166828261211f565b919050565b600067ffffffffffffffff821115612186576121856120f0565b5b61218f826120df565b9050602081019050919050565b82818337600083830152505050565b60006121be6121b98461216b565b612150565b9050828152602081018484840111156121da576121d96120da565b5b6121e584828561219c565b509392505050565b600082601f83011261220257612201611dd6565b5b81356122128482602086016121ab565b91505092915050565b6000806040838503121561223257612231611d38565b5b6000612240858286016120c5565b925050602083013567ffffffffffffffff81111561226157612260611d3d565b5b61226d858286016121ed565b9150509250929050565b60008083601f84011261228d5761228c611dd6565b5b8235905067ffffffffffffffff8111156122aa576122a9611ddb565b5b6020830191508360208202830111156122c6576122c5611de0565b5b9250929050565b60008083601f8401126122e3576122e2611dd6565b5b8235905067ffffffffffffffff811115612300576122ff611ddb565b5b60208301915083602082028301111561231c5761231b611de0565b5b9250929050565b6000806000806040858703121561233d5761233c611d38565b5b600085013567ffffffffffffffff81111561235b5761235a611d3d565b5b61236787828801612277565b9450945050602085013567ffffffffffffffff81111561238a57612389611d3d565b5b612396878288016122cd565b925092505092959194509250565b600080fd5b600061016082840312156123c0576123bf6123a4565b5b81905092915050565b6000806000606084860312156123e2576123e1611d38565b5b600084013567ffffffffffffffff811115612400576123ff611d3d565b5b61240c868287016123a9565b935050602061241d868287016120c5565b925050604061242e86828701611dc1565b9150509250925092565b61244181611da0565b82525050565b600060208201905061245c6000830184612438565b92915050565b600061246d82611d42565b9050919050565b61247d81612462565b811461248857600080fd5b50565b60008135905061249a81612474565b92915050565b600080604083850312156124b7576124b6611d38565b5b60006124c58582860161248b565b92505060206124d685828601611dc1565b9150509250929050565b600080604083850312156124f7576124f6611d38565b5b600061250585828601611d8b565b925050602083013567ffffffffffffffff81111561252657612525611d3d565b5b612532858286016121ed565b9150509250929050565b612545816120a4565b82525050565b6000602082019050612560600083018461253c565b92915050565b6000819050919050565b600061258b61258661258184611d42565b612566565b611d42565b9050919050565b600061259d82612570565b9050919050565b60006125af82612592565b9050919050565b6125bf816125a4565b82525050565b60006020820190506125da60008301846125b6565b92915050565b600080600080606085870312156125fa576125f9611d38565b5b600061260887828801611d8b565b945050602061261987828801611dc1565b935050604085013567ffffffffffffffff81111561263a57612639611d3d565b5b61264687828801611de5565b925092505092959194509250565b60008083601f84011261266a57612669611dd6565b5b8235905067ffffffffffffffff81111561268757612686611ddb565b5b6020830191508360208202830111156126a3576126a2611de0565b5b9250929050565b60008060008060008060008060a0898b0312156126ca576126c9611d38565b5b60006126d88b828c01611d8b565b98505060206126e98b828c01611d8b565b975050604089013567ffffffffffffffff81111561270a57612709611d3d565b5b6127168b828c01612654565b9650965050606089013567ffffffffffffffff81111561273957612738611d3d565b5b6127458b828c01612654565b9450945050608089013567ffffffffffffffff81111561276857612767611d3d565b5b6127748b828c01611de5565b92509250509295985092959890939650565b60008060008060008060a087890312156127a3576127a2611d38565b5b60006127b189828a01611d8b565b96505060206127c289828a01611d8b565b95505060406127d389828a01611dc1565b94505060606127e489828a01611dc1565b935050608087013567ffffffffffffffff81111561280557612804611d3d565b5b61281189828a01611de5565b92509250509295509295509295565b600082825260208201905092915050565b7f77726f6e67206172726179206c656e6774687300000000000000000000000000600082015250565b6000612867601383612820565b915061287282612831565b602082019050919050565b600060208201905081810360008301526128968161285a565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080fd5b600080fd5b600080fd5b600080833560016020038436030381126128f8576128f76128cc565b5b80840192508235915067ffffffffffffffff82111561291a576129196128d1565b5b602083019250600182023603831315612936576129356128d6565b5b509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061297882611da0565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036129aa576129a961293e565b5b600182019050919050565b7f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060008201527f64656c656761746563616c6c0000000000000000000000000000000000000000602082015250565b6000612a11602c83612820565b9150612a1c826129b5565b604082019050919050565b60006020820190508181036000830152612a4081612a04565b9050919050565b7f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060008201527f6163746976652070726f78790000000000000000000000000000000000000000602082015250565b6000612aa3602c83612820565b9150612aae82612a47565b604082019050919050565b60006020820190508181036000830152612ad281612a96565b9050919050565b612ae281611d62565b82525050565b6000602082019050612afd6000830184612ad9565b92915050565b612b0c81612462565b82525050565b6000604082019050612b276000830185612b03565b612b346020830184612438565b9392505050565b7f555550535570677261646561626c653a206d757374206e6f742062652063616c60008201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000602082015250565b6000612b97603883612820565b9150612ba282612b3b565b604082019050919050565b60006020820190508181036000830152612bc681612b8a565b9050919050565b600081519050612bdc81611daa565b92915050565b600060208284031215612bf857612bf7611d38565b5b6000612c0684828501612bcd565b91505092915050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b6000612c6b602e83612820565b9150612c7682612c0f565b604082019050919050565b60006020820190508181036000830152612c9a81612c5e565b9050919050565b6000819050919050565b600060ff82169050919050565b6000612cd3612cce612cc984612ca1565b612566565b612cab565b9050919050565b612ce381612cb8565b82525050565b6000602082019050612cfe6000830184612cda565b92915050565b6000819050919050565b600077ffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612d4d612d48612d4384612d04565b612566565b612d0e565b9050919050565b612d5d81612d32565b82525050565b6000604082019050612d786000830185612ad9565b612d856020830184612d54565b9392505050565b7f6163636f756e743a206e6f74204f776e6572206f7220456e747279506f696e74600082015250565b6000612dc2602083612820565b9150612dcd82612d8c565b602082019050919050565b60006020820190508181036000830152612df181612db5565b9050919050565b600081519050919050565b600081905092915050565b60005b83811015612e2c578082015181840152602081019050612e11565b60008484015250505050565b6000612e4382612df8565b612e4d8185612e03565b9350612e5d818560208601612e0e565b80840191505092915050565b6000612e758284612e38565b915081905092915050565b600081519050612e8f816120ae565b92915050565b600060208284031215612eab57612eaa611d38565b5b6000612eb984828501612e80565b91505092915050565b7f45524331393637557067726164653a206e657720696d706c656d656e7461746960008201527f6f6e206973206e6f742055555053000000000000000000000000000000000000602082015250565b6000612f1e602e83612820565b9150612f2982612ec2565b604082019050919050565b60006020820190508181036000830152612f4d81612f11565b9050919050565b7f45524331393637557067726164653a20756e737570706f727465642070726f7860008201527f6961626c65555549440000000000000000000000000000000000000000000000602082015250565b6000612fb0602983612820565b9150612fbb82612f54565b604082019050919050565b60006020820190508181036000830152612fdf81612fa3565b9050919050565b7f6163636f756e743a206e6f742066726f6d20456e747279506f696e7400000000600082015250565b600061301c601c83612820565b915061302782612fe6565b602082019050919050565b6000602082019050818103600083015261304b8161300f565b9050919050565b50565b6000613062600083612e03565b915061306d82613052565b600082019050919050565b600061308382613055565b9150819050919050565b7f6f6e6c79206f776e657200000000000000000000000000000000000000000000600082015250565b60006130c3600a83612820565b91506130ce8261308d565b602082019050919050565b600060208201905081810360008301526130f2816130b6565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b600061315e601883612820565b915061316982613128565b602082019050919050565b6000602082019050818103600083015261318d81613151565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b60006131ca601f83612820565b91506131d582613194565b602082019050919050565b600060208201905081810360008301526131f9816131bd565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b600061325c602283612820565b915061326782613200565b604082019050919050565b6000602082019050818103600083015261328b8161324f565b9050919050565b7f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60008201527f6f74206120636f6e747261637400000000000000000000000000000000000000602082015250565b60006132ee602d83612820565b91506132f982613292565b604082019050919050565b6000602082019050818103600083015261331d816132e1565b9050919050565b61332d81612cab565b82525050565b6000608082019050613348600083018761253c565b6133556020830186613324565b613362604083018561253c565b61336f606083018461253c565b95945050505050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b60006133ae601d83612820565b91506133b982613378565b602082019050919050565b600060208201905081810360008301526133dd816133a1565b9050919050565b600081519050919050565b60006133fa826133e4565b6134048185612820565b9350613414818560208601612e0e565b61341d816120df565b840191505092915050565b6000602082019050818103600083015261344281846133ef565b90509291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220d28ac45bc01cddef7ab122179533409208703d03038de5ef229e404d5f72d86964736f6c634300081300330000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789
Deployed Bytecode
0x60806040523480156200001157600080fd5b5060043610620000465760003560e01c806311464fbe146200004b5780637ac4ed64146200006d578063f14ddffc14620000a3575b600080fd5b62000055620000d9565b604051620000649190620003db565b60405180910390f35b6200008b60048036038101906200008591906200047d565b620000fd565b6040516200009a9190620004d5565b60405180910390f35b620000c16004803603810190620000bb91906200047d565b620001fc565b604051620000d09190620003db565b60405180910390f35b7f000000000000000000000000d920690dbce161953383d5e34e298481ed06960781565b6000620001f48260405180602001620001169062000342565b6020820181038252601f19601f820116604052507f000000000000000000000000d920690dbce161953383d5e34e298481ed069607866040516024016200015e9190620004d5565b60405160208183030381529060405263c4d66de860e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051602001620001b69291906200058c565b604051602081830303815290604052604051602001620001d892919062000602565b6040516020818303038152906040528051906020012062000300565b905092915050565b6000806200020b8484620000fd565b905060008173ffffffffffffffffffffffffffffffffffffffff163b905060008111156200023e578192505050620002fa565b837f000000000000000000000000d920690dbce161953383d5e34e298481ed06960786604051602401620002739190620004d5565b60405160208183030381529060405263c4d66de860e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051620002c69062000342565b620002d39291906200058c565b8190604051809103906000f5905080158015620002f4573d6000803e3d6000fd5b50925050505b92915050565b60006200030f83833062000317565b905092915050565b6000604051836040820152846020820152828152600b810160ff815360558120925050509392505050565b610879806200062b83390190565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006200039b620003956200038f8462000350565b62000370565b62000350565b9050919050565b6000620003af826200037a565b9050919050565b6000620003c382620003a2565b9050919050565b620003d581620003b6565b82525050565b6000602082019050620003f26000830184620003ca565b92915050565b600080fd5b60006200040a8262000350565b9050919050565b6200041c81620003fd565b81146200042857600080fd5b50565b6000813590506200043c8162000411565b92915050565b6000819050919050565b620004578162000442565b81146200046357600080fd5b50565b60008135905062000477816200044c565b92915050565b60008060408385031215620004975762000496620003f8565b5b6000620004a7858286016200042b565b9250506020620004ba8582860162000466565b9150509250929050565b620004cf81620003fd565b82525050565b6000602082019050620004ec6000830184620004c4565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156200052e57808201518184015260208101905062000511565b60008484015250505050565b6000601f19601f8301169050919050565b60006200055882620004f2565b620005648185620004fd565b9350620005768185602086016200050e565b62000581816200053a565b840191505092915050565b6000604082019050620005a36000830185620004c4565b8181036020830152620005b781846200054b565b90509392505050565b600081905092915050565b6000620005d882620004f2565b620005e48185620005c0565b9350620005f68185602086016200050e565b80840191505092915050565b6000620006108285620005cb565b91506200061e8284620005cb565b9150819050939250505056fe608060405260405161087938038061087983398181016040528101906100259190610520565b6100378282600061003e60201b60201c565b505061074f565b61004d8361007660201b60201c565b60008251118061005a5750805b156100715761006f83836100cb60201b60201c565b505b505050565b610085816100fe60201b60201c565b8073ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a250565b60606100f68383604051806060016040528060278152602001610852602791396101c360201b60201c565b905092915050565b61010d8161024f60201b60201c565b61014c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610143906105ff565b60405180910390fd5b8061017f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61027260201b60201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516101ed9190610666565b600060405180830381855af49150503d8060008114610228576040519150601f19603f3d011682016040523d82523d6000602084013e61022d565b606091505b50915091506102448683838761027c60201b60201c565b925050509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000819050919050565b606083156102e45760008351036102dc5761029c8561024f60201b60201c565b6102db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d2906106c9565b60405180910390fd5b5b8290506102f5565b6102f483836102fd60201b60201c565b5b949350505050565b6000825111156103105781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610344919061072d565b60405180910390fd5b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061038c82610361565b9050919050565b61039c81610381565b81146103a757600080fd5b50565b6000815190506103b981610393565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610412826103c9565b810181811067ffffffffffffffff82111715610431576104306103da565b5b80604052505050565b600061044461034d565b90506104508282610409565b919050565b600067ffffffffffffffff8211156104705761046f6103da565b5b610479826103c9565b9050602081019050919050565b60005b838110156104a4578082015181840152602081019050610489565b60008484015250505050565b60006104c36104be84610455565b61043a565b9050828152602081018484840111156104df576104de6103c4565b5b6104ea848285610486565b509392505050565b600082601f830112610507576105066103bf565b5b81516105178482602086016104b0565b91505092915050565b6000806040838503121561053757610536610357565b5b6000610545858286016103aa565b925050602083015167ffffffffffffffff8111156105665761056561035c565b5b610572858286016104f2565b9150509250929050565b600082825260208201905092915050565b7f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60008201527f6f74206120636f6e747261637400000000000000000000000000000000000000602082015250565b60006105e9602d8361057c565b91506105f48261058d565b604082019050919050565b60006020820190508181036000830152610618816105dc565b9050919050565b600081519050919050565b600081905092915050565b60006106408261061f565b61064a818561062a565b935061065a818560208601610486565b80840191505092915050565b60006106728284610635565b915081905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b60006106b3601d8361057c565b91506106be8261067d565b602082019050919050565b600060208201905081810360008301526106e2816106a6565b9050919050565b600081519050919050565b60006106ff826106e9565b610709818561057c565b9350610719818560208601610486565b610722816103c9565b840191505092915050565b6000602082019050818103600083015261074781846106f4565b905092915050565b60f58061075d6000396000f3fe608060405236601057600e6018565b005b60166018565b005b601e602c565b602a6026602e565b603b565b565b565b600060366060565b905090565b3660008037600080366000845af43d6000803e8060008114605b573d6000f35b3d6000fd5b6000608c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b60b5565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600081905091905056fea2646970667358221220404231478476d0836c45ca1dd9071786393ae16c95f87363908750439632ebf164736f6c63430008130033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212205c277caf5f702b53138288783289754c0aad4e2df0e37c160bbe76e8a080b08964736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789
-----Decoded View---------------
Arg [0] : _entryPoint (address): 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789
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.