Overview
POL Balance
0 POL
POL Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
46741755 | 476 days ago | Contract Creation | 0 POL |
Loading...
Loading
Contract Name:
MultiECDSAValidatorNew
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "solady/utils/ECDSA.sol"; import "src/utils/KernelHelper.sol"; import "src/interfaces/IAddressBook.sol"; import "src/interfaces/IValidator.sol"; import "src/common/Types.sol"; contract MultiECDSAValidatorNew is IKernelValidator { event OwnerAdded(address indexed kernel, address indexed owner); event OwnerRemoved(address indexed kernel, address indexed owner); mapping(address owner => mapping(address kernel => bool) hello) public isOwner; function disable(bytes calldata _data) external payable override { address[] memory owners = abi.decode(_data, (address[])); for (uint256 i = 0; i < owners.length; i++) { isOwner[owners[i]][msg.sender] = false; emit OwnerRemoved(msg.sender, owners[i]); } } function enable(bytes calldata _data) external payable override { address addressBook = address(bytes20(_data)); address[] memory owners = IAddressBook(addressBook).getOwners(); for (uint256 i = 0; i < owners.length; i++) { isOwner[owners[i]][msg.sender] = true; emit OwnerAdded(msg.sender, owners[i]); } } function validateUserOp( UserOperation calldata _userOp, bytes32 _userOpHash, uint256 ) external payable override returns (ValidationData validationData) { address signer = ECDSA.recover(_userOpHash, _userOp.signature); if (isOwner[signer][msg.sender]) { return ValidationData.wrap(0); } bytes32 hash = ECDSA.toEthSignedMessageHash(_userOpHash); signer = ECDSA.recover(hash, _userOp.signature); if (!isOwner[signer][msg.sender]) { return SIG_VALIDATION_FAILED; } return ValidationData.wrap(0); } function validateSignature( bytes32 hash, bytes calldata signature ) public view override returns (ValidationData) { bytes32 wrappedHash = keccak256(abi.encodePacked(hash, msg.sender)); address signer = ECDSA.recover(wrappedHash, signature); if (isOwner[signer][msg.sender]) { return ValidationData.wrap(0); } bytes32 ethHash = ECDSA.toEthSignedMessageHash(wrappedHash); signer = ECDSA.recover(ethHash, signature); if (!isOwner[signer][msg.sender]) { return SIG_VALIDATION_FAILED; } return ValidationData.wrap(0); } function validCaller( address _caller, bytes calldata ) external view override returns (bool) { return isOwner[_caller][msg.sender]; } }
// 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) library ECDSA { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The signature is invalid. error InvalidSignature(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The number which `s` must not exceed in order for /// the signature to be non-malleable. bytes32 private constant _MALLEABILITY_THRESHOLD = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* RECOVERY OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // Note: as of Solady version 0.0.68, these functions will // revert upon recovery failure for more safety by default. /// @dev Recovers the signer's address from a message digest `hash`, /// and the `signature`. /// /// This function does NOT accept EIP-2098 short form signatures. /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098 /// short form signatures instead. function recover(bytes32 hash, bytes memory signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { // Copy the free memory pointer so that we can restore it later. let m := mload(0x40) // Copy `r` and `s`. mstore(0x40, mload(add(signature, 0x20))) // `r`. let s := mload(add(signature, 0x40)) mstore(0x60, s) // Store the `hash` in the scratch space. mstore(0x00, hash) // Compute `v` and store it in the scratch space. mstore(0x20, byte(0, mload(add(signature, 0x60)))) pop( staticcall( gas(), // Amount of gas left for the transaction. and( // If the signature is exactly 65 bytes in length. eq(mload(signature), 65), // If `s` in lower half order, such that the signature is not malleable. lt(s, add(_MALLEABILITY_THRESHOLD, 1)) ), // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x00, // Start of output. 0x20 // Size of output. ) ) result := mload(0x00) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { // Store the function selector of `InvalidSignature()`. mstore(0x00, 0x8baa579f) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the zero slot. mstore(0x60, 0) // Restore the free memory pointer. mstore(0x40, m) } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the `signature`. /// /// This function does NOT accept EIP-2098 short form signatures. /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098 /// short form signatures instead. function recoverCalldata(bytes32 hash, bytes calldata signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { // Copy the free memory pointer so that we can restore it later. let m := mload(0x40) // Directly copy `r` and `s` from the calldata. calldatacopy(0x40, signature.offset, 0x40) // Store the `hash` in the scratch space. mstore(0x00, hash) // Compute `v` and store it in the scratch space. mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) pop( staticcall( gas(), // Amount of gas left for the transaction. and( // If the signature is exactly 65 bytes in length. eq(signature.length, 65), // If `s` in lower half order, such that the signature is not malleable. lt(mload(0x60), add(_MALLEABILITY_THRESHOLD, 1)) ), // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x00, // Start of output. 0x20 // Size of output. ) ) result := mload(0x00) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { // Store the function selector of `InvalidSignature()`. mstore(0x00, 0x8baa579f) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the zero slot. mstore(0x60, 0) // Restore the free memory pointer. mstore(0x40, m) } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the EIP-2098 short form signature defined by `r` and `vs`. /// /// This function only accepts EIP-2098 short form signatures. /// See: https://eips.ethereum.org/EIPS/eip-2098 /// /// To be honest, I do not recommend using EIP-2098 signatures /// for simplicity, performance, and security reasons. Most if not /// all clients support traditional non EIP-2098 signatures by default. /// As such, this method is intentionally not fully inlined. /// It is merely included for completeness. function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) { uint8 v; bytes32 s; /// @solidity memory-safe-assembly assembly { s := shr(1, shl(1, vs)) v := add(shr(255, vs), 27) } result = recover(hash, v, r, s); } /// @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 { // Copy the free memory pointer so that we can restore it later. let m := mload(0x40) mstore(0x00, hash) mstore(0x20, and(v, 0xff)) mstore(0x40, r) mstore(0x60, s) pop( staticcall( gas(), // Amount of gas left for the transaction. // If `s` in lower half order, such that the signature is not malleable. lt(s, add(_MALLEABILITY_THRESHOLD, 1)), // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x00, // Start of output. 0x20 // Size of output. ) ) result := mload(0x00) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { // Store the function selector of `InvalidSignature()`. mstore(0x00, 0x8baa579f) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the zero slot. mstore(0x60, 0) // Restore the free memory pointer. mstore(0x40, m) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* 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`. /// /// This function does NOT accept EIP-2098 short form signatures. /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098 /// short form signatures instead. function tryRecover(bytes32 hash, bytes memory signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { if iszero(xor(mload(signature), 65)) { // Copy the free memory pointer so that we can restore it later. let m := mload(0x40) // Copy `r` and `s`. mstore(0x40, mload(add(signature, 0x20))) // `r`. let s := mload(add(signature, 0x40)) mstore(0x60, s) // If `s` in lower half order, such that the signature is not malleable. if iszero(gt(s, _MALLEABILITY_THRESHOLD)) { // Store the `hash` in the scratch space. mstore(0x00, hash) // Compute `v` and store it in the scratch space. mstore(0x20, byte(0, mload(add(signature, 0x60)))) pop( staticcall( gas(), // Amount of gas left for the transaction. 0x01, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) // Restore the zero slot. mstore(0x60, 0) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) } // Restore the free memory pointer. mstore(0x40, m) } } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the `signature`. /// /// This function does NOT accept EIP-2098 short form signatures. /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098 /// short form signatures instead. function tryRecoverCalldata(bytes32 hash, bytes calldata signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { if iszero(xor(signature.length, 65)) { // Copy the free memory pointer so that we can restore it later. let m := mload(0x40) // Directly copy `r` and `s` from the calldata. calldatacopy(0x40, signature.offset, 0x40) // If `s` in lower half order, such that the signature is not malleable. if iszero(gt(mload(0x60), _MALLEABILITY_THRESHOLD)) { // Store the `hash` in the scratch space. mstore(0x00, hash) // Compute `v` and store it in the scratch space. mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) pop( staticcall( gas(), // Amount of gas left for the transaction. 0x01, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) // Restore the zero slot. mstore(0x60, 0) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) } // Restore the free memory pointer. mstore(0x40, m) } } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the EIP-2098 short form signature defined by `r` and `vs`. /// /// This function only accepts EIP-2098 short form signatures. /// See: https://eips.ethereum.org/EIPS/eip-2098 /// /// To be honest, I do not recommend using EIP-2098 signatures /// for simplicity, performance, and security reasons. Most if not /// all clients support traditional non EIP-2098 signatures by default. /// As such, this method is intentionally not fully inlined. /// It is merely included for completeness. function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) { uint8 v; bytes32 s; /// @solidity memory-safe-assembly assembly { s := shr(1, shl(1, vs)) v := add(shr(255, vs), 27) } result = tryRecover(hash, v, r, s); } /// @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 { // Copy the free memory pointer so that we can restore it later. let m := mload(0x40) // If `s` in lower half order, such that the signature is not malleable. if iszero(gt(s, _MALLEABILITY_THRESHOLD)) { // Store the `hash`, `v`, `r`, `s` in the scratch space. mstore(0x00, hash) mstore(0x20, and(v, 0xff)) mstore(0x40, r) mstore(0x60, s) pop( staticcall( gas(), // Amount of gas left for the transaction. 0x01, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) // Restore the zero slot. mstore(0x60, 0) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) } // Restore the free memory pointer. mstore(0x40, m) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* 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 { // Store into scratch space for keccak256. mstore(0x20, hash) mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 0x40 - 0x04 = 0x3c result := keccak256(0x04, 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. function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) { assembly { // The length of "\x19Ethereum Signed Message:\n" is 26 bytes (i.e. 0x1a). // If we reserve 2 words, we'll have 64 - 26 = 38 bytes to store the // ASCII decimal representation of the length of `s` up to about 2 ** 126. // Instead of allocating, we temporarily copy the 64 bytes before the // start of `s` data to some variables. let m := mload(sub(s, 0x20)) // The length of `s` is in bytes. let sLength := mload(s) let ptr := add(s, 0x20) let w := not(0) // `end` marks the end of the memory which we will compute the keccak256 of. let end := add(ptr, sLength) // Convert the length of the bytes to ASCII decimal representation // and store it into the memory. for { let temp := sLength } 1 {} { ptr := add(ptr, w) // `sub(ptr, 1)`. mstore8(ptr, add(48, mod(temp, 10))) temp := div(temp, 10) if iszero(temp) { break } } // Copy the header over to the memory. mstore(sub(ptr, 0x20), "\x00\x00\x00\x00\x00\x00\x19Ethereum Signed Message:\n") // Compute the keccak256 of the memory. result := keccak256(sub(ptr, 0x1a), sub(end, sub(ptr, 0x1a))) // Restore the previous memory. mstore(s, sLength) mstore(sub(s, 0x20), m) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* 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 } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {SIG_VALIDATION_FAILED_UINT} from "src/common/Constants.sol"; import {ValidationData} from "src/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 switch iszero(and(xor(a, b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff)) case 1 { // validAfter let a_vd := and(0xffffffffffff000000000000ffffffffffffffffffffffffffffffffffffffff, a) let b_vd := and(0xffffffffffff000000000000ffffffffffffffffffffffffffffffffffffffff, b) validationData := xor(a_vd, mul(xor(a_vd, b_vd), gt(b_vd, a_vd))) // validUntil a_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, a) b_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, b) 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.18; interface IAddressBook { function getOwners() external view returns (address[] memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {UserOperation} from "account-abstraction/interfaces/UserOperation.sol"; import "src/common/Types.sol"; interface IKernelValidator { 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.9; import "src/common/Constants.sol"; type ValidAfter is uint48; type ValidUntil is uint48; type ValidationData is uint256; ValidationData constant SIG_VALIDATION_FAILED = ValidationData.wrap(SIG_VALIDATION_FAILED_UINT); function packValidationData(ValidAfter validAfter, ValidUntil validUntil) pure returns (ValidationData) { return ValidationData.wrap( uint256(ValidAfter.unwrap(validAfter)) << 208 | uint256(ValidUntil.unwrap(validUntil)) << 160 ); } 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) } }
pragma solidity ^0.8.0; // constants for kernel metadata string constant KERNEL_NAME = "Kernel"; string constant KERNEL_VERSION = "0.2.1"; // ERC4337 constants uint256 constant SIG_VALIDATION_FAILED_UINT = 1; // STRUCT_HASH bytes32 constant VALIDATOR_APPROVED_STRUCT_HASH = 0x3ce406685c1b3551d706d85a68afdaa49ac4e07b451ad9b8ff8b58c3ee964176; // Storage slots bytes32 constant KERNEL_STORAGE_SLOT = 0x439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd8; bytes32 constant KERNEL_STORAGE_SLOT_1 = 0x439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd9; bytes32 constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; /* solhint-disable no-inline-assembly */ import {calldataKeccak} from "../core/Helpers.sol"; /** * User Operation struct * @param sender the sender account of this request. * @param nonce unique value the sender uses to verify it is not a replay. * @param initCode if set, the account contract will be created by this constructor/ * @param callData the method call to execute on this account. * @param callGasLimit the gas limit passed to the callData method call. * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp. * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead. * @param maxFeePerGas same as EIP-1559 gas parameter. * @param maxPriorityFeePerGas same as EIP-1559 gas parameter. * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender. * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID. */ struct UserOperation { address sender; uint256 nonce; bytes initCode; bytes callData; uint256 callGasLimit; uint256 verificationGasLimit; uint256 preVerificationGas; uint256 maxFeePerGas; uint256 maxPriorityFeePerGas; bytes paymasterAndData; bytes signature; } /** * Utility functions helpful when working with UserOperation structs. */ library UserOperationLib { function getSender(UserOperation calldata userOp) internal pure returns (address) { address data; //read sender from userOp, which is first userOp member (saves 800 gas...) assembly {data := calldataload(userOp)} return address(uint160(data)); } //relayer/block builder might submit the TX with higher priorityFee, but the user should not // pay above what he signed for. function gasPrice(UserOperation calldata userOp) internal view returns (uint256) { unchecked { uint256 maxFeePerGas = userOp.maxFeePerGas; uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas; if (maxFeePerGas == maxPriorityFeePerGas) { //legacy mode (for networks that don't support basefee opcode) return maxFeePerGas; } return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee); } } function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) { address sender = getSender(userOp); uint256 nonce = userOp.nonce; bytes32 hashInitCode = calldataKeccak(userOp.initCode); bytes32 hashCallData = calldataKeccak(userOp.callData); uint256 callGasLimit = userOp.callGasLimit; uint256 verificationGasLimit = userOp.verificationGasLimit; uint256 preVerificationGas = userOp.preVerificationGas; uint256 maxFeePerGas = userOp.maxFeePerGas; uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas; bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData); return abi.encode( sender, nonce, hashInitCode, hashCallData, callGasLimit, verificationGasLimit, preVerificationGas, maxFeePerGas, maxPriorityFeePerGas, hashPaymasterAndData ); } function hash(UserOperation calldata userOp) internal pure returns (bytes32) { return keccak256(pack(userOp)); } function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; /* solhint-disable no-inline-assembly */ /** * returned data from validateUserOp. * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData` * @param aggregator - address(0) - the account validated the signature by itself. * address(1) - the account failed to validate the signature. * otherwise - this is an address of a signature aggregator that must be used to validate the signature. * @param validAfter - this UserOp is valid only after this timestamp. * @param validaUntil - this UserOp is valid only up to this timestamp. */ struct ValidationData { address aggregator; uint48 validAfter; uint48 validUntil; } //extract sigFailed, validAfter, validUntil. // also convert zero validUntil to type(uint48).max function _parseValidationData(uint validationData) pure returns (ValidationData memory data) { address aggregator = address(uint160(validationData)); uint48 validUntil = uint48(validationData >> 160); if (validUntil == 0) { validUntil = type(uint48).max; } uint48 validAfter = uint48(validationData >> (48 + 160)); return ValidationData(aggregator, validAfter, validUntil); } // intersect account and paymaster ranges. function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) { ValidationData memory accountValidationData = _parseValidationData(validationData); ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData); address aggregator = accountValidationData.aggregator; if (aggregator == address(0)) { aggregator = pmValidationData.aggregator; } uint48 validAfter = accountValidationData.validAfter; uint48 validUntil = accountValidationData.validUntil; uint48 pmValidAfter = pmValidationData.validAfter; uint48 pmValidUntil = pmValidationData.validUntil; if (validAfter < pmValidAfter) validAfter = pmValidAfter; if (validUntil > pmValidUntil) validUntil = pmValidUntil; return ValidationData(aggregator, validAfter, validUntil); } /** * helper to pack the return value for validateUserOp * @param data - the ValidationData to pack */ function _packValidationData(ValidationData memory data) pure returns (uint256) { return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48)); } /** * helper to pack the return value for validateUserOp, when not using an aggregator * @param sigFailed - true for signature failure, false for success * @param validUntil last timestamp this UserOperation is valid (or zero for infinite) * @param validAfter first timestamp this UserOperation is valid */ function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) { return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48)); } /** * keccak function over calldata. * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it. */ function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) { assembly { let mem := mload(0x40) let len := data.length calldatacopy(mem, data.offset, len) ret := keccak256(mem, len) } }
{ "remappings": [ "account-abstraction/=lib/account-abstraction/contracts/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "@openzeppelin/=lib/openzeppelin-contracts/", "solady/=lib/solady/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none", "appendCBOR": false }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"kernel","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"OwnerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"kernel","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"OwnerRemoved","type":"event"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"disable","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"enable","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"kernel","type":"address"}],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_caller","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"validCaller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":"","type":"uint256"}],"name":"validateUserOp","outputs":[{"internalType":"ValidationData","name":"validationData","type":"uint256"}],"stateMutability":"payable","type":"function"}]
Contract Creation Code
60808060405234610016576107f3908161001c8239f35b600080fdfe6080604081815260048036101561001557600080fd5b600092833560e01c9081630c959556146102e257508063333daf92146102a25780633a871cdd146102575780637ddc02d4146102035780638fc925aa146100d057639ea9bd591461006557600080fd5b346100cc57816003193601126100cc5761007d6104bb565b9060243567ffffffffffffffff81116100c8579360ff926100a48593602097369101610488565b50506001600160a01b03168152808552818120338252855220549151911615158152f35b8480fd5b8280fd5b50916020806003193601126101ff5767ffffffffffffffff9380358581116101fb576100fe91369101610488565b819591019482818703126101fb5780359182116101fb57019380601f860112156100cc57843561012d81610509565b9561013a865197886104d1565b818752838088019260051b8201019283116100c8578301905b8282106101d857505050815b84518110156101d4576101cf906001600160a01b038061017f8389610546565b511685528484528585203386528452858520805460ff191690556101a38288610546565b5116337fe594d081b4382713733fe631966432c9cea5199afb2db5c3c1931f9f930036798680a3610521565b61015f565b8280f35b81356001600160a01b03811681036101f7578152908301908301610153565b8580fd5b8380fd5b5080fd5b5050346101ff57806003193601126101ff5761021d6104bb565b6001600160a01b0360243581811692908390036100c8579360ff928492602096168252818652828220908252855220541690519015158152f35b50916003199060603683011261029f5783359167ffffffffffffffff83116101ff5761016090833603011261029f57506020926102989160243591016105ea565b9051908152f35b80fd5b50913461029f578160031936011261029f576024359067ffffffffffffffff821161029f57506020926102db6102989236908301610488565b9135610725565b83858492602090816003193601126100cc5767ffffffffffffffff9480358681116100c857849183610318819336908401610488565b6bffffffffffffffffffffffff1991358281169160148110610473575b505063a0e67e2b60e01b835260601c90505afa9485156104695783956103d2575b5050815b84518110156101d4576103cd906001600160a01b038061037a8389610546565b511685528484528585203386528452858520805460ff191660011790556103a18288610546565b5116337fc82bdbbf677a2462f2a7e22e4ba9abd209496b69cd7b868b3b1d28f76e09a40a8680a3610521565b61035a565b909194503d8084843e6103e581846104d1565b82019185818403126101fb5780519182116101fb57019080601f830112156100cc57815161041281610509565b9261041f865194856104d1565b818452868085019260051b8201019283116100c8578601905b82821061044a57505050928480610356565b81516001600160a01b03811681036101f7578152908601908601610438565b84513d85823e3d90fd5b8391925060140360031b1b1616808b80610335565b9181601f840112156104b65782359167ffffffffffffffff83116104b657602083818601950101116104b657565b600080fd5b600435906001600160a01b03821682036104b657565b90601f8019910116810190811067ffffffffffffffff8211176104f357604052565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff81116104f35760051b60200190565b60001981146105305760010190565b634e487b7160e01b600052601160045260246000fd5b805182101561055a5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b903590601e19813603018212156104b6570180359067ffffffffffffffff82116104b6576020019181360383136104b657565b92919267ffffffffffffffff82116104f357604051916105cd601f8201601f1916602001846104d1565b8294818452818301116104b6578281602093846000960137010152565b6101408101916105fa8383610570565b6001600160a01b039391849161061b916106159136916105a3565b846106af565b16936000948552846020526040852033865260205260ff6040862054166106a85761067461067b91610681946020527b19457468657265756d205369676e6564204d6573736167653a0a33328752603c60042093610570565b36916105a3565b906106af565b168152806020526040812033825260205260ff604082205416156106a25790565b50600190565b5050505090565b60207f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a19392608060405193838301516040526040830151928360605260416000988995869485526060840151851a885210915114165afa508251923d1561071857606052604052565b638baa579f90526004601cfd5b6040908151906020918281019182523360601b84820152603481526060810181811067ffffffffffffffff8211176104f3578452519020926001600160a01b03908161077b6107753689856105a3565b876106af565b16956000968752868452848720338852845260ff85882054166107ea5761067b6107d09260ff9786527b19457468657265756d205369676e6564204d6573736167653a0a33328952603c6004209236916105a3565b168452838152818420903385525282205416156106a25790565b5050505050509056
Deployed Bytecode
0x6080604081815260048036101561001557600080fd5b600092833560e01c9081630c959556146102e257508063333daf92146102a25780633a871cdd146102575780637ddc02d4146102035780638fc925aa146100d057639ea9bd591461006557600080fd5b346100cc57816003193601126100cc5761007d6104bb565b9060243567ffffffffffffffff81116100c8579360ff926100a48593602097369101610488565b50506001600160a01b03168152808552818120338252855220549151911615158152f35b8480fd5b8280fd5b50916020806003193601126101ff5767ffffffffffffffff9380358581116101fb576100fe91369101610488565b819591019482818703126101fb5780359182116101fb57019380601f860112156100cc57843561012d81610509565b9561013a865197886104d1565b818752838088019260051b8201019283116100c8578301905b8282106101d857505050815b84518110156101d4576101cf906001600160a01b038061017f8389610546565b511685528484528585203386528452858520805460ff191690556101a38288610546565b5116337fe594d081b4382713733fe631966432c9cea5199afb2db5c3c1931f9f930036798680a3610521565b61015f565b8280f35b81356001600160a01b03811681036101f7578152908301908301610153565b8580fd5b8380fd5b5080fd5b5050346101ff57806003193601126101ff5761021d6104bb565b6001600160a01b0360243581811692908390036100c8579360ff928492602096168252818652828220908252855220541690519015158152f35b50916003199060603683011261029f5783359167ffffffffffffffff83116101ff5761016090833603011261029f57506020926102989160243591016105ea565b9051908152f35b80fd5b50913461029f578160031936011261029f576024359067ffffffffffffffff821161029f57506020926102db6102989236908301610488565b9135610725565b83858492602090816003193601126100cc5767ffffffffffffffff9480358681116100c857849183610318819336908401610488565b6bffffffffffffffffffffffff1991358281169160148110610473575b505063a0e67e2b60e01b835260601c90505afa9485156104695783956103d2575b5050815b84518110156101d4576103cd906001600160a01b038061037a8389610546565b511685528484528585203386528452858520805460ff191660011790556103a18288610546565b5116337fc82bdbbf677a2462f2a7e22e4ba9abd209496b69cd7b868b3b1d28f76e09a40a8680a3610521565b61035a565b909194503d8084843e6103e581846104d1565b82019185818403126101fb5780519182116101fb57019080601f830112156100cc57815161041281610509565b9261041f865194856104d1565b818452868085019260051b8201019283116100c8578601905b82821061044a57505050928480610356565b81516001600160a01b03811681036101f7578152908601908601610438565b84513d85823e3d90fd5b8391925060140360031b1b1616808b80610335565b9181601f840112156104b65782359167ffffffffffffffff83116104b657602083818601950101116104b657565b600080fd5b600435906001600160a01b03821682036104b657565b90601f8019910116810190811067ffffffffffffffff8211176104f357604052565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff81116104f35760051b60200190565b60001981146105305760010190565b634e487b7160e01b600052601160045260246000fd5b805182101561055a5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b903590601e19813603018212156104b6570180359067ffffffffffffffff82116104b6576020019181360383136104b657565b92919267ffffffffffffffff82116104f357604051916105cd601f8201601f1916602001846104d1565b8294818452818301116104b6578281602093846000960137010152565b6101408101916105fa8383610570565b6001600160a01b039391849161061b916106159136916105a3565b846106af565b16936000948552846020526040852033865260205260ff6040862054166106a85761067461067b91610681946020527b19457468657265756d205369676e6564204d6573736167653a0a33328752603c60042093610570565b36916105a3565b906106af565b168152806020526040812033825260205260ff604082205416156106a25790565b50600190565b5050505090565b60207f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a19392608060405193838301516040526040830151928360605260416000988995869485526060840151851a885210915114165afa508251923d1561071857606052604052565b638baa579f90526004601cfd5b6040908151906020918281019182523360601b84820152603481526060810181811067ffffffffffffffff8211176104f3578452519020926001600160a01b03908161077b6107753689856105a3565b876106af565b16956000968752868452848720338852845260ff85882054166107ea5761067b6107d09260ff9786527b19457468657265756d205369676e6564204d6573736167653a0a33328952603c6004209236916105a3565b168452838152818420903385525282205416156106a25790565b5050505050509056
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.