ETH Price: $3,326.81 (+1.62%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block
From
To
203116652024-07-15 11:38:47194 days ago1721043527  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
CallPolicy

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 9 : CallPolicy.sol
pragma solidity ^0.8.0;

import "kernel/sdk/moduleBase/PolicyBase.sol";
import "kernel/utils/ExecLib.sol";
import {IERC7579Account} from "kernel/interfaces/IERC7579Account.sol";

struct Permission {
    CallType callType; // calltype can be CALLTYPE_SINGLE/CALLTYPE_DELEGATECALL
    address target;
    bytes4 selector;
    uint256 valueLimit;
    ParamRule[] rules;
}

struct ParamRule {
    ParamCondition condition;
    uint64 offset;
    bytes32[] params;
}

enum ParamCondition {
    EQUAL,
    GREATER_THAN,
    LESS_THAN,
    GREATER_THAN_OR_EQUAL,
    LESS_THAN_OR_EQUAL,
    NOT_EQUAL,
    ONE_OF
}

enum Status {
    NA,
    Live,
    Deprecated
}

contract CallPolicy is PolicyBase {
    error InvalidCallType();
    error InvalidCallData();
    error CallViolatesParamRule();
    error CallViolatesValueRule();

    mapping(address => uint256) public usedIds;
    mapping(bytes32 id => mapping(address => Status)) public status;
    mapping(bytes32 id => mapping(bytes32 permissionHash => mapping(address => bytes))) public encodedPermissions;

    function isInitialized(address wallet) external view override returns (bool) {
        return usedIds[wallet] > 0;
    }

    function checkUserOpPolicy(bytes32 id, PackedUserOperation calldata userOp)
        external
        payable
        override
        returns (uint256)
    {
        require(bytes4(userOp.callData[0:4]) == IERC7579Account.execute.selector);
        ExecMode mode = ExecMode.wrap(bytes32(userOp.callData[4:36]));
        (CallType callType, ExecType execType,,) = ExecLib.decode(mode);
        bytes calldata executionCallData = userOp.callData; // Cache calldata here
        assembly {
            executionCallData.offset :=
                add(add(executionCallData.offset, 0x24), calldataload(add(executionCallData.offset, 0x24)))
            executionCallData.length := calldataload(sub(executionCallData.offset, 0x20))
        }
        if (callType == CALLTYPE_SINGLE) {
            (address target, uint256 value, bytes calldata callData) = ExecLib.decodeSingle(executionCallData);
            bool permissionPass = _checkPermission(msg.sender, id, CALLTYPE_SINGLE, target, callData, value);
            if (!permissionPass) {
                revert CallViolatesParamRule();
            }
        } else if (callType == CALLTYPE_BATCH) {
            Execution[] calldata exec = ExecLib.decodeBatch(executionCallData);
            for (uint256 i = 0; i < exec.length; i++) {
                bool permissionPass =
                    _checkPermission(msg.sender, id, CALLTYPE_SINGLE, exec[i].target, exec[i].callData, exec[i].value);
                if (!permissionPass) {
                    revert CallViolatesParamRule();
                }
            }
        } else if (callType == CALLTYPE_DELEGATECALL) {
            (address target, uint256 value, bytes calldata callData) = ExecLib.decodeSingle(executionCallData);
            bool permissionPass = _checkPermission(msg.sender, id, CALLTYPE_DELEGATECALL, target, callData, value);
            if (!permissionPass) {
                revert CallViolatesParamRule();
            }
        } else {
            revert InvalidCallType();
        }
    }

    function _checkPermission(
        address wallet,
        bytes32 id,
        CallType callType,
        address target,
        bytes calldata data,
        uint256 value
    ) internal returns (bool) {
        bytes4 _data = data.length == 0 ? bytes4(0x0) : bytes4(data[0:4]);
        bytes32 permissionHash = keccak256(abi.encodePacked(callType, target, _data));
        bytes memory encodedPermission = encodedPermissions[id][permissionHash][wallet];

        // try to find the permission with zero address which means ANY target address
        // e.g. allow to call `approve` function of `ANY` ERC20 token contracts
        if (encodedPermission.length == 0) {
            bytes32 permissionHashWithZeroAddress = keccak256(abi.encodePacked(callType, address(0), _data));
            encodedPermission = encodedPermissions[id][permissionHashWithZeroAddress][wallet];
        }

        // if still no permission found, then the call is not allowed
        if (encodedPermission.length == 0) {
            revert InvalidCallData();
        }

        (uint256 allowedValue, ParamRule[] memory rules) = abi.decode(encodedPermission, (uint256, ParamRule[]));

        if (value > allowedValue) {
            revert CallViolatesValueRule();
        }
        for (uint256 i = 0; i < rules.length; i++) {
            ParamRule memory rule = rules[i];
            bytes32 param = bytes32(data[4 + rule.offset:4 + rule.offset + 32]);
            // only ONE_OF condition can have multiple params
            if (rule.condition == ParamCondition.EQUAL && param != rule.params[0]) {
                return false;
            } else if (rule.condition == ParamCondition.GREATER_THAN && param <= rule.params[0]) {
                return false;
            } else if (rule.condition == ParamCondition.LESS_THAN && param >= rule.params[0]) {
                return false;
            } else if (rule.condition == ParamCondition.GREATER_THAN_OR_EQUAL && param < rule.params[0]) {
                return false;
            } else if (rule.condition == ParamCondition.LESS_THAN_OR_EQUAL && param > rule.params[0]) {
                return false;
            } else if (rule.condition == ParamCondition.NOT_EQUAL && param == rule.params[0]) {
                return false;
            } else if (rule.condition == ParamCondition.ONE_OF) {
                bool oneOfStatus = false;
                for (uint256 j = 0; j < rule.params.length; j++) {
                    if (param == rule.params[j]) {
                        oneOfStatus = true;
                        break;
                    }
                }
                if (!oneOfStatus) {
                    return false;
                }
            }
        }
        return true;
    }

    function checkSignaturePolicy(bytes32 id, address sender, bytes32 hash, bytes calldata sig)
        external
        view
        override
        returns (uint256)
    {
        require(status[id][msg.sender] == Status.Live);
        return 0;
    }

    function _parsePermission(bytes calldata _sig) internal pure returns (Permission[] calldata permissions) {
        assembly {
            permissions.offset := add(add(_sig.offset, 32), calldataload(_sig.offset))
            permissions.length := calldataload(sub(permissions.offset, 32))
        }
    }

    function _policyOninstall(bytes32 id, bytes calldata _data) internal override {
        require(status[id][msg.sender] == Status.NA);
        Permission[] calldata permissions = _parsePermission(_data);
        for (uint256 i = 0; i < permissions.length; i++) {
            // check if the permissionHash is unique
            bytes32 permissionHash =
                keccak256(abi.encodePacked(permissions[i].callType, permissions[i].target, permissions[i].selector));
            require(encodedPermissions[id][permissionHash][msg.sender].length == 0, "duplicate permissionHash");

            // check if the params length is correct
            for (uint256 j = 0; j < permissions[i].rules.length; j++) {
                if (permissions[i].rules[j].condition != ParamCondition.ONE_OF) {
                    require(permissions[i].rules[j].params.length == 1, "only OneOf condition can have multiple params");
                }
            }

            encodedPermissions[id][permissionHash][msg.sender] =
                abi.encode(permissions[i].valueLimit, permissions[i].rules);
        }
        status[id][msg.sender] = Status.Live;
        usedIds[msg.sender]++;
    }

    function _policyOnUninstall(bytes32 id, bytes calldata _data) internal override {
        require(status[id][msg.sender] == Status.Live);
        //delete encodedPermissions[id][msg.sender];
        status[id][msg.sender] = Status.Deprecated;
        usedIds[msg.sender]--;
    }
}

File 2 of 9 : PolicyBase.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IPolicy} from "../../interfaces/IERC7579Modules.sol";
import {PackedUserOperation} from "../../interfaces/PackedUserOperation.sol";

abstract contract PolicyBase is IPolicy {
    function onInstall(bytes calldata data) external payable {
        bytes32 id = bytes32(data[0:32]);
        bytes calldata _data = data[32:];
        _policyOninstall(id, _data);
    }

    function onUninstall(bytes calldata data) external payable {
        bytes32 id = bytes32(data[0:32]);
        bytes calldata _data = data[32:];
        _policyOnUninstall(id, _data);
    }

    function isModuleType(uint256 id) external pure returns (bool) {
        return id == 5;
    }

    function isInitialized(address) external view virtual returns (bool); // TODO : not sure if this is the right way to do it
    function checkUserOpPolicy(bytes32 id, PackedUserOperation calldata userOp)
        external
        payable
        virtual
        returns (uint256);
    function checkSignaturePolicy(bytes32 id, address sender, bytes32 hash, bytes calldata sig)
        external
        view
        virtual
        returns (uint256);

    function _policyOninstall(bytes32 id, bytes calldata _data) internal virtual;
    function _policyOnUninstall(bytes32 id, bytes calldata _data) internal virtual;
}

File 3 of 9 : ExecLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import {ExecMode, CallType, ExecType, ExecModeSelector, ExecModePayload} from "../types/Types.sol";
import {
    CALLTYPE_SINGLE,
    CALLTYPE_BATCH,
    EXECTYPE_DEFAULT,
    EXEC_MODE_DEFAULT,
    EXECTYPE_TRY,
    CALLTYPE_DELEGATECALL
} from "../types/Constants.sol";
import {Execution} from "../types/Structs.sol";

/**
 * @dev ExecLib is a helper library for execution
 */
library ExecLib {
    error ExecutionFailed();

    event TryExecuteUnsuccessful(uint256 batchExecutionindex, bytes result);

    function execute(ExecMode execMode, bytes calldata executionCalldata)
        internal
        returns (bytes[] memory returnData)
    {
        (CallType callType, ExecType execType,,) = decode(execMode);

        // check if calltype is batch or single
        if (callType == CALLTYPE_BATCH) {
            // destructure executionCallData according to batched exec
            Execution[] calldata executions = decodeBatch(executionCalldata);
            // check if execType is revert or try
            if (execType == EXECTYPE_DEFAULT) returnData = execute(executions);
            else if (execType == EXECTYPE_TRY) returnData = tryExecute(executions);
            else revert("Unsupported");
        } else if (callType == CALLTYPE_SINGLE) {
            // destructure executionCallData according to single exec
            (address target, uint256 value, bytes calldata callData) = decodeSingle(executionCalldata);
            returnData = new bytes[](1);
            bool success;
            // check if execType is revert or try
            if (execType == EXECTYPE_DEFAULT) {
                returnData[0] = execute(target, value, callData);
            } else if (execType == EXECTYPE_TRY) {
                (success, returnData[0]) = tryExecute(target, value, callData);
                if (!success) emit TryExecuteUnsuccessful(0, returnData[0]);
            } else {
                revert("Unsupported");
            }
        } else if (callType == CALLTYPE_DELEGATECALL) {
            address delegate = address(bytes20(executionCalldata[0:20]));
            bytes calldata callData = executionCalldata[20:];
            executeDelegatecall(delegate, callData);
        } else {
            revert("Unsupported");
        }
    }

    function execute(Execution[] calldata executions) internal returns (bytes[] memory result) {
        uint256 length = executions.length;
        result = new bytes[](length);

        for (uint256 i; i < length; i++) {
            Execution calldata _exec = executions[i];
            result[i] = execute(_exec.target, _exec.value, _exec.callData);
        }
    }

    function tryExecute(Execution[] calldata executions) internal returns (bytes[] memory result) {
        uint256 length = executions.length;
        result = new bytes[](length);

        for (uint256 i; i < length; i++) {
            Execution calldata _exec = executions[i];
            bool success;
            (success, result[i]) = tryExecute(_exec.target, _exec.value, _exec.callData);
            if (!success) emit TryExecuteUnsuccessful(i, result[i]);
        }
    }

    function execute(address target, uint256 value, bytes calldata callData) internal returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            calldatacopy(result, callData.offset, callData.length)
            if iszero(call(gas(), target, value, result, callData.length, codesize(), 0x00)) {
                // Bubble up the revert if the call reverts.
                returndatacopy(result, 0x00, returndatasize())
                revert(result, returndatasize())
            }
            mstore(result, returndatasize()) // Store the length.
            let o := add(result, 0x20)
            returndatacopy(o, 0x00, returndatasize()) // Copy the returndata.
            mstore(0x40, add(o, returndatasize())) // Allocate the memory.
        }
    }

    function tryExecute(address target, uint256 value, bytes calldata callData)
        internal
        returns (bool success, bytes memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            calldatacopy(result, callData.offset, callData.length)
            success := call(gas(), target, value, result, callData.length, codesize(), 0x00)
            mstore(result, returndatasize()) // Store the length.
            let o := add(result, 0x20)
            returndatacopy(o, 0x00, returndatasize()) // Copy the returndata.
            mstore(0x40, add(o, returndatasize())) // Allocate the memory.
        }
    }

    /// @dev Execute a delegatecall with `delegate` on this account.
    function executeDelegatecall(address delegate, bytes calldata callData)
        internal
        returns (bool success, bytes memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            calldatacopy(result, callData.offset, callData.length)
            // Forwards the `data` to `delegate` via delegatecall.
            success := delegatecall(gas(), delegate, result, callData.length, codesize(), 0x00)
            mstore(result, returndatasize()) // Store the length.
            let o := add(result, 0x20)
            returndatacopy(o, 0x00, returndatasize()) // Copy the returndata.
            mstore(0x40, add(o, returndatasize())) // Allocate the memory.
        }
    }

    function decode(ExecMode mode)
        internal
        pure
        returns (CallType _calltype, ExecType _execType, ExecModeSelector _modeSelector, ExecModePayload _modePayload)
    {
        assembly {
            _calltype := mode
            _execType := shl(8, mode)
            _modeSelector := shl(48, mode)
            _modePayload := shl(80, mode)
        }
    }

    function encode(CallType callType, ExecType execType, ExecModeSelector mode, ExecModePayload payload)
        internal
        pure
        returns (ExecMode)
    {
        return ExecMode.wrap(
            bytes32(abi.encodePacked(callType, execType, bytes4(0), ExecModeSelector.unwrap(mode), payload))
        );
    }

    function encodeSimpleBatch() internal pure returns (ExecMode mode) {
        mode = encode(CALLTYPE_BATCH, EXECTYPE_DEFAULT, EXEC_MODE_DEFAULT, ExecModePayload.wrap(0x00));
    }

    function encodeSimpleSingle() internal pure returns (ExecMode mode) {
        mode = encode(CALLTYPE_SINGLE, EXECTYPE_DEFAULT, EXEC_MODE_DEFAULT, ExecModePayload.wrap(0x00));
    }

    function getCallType(ExecMode mode) internal pure returns (CallType calltype) {
        assembly {
            calltype := mode
        }
    }

    function decodeBatch(bytes calldata callData) internal pure returns (Execution[] calldata executionBatch) {
        /*
         * Batch Call Calldata Layout
         * Offset (in bytes)    | Length (in bytes) | Contents
         * 0x0                  | 0x4               | bytes4 function selector
        *  0x4                  | -                 |
        abi.encode(IERC7579Execution.Execution[])
         */
        // solhint-disable-next-line no-inline-assembly
        assembly ("memory-safe") {
            let dataPointer := add(callData.offset, calldataload(callData.offset))

            // Extract the ERC7579 Executions
            executionBatch.offset := add(dataPointer, 32)
            executionBatch.length := calldataload(dataPointer)
        }
    }

    function encodeBatch(Execution[] memory executions) internal pure returns (bytes memory callData) {
        callData = abi.encode(executions);
    }

    function decodeSingle(bytes calldata executionCalldata)
        internal
        pure
        returns (address target, uint256 value, bytes calldata callData)
    {
        target = address(bytes20(executionCalldata[0:20]));
        value = uint256(bytes32(executionCalldata[20:52]));
        callData = executionCalldata[52:];
    }

    function encodeSingle(address target, uint256 value, bytes memory callData)
        internal
        pure
        returns (bytes memory userOpCalldata)
    {
        userOpCalldata = abi.encodePacked(target, value, callData);
    }

    function doFallback2771Static(address fallbackHandler) internal view returns (bool success, bytes memory result) {
        assembly {
            function allocate(length) -> pos {
                pos := mload(0x40)
                mstore(0x40, add(pos, length))
            }

            let calldataPtr := allocate(calldatasize())
            calldatacopy(calldataPtr, 0, calldatasize())

            // The msg.sender address is shifted to the left by 12 bytes to remove the padding
            // Then the address without padding is stored right after the calldata
            let senderPtr := allocate(20)
            mstore(senderPtr, shl(96, caller()))

            // Add 20 bytes for the address appended add the end
            success := staticcall(gas(), fallbackHandler, calldataPtr, add(calldatasize(), 20), 0, 0)

            result := mload(0x40)
            mstore(result, returndatasize()) // Store the length.
            let o := add(result, 0x20)
            returndatacopy(o, 0x00, returndatasize()) // Copy the returndata.
            mstore(0x40, add(o, returndatasize())) // Allocate the memory.
        }
    }

    function doFallback2771Call(address target) internal returns (bool success, bytes memory result) {
        assembly {
            function allocate(length) -> pos {
                pos := mload(0x40)
                mstore(0x40, add(pos, length))
            }

            let calldataPtr := allocate(calldatasize())
            calldatacopy(calldataPtr, 0, calldatasize())

            // The msg.sender address is shifted to the left by 12 bytes to remove the padding
            // Then the address without padding is stored right after the calldata
            let senderPtr := allocate(20)
            mstore(senderPtr, shl(96, caller()))

            // Add 20 bytes for the address appended add the end
            success := call(gas(), target, 0, calldataPtr, add(calldatasize(), 20), 0, 0)

            result := mload(0x40)
            mstore(result, returndatasize()) // Store the length.
            let o := add(result, 0x20)
            returndatacopy(o, 0x00, returndatasize()) // Copy the returndata.
            mstore(0x40, add(o, returndatasize())) // Allocate the memory.
        }
    }
}

File 4 of 9 : IERC7579Account.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import {CallType, ExecType, ExecMode} from "../utils/ExecLib.sol";
import {PackedUserOperation} from "./PackedUserOperation.sol";

struct Execution {
    address target;
    uint256 value;
    bytes callData;
}

interface IERC7579Account {
    event ModuleInstalled(uint256 moduleTypeId, address module);
    event ModuleUninstalled(uint256 moduleTypeId, address module);

    /**
     * @dev Executes a transaction on behalf of the account.
     *         This function is intended to be called by ERC-4337 EntryPoint.sol
     * @dev Ensure adequate authorization control: i.e. onlyEntryPointOrSelf
     *
     * @dev MSA MUST implement this function signature.
     * If a mode is requested that is not supported by the Account, it MUST revert
     * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details
     * @param executionCalldata The encoded execution call data
     */
    function execute(ExecMode mode, bytes calldata executionCalldata) external payable;

    /**
     * @dev Executes a transaction on behalf of the account.
     *         This function is intended to be called by Executor Modules
     * @dev Ensure adequate authorization control: i.e. onlyExecutorModule
     *
     * @dev MSA MUST implement this function signature.
     * If a mode is requested that is not supported by the Account, it MUST revert
     * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details
     * @param executionCalldata The encoded execution call data
     */
    function executeFromExecutor(ExecMode mode, bytes calldata executionCalldata)
        external
        payable
        returns (bytes[] memory returnData);

    /**
     * @dev ERC-1271 isValidSignature
     *         This function is intended to be used to validate a smart account signature
     * and may forward the call to a validator module
     *
     * @param hash The hash of the data that is signed
     * @param data The data that is signed
     */
    function isValidSignature(bytes32 hash, bytes calldata data) external view returns (bytes4);

    /**
     * @dev installs a Module of a certain type on the smart account
     * @dev Implement Authorization control of your chosing
     * @param moduleTypeId the module type ID according the ERC-7579 spec
     * @param module the module address
     * @param initData arbitrary data that may be required on the module during `onInstall`
     * initialization.
     */
    function installModule(uint256 moduleTypeId, address module, bytes calldata initData) external payable;

    /**
     * @dev uninstalls a Module of a certain type on the smart account
     * @dev Implement Authorization control of your chosing
     * @param moduleTypeId the module type ID according the ERC-7579 spec
     * @param module the module address
     * @param deInitData arbitrary data that may be required on the module during `onUninstall`
     * de-initialization.
     */
    function uninstallModule(uint256 moduleTypeId, address module, bytes calldata deInitData) external payable;

    /**
     * Function to check if the account supports a certain CallType or ExecType (see ModeLib.sol)
     * @param encodedMode the encoded mode
     */
    function supportsExecutionMode(ExecMode encodedMode) external view returns (bool);

    /**
     * Function to check if the account supports installation of a certain module type Id
     * @param moduleTypeId the module type ID according the ERC-7579 spec
     */
    function supportsModule(uint256 moduleTypeId) external view returns (bool);

    /**
     * Function to check if the account has a certain module installed
     * @param moduleTypeId the module type ID according the ERC-7579 spec
     *      Note: keep in mind that some contracts can be multiple module types at the same time. It
     *            thus may be necessary to query multiple module types
     * @param module the module address
     * @param additionalContext additional context data that the smart account may interpret to
     *                          identifiy conditions under which the module is installed.
     *                          usually this is not necessary, but for some special hooks that
     *                          are stored in mappings, this param might be needed
     */
    function isModuleInstalled(uint256 moduleTypeId, address module, bytes calldata additionalContext)
        external
        view
        returns (bool);

    /**
     * @dev Returns the account id of the smart account
     * @return accountImplementationId the account id of the smart account
     * the accountId should be structured like so:
     *        "vendorname.accountname.semver"
     */
    function accountId() external view returns (string memory accountImplementationId);
}

File 5 of 9 : IERC7579Modules.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import {PackedUserOperation} from "./PackedUserOperation.sol";

interface IModule {
    error AlreadyInitialized(address smartAccount);
    error NotInitialized(address smartAccount);

    /**
     * @dev This function is called by the smart account during installation of the module
     * @param data arbitrary data that may be required on the module during `onInstall`
     * initialization
     *
     * MUST revert on error (i.e. if module is already enabled)
     */
    function onInstall(bytes calldata data) external payable;

    /**
     * @dev This function is called by the smart account during uninstallation of the module
     * @param data arbitrary data that may be required on the module during `onUninstall`
     * de-initialization
     *
     * MUST revert on error
     */
    function onUninstall(bytes calldata data) external payable;

    /**
     * @dev Returns boolean value if module is a certain type
     * @param moduleTypeId the module type ID according the ERC-7579 spec
     *
     * MUST return true if the module is of the given type and false otherwise
     */
    function isModuleType(uint256 moduleTypeId) external view returns (bool);

    /**
     * @dev Returns if the module was already initialized for a provided smartaccount
     */
    function isInitialized(address smartAccount) external view returns (bool);
}

interface IValidator is IModule {
    error InvalidTargetAddress(address target);

    /**
     * @dev Validates a transaction on behalf of the account.
     *         This function is intended to be called by the MSA during the ERC-4337 validaton phase
     *         Note: solely relying on bytes32 hash and signature is not suffcient for some
     * validation implementations (i.e. SessionKeys often need access to userOp.calldata)
     * @param userOp The user operation to be validated. The userOp MUST NOT contain any metadata.
     * The MSA MUST clean up the userOp before sending it to the validator.
     * @param userOpHash The hash of the user operation to be validated
     * @return return value according to ERC-4337
     */
    function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)
        external
        payable
        returns (uint256);

    /**
     * Validator can be used for ERC-1271 validation
     */
    function isValidSignatureWithSender(address sender, bytes32 hash, bytes calldata data)
        external
        view
        returns (bytes4);
}

interface IExecutor is IModule {}

interface IHook is IModule {
    /**
     * @dev Called by the smart account before execution
     * @param msgSender the address that called the smart account
     * @param value the value that was sent to the smart account
     * @param msgData the data that was sent to the smart account
     *
     * MAY return arbitrary data in the `hookData` return value
     */
    function preCheck(address msgSender, uint256 value, bytes calldata msgData)
        external
        payable
        returns (bytes memory hookData);

    /**
     * @dev Called by the smart account after execution
     * @param hookData the data that was returned by the `preCheck` function
     * @param executionSuccess whether the execution(s) was (were) successful
     * @param executionReturn the return/revert data of the execution(s)
     *
     * MAY validate the `hookData` to validate transaction context of the `preCheck` function
     */
    function postCheck(bytes calldata hookData, bool executionSuccess, bytes calldata executionReturn)
        external
        payable;
}

interface IFallback is IModule {}

interface IPolicy is IModule {
    function checkUserOpPolicy(bytes32 id, PackedUserOperation calldata userOp) external payable returns (uint256);
    function checkSignaturePolicy(bytes32 id, address sender, bytes32 hash, bytes calldata sig)
        external
        view
        returns (uint256);
}

interface ISigner is IModule {
    function checkUserOpSignature(bytes32 id, PackedUserOperation calldata userOp, bytes32 userOpHash)
        external
        payable
        returns (uint256);
    function checkSignature(bytes32 id, address sender, bytes32 hash, bytes calldata sig)
        external
        view
        returns (bytes4);
}

File 6 of 9 : PackedUserOperation.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.5;

/**
 * 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 accountGasLimits      - Packed gas limits for validateUserOp and gas limit passed to the callData method call.
 * @param preVerificationGas    - Gas not calculated by the handleOps method, but added to the gas paid.
 *                                Covers batch overhead.
 * @param gasFees                - packed gas fields maxFeePerGas and maxPriorityFeePerGas - Same as EIP-1559 gas parameter.
 * @param paymasterAndData      - If set, this field holds the paymaster address, verification gas limit, postOp gas limit and paymaster-specific extra 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 PackedUserOperation {
    address sender;
    uint256 nonce;
    bytes initCode;
    bytes callData;
    bytes32 accountGasLimits;
    uint256 preVerificationGas;
    bytes32 gasFees; //maxPriorityFee and maxFeePerGas;
    bytes paymasterAndData;
    bytes signature;
}

File 7 of 9 : Types.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.23;

// Custom type for improved developer experience
type ExecMode is bytes32;

type CallType is bytes1;

type ExecType is bytes1;

type ExecModeSelector is bytes4;

type ExecModePayload is bytes22;

using {eqModeSelector as ==} for ExecModeSelector global;
using {eqCallType as ==} for CallType global;
using {notEqCallType as !=} for CallType global;
using {eqExecType as ==} for ExecType global;

function eqCallType(CallType a, CallType b) pure returns (bool) {
    return CallType.unwrap(a) == CallType.unwrap(b);
}

function notEqCallType(CallType a, CallType b) pure returns (bool) {
    return CallType.unwrap(a) != CallType.unwrap(b);
}

function eqExecType(ExecType a, ExecType b) pure returns (bool) {
    return ExecType.unwrap(a) == ExecType.unwrap(b);
}

function eqModeSelector(ExecModeSelector a, ExecModeSelector b) pure returns (bool) {
    return ExecModeSelector.unwrap(a) == ExecModeSelector.unwrap(b);
}

type ValidationMode is bytes1;

type ValidationId is bytes21;

type ValidationType is bytes1;

type PermissionId is bytes4;

type PolicyData is bytes22; // 2bytes for flag on skip, 20 bytes for validator address

type PassFlag is bytes2;

using {vModeEqual as ==} for ValidationMode global;
using {vTypeEqual as ==} for ValidationType global;
using {vIdentifierEqual as ==} for ValidationId global;
using {vModeNotEqual as !=} for ValidationMode global;
using {vTypeNotEqual as !=} for ValidationType global;
using {vIdentifierNotEqual as !=} for ValidationId global;

// nonce = uint192(key) + nonce
// key = mode + (vtype + validationDataWithoutType) + 2bytes parallelNonceKey
// key = 0x00 + 0x00 + 0x000 .. 00 + 0x0000
// key = 0x00 + 0x01 + 0x1234...ff + 0x0000
// key = 0x00 + 0x02 + ( ) + 0x000

function vModeEqual(ValidationMode a, ValidationMode b) pure returns (bool) {
    return ValidationMode.unwrap(a) == ValidationMode.unwrap(b);
}

function vModeNotEqual(ValidationMode a, ValidationMode b) pure returns (bool) {
    return ValidationMode.unwrap(a) != ValidationMode.unwrap(b);
}

function vTypeEqual(ValidationType a, ValidationType b) pure returns (bool) {
    return ValidationType.unwrap(a) == ValidationType.unwrap(b);
}

function vTypeNotEqual(ValidationType a, ValidationType b) pure returns (bool) {
    return ValidationType.unwrap(a) != ValidationType.unwrap(b);
}

function vIdentifierEqual(ValidationId a, ValidationId b) pure returns (bool) {
    return ValidationId.unwrap(a) == ValidationId.unwrap(b);
}

function vIdentifierNotEqual(ValidationId a, ValidationId b) pure returns (bool) {
    return ValidationId.unwrap(a) != ValidationId.unwrap(b);
}

type ValidationData is uint256;

type ValidAfter is uint48;

type ValidUntil is uint48;

function getValidationResult(ValidationData validationData) pure returns (address result) {
    assembly {
        result := validationData
    }
}

function packValidationData(ValidAfter validAfter, ValidUntil validUntil) pure returns (uint256) {
    return uint256(ValidAfter.unwrap(validAfter)) << 208 | uint256(ValidUntil.unwrap(validUntil)) << 160;
}

function parseValidationData(uint256 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)
    }
}

File 8 of 9 : Constants.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import {CallType, ExecType, ExecModeSelector} from "./Types.sol";
import {PassFlag, ValidationMode, ValidationType} from "./Types.sol";
import {ValidationData} from "./Types.sol";

// --- ERC7579 calltypes ---
// Default CallType
CallType constant CALLTYPE_SINGLE = CallType.wrap(0x00);
// Batched CallType
CallType constant CALLTYPE_BATCH = CallType.wrap(0x01);
CallType constant CALLTYPE_STATIC = CallType.wrap(0xFE);
// @dev Implementing delegatecall is OPTIONAL!
// implement delegatecall with extreme care.
CallType constant CALLTYPE_DELEGATECALL = CallType.wrap(0xFF);

// --- ERC7579 exectypes ---
// @dev default behavior is to revert on failure
// To allow very simple accounts to use mode encoding, the default behavior is to revert on failure
// Since this is value 0x00, no additional encoding is required for simple accounts
ExecType constant EXECTYPE_DEFAULT = ExecType.wrap(0x00);
// @dev account may elect to change execution behavior. For example "try exec" / "allow fail"
ExecType constant EXECTYPE_TRY = ExecType.wrap(0x01);

// --- ERC7579 mode selector ---
ExecModeSelector constant EXEC_MODE_DEFAULT = ExecModeSelector.wrap(bytes4(0x00000000));

// --- Kernel permission skip flags ---
PassFlag constant SKIP_USEROP = PassFlag.wrap(0x0001);
PassFlag constant SKIP_SIGNATURE = PassFlag.wrap(0x0002);

// --- Kernel validation modes ---
ValidationMode constant VALIDATION_MODE_DEFAULT = ValidationMode.wrap(0x00);
ValidationMode constant VALIDATION_MODE_ENABLE = ValidationMode.wrap(0x01);
ValidationMode constant VALIDATION_MODE_INSTALL = ValidationMode.wrap(0x02);

// --- Kernel validation types ---
ValidationType constant VALIDATION_TYPE_ROOT = ValidationType.wrap(0x00);
ValidationType constant VALIDATION_TYPE_VALIDATOR = ValidationType.wrap(0x01);
ValidationType constant VALIDATION_TYPE_PERMISSION = ValidationType.wrap(0x02);

// --- storage slots ---
// bytes32(uint256(keccak256('kernel.v3.selector')) - 1)
bytes32 constant SELECTOR_MANAGER_STORAGE_SLOT = 0x7c341349a4360fdd5d5bc07e69f325dc6aaea3eb018b3e0ea7e53cc0bb0d6f3b;
// bytes32(uint256(keccak256('kernel.v3.executor')) - 1)
bytes32 constant EXECUTOR_MANAGER_STORAGE_SLOT = 0x1bbee3173dbdc223633258c9f337a0fff8115f206d302bea0ed3eac003b68b86;
// bytes32(uint256(keccak256('kernel.v3.hook')) - 1)
bytes32 constant HOOK_MANAGER_STORAGE_SLOT = 0x4605d5f70bb605094b2e761eccdc27bed9a362d8612792676bf3fb9b12832ffc;
// bytes32(uint256(keccak256('kernel.v3.validation')) - 1)
bytes32 constant VALIDATION_MANAGER_STORAGE_SLOT = 0x7bcaa2ced2a71450ed5a9a1b4848e8e5206dbc3f06011e595f7f55428cc6f84f;
bytes32 constant ERC1967_IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

// --- Kernel validation nonce incremental size limit ---
uint32 constant MAX_NONCE_INCREMENT_SIZE = 10;

// -- EIP712 type hash ---
bytes32 constant ENABLE_TYPE_HASH = 0xb17ab1224aca0d4255ef8161acaf2ac121b8faa32a4b2258c912cc5f8308c505;
bytes32 constant KERNEL_WRAPPER_TYPE_HASH = 0x1547321c374afde8a591d972a084b071c594c275e36724931ff96c25f2999c83;

// --- ERC constants ---
// ERC4337 constants
uint256 constant SIG_VALIDATION_FAILED_UINT = 1;
uint256 constant SIG_VALIDATION_SUCCESS_UINT = 0;
ValidationData constant SIG_VALIDATION_FAILED = ValidationData.wrap(SIG_VALIDATION_FAILED_UINT);

// ERC-1271 constants
bytes4 constant ERC1271_MAGICVALUE = 0x1626ba7e;
bytes4 constant ERC1271_INVALID = 0xffffffff;

uint256 constant MODULE_TYPE_VALIDATOR = 1;
uint256 constant MODULE_TYPE_EXECUTOR = 2;
uint256 constant MODULE_TYPE_FALLBACK = 3;
uint256 constant MODULE_TYPE_HOOK = 4;
uint256 constant MODULE_TYPE_POLICY = 5;
uint256 constant MODULE_TYPE_SIGNER = 6;

File 9 of 9 : Structs.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

struct Execution {
    address target;
    uint256 value;
    bytes callData;
}

Settings
{
  "remappings": [
    "ds-test/=lib/kernel_v3/lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "kernel/=lib/kernel_v3/src/",
    "solady/=lib/kernel_v3/lib/solady/src/",
    "ExcessivelySafeCall/=lib/kernel_v3/lib/ExcessivelySafeCall/src/",
    "kernel_v3/=lib/kernel_v3/"
  ],
  "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

Contract ABI

[{"inputs":[{"internalType":"address","name":"smartAccount","type":"address"}],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"CallViolatesParamRule","type":"error"},{"inputs":[],"name":"CallViolatesValueRule","type":"error"},{"inputs":[],"name":"InvalidCallData","type":"error"},{"inputs":[],"name":"InvalidCallType","type":"error"},{"inputs":[{"internalType":"address","name":"smartAccount","type":"address"}],"name":"NotInitialized","type":"error"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"checkSignaturePolicy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"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":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation","name":"userOp","type":"tuple"}],"name":"checkUserOpPolicy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bytes32","name":"permissionHash","type":"bytes32"},{"internalType":"address","name":"","type":"address"}],"name":"encodedPermissions","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"isInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"isModuleType","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onInstall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onUninstall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"address","name":"","type":"address"}],"name":"status","outputs":[{"internalType":"enum Status","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"usedIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

6080806040523461001657611cd9908161001c8239f35b600080fdfe608080604052600436101561001357600080fd5b60003560e01c908163244d6cb214610a2357508063309bfb76146109ad5780636d61fe70146104505780637129edce146102a25780638a91b0e3146101f5578063d60b347f146101b9578063d8ed2b3c1461014f578063ecd059611461012f5763ffbb39f81461008257600080fd5b3461012a57606036600319011261012a576044356001600160a01b0381169081900361012a57600435600052602090600282526040600020602435600052825260406000209060005281526100da6040600020610b43565b604051828193825282519081818401526000935b828510610111575050604092506000838284010152601f80199101168101030190f35b84810182015186860160400152938101938593506100ee565b600080fd5b3461012a57602036600319011261012a5760206040516005600435148152f35b3461012a57604036600319011261012a57610168610a6f565b600435600052600160205260406000209060018060a01b031660005260205260ff6040600020541660405160038210156101a3576020918152f35b634e487b7160e01b600052602160045260246000fd5b3461012a57602036600319011261012a576001600160a01b036101da610a59565b16600052600060205260206040600020541515604051908152f35b60208060031936011261012a576004356001600160401b03811161012a57610221903690600401610a85565b821161012a5735908160005260018152604060002033600052815260ff6040600020541660038110156101a35760010361012a5760009182526001815260408220338352815260408220600260ff198254161790555260406000208054801561028c57600019019055005b634e487b7160e01b600052601160045260246000fd5b60031960403682011261012a57600435906024356001600160401b03811161012a576101208160040192823603011261012a57606401906102e38282610c1d565b60041161012a57631651a3ad60e01b90356001600160e01b0319160161012a5761030d8282610c1d565b60249391931161012a5761032091610c1d565b5060248101350160248101906004808201359360ff60f81b918291013516801560001461038557505050610362929161035891610cf2565b92909193336117de565b15610373575b602060405160008152f35b60405163016754b960e61b8152600490fd5b919391600160f81b81036104085750505035016024604482019101359160005b8381106103b55750505050610368565b6103fb6103cb6103c6838787610c4f565b610c87565b6103e36103d9848888610c4f565b6040810190610c1d565b9060206103f1868a8a610c4f565b01359286336112d6565b15610373576001016103a5565b919493500361043e576104289261041e91610cf2565b9290919333610d82565b6103685760405163016754b960e61b8152600490fd5b6040516339d2eb5560e01b8152600490fd5b602036600319011261012a576004356001600160401b03811161012a5761047b903690600401610a85565b60201161012a578035600052600160205260406000203360005260205260ff6040600020541660038110156101a35761012a576000602082013582015b6020810135821061050557823560005260016020526040600020336000526020526040600020600160ff19825416179055600060205260406000208054600019811461028c576001019055005b61051782602083013560408401610c9b565b3560ff60f81b811680910361012a57610542602061053c858286013560408701610c9b565b01610c87565b6040610555856020860135838701610c9b565b013563ffffffff60e01b811680910361012a5760405191602083019384526bffffffffffffffffffffffff199060601b16602183015260358201526019815261059d81610b07565b519020833560005260026020526040600020816000526020526040600020336000526020526105d0604060002054610ab2565b6109685760005b6105f66105ec85602086013560408701610c9b565b6080810190610cbd565b90508110156106c35761061e816106186105ec87602088013560408901610c9b565b90610c4f565b35600781101561012a57600603610638575b6001016105d7565b6001610660610656836106186105ec8960208a013560408b01610c9b565b6040810190610cbd565b905003156106305760405162461bcd60e51b815260206004820152602d60248201527f6f6e6c79204f6e654f6620636f6e646974696f6e2063616e2068617665206d7560448201526c6c7469706c6520706172616d7360981b6064820152608490fd5b50929160606106da82602085013560408601610c9b565b0135936106f26105ec83602086013560408701610c9b565b958660405197889260608401906020850152604080850152526080820160808260051b8401019380926000915b81831061088e57505050505061073d9103601f198101875286610b22565b83356000526002602052604060002090600052602052604060002033600052602052604060002084516001600160401b0381116108785761077e8254610ab2565b601f8111610834575b506020601f82116001146107ca57819060019596976000926107bf575b5050600019600383901b1c191690841b1790555b01906104b8565b0151905087806107a4565b601f198216968360005260206000209760005b81811061081c5750916001969798918488959410610803575b505050811b0190556107b8565b015160001960f88460031b161c191690558780806107f6565b92986020600181928c8601518155019a0193016107dd565b826000526020600020601f830160051c810160208410610871575b601f830160051c82018110610865575050610787565b6000815560010161084f565b508061084f565b634e487b7160e01b600052604160045260246000fd5b909192939450607f198b87030184528435605e198236030181121561012a57600782820135101561012a5780820180358852602001356001600160401b038116810361012a576001600160401b03166020880152601e1982820136030160408383010135121561012a578101604081013501956001600160401b0387351161012a57863560051b3603602088011361012a5760606040820181905287359082018190526001600160fb1b031061012a5760208060806001938f9a803560051b848201848401373560051b010198970195019301919061071f565b60405162461bcd60e51b815260206004820152601860248201527f6475706c6963617465207065726d697373696f6e4861736800000000000000006044820152606490fd5b3461012a57608036600319011261012a576109c6610a6f565b506064356001600160401b03811161012a576109e6903690600401610a85565b5050600435600052600160205260406000203360005260205260ff6040600020541660038110156101a35760010361012a57602060405160008152f35b3461012a57602036600319011261012a576020906001600160a01b03610a47610a59565b16600052600082526040600020548152f35b600435906001600160a01b038216820361012a57565b602435906001600160a01b038216820361012a57565b9181601f8401121561012a578235916001600160401b03831161012a576020838186019501011161012a57565b90600182811c92168015610ae2575b6020831014610acc57565b634e487b7160e01b600052602260045260246000fd5b91607f1691610ac1565b606081019081106001600160401b0382111761087857604052565b604081019081106001600160401b0382111761087857604052565b90601f801991011681019081106001600160401b0382111761087857604052565b90604051918260008254610b5681610ab2565b90818452602094600191600181169081600014610bc65750600114610b87575b505050610b8592500383610b22565b565b600090815285812095935091905b818310610bae575050610b859350820101388080610b76565b85548884018501529485019487945091830191610b95565b92505050610b8594925060ff191682840152151560051b820101388080610b76565b9093929384831161012a57841161012a578101920390565b359060208110610c0e575090565b6000199060200360031b1b1690565b903590601e198136030182121561012a57018035906001600160401b03821161012a5760200191813603831361012a57565b9190811015610c715760051b81013590605e198136030182121561012a570190565b634e487b7160e01b600052603260045260246000fd5b356001600160a01b038116810361012a5790565b9190811015610c715760051b81013590609e198136030182121561012a570190565b903590601e198136030182121561012a57018035906001600160401b03821161012a57602001918160051b3603831361012a57565b908060141161012a57813560601c928160341161012a57601483013592603401916033190190565b6001600160401b0381116108785760051b60200190565b805115610c715760200190565b8051821015610c715760209160051b010190565b906001600160401b0380921660040191821161028c57565b9060206001600160401b038093160191821161028c57565b91949293929190836112bc576000955b6040516001600160f81b03196020820181815260609390931b6001600160601b03191660218301526001600160e01b03199098166035820181905260198252979190610ddd81610b07565b51902082600052600260205260406000209060005260205260406000209260018060a01b03169283600052602052610e186040600020610b43565b96875115611257575b5050505083511561124557835184019060408583031261012a576020850151916040860151906001600160401b03821161012a5760208101603f83890101121561012a5760208288010151610e7581610d1a565b97610e83604051998a610b22565b81895260208901936020840160408460051b83850101011161012a57604081830101945b60408460051b8385010101861061114d575050505050501161113b5760005b835181101561113257610ed98185610d3e565b51610f1d610f17602083016001600160401b0380610f0d610f0882610f0081875116610d52565b955116610d52565b610d6a565b1691168688610be8565b90610c00565b815190600791828110156101a357158061111b575b15610f435750505050505050600090565b825191808310156101a357600180931480611104575b15610f6b575050505050505050600090565b8351818110156101a357600214806110ed575b15610f90575050505050505050600090565b8351818110156101a357600314806110d7575b15610fb5575050505050505050600090565b8351818110156101a3576004809114806110c1575b15610fdd57505050505050505050600090565b8451828110156110ac5760051480611096575b1561100357505050505050505050600090565b8451918210156110815750600614611021575b505050600101610ec6565b60009260400183835b611049575b505050501561104057388080611016565b50505050600090565b8151805182101561107b578161105e91610d3e565b51831461106d5783018361102a565b50505090503880808061102f565b5061102f565b602190634e487b7160e01b6000525260246000fd5b506110a46040860151610d31565b518314610ff0565b602182634e487b7160e01b6000525260246000fd5b506110cf6040860151610d31565b518311610fca565b506110e56040850151610d31565b518210610fa3565b506110fb6040850151610d31565b51821015610f7e565b506111126040850151610d31565b51821115610f59565b506111296040840151610d31565b51811415610f32565b50505050600190565b604051631ed604b560e21b8152600490fd5b85516001600160401b03811161012a57838301016060818703601f19011261012a576040519061117c82610aec565b6040810151600781101561012a57825260608101516001600160401b038116810361012a57602083015260808101516001600160401b03811161012a5760208801605f82840101121561012a5760408183010151906111da82610d1a565b926111e86040519485610b22565b828452602084019160208b0160608560051b83850101011161012a57606081830101925b60608560051b838501010184106112355750505050506040820152815260209586019501610ea7565b835181526020938401930161120c565b604051631c49f4d160e01b8152600490fd5b90919293965060405190602082019283526000602183015260358201526019815261128181610b07565b5190209060005260026020526040600020906000526020526040600020906000526020526112b26040600020610b43565b9238808080610e21565b8360041161012a5784356001600160e01b03191695610d92565b929392906000846117c057506000925b60405160006020820190815260609290921b6001600160601b03191660218201526001600160e01b03198516603582015261132e81603981015b03601f198101835282610b22565b51902081600052600260205260406000209060005260205260406000209160018060a01b031691826000526020526113696040600020610b43565b92835115611755575b50505080511561124557805181019360408286031261012a576020820151916040810151906001600160401b03821161012a5760208701603f83830101121561012a57602082820101516113c581610d1a565b976113d3604051998a610b22565b81895260208901906020810160408460051b87870101011161012a57604085850101915b60408460051b87870101018310611632575050505050501161113b5760005b8351811015611132576114298185610d3e565b51611450610f17602083016001600160401b0380610f0d610f0882610f0081875116610d52565b815190600791828110156101a357158061161b575b156114765750505050505050600090565b825191808310156101a357600180931480611604575b1561149e575050505050505050600090565b8351818110156101a357600214806115ed575b156114c3575050505050505050600090565b8351818110156101a357600314806115d7575b156114e8575050505050505050600090565b8351818110156101a3576004809114806115c1575b1561151057505050505050505050600090565b8451828110156110ac57600514806115ab575b1561153657505050505050505050600090565b8451918210156110815750600614611554575b505050600101611416565b60009260400183835b611573575b505050501561104057388080611549565b815180518210156115a5578161158891610d3e565b5183146115975783018361155d565b505050905038808080611562565b50611562565b506115b96040860151610d31565b518314611523565b506115cf6040860151610d31565b5183116114fd565b506115e56040850151610d31565b5182106114d6565b506115fb6040850151610d31565b518210156114b1565b506116126040850151610d31565b5182111561148c565b506116296040840151610d31565b51811415611465565b82516001600160401b03811161012a57606086880182018403601f19011261012a576040519061166182610aec565b604081898901010151600781101561012a5782526060818989010101516001600160401b038116810361012a576020830152608081898901010151906001600160401b03821161012a5760208501605f83838c8c01010101121561012a57604082828b8b0101010151906116d482610d1a565b926116e26040519485610b22565b82845260208401918b60608c848460208d01948960051b9301010101011161012a578b928b60608484878401010101915b60608760051b8686898601010101018310611745575050505050604084019290925250508152602092830192016113f7565b8251815260209283019201611713565b909192506040516020810191600083526000602183015263ffffffff60e01b1660358201526019815261178781610b07565b5190209060005260026020526040600020906000526020526040600020906000526020526117b86040600020610b43565b388080611372565b846004116117db575084356001600160e01b031916926112e6565b80fd5b92939290600084611cbe57506000925b60405160006020820190815260609290921b6001600160601b03191660218201526001600160e01b03198516603582015261182c8160398101611320565b51902081600052600260205260406000209060005260205260406000209160018060a01b031691826000526020526118676040600020610b43565b92835115611c53575b50505080511561124557805181019360408286031261012a576020820151916040810151906001600160401b03821161012a5760208701603f83830101121561012a57602082820101516118c381610d1a565b976118d1604051998a610b22565b81895260208901906020810160408460051b87870101011161012a57604085850101915b60408460051b87870101018310611b30575050505050501161113b5760005b8351811015611132576119278185610d3e565b5161194e610f17602083016001600160401b0380610f0d610f0882610f0081875116610d52565b815190600791828110156101a3571580611b19575b156119745750505050505050600090565b825191808310156101a357600180931480611b02575b1561199c575050505050505050600090565b8351818110156101a35760021480611aeb575b156119c1575050505050505050600090565b8351818110156101a35760031480611ad5575b156119e6575050505050505050600090565b8351818110156101a357600480911480611abf575b15611a0e57505050505050505050600090565b8451828110156110ac5760051480611aa9575b15611a3457505050505050505050600090565b8451918210156110815750600614611a52575b505050600101611914565b60009260400183835b611a71575b505050501561104057388080611a47565b81518051821015611aa35781611a8691610d3e565b518314611a9557830183611a5b565b505050905038808080611a60565b50611a60565b50611ab76040860151610d31565b518314611a21565b50611acd6040860151610d31565b5183116119fb565b50611ae36040850151610d31565b5182106119d4565b50611af96040850151610d31565b518210156119af565b50611b106040850151610d31565b5182111561198a565b50611b276040840151610d31565b51811415611963565b82516001600160401b03811161012a57606086880182018403601f19011261012a5760405190611b5f82610aec565b604081898901010151600781101561012a5782526060818989010101516001600160401b038116810361012a576020830152608081898901010151906001600160401b03821161012a5760208501605f83838c8c01010101121561012a57604082828b8b010101015190611bd282610d1a565b92611be06040519485610b22565b82845260208401918b60608c848460208d01948960051b9301010101011161012a578b928b60608484878401010101915b60608760051b8686898601010101018310611c43575050505050604084019290925250508152602092830192016118f5565b8251815260209283019201611c11565b909192506040516020810191600083526000602183015263ffffffff60e01b16603582015260198152611c8581610b07565b519020906000526002602052604060002090600052602052604060002090600052602052611cb66040600020610b43565b388080611870565b846004116117db575084356001600160e01b031916926117ee56

Deployed Bytecode

0x608080604052600436101561001357600080fd5b60003560e01c908163244d6cb214610a2357508063309bfb76146109ad5780636d61fe70146104505780637129edce146102a25780638a91b0e3146101f5578063d60b347f146101b9578063d8ed2b3c1461014f578063ecd059611461012f5763ffbb39f81461008257600080fd5b3461012a57606036600319011261012a576044356001600160a01b0381169081900361012a57600435600052602090600282526040600020602435600052825260406000209060005281526100da6040600020610b43565b604051828193825282519081818401526000935b828510610111575050604092506000838284010152601f80199101168101030190f35b84810182015186860160400152938101938593506100ee565b600080fd5b3461012a57602036600319011261012a5760206040516005600435148152f35b3461012a57604036600319011261012a57610168610a6f565b600435600052600160205260406000209060018060a01b031660005260205260ff6040600020541660405160038210156101a3576020918152f35b634e487b7160e01b600052602160045260246000fd5b3461012a57602036600319011261012a576001600160a01b036101da610a59565b16600052600060205260206040600020541515604051908152f35b60208060031936011261012a576004356001600160401b03811161012a57610221903690600401610a85565b821161012a5735908160005260018152604060002033600052815260ff6040600020541660038110156101a35760010361012a5760009182526001815260408220338352815260408220600260ff198254161790555260406000208054801561028c57600019019055005b634e487b7160e01b600052601160045260246000fd5b60031960403682011261012a57600435906024356001600160401b03811161012a576101208160040192823603011261012a57606401906102e38282610c1d565b60041161012a57631651a3ad60e01b90356001600160e01b0319160161012a5761030d8282610c1d565b60249391931161012a5761032091610c1d565b5060248101350160248101906004808201359360ff60f81b918291013516801560001461038557505050610362929161035891610cf2565b92909193336117de565b15610373575b602060405160008152f35b60405163016754b960e61b8152600490fd5b919391600160f81b81036104085750505035016024604482019101359160005b8381106103b55750505050610368565b6103fb6103cb6103c6838787610c4f565b610c87565b6103e36103d9848888610c4f565b6040810190610c1d565b9060206103f1868a8a610c4f565b01359286336112d6565b15610373576001016103a5565b919493500361043e576104289261041e91610cf2565b9290919333610d82565b6103685760405163016754b960e61b8152600490fd5b6040516339d2eb5560e01b8152600490fd5b602036600319011261012a576004356001600160401b03811161012a5761047b903690600401610a85565b60201161012a578035600052600160205260406000203360005260205260ff6040600020541660038110156101a35761012a576000602082013582015b6020810135821061050557823560005260016020526040600020336000526020526040600020600160ff19825416179055600060205260406000208054600019811461028c576001019055005b61051782602083013560408401610c9b565b3560ff60f81b811680910361012a57610542602061053c858286013560408701610c9b565b01610c87565b6040610555856020860135838701610c9b565b013563ffffffff60e01b811680910361012a5760405191602083019384526bffffffffffffffffffffffff199060601b16602183015260358201526019815261059d81610b07565b519020833560005260026020526040600020816000526020526040600020336000526020526105d0604060002054610ab2565b6109685760005b6105f66105ec85602086013560408701610c9b565b6080810190610cbd565b90508110156106c35761061e816106186105ec87602088013560408901610c9b565b90610c4f565b35600781101561012a57600603610638575b6001016105d7565b6001610660610656836106186105ec8960208a013560408b01610c9b565b6040810190610cbd565b905003156106305760405162461bcd60e51b815260206004820152602d60248201527f6f6e6c79204f6e654f6620636f6e646974696f6e2063616e2068617665206d7560448201526c6c7469706c6520706172616d7360981b6064820152608490fd5b50929160606106da82602085013560408601610c9b565b0135936106f26105ec83602086013560408701610c9b565b958660405197889260608401906020850152604080850152526080820160808260051b8401019380926000915b81831061088e57505050505061073d9103601f198101875286610b22565b83356000526002602052604060002090600052602052604060002033600052602052604060002084516001600160401b0381116108785761077e8254610ab2565b601f8111610834575b506020601f82116001146107ca57819060019596976000926107bf575b5050600019600383901b1c191690841b1790555b01906104b8565b0151905087806107a4565b601f198216968360005260206000209760005b81811061081c5750916001969798918488959410610803575b505050811b0190556107b8565b015160001960f88460031b161c191690558780806107f6565b92986020600181928c8601518155019a0193016107dd565b826000526020600020601f830160051c810160208410610871575b601f830160051c82018110610865575050610787565b6000815560010161084f565b508061084f565b634e487b7160e01b600052604160045260246000fd5b909192939450607f198b87030184528435605e198236030181121561012a57600782820135101561012a5780820180358852602001356001600160401b038116810361012a576001600160401b03166020880152601e1982820136030160408383010135121561012a578101604081013501956001600160401b0387351161012a57863560051b3603602088011361012a5760606040820181905287359082018190526001600160fb1b031061012a5760208060806001938f9a803560051b848201848401373560051b010198970195019301919061071f565b60405162461bcd60e51b815260206004820152601860248201527f6475706c6963617465207065726d697373696f6e4861736800000000000000006044820152606490fd5b3461012a57608036600319011261012a576109c6610a6f565b506064356001600160401b03811161012a576109e6903690600401610a85565b5050600435600052600160205260406000203360005260205260ff6040600020541660038110156101a35760010361012a57602060405160008152f35b3461012a57602036600319011261012a576020906001600160a01b03610a47610a59565b16600052600082526040600020548152f35b600435906001600160a01b038216820361012a57565b602435906001600160a01b038216820361012a57565b9181601f8401121561012a578235916001600160401b03831161012a576020838186019501011161012a57565b90600182811c92168015610ae2575b6020831014610acc57565b634e487b7160e01b600052602260045260246000fd5b91607f1691610ac1565b606081019081106001600160401b0382111761087857604052565b604081019081106001600160401b0382111761087857604052565b90601f801991011681019081106001600160401b0382111761087857604052565b90604051918260008254610b5681610ab2565b90818452602094600191600181169081600014610bc65750600114610b87575b505050610b8592500383610b22565b565b600090815285812095935091905b818310610bae575050610b859350820101388080610b76565b85548884018501529485019487945091830191610b95565b92505050610b8594925060ff191682840152151560051b820101388080610b76565b9093929384831161012a57841161012a578101920390565b359060208110610c0e575090565b6000199060200360031b1b1690565b903590601e198136030182121561012a57018035906001600160401b03821161012a5760200191813603831361012a57565b9190811015610c715760051b81013590605e198136030182121561012a570190565b634e487b7160e01b600052603260045260246000fd5b356001600160a01b038116810361012a5790565b9190811015610c715760051b81013590609e198136030182121561012a570190565b903590601e198136030182121561012a57018035906001600160401b03821161012a57602001918160051b3603831361012a57565b908060141161012a57813560601c928160341161012a57601483013592603401916033190190565b6001600160401b0381116108785760051b60200190565b805115610c715760200190565b8051821015610c715760209160051b010190565b906001600160401b0380921660040191821161028c57565b9060206001600160401b038093160191821161028c57565b91949293929190836112bc576000955b6040516001600160f81b03196020820181815260609390931b6001600160601b03191660218301526001600160e01b03199098166035820181905260198252979190610ddd81610b07565b51902082600052600260205260406000209060005260205260406000209260018060a01b03169283600052602052610e186040600020610b43565b96875115611257575b5050505083511561124557835184019060408583031261012a576020850151916040860151906001600160401b03821161012a5760208101603f83890101121561012a5760208288010151610e7581610d1a565b97610e83604051998a610b22565b81895260208901936020840160408460051b83850101011161012a57604081830101945b60408460051b8385010101861061114d575050505050501161113b5760005b835181101561113257610ed98185610d3e565b51610f1d610f17602083016001600160401b0380610f0d610f0882610f0081875116610d52565b955116610d52565b610d6a565b1691168688610be8565b90610c00565b815190600791828110156101a357158061111b575b15610f435750505050505050600090565b825191808310156101a357600180931480611104575b15610f6b575050505050505050600090565b8351818110156101a357600214806110ed575b15610f90575050505050505050600090565b8351818110156101a357600314806110d7575b15610fb5575050505050505050600090565b8351818110156101a3576004809114806110c1575b15610fdd57505050505050505050600090565b8451828110156110ac5760051480611096575b1561100357505050505050505050600090565b8451918210156110815750600614611021575b505050600101610ec6565b60009260400183835b611049575b505050501561104057388080611016565b50505050600090565b8151805182101561107b578161105e91610d3e565b51831461106d5783018361102a565b50505090503880808061102f565b5061102f565b602190634e487b7160e01b6000525260246000fd5b506110a46040860151610d31565b518314610ff0565b602182634e487b7160e01b6000525260246000fd5b506110cf6040860151610d31565b518311610fca565b506110e56040850151610d31565b518210610fa3565b506110fb6040850151610d31565b51821015610f7e565b506111126040850151610d31565b51821115610f59565b506111296040840151610d31565b51811415610f32565b50505050600190565b604051631ed604b560e21b8152600490fd5b85516001600160401b03811161012a57838301016060818703601f19011261012a576040519061117c82610aec565b6040810151600781101561012a57825260608101516001600160401b038116810361012a57602083015260808101516001600160401b03811161012a5760208801605f82840101121561012a5760408183010151906111da82610d1a565b926111e86040519485610b22565b828452602084019160208b0160608560051b83850101011161012a57606081830101925b60608560051b838501010184106112355750505050506040820152815260209586019501610ea7565b835181526020938401930161120c565b604051631c49f4d160e01b8152600490fd5b90919293965060405190602082019283526000602183015260358201526019815261128181610b07565b5190209060005260026020526040600020906000526020526040600020906000526020526112b26040600020610b43565b9238808080610e21565b8360041161012a5784356001600160e01b03191695610d92565b929392906000846117c057506000925b60405160006020820190815260609290921b6001600160601b03191660218201526001600160e01b03198516603582015261132e81603981015b03601f198101835282610b22565b51902081600052600260205260406000209060005260205260406000209160018060a01b031691826000526020526113696040600020610b43565b92835115611755575b50505080511561124557805181019360408286031261012a576020820151916040810151906001600160401b03821161012a5760208701603f83830101121561012a57602082820101516113c581610d1a565b976113d3604051998a610b22565b81895260208901906020810160408460051b87870101011161012a57604085850101915b60408460051b87870101018310611632575050505050501161113b5760005b8351811015611132576114298185610d3e565b51611450610f17602083016001600160401b0380610f0d610f0882610f0081875116610d52565b815190600791828110156101a357158061161b575b156114765750505050505050600090565b825191808310156101a357600180931480611604575b1561149e575050505050505050600090565b8351818110156101a357600214806115ed575b156114c3575050505050505050600090565b8351818110156101a357600314806115d7575b156114e8575050505050505050600090565b8351818110156101a3576004809114806115c1575b1561151057505050505050505050600090565b8451828110156110ac57600514806115ab575b1561153657505050505050505050600090565b8451918210156110815750600614611554575b505050600101611416565b60009260400183835b611573575b505050501561104057388080611549565b815180518210156115a5578161158891610d3e565b5183146115975783018361155d565b505050905038808080611562565b50611562565b506115b96040860151610d31565b518314611523565b506115cf6040860151610d31565b5183116114fd565b506115e56040850151610d31565b5182106114d6565b506115fb6040850151610d31565b518210156114b1565b506116126040850151610d31565b5182111561148c565b506116296040840151610d31565b51811415611465565b82516001600160401b03811161012a57606086880182018403601f19011261012a576040519061166182610aec565b604081898901010151600781101561012a5782526060818989010101516001600160401b038116810361012a576020830152608081898901010151906001600160401b03821161012a5760208501605f83838c8c01010101121561012a57604082828b8b0101010151906116d482610d1a565b926116e26040519485610b22565b82845260208401918b60608c848460208d01948960051b9301010101011161012a578b928b60608484878401010101915b60608760051b8686898601010101018310611745575050505050604084019290925250508152602092830192016113f7565b8251815260209283019201611713565b909192506040516020810191600083526000602183015263ffffffff60e01b1660358201526019815261178781610b07565b5190209060005260026020526040600020906000526020526040600020906000526020526117b86040600020610b43565b388080611372565b846004116117db575084356001600160e01b031916926112e6565b80fd5b92939290600084611cbe57506000925b60405160006020820190815260609290921b6001600160601b03191660218201526001600160e01b03198516603582015261182c8160398101611320565b51902081600052600260205260406000209060005260205260406000209160018060a01b031691826000526020526118676040600020610b43565b92835115611c53575b50505080511561124557805181019360408286031261012a576020820151916040810151906001600160401b03821161012a5760208701603f83830101121561012a57602082820101516118c381610d1a565b976118d1604051998a610b22565b81895260208901906020810160408460051b87870101011161012a57604085850101915b60408460051b87870101018310611b30575050505050501161113b5760005b8351811015611132576119278185610d3e565b5161194e610f17602083016001600160401b0380610f0d610f0882610f0081875116610d52565b815190600791828110156101a3571580611b19575b156119745750505050505050600090565b825191808310156101a357600180931480611b02575b1561199c575050505050505050600090565b8351818110156101a35760021480611aeb575b156119c1575050505050505050600090565b8351818110156101a35760031480611ad5575b156119e6575050505050505050600090565b8351818110156101a357600480911480611abf575b15611a0e57505050505050505050600090565b8451828110156110ac5760051480611aa9575b15611a3457505050505050505050600090565b8451918210156110815750600614611a52575b505050600101611914565b60009260400183835b611a71575b505050501561104057388080611a47565b81518051821015611aa35781611a8691610d3e565b518314611a9557830183611a5b565b505050905038808080611a60565b50611a60565b50611ab76040860151610d31565b518314611a21565b50611acd6040860151610d31565b5183116119fb565b50611ae36040850151610d31565b5182106119d4565b50611af96040850151610d31565b518210156119af565b50611b106040850151610d31565b5182111561198a565b50611b276040840151610d31565b51811415611963565b82516001600160401b03811161012a57606086880182018403601f19011261012a5760405190611b5f82610aec565b604081898901010151600781101561012a5782526060818989010101516001600160401b038116810361012a576020830152608081898901010151906001600160401b03821161012a5760208501605f83838c8c01010101121561012a57604082828b8b010101015190611bd282610d1a565b92611be06040519485610b22565b82845260208401918b60608c848460208d01948960051b9301010101011161012a578b928b60608484878401010101915b60608760051b8686898601010101018310611c43575050505050604084019290925250508152602092830192016118f5565b8251815260209283019201611c11565b909192506040516020810191600083526000602183015263ffffffff60e01b16603582015260198152611c8581610b07565b519020906000526002602052604060002090600052602052604060002090600052602052611cb66040600020610b43565b388080611870565b846004116117db575084356001600160e01b031916926117ee56

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.