Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
5339466 | 291 days ago | Contract Creation | 0 ETH |
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:
Kernel
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // Importing external libraries and contracts import {EIP712} from "solady/utils/EIP712.sol"; import {ECDSA} from "solady/utils/ECDSA.sol"; import {IEntryPoint} from "I4337/interfaces/IEntryPoint.sol"; import {UserOperation} from "I4337/interfaces/UserOperation.sol"; import {Compatibility} from "./abstract/Compatibility.sol"; import {KernelStorage} from "./abstract/KernelStorage.sol"; import {_intersectValidationData} from "./utils/KernelHelper.sol"; import {IKernelValidator} from "./interfaces/IKernelValidator.sol"; import { KERNEL_NAME, KERNEL_VERSION, VALIDATOR_APPROVED_STRUCT_HASH, KERNEL_STORAGE_SLOT_1, SIG_VALIDATION_FAILED } from "./common/Constants.sol"; import {Operation} from "./common/Enums.sol"; import {WalletKernelStorage, Call, ExecutionDetail} from "./common/Structs.sol"; import {ValidationData, ValidAfter, ValidUntil, parseValidationData, packValidationData} from "./common/Types.sol"; /// @title Kernel /// @author taek<[email protected]> /// @notice wallet kernel for extensible wallet functionality contract Kernel is EIP712, Compatibility, KernelStorage { /// @dev Selector of the `DisabledMode()` error, to be used in assembly, 'bytes4(keccak256(bytes("DisabledMode()")))', same as DisabledMode.selector() uint256 private constant _DISABLED_MODE_SELECTOR = 0xfc2f51c5; bytes32 internal constant EIP712_DOMAIN_TYPEHASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f; /// @dev Current kernel name and version string public constant name = KERNEL_NAME; string public constant version = KERNEL_VERSION; /// @dev Sets up the EIP712 and KernelStorage with the provided entry point constructor(IEntryPoint _entryPoint) KernelStorage(_entryPoint) {} /// @notice Accepts incoming Ether transactions and calls from the EntryPoint contract /// @dev This function will delegate any call to the appropriate executor based on the function signature. fallback() external payable { bytes4 sig = msg.sig; address executor = getKernelStorage().execution[sig].executor; if (msg.sender != address(entryPoint) && !_checkCaller()) { revert NotAuthorizedCaller(); } assembly { calldatacopy(0, 0, calldatasize()) let result := delegatecall(gas(), executor, 0, calldatasize(), 0, 0) returndatacopy(0, 0, returndatasize()) switch result case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /// @notice Executes a function call to an external contract /// @param to The address of the target contract /// @param value The amount of Ether to send /// @param data The call data to be sent /// @dev operation is deprecated param, use executeBatch for batched transaction function execute(address to, uint256 value, bytes memory data, Operation _operation) external payable { if (msg.sender != address(entryPoint) && msg.sender != address(this) && !_checkCaller()) { revert NotAuthorizedCaller(); } if (_operation != Operation.Call) { revert DeprecatedOperation(); } assembly { let success := call(gas(), to, value, add(data, 0x20), mload(data), 0, 0) returndatacopy(0, 0, returndatasize()) switch success case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /// @notice Executes a function call to an external contract with delegatecall /// @param to The address of the target contract /// @param data The call data to be sent function executeDelegateCall(address to, bytes memory data) external payable { if (msg.sender != address(entryPoint) && msg.sender != address(this) && !_checkCaller()) { revert NotAuthorizedCaller(); } assembly { let success := delegatecall(gas(), to, add(data, 0x20), mload(data), 0, 0) returndatacopy(0, 0, returndatasize()) switch success case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /// @notice Executes a function call to an external contract batched /// @param calls The calls to be executed, in order /// @dev operation deprecated param, use executeBatch for batched transaction function executeBatch(Call[] memory calls) external payable { if (msg.sender != address(entryPoint) && !_checkCaller()) { revert NotAuthorizedCaller(); } uint256 len = calls.length; for (uint256 i = 0; i < len;) { Call memory call = calls[i]; address to = call.to; uint256 value = call.value; bytes memory data = call.data; assembly { let success := call(gas(), to, value, add(data, 0x20), mload(data), 0, 0) switch success case 0 { returndatacopy(0, 0, returndatasize()) revert(0, returndatasize()) } default { i := add(i, 1) } } } } /// @notice Validates a user operation based on its mode /// @dev This function will validate user operation and be called by EntryPoint /// @param _userOp The user operation to be validated /// @param userOpHash The hash of the user operation /// @param missingAccountFunds The funds needed to be reimbursed /// @return validationData The data used for validation function validateUserOp(UserOperation calldata _userOp, bytes32 userOpHash, uint256 missingAccountFunds) external payable virtual returns (ValidationData validationData) { if (msg.sender != address(entryPoint)) { revert NotEntryPoint(); } bytes calldata userOpSignature; uint256 userOpEndOffset; assembly { // Store the userOpSignature offset userOpEndOffset := add(calldataload(0x04), 0x24) // Extract the user op signature from the calldata (but keep it in the calldata, just extract offset & length) userOpSignature.offset := add(calldataload(add(userOpEndOffset, 0x120)), userOpEndOffset) userOpSignature.length := calldataload(sub(userOpSignature.offset, 0x20)) } // mode based signature bytes4 mode = bytes4(userOpSignature[0:4]); // mode == 00..00 use validators // mode == 0x00000000 use sudo validator if (mode == 0x00000000) { assembly { if missingAccountFunds { pop(call(gas(), caller(), missingAccountFunds, callvalue(), callvalue(), callvalue(), callvalue())) //ignore failure (its EntryPoint's job to verify, not account.) } } // short circuit here for default validator return _validateUserOp(_userOp, userOpHash, missingAccountFunds); } // Check if the kernel is disabled, if that's the case, it's only accepting userOperation with sudo mode assembly ("memory-safe") { // Extract the disabled mode from the storage slot let isKernelDisabled := shl(224, sload(KERNEL_STORAGE_SLOT_1)) // If we got a non-zero disabled mode, and non zero mode, then revert if and(isKernelDisabled, mode) { mstore(0x00, _DISABLED_MODE_SELECTOR) revert(0x1c, 0x04) } } // The validator that will be used IKernelValidator validator; // mode == 0x00000001 use given validator // mode == 0x00000002 enable validator if (mode == 0x00000001) { bytes calldata userOpCallData; assembly { userOpCallData.offset := add(calldataload(add(userOpEndOffset, 0x40)), userOpEndOffset) userOpCallData.length := calldataload(sub(userOpCallData.offset, 0x20)) } ExecutionDetail storage detail = getKernelStorage().execution[bytes4(userOpCallData[0:4])]; validator = detail.validator; userOpSignature = userOpSignature[4:]; validationData = packValidationData(detail.validAfter, detail.validUntil); } else if (mode == 0x00000002) { bytes calldata userOpCallData; assembly { userOpCallData.offset := add(calldataload(add(userOpEndOffset, 0x40)), userOpEndOffset) userOpCallData.length := calldataload(sub(userOpCallData.offset, 0x20)) } // use given validator // userOpSignature[4:10] = validAfter, // userOpSignature[10:16] = validUntil, // userOpSignature[16:36] = validator address, (validator, validationData, userOpSignature) = _approveValidator(bytes4(userOpCallData[0:4]), userOpSignature); } else { return SIG_VALIDATION_FAILED; } assembly { if missingAccountFunds { pop(call(gas(), caller(), missingAccountFunds, callvalue(), callvalue(), callvalue(), callvalue())) //ignore failure (its EntryPoint's job to verify, not account.) } } // Replicate the userOp from memory to calldata, to update it's signature (since with mode 1 & 2 the signatre can be updated) UserOperation memory userOp = _userOp; userOp.signature = userOpSignature; // Get the validator data from the designated signer validationData = _intersectValidationData(validationData, validator.validateUserOp(userOp, userOpHash, missingAccountFunds)); return validationData; } /// @dev This function will approve a new validator for the current kernel /// @param sig The signature of the userOp asking for a validator approval /// @param signature The signature of the userOp asking for a validator approval function _approveValidator(bytes4 sig, bytes calldata signature) internal returns (IKernelValidator validator, ValidationData validationData, bytes calldata validationSig) { unchecked { validator = IKernelValidator(address(bytes20(signature[16:36]))); uint256 cursor = 88; uint256 length = uint256(bytes32(signature[56:88])); // this is enableDataLength bytes calldata enableData; assembly { enableData.offset := add(signature.offset, cursor) enableData.length := length cursor := add(cursor, length) // 88 + enableDataLength } length = uint256(bytes32(signature[cursor:cursor + 32])); // this is enableSigLength assembly { cursor := add(cursor, 32) } bytes32 enableDigest = _hashTypedData( keccak256( abi.encode( VALIDATOR_APPROVED_STRUCT_HASH, bytes4(sig), uint256(bytes32(signature[4:36])), address(bytes20(signature[36:56])), keccak256(enableData) ) ) ); validationData = _intersectValidationData( _validateSignature(address(this), enableDigest, enableDigest, signature[cursor:cursor + length]), ValidationData.wrap( uint256(bytes32(signature[4:36])) & 0xffffffffffffffffffffffff0000000000000000000000000000000000000000 ) ); assembly { cursor := add(cursor, length) validationSig.offset := add(signature.offset, cursor) validationSig.length := sub(signature.length, cursor) } getKernelStorage().execution[sig] = ExecutionDetail({ validAfter: ValidAfter.wrap(uint48(bytes6(signature[4:10]))), validUntil: ValidUntil.wrap(uint48(bytes6(signature[10:16]))), executor: address(bytes20(signature[36:56])), validator: IKernelValidator(address(bytes20(signature[16:36]))) }); validator.enable(enableData); } } /// @dev Validates a signature for the given kernel /// @param hash The hash of the data that was signed /// @param signature The signature to be validated function validateSignature(bytes32 hash, bytes calldata signature) public view returns (ValidationData) { return _validateSignature(msg.sender, hash, hash, signature); } /// @dev Get the current name & version of the kernel, used for the EIP-712 domain separator function _domainNameAndVersion() internal pure override returns (string memory, string memory) { return (name, version); } /// @dev Get an EIP-712 compliant domain separator function _domainSeparator() internal view override returns (bytes32) { // Obtain the name and version from the _domainNameAndVersion function. (string memory _name, string memory _version) = _domainNameAndVersion(); bytes32 nameHash = keccak256(bytes(_name)); bytes32 versionHash = keccak256(bytes(_version)); // Use the proxy address for the EIP-712 domain separator. address proxyAddress = address(this); // Construct the domain separator with name, version, chainId, and proxy address. bytes32 typeHash = EIP712_DOMAIN_TYPEHASH; return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, proxyAddress)); } /// @notice Checks if a signature is valid /// @dev This function checks if a signature is valid based on the hash of the data signed. /// @param hash The hash of the data that was signed /// @param signature The signature to be validated /// @return The magic value 0x1626ba7e if the signature is valid, otherwise returns 0xffffffff. function isValidSignature(bytes32 hash, bytes calldata signature) public view returns (bytes4) { // Include the proxy address in the domain separator bytes32 domainSeparator = _domainSeparator(); // Recreate the signed message hash with the correct domain separator bytes32 signedMessageHash = keccak256(abi.encodePacked("\x19\x01", domainSeparator, hash)); ValidationData validationData = _validateSignature(msg.sender, signedMessageHash, hash, signature); (ValidAfter validAfter, ValidUntil validUntil, address result) = parseValidationData(validationData); // Check if the signature is valid within the specified time frame and the result is successful if ( ValidAfter.unwrap(validAfter) <= block.timestamp && ValidUntil.unwrap(validUntil) >= block.timestamp && result == address(0) ) { // If all checks pass, return the ERC1271 magic value for a valid signature return 0x1626ba7e; } else { // If any check fails, return the failure magic value return 0xffffffff; } } /// @dev Check if the current caller is authorized or no to perform the call /// @return True if the caller is authorized, otherwise false function _checkCaller() internal returns (bool) { if (_validCaller(msg.sender, msg.data)) { return true; } bytes4 sig = msg.sig; ExecutionDetail storage detail = getKernelStorage().execution[sig]; if ( address(detail.validator) == address(0) || (ValidUntil.unwrap(detail.validUntil) != 0 && ValidUntil.unwrap(detail.validUntil) < block.timestamp) || ValidAfter.unwrap(detail.validAfter) > block.timestamp ) { return false; } else { return detail.validator.validCaller(msg.sender, msg.data); } } /// @dev This function will validate user operation and be called by EntryPoint /// @param _op The user operation to be validated /// @param _opHash The hash of the user operation /// @param _missingFunds The funds needed to be reimbursed function _validateUserOp(UserOperation calldata _op, bytes32 _opHash, uint256 _missingFunds) internal virtual returns (ValidationData) { // Replace the user op in memory to update the signature UserOperation memory op = _op; // Remove the validation mode flag from the signature op.signature = _op.signature[4:]; IKernelValidator validator; assembly { validator := shr(80, sload(KERNEL_STORAGE_SLOT_1)) } return IKernelValidator(validator).validateUserOp(op, _opHash, _missingFunds); } /// @dev This function will validate a signature for the given kernel /// @param _hash The hash of the data that was signed /// @param _signature The signature to be validated /// @return The magic value 0x1626ba7e if the signature is valid, otherwise returns 0xffffffff. function _validateSignature(address _requestor, bytes32 _hash, bytes32 _rawHash, bytes calldata _signature) internal view virtual returns (ValidationData) { address validator; assembly { validator := shr(80, sload(KERNEL_STORAGE_SLOT_1)) } // 20 bytes added at the end of the signature to store the address of the caller (bool success, bytes memory res) = validator.staticcall( abi.encodePacked( abi.encodeWithSelector(IKernelValidator.validateSignature.selector, _hash, _signature), _rawHash, _requestor ) ); require(success, "Kernel::_validateSignature: failed to validate signature"); return abi.decode(res, (ValidationData)); } /// @dev Check if the given caller is valid for the given data /// @param _caller The caller to be checked /// @param _data The data to be checked /// @return True if the caller is valid, otherwise false function _validCaller(address _caller, bytes calldata _data) internal virtual returns (bool) { address validator; assembly { // Load the validator from the storage slot validator := shr(80, sload(KERNEL_STORAGE_SLOT_1)) } return IKernelValidator(validator).validCaller(_caller, _data); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Contract for EIP-712 typed structured data hashing and signing. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EIP712.sol) /// @author Modified from Solbase (https://github.com/Sol-DAO/solbase/blob/main/src/utils/EIP712.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol) /// /// @dev Note, this implementation: /// - Uses `address(this)` for the `verifyingContract` field. /// - Does NOT use the optional EIP-712 salt. /// - Does NOT use any EIP-712 extensions. /// This is for simplicity and to save gas. /// If you need to customize, please fork / modify accordingly. abstract contract EIP712 { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS AND IMMUTABLES */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`. bytes32 internal constant _DOMAIN_TYPEHASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f; uint256 private immutable _cachedThis; uint256 private immutable _cachedChainId; bytes32 private immutable _cachedNameHash; bytes32 private immutable _cachedVersionHash; bytes32 private immutable _cachedDomainSeparator; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTRUCTOR */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Cache the hashes for cheaper runtime gas costs. /// In the case of upgradeable contracts (i.e. proxies), /// or if the chain id changes due to a hard fork, /// the domain separator will be seamlessly calculated on-the-fly. constructor() { _cachedThis = uint256(uint160(address(this))); _cachedChainId = block.chainid; string memory name; string memory version; if (!_domainNameAndVersionMayChange()) (name, version) = _domainNameAndVersion(); bytes32 nameHash = _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(name)); bytes32 versionHash = _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(version)); _cachedNameHash = nameHash; _cachedVersionHash = versionHash; bytes32 separator; if (!_domainNameAndVersionMayChange()) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Load the free memory pointer. mstore(m, _DOMAIN_TYPEHASH) mstore(add(m, 0x20), nameHash) mstore(add(m, 0x40), versionHash) mstore(add(m, 0x60), chainid()) mstore(add(m, 0x80), address()) separator := keccak256(m, 0xa0) } } _cachedDomainSeparator = separator; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* FUNCTIONS TO OVERRIDE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Please override this function to return the domain name and version. /// ``` /// function _domainNameAndVersion() /// internal /// pure /// virtual /// returns (string memory name, string memory version) /// { /// name = "Solady"; /// version = "1"; /// } /// ``` /// /// Note: If the returned result may change after the contract has been deployed, /// you must override `_domainNameAndVersionMayChange()` to return true. function _domainNameAndVersion() internal view virtual returns (string memory name, string memory version); /// @dev Returns if `_domainNameAndVersion()` may change /// after the contract has been deployed (i.e. after the constructor). /// Default: false. function _domainNameAndVersionMayChange() internal pure virtual returns (bool result) {} /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HASHING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the EIP-712 domain separator. function _domainSeparator() internal view virtual returns (bytes32 separator) { if (_domainNameAndVersionMayChange()) { separator = _buildDomainSeparator(); } else { separator = _cachedDomainSeparator; if (_cachedDomainSeparatorInvalidated()) separator = _buildDomainSeparator(); } } /// @dev Returns the hash of the fully encoded EIP-712 message for this domain, /// given `structHash`, as defined in /// https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct. /// /// The hash can be used together with {ECDSA-recover} to obtain the signer of a message: /// ``` /// bytes32 digest = _hashTypedData(keccak256(abi.encode( /// keccak256("Mail(address to,string contents)"), /// mailTo, /// keccak256(bytes(mailContents)) /// ))); /// address signer = ECDSA.recover(digest, signature); /// ``` function _hashTypedData(bytes32 structHash) internal view virtual returns (bytes32 digest) { // We will use `digest` to store the domain separator to save a bit of gas. if (_domainNameAndVersionMayChange()) { digest = _buildDomainSeparator(); } else { digest = _cachedDomainSeparator; if (_cachedDomainSeparatorInvalidated()) digest = _buildDomainSeparator(); } /// @solidity memory-safe-assembly assembly { // Compute the digest. mstore(0x00, 0x1901000000000000) // Store "\x19\x01". mstore(0x1a, digest) // Store the domain separator. mstore(0x3a, structHash) // Store the struct hash. digest := keccak256(0x18, 0x42) // Restore the part of the free memory slot that was overwritten. mstore(0x3a, 0) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EIP-5267 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev See: https://eips.ethereum.org/EIPS/eip-5267 function eip712Domain() public view virtual returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { fields = hex"0f"; // `0b01111`. (name, version) = _domainNameAndVersion(); chainId = block.chainid; verifyingContract = address(this); salt = salt; // `bytes32(0)`. extensions = extensions; // `new uint256[](0)`. } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PRIVATE HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the EIP-712 domain separator. function _buildDomainSeparator() private view returns (bytes32 separator) { // We will use `separator` to store the name hash to save a bit of gas. bytes32 versionHash; if (_domainNameAndVersionMayChange()) { (string memory name, string memory version) = _domainNameAndVersion(); separator = keccak256(bytes(name)); versionHash = keccak256(bytes(version)); } else { separator = _cachedNameHash; versionHash = _cachedVersionHash; } /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Load the free memory pointer. mstore(m, _DOMAIN_TYPEHASH) mstore(add(m, 0x20), separator) // Name hash. mstore(add(m, 0x40), versionHash) mstore(add(m, 0x60), chainid()) mstore(add(m, 0x80), address()) separator := keccak256(m, 0xa0) } } /// @dev Returns if the cached domain separator has been invalidated. function _cachedDomainSeparatorInvalidated() private view returns (bool result) { uint256 cachedChainId = _cachedChainId; uint256 cachedThis = _cachedThis; /// @solidity memory-safe-assembly assembly { result := iszero(and(eq(chainid(), cachedChainId), eq(address(), cachedThis))) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Gas optimized ECDSA wrapper. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol) /// /// @dev Note: /// - The recovery functions use the ecrecover precompile (0x1). /// - As of Solady version 0.0.68, the `recover` variants will revert upon recovery failure. /// This is for more safety by default. /// Use the `tryRecover` variants if you need to get the zero address back /// upon recovery failure instead. /// - As of Solady version 0.0.134, all `bytes signature` variants accept both /// regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures. /// See: https://eips.ethereum.org/EIPS/eip-2098 /// This is for calldata efficiency on smart accounts prevalent on L2s. /// /// WARNING! Do NOT use signatures as unique identifiers: /// - Use a nonce in the digest to prevent replay attacks on the same contract. /// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts. /// EIP-712 also enables readable signing of typed data for better user safety. /// This implementation does NOT check if a signature is non-malleable. library ECDSA { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The signature is invalid. error InvalidSignature(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* RECOVERY OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`. function recover(bytes32 hash, bytes memory signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { result := 1 let m := mload(0x40) // Cache the free memory pointer. for {} 1 {} { mstore(0x00, hash) mstore(0x40, mload(add(signature, 0x20))) // `r`. if eq(mload(signature), 64) { let vs := mload(add(signature, 0x40)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x60, shr(1, shl(1, vs))) // `s`. break } if eq(mload(signature), 65) { mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`. mstore(0x60, mload(add(signature, 0x40))) // `s`. break } result := 0 break } result := mload( staticcall( gas(), // Amount of gas left for the transaction. result, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`. function recoverCalldata(bytes32 hash, bytes calldata signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { result := 1 let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) for {} 1 {} { if eq(signature.length, 64) { let vs := calldataload(add(signature.offset, 0x20)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, calldataload(signature.offset)) // `r`. mstore(0x60, shr(1, shl(1, vs))) // `s`. break } if eq(signature.length, 65) { mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`. calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`. break } result := 0 break } result := mload( staticcall( gas(), // Amount of gas left for the transaction. result, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the EIP-2098 short form signature defined by `r` and `vs`. function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, r) mstore(0x60, shr(1, shl(1, vs))) // `s`. result := mload( staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the signature defined by `v`, `r`, `s`. function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, and(v, 0xff)) mstore(0x40, r) mstore(0x60, s) result := mload( staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* TRY-RECOVER OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // WARNING! // These functions will NOT revert upon recovery failure. // Instead, they will return the zero address upon recovery failure. // It is critical that the returned address is NEVER compared against // a zero address (e.g. an uninitialized address variable). /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`. function tryRecover(bytes32 hash, bytes memory signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { result := 1 let m := mload(0x40) // Cache the free memory pointer. for {} 1 {} { mstore(0x00, hash) mstore(0x40, mload(add(signature, 0x20))) // `r`. if eq(mload(signature), 64) { let vs := mload(add(signature, 0x40)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x60, shr(1, shl(1, vs))) // `s`. break } if eq(mload(signature), 65) { mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`. mstore(0x60, mload(add(signature, 0x40))) // `s`. break } result := 0 break } pop( staticcall( gas(), // Amount of gas left for the transaction. result, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`. function tryRecoverCalldata(bytes32 hash, bytes calldata signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { result := 1 let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) for {} 1 {} { if eq(signature.length, 64) { let vs := calldataload(add(signature.offset, 0x20)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, calldataload(signature.offset)) // `r`. mstore(0x60, shr(1, shl(1, vs))) // `s`. break } if eq(signature.length, 65) { mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`. calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`. break } result := 0 break } pop( staticcall( gas(), // Amount of gas left for the transaction. result, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the EIP-2098 short form signature defined by `r` and `vs`. function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, r) mstore(0x60, shr(1, shl(1, vs))) // `s`. pop( staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the signature defined by `v`, `r`, `s`. function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, and(v, 0xff)) mstore(0x40, r) mstore(0x60, s) pop( staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HASHING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an Ethereum Signed Message, created from a `hash`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { mstore(0x20, hash) // Store into scratch space for keccak256. mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes. result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`. } } /// @dev Returns an Ethereum Signed Message, created from `s`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. /// Note: Supports lengths of `s` up to 999999 bytes. function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { let sLength := mload(s) let o := 0x20 mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded. mstore(0x00, 0x00) // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`. for { let temp := sLength } 1 {} { o := sub(o, 1) mstore8(o, add(48, mod(temp, 10))) temp := div(temp, 10) if iszero(temp) { break } } let n := sub(0x3a, o) // Header length: `26 + 32 - o`. // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes. returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20)) mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header. result := keccak256(add(s, sub(0x20, n)), add(n, sLength)) mstore(s, sLength) // Restore the length. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EMPTY CALLDATA HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an empty calldata bytes. function emptySignature() internal pure returns (bytes calldata signature) { /// @solidity memory-safe-assembly assembly { signature.length := 0 } } }
/** ** 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. * @param aggregator - The aggregator used for the following UserOperationEvents. */ event SignatureAggregatorChanged(address indexed aggregator); /** * A custom revert error of handleOps, to identify the offending op. * 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. * 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. */ error FailedOp(uint256 opIndex, string reason); /** * Error case when a signature aggregator fails to verify the aggregated signature it had created. * @param aggregator The aggregator that failed to verify the signature */ error SignatureValidationFailed(address aggregator); // Return value of getSenderAddress. error SenderAddressResult(address sender); // UserOps handled, per aggregator. struct UserOpsPerAggregator { UserOperation[] userOps; // Aggregator address IAggregator aggregator; // Aggregated signature bytes signature; } /** * Execute a batch of UserOperations. * 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. * @param userOp - The user operation to generate the request ID for. */ function getUserOpHash( UserOperation calldata userOp ) external view returns (bytes32); /** * 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; }
// 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; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; abstract contract Compatibility { event Received(address sender, uint256 amount); receive() external payable { emit Received(msg.sender, msg.value); } function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) { return this.onERC721Received.selector; } function onERC1155Received(address, address, uint256, uint256, bytes calldata) external pure returns (bytes4) { return this.onERC1155Received.selector; } function onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata) external pure returns (bytes4) { return this.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // Importing necessary interfaces import {IEntryPoint} from "I4337/interfaces/IEntryPoint.sol"; import {IKernelValidator} from "../interfaces/IKernelValidator.sol"; import {IKernel} from "../interfaces/IKernel.sol"; import {KERNEL_STORAGE_SLOT, KERNEL_STORAGE_SLOT_1, IMPLEMENTATION_SLOT} from "../common/Constants.sol"; import {ExecutionDetail, WalletKernelStorage} from "../common/Structs.sol"; import {ValidUntil, ValidAfter} from "../common/Types.sol"; /// @title Kernel Storage Contract /// @author taek<[email protected]> /// @notice This contract serves as the storage module for the Kernel contract. /// @dev This contract should only be used by the main Kernel contract. abstract contract KernelStorage is IKernel { IEntryPoint public immutable entryPoint; // The entry point of the contract // Modifier to check if the function is called by the entry point, the contract itself or the owner modifier onlyFromEntryPointOrSelf() { if (msg.sender != address(entryPoint) && msg.sender != address(this)) { revert NotAuthorizedCaller(); } _; } /// @param _entryPoint The address of the EntryPoint contract /// @dev Sets up the EntryPoint contract address constructor(IEntryPoint _entryPoint) { entryPoint = _entryPoint; getKernelStorage().defaultValidator = IKernelValidator(address(1)); } // Function to initialize the wallet kernel function initialize(IKernelValidator _defaultValidator, bytes calldata _data) external payable override { _setInitialData(_defaultValidator, _data); } // Function to get the wallet kernel storage function getKernelStorage() internal pure returns (WalletKernelStorage storage ws) { assembly { ws.slot := KERNEL_STORAGE_SLOT } } // Function to upgrade the contract to a new implementation function upgradeTo(address _newImplementation) external payable override onlyFromEntryPointOrSelf { assembly { sstore(IMPLEMENTATION_SLOT, _newImplementation) } emit Upgraded(_newImplementation); } // Functions to get the nonce from the entry point function getNonce() external view virtual returns (uint256) { return entryPoint.getNonce(address(this), 0); } function getNonce(uint192 key) external view virtual returns (uint256) { return entryPoint.getNonce(address(this), key); } // query storage function getDefaultValidator() external view override returns (IKernelValidator validator) { assembly { validator := shr(80, sload(KERNEL_STORAGE_SLOT_1)) } } function getDisabledMode() external view override returns (bytes4 disabled) { assembly { disabled := shl(224, sload(KERNEL_STORAGE_SLOT_1)) } } function getLastDisabledTime() external view override returns (uint48) { return getKernelStorage().lastDisabledTime; } function getExecution(bytes4 _selector) external view override returns (ExecutionDetail memory) { return getKernelStorage().execution[_selector]; } function setExecution( bytes4 _selector, address _executor, IKernelValidator _validator, ValidUntil _validUntil, ValidAfter _validAfter, bytes calldata _enableData ) external payable override onlyFromEntryPointOrSelf { getKernelStorage().execution[_selector] = ExecutionDetail({ executor: _executor, validator: _validator, validUntil: _validUntil, validAfter: _validAfter }); _validator.enable(_enableData); emit ExecutionChanged(_selector, _executor, address(_validator)); } function setDefaultValidator(IKernelValidator _defaultValidator, bytes calldata _data) external payable virtual onlyFromEntryPointOrSelf { IKernelValidator oldValidator = getKernelStorage().defaultValidator; getKernelStorage().defaultValidator = _defaultValidator; emit DefaultValidatorChanged(address(oldValidator), address(_defaultValidator)); _defaultValidator.enable(_data); } function disableMode(bytes4 _disableFlag) external payable override onlyFromEntryPointOrSelf { getKernelStorage().disabledMode = _disableFlag; getKernelStorage().lastDisabledTime = uint48(block.timestamp); } function _setInitialData(IKernelValidator _defaultValidator, bytes calldata _data) internal virtual { address validator; assembly { validator := shr(80, sload(KERNEL_STORAGE_SLOT_1)) } if (address(validator) != address(0)) { revert AlreadyInitialized(); } getKernelStorage().defaultValidator = _defaultValidator; _defaultValidator.enable(_data); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {SIG_VALIDATION_FAILED_UINT} from "../common/Constants.sol"; import {ValidationData} from "../common/Types.sol"; function _intersectValidationData(ValidationData a, ValidationData b) pure returns (ValidationData validationData) { assembly { // xor(a,b) == shows only matching bits // and(xor(a,b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff) == filters out the validAfter and validUntil bits // if the result is not zero, then aggregator part is not matching // validCase : // a == 0 || b == 0 || xor(a,b) == 0 // invalidCase : // a mul b != 0 && xor(a,b) != 0 let sum := shl(96, add(a, b)) switch or( iszero(and(xor(a, b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff)), or(eq(sum, shl(96, a)), eq(sum, shl(96, b))) ) case 1 { validationData := and(or(a, b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff) // validAfter let a_vd := and(0xffffffffffff0000000000000000000000000000000000000000000000000000, a) let b_vd := and(0xffffffffffff0000000000000000000000000000000000000000000000000000, b) validationData := or(validationData, xor(a_vd, mul(xor(a_vd, b_vd), gt(b_vd, a_vd)))) // validUntil a_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, a) if iszero(a_vd) { a_vd := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } b_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, b) if iszero(b_vd) { b_vd := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } let until := xor(a_vd, mul(xor(a_vd, b_vd), lt(b_vd, a_vd))) if iszero(until) { until := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } validationData := or(validationData, until) } default { validationData := SIG_VALIDATION_FAILED_UINT } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {UserOperation} from "I4337/interfaces/UserOperation.sol"; import "../common/Types.sol"; interface IKernelValidator { error NotImplemented(); function enable(bytes calldata _data) external payable; function disable(bytes calldata _data) external payable; function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingFunds) external payable returns (ValidationData); function validateSignature(bytes32 hash, bytes calldata signature) external view returns (ValidationData); function validCaller(address caller, bytes calldata data) external view returns (bool); } // 3 modes // 1. default mode, use preset validator for the kernel // 2. enable mode, enable a new validator for given action and use it for current userOp // 3. sudo mode, use default plugin for current userOp
pragma solidity ^0.8.0; import {ValidationData} from "./Types.sol"; // Constants for kernel metadata string constant KERNEL_NAME = "Kernel"; string constant KERNEL_VERSION = "0.2.4"; // ERC4337 constants uint256 constant SIG_VALIDATION_FAILED_UINT = 1; ValidationData constant SIG_VALIDATION_FAILED = ValidationData.wrap(SIG_VALIDATION_FAILED_UINT); // STRUCT_HASH /// @dev Struct hash for the ValidatorApproved struct -> keccak256("ValidatorApproved(bytes4 sig,uint256 validatorData,address executor,bytes enableData)") bytes32 constant VALIDATOR_APPROVED_STRUCT_HASH = 0x3ce406685c1b3551d706d85a68afdaa49ac4e07b451ad9b8ff8b58c3ee964176; /* -------------------------------------------------------------------------- */ /* Storage slots */ /* -------------------------------------------------------------------------- */ /// @dev Storage slot for the kernel storage bytes32 constant KERNEL_STORAGE_SLOT = 0x439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd8; /// @dev Storage pointer inside the kernel storage, with 1 offset, to access directly disblaedMode, disabled date and default validator bytes32 constant KERNEL_STORAGE_SLOT_1 = 0x439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd9; /// @dev Storage slot for the logic implementation address bytes32 constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
pragma solidity ^0.8.0; enum Operation { Call, DelegateCall } enum ParamCondition { EQUAL, GREATER_THAN, LESS_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN_OR_EQUAL, NOT_EQUAL }
pragma solidity ^0.8.0; import {IKernelValidator} from "../interfaces/IKernelValidator.sol"; import {ParamCondition, Operation} from "./Enums.sol"; import {ValidAfter, ValidUntil} from "./Types.sol"; // Defining a struct for execution details struct ExecutionDetail { ValidAfter validAfter; // Until what time is this execution valid ValidUntil validUntil; // After what time is this execution valid address executor; // Who is the executor of this execution IKernelValidator validator; // The validator for this execution } struct Call { address to; uint256 value; bytes data; } // Defining a struct for wallet kernel storage struct WalletKernelStorage { bytes32 __deprecated; // A deprecated field bytes4 disabledMode; // Mode which is currently disabled uint48 lastDisabledTime; // Last time when a mode was disabled IKernelValidator defaultValidator; // Default validator for the wallet mapping(bytes4 => ExecutionDetail) execution; // Mapping of function selectors to execution details } // Param Rule for session key struct Nonces { uint128 lastNonce; uint128 invalidNonce; } struct ParamRule { uint256 offset; ParamCondition condition; bytes32 param; } struct ExecutionRule { ValidAfter validAfter; // 48 bits uint48 interval; // 48 bits uint48 runs; // 48 bits } struct ExecutionStatus { ValidAfter validAfter; // 48 bits uint48 runs; // 48 bits } struct Permission { uint32 index; address target; bytes4 sig; uint256 valueLimit; ParamRule[] rules; ExecutionRule executionRule; Operation operation; } struct SessionData { bytes32 merkleRoot; ValidAfter validAfter; ValidUntil validUntil; address paymaster; // address(0) means accept userOp without paymaster, address(1) means reject userOp with paymaster, other address means accept userOp with paymaster with the address uint256 nonce; }
pragma solidity ^0.8.9; type ValidAfter is uint48; type ValidUntil is uint48; type ValidationData is uint256; function packValidationData(ValidAfter validAfter, ValidUntil validUntil) pure returns (ValidationData) { return ValidationData.wrap( uint256(ValidAfter.unwrap(validAfter)) << 208 | uint256(ValidUntil.unwrap(validUntil)) << 160 ); } function packValidationData(address aggregator, ValidAfter validAfter, ValidUntil validUntil) pure returns (ValidationData) { return ValidationData.wrap( uint256(ValidAfter.unwrap(validAfter)) << 208 | uint256(ValidUntil.unwrap(validUntil)) << 160 | uint160(aggregator) ); } function parseValidationData(ValidationData validationData) pure returns (ValidAfter validAfter, ValidUntil validUntil, address result) { assembly { result := validationData validUntil := and(shr(160, validationData), 0xffffffffffff) switch iszero(validUntil) case 1 { validUntil := 0xffffffffffff } validAfter := shr(208, validationData) } }
// 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; } /** * Get deposit info. * @param account - The account to query. * @return info - Full deposit information of given account. */ function getDepositInfo( address account ) external view returns (DepositInfo memory info); /** * Get account balance. * @param account - The account to query. * @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. * @param account - The account to add to. */ 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; import "./UserOperation.sol"; /** * Aggregated Signatures validator. */ interface IAggregator { /** * Validate aggregated signature. * Revert if the aggregated signature does not match the given list of operations. * @param userOps - Array of UserOperations to validate the signature for. * @param signature - The aggregated signature. */ 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 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: MIT pragma solidity ^0.8.0; import {IKernelValidator} from "./IKernelValidator.sol"; import {ExecutionDetail, Call} from "../common/Structs.sol"; import {ValidationData, ValidUntil, ValidAfter} from "../common/Types.sol"; import {Operation} from "../common/Enums.sol"; import {UserOperation} from "I4337/interfaces/UserOperation.sol"; interface IKernel { // Event declarations event Upgraded(address indexed newImplementation); event DefaultValidatorChanged(address indexed oldValidator, address indexed newValidator); event ExecutionChanged(bytes4 indexed selector, address indexed executor, address indexed validator); // Error declarations error NotAuthorizedCaller(); error AlreadyInitialized(); error NotEntryPoint(); error DisabledMode(); error DeprecatedOperation(); function initialize(IKernelValidator _validator, bytes calldata _data) external payable; function upgradeTo(address _newImplementation) external payable; function getNonce() external view returns (uint256); function getNonce(uint192 key) external view returns (uint256); function getDefaultValidator() external view returns (IKernelValidator); function getDisabledMode() external view returns (bytes4 disabled); function getLastDisabledTime() external view returns (uint48); /// @notice Returns the execution details for a specific function signature /// @dev This function can be used to get execution details for a specific function signature /// @param _selector The function signature /// @return ExecutionDetail struct containing the execution details function getExecution(bytes4 _selector) external view returns (ExecutionDetail memory); /// @notice Changes the execution details for a specific function selector /// @dev This function can only be called from the EntryPoint contract, the contract owner, or itself /// @param _selector The selector of the function for which execution details are being set /// @param _executor The executor to be associated with the function selector /// @param _validator The validator contract that will be responsible for validating operations associated with this function selector /// @param _validUntil The timestamp until which the execution details are valid /// @param _validAfter The timestamp after which the execution details are valid function setExecution( bytes4 _selector, address _executor, IKernelValidator _validator, ValidUntil _validUntil, ValidAfter _validAfter, bytes calldata _enableData ) external payable; function setDefaultValidator(IKernelValidator _defaultValidator, bytes calldata _data) external payable; /// @notice Updates the disabled mode /// @dev This function can be used to update the disabled mode /// @param _disableFlag The new disabled mode function disableMode(bytes4 _disableFlag) external payable; /// @notice Executes a function call to an external contract /// @dev The type of operation (call or delegatecall) is specified as an argument. /// @param to The address of the target contract /// @param value The amount of Ether to send /// @param data The call data to be sent /// operation deprecated operation type, usere executeBatch for batch operation function execute(address to, uint256 value, bytes memory data, Operation) external payable; function executeBatch(Call[] memory calls) external payable; function executeDelegateCall(address to, bytes memory data) external payable; /// @notice Validates a user operation based on its mode /// @dev This function will validate user operation and be called by EntryPoint /// @param userOp The user operation to be validated /// @param userOpHash The hash of the user operation /// @param missingAccountFunds The funds needed to be reimbursed /// @return validationData The data used for validation function validateUserOp(UserOperation memory userOp, bytes32 userOpHash, uint256 missingAccountFunds) external payable returns (ValidationData validationData); }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "solady/=lib/solady/src/", "I4337/=lib/I4337/src/", "FreshCryptoLib/=lib/FreshCryptoLib/solidity/src/", "p256-verifier/=lib/p256-verifier/src/", "@openzeppelin/contracts/=lib/p256-verifier/lib/openzeppelin-contracts/contracts/", "account-abstraction/=lib/account-abstraction/contracts/", "erc4626-tests/=lib/p256-verifier/lib/openzeppelin-contracts/lib/erc4626-tests/", "openzeppelin-contracts/=lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none", "appendCBOR": false }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": {} }
[{"inputs":[{"internalType":"contract IEntryPoint","name":"_entryPoint","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"DeprecatedOperation","type":"error"},{"inputs":[],"name":"DisabledMode","type":"error"},{"inputs":[],"name":"NotAuthorizedCaller","type":"error"},{"inputs":[],"name":"NotEntryPoint","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldValidator","type":"address"},{"indexed":true,"internalType":"address","name":"newValidator","type":"address"}],"name":"DefaultValidatorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes4","name":"selector","type":"bytes4"},{"indexed":true,"internalType":"address","name":"executor","type":"address"},{"indexed":true,"internalType":"address","name":"validator","type":"address"}],"name":"ExecutionChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Received","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newImplementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"bytes4","name":"_disableFlag","type":"bytes4"}],"name":"disableMode","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"entryPoint","outputs":[{"internalType":"contract IEntryPoint","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum Operation","name":"_operation","type":"uint8"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Call[]","name":"calls","type":"tuple[]"}],"name":"executeBatch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"executeDelegateCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getDefaultValidator","outputs":[{"internalType":"contract IKernelValidator","name":"validator","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDisabledMode","outputs":[{"internalType":"bytes4","name":"disabled","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_selector","type":"bytes4"}],"name":"getExecution","outputs":[{"components":[{"internalType":"ValidAfter","name":"validAfter","type":"uint48"},{"internalType":"ValidUntil","name":"validUntil","type":"uint48"},{"internalType":"address","name":"executor","type":"address"},{"internalType":"contract IKernelValidator","name":"validator","type":"address"}],"internalType":"struct ExecutionDetail","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastDisabledTime","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint192","name":"key","type":"uint192"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IKernelValidator","name":"_defaultValidator","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"initialize","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"contract IKernelValidator","name":"_defaultValidator","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"setDefaultValidator","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_selector","type":"bytes4"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"contract IKernelValidator","name":"_validator","type":"address"},{"internalType":"ValidUntil","name":"_validUntil","type":"uint48"},{"internalType":"ValidAfter","name":"_validAfter","type":"uint48"},{"internalType":"bytes","name":"_enableData","type":"bytes"}],"name":"setExecution","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"validateSignature","outputs":[{"internalType":"ValidationData","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"uint256","name":"callGasLimit","type":"uint256"},{"internalType":"uint256","name":"verificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation","name":"_userOp","type":"tuple"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"uint256","name":"missingAccountFunds","type":"uint256"}],"name":"validateUserOp","outputs":[{"internalType":"ValidationData","name":"validationData","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6101406040523480156200001257600080fd5b5060405162002c4738038062002c47833981016040819052620000359162000137565b306080524660a0528060608062000081604080518082018252600681526512d95c9b995b60d21b602080830191909152825180840190935260058352640c0b8c8b8d60da1b9083015291565b815160209283012081519183019190912060c082905260e0819052604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8152938401929092529082015246606082015230608082015260a090206101005250506001600160a01b031661012052507f439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd98054600160501b600160f01b0319166a010000000000000000000017905562000169565b6000602082840312156200014a57600080fd5b81516001600160a01b03811681146200016257600080fd5b9392505050565b60805160a05160c05160e0516101005161012051612a4162000206600039600081816101e9015281816105ec015281816108e201528181610ae401528181610bbf01528181610c7301528181610f8301528181611007015281816110bf0152818161120a015281816112a3015261133101526000611c6f01526000611d2901526000611d0301526000611cb301526000611c900152612a416000f3fe60806040526004361061014f5760003560e01c806354fd4d50116100b6578063b68df16d1161006f578063b68df16d1461060e578063bc197c8114610621578063d087d28814610650578063d1f5789414610665578063d541622114610678578063f23a6e611461068b5761018e565b806354fd4d501461050557806355b14f501461053657806357b750471461054957806384b0196e1461056e57806388e7fd0614610596578063b0d691fe146105da5761018e565b806334fcd5be1161010857806334fcd5be146103885780633659cfe61461039b5780633a871cdd146103ae5780633e1b0812146103c157806351166ba0146103e157806351945447146104f25761018e565b806306fdde03146102615780630b3dc354146102a9578063150b7a02146102e25780631626ba7e1461032757806329f8b17414610347578063333daf921461035a5761018e565b3661018e57604080513381523460208201527f88a5966d370b9919b20f3e2c13ff65706f196a4e32cc2c12bf57088f88525874910160405180910390a1005b600080356001600160e01b031916905060006101b5600080516020612a0183398151915290565b6001600160e01b0319831660009081526002919091016020526040902054600160601b90046001600160a01b0390811691507f000000000000000000000000000000000000000000000000000000000000000016331480159061021d575061021b6106b8565b155b1561023b57604051637046c88d60e01b815260040160405180910390fd5b3660008037600080366000845af43d6000803e80801561025a573d6000f35b3d6000fd5b005b34801561026d57600080fd5b506102936040518060400160405280600681526020016512d95c9b995b60d21b81525081565b6040516102a09190611dd5565b60405180910390f35b3480156102b557600080fd5b50600080516020612a218339815191525460501c5b6040516001600160a01b0390911681526020016102a0565b3480156102ee57600080fd5b5061030e6102fd366004611e58565b630a85bd0160e11b95945050505050565b6040516001600160e01b031990911681526020016102a0565b34801561033357600080fd5b5061030e610342366004611eca565b6107fe565b61025f610355366004611f41565b6108d7565b34801561036657600080fd5b5061037a610375366004611eca565b610ac2565b6040519081526020016102a0565b61025f6103963660046120df565b610ad9565b61025f6103a93660046121e5565b610bb4565b61037a6103bc366004612202565b610c66565b3480156103cd57600080fd5b5061037a6103dc366004612255565b610f5c565b3480156103ed57600080fd5b506104a56103fc36600461227e565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160e01b03199590951681527f439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dda855283902083519182018452805465ffffffffffff8082168452600160301b82041695830195909552600160601b9094046001600160a01b03908116938201939093526001909301549091169082015290565b60408051825165ffffffffffff908116825260208085015190911690820152828201516001600160a01b0390811692820192909252606092830151909116918101919091526080016102a0565b61025f610500366004612299565b610ffc565b34801561051157600080fd5b50610293604051806040016040528060058152602001640c0b8c8b8d60da1b81525081565b61025f610544366004612308565b6110b4565b34801561055557600080fd5b50600080516020612a218339815191525460e01b61030e565b34801561057a57600080fd5b506105836111d8565b6040516102a09796959493929190612343565b3480156105a257600080fd5b50600080516020612a2183398151915254640100000000900465ffffffffffff1660405165ffffffffffff90911681526020016102a0565b3480156105e657600080fd5b506102ca7f000000000000000000000000000000000000000000000000000000000000000081565b61025f61061c3660046123d9565b6111ff565b34801561062d57600080fd5b5061030e61063c36600461246c565b63bc197c8160e01b98975050505050505050565b34801561065c57600080fd5b5061037a611284565b61025f610673366004612308565b61131b565b61025f61068636600461227e565b611326565b34801561069757600080fd5b5061030e6106a636600461252a565b63f23a6e6160e01b9695505050505050565b60006106c6336000366113bc565b156106d15750600190565b600080356001600160e01b031916905060006106f8600080516020612a0183398151915290565b6001600160e01b0319831660009081526002919091016020526040902060018101549091506001600160a01b0316158061075c57508054600160301b900465ffffffffffff161580159061075c5750805442600160301b90910465ffffffffffff16105b80610771575080544265ffffffffffff909116115b1561077f5760009250505090565b6001810154604051639ea9bd5960e01b81526001600160a01b0390911690639ea9bd59906107b690339060009036906004016125ce565b602060405180830381865afa1580156107d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f791906125f3565b9250505090565b60008061080961144d565b60405161190160f01b60208201526022810182905260428101879052909150600090606201604051602081830303815290604052805190602001209050600061085533838989896114d0565b905060008060006108658461164b565b925092509250428365ffffffffffff161115801561088b5750428265ffffffffffff1610155b801561089e57506001600160a01b038116155b156108b95750630b135d3f60e11b95506108d0945050505050565b506001600160e01b031995506108d0945050505050565b9392505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015906109105750333014155b1561092e57604051637046c88d60e01b815260040160405180910390fd5b60405180608001604052808465ffffffffffff1681526020018565ffffffffffff168152602001876001600160a01b03168152602001866001600160a01b0316815250610986600080516020612a0183398151915290565b6001600160e01b031989166000908152600291909101602090815260409182902083518154928501518585015165ffffffffffff9283166001600160601b031990951694909417600160301b9290911691909102176bffffffffffffffffffffffff16600160601b6001600160a01b0393841602178155606090930151600190930180546001600160a01b031916938216939093179092555163064acaab60e11b815290861690630c95955690610a439085908590600401612615565b600060405180830381600087803b158015610a5d57600080fd5b505af1158015610a71573d6000803e3d6000fd5b50506040516001600160a01b038089169350891691506001600160e01b03198a16907fed03d2572564284398470d3f266a693e29ddfff3eba45fc06c5e91013d32135390600090a450505050505050565b6000610ad133858686866114d0565b949350505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801590610b175750610b156106b8565b155b15610b3557604051637046c88d60e01b815260040160405180910390fd5b805160005b81811015610baf576000838281518110610b5657610b56612629565b6020026020010151905060008160000151905060008260200151905060008360400151905060008082516020840185875af1808015610b9a57600187019650610ba4565b3d6000803e3d6000fd5b505050505050610b3a565b505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801590610bed5750333014155b15610c0b57604051637046c88d60e01b815260040160405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8190556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6000336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cb157604051636b31ba1560e11b815260040160405180910390fd5b6024600480356101448101358101838101939083013592910190600090610cda9082858761263f565b610ce391612669565b90506001600160e01b03198116600003610d1d578515610d07573434343489335af1505b610d1288888861167e565b9450505050506108d0565b600080516020612a218339815191525460e01b81811615610d465763fc2f51c56000526004601cfd5b5060006001600160e01b03198216600160e01b03610e155760408301358301601f1981013560007f439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dda81610d9c600482868861263f565b610da591612669565b6001600160e01b0319168152602081019190915260400160002060018101546001600160a01b031694509050610dde876004818b61263f565b82549199509750600160301b810460a01b65ffffffffffff60a01b1660d09190911b6001600160d01b031916179850505050610e77565b6001600160e01b03198216600160e11b03610e695760408301358301601f19810135610e58610e4860046000848661263f565b610e5191612669565b8888611776565b919a50985096509250610e77915050565b6001955050505050506108d0565b8615610e8757343434348a335af1505b6000610e928a612697565b905085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505050610140820152604051633a871cdd60e01b8152610f4e9088906001600160a01b03851690633a871cdd90610f069086908f908f906004016127a5565b6020604051808303816000875af1158015610f25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f499190612897565b611adf565b9a9950505050505050505050565b604051631aab3f0d60e11b81523060048201526001600160c01b03821660248201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906335567e1a90604401602060405180830381865afa158015610fd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff69190612897565b92915050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015906110355750333014155b801561104657506110446106b8565b155b1561106457604051637046c88d60e01b815260040160405180910390fd5b6000816001811115611078576110786128b0565b14611096576040516367ce775960e01b815260040160405180910390fd5b60008083516020850186885af13d6000803e80801561025a573d6000f35b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015906110ed5750333014155b1561110b57604051637046c88d60e01b815260040160405180910390fd5b600080516020612a2183398151915280546001600160a01b03858116600160501b818102600160501b600160f01b031985161790945560405193909204169182907fa35f5cdc5fbabb614b4cd5064ce5543f43dc8fab0e4da41255230eb8aba2531c90600090a360405163064acaab60e11b81526001600160a01b03851690630c959556906111a09086908690600401612615565b600060405180830381600087803b1580156111ba57600080fd5b505af11580156111ce573d6000803e3d6000fd5b5050505050505050565b600f60f81b60608060008080836111ed611b9d565b97989097965046955030945091925090565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015906112385750333014155b801561124957506112476106b8565b155b1561126757604051637046c88d60e01b815260040160405180910390fd5b600080825160208401855af43d6000803e80801561025a573d6000f35b604051631aab3f0d60e11b8152306004820152600060248201819052907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906335567e1a90604401602060405180830381865afa1580156112f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113169190612897565b905090565b610baf838383611bd9565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480159061135f5750333014155b1561137d57604051637046c88d60e01b815260040160405180910390fd5b600080516020612a21833981519152805460e09290921c69ffffffffffffffffffff19909216919091176401000000004265ffffffffffff1602179055565b600080516020612a2183398151915254604051639ea9bd5960e01b815260009160501c906001600160a01b03821690639ea9bd5990611403908890889088906004016125ce565b602060405180830381865afa158015611420573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144491906125f3565b95945050505050565b600080600061145a611b9d565b8151602092830120815191830191909120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818601528082019390935260608301919091524660808301523060a0808401919091528151808403909101815260c0909201905280519101209392505050565b600080600080516020612a218339815191525460501c9050600080826001600160a01b031663333daf9260e01b898888604051602401611512939291906128c6565b60408051601f19818403018152918152602080830180516001600160e01b03166001600160e01b03199095169490941790935251611554928b918e91016128e0565b60408051601f198184030181529082905261156e91612914565b600060405180830381855afa9150503d80600081146115a9576040519150601f19603f3d011682016040523d82523d6000602084013e6115ae565b606091505b50915091508161162a5760405162461bcd60e51b815260206004820152603860248201527f4b65726e656c3a3a5f76616c69646174655369676e61747572653a206661696c60448201527f656420746f2076616c6964617465207369676e61747572650000000000000000606482015260840160405180910390fd5b8080602001905181019061163e9190612897565b9998505050505050505050565b600060a082901c65ffffffffffff1682811560001981016116705765ffffffffffff92505b508360d01c92509193909250565b60008061168a85612697565b905061169a610140860186612930565b6116a891600490829061263f565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505050610140820152600080516020612a2183398151915254604051633a871cdd60e01b815260509190911c906001600160a01b03821690633a871cdd90611729908590899089906004016127a5565b6020604051808303816000875af1158015611748573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176c9190612897565b9695505050505050565b600080368161178960246010878961263f565b61179291612976565b60601c9350605860006117a8826038898b61263f565b6117b1916129a4565b828101929091508801816117ca60208501858b8d61263f565b6117d3916129a4565b60001c925060208401935060006118bd7f3ce406685c1b3551d706d85a68afdaa49ac4e07b451ad9b8ff8b58c3ee96417660001b8d8d8d60049060249261181c9392919061263f565b611825916129a4565b60001c8e8e60249060389261183c9392919061263f565b61184591612976565b60601c87876040516118589291906129c2565b6040519081900381206118a295949392916020019485526001600160e01b031993909316602085015260408401919091526001600160a01b03166060830152608082015260a00190565b60405160208183030381529060405280519060200120611c6d565b905061190d6118e13083848f8f8b908b8d01926118dc9392919061263f565b6114d0565b8c8c6004906024926118f59392919061263f565b6118fe916129a4565b6001600160a01b031916611adf565b97508385019450848b019650848a03955060405180608001604052808c8c600490600a9261193d9392919061263f565b611946916129d2565b60d01c65ffffffffffff1681526020018c8c600a9060109261196a9392919061263f565b611973916129d2565b60d01c65ffffffffffff1681526020018c8c6024906038926119979392919061263f565b6119a091612976565b60601c6001600160a01b031681526020018c8c6010906024926119c59392919061263f565b6119ce91612976565b60601c9052600080516020612a018339815191526001600160e01b03198e166000908152600291909101602090815260409182902083518154928501518585015165ffffffffffff9283166001600160601b031990951694909417600160301b9290911691909102176bffffffffffffffffffffffff16600160601b6001600160a01b0393841602178155606090930151600190930180546001600160a01b031916938216939093179092555163064acaab60e11b8152908a1690630c95955690611a9f9086908690600401612615565b600060405180830381600087803b158015611ab957600080fd5b505af1158015611acd573d6000803e3d6000fd5b50505050505050505093509350935093565b600081830160601b8260601b81148460601b8214176001600160a01b0384861816151760018114611b135760019250611b95565b6001600160d01b031980851690861681811881831102188686176001600160a01b031617935065ffffffffffff60a01b86169081611b585765ffffffffffff60a01b91505b5065ffffffffffff60a01b851680611b76575065ffffffffffff60a01b5b808218908211021880611b8f575065ffffffffffff60a01b5b92909217915b505092915050565b604080518082018252600681526512d95c9b995b60d21b602080830191909152825180840190935260058352640c0b8c8b8d60da1b9083015291565b600080516020612a218339815191525460501c6001600160a01b03811615611c135760405162dc149f60e41b815260040160405180910390fd5b600080516020612a218339815191528054600160501b600160f01b031916600160501b6001600160a01b0387169081029190911790915560405163064acaab60e11b8152630c959556906111a09086908690600401612615565b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000030147f0000000000000000000000000000000000000000000000000000000000000000461416611d605750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f000000000000000000000000000000000000000000000000000000000000000060208201527f00000000000000000000000000000000000000000000000000000000000000009181019190915246606082015230608082015260a090205b67190100000000000060005280601a5281603a52604260182090506000603a52919050565b60005b83811015611da0578181015183820152602001611d88565b50506000910152565b60008151808452611dc1816020860160208601611d85565b601f01601f19169290920160200192915050565b6020815260006108d06020830184611da9565b6001600160a01b0381168114611dfd57600080fd5b50565b8035611e0b81611de8565b919050565b60008083601f840112611e2257600080fd5b5081356001600160401b03811115611e3957600080fd5b602083019150836020828501011115611e5157600080fd5b9250929050565b600080600080600060808688031215611e7057600080fd5b8535611e7b81611de8565b94506020860135611e8b81611de8565b93506040860135925060608601356001600160401b03811115611ead57600080fd5b611eb988828901611e10565b969995985093965092949392505050565b600080600060408486031215611edf57600080fd5b8335925060208401356001600160401b03811115611efc57600080fd5b611f0886828701611e10565b9497909650939450505050565b80356001600160e01b031981168114611e0b57600080fd5b65ffffffffffff81168114611dfd57600080fd5b600080600080600080600060c0888a031215611f5c57600080fd5b611f6588611f15565b96506020880135611f7581611de8565b95506040880135611f8581611de8565b94506060880135611f9581611f2d565b93506080880135611fa581611f2d565b925060a08801356001600160401b03811115611fc057600080fd5b611fcc8a828b01611e10565b989b979a50959850939692959293505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561201757612017611fdf565b60405290565b60405161016081016001600160401b038111828210171561201757612017611fdf565b604051601f8201601f191681016001600160401b038111828210171561206857612068611fdf565b604052919050565b600082601f83011261208157600080fd5b81356001600160401b0381111561209a5761209a611fdf565b6120ad601f8201601f1916602001612040565b8181528460208386010111156120c257600080fd5b816020850160208301376000918101602001919091529392505050565b600060208083850312156120f257600080fd5b82356001600160401b038082111561210957600080fd5b818501915085601f83011261211d57600080fd5b81358181111561212f5761212f611fdf565b8060051b61213e858201612040565b918252838101850191858101908984111561215857600080fd5b86860192505b8383101561163e578235858111156121765760008081fd5b86016060818c03601f190181131561218e5760008081fd5b612196611ff5565b898301356121a381611de8565b81526040838101358b8301529183013591888311156121c25760008081fd5b6121d08e8c85870101612070565b9082015284525050918601919086019061215e565b6000602082840312156121f757600080fd5b81356108d081611de8565b60008060006060848603121561221757600080fd5b83356001600160401b0381111561222d57600080fd5b8401610160818703121561224057600080fd5b95602085013595506040909401359392505050565b60006020828403121561226757600080fd5b81356001600160c01b03811681146108d057600080fd5b60006020828403121561229057600080fd5b6108d082611f15565b600080600080608085870312156122af57600080fd5b84356122ba81611de8565b93506020850135925060408501356001600160401b038111156122dc57600080fd5b6122e887828801612070565b9250506060850135600281106122fd57600080fd5b939692955090935050565b60008060006040848603121561231d57600080fd5b833561232881611de8565b925060208401356001600160401b03811115611efc57600080fd5b60ff60f81b881681526000602060e08184015261236360e084018a611da9565b8381036040850152612375818a611da9565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b818110156123c7578351835292840192918401916001016123ab565b50909c9b505050505050505050505050565b600080604083850312156123ec57600080fd5b82356123f781611de8565b915060208301356001600160401b0381111561241257600080fd5b61241e85828601612070565b9150509250929050565b60008083601f84011261243a57600080fd5b5081356001600160401b0381111561245157600080fd5b6020830191508360208260051b8501011115611e5157600080fd5b60008060008060008060008060a0898b03121561248857600080fd5b883561249381611de8565b975060208901356124a381611de8565b965060408901356001600160401b03808211156124bf57600080fd5b6124cb8c838d01612428565b909850965060608b01359150808211156124e457600080fd5b6124f08c838d01612428565b909650945060808b013591508082111561250957600080fd5b506125168b828c01611e10565b999c989b5096995094979396929594505050565b60008060008060008060a0878903121561254357600080fd5b863561254e81611de8565b9550602087013561255e81611de8565b9450604087013593506060870135925060808701356001600160401b0381111561258757600080fd5b61259389828a01611e10565b979a9699509497509295939492505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b038416815260406020820181905260009061144490830184866125a5565b60006020828403121561260557600080fd5b815180151581146108d057600080fd5b602081526000610ad16020830184866125a5565b634e487b7160e01b600052603260045260246000fd5b6000808585111561264f57600080fd5b8386111561265c57600080fd5b5050820193919092039150565b6001600160e01b03198135818116916004851015611b955760049490940360031b84901b1690921692915050565b600061016082360312156126aa57600080fd5b6126b261201d565b6126bb83611e00565b81526020830135602082015260408301356001600160401b03808211156126e157600080fd5b6126ed36838701612070565b6040840152606085013591508082111561270657600080fd5b61271236838701612070565b60608401526080850135608084015260a085013560a084015260c085013560c084015260e085013560e0840152610100915081850135828401526101209150818501358181111561276257600080fd5b61276e36828801612070565b83850152506101409150818501358181111561278957600080fd5b61279536828801612070565b8385015250505080915050919050565b606081526127bf6060820185516001600160a01b03169052565b60208401516080820152600060408501516101608060a08501526127e76101c0850183611da9565b91506060870151605f19808685030160c08701526128058483611da9565b9350608089015160e087015260a08901519150610100828188015260c08a01519250610120838189015260e08b0151935061014084818a0152828c0151868a0152818c0151955083898803016101808a01526128618787611da9565b9650808c0151955050505080868503016101a087015250506128838282611da9565b602085019690965250505060400152919050565b6000602082840312156128a957600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b8381526040602082015260006114446040830184866125a5565b600084516128f2818460208901611d85565b919091019283525060601b6001600160601b0319166020820152603401919050565b60008251612926818460208701611d85565b9190910192915050565b6000808335601e1984360301811261294757600080fd5b8301803591506001600160401b0382111561296157600080fd5b602001915036819003821315611e5157600080fd5b6001600160601b03198135818116916014851015611b955760149490940360031b84901b1690921692915050565b80356020831015610ff657600019602084900360031b1b1692915050565b8183823760009101908152919050565b6001600160d01b03198135818116916006851015611b955760069490940360031b84901b169092169291505056fe439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd8439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd90000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789
Deployed Bytecode
0x60806040526004361061014f5760003560e01c806354fd4d50116100b6578063b68df16d1161006f578063b68df16d1461060e578063bc197c8114610621578063d087d28814610650578063d1f5789414610665578063d541622114610678578063f23a6e611461068b5761018e565b806354fd4d501461050557806355b14f501461053657806357b750471461054957806384b0196e1461056e57806388e7fd0614610596578063b0d691fe146105da5761018e565b806334fcd5be1161010857806334fcd5be146103885780633659cfe61461039b5780633a871cdd146103ae5780633e1b0812146103c157806351166ba0146103e157806351945447146104f25761018e565b806306fdde03146102615780630b3dc354146102a9578063150b7a02146102e25780631626ba7e1461032757806329f8b17414610347578063333daf921461035a5761018e565b3661018e57604080513381523460208201527f88a5966d370b9919b20f3e2c13ff65706f196a4e32cc2c12bf57088f88525874910160405180910390a1005b600080356001600160e01b031916905060006101b5600080516020612a0183398151915290565b6001600160e01b0319831660009081526002919091016020526040902054600160601b90046001600160a01b0390811691507f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d278916331480159061021d575061021b6106b8565b155b1561023b57604051637046c88d60e01b815260040160405180910390fd5b3660008037600080366000845af43d6000803e80801561025a573d6000f35b3d6000fd5b005b34801561026d57600080fd5b506102936040518060400160405280600681526020016512d95c9b995b60d21b81525081565b6040516102a09190611dd5565b60405180910390f35b3480156102b557600080fd5b50600080516020612a218339815191525460501c5b6040516001600160a01b0390911681526020016102a0565b3480156102ee57600080fd5b5061030e6102fd366004611e58565b630a85bd0160e11b95945050505050565b6040516001600160e01b031990911681526020016102a0565b34801561033357600080fd5b5061030e610342366004611eca565b6107fe565b61025f610355366004611f41565b6108d7565b34801561036657600080fd5b5061037a610375366004611eca565b610ac2565b6040519081526020016102a0565b61025f6103963660046120df565b610ad9565b61025f6103a93660046121e5565b610bb4565b61037a6103bc366004612202565b610c66565b3480156103cd57600080fd5b5061037a6103dc366004612255565b610f5c565b3480156103ed57600080fd5b506104a56103fc36600461227e565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160e01b03199590951681527f439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dda855283902083519182018452805465ffffffffffff8082168452600160301b82041695830195909552600160601b9094046001600160a01b03908116938201939093526001909301549091169082015290565b60408051825165ffffffffffff908116825260208085015190911690820152828201516001600160a01b0390811692820192909252606092830151909116918101919091526080016102a0565b61025f610500366004612299565b610ffc565b34801561051157600080fd5b50610293604051806040016040528060058152602001640c0b8c8b8d60da1b81525081565b61025f610544366004612308565b6110b4565b34801561055557600080fd5b50600080516020612a218339815191525460e01b61030e565b34801561057a57600080fd5b506105836111d8565b6040516102a09796959493929190612343565b3480156105a257600080fd5b50600080516020612a2183398151915254640100000000900465ffffffffffff1660405165ffffffffffff90911681526020016102a0565b3480156105e657600080fd5b506102ca7f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d278981565b61025f61061c3660046123d9565b6111ff565b34801561062d57600080fd5b5061030e61063c36600461246c565b63bc197c8160e01b98975050505050505050565b34801561065c57600080fd5b5061037a611284565b61025f610673366004612308565b61131b565b61025f61068636600461227e565b611326565b34801561069757600080fd5b5061030e6106a636600461252a565b63f23a6e6160e01b9695505050505050565b60006106c6336000366113bc565b156106d15750600190565b600080356001600160e01b031916905060006106f8600080516020612a0183398151915290565b6001600160e01b0319831660009081526002919091016020526040902060018101549091506001600160a01b0316158061075c57508054600160301b900465ffffffffffff161580159061075c5750805442600160301b90910465ffffffffffff16105b80610771575080544265ffffffffffff909116115b1561077f5760009250505090565b6001810154604051639ea9bd5960e01b81526001600160a01b0390911690639ea9bd59906107b690339060009036906004016125ce565b602060405180830381865afa1580156107d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f791906125f3565b9250505090565b60008061080961144d565b60405161190160f01b60208201526022810182905260428101879052909150600090606201604051602081830303815290604052805190602001209050600061085533838989896114d0565b905060008060006108658461164b565b925092509250428365ffffffffffff161115801561088b5750428265ffffffffffff1610155b801561089e57506001600160a01b038116155b156108b95750630b135d3f60e11b95506108d0945050505050565b506001600160e01b031995506108d0945050505050565b9392505050565b336001600160a01b037f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d278916148015906109105750333014155b1561092e57604051637046c88d60e01b815260040160405180910390fd5b60405180608001604052808465ffffffffffff1681526020018565ffffffffffff168152602001876001600160a01b03168152602001866001600160a01b0316815250610986600080516020612a0183398151915290565b6001600160e01b031989166000908152600291909101602090815260409182902083518154928501518585015165ffffffffffff9283166001600160601b031990951694909417600160301b9290911691909102176bffffffffffffffffffffffff16600160601b6001600160a01b0393841602178155606090930151600190930180546001600160a01b031916938216939093179092555163064acaab60e11b815290861690630c95955690610a439085908590600401612615565b600060405180830381600087803b158015610a5d57600080fd5b505af1158015610a71573d6000803e3d6000fd5b50506040516001600160a01b038089169350891691506001600160e01b03198a16907fed03d2572564284398470d3f266a693e29ddfff3eba45fc06c5e91013d32135390600090a450505050505050565b6000610ad133858686866114d0565b949350505050565b336001600160a01b037f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27891614801590610b175750610b156106b8565b155b15610b3557604051637046c88d60e01b815260040160405180910390fd5b805160005b81811015610baf576000838281518110610b5657610b56612629565b6020026020010151905060008160000151905060008260200151905060008360400151905060008082516020840185875af1808015610b9a57600187019650610ba4565b3d6000803e3d6000fd5b505050505050610b3a565b505050565b336001600160a01b037f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27891614801590610bed5750333014155b15610c0b57604051637046c88d60e01b815260040160405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8190556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6000336001600160a01b037f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27891614610cb157604051636b31ba1560e11b815260040160405180910390fd5b6024600480356101448101358101838101939083013592910190600090610cda9082858761263f565b610ce391612669565b90506001600160e01b03198116600003610d1d578515610d07573434343489335af1505b610d1288888861167e565b9450505050506108d0565b600080516020612a218339815191525460e01b81811615610d465763fc2f51c56000526004601cfd5b5060006001600160e01b03198216600160e01b03610e155760408301358301601f1981013560007f439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dda81610d9c600482868861263f565b610da591612669565b6001600160e01b0319168152602081019190915260400160002060018101546001600160a01b031694509050610dde876004818b61263f565b82549199509750600160301b810460a01b65ffffffffffff60a01b1660d09190911b6001600160d01b031916179850505050610e77565b6001600160e01b03198216600160e11b03610e695760408301358301601f19810135610e58610e4860046000848661263f565b610e5191612669565b8888611776565b919a50985096509250610e77915050565b6001955050505050506108d0565b8615610e8757343434348a335af1505b6000610e928a612697565b905085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505050610140820152604051633a871cdd60e01b8152610f4e9088906001600160a01b03851690633a871cdd90610f069086908f908f906004016127a5565b6020604051808303816000875af1158015610f25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f499190612897565b611adf565b9a9950505050505050505050565b604051631aab3f0d60e11b81523060048201526001600160c01b03821660248201526000907f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27896001600160a01b0316906335567e1a90604401602060405180830381865afa158015610fd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff69190612897565b92915050565b336001600160a01b037f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d278916148015906110355750333014155b801561104657506110446106b8565b155b1561106457604051637046c88d60e01b815260040160405180910390fd5b6000816001811115611078576110786128b0565b14611096576040516367ce775960e01b815260040160405180910390fd5b60008083516020850186885af13d6000803e80801561025a573d6000f35b336001600160a01b037f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d278916148015906110ed5750333014155b1561110b57604051637046c88d60e01b815260040160405180910390fd5b600080516020612a2183398151915280546001600160a01b03858116600160501b818102600160501b600160f01b031985161790945560405193909204169182907fa35f5cdc5fbabb614b4cd5064ce5543f43dc8fab0e4da41255230eb8aba2531c90600090a360405163064acaab60e11b81526001600160a01b03851690630c959556906111a09086908690600401612615565b600060405180830381600087803b1580156111ba57600080fd5b505af11580156111ce573d6000803e3d6000fd5b5050505050505050565b600f60f81b60608060008080836111ed611b9d565b97989097965046955030945091925090565b336001600160a01b037f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d278916148015906112385750333014155b801561124957506112476106b8565b155b1561126757604051637046c88d60e01b815260040160405180910390fd5b600080825160208401855af43d6000803e80801561025a573d6000f35b604051631aab3f0d60e11b8152306004820152600060248201819052907f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27896001600160a01b0316906335567e1a90604401602060405180830381865afa1580156112f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113169190612897565b905090565b610baf838383611bd9565b336001600160a01b037f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789161480159061135f5750333014155b1561137d57604051637046c88d60e01b815260040160405180910390fd5b600080516020612a21833981519152805460e09290921c69ffffffffffffffffffff19909216919091176401000000004265ffffffffffff1602179055565b600080516020612a2183398151915254604051639ea9bd5960e01b815260009160501c906001600160a01b03821690639ea9bd5990611403908890889088906004016125ce565b602060405180830381865afa158015611420573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144491906125f3565b95945050505050565b600080600061145a611b9d565b8151602092830120815191830191909120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818601528082019390935260608301919091524660808301523060a0808401919091528151808403909101815260c0909201905280519101209392505050565b600080600080516020612a218339815191525460501c9050600080826001600160a01b031663333daf9260e01b898888604051602401611512939291906128c6565b60408051601f19818403018152918152602080830180516001600160e01b03166001600160e01b03199095169490941790935251611554928b918e91016128e0565b60408051601f198184030181529082905261156e91612914565b600060405180830381855afa9150503d80600081146115a9576040519150601f19603f3d011682016040523d82523d6000602084013e6115ae565b606091505b50915091508161162a5760405162461bcd60e51b815260206004820152603860248201527f4b65726e656c3a3a5f76616c69646174655369676e61747572653a206661696c60448201527f656420746f2076616c6964617465207369676e61747572650000000000000000606482015260840160405180910390fd5b8080602001905181019061163e9190612897565b9998505050505050505050565b600060a082901c65ffffffffffff1682811560001981016116705765ffffffffffff92505b508360d01c92509193909250565b60008061168a85612697565b905061169a610140860186612930565b6116a891600490829061263f565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505050610140820152600080516020612a2183398151915254604051633a871cdd60e01b815260509190911c906001600160a01b03821690633a871cdd90611729908590899089906004016127a5565b6020604051808303816000875af1158015611748573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176c9190612897565b9695505050505050565b600080368161178960246010878961263f565b61179291612976565b60601c9350605860006117a8826038898b61263f565b6117b1916129a4565b828101929091508801816117ca60208501858b8d61263f565b6117d3916129a4565b60001c925060208401935060006118bd7f3ce406685c1b3551d706d85a68afdaa49ac4e07b451ad9b8ff8b58c3ee96417660001b8d8d8d60049060249261181c9392919061263f565b611825916129a4565b60001c8e8e60249060389261183c9392919061263f565b61184591612976565b60601c87876040516118589291906129c2565b6040519081900381206118a295949392916020019485526001600160e01b031993909316602085015260408401919091526001600160a01b03166060830152608082015260a00190565b60405160208183030381529060405280519060200120611c6d565b905061190d6118e13083848f8f8b908b8d01926118dc9392919061263f565b6114d0565b8c8c6004906024926118f59392919061263f565b6118fe916129a4565b6001600160a01b031916611adf565b97508385019450848b019650848a03955060405180608001604052808c8c600490600a9261193d9392919061263f565b611946916129d2565b60d01c65ffffffffffff1681526020018c8c600a9060109261196a9392919061263f565b611973916129d2565b60d01c65ffffffffffff1681526020018c8c6024906038926119979392919061263f565b6119a091612976565b60601c6001600160a01b031681526020018c8c6010906024926119c59392919061263f565b6119ce91612976565b60601c9052600080516020612a018339815191526001600160e01b03198e166000908152600291909101602090815260409182902083518154928501518585015165ffffffffffff9283166001600160601b031990951694909417600160301b9290911691909102176bffffffffffffffffffffffff16600160601b6001600160a01b0393841602178155606090930151600190930180546001600160a01b031916938216939093179092555163064acaab60e11b8152908a1690630c95955690611a9f9086908690600401612615565b600060405180830381600087803b158015611ab957600080fd5b505af1158015611acd573d6000803e3d6000fd5b50505050505050505093509350935093565b600081830160601b8260601b81148460601b8214176001600160a01b0384861816151760018114611b135760019250611b95565b6001600160d01b031980851690861681811881831102188686176001600160a01b031617935065ffffffffffff60a01b86169081611b585765ffffffffffff60a01b91505b5065ffffffffffff60a01b851680611b76575065ffffffffffff60a01b5b808218908211021880611b8f575065ffffffffffff60a01b5b92909217915b505092915050565b604080518082018252600681526512d95c9b995b60d21b602080830191909152825180840190935260058352640c0b8c8b8d60da1b9083015291565b600080516020612a218339815191525460501c6001600160a01b03811615611c135760405162dc149f60e41b815260040160405180910390fd5b600080516020612a218339815191528054600160501b600160f01b031916600160501b6001600160a01b0387169081029190911790915560405163064acaab60e11b8152630c959556906111a09086908690600401612615565b7ffbfed6646b979c9c720fcef5bc8de90666984c78fcce48057b7595d0ede6f6267f000000000000000000000000d3082872f8b06073a021b4602e022d5a070d7cfc30147f0000000000000000000000000000000000000000000000000000000000aa36a7461416611d605750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f32ba20807d2fff2dbb34e0bcfa82982565bef566d4c0c633dc57b700b81c342760208201527f9e7e907b5361ed55126e4f0e20b6f60c86b8b85222f1c3d6d1972657674943699181019190915246606082015230608082015260a090205b67190100000000000060005280601a5281603a52604260182090506000603a52919050565b60005b83811015611da0578181015183820152602001611d88565b50506000910152565b60008151808452611dc1816020860160208601611d85565b601f01601f19169290920160200192915050565b6020815260006108d06020830184611da9565b6001600160a01b0381168114611dfd57600080fd5b50565b8035611e0b81611de8565b919050565b60008083601f840112611e2257600080fd5b5081356001600160401b03811115611e3957600080fd5b602083019150836020828501011115611e5157600080fd5b9250929050565b600080600080600060808688031215611e7057600080fd5b8535611e7b81611de8565b94506020860135611e8b81611de8565b93506040860135925060608601356001600160401b03811115611ead57600080fd5b611eb988828901611e10565b969995985093965092949392505050565b600080600060408486031215611edf57600080fd5b8335925060208401356001600160401b03811115611efc57600080fd5b611f0886828701611e10565b9497909650939450505050565b80356001600160e01b031981168114611e0b57600080fd5b65ffffffffffff81168114611dfd57600080fd5b600080600080600080600060c0888a031215611f5c57600080fd5b611f6588611f15565b96506020880135611f7581611de8565b95506040880135611f8581611de8565b94506060880135611f9581611f2d565b93506080880135611fa581611f2d565b925060a08801356001600160401b03811115611fc057600080fd5b611fcc8a828b01611e10565b989b979a50959850939692959293505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561201757612017611fdf565b60405290565b60405161016081016001600160401b038111828210171561201757612017611fdf565b604051601f8201601f191681016001600160401b038111828210171561206857612068611fdf565b604052919050565b600082601f83011261208157600080fd5b81356001600160401b0381111561209a5761209a611fdf565b6120ad601f8201601f1916602001612040565b8181528460208386010111156120c257600080fd5b816020850160208301376000918101602001919091529392505050565b600060208083850312156120f257600080fd5b82356001600160401b038082111561210957600080fd5b818501915085601f83011261211d57600080fd5b81358181111561212f5761212f611fdf565b8060051b61213e858201612040565b918252838101850191858101908984111561215857600080fd5b86860192505b8383101561163e578235858111156121765760008081fd5b86016060818c03601f190181131561218e5760008081fd5b612196611ff5565b898301356121a381611de8565b81526040838101358b8301529183013591888311156121c25760008081fd5b6121d08e8c85870101612070565b9082015284525050918601919086019061215e565b6000602082840312156121f757600080fd5b81356108d081611de8565b60008060006060848603121561221757600080fd5b83356001600160401b0381111561222d57600080fd5b8401610160818703121561224057600080fd5b95602085013595506040909401359392505050565b60006020828403121561226757600080fd5b81356001600160c01b03811681146108d057600080fd5b60006020828403121561229057600080fd5b6108d082611f15565b600080600080608085870312156122af57600080fd5b84356122ba81611de8565b93506020850135925060408501356001600160401b038111156122dc57600080fd5b6122e887828801612070565b9250506060850135600281106122fd57600080fd5b939692955090935050565b60008060006040848603121561231d57600080fd5b833561232881611de8565b925060208401356001600160401b03811115611efc57600080fd5b60ff60f81b881681526000602060e08184015261236360e084018a611da9565b8381036040850152612375818a611da9565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b818110156123c7578351835292840192918401916001016123ab565b50909c9b505050505050505050505050565b600080604083850312156123ec57600080fd5b82356123f781611de8565b915060208301356001600160401b0381111561241257600080fd5b61241e85828601612070565b9150509250929050565b60008083601f84011261243a57600080fd5b5081356001600160401b0381111561245157600080fd5b6020830191508360208260051b8501011115611e5157600080fd5b60008060008060008060008060a0898b03121561248857600080fd5b883561249381611de8565b975060208901356124a381611de8565b965060408901356001600160401b03808211156124bf57600080fd5b6124cb8c838d01612428565b909850965060608b01359150808211156124e457600080fd5b6124f08c838d01612428565b909650945060808b013591508082111561250957600080fd5b506125168b828c01611e10565b999c989b5096995094979396929594505050565b60008060008060008060a0878903121561254357600080fd5b863561254e81611de8565b9550602087013561255e81611de8565b9450604087013593506060870135925060808701356001600160401b0381111561258757600080fd5b61259389828a01611e10565b979a9699509497509295939492505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b038416815260406020820181905260009061144490830184866125a5565b60006020828403121561260557600080fd5b815180151581146108d057600080fd5b602081526000610ad16020830184866125a5565b634e487b7160e01b600052603260045260246000fd5b6000808585111561264f57600080fd5b8386111561265c57600080fd5b5050820193919092039150565b6001600160e01b03198135818116916004851015611b955760049490940360031b84901b1690921692915050565b600061016082360312156126aa57600080fd5b6126b261201d565b6126bb83611e00565b81526020830135602082015260408301356001600160401b03808211156126e157600080fd5b6126ed36838701612070565b6040840152606085013591508082111561270657600080fd5b61271236838701612070565b60608401526080850135608084015260a085013560a084015260c085013560c084015260e085013560e0840152610100915081850135828401526101209150818501358181111561276257600080fd5b61276e36828801612070565b83850152506101409150818501358181111561278957600080fd5b61279536828801612070565b8385015250505080915050919050565b606081526127bf6060820185516001600160a01b03169052565b60208401516080820152600060408501516101608060a08501526127e76101c0850183611da9565b91506060870151605f19808685030160c08701526128058483611da9565b9350608089015160e087015260a08901519150610100828188015260c08a01519250610120838189015260e08b0151935061014084818a0152828c0151868a0152818c0151955083898803016101808a01526128618787611da9565b9650808c0151955050505080868503016101a087015250506128838282611da9565b602085019690965250505060400152919050565b6000602082840312156128a957600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b8381526040602082015260006114446040830184866125a5565b600084516128f2818460208901611d85565b919091019283525060601b6001600160601b0319166020820152603401919050565b60008251612926818460208701611d85565b9190910192915050565b6000808335601e1984360301811261294757600080fd5b8301803591506001600160401b0382111561296157600080fd5b602001915036819003821315611e5157600080fd5b6001600160601b03198135818116916014851015611b955760149490940360031b84901b1690921692915050565b80356020831015610ff657600019602084900360031b1b1692915050565b8183823760009101908152919050565b6001600160d01b03198135818116916006851015611b955760069490940360031b84901b169092169291505056fe439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd8439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd9
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.