Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
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:
SmartAccountFactory
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 800 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import "../Proxy.sol"; import "../BaseSmartAccount.sol"; import {DefaultCallbackHandler} from "../handler/DefaultCallbackHandler.sol"; import {Stakeable} from "../common/Stakeable.sol"; /** * @title Smart Account Factory - factory responsible for deploying Smart Accounts using CREATE2 and CREATE * @dev It deploys Smart Accounts as proxies pointing to `basicImplementation` that is immutable. * This allows keeping the same address for the same Smart Account owner on various chains via CREATE2 * @author Chirag Titiya - <[email protected]> */ contract SmartAccountFactory is Stakeable { address public immutable basicImplementation; DefaultCallbackHandler public immutable minimalHandler; event AccountCreation( address indexed account, address indexed initialAuthModule, uint256 indexed index ); event AccountCreationWithoutIndex( address indexed account, address indexed initialAuthModule ); constructor( address _basicImplementation, address _newOwner ) Stakeable(_newOwner) { require( _basicImplementation != address(0), "implementation cannot be zero" ); basicImplementation = _basicImplementation; minimalHandler = new DefaultCallbackHandler(); } /** * @notice Allows to find out account address prior to deployment * @param index extra salt that allows to deploy more accounts if needed for same EOA (default 0) */ function getAddressForCounterFactualAccount( address moduleSetupContract, bytes calldata moduleSetupData, uint256 index ) external view returns (address _account) { // create initializer data based on init method, _owner and minimalHandler bytes memory initializer = _getInitializer( moduleSetupContract, moduleSetupData ); bytes memory code = abi.encodePacked( type(Proxy).creationCode, uint256(uint160(basicImplementation)) ); bytes32 salt = keccak256( abi.encodePacked(keccak256(initializer), index) ); bytes32 hash = keccak256( abi.encodePacked(bytes1(0xff), address(this), salt, keccak256(code)) ); _account = address(uint160(uint256(hash))); } /** * @notice Deploys account using create2 and points it to basicImplementation * * @param index extra salt that allows to deploy more account if needed for same EOA (default 0) */ function deployCounterFactualAccount( address moduleSetupContract, bytes calldata moduleSetupData, uint256 index ) public returns (address proxy) { // create initializer data based on init method and parameters bytes memory initializer = _getInitializer( moduleSetupContract, moduleSetupData ); bytes32 salt = keccak256( abi.encodePacked(keccak256(initializer), index) ); bytes memory deploymentData = abi.encodePacked( type(Proxy).creationCode, uint256(uint160(basicImplementation)) ); assembly { proxy := create2( 0x0, add(0x20, deploymentData), mload(deploymentData), salt ) } require(address(proxy) != address(0), "Create2 call failed"); address initialAuthorizationModule; if (initializer.length > 0) { assembly { let success := call( gas(), proxy, 0, add(initializer, 0x20), mload(initializer), 0, 0 ) let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) if iszero(success) { revert(ptr, returndatasize()) } initialAuthorizationModule := mload(ptr) } } emit AccountCreation(proxy, initialAuthorizationModule, index); } /** * @notice Deploys account using create and points it to _implementation * @return proxy address of the deployed account */ function deployAccount( address moduleSetupContract, bytes calldata moduleSetupData ) public returns (address proxy) { bytes memory deploymentData = abi.encodePacked( type(Proxy).creationCode, uint256(uint160(basicImplementation)) ); assembly { proxy := create( 0x0, add(0x20, deploymentData), mload(deploymentData) ) } require(address(proxy) != address(0), "Create call failed"); bytes memory initializer = _getInitializer( moduleSetupContract, moduleSetupData ); address initialAuthorizationModule; if (initializer.length > 0) { assembly { let success := call( gas(), proxy, 0, add(initializer, 0x20), mload(initializer), 0, 0 ) let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) if iszero(success) { revert(ptr, returndatasize()) } initialAuthorizationModule := mload(ptr) } } emit AccountCreationWithoutIndex(proxy, initialAuthorizationModule); } /** * @dev Allows to retrieve the creation code used for the Proxy deployment. * @return The creation code for the Proxy. */ function accountCreationCode() public pure returns (bytes memory) { return type(Proxy).creationCode; } /** * @dev Allows to retrieve the initializer data for the account. * @param moduleSetupContract Initializes the auth module; can be a factory or registry for multiple accounts. * @param moduleSetupData modules setup data (a standard calldata for the module setup contract) * @return initializer bytes for init method */ function _getInitializer( address moduleSetupContract, bytes calldata moduleSetupData ) internal view returns (bytes memory) { return abi.encodeCall( BaseSmartAccount.init, (address(minimalHandler), moduleSetupContract, moduleSetupData) ); } }
// 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; import "./UserOperation.sol"; interface IAccount { /** * 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(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds) external returns (uint256 validationData); }
// 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); }
/** ** 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 "./UserOperation.sol"; import "./IStakeManager.sol"; import "./IAggregator.sol"; import "./INonceManager.sol"; interface IEntryPoint is IStakeManager, INonceManager { /*** * 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 { UserOperation[] 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(UserOperation[] 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(UserOperation 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(UserOperation 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(UserOperation calldata op, address target, bytes calldata targetCallData) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; interface INonceManager { /** * 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-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 */ import {calldataKeccak} from "../core/Helpers.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 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)); } //relayer/block builder might submit the TX with higher priorityFee, but the user should not // pay above what he signed for. 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) { 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(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: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.17; import {IAccount} from "@account-abstraction/contracts/interfaces/IAccount.sol"; import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol"; import {UserOperationLib, UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol"; import {BaseSmartAccountErrors} from "./common/Errors.sol"; import "@account-abstraction/contracts/core/Helpers.sol"; /** * Basic account implementation. * This contract provides the basic logic for implementing the IAccount interface: validateUserOp function * Specific account implementation should inherit it and provide the account-specific logic */ abstract contract BaseSmartAccount is IAccount, BaseSmartAccountErrors { using UserOperationLib for UserOperation; // Return value in case of signature failure, with no time-range. // equivalent to _packValidationData(true,0,0); uint256 internal constant SIG_VALIDATION_FAILED = 1; /** * @dev Initialize the Smart Account with required states. * @param handler Default fallback handler for the Smart Account. * @param moduleSetupContract Initializes the auth module; can be a factory or registry for multiple accounts. * @param moduleSetupData Contains address of the Setup Contract and setup data. * @notice Ensure this is callable only once (use initializer modifier or state checks). */ function init( address handler, address moduleSetupContract, bytes calldata moduleSetupData ) external virtual returns (address); /** * Validates the userOp. * @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) * @param missingAccountFunds the amount of funds required to pay to EntryPoint to pay for the userOp execution. * @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 no time-range in account, return SIG_VALIDATION_FAILED (1) for signature failure. * Note that the validation code cannot use block.timestamp (or block.number) directly. */ function validateUserOp( UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds ) external virtual override returns (uint256); /** * @return nonce the account nonce. * @dev This method returns the next sequential nonce. * @notice Provides 2D nonce functionality by allowing to use a nonce of a specific key. */ function nonce(uint192 _key) public view virtual returns (uint256) { return entryPoint().getNonce(address(this), _key); } /** * return the entryPoint used by this account. * subclass should return the current entryPoint used by this account. */ function entryPoint() public view virtual returns (IEntryPoint); /** * 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) { payable(msg.sender).call{ value: missingAccountFunds, gas: type(uint256).max }(""); //ignore failure (its EntryPoint's job to verify, not account.) } } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.17; contract BaseSmartAccountErrors { /** * @notice Throws at onlyEntryPoint when msg.sender is not an EntryPoint set for this Smart Account * @param caller address that tried to call onlyEntryPoint-protected method */ error CallerIsNotAnEntryPoint(address caller); } contract FallbackManagerErrors { /** * @notice Throws if zero address has been provided as Fallback Handler address */ error HandlerCannotBeZero(); } contract ModuleManagerErrors { /** * @notice Throws when trying to initialize module manager that already been initialized */ error ModulesAlreadyInitialized(); /** * @notice Throws when a delegatecall in course of module manager initialization has failed */ error ModulesSetupExecutionFailed(); /** * @notice Throws when address(0) or SENTINEL_MODULES constant has been provided as a module address * @param module Module address provided */ error ModuleCannotBeZeroOrSentinel(address module); /** * @notice Throws when trying to enable module that has already been enabled * @param module Module address provided */ error ModuleAlreadyEnabled(address module); /** * @notice Throws when module and previous module mismatch * @param expectedModule expected module at modules[prevModule] * @param returnedModule the module that has been found at modules[prevModule] * @param prevModule previous module address provided at call */ error ModuleAndPrevModuleMismatch( address expectedModule, address returnedModule, address prevModule ); /** * @notice Throws when trying to execute transaction from module that is not enabled * @param module Module address provided */ error ModuleNotEnabled(address module); /** * @notice Throws when data for executeBatchCall provided in wrong format (i.e. empty array or lengths mismatch) * @param destLength length of destination contracts array * @param valueLength length of txn values array * @param funcLength length of function signatures array * @param operationLength length of operation types array. 0 if there's no operations */ error WrongBatchProvided( uint256 destLength, uint256 valueLength, uint256 funcLength, uint256 operationLength ); } contract SmartAccountErrors is BaseSmartAccountErrors, ModuleManagerErrors { /** * @notice Throws if zero address has been provided as Entry Point address */ error EntryPointCannotBeZero(); /** * @notice Throws at mixedAuth when msg.sender is not an owner neither _self * @param caller address that tried to call mixedAuth-protected method */ error MixedAuthFail(address caller); /** * @notice Throws if trying to change an owner of a SmartAccount to the zero address */ error OwnerCannotBeZero(); /** * @notice Throws if zero address has been provided as Base Implementation address */ error BaseImplementationCannotBeZero(); /** * @notice Throws if there is no code at implementationAddress * @param implementationAddress implementation address provided */ error InvalidImplementation(address implementationAddress); /** * @notice Throws at onlyOwner when msg.sender is not an owner * @param caller address that tried to call onlyOwner method */ error CallerIsNotOwner(address caller); /** * @notice Throws at _requireFromEntryPointOrOwner when msg.sender is not an EntryPoint neither an owner * @param caller address that tried to call _requireFromEntryPointOrOwner-protected method */ error CallerIsNotEntryPointOrOwner(address caller); /** * @notice Throws at _requireFromEntryPointOrSelf when msg.sender is not an EntryPoint neither self * @param caller address that tried to call _requireFromEntryPointOrSelf-protected method */ error CallerIsNotEntryPointOrSelf(address caller); /** * @notice Throws at _requireFromEntryPoint when msg.sender is not an EntryPoint * @param caller address that tried to call _requireFromEntryPoint-protected method */ error CallerIsNotEntryPoint(address caller); /** * @notice Throws if trying to initialize a Smart Account that has already been initialized */ error AlreadyInitialized(); /** * @notice Throws if contract signature is provided in frong format * @param uintS s converted to uint256 * @param contractSignatureLength length of a contract signature * @param signatureLength the whole signature length */ error WrongContractSignatureFormat( uint256 uintS, uint256 contractSignatureLength, uint256 signatureLength ); /** * @notice Throws if isValidSignature for the conrtact signature and data hash differs from EIP1271 Magic Value * @param contractSignature the contract signature that has been verified */ error WrongContractSignature(bytes contractSignature); /** * @notice Throws when if trying to transfer to zero address */ error TransferToZeroAddressAttempt(); /** * @notice Throws when module address taken from signature is not enabled * @param moduleAddressProvided module address taken from signature */ error WrongValidationModule(address moduleAddressProvided); /** * @notice Thrown when the function that must be called only via delegatecall is called directly */ error DelegateCallsOnly(); /** * @notice Thrown when trying to use address of the Smart Account as an owner for itself */ error OwnerCanNotBeSelf(); /** * @notice Thrown when trying to use current owner as a new owner in a _setOwner() call */ error OwnerProvidedIsSame(); } contract SmartAccountFactoryErrors is SmartAccountErrors { /** * @notice Throws when the new Proxy deployment fails * @param owner Owner of a Proxy (Smart Account) * @param index Deployment index */ error ProxyDeploymentFailed(address owner, uint256 index); } contract SelfAuthorizedErrors { /** * @notice Throws when the caller is not address(this) * @param caller Caller address */ error CallerIsNotSelf(address caller); } contract SingletonPaymasterErrors { /** * @notice Throws when the Entrypoint address provided is address(0) */ error EntryPointCannotBeZero(); /** * @notice Throws when the verifiying signer address provided is address(0) */ error VerifyingSignerCannotBeZero(); /** * @notice Throws when the paymaster address provided is address(0) */ error PaymasterIdCannotBeZero(); /** * @notice Throws when the 0 has been provided as deposit */ error DepositCanNotBeZero(); /** * @notice Throws when trying to withdraw to address(0) */ error CanNotWithdrawToZeroAddress(); /** * @notice Throws when trying to withdraw more than balance available * @param amountRequired required balance * @param currentBalance available balance */ error InsufficientBalance(uint256 amountRequired, uint256 currentBalance); /** * @notice Throws when signature provided has invalid length * @param sigLength length oif the signature provided */ error InvalidPaymasterSignatureLength(uint256 sigLength); } //
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol"; /** * @title Stakeable Entity * @author Fil Makarov - <[email protected]> */ contract Stakeable is Ownable { constructor(address _newOwner) { _transferOwnership(_newOwner); } function addStake( address epAddress, uint32 unstakeDelaySec ) external payable onlyOwner { require(epAddress != address(0), "Invalid EP address"); IEntryPoint(epAddress).addStake{value: msg.value}(unstakeDelaySec); } function unlockStake(address epAddress) external onlyOwner { require(epAddress != address(0), "Invalid EP address"); IEntryPoint(epAddress).unlockStake(); } function withdrawStake( address epAddress, address payable withdrawAddress ) external onlyOwner { require(epAddress != address(0), "Invalid EP address"); IEntryPoint(epAddress).withdrawStake(withdrawAddress); } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.17; /* solhint-disable no-empty-blocks */ import {IERC1155TokenReceiver} from "../interfaces/IERC1155TokenReceiver.sol"; import {IERC721TokenReceiver} from "../interfaces/IERC721TokenReceiver.sol"; import {IERC777TokensRecipient} from "../interfaces/IERC777TokensRecipient.sol"; import {IERC165} from "../interfaces/IERC165.sol"; /** @title Default Callback Handler - returns true for known token callbacks * @dev Handles EIP-1271 compliant isValidSignature requests. * @notice inspired by Richard Meissner's <[email protected]> implementation */ contract DefaultCallbackHandler is IERC1155TokenReceiver, IERC777TokensRecipient, IERC721TokenReceiver, IERC165 { string public constant NAME = "Default Callback Handler"; string public constant VERSION = "1.0.0"; function supportsInterface( bytes4 interfaceId ) external view virtual override returns (bool) { return interfaceId == type(IERC1155TokenReceiver).interfaceId || interfaceId == type(IERC721TokenReceiver).interfaceId || interfaceId == type(IERC777TokensRecipient).interfaceId || interfaceId == type(IERC165).interfaceId; } function onERC1155Received( address, address, uint256, uint256, bytes calldata ) external pure override returns (bytes4) { return IERC1155TokenReceiver.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] calldata, uint256[] calldata, bytes calldata ) external pure override returns (bytes4) { return IERC1155TokenReceiver.onERC1155BatchReceived.selector; } function onERC721Received( address, address, uint256, bytes calldata ) external pure override returns (bytes4) { return IERC721TokenReceiver.onERC721Received.selector; } function tokensReceived( address, address, address, uint256, bytes calldata, bytes calldata ) external pure override { // We implement this for completeness, doesn't really have any value } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.17; /** Note: The ERC-165 identifier for this interface is 0x4e2312e0. */ interface IERC1155TokenReceiver { /** * @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 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 allowed */ function onERC1155BatchReceived( address _operator, address _from, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data ) external returns (bytes4); }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.17; /** * @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: LGPL-3.0-only pragma solidity 0.8.17; /// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02. interface IERC721TokenReceiver { /// @notice Handle the receipt of an NFT /// @dev The ERC721 smart contract calls this function on the recipient /// after a `transfer`. This function MAY throw to revert and reject the /// transfer. Return of other than the magic value MUST result in the /// transaction being reverted. /// Note: the contract address is always the message sender. /// @param _operator The address which called `safeTransferFrom` function /// @param _from The address which previously owned the token /// @param _tokenId The NFT identifier which is being transferred /// @param _data Additional data with no specified format /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` /// unless throwing function onERC721Received( address _operator, address _from, uint256 _tokenId, bytes calldata _data ) external returns (bytes4); }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.17; interface IERC777TokensRecipient { function tokensReceived( address operator, address from, address to, uint256 amount, bytes calldata data, bytes calldata operatorData ) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; /** * @title Proxy // This is the user's Smart Account * @notice Basic proxy that delegates all calls to a fixed implementation contract. * @dev Implementation address is stored in the slot defined by the Proxy's address */ contract Proxy { constructor(address _implementation) { require( _implementation != address(0), "Invalid implementation address" ); assembly { sstore(address(), _implementation) } } fallback() external payable { address target; assembly { target := sload(address()) calldatacopy(0, 0, calldatasize()) let result := delegatecall(gas(), target, 0, calldatasize(), 0, 0) returndatacopy(0, 0, returndatasize()) switch result case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } }
{ "optimizer": { "enabled": true, "runs": 800 }, "viaIR": true, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
[{"inputs":[{"internalType":"address","name":"_basicImplementation","type":"address"},{"internalType":"address","name":"_newOwner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"initialAuthModule","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"}],"name":"AccountCreation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"initialAuthModule","type":"address"}],"name":"AccountCreationWithoutIndex","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"accountCreationCode","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"epAddress","type":"address"},{"internalType":"uint32","name":"unstakeDelaySec","type":"uint32"}],"name":"addStake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"basicImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"moduleSetupContract","type":"address"},{"internalType":"bytes","name":"moduleSetupData","type":"bytes"}],"name":"deployAccount","outputs":[{"internalType":"address","name":"proxy","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"moduleSetupContract","type":"address"},{"internalType":"bytes","name":"moduleSetupData","type":"bytes"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"deployCounterFactualAccount","outputs":[{"internalType":"address","name":"proxy","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"moduleSetupContract","type":"address"},{"internalType":"bytes","name":"moduleSetupData","type":"bytes"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getAddressForCounterFactualAccount","outputs":[{"internalType":"address","name":"_account","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimalHandler","outputs":[{"internalType":"contract DefaultCallbackHandler","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"epAddress","type":"address"}],"name":"unlockStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"epAddress","type":"address"},{"internalType":"address payable","name":"withdrawAddress","type":"address"}],"name":"withdrawStake","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c0346101445761171b906001600160401b0390601f38849003908101601f1916820190838211838310176100ea57808391604096879485528339810103126101445761006861005a602061005384610149565b9301610149565b6100633361015d565b61015d565b6001600160a01b03811615610100576080528151906104e690818301908111838210176100ea578291611235833903906000f080156100df5760a0525161109090816101a582396080518181816101ed015281816105a70152818161074601526107ef015260a05181818161039e0152610b7c0152f35b50513d6000823e3d90fd5b634e487b7160e01b600052604160045260246000fd5b825162461bcd60e51b815260206004820152601d60248201527f696d706c656d656e746174696f6e2063616e6e6f74206265207a65726f0000006044820152606490fd5b600080fd5b51906001600160a01b038216820361014457565b600080546001600160a01b039283166001600160a01b03198216811783559216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a356fe60806040526004361015610013575b600080fd5b60003560e01c80632e7a1a831461010357806331c884df146100fa5780633b3cb143146100f157806345171159146100e85780634a1ce599146100df578063715018a6146100d6578063743b1e03146100cd5780638da5cb5b146100c4578063b36f9705146100bb578063daf0dfc8146100b2578063df20ffbc146100a95763f2fde38b146100a157600080fd5b61000e6108a6565b5061000e61076a565b5061000e610725565b5061000e6106a1565b5061000e610679565b5061000e610533565b5061000e6104cb565b5061000e61045f565b5061000e6103c2565b5061000e61037d565b5061000e61031d565b5061000e61018c565b6001600160a01b0381160361000e57565b9181601f8401121561000e5782359167ffffffffffffffff831161000e576020838186019501011161000e57565b90606060031983011261000e576004356101648161010c565b916024359067ffffffffffffffff821161000e576101849160040161011d565b909160443590565b503461000e576102f66102dc6102d06101b16101a73661014b565b9392919091610b54565b6102c1610120916020926101c6848201610a8e565b90808252610bdb858301396040519461024a61025687610214888201956001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169087610a9e565b0394610228601f19968781018b528a610a5f565b8781519101209260405192839189830195869091604092825260208201520190565b03858101835282610a5f565b519020945190206040517fff000000000000000000000000000000000000000000000000000000000000009481019485523060601b6bffffffffffffffffffffffff191660018601526015850195909552603584015291929182605585015b03908101835282610a5f565b5190206001600160a01b031690565b6001600160a01b031690565b6040516001600160a01b0390911681529081906020820190565b0390f35b60005b83811061030d5750506000910152565b81810151838201526020016102fd565b503461000e57600036600319011261000e5761036f60406101208151906103476020820183610a5f565b8082526020820190610cfb8239825193849260208452518092816020860152858501906102fa565b601f01601f19168101030190f35b503461000e57600036600319011261000e5760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b506000604036600319011261045c576004356103dd8161010c565b816024359163ffffffff8316809303610458576001600160a01b0390610401610991565b169161040e8315156109e9565b823b1561045857602460405180948193621cb65b60e51b8352600483015234905af1801561044b575b61043f575080f35b61044890610a35565b80f35b610453610a81565b610437565b5080fd5b80fd5b503461000e576000602036600319011261045c57806001600160a01b036004356104888161010c565b610490610991565b1661049c8115156109e9565b803b156104c857819060046040518094819363bb9fe6bf60e01b83525af1801561044b5761043f575080f35b50fd5b503461000e5760008060031936011261045c576104e6610991565b806001600160a01b03815473ffffffffffffffffffffffffffffffffffffffff1981168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b503461000e57604036600319011261000e576004356105518161010c565b60243567ffffffffffffffff811161000e5761057190369060040161011d565b6101209161058160208401610a8e565b92808452610e1b60208501396105fe604051926105df846105d16001600160a01b0397887f0000000000000000000000000000000000000000000000000000000000000000169060208401610a9e565b03601f198101865285610a5f565b835160009460200185f092858416966105f9881515610b08565b610b54565b805183918161064c575b50506040519485946102f69416917f9a6cbf173278cf7dfadb45414d824f7828c0c94479f1b15e45453653070cf6579080a36001600160a01b031682526020820190565b8296945090602083920182855af193604051943d82873e1561067557935191936102f638610608565b3d85fd5b503461000e57600036600319011261000e5760206001600160a01b0360005416604051908152f35b503461000e576000604036600319011261045c576004356106c18161010c565b81602435916106cf8361010c565b6106d7610991565b6001600160a01b03809116926106ee8415156109e9565b833b156107215760249083604051958694859363611d2e7560e11b85521660048401525af1801561044b5761043f575080f35b8280fd5b503461000e57600036600319011261000e5760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461000e5761077c6101a73661014b565b9081519160208082019384209260405193846107a78385830193849091604092825260208201520190565b03946107bb601f1996878101835282610a5f565b519020610120946107cd848701610a8e565b95808752610f3b8588013961081860405191826102b56001600160a01b03998a7f00000000000000000000000000000000000000000000000000000000000000001690898401610a9e565b8051906000940184f591848316610830811515610abc565b8194518061087d575b50604051965086956102f69516917f8967dcaa00d8fcb9bb2b5beff4aaf8c020063512cf08fbe11fec37a1e3a150f29080a46001600160a01b031682526020820190565b82978380939750865af194604051953d82883e156108a2579451939485949338610839565b3d86fd5b503461000e57602036600319011261000e576004356108c48161010c565b6108cc610991565b6001600160a01b0380911680156109265760009182548273ffffffffffffffffffffffffffffffffffffffff198216178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608490fd5b6001600160a01b036000541633036109a557565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b156109f057565b60405162461bcd60e51b815260206004820152601260248201527f496e76616c6964204550206164647265737300000000000000000000000000006044820152606490fd5b67ffffffffffffffff8111610a4957604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff821117610a4957604052565b506040513d6000823e3d90fd5b90610a9c6040519283610a5f565b565b6020929190610ab48492828151948592016102fa565b019081520190565b15610ac357565b60405162461bcd60e51b815260206004820152601360248201527f437265617465322063616c6c206661696c6564000000000000000000000000006044820152606490fd5b15610b0f57565b60405162461bcd60e51b815260206004820152601260248201527f4372656174652063616c6c206661696c656400000000000000000000000000006044820152606490fd5b60a490610bd7929380604051958693631bc6fec760e11b60208601526001600160a01b0390817f000000000000000000000000000000000000000000000000000000000000000016602487015216604485015260606064850152816084850152848401376000838284010152601f80199101168101036084810184520182610a5f565b9056fe6080346100aa57601f61012038819003918201601f19168301916001600160401b038311848410176100af578084926020946040528339810103126100aa57516001600160a01b0381168082036100aa5715610065573055604051605a90816100c68239f35b60405162461bcd60e51b815260206004820152601e60248201527f496e76616c696420696d706c656d656e746174696f6e206164647265737300006044820152606490fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe608060405230546000808092368280378136915af43d82803e156020573d90f35b3d90fdfea2646970667358221220848d096f9c481a5b694ab87e0a4c770de1a5316a9072906cfdc9799c6c7d50d064736f6c634300081100336080346100aa57601f61012038819003918201601f19168301916001600160401b038311848410176100af578084926020946040528339810103126100aa57516001600160a01b0381168082036100aa5715610065573055604051605a90816100c68239f35b60405162461bcd60e51b815260206004820152601e60248201527f496e76616c696420696d706c656d656e746174696f6e206164647265737300006044820152606490fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe608060405230546000808092368280378136915af43d82803e156020573d90f35b3d90fdfea2646970667358221220848d096f9c481a5b694ab87e0a4c770de1a5316a9072906cfdc9799c6c7d50d064736f6c634300081100336080346100aa57601f61012038819003918201601f19168301916001600160401b038311848410176100af578084926020946040528339810103126100aa57516001600160a01b0381168082036100aa5715610065573055604051605a90816100c68239f35b60405162461bcd60e51b815260206004820152601e60248201527f496e76616c696420696d706c656d656e746174696f6e206164647265737300006044820152606490fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe608060405230546000808092368280378136915af43d82803e156020573d90f35b3d90fdfea2646970667358221220848d096f9c481a5b694ab87e0a4c770de1a5316a9072906cfdc9799c6c7d50d064736f6c634300081100336080346100aa57601f61012038819003918201601f19168301916001600160401b038311848410176100af578084926020946040528339810103126100aa57516001600160a01b0381168082036100aa5715610065573055604051605a90816100c68239f35b60405162461bcd60e51b815260206004820152601e60248201527f496e76616c696420696d706c656d656e746174696f6e206164647265737300006044820152606490fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe608060405230546000808092368280378136915af43d82803e156020573d90f35b3d90fdfea2646970667358221220848d096f9c481a5b694ab87e0a4c770de1a5316a9072906cfdc9799c6c7d50d064736f6c63430008110033a26469706673582212203e55cec38e07f7cc5e200cf7a60929d3d4a661eca868bbbf5e506eebc7673fb764736f6c6343000811003360808060405234610016576104ca908161001c8239f35b600080fdfe60806040908082526004918236101561001757600080fd5b600091823560e01c90816223de291461031b57816301ffc9a71461029457508063150b7a021461023d578063a3f4df7e146101d6578063bc197c811461014c578063f23a6e61146100f25763ffa1ad741461007157600080fd5b346100ee57816003193601126100ee578051918183019083821067ffffffffffffffff8311176100db57506100d793508152600582527f312e302e300000000000000000000000000000000000000000000000000000006020830152519182918261041a565b0390f35b634e487b7160e01b815260418552602490fd5b5080fd5b5090346101495760a03660031901126101495761010d6103a1565b506101166103c9565b506084359067ffffffffffffffff8211610149575060209261013a913691016103ec565b50505163f23a6e6160e01b8152f35b80fd5b5090346101495760a0366003190112610149576101676103a1565b506101706103c9565b5067ffffffffffffffff906044358281116100ee576101929036908601610463565b50506064358281116100ee576101ab9036908601610463565b505060843591821161014957506020926101c7913691016103ec565b50505163bc197c8160e01b8152f35b50346100ee57816003193601126100ee578051918183019083821067ffffffffffffffff8311176100db57506100d793508152601882527f44656661756c742043616c6c6261636b2048616e646c657200000000000000006020830152519182918261041a565b509034610149576080366003190112610149576102586103a1565b506102616103c9565b506064359067ffffffffffffffff82116101495750602092610285913691016103ec565b505051630a85bd0160e11b8152f35b83908534610317576020366003190112610317573563ffffffff60e01b81168091036103175760209250630271189760e51b8114908115610306575b81156102f6575b81156102e5575b5015158152f35b6301ffc9a760e01b149050836102de565b6223de2960e01b811491506102d7565b630a85bd0160e11b811491506102d0565b8280fd5b8385346100ee5760c03660031901126100ee576103366103a1565b5061033f6103c9565b5060443573ffffffffffffffffffffffffffffffffffffffff8116036100ee5767ffffffffffffffff9060843582811161039d5761038090369083016103ec565b505060a43591821161031757610398913691016103ec565b505080f35b8380fd5b6004359073ffffffffffffffffffffffffffffffffffffffff821682036103c457565b600080fd5b6024359073ffffffffffffffffffffffffffffffffffffffff821682036103c457565b9181601f840112156103c45782359167ffffffffffffffff83116103c457602083818601950101116103c457565b6020808252825181830181905290939260005b82811061044f57505060409293506000838284010152601f8019910116010190565b81810186015184820160400152850161042d565b9181601f840112156103c45782359167ffffffffffffffff83116103c4576020808501948460051b0101116103c45756fea2646970667358221220fdef8a86ab4f6e765efb23ecf4df9f592b8912af3f97b980855b787dbdbdccb264736f6c6343000811003300000000000000000000000010a1456c37c2e90be814d5ace74bf903a7a823c2000000000000000000000000de55a782017cf60cb603aea899fea5c435ebf545
Deployed Bytecode
0x60806040526004361015610013575b600080fd5b60003560e01c80632e7a1a831461010357806331c884df146100fa5780633b3cb143146100f157806345171159146100e85780634a1ce599146100df578063715018a6146100d6578063743b1e03146100cd5780638da5cb5b146100c4578063b36f9705146100bb578063daf0dfc8146100b2578063df20ffbc146100a95763f2fde38b146100a157600080fd5b61000e6108a6565b5061000e61076a565b5061000e610725565b5061000e6106a1565b5061000e610679565b5061000e610533565b5061000e6104cb565b5061000e61045f565b5061000e6103c2565b5061000e61037d565b5061000e61031d565b5061000e61018c565b6001600160a01b0381160361000e57565b9181601f8401121561000e5782359167ffffffffffffffff831161000e576020838186019501011161000e57565b90606060031983011261000e576004356101648161010c565b916024359067ffffffffffffffff821161000e576101849160040161011d565b909160443590565b503461000e576102f66102dc6102d06101b16101a73661014b565b9392919091610b54565b6102c1610120916020926101c6848201610a8e565b90808252610bdb858301396040519461024a61025687610214888201956001600160a01b037f00000000000000000000000010a1456c37c2e90be814d5ace74bf903a7a823c2169087610a9e565b0394610228601f19968781018b528a610a5f565b8781519101209260405192839189830195869091604092825260208201520190565b03858101835282610a5f565b519020945190206040517fff000000000000000000000000000000000000000000000000000000000000009481019485523060601b6bffffffffffffffffffffffff191660018601526015850195909552603584015291929182605585015b03908101835282610a5f565b5190206001600160a01b031690565b6001600160a01b031690565b6040516001600160a01b0390911681529081906020820190565b0390f35b60005b83811061030d5750506000910152565b81810151838201526020016102fd565b503461000e57600036600319011261000e5761036f60406101208151906103476020820183610a5f565b8082526020820190610cfb8239825193849260208452518092816020860152858501906102fa565b601f01601f19168101030190f35b503461000e57600036600319011261000e5760206040516001600160a01b037f00000000000000000000000076f17e14a3416952daecb691d2bc73058e347ce1168152f35b506000604036600319011261045c576004356103dd8161010c565b816024359163ffffffff8316809303610458576001600160a01b0390610401610991565b169161040e8315156109e9565b823b1561045857602460405180948193621cb65b60e51b8352600483015234905af1801561044b575b61043f575080f35b61044890610a35565b80f35b610453610a81565b610437565b5080fd5b80fd5b503461000e576000602036600319011261045c57806001600160a01b036004356104888161010c565b610490610991565b1661049c8115156109e9565b803b156104c857819060046040518094819363bb9fe6bf60e01b83525af1801561044b5761043f575080f35b50fd5b503461000e5760008060031936011261045c576104e6610991565b806001600160a01b03815473ffffffffffffffffffffffffffffffffffffffff1981168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b503461000e57604036600319011261000e576004356105518161010c565b60243567ffffffffffffffff811161000e5761057190369060040161011d565b6101209161058160208401610a8e565b92808452610e1b60208501396105fe604051926105df846105d16001600160a01b0397887f00000000000000000000000010a1456c37c2e90be814d5ace74bf903a7a823c2169060208401610a9e565b03601f198101865285610a5f565b835160009460200185f092858416966105f9881515610b08565b610b54565b805183918161064c575b50506040519485946102f69416917f9a6cbf173278cf7dfadb45414d824f7828c0c94479f1b15e45453653070cf6579080a36001600160a01b031682526020820190565b8296945090602083920182855af193604051943d82873e1561067557935191936102f638610608565b3d85fd5b503461000e57600036600319011261000e5760206001600160a01b0360005416604051908152f35b503461000e576000604036600319011261045c576004356106c18161010c565b81602435916106cf8361010c565b6106d7610991565b6001600160a01b03809116926106ee8415156109e9565b833b156107215760249083604051958694859363611d2e7560e11b85521660048401525af1801561044b5761043f575080f35b8280fd5b503461000e57600036600319011261000e5760206040516001600160a01b037f00000000000000000000000010a1456c37c2e90be814d5ace74bf903a7a823c2168152f35b503461000e5761077c6101a73661014b565b9081519160208082019384209260405193846107a78385830193849091604092825260208201520190565b03946107bb601f1996878101835282610a5f565b519020610120946107cd848701610a8e565b95808752610f3b8588013961081860405191826102b56001600160a01b03998a7f00000000000000000000000010a1456c37c2e90be814d5ace74bf903a7a823c21690898401610a9e565b8051906000940184f591848316610830811515610abc565b8194518061087d575b50604051965086956102f69516917f8967dcaa00d8fcb9bb2b5beff4aaf8c020063512cf08fbe11fec37a1e3a150f29080a46001600160a01b031682526020820190565b82978380939750865af194604051953d82883e156108a2579451939485949338610839565b3d86fd5b503461000e57602036600319011261000e576004356108c48161010c565b6108cc610991565b6001600160a01b0380911680156109265760009182548273ffffffffffffffffffffffffffffffffffffffff198216178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608490fd5b6001600160a01b036000541633036109a557565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b156109f057565b60405162461bcd60e51b815260206004820152601260248201527f496e76616c6964204550206164647265737300000000000000000000000000006044820152606490fd5b67ffffffffffffffff8111610a4957604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff821117610a4957604052565b506040513d6000823e3d90fd5b90610a9c6040519283610a5f565b565b6020929190610ab48492828151948592016102fa565b019081520190565b15610ac357565b60405162461bcd60e51b815260206004820152601360248201527f437265617465322063616c6c206661696c6564000000000000000000000000006044820152606490fd5b15610b0f57565b60405162461bcd60e51b815260206004820152601260248201527f4372656174652063616c6c206661696c656400000000000000000000000000006044820152606490fd5b60a490610bd7929380604051958693631bc6fec760e11b60208601526001600160a01b0390817f00000000000000000000000076f17e14a3416952daecb691d2bc73058e347ce116602487015216604485015260606064850152816084850152848401376000838284010152601f80199101168101036084810184520182610a5f565b9056fe6080346100aa57601f61012038819003918201601f19168301916001600160401b038311848410176100af578084926020946040528339810103126100aa57516001600160a01b0381168082036100aa5715610065573055604051605a90816100c68239f35b60405162461bcd60e51b815260206004820152601e60248201527f496e76616c696420696d706c656d656e746174696f6e206164647265737300006044820152606490fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe608060405230546000808092368280378136915af43d82803e156020573d90f35b3d90fdfea2646970667358221220848d096f9c481a5b694ab87e0a4c770de1a5316a9072906cfdc9799c6c7d50d064736f6c634300081100336080346100aa57601f61012038819003918201601f19168301916001600160401b038311848410176100af578084926020946040528339810103126100aa57516001600160a01b0381168082036100aa5715610065573055604051605a90816100c68239f35b60405162461bcd60e51b815260206004820152601e60248201527f496e76616c696420696d706c656d656e746174696f6e206164647265737300006044820152606490fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe608060405230546000808092368280378136915af43d82803e156020573d90f35b3d90fdfea2646970667358221220848d096f9c481a5b694ab87e0a4c770de1a5316a9072906cfdc9799c6c7d50d064736f6c634300081100336080346100aa57601f61012038819003918201601f19168301916001600160401b038311848410176100af578084926020946040528339810103126100aa57516001600160a01b0381168082036100aa5715610065573055604051605a90816100c68239f35b60405162461bcd60e51b815260206004820152601e60248201527f496e76616c696420696d706c656d656e746174696f6e206164647265737300006044820152606490fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe608060405230546000808092368280378136915af43d82803e156020573d90f35b3d90fdfea2646970667358221220848d096f9c481a5b694ab87e0a4c770de1a5316a9072906cfdc9799c6c7d50d064736f6c634300081100336080346100aa57601f61012038819003918201601f19168301916001600160401b038311848410176100af578084926020946040528339810103126100aa57516001600160a01b0381168082036100aa5715610065573055604051605a90816100c68239f35b60405162461bcd60e51b815260206004820152601e60248201527f496e76616c696420696d706c656d656e746174696f6e206164647265737300006044820152606490fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe608060405230546000808092368280378136915af43d82803e156020573d90f35b3d90fdfea2646970667358221220848d096f9c481a5b694ab87e0a4c770de1a5316a9072906cfdc9799c6c7d50d064736f6c63430008110033a26469706673582212203e55cec38e07f7cc5e200cf7a60929d3d4a661eca868bbbf5e506eebc7673fb764736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000010a1456c37c2e90be814d5ace74bf903a7a823c2000000000000000000000000de55a782017cf60cb603aea899fea5c435ebf545
-----Decoded View---------------
Arg [0] : _basicImplementation (address): 0x10A1456c37C2E90be814D5AcE74bF903A7a823C2
Arg [1] : _newOwner (address): 0xDe55A782017CF60Cb603aEA899fea5c435eBF545
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000010a1456c37c2e90be814d5ace74bf903a7a823c2
Arg [1] : 000000000000000000000000de55a782017cf60cb603aea899fea5c435ebf545
Loading...
Loading
[ Download: CSV Export ]
[ 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.