Overview
ETH Balance
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
17435864 | 26 days ago | 0 ETH | ||||
17427191 | 26 days ago | 0 ETH | ||||
17417117 | 27 days ago | 0 ETH | ||||
17411994 | 27 days ago | 0 ETH | ||||
17394760 | 27 days ago | 0 ETH | ||||
17392234 | 27 days ago | 0 ETH | ||||
17385410 | 27 days ago | 0 ETH | ||||
17373351 | 28 days ago | 0 ETH | ||||
17370530 | 28 days ago | 0 ETH | ||||
17361255 | 28 days ago | 0 ETH | ||||
17360278 | 28 days ago | 0 ETH | ||||
17356369 | 28 days ago | 0 ETH | ||||
17355607 | 28 days ago | 0 ETH | ||||
17353276 | 28 days ago | 0 ETH | ||||
17350014 | 28 days ago | 0 ETH | ||||
17348829 | 28 days ago | 0 ETH | ||||
17346820 | 28 days ago | 0 ETH | ||||
17346805 | 28 days ago | 0 ETH | ||||
17346497 | 28 days ago | 0 ETH | ||||
17346436 | 28 days ago | 0 ETH | ||||
17346328 | 28 days ago | 0 ETH | ||||
17345698 | 28 days ago | 0 ETH | ||||
17345455 | 28 days ago | 0 ETH | ||||
17344951 | 28 days ago | 0 ETH | ||||
17342619 | 29 days ago | 0 ETH |
Loading...
Loading
Contract Name:
SessionKeyManager
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 800 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {BaseAuthorizationModule, UserOperation} from "./BaseAuthorizationModule.sol"; import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; import "@account-abstraction/contracts/core/Helpers.sol"; import "./SessionValidationModules/ISessionValidationModule.sol"; import {ISessionKeyManager} from "../interfaces/ISessionKeyManager.sol"; struct SessionStorage { bytes32 merkleRoot; } /** * @title Session Key Manager module for Biconomy Modular Smart Accounts. * @dev Performs basic verifications for every session key signed userOp. * Checks if the session key has been enabled, that it is not due and has not yet expired * Then passes the validation flow to appropriate Session Validation module * - For the sake of efficiency and flexibility, doesn't limit what operations * Session Validation modules can perform * - Should be used with carefully verified and audited Session Validation Modules only * - Compatible with Biconomy Modular Interface v 0.1 * @author Fil Makarov - <[email protected]> */ contract SessionKeyManager is BaseAuthorizationModule, ISessionKeyManager { /** * @dev mapping of Smart Account to a SessionStorage * Info about session keys is stored as root of the merkle tree built over the session keys */ mapping(address => SessionStorage) internal _userSessions; /** * @dev sets the merkle root of a tree containing session keys for msg.sender * should be called by Smart Account * @param _merkleRoot Merkle Root of a tree that contains session keys with their permissions and parameters */ function setMerkleRoot(bytes32 _merkleRoot) external { _userSessions[msg.sender].merkleRoot = _merkleRoot; // TODO:should we add an event here? which emits the new merkle root } /** * @dev validates userOperation * @param userOp User Operation to be validated. * @param userOpHash Hash of the User Operation to be validated. * @return sigValidationResult 0 if signature is valid, SIG_VALIDATION_FAILED otherwise. */ function validateUserOp( UserOperation calldata userOp, bytes32 userOpHash ) external virtual returns (uint256) { (bytes memory moduleSignature, ) = abi.decode( userOp.signature, (bytes, address) ); ( uint48 validUntil, uint48 validAfter, address sessionValidationModule, bytes memory sessionKeyData, bytes32[] memory merkleProof, bytes memory sessionKeySignature ) = abi.decode( moduleSignature, (uint48, uint48, address, bytes, bytes32[], bytes) ); validateSessionKey( userOp.sender, validUntil, validAfter, sessionValidationModule, sessionKeyData, merkleProof ); return _packValidationData( //_packValidationData expects true if sig validation has failed, false otherwise !ISessionValidationModule(sessionValidationModule) .validateSessionUserOp( userOp, userOpHash, sessionKeyData, sessionKeySignature ), validUntil, validAfter ); } /** * @dev returns the SessionStorage object for a given smartAccount * @param smartAccount Smart Account address */ function getSessionKeys( address smartAccount ) external view returns (SessionStorage memory) { return _userSessions[smartAccount]; } /** * @dev validates that Session Key + parameters are enabled * by being included into the merkle tree * @param smartAccount smartAccount for which session key is being validated * @param validUntil timestamp when the session key expires * @param validAfter timestamp when the session key becomes valid * @param sessionValidationModule address of the Session Validation Module * @param sessionKeyData session parameters (limitations/permissions) * @param merkleProof merkle proof for the leaf which represents this session key + params * @dev if doesn't revert, session key is considered valid */ function validateSessionKey( address smartAccount, uint48 validUntil, uint48 validAfter, address sessionValidationModule, bytes memory sessionKeyData, bytes32[] memory merkleProof ) public virtual override { SessionStorage storage sessionKeyStorage = _getSessionData( smartAccount ); bytes32 leaf = keccak256( abi.encodePacked( validUntil, validAfter, sessionValidationModule, sessionKeyData ) ); if ( !MerkleProof.verify(merkleProof, sessionKeyStorage.merkleRoot, leaf) ) { revert("SessionNotApproved"); } } /** * @dev isValidSignature according to BaseAuthorizationModule * @param _dataHash Hash of the data to be validated. * @param _signature Signature over the the _dataHash. * @return always returns 0xffffffff as signing messages is not supported by SessionKeys */ function isValidSignature( bytes32 _dataHash, bytes memory _signature ) public view override returns (bytes4) { (_dataHash, _signature); return 0xffffffff; // do not support it here } /** * @dev returns the SessionStorage object for a given smartAccount * @param _account Smart Account address * @return sessionKeyStorage SessionStorage object at storage */ function _getSessionData( address _account ) internal view returns (SessionStorage storage sessionKeyStorage) { sessionKeyStorage = _userSessions[_account]; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; /* solhint-disable no-inline-assembly */ /** * returned data from validateUserOp. * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData` * @param aggregator - address(0) - the account validated the signature by itself. * address(1) - the account failed to validate the signature. * otherwise - this is an address of a signature aggregator that must be used to validate the signature. * @param validAfter - this UserOp is valid only after this timestamp. * @param validaUntil - this UserOp is valid only up to this timestamp. */ struct ValidationData { address aggregator; uint48 validAfter; uint48 validUntil; } //extract sigFailed, validAfter, validUntil. // also convert zero validUntil to type(uint48).max function _parseValidationData(uint validationData) pure returns (ValidationData memory data) { address aggregator = address(uint160(validationData)); uint48 validUntil = uint48(validationData >> 160); if (validUntil == 0) { validUntil = type(uint48).max; } uint48 validAfter = uint48(validationData >> (48 + 160)); return ValidationData(aggregator, validAfter, validUntil); } // intersect account and paymaster ranges. function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) { ValidationData memory accountValidationData = _parseValidationData(validationData); ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData); address aggregator = accountValidationData.aggregator; if (aggregator == address(0)) { aggregator = pmValidationData.aggregator; } uint48 validAfter = accountValidationData.validAfter; uint48 validUntil = accountValidationData.validUntil; uint48 pmValidAfter = pmValidationData.validAfter; uint48 pmValidUntil = pmValidationData.validUntil; if (validAfter < pmValidAfter) validAfter = pmValidAfter; if (validUntil > pmValidUntil) validUntil = pmValidUntil; return ValidationData(aggregator, validAfter, validUntil); } /** * helper to pack the return value for validateUserOp * @param data - the ValidationData to pack */ function _packValidationData(ValidationData memory data) pure returns (uint256) { return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48)); } /** * helper to pack the return value for validateUserOp, when not using an aggregator * @param sigFailed - true for signature failure, false for success * @param validUntil last timestamp this UserOperation is valid (or zero for infinite) * @param validAfter first timestamp this UserOperation is valid */ function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) { return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48)); } /** * keccak function over calldata. * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it. */ function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) { assembly { let mem := mload(0x40) let len := data.length calldatacopy(mem, data.offset, len) ret := keccak256(mem, len) } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; /* solhint-disable no-inline-assembly */ import {calldataKeccak} from "../core/Helpers.sol"; /** * User Operation struct * @param sender the sender account of this request. * @param nonce unique value the sender uses to verify it is not a replay. * @param initCode if set, the account contract will be created by this constructor/ * @param callData the method call to execute on this account. * @param callGasLimit the gas limit passed to the callData method call. * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp. * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead. * @param maxFeePerGas same as EIP-1559 gas parameter. * @param maxPriorityFeePerGas same as EIP-1559 gas parameter. * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender. * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID. */ struct UserOperation { address sender; uint256 nonce; bytes initCode; bytes callData; uint256 callGasLimit; uint256 verificationGasLimit; uint256 preVerificationGas; uint256 maxFeePerGas; uint256 maxPriorityFeePerGas; bytes paymasterAndData; bytes signature; } /** * Utility functions helpful when working with UserOperation structs. */ library UserOperationLib { function getSender(UserOperation calldata userOp) internal pure returns (address) { address data; //read sender from userOp, which is first userOp member (saves 800 gas...) assembly {data := calldataload(userOp)} return address(uint160(data)); } //relayer/block builder might submit the TX with higher priorityFee, but the user should not // pay above what he signed for. function gasPrice(UserOperation calldata userOp) internal view returns (uint256) { unchecked { uint256 maxFeePerGas = userOp.maxFeePerGas; uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas; if (maxFeePerGas == maxPriorityFeePerGas) { //legacy mode (for networks that don't support basefee opcode) return maxFeePerGas; } return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee); } } function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) { address sender = getSender(userOp); uint256 nonce = userOp.nonce; bytes32 hashInitCode = calldataKeccak(userOp.initCode); bytes32 hashCallData = calldataKeccak(userOp.callData); uint256 callGasLimit = userOp.callGasLimit; uint256 verificationGasLimit = userOp.verificationGasLimit; uint256 preVerificationGas = userOp.preVerificationGas; uint256 maxFeePerGas = userOp.maxFeePerGas; uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas; bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData); return abi.encode( sender, nonce, hashInitCode, hashCallData, callGasLimit, verificationGasLimit, preVerificationGas, maxFeePerGas, maxPriorityFeePerGas, hashPaymasterAndData ); } function hash(UserOperation calldata userOp) internal pure returns (bytes32) { return keccak256(pack(userOp)); } function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.2) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The tree and the proofs can be generated using our * https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. * You will find a quickstart guide in the readme. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. * OpenZeppelin's JavaScript library generates merkle trees that are safe * against this attack out of the box. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Calldata version of {verify} * * _Available since v4.7._ */ function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} * * _Available since v4.7._ */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false * respectively. * * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). * * _Available since v4.7._ */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { require(proofPos == proofLen, "MerkleProof: invalid multiproof"); unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { require(proofPos == proofLen, "MerkleProof: invalid multiproof"); unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol"; // interface for modules to verify singatures signed over userOpHash interface IAuthorizationModule { function validateUserOp( UserOperation calldata userOp, bytes32 userOpHash ) external returns (uint256 validationData); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol"; interface ISessionKeyManager { /** * @dev validates that Session Key + parameters are enabled * by being included into the merkle tree * @param userOpSender smartAccount for which session key is being validated * @param validUntil timestamp when the session key expires * @param validAfter timestamp when the session key becomes valid * @param sessionValidationModule address of the Session Validation Module * @param sessionKeyData session parameters (limitations/permissions) * @param merkleProof merkle proof for the leaf which represents this session key + params * @dev if doesn't revert, session key is considered valid */ function validateSessionKey( address userOpSender, uint48 validUntil, uint48 validAfter, address sessionValidationModule, bytes calldata sessionKeyData, bytes32[] calldata merkleProof ) external; }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.17; contract ISignatureValidatorConstants { // bytes4(keccak256("isValidSignature(bytes32,bytes)") bytes4 internal constant EIP1271_MAGIC_VALUE = 0x1626ba7e; } abstract contract ISignatureValidator is ISignatureValidatorConstants { /** * @dev Should return whether the signature provided is valid for the provided data * @param _dataHash Arbitrary length data signed on behalf of address(this) * @param _signature Signature byte array associated with _data * * MUST return the bytes4 magic value 0x1626ba7e when function passes. * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5) * MUST allow external calls */ function isValidSignature( bytes32 _dataHash, bytes memory _signature ) public view virtual returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {IAuthorizationModule, UserOperation} from "../interfaces/IAuthorizationModule.sol"; import {ISignatureValidator, ISignatureValidatorConstants} from "../interfaces/ISignatureValidator.sol"; contract AuthorizationModulesConstants { uint256 internal constant VALIDATION_SUCCESS = 0; uint256 internal constant SIG_VALIDATION_FAILED = 1; } abstract contract BaseAuthorizationModule is IAuthorizationModule, ISignatureValidator, AuthorizationModulesConstants {}
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {UserOperation} from "../BaseAuthorizationModule.sol"; abstract contract ISessionValidationModule { // execute(address,uint256,bytes) bytes4 public constant EXECUTE_SELECTOR = 0xb61d27f6; // execute_ncC(address,uint256,bytes) bytes4 public constant EXECUTE_OPTIMIZED_SELECTOR = 0x0000189a; /** * @dev validates if the _op (UserOperation) matches the SessionKey permissions * and that _op has been signed by this SessionKey * @param _op User Operation to be validated. * @param _userOpHash Hash of the User Operation to be validated. * @param _sessionKeyData SessionKey data, that describes sessionKey permissions * @param _sessionKeySignature Signature over the the _userOpHash. * @return true if the _op is valid, false otherwise. */ function validateSessionUserOp( UserOperation calldata _op, bytes32 _userOpHash, bytes calldata _sessionKeyData, bytes calldata _sessionKeySignature ) external virtual returns (bool); /** * @dev validates that the call (destinationContract, callValue, funcCallData) * complies with the Session Key permissions represented by sessionKeyData * @param destinationContract address of the contract to be called * @param callValue value to be sent with the call * @param funcCallData the data for the call. * is parsed inside the Session Validation Module (SVM) * @param sessionKeyData SessionKey data, that describes sessionKey permissions */ function validateSessionParams( address destinationContract, uint256 callValue, bytes calldata funcCallData, bytes calldata sessionKeyData, bytes calldata callSpecificData ) external virtual returns (address); }
{ "optimizer": { "enabled": true, "runs": 800 }, "viaIR": true, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"smartAccount","type":"address"}],"name":"getSessionKeys","outputs":[{"components":[{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"internalType":"struct SessionStorage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_dataHash","type":"bytes32"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"}],"name":"setMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"smartAccount","type":"address"},{"internalType":"uint48","name":"validUntil","type":"uint48"},{"internalType":"uint48","name":"validAfter","type":"uint48"},{"internalType":"address","name":"sessionValidationModule","type":"address"},{"internalType":"bytes","name":"sessionKeyData","type":"bytes"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"validateSessionKey","outputs":[],"stateMutability":"nonpayable","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"}],"name":"validateUserOp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608080604052346100165761098d908161001c8239f35b600080fdfe6080604052600436101561001257600080fd5b60003560e01c80631626ba7e146105d35780637cb64759146105ab578063b13152ee146104c7578063fde5354d1461046e5763fff35b721461005357600080fd5b346104405760403660031901126104405767ffffffffffffffff6004351161044057600435360361016060031982011261044057600435610144013590602219018112156104405760043501600481013567ffffffffffffffff811161044057602482019080360382136104405782019060408383031261044057359067ffffffffffffffff8211610440576044916024806100f39301918501016106a0565b9101356001600160a01b03811603610440578051810160c0828203126104405761011f60208301610715565b61012b60408401610715565b9160608401516001600160a01b038116810361044057608085015167ffffffffffffffff8111610440576101679060208085019188010161074b565b9160a08601519567ffffffffffffffff87116104405760208201603f888301011215610440576020878201015161019d816106fd565b976101ab604051998a610662565b81895260208901906020850160408460051b8387010101116104405790604082850101915b60408460051b82870101018310610459575050505060c08101519167ffffffffffffffff83116104405761020b92602080920192010161074b565b906004803501356001600160a01b03811690036104405761038060006001600160a01b038561024b6103929a6020988488168c8c60043560040135610808565b604051998a96879586936384f16a4d60e01b85526080600486015285600435600401351660848601526024600435013560a48601526103666102ad61029a604460043501600435600401610790565b61016060c48a01526101e48901916107c2565b6103406102db6102c7606460043501600435600401610790565b6083198b8603810160e48d015294916107c2565b61032f61010460846004350135818c01526101249060a46004350135828d015260c460043501356101448d015260e460043501356101648d015260043501356101848c015260043501600435600401610790565b90848b8403016101a48c01526107c2565b9061035661014460043501600435600401610790565b91898403016101c48a01526107c2565b9060243560248701526003198683030160448701526107e3565b838103600319016064850152906107e3565b0393165af1801561044d5760009061040a575b602093506104035760015b60ff79ffffffffffff00000000000000000000000000000000000000007fffffffffffff00000000000000000000000000000000000000000000000000006040519560d01b169360a01b16911617178152f35b60006103b0565b50916020813d602011610445575b8161042560209383610662565b810103126104405751918215158303610440576020926103a5565b600080fd5b3d9150610418565b6040513d6000823e3d90fd5b602080604093855181520193019291506101d0565b34610440576020366003190112610440576001600160a01b0361048f6106e7565b600060405161049d81610630565b5216600052600060205260206040600020604051906104bb82610630565b54809152604051908152f35b346104405760c0366003190112610440576104e06106e7565b65ffffffffffff6024358181168103610440576044359182168203610440576064356001600160a01b03811681036104405767ffffffffffffffff92608435848111610440576105349036906004016106a0565b9260a435948511610440573660238601121561044057846004013595610559876106fd565b956105676040519788610662565b87875260209760248989019160051b8301019136831161044057602401905b82821061059c5750505061059a9650610808565b005b81358152908901908901610586565b3461044057602036600319011261044057336000526000602052600435604060002055600080f35b346104405760403660031901126104405760243567ffffffffffffffff8111610440576106049036906004016106a0565b506040517fffffffff000000000000000000000000000000000000000000000000000000008152602090f35b6020810190811067ffffffffffffffff82111761064c57604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff82111761064c57604052565b67ffffffffffffffff811161064c57601f01601f191660200190565b81601f82011215610440578035906106b782610684565b926106c56040519485610662565b8284526020838301011161044057816000926020809301838601378301015290565b600435906001600160a01b038216820361044057565b67ffffffffffffffff811161064c5760051b60200190565b519065ffffffffffff8216820361044057565b60005b83811061073b5750506000910152565b818101518382015260200161072b565b81601f8201121561044057805161076181610684565b9261076f6040519485610662565b818452602082840101116104405761078d9160208085019101610728565b90565b9035601e198236030181121561044057016020813591019167ffffffffffffffff821161044057813603831361044057565b908060209392818452848401376000828201840152601f01601f1916010190565b906020916107fc81518092818552858086019101610728565b601f01601f1916010190565b9490939592916001600160a01b036000961686526020928684526108a160408097818a209a8251948592898401977fffffffffffff0000000000000000000000000000000000000000000000000000809260d01b16895260d01b1660268401526bffffffffffffffffffffffff199060601b16602c830152610892815180928a8686019101610728565b81010386810184520182610662565b5190209554959285935b825185101561090457838560051b84010151908181106000146108f757875283528486205b9360001981146108e357600101936108ab565b634e487b7160e01b87526011600452602487fd5b90875283528486206108d0565b9295509592505003610914575050565b60649250519062461bcd60e51b82526004820152601260248201527f53657373696f6e4e6f74417070726f76656400000000000000000000000000006044820152fdfea26469706673582212206e319ba0cd2074c2476c54765e486d5e38b9906f13ca047f6aeaa0c8561fa33164736f6c63430008110033
Deployed Bytecode
0x6080604052600436101561001257600080fd5b60003560e01c80631626ba7e146105d35780637cb64759146105ab578063b13152ee146104c7578063fde5354d1461046e5763fff35b721461005357600080fd5b346104405760403660031901126104405767ffffffffffffffff6004351161044057600435360361016060031982011261044057600435610144013590602219018112156104405760043501600481013567ffffffffffffffff811161044057602482019080360382136104405782019060408383031261044057359067ffffffffffffffff8211610440576044916024806100f39301918501016106a0565b9101356001600160a01b03811603610440578051810160c0828203126104405761011f60208301610715565b61012b60408401610715565b9160608401516001600160a01b038116810361044057608085015167ffffffffffffffff8111610440576101679060208085019188010161074b565b9160a08601519567ffffffffffffffff87116104405760208201603f888301011215610440576020878201015161019d816106fd565b976101ab604051998a610662565b81895260208901906020850160408460051b8387010101116104405790604082850101915b60408460051b82870101018310610459575050505060c08101519167ffffffffffffffff83116104405761020b92602080920192010161074b565b906004803501356001600160a01b03811690036104405761038060006001600160a01b038561024b6103929a6020988488168c8c60043560040135610808565b604051998a96879586936384f16a4d60e01b85526080600486015285600435600401351660848601526024600435013560a48601526103666102ad61029a604460043501600435600401610790565b61016060c48a01526101e48901916107c2565b6103406102db6102c7606460043501600435600401610790565b6083198b8603810160e48d015294916107c2565b61032f61010460846004350135818c01526101249060a46004350135828d015260c460043501356101448d015260e460043501356101648d015260043501356101848c015260043501600435600401610790565b90848b8403016101a48c01526107c2565b9061035661014460043501600435600401610790565b91898403016101c48a01526107c2565b9060243560248701526003198683030160448701526107e3565b838103600319016064850152906107e3565b0393165af1801561044d5760009061040a575b602093506104035760015b60ff79ffffffffffff00000000000000000000000000000000000000007fffffffffffff00000000000000000000000000000000000000000000000000006040519560d01b169360a01b16911617178152f35b60006103b0565b50916020813d602011610445575b8161042560209383610662565b810103126104405751918215158303610440576020926103a5565b600080fd5b3d9150610418565b6040513d6000823e3d90fd5b602080604093855181520193019291506101d0565b34610440576020366003190112610440576001600160a01b0361048f6106e7565b600060405161049d81610630565b5216600052600060205260206040600020604051906104bb82610630565b54809152604051908152f35b346104405760c0366003190112610440576104e06106e7565b65ffffffffffff6024358181168103610440576044359182168203610440576064356001600160a01b03811681036104405767ffffffffffffffff92608435848111610440576105349036906004016106a0565b9260a435948511610440573660238601121561044057846004013595610559876106fd565b956105676040519788610662565b87875260209760248989019160051b8301019136831161044057602401905b82821061059c5750505061059a9650610808565b005b81358152908901908901610586565b3461044057602036600319011261044057336000526000602052600435604060002055600080f35b346104405760403660031901126104405760243567ffffffffffffffff8111610440576106049036906004016106a0565b506040517fffffffff000000000000000000000000000000000000000000000000000000008152602090f35b6020810190811067ffffffffffffffff82111761064c57604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff82111761064c57604052565b67ffffffffffffffff811161064c57601f01601f191660200190565b81601f82011215610440578035906106b782610684565b926106c56040519485610662565b8284526020838301011161044057816000926020809301838601378301015290565b600435906001600160a01b038216820361044057565b67ffffffffffffffff811161064c5760051b60200190565b519065ffffffffffff8216820361044057565b60005b83811061073b5750506000910152565b818101518382015260200161072b565b81601f8201121561044057805161076181610684565b9261076f6040519485610662565b818452602082840101116104405761078d9160208085019101610728565b90565b9035601e198236030181121561044057016020813591019167ffffffffffffffff821161044057813603831361044057565b908060209392818452848401376000828201840152601f01601f1916010190565b906020916107fc81518092818552858086019101610728565b601f01601f1916010190565b9490939592916001600160a01b036000961686526020928684526108a160408097818a209a8251948592898401977fffffffffffff0000000000000000000000000000000000000000000000000000809260d01b16895260d01b1660268401526bffffffffffffffffffffffff199060601b16602c830152610892815180928a8686019101610728565b81010386810184520182610662565b5190209554959285935b825185101561090457838560051b84010151908181106000146108f757875283528486205b9360001981146108e357600101936108ab565b634e487b7160e01b87526011600452602487fd5b90875283528486206108d0565b9295509592505003610914575050565b60649250519062461bcd60e51b82526004820152601260248201527f53657373696f6e4e6f74417070726f76656400000000000000000000000000006044820152fdfea26469706673582212206e319ba0cd2074c2476c54765e486d5e38b9906f13ca047f6aeaa0c8561fa33164736f6c63430008110033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.