ETH Price: $2,821.68 (+2.55%)

Contract

0x00000000561Dd60aEa485cDb26E4618B1E40Fd6E

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

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
168952712025-11-20 11:28:022 days ago1763638082  Contract Creation0 ETH

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Nexus

Compiler Version
v0.8.27+commit.40a35a09

Optimization Enabled:
Yes with 999 runs

Other Settings:
cancun EvmVersion
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// ──────────────────────────────────────────────────────────────────────────────
//     _   __    _  __
//    / | / /__ | |/ /_  _______
//   /  |/ / _ \|   / / / / ___/
//  / /|  /  __/   / /_/ (__  )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Accounts compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

import { BaseAccount } from "./base/BaseAccount.sol";
import { ModuleManager } from "./base/ModuleManager.sol";
import { ExecutionHelper } from "./base/ExecutionHelper.sol";
import { ComposableExecutionBase, ComposableExecution } from "../composability/ComposableExecutionBase.sol";
import { Initializable } from "../lib/nexus/Initializable.sol";
import { UUPSUpgradeable } from "solady/utils/UUPSUpgradeable.sol";
import { INexus } from "../interfaces/nexus/INexus.sol";
import { ExecLib } from "../lib/erc-7579/ExecLib.sol";
import { NonceLib } from "../lib/nexus/NonceLib.sol";
import { SentinelListLib, SENTINEL, ZERO_ADDRESS } from "sentinellist/SentinelList.sol";
import { EmergencyUninstall } from "../types/DataTypes.sol";
import { LibPREP } from "../lib/nexus/local/LibPREP.sol";
import { ECDSA } from "solady/utils/ECDSA.sol";
import { IValidator } from "erc7579/interfaces/IERC7579Module.sol";
import {
    MODULE_TYPE_VALIDATOR,
    MODULE_TYPE_EXECUTOR,
    MODULE_TYPE_FALLBACK,
    MODULE_TYPE_HOOK,
    SUPPORTS_ERC7739
} from "../types/Constants.sol";
import {
    ModeLib,
    ExecutionMode,
    ExecType,
    CallType,
    CALLTYPE_BATCH,
    CALLTYPE_SINGLE,
    CALLTYPE_DELEGATECALL,
    EXECTYPE_DEFAULT,
    EXECTYPE_TRY
} from "../lib/erc-7579/ModeLib.sol";
import { PackedUserOperation } from "account-abstraction/interfaces/PackedUserOperation.sol";

/// @title Nexus - Smart Account
/// @notice This contract integrates various functionalities to handle modular smart accounts compliant with ERC-7579
/// and
/// ERC-4337 standards.
/// @dev Comprehensive suite of methods for managing smart accounts, integrating module management, execution
/// management,
/// and upgradability via UUPS.
/// @author @livingrockrises | Biconomy | [email protected]
/// @author @aboudjem | Biconomy | [email protected]
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady
contract Nexus is INexus, BaseAccount, ExecutionHelper, ModuleManager, UUPSUpgradeable, ComposableExecutionBase {
    using ModeLib for ExecutionMode;
    using ExecLib for bytes;
    using NonceLib for uint256;
    using SentinelListLib for SentinelListLib.SentinelList;

    /// @dev The timelock period for emergency hook uninstallation.
    uint256 internal constant _EMERGENCY_TIMELOCK = 1 days;

    /// @dev The event emitted when an emergency hook uninstallation is initiated.
    event EmergencyHookUninstallRequest(address hook, uint256 timestamp);

    /// @dev The event emitted when an emergency hook uninstallation request is reset.
    event EmergencyHookUninstallRequestReset(address hook, uint256 timestamp);

    /// @notice Initializes the smart account with the specified entry point.
    constructor(
        address anEntryPoint,
        address defaultValidator,
        bytes memory initData
    )
        ModuleManager(defaultValidator, initData)
    {
        require(address(anEntryPoint) != address(0), EntryPointCanNotBeZero());
        _ENTRYPOINT = anEntryPoint;
    }

    /// @notice Validates a user operation against a specified validator, extracted from the operation's nonce.
    /// @param op The user operation to validate, encapsulating all transaction details.
    /// @param userOpHash Hash of the user operation data, used for signature validation.
    /// @param missingAccountFunds Funds missing from the account's deposit necessary for transaction execution.
    /// This can be zero if covered by a paymaster or if sufficient deposit exists.
    /// @return validationData Encoded validation result or failure, propagated from the validator module.
    /// - Encoded format in validationData:
    ///     - First 20 bytes: Address of the Validator module, to which the validation task is forwarded.
    ///       The validator module returns:
    ///         - `SIG_VALIDATION_SUCCESS` (0) indicates successful validation.
    ///         - `SIG_VALIDATION_FAILED` (1) indicates signature validation failure.
    /// @dev Expects the validator's address to be encoded in the upper 96 bits of the user operation's nonce.
    /// This method forwards the validation task to the extracted validator module address.
    /// @dev The entryPoint calls this function. If validation fails, it returns `VALIDATION_FAILED` (1) otherwise `0`.
    /// @dev Features Module Enable Mode.
    /// This Module Enable Mode flow is intended for the module acting as the validator
    /// for the user operation that triggers the Module Enable Flow. Otherwise, a call to
    /// `Nexus.installModule` should be included in `userOp.callData`.
    function validateUserOp(
        PackedUserOperation calldata op,
        bytes32 userOpHash,
        uint256 missingAccountFunds
    )
        external
        virtual
        payPrefund(missingAccountFunds)
        onlyEntryPoint
        returns (uint256 validationData)
    {
        address validator;
        PackedUserOperation memory userOp = op;

        if (op.nonce.isValidateMode()) {
            // do nothing special. This is introduced
            // to quickly identify the most commonly used
            // mode which is validate mode
            // and avoid checking two above conditions
        } else if (op.nonce.isModuleEnableMode()) {
            // if it is module enable mode, we need to enable the module first
            // and get the cleaned signature
            userOp.signature = _enableMode(userOpHash, op.signature);
        } else if (op.nonce.isPrepMode()) {
            // PREP Mode. Authorize prep signature
            // and initialize the account
            // PREP mode is only used for the uninited PREPs
            require(!isInitialized(), AccountAlreadyInitialized());
            bytes calldata initData;
            (userOp.signature, initData) = _handlePREP(op.signature);
            _initializeAccount(initData);
        }
        validator = _handleValidator(op.nonce.getValidator());
        (userOpHash, userOp.signature) = _withPreValidationHook(userOpHash, userOp, missingAccountFunds);
        validationData = IValidator(validator).validateUserOp(userOp, userOpHash);
    }

    /// @notice Executes transactions in single or batch modes as specified by the execution mode.
    /// @param mode The execution mode detailing how transactions should be handled (single, batch, default, try/catch).
    /// @param executionCalldata The encoded transaction data to execute.
    /// @dev This function handles transaction execution flexibility and is protected by the `onlyEntryPoint` modifier.
    /// @dev This function also goes through hook checks via withHook modifier.
    function execute(ExecutionMode mode, bytes calldata executionCalldata) external payable onlyEntryPoint withHook {
        (CallType callType, ExecType execType) = mode.decodeBasic();
        if (callType == CALLTYPE_SINGLE) {
            _handleSingleExecution(executionCalldata, execType);
        } else if (callType == CALLTYPE_BATCH) {
            _handleBatchExecution(executionCalldata, execType);
        } else if (callType == CALLTYPE_DELEGATECALL) {
            _handleDelegateCallExecution(executionCalldata, execType);
        } else {
            revert UnsupportedCallType(callType);
        }
    }

    /// @notice Executes transactions from an executor module, supporting both single and batch transactions.
    /// @param mode The execution mode (single or batch, default or try).
    /// @param executionCalldata The transaction data to execute.
    /// @return returnData The results of the transaction executions, which may include errors in try mode.
    /// @dev This function is callable only by an executor module and goes through hook checks.
    function executeFromExecutor(
        ExecutionMode mode,
        bytes calldata executionCalldata
    )
        external
        payable
        onlyExecutorModule
        withHook
        returns (bytes[] memory returnData)
    {
        (CallType callType, ExecType execType) = mode.decodeBasic();
        // check if calltype is batch or single or delegate call
        if (callType == CALLTYPE_SINGLE) {
            returnData = _handleSingleExecutionAndReturnData(executionCalldata, execType);
        } else if (callType == CALLTYPE_BATCH) {
            returnData = _handleBatchExecutionAndReturnData(executionCalldata, execType);
        } else if (callType == CALLTYPE_DELEGATECALL) {
            returnData = _handleDelegateCallExecutionAndReturnData(executionCalldata, execType);
        } else {
            revert UnsupportedCallType(callType);
        }
    }

    /// @notice Executes a user operation via a call using the contract's context.
    /// @param userOp The user operation to execute, containing transaction details.
    /// @param - Hash of the user operation.
    /// @dev Only callable by the EntryPoint. Decodes the user operation calldata, skipping the first four bytes, and
    /// executes the inner call.
    function executeUserOp(
        PackedUserOperation calldata userOp,
        bytes32
    )
        external
        payable
        virtual
        onlyEntryPoint
        withHook
    {
        bytes calldata callData = userOp.callData[4:];
        (bool success,) = address(this).delegatecall(callData);
        assembly {
            if iszero(success) {
                // revert ExecutionFailed()
                mstore(0x00, 0xacfdb444)
                revert(0x1c, 0x04)
            }
        }
    }

    /// @notice Executes a composable execution
    /// See more about composability here: https://docs.biconomy.io/composability
    /// @param executions The composable executions to execute
    function executeComposable(ComposableExecution[] calldata executions)
        external
        payable
        override
        onlyEntryPoint
        withHook
    {
        _executeComposable(executions);
    }

    /// @notice Executes a call to a target address with specified value and data.
    /// @param to The address to execute the action on
    /// @param value The value to send with the action
    /// @param data The data to send with the action
    /// @return result The result of the execution
    function _executeAction(address to, uint256 value, bytes memory data) internal override returns (bytes memory) {
        return _executeMemory(to, value, data);
    }

    /// @notice Installs a new module to the smart account.
    /// @param moduleTypeId The type identifier of the module being installed, which determines its role:
    /// - 1 for Validator
    /// - 2 for Executor
    /// - 3 for Fallback
    /// - 4 for Hook
    /// - 8 for 1271 Prevalidation Hook
    /// - 9 for 4337 Prevalidation Hook
    /// @param module The address of the module to install.
    /// @param initData Initialization data for the module.
    /// @dev This function can only be called by the EntryPoint or the account itself for security reasons.
    /// @dev This function goes through hook checks via withHook modifier through internal function _installModule.
    function installModule(
        uint256 moduleTypeId,
        address module,
        bytes calldata initData
    )
        external
        payable
        virtual
        override
        onlyEntryPointOrSelf
    {
        _installModule(moduleTypeId, module, initData);
        assembly {
            // emit ModuleInstalled(moduleTypeId, module)
            mstore(0x00, moduleTypeId)
            mstore(0x20, module)
            log1(0x00, 0x40, 0xd21d0b289f126c4b473ea641963e766833c2f13866e4ff480abd787c100ef123)
        }
    }

    /// @notice Uninstalls a module from the smart account.
    /// @param moduleTypeId The type ID of the module to be uninstalled, matching the installation type:
    /// - 1 for Validator
    /// - 2 for Executor
    /// - 3 for Fallback
    /// - 4 for Hook
    /// - 8 for 1271 Prevalidation Hook
    /// - 9 for 4337 Prevalidation Hook
    /// @dev Attention: All the underlying functions _uninstall[ModuleType] are calling module.onInstall() method.
    /// If the module is malicious (which is not likely because such a module won't be attested), it can prevent
    /// itself from being uninstalled by spending all gas in the onUninstall() method. Then 1/64 gas left can
    /// be not enough to finish the uninstallation, assuming there may be hook postCheck() call.
    /// In this highly unlikely scenario, user will have to uninstall the hook, then uninstall the malicious
    /// module => in this case 1/64 gas left should be enough to finish the uninstallation.
    /// @param module The address of the module to uninstall.
    /// @param deInitData De-initialization data for the module.
    /// @dev Ensures that the operation is authorized and valid before proceeding with the uninstallation.
    function uninstallModule(
        uint256 moduleTypeId,
        address module,
        bytes calldata deInitData
    )
        external
        payable
        onlyEntryPointOrSelf
        withHook
    {
        require(_isModuleInstalled(moduleTypeId, module, deInitData), ModuleNotInstalled(moduleTypeId, module));

        if (moduleTypeId == MODULE_TYPE_VALIDATOR) {
            _uninstallValidator(module, deInitData);
            _checkInitializedValidators();
        } else if (moduleTypeId == MODULE_TYPE_EXECUTOR) {
            _uninstallExecutor(module, deInitData);
        } else if (moduleTypeId == MODULE_TYPE_FALLBACK) {
            _uninstallFallbackHandler(module, deInitData);
        } else if (moduleTypeId == MODULE_TYPE_HOOK || _isPrevalidationHookType(moduleTypeId)) {
            _uninstallHook(module, moduleTypeId, deInitData);
        }
        emit ModuleUninstalled(moduleTypeId, module);
    }

    function emergencyUninstallHook(EmergencyUninstall calldata data, bytes calldata signature) external payable {
        // Validate the signature
        _checkEmergencyUninstallSignature(data, signature);
        // Parse uninstall data
        (uint256 hookType, address hook, bytes calldata deInitData) = (data.hookType, data.hook, data.deInitData);

        // Validate the hook is of a supported type and is installed
        require(hookType == MODULE_TYPE_HOOK || _isPrevalidationHookType(hookType), UnsupportedModuleType(hookType));
        require(_isModuleInstalled(hookType, hook, deInitData), ModuleNotInstalled(hookType, hook));

        // Get the account storage
        AccountStorage storage accountStorage = _getAccountStorage();
        uint256 hookTimelock = accountStorage.emergencyUninstallTimelock[hook];

        if (hookTimelock == 0) {
            // if the timelock hasnt been initiated, initiate it
            accountStorage.emergencyUninstallTimelock[hook] = block.timestamp;
            emit EmergencyHookUninstallRequest(hook, block.timestamp);
        } else if (block.timestamp >= hookTimelock + 3 * _EMERGENCY_TIMELOCK) {
            // if the timelock has been left for too long, reset it
            accountStorage.emergencyUninstallTimelock[hook] = block.timestamp;
            emit EmergencyHookUninstallRequestReset(hook, block.timestamp);
        } else if (block.timestamp >= hookTimelock + _EMERGENCY_TIMELOCK) {
            // if the timelock expired, clear it and uninstall the hook
            accountStorage.emergencyUninstallTimelock[hook] = 0;
            _uninstallHook(hook, hookType, deInitData);
            emit ModuleUninstalled(hookType, hook);
        } else {
            // if the timelock is initiated but not expired, revert
            revert EmergencyTimeLockNotExpired();
        }
    }

    /// @notice Initializes the smart account with the specified initialization data.
    /// @param initData The initialization data for the smart account.
    /// @dev This function can only be called by the account itself or the proxy factory.
    /// When a 7702 account is created, the first userOp should contain self-call to initialize the account.
    function initializeAccount(bytes calldata initData) external payable virtual {
        // Protect this function to only be callable when used with the proxy factory or when
        // account calls itself
        if (msg.sender != address(this)) {
            if (_amIERC7702()) {
                // If this is a 7702 account, we allow passing a user signature with the initData
                // to initialize the account. This allows 7702 accounts to be initialized
                // by a relayer.
                bytes calldata signature = initData[0:65];
                AccountStorage storage $accountStorage = _getAccountStorage();
                // Remove the signature  from the initData
                initData = initData[65:];
                // Calculate the hash of the initData
                bytes32 initDataHash;
                assembly {
                    let ptr := mload(0x40)
                    calldatacopy(ptr, initData.offset, initData.length)
                    initDataHash := keccak256(ptr, initData.length)
                }
                // Make sure the account has not been already initialized
                // Means relay can not re-initialize the account
                require(!isInitialized(), AccountAlreadyInitialized());
                // Make sure the initHash is not already used
                require(!$accountStorage.erc7702InitHashes[initDataHash], AccountAlreadyInitialized());
                // Check if the signature is valid
                require(ECDSA.recover(initDataHash, signature) == address(this), InvalidSignature());
                // Mark the initDataHash as used
                $accountStorage.erc7702InitHashes[initDataHash] = true;
            } else {
                Initializable.requireInitializable();
            }
        }
        _initializeAccount(initData);
    }

    function _initializeAccount(bytes calldata initData) internal {
        require(initData.length >= 24, InvalidInitData());

        address bootstrap;
        bytes calldata bootstrapCall;

        assembly {
            bootstrap := calldataload(initData.offset)
            let s := calldataload(add(initData.offset, 0x20))
            let u := add(initData.offset, s)
            bootstrapCall.offset := add(u, 0x20)
            bootstrapCall.length := calldataload(u)
        }

        (bool success,) = bootstrap.delegatecall(bootstrapCall);

        assembly {
            if iszero(success) {
                mstore(0x00, 0x315927c5) // NexusInitializationFailed()
                revert(0x1c, 0x04)
            }
        }
        if (!_amIERC7702()) {
            require(isInitialized(), AccountNotInitialized());
        }
    }

    /// @notice Validates a signature according to ERC-1271 standards.
    /// @param hash The hash of the data being validated.
    /// @param signature Signature data that needs to be validated.
    /// @return The status code of the signature validation (`0x1626ba7e` if valid).
    /// bytes4(keccak256("isValidSignature(bytes32,bytes)") = 0x1626ba7e
    /// @dev Delegates the validation to a validator module specified within the signature data.
    function isValidSignature(bytes32 hash, bytes calldata signature) external view virtual override returns (bytes4) {
        // Handle potential ERC7739 support detection request
        if (signature.length == 0) {
            // Forces the compiler to optimize for smaller bytecode size.
            /// forge-lint:disable-next-line(divide-before-multiply)
            if (uint256(hash) == (~signature.length / 0xffff) * 0x7739) {
                return _checkERC7739Support(hash, signature);
            }
        }
        // else proceed with normal signature verification
        // First 20 bytes of data will be validator address and rest of the bytes is complete signature.
        address validator = _handleValidator(address(bytes20(signature[0:20])));
        bytes memory signature_;
        (hash, signature_) = _withPreValidationHook(hash, signature[20:]);
        try IValidator(validator).isValidSignatureWithSender(msg.sender, hash, signature_) returns (bytes4 res) {
            return res;
        } catch {
            return bytes4(0xffffffff);
        }
    }

    /// @notice Retrieves the address of the current implementation from the EIP-1967 slot.
    /// @notice Checks the 1967 implementation slot, if not found then checks the slot defined by address (Biconomy V2
    /// smart account)
    /// @return implementation The address of the current contract implementation.
    function getImplementation() external view returns (address implementation) {
        assembly {
            implementation := sload(_ERC1967_IMPLEMENTATION_SLOT)
        }
        if (implementation == address(0)) {
            assembly {
                implementation := sload(address())
            }
        }
    }

    /// @notice Checks if a specific module type is supported by this smart account.
    /// @param moduleTypeId The identifier of the module type to check.
    /// @return True if the module type is supported, false otherwise.
    function supportsModule(uint256 moduleTypeId) external view virtual returns (bool) {
        /* MODULE_TYPE_VALIDATOR || MODULE_TYPE_EXECUTOR
        || MODULE_TYPE_FALLBACK || MODULE_TYPE_HOOK
        || MODULE_TYPE_PREVALIDATION_HOOK_ERC1271
        || MODULE_TYPE_PREVALIDATION_HOOK_ERC4337 || MODULE_TYPE_MULTI */
        // Bitmap: 0x31F represents supported module types: 0,1,2,3,4,8,9
        // 0x31F = 0b1100011111 = (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<8)|(1<<9)
        /// forge-lint:disable-next-line(incorrect-shift)
        return ((1 << moduleTypeId) & 0x31F) != 0;
    }

    /// @notice Determines if a specific execution mode is supported.
    /// @param mode The execution mode to evaluate.
    /// @return isSupported True if the execution mode is supported, false otherwise.
    function supportsExecutionMode(ExecutionMode mode) external view virtual returns (bool isSupported) {
        (CallType callType, ExecType execType) = mode.decodeBasic();

        // Return true if both the call type and execution type are supported.
        return (callType == CALLTYPE_SINGLE || callType == CALLTYPE_BATCH || callType == CALLTYPE_DELEGATECALL)
            && (execType == EXECTYPE_DEFAULT || execType == EXECTYPE_TRY);
    }

    /// @notice Determines whether a module is installed on the smart account.
    /// @param moduleTypeId The ID corresponding to the type of module (Validator, Executor, Fallback, Hook).
    /// @param module The address of the module to check.
    /// @param additionalContext Optional context that may be needed for certain checks.
    /// @return True if the module is installed, false otherwise.
    function isModuleInstalled(
        uint256 moduleTypeId,
        address module,
        bytes calldata additionalContext
    )
        external
        view
        returns (bool)
    {
        return _isModuleInstalled(moduleTypeId, module, additionalContext);
    }

    /// @notice Checks if the smart account is initialized.
    /// @return True if the smart account is initialized, false otherwise.
    /// @dev In case default validator is initialized, two other SLOADS from _areSentinelListsInitialized() are not
    /// checked,
    /// this method should not introduce huge gas overhead.
    function isInitialized() public view returns (bool) {
        return (IValidator(_DEFAULT_VALIDATOR).isInitialized(address(this)) || _areSentinelListsInitialized());
    }

    /// Returns the account's implementation ID.
    /// @return The unique identifier for this account implementation.
    function accountId() external pure virtual returns (string memory) {
        return "biconomy.nexus.1.3.1";
    }

    /// Upgrades the contract to a new implementation and calls a function on the new contract.
    /// @notice Updates two slots 1. ERC1967 slot and
    /// 2. address() slot in case if it's potentially upgraded earlier from Biconomy V2 account,
    /// as Biconomy v2 Account (proxy) reads implementation from the slot that is defined by its address
    /// @param newImplementation The address of the new contract implementation.
    /// @param data The calldata to be sent to the new implementation.
    function upgradeToAndCall(address newImplementation, bytes calldata data) public payable virtual override withHook {
        require(newImplementation != address(0), InvalidImplementationAddress());
        bool res;
        assembly {
            res := gt(extcodesize(newImplementation), 0)
        }
        require(res, InvalidImplementationAddress());
        // update the address() storage slot as well
        // This is needed in case the og proxy is Nexus v2 proxy which
        // reads the implementation from the slot defined by its address
        assembly {
            sstore(address(), newImplementation)
        }
        UUPSUpgradeable.upgradeToAndCall(newImplementation, data);
    }

    /// @dev For automatic detection that the smart account supports the ERC7739 workflow
    /// Iterates over all the validators but only if this is a detection request
    /// ERC-7739 spec assumes that if the account doesn't support ERC-7739
    /// it will try to handle the detection request as it was normal sig verification
    /// request and will return 0xffffffff since it won't be able to verify the 0x signature
    /// against 0x7739...7739 hash.
    /// So this approach is consistent with the ERC-7739 spec.
    /// If no validator supports ERC-7739, this function returns false
    /// thus the account will proceed with normal signature verification
    /// and return 0xffffffff as a result.
    function _checkERC7739Support(bytes32 hash, bytes calldata signature) internal view virtual returns (bytes4) {
        bytes4 result;
        unchecked {
            SentinelListLib.SentinelList storage validators = _getAccountStorage().validators;
            address next = validators.entries[SENTINEL];
            while (next != ZERO_ADDRESS && next != SENTINEL) {
                result = _get7739Version(next, result, hash, signature);
                next = validators.getNext(next);
            }
        }
        result = _get7739Version(_DEFAULT_VALIDATOR, result, hash, signature); // check default validator
        return result == bytes4(0) ? bytes4(0xffffffff) : result;
    }

    function _get7739Version(
        address validator,
        bytes4 prevResult,
        bytes32 hash,
        bytes calldata signature
    )
        internal
        view
        returns (bytes4)
    {
        bytes4 support = IValidator(validator).isValidSignatureWithSender(msg.sender, hash, signature);
        /// forge-lint:disable-next-line(unsafe-typecast)
        if (bytes2(support) == bytes2(SUPPORTS_ERC7739) && support > prevResult) {
            return support;
        }
        return prevResult;
    }

    /// @dev Ensures that only authorized callers can upgrade the smart contract implementation.
    /// This is part of the UUPS (Universal Upgradeable Proxy Standard) pattern.
    /// param newImplementation The address of the new implementation to upgrade to.
    function _authorizeUpgrade(
        address /* newImplementation */
    )
        internal
        virtual
        override(UUPSUpgradeable)
        onlyEntryPointOrSelf
    {
        if (_amIERC7702()) {
            revert ERC7702AccountCannotBeUpgradedThisWay();
        }
    }

    /// @dev Handles the PREP initialization.
    /// @param data The packed data to be handled.
    /// @return cleanedSignature The cleaned signature for Nexus 4337 (validateUserOp) flow.
    /// @return initData The data to initialize the account with.
    function _handlePREP(bytes calldata data)
        internal
        returns (bytes calldata cleanedSignature, bytes calldata initData)
    {
        bytes32 saltAndDelegation;
        // unpack the data
        assembly {
            if lt(data.length, 0xf9) {
                mstore(0x0, 0xaed59595) // NotInitializable()
                revert(0x1c, 0x04)
            }

            saltAndDelegation := calldataload(data.offset)

            // initData
            let p := calldataload(add(data.offset, 0x20))
            let u := add(data.offset, p)
            initData.offset := add(u, 0x20)
            initData.length := calldataload(u)

            // cleanedSignature
            p := calldataload(add(data.offset, 0x40))
            u := add(data.offset, p)
            cleanedSignature.offset := add(u, 0x20)
            cleanedSignature.length := calldataload(u)
        }

        // check r is valid
        bytes32 r = LibPREP.rPREP(address(this), keccak256(initData), saltAndDelegation);
        assembly {
            if iszero(r) {
                mstore(0x00, 0xe483bbcb) // revert InvalidPREP()
                revert(0x1c, 0x04)
            }
            // emit PREPInitialized(r)
            mstore(0x00, r)
            log1(0x00, 0x20, 0x4f058962bce244bca6c9be42f256083afc66f1f63a1f9a04e31a3042311af38d)
        }
    }

    // checks if there's at least one validator initialized
    function _checkInitializedValidators() internal view {
        if (!_amIERC7702() && !IValidator(_DEFAULT_VALIDATOR).isInitialized(address(this))) {
            unchecked {
                SentinelListLib.SentinelList storage validators = _getAccountStorage().validators;
                address next = validators.entries[SENTINEL];
                while (next != ZERO_ADDRESS && next != SENTINEL) {
                    if (IValidator(next).isInitialized(address(this))) {
                        break;
                    }
                    next = validators.getNext(next);
                }
                if (next == SENTINEL) {
                    //went through all validators and none was initialized
                    assembly {
                        // revert CanNotRemoveLastValidator()
                        mstore(0x00, 0xcc319d84)
                        revert(0x1c, 0x04)
                    }
                }
            }
        }
    }

    /// @dev EIP712 domain name and version.
    function _domainNameAndVersion() internal pure override returns (string memory name, string memory version) {
        name = "Nexus";
        version = "1.3.1";
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// ──────────────────────────────────────────────────────────────────────────────
//     _   __    _  __
//    / | / /__ | |/ /_  _______
//   /  |/ / _ \|   / / / / ___/
//  / /|  /  __/   / /_/ (__  )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Accounts compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

import { IBaseAccount } from "../../interfaces/nexus/base/IBaseAccount.sol";

/// @title Nexus - BaseAccount
/// @notice Implements ERC-4337 and ERC-7579 standards for account management and access control within the Nexus suite.
/// @dev Manages entry points and configurations as specified in the ERC-4337 and ERC-7579 documentation.
/// @author @livingrockrises | Biconomy | [email protected]
/// @author @aboudjem | Biconomy | [email protected]
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady
contract BaseAccount is IBaseAccount {
    /// @notice The canonical address for the ERC4337 EntryPoint contract, version 0.7.
    /// This address is consistent across all supported networks.
    address internal immutable _ENTRYPOINT;

    /// @dev Ensures the caller is either the EntryPoint or this account itself.
    /// Reverts with AccountAccessUnauthorized if the check fails.
    modifier onlyEntryPointOrSelf() {
        require(msg.sender == _ENTRYPOINT || msg.sender == address(this), AccountAccessUnauthorized());
        _;
    }

    /// @dev Ensures the caller is the EntryPoint.
    /// Reverts with AccountAccessUnauthorized if the check fails.
    modifier onlyEntryPoint() {
        require(msg.sender == _ENTRYPOINT, AccountAccessUnauthorized());
        _;
    }

    /// @dev Sends to the EntryPoint (i.e. `msg.sender`) the missing funds for this transaction.
    /// Subclass MAY override this modifier for better funds management.
    /// (e.g. send to the EntryPoint more than the minimum required, so that in future transactions
    /// it will not be required to send again)
    ///
    /// `missingAccountFunds` is the minimum value this modifier should send the EntryPoint,
    /// which MAY be zero, in case there is enough deposit, or the userOp has a paymaster.
    modifier payPrefund(uint256 missingAccountFunds) virtual {
        _;
        /// @solidity memory-safe-assembly
        assembly {
            if missingAccountFunds {
                // Ignore failure (it's EntryPoint's job to verify, not the account's).
                pop(call(gas(), caller(), missingAccountFunds, codesize(), 0x00, codesize(), 0x00))
            }
        }
    }

    /// @notice Adds deposit to the EntryPoint to fund transactions.
    function addDeposit() external payable virtual {
        address entryPointAddress = _ENTRYPOINT;
        /// @solidity memory-safe-assembly
        assembly {
            // The EntryPoint has balance accounting logic in the `receive()` function.
            if iszero(call(gas(), entryPointAddress, callvalue(), codesize(), 0x00, codesize(), 0x00)) {
                revert(codesize(), 0x00)
            } // For gas estimation.
        }
    }

    /// @notice Withdraws ETH from the EntryPoint to a specified address.
    /// @param to The address to receive the withdrawn funds.
    /// @param amount The amount to withdraw.
    function withdrawDepositTo(address to, uint256 amount) external payable virtual onlyEntryPointOrSelf {
        address entryPointAddress = _ENTRYPOINT;
        assembly {
            let freeMemPtr := mload(0x40) // Store the free memory pointer.
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x205c2878000000000000000000000000) // `withdrawTo(address,uint256)`.
            if iszero(call(gas(), entryPointAddress, 0, 0x10, 0x44, codesize(), 0x00)) {
                returndatacopy(freeMemPtr, 0x00, returndatasize())
                revert(freeMemPtr, returndatasize())
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @notice Returns the current deposit balance of this account on the EntryPoint.
    /// @return result The current balance held at the EntryPoint.
    function getDeposit() external view virtual returns (uint256 result) {
        address entryPointAddress = _ENTRYPOINT;
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, address()) // Store the `account` argument.
            mstore(0x00, 0x70a08231) // `balanceOf(address)`.
            result := mul(
                // Returns 0 if the EntryPoint does not exist.
                mload(0x20),
                and(
                    // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), entryPointAddress, 0x1c, 0x24, 0x20, 0x20)
                )
            )
        }
    }

    /// @notice Retrieves the address of the EntryPoint contract, currently using version 0.7.
    /// @dev This function returns the address of the canonical ERC4337 EntryPoint contract.
    /// It can be overridden to return a different EntryPoint address if needed.
    /// @return The address of the EntryPoint contract.
    function entryPoint() external view returns (address) {
        return _ENTRYPOINT;
    }
}

File 3 of 44 : ModuleManager.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// ──────────────────────────────────────────────────────────────────────────────
//     _   __    _  __
//    / | / /__ | |/ /_  _______
//   /  |/ / _ \|   / / / / ___/
//  / /|  /  __/   / /_/ (__  )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Accounts compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

import { SentinelListLib } from "sentinellist/SentinelList.sol";
import { Storage } from "./Storage.sol";
import {
    IModule,
    IValidator,
    IExecutor,
    IHook,
    IPreValidationHookERC1271,
    IPreValidationHookERC4337,
    IFallback
} from "erc7579/interfaces/IERC7579Module.sol";
import { CallType, CALLTYPE_SINGLE, CALLTYPE_STATIC } from "../../lib/erc-7579/ModeLib.sol";
import { ExecLib } from "../../lib/erc-7579/ExecLib.sol";
import { LocalCallDataParserLib } from "../../lib/nexus/local/LocalCallDataParserLib.sol";
import { IModuleManager } from "../../interfaces/nexus/base/IModuleManager.sol";
// solhint-disable no-unused-import
import {
    MODULE_TYPE_VALIDATOR,
    MODULE_TYPE_EXECUTOR,
    MODULE_TYPE_FALLBACK,
    MODULE_TYPE_HOOK,
    MODULE_TYPE_PREVALIDATION_HOOK_ERC1271,
    MODULE_TYPE_PREVALIDATION_HOOK_ERC4337,
    MODULE_TYPE_MULTI,
    MODULE_ENABLE_MODE_TYPE_HASH,
    EMERGENCY_UNINSTALL_TYPE_HASH,
    ERC1271_SUCCESS
} from "../../types/Constants.sol";
// solhint-enable no-unused-import
import { EIP712 } from "solady/utils/EIP712.sol";
import { ExcessivelySafeCall } from "excessively-safe-call/ExcessivelySafeCall.sol";
import { PackedUserOperation } from "account-abstraction/interfaces/PackedUserOperation.sol";
import { EmergencyUninstall } from "../../types/DataTypes.sol";

/// @title Nexus - ModuleManager
/// @notice Manages Validator, Executor, Hook, and Fallback modules within the Nexus suite, supporting
/// @dev Implements SentinelList for managing modules via a linked list structure, adhering to ERC-7579.
/// @author @livingrockrises | Biconomy | [email protected]
/// @author @aboudjem | Biconomy | [email protected]
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady
abstract contract ModuleManager is Storage, EIP712, IModuleManager {
    using SentinelListLib for SentinelListLib.SentinelList;
    using LocalCallDataParserLib for bytes;
    using ExecLib for address;
    using ExcessivelySafeCall for address;

    /// @dev The default validator address.
    /// @notice To explicitly initialize the default validator, Nexus.execute(_DEFAULT_VALIDATOR.onInstall(...)) should
    /// be
    /// called.
    address internal immutable _DEFAULT_VALIDATOR;

    /// @notice Ensures the message sender is a registered executor module.
    modifier onlyExecutorModule() virtual {
        require(_getAccountStorage().executors.contains(msg.sender), InvalidModule(msg.sender));
        _;
    }

    /// @notice Does pre-checks and post-checks using an installed hook on the account.
    /// @dev sender, msg.data and msg.value is passed to the hook to implement custom flows.
    modifier withHook() {
        address hook = _getHook();
        if (hook == address(0)) {
            _;
        } else {
            bytes memory hookData = IHook(hook).preCheck(msg.sender, msg.value, msg.data);
            _;
            IHook(hook).postCheck(hookData);
        }
    }

    /// @dev initData should block the implementation from being used as a Smart Account
    constructor(address defaultValidator_, bytes memory initData_) {
        if (!IValidator(defaultValidator_).isModuleType(MODULE_TYPE_VALIDATOR)) {
            revert MismatchModuleTypeId();
        }
        IValidator(defaultValidator_).onInstall(initData_);
        _DEFAULT_VALIDATOR = defaultValidator_;
    }

    // receive function
    receive() external payable { }

    /// @dev Fallback function to manage incoming calls using designated handlers based on the call type.
    /// Hooked manually in the _fallback function
    fallback() external payable {
        _fallback(msg.data);
    }

    /// @dev Retrieves the default validator address.
    /// @return The address of the default validator.
    function getDefaultValidator() external view returns (address) {
        return _DEFAULT_VALIDATOR;
    }

    /// @dev Retrieves a paginated list of validator addresses from the linked list.
    /// This utility function is not defined by the ERC-7579 standard and is implemented to facilitate
    /// easier management and retrieval of large sets of validator modules.
    /// @param cursor The address to start pagination from, or zero to start from the first entry.
    /// @param size The number of validator addresses to return.
    /// @return array An array of validator addresses.
    /// @return next The address to use as a cursor for the next page of results.
    function getValidatorsPaginated(
        address cursor,
        uint256 size
    )
        external
        view
        returns (address[] memory array, address next)
    {
        (array, next) = _paginate(_getAccountStorage().validators, cursor, size);
    }

    /// @dev Retrieves a paginated list of executor addresses from the linked list.
    /// This utility function is not defined by the ERC-7579 standard and is implemented to facilitate
    /// easier management and retrieval of large sets of executor modules.
    /// @param cursor The address to start pagination from, or zero to start from the first entry.
    /// @param size The number of executor addresses to return.
    /// @return array An array of executor addresses.
    /// @return next The address to use as a cursor for the next page of results.
    function getExecutorsPaginated(
        address cursor,
        uint256 size
    )
        external
        view
        returns (address[] memory array, address next)
    {
        (array, next) = _paginate(_getAccountStorage().executors, cursor, size);
    }

    /// @notice Retrieves the currently active hook address.
    /// @return hook The address of the active hook module.
    function getActiveHook() external view returns (address hook) {
        return _getHook();
    }

    /// @notice Fetches the fallback handler for a specific selector.
    /// @param selector The function selector to query.
    /// @return calltype The type of call that the handler manages.
    /// @return handler The address of the fallback handler.
    function getFallbackHandlerBySelector(bytes4 selector) external view returns (CallType, address) {
        FallbackHandler memory handler = _getAccountStorage().fallbacks[selector];
        return (handler.calltype, handler.handler);
    }

    /// @dev Initializes the module manager by setting up default states for validators and executors.
    function _initSentinelLists() internal virtual {
        // account module storage
        AccountStorage storage ams = _getAccountStorage();
        ams.executors.init();
        ams.validators.init();
    }

    /// @dev Implements Module Enable Mode flow.
    /// @param packedData Data source to parse data required to perform Module Enable mode from.
    /// @return userOpSignature the clean signature which can be further used for userOp validation
    function _enableMode(
        bytes32 userOpHash,
        bytes calldata packedData
    )
        internal
        returns (bytes calldata userOpSignature)
    {
        address module;
        uint256 moduleType;
        bytes calldata moduleInitData;
        bytes calldata enableModeSignature;

        (module, moduleType, moduleInitData, enableModeSignature, userOpSignature) = packedData.parseEnableModeData();

        address enableModeSigValidator = _handleValidator(address(bytes20(enableModeSignature[0:20])));

        enableModeSignature = enableModeSignature[20:];

        bytes32 structHash = _getEnableModeDataHash(module, moduleType, userOpHash, moduleInitData);
        bool isValid = _checkEnableModeSignature(structHash, enableModeSignature, enableModeSigValidator);

        assembly {
            if iszero(isValid) {
                // revert EnableModeSigError()
                mstore(0x00, 0x46fdc333)
                revert(0x1c, 0x04)
            }
        }

        this.installModule(moduleType, module, moduleInitData);
    }

    /// @notice Installs a new module to the smart account.
    /// @param moduleTypeId The type identifier of the module being installed, which determines its role:
    /// - 0 for MultiType
    /// - 1 for Validator
    /// - 2 for Executor
    /// - 3 for Fallback
    /// - 4 for Hook
    /// - 8 for PreValidationHookERC1271
    /// - 9 for PreValidationHookERC4337
    /// @param module The address of the module to install.
    /// @param initData Initialization data for the module.
    /// @dev This function goes through hook checks via withHook modifier.
    /// @dev No need to check that the module is already installed, as this check is done
    /// when trying to sstore the module in an appropriate SentinelList
    function _installModule(uint256 moduleTypeId, address module, bytes calldata initData) internal {
        if (!_areSentinelListsInitialized()) {
            _initSentinelLists();
        }
        if (module == address(0)) revert ModuleAddressCanNotBeZero();
        if (moduleTypeId == MODULE_TYPE_VALIDATOR) {
            _installValidator(module, initData);
        } else if (moduleTypeId == MODULE_TYPE_EXECUTOR) {
            _installExecutor(module, initData);
        } else if (moduleTypeId == MODULE_TYPE_FALLBACK) {
            _installFallbackHandler(module, initData);
        } else if (moduleTypeId == MODULE_TYPE_HOOK) {
            _installHook(module, initData);
        } else if (_isPrevalidationHookType(moduleTypeId)) {
            _installPreValidationHook(moduleTypeId, module, initData);
        } else if (moduleTypeId == MODULE_TYPE_MULTI) {
            _multiTypeInstall(module, initData);
        } else {
            revert InvalidModuleTypeId(moduleTypeId);
        }
    }

    /// @dev Installs a new validator module after checking if it matches the required module type.
    /// @param validator The address of the validator module to be installed.
    /// @param data Initialization data to configure the validator upon installation.
    function _installValidator(address validator, bytes calldata data) internal virtual withHook {
        if (!IValidator(validator).isModuleType(MODULE_TYPE_VALIDATOR)) revert MismatchModuleTypeId();
        if (validator == _DEFAULT_VALIDATOR) {
            revert DefaultValidatorAlreadyInstalled();
        }
        _getAccountStorage().validators.push(validator);
        IValidator(validator).onInstall(data);
    }

    /// @dev Uninstalls a validator module.
    /// @param validator The address of the validator to be uninstalled.
    /// @param data De-initialization data to configure the validator upon uninstallation.
    function _uninstallValidator(address validator, bytes calldata data) internal virtual {
        SentinelListLib.SentinelList storage validators = _getAccountStorage().validators;

        (address prev, bytes memory disableModuleData) = abi.decode(data, (address, bytes));

        // Perform the removal first
        validators.pop(prev, validator);

        validator.excessivelySafeCall(
            gasleft(), 0, 0, abi.encodeWithSelector(IModule.onUninstall.selector, disableModuleData)
        );
    }

    /// @dev Installs a new executor module after checking if it matches the required module type.
    /// @param executor The address of the executor module to be installed.
    /// @param data Initialization data to configure the executor upon installation.
    function _installExecutor(address executor, bytes calldata data) internal virtual withHook {
        if (!IExecutor(executor).isModuleType(MODULE_TYPE_EXECUTOR)) revert MismatchModuleTypeId();
        _getAccountStorage().executors.push(executor);
        IExecutor(executor).onInstall(data);
    }

    /// @dev Uninstalls an executor module by removing it from the executors list.
    /// @param executor The address of the executor to be uninstalled.
    /// @param data De-initialization data to configure the executor upon uninstallation.
    function _uninstallExecutor(address executor, bytes calldata data) internal virtual {
        (address prev, bytes memory disableModuleData) = abi.decode(data, (address, bytes));
        _getAccountStorage().executors.pop(prev, executor);
        executor.excessivelySafeCall(
            gasleft(), 0, 0, abi.encodeWithSelector(IModule.onUninstall.selector, disableModuleData)
        );
    }

    /// @dev Installs a hook module, ensuring no other hooks are installed before proceeding.
    /// @param hook The address of the hook to be installed.
    /// @param data Initialization data to configure the hook upon installation.
    function _installHook(address hook, bytes calldata data) internal virtual withHook {
        if (!IHook(hook).isModuleType(MODULE_TYPE_HOOK)) revert MismatchModuleTypeId();
        address currentHook = _getHook();
        require(currentHook == address(0), HookAlreadyInstalled(currentHook));
        _setHook(hook);
        IHook(hook).onInstall(data);
    }

    /// @dev Uninstalls a hook module, ensuring the current hook matches the one intended for uninstallation.
    /// @param hook The address of the hook to be uninstalled.
    /// @param hookType The type of the hook to be uninstalled.
    /// @param data De-initialization data to configure the hook upon uninstallation.
    function _uninstallHook(address hook, uint256 hookType, bytes calldata data) internal virtual {
        if (hookType == MODULE_TYPE_HOOK) {
            _setHook(address(0));
        } else if (_isPrevalidationHookType(hookType)) {
            _uninstallPreValidationHook(hookType);
        }
        hook.excessivelySafeCall(gasleft(), 0, 0, abi.encodeWithSelector(IModule.onUninstall.selector, data));
    }

    /// @dev Sets the current hook in the storage to the specified address.
    /// @param hook The new hook address.
    function _setHook(address hook) internal virtual {
        _getAccountStorage().hook = IHook(hook);
    }

    /// @dev Installs a fallback handler for a given selector with initialization data.
    /// @param handler The address of the fallback handler to install.
    /// @param params The initialization parameters including the selector and call type.
    function _installFallbackHandler(address handler, bytes calldata params) internal virtual withHook {
        if (!IFallback(handler).isModuleType(MODULE_TYPE_FALLBACK)) revert MismatchModuleTypeId();
        // Extract the function selector from the provided parameters.
        bytes4 selector = bytes4(params[0:4]);

        // Extract the call type from the provided parameters.
        CallType calltype = CallType.wrap(bytes1(params[4]));

        require(calltype == CALLTYPE_SINGLE || calltype == CALLTYPE_STATIC, FallbackCallTypeInvalid());

        // Extract the initialization data from the provided parameters.
        bytes memory initData = params[5:];

        // Revert if the selector is either `onInstall(bytes)` (0x6d61fe70) or `onUninstall(bytes)` (0x8a91b0e3) or
        // explicit bytes(0).
        // These selectors are explicitly forbidden to prevent security vulnerabilities.
        // Allowing these selectors would enable unauthorized users to uninstall and reinstall critical modules.
        // If a validator module is uninstalled and reinstalled without proper authorization, it can compromise
        // the account's security and integrity. By restricting these selectors, we ensure that the fallback handler
        // cannot be manipulated to disrupt the expected behavior and security of the account.
        require(
            !(selector == bytes4(0x6d61fe70) || selector == bytes4(0x8a91b0e3) || selector == bytes4(0)),
            FallbackSelectorForbidden()
        );

        // Revert if a fallback handler is already installed for the given selector.
        // This check ensures that we do not overwrite an existing fallback handler, which could lead to unexpected
        // behavior.
        require(!_isFallbackHandlerInstalled(selector), FallbackAlreadyInstalledForSelector(selector));

        // Store the fallback handler and its call type in the account storage.
        // This maps the function selector to the specified fallback handler and call type.
        _getAccountStorage().fallbacks[selector] = FallbackHandler(handler, calltype);

        // Invoke the `onInstall` function of the fallback handler with the provided initialization data.
        // This step allows the fallback handler to perform any necessary setup or initialization.
        IFallback(handler).onInstall(initData);
    }

    /// @dev Uninstalls a fallback handler for a given selector.
    /// @param fallbackHandler The address of the fallback handler to uninstall.
    /// @param data The de-initialization data containing the selector.
    function _uninstallFallbackHandler(address fallbackHandler, bytes calldata data) internal virtual {
        _getAccountStorage().fallbacks[bytes4(data[0:4])] = FallbackHandler(address(0), CallType.wrap(0x00));
        fallbackHandler.excessivelySafeCall(
            gasleft(), 0, 0, abi.encodeWithSelector(IModule.onUninstall.selector, data[4:])
        );
    }

    /// @dev Installs a pre-validation hook module, ensuring no other pre-validation hooks are installed before
    /// proceeding.
    /// @param preValidationHookType The type of the pre-validation hook.
    /// @param preValidationHook The address of the pre-validation hook to be installed.
    /// @param data Initialization data to configure the hook upon installation.
    function _installPreValidationHook(
        uint256 preValidationHookType,
        address preValidationHook,
        bytes calldata data
    )
        internal
        virtual
        withHook
    {
        if (!IModule(preValidationHook).isModuleType(preValidationHookType)) revert MismatchModuleTypeId();
        address currentPreValidationHook = _getPreValidationHook(preValidationHookType);
        require(currentPreValidationHook == address(0), PrevalidationHookAlreadyInstalled(currentPreValidationHook));
        _setPreValidationHook(preValidationHookType, preValidationHook);
        IModule(preValidationHook).onInstall(data);
    }

    /// @dev Uninstalls a pre-validation hook module
    /// @param hookType The type of the pre-validation hook.
    function _uninstallPreValidationHook(uint256 hookType) internal virtual {
        _setPreValidationHook(hookType, address(0));
    }

    /// @dev Sets the current pre-validation hook in the storage to the specified address, based on the hook type.
    /// @param hookType The type of the pre-validation hook.
    /// @param hook The new hook address.
    function _setPreValidationHook(uint256 hookType, address hook) internal virtual {
        if (hookType == MODULE_TYPE_PREVALIDATION_HOOK_ERC1271) {
            _getAccountStorage().preValidationHookERC1271 = IPreValidationHookERC1271(hook);
        } else if (hookType == MODULE_TYPE_PREVALIDATION_HOOK_ERC4337) {
            _getAccountStorage().preValidationHookERC4337 = IPreValidationHookERC4337(hook);
        }
    }

    /// @notice Installs a module with multiple types in a single operation.
    /// @dev This function handles installing a multi-type module by iterating through each type and initializing it.
    /// The initData should include an ABI-encoded tuple of (uint[] types, bytes[] initDatas).
    /// @param module The address of the multi-type module.
    /// @param initData Initialization data for each type within the module.
    function _multiTypeInstall(address module, bytes calldata initData) internal virtual {
        (uint256[] calldata types, bytes[] calldata initDatas) = initData.parseMultiTypeInitData();

        uint256 length = types.length;
        if (initDatas.length != length) revert InvalidInput();

        // iterate over all module types and install the module as a type accordingly
        for (uint256 i; i < length; i++) {
            uint256 theType = types[i];

            /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
            /*                      INSTALL VALIDATORS                    */
            /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
            if (theType == MODULE_TYPE_VALIDATOR) {
                _installValidator(module, initDatas[i]);
            }
            /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
            /*                       INSTALL EXECUTORS                    */
            /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
            else if (theType == MODULE_TYPE_EXECUTOR) {
                _installExecutor(module, initDatas[i]);
            }
            /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
            /*                       INSTALL FALLBACK                     */
            /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
            else if (theType == MODULE_TYPE_FALLBACK) {
                _installFallbackHandler(module, initDatas[i]);
            }
            /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
            /*          INSTALL HOOK (global only, not sig-specific)      */
            /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
            else if (theType == MODULE_TYPE_HOOK) {
                _installHook(module, initDatas[i]);
            }
            /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
            /*          INSTALL PRE-VALIDATION HOOK                       */
            /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
            else if (_isPrevalidationHookType(theType)) {
                _installPreValidationHook(theType, module, initDatas[i]);
            }
        }
    }

    /// @notice Checks if an emergency uninstall signature is valid.
    /// @param data The emergency uninstall data.
    /// @param signature The signature to validate.
    function _checkEmergencyUninstallSignature(EmergencyUninstall calldata data, bytes calldata signature) internal {
        address validator = _handleValidator(address(bytes20(signature[0:20])));
        // Hash the data
        bytes32 hash = _hashTypedData(
            keccak256(
                abi.encode(
                    EMERGENCY_UNINSTALL_TYPE_HASH, data.hook, data.hookType, keccak256(data.deInitData), data.nonce
                )
            )
        );
        // Check if nonce is valid
        require(!_getAccountStorage().nonces[data.nonce], InvalidNonce());
        // Mark nonce as used
        _getAccountStorage().nonces[data.nonce] = true;
        // Check if the signature is valid
        require(
            (IValidator(validator).isValidSignatureWithSender(address(this), hash, signature[20:]) == ERC1271_SUCCESS),
            EmergencyUninstallSigError()
        );
    }

    /// @dev Calls the pre-validation hook for ERC-4337.
    /// @param hash The hash of the user operation.
    /// @param userOp The user operation data.
    /// @param missingAccountFunds The amount of missing account funds.
    /// @return postHash The updated hash after the pre-validation hook.
    /// @return postSig The updated signature after the pre-validation hook.
    function _withPreValidationHook(
        bytes32 hash,
        PackedUserOperation memory userOp,
        uint256 missingAccountFunds
    )
        internal
        virtual
        returns (bytes32 postHash, bytes memory postSig)
    {
        // Get the pre-validation hook for ERC-4337
        address preValidationHook = _getPreValidationHook(MODULE_TYPE_PREVALIDATION_HOOK_ERC4337);
        // If no pre-validation hook is installed, return the original hash and signature
        if (preValidationHook == address(0)) {
            return (hash, userOp.signature);
        }
        // Otherwise, call the pre-validation hook and return the updated hash and signature
        else {
            return
                IPreValidationHookERC4337(preValidationHook).preValidationHookERC4337(userOp, missingAccountFunds, hash);
        }
    }

    /// @dev Retrieves the pre-validation hook from the storage based on the hook type.
    /// @param preValidationHookType The type of the pre-validation hook.
    /// @return preValidationHook The address of the pre-validation hook.
    function _getPreValidationHook(uint256 preValidationHookType) internal view returns (address preValidationHook) {
        preValidationHook = preValidationHookType == MODULE_TYPE_PREVALIDATION_HOOK_ERC1271
            ? address(_getAccountStorage().preValidationHookERC1271)
            : address(_getAccountStorage().preValidationHookERC4337);
    }

    /// @dev Calls the pre-validation hook for ERC-1271.
    /// @param hash The hash of the user operation.
    /// @param signature The signature to validate.
    /// @return postHash The updated hash after the pre-validation hook.
    /// @return postSig The updated signature after the pre-validation hook.
    function _withPreValidationHook(
        bytes32 hash,
        bytes calldata signature
    )
        internal
        view
        virtual
        returns (bytes32 postHash, bytes memory postSig)
    {
        // Get the pre-validation hook for ERC-1271
        address preValidationHook = _getPreValidationHook(MODULE_TYPE_PREVALIDATION_HOOK_ERC1271);
        // If no pre-validation hook is installed, return the original hash and signature
        if (preValidationHook == address(0)) {
            return (hash, signature);
        }
        // Otherwise, call the pre-validation hook and return the updated hash and signature
        else {
            return IPreValidationHookERC1271(preValidationHook).preValidationHookERC1271(msg.sender, hash, signature);
        }
    }

    /// @notice Checks if an enable mode signature is valid.
    /// @param structHash data hash.
    /// @param sig Signature.
    /// @param validator Validator address.
    function _checkEnableModeSignature(
        bytes32 structHash,
        bytes calldata sig,
        address validator
    )
        internal
        view
        returns (bool)
    {
        bytes32 eip712Digest = _hashTypedData(structHash);
        // Use standard IERC-1271/ERC-7739 interface.
        // Even if the validator doesn't support 7739 under the hood, it is still secure,
        // as eip712digest is already built based on 712Domain of this Smart Account
        // This interface should always be exposed by validators as per ERC-7579
        try IValidator(validator).isValidSignatureWithSender(address(this), eip712Digest, sig) returns (bytes4 res) {
            return res == ERC1271_SUCCESS;
        } catch {
            return false;
        }
    }

    /// @notice Checks if a module is installed on the smart account.
    /// @param moduleTypeId The module type ID.
    /// @param module The module address.
    /// @param additionalContext Additional context for checking installation.
    /// @return True if the module is installed, false otherwise.
    function _isModuleInstalled(
        uint256 moduleTypeId,
        address module,
        bytes calldata additionalContext
    )
        internal
        view
        returns (bool)
    {
        additionalContext;
        if (moduleTypeId == MODULE_TYPE_VALIDATOR) {
            return _isValidatorInstalled(module);
        } else if (moduleTypeId == MODULE_TYPE_EXECUTOR) {
            return _isExecutorInstalled(module);
        } else if (moduleTypeId == MODULE_TYPE_FALLBACK) {
            bytes4 selector;
            if (additionalContext.length >= 4) {
                selector = bytes4(additionalContext[0:4]);
            } else {
                selector = bytes4(0x00000000);
            }
            return _isFallbackHandlerInstalled(selector, module);
        } else if (moduleTypeId == MODULE_TYPE_HOOK) {
            return _isHookInstalled(module);
        } else if (_isPrevalidationHookType(moduleTypeId)) {
            return _getPreValidationHook(moduleTypeId) == module;
        } else {
            return false;
        }
    }

    /// @dev Does bytecode optimized check of the module type id being a pre-validation hook type.
    /// @param moduleTypeId The module type id to check.
    /// return True if the module type id is a pre-validation hook type, otherwise false.
    /// If theType == 8: 8 - 8 = 0, and 0 < 2 ✓
    /// If theType == 9: 9 - 8 = 1, and 1 < 2 ✓
    /// If theType < 8 (e.g., 7): 7 - 8 = type(uint256).max (wraps), and type(uint256).max < 2 is false ✓
    /// If theType >= 10: result is >= 2, and fails the check ✓
    function _isPrevalidationHookType(uint256 moduleTypeId) internal pure returns (bool res) {
        assembly {
            res := lt(sub(moduleTypeId, 8), 2)
        }
    }

    /// @dev Checks if the validator list is already initialized.
    ///      In theory it doesn't 100% mean there is a validator or executor installed.
    ///      Use below functions to check for validators and executors.
    function _areSentinelListsInitialized() internal view virtual returns (bool) {
        // account module storage
        AccountStorage storage ams = _getAccountStorage();
        return ams.validators.alreadyInitialized() && ams.executors.alreadyInitialized();
    }

    /// @dev Checks if a fallback handler is set for a given selector.
    /// @param selector The function selector to check.
    /// @return True if a fallback handler is set, otherwise false.
    function _isFallbackHandlerInstalled(bytes4 selector) internal view virtual returns (bool) {
        FallbackHandler storage handler = _getAccountStorage().fallbacks[selector];
        return handler.handler != address(0);
    }

    /// @dev Checks if the expected fallback handler is installed for a given selector.
    /// @param selector The function selector to check.
    /// @param expectedHandler The address of the handler expected to be installed.
    /// @return True if the installed handler matches the expected handler, otherwise false.
    function _isFallbackHandlerInstalled(bytes4 selector, address expectedHandler) internal view returns (bool) {
        FallbackHandler storage handler = _getAccountStorage().fallbacks[selector];
        return handler.handler == expectedHandler;
    }

    /// @dev Checks if a validator is currently installed.
    /// @param validator The address of the validator to check.
    /// @return True if the validator is installed, otherwise false.
    function _isValidatorInstalled(address validator) internal view virtual returns (bool) {
        return _getAccountStorage().validators.contains(validator);
    }

    /// @dev Checks if an executor is currently installed.
    /// @param executor The address of the executor to check.
    /// @return True if the executor is installed, otherwise false.
    function _isExecutorInstalled(address executor) internal view virtual returns (bool) {
        return _getAccountStorage().executors.contains(executor);
    }

    /// @dev Checks if a hook is currently installed.
    /// @param hook The address of the hook to check.
    /// @return True if the hook is installed, otherwise false.
    function _isHookInstalled(address hook) internal view returns (bool) {
        return _getHook() == hook;
    }

    /// @dev Retrieves the current hook from the storage.
    /// @return hook The address of the current hook.
    function _getHook() internal view returns (address hook) {
        hook = address(_getAccountStorage().hook);
    }

    /// @dev Checks if the account is an ERC7702 account
    function _amIERC7702() internal view returns (bool res) {
        assembly {
            // use extcodesize as the first cheapest check
            if eq(extcodesize(address()), 23) {
                // use extcodecopy to copy first 3 bytes of this contract and compare with 0xef0100
                extcodecopy(address(), 0, 0, 3)
                res := eq(0xef0100, shr(232, mload(0x00)))
            }
            // if it is not 23, we do not even check the first 3 bytes
        }
    }

    /// @dev Returns the validator address to use
    function _handleValidator(address _validator) internal view returns (address validator) {
        if (_validator == address(0)) {
            validator = _DEFAULT_VALIDATOR;
        } else {
            if (!_isValidatorInstalled(_validator)) {
                assembly {
                    // revert ValidatorNotInstalled(address)
                    mstore(0x00, 0x6859e01e)
                    mstore(0x20, _validator)
                    revert(0x1c, 0x24)
                }
            }
            validator = _validator;
        }
    }

    /// @notice Builds the enable mode data hash as per eip712
    /// @param module Module being enabled
    /// @param moduleType Type of the module as per EIP-7579
    /// @param userOpHash Hash of the User Operation
    /// @param initData Module init data.
    /// @return structHash data hash
    function _getEnableModeDataHash(
        address module,
        uint256 moduleType,
        bytes32 userOpHash,
        bytes calldata initData
    )
        internal
        pure
        returns (bytes32)
    {
        bytes32 structHash;
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, MODULE_ENABLE_MODE_TYPE_HASH)
            mstore(add(ptr, 0x20), module)
            mstore(add(ptr, 0x40), moduleType)
            mstore(add(ptr, 0x60), userOpHash)

            // Hash initData and store at ptr + 0x80
            // calldatacopy to copy initData to memory, then hash it
            let initDataPtr := add(ptr, 0xa0)
            calldatacopy(initDataPtr, initData.offset, initData.length)
            let initDataHash := keccak256(initDataPtr, initData.length)
            mstore(add(ptr, 0x80), initDataHash)

            // Hash the entire struct
            structHash := keccak256(ptr, 0xa0)
        }
        return structHash;
    }

    function _fallback(bytes calldata callData) private {
        bool success;
        bytes memory result;
        FallbackHandler storage $fallbackHandler = _getAccountStorage().fallbacks[msg.sig];
        address handler = $fallbackHandler.handler;
        CallType calltype = $fallbackHandler.calltype;

        if (handler != address(0)) {
            // hook manually
            address hook = _getHook();
            bytes memory hookData;
            if (hook != address(0)) {
                hookData = IHook(hook).preCheck(msg.sender, msg.value, msg.data);
            }
            //if there's a fallback handler, call it
            if (calltype == CALLTYPE_STATIC) {
                (success, result) = handler.staticcall(ExecLib.get2771CallData(callData));
            } else if (calltype == CALLTYPE_SINGLE) {
                (success, result) = handler.call{ value: msg.value }(ExecLib.get2771CallData(callData));
            } else {
                revert UnsupportedCallType(calltype);
            }

            // Use revert message from fallback handler if the call was not successful
            assembly {
                if iszero(success) { revert(add(result, 0x20), mload(result)) }
            }

            // hook post check
            if (hook != address(0)) {
                IHook(hook).postCheck(hookData);
            }

            // return the result
            assembly {
                return(add(result, 0x20), mload(result))
            }
        }

        // If there's no handler, the call can be one of onERCXXXReceived()
        // No need to hook this as no execution is done here
        bytes32 s;
        /// @solidity memory-safe-assembly
        assembly {
            s := shr(224, calldataload(0))
            // 0x150b7a02: `onERC721Received(address,address,uint256,bytes)`.
            // 0xf23a6e61: `onERC1155Received(address,address,uint256,uint256,bytes)`.
            // 0xbc197c81: `onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)`.
            if or(eq(s, 0x150b7a02), or(eq(s, 0xf23a6e61), eq(s, 0xbc197c81))) {
                mstore(0x20, s) // Store `msg.sig`.
                return(0x3c, 0x20) // Return `msg.sig`.
            }
            mstore(0x00, 0x08c63e27)
            mstore(0x20, shl(224, s)) // Left-align bytes4 for ABI encoding
            revert(0x1c, 0x24) // revert MissingFallbackHandler(msg.sig)
        }
    }

    /// @dev Helper function to paginate entries in a SentinelList.
    /// @param list The SentinelList to paginate.
    /// @param cursor The cursor to start paginating from.
    /// @param size The number of entries to return.
    /// @return array The array of addresses in the list.
    /// @return nextCursor The cursor for the next page of entries.
    function _paginate(
        SentinelListLib.SentinelList storage list,
        address cursor,
        uint256 size
    )
        private
        view
        returns (address[] memory array, address nextCursor)
    {
        (array, nextCursor) = list.getEntriesPaginated(cursor, size);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// ──────────────────────────────────────────────────────────────────────────────
//     _   __    _  __
//    / | / /__ | |/ /_  _______
//   /  |/ / _ \|   / / / / ___/
//  / /|  /  __/   / /_/ (__  )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Accounts compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

import { Execution } from "erc7579/interfaces/IERC7579Account.sol";
import { IExecutionHelperEventsAndErrors } from "../../interfaces/nexus/base/IExecutionHelper.sol";
import { ExecType, EXECTYPE_DEFAULT, EXECTYPE_TRY } from "../../lib/erc-7579/ModeLib.sol";
import { ExecLib } from "../../lib/erc-7579/ExecLib.sol";

/// @title Nexus - ExecutionHelper
/// @notice Implements execution management within the Nexus suite, facilitating transaction execution strategies and
/// error handling.
/// @dev Provides mechanisms for direct and batched transactions with both committed and tentative execution strategies
/// as per ERC-4337 and ERC-7579 standards.
/// @author @livingrockrises | Biconomy | [email protected]
/// @author @aboudjem | Biconomy | [email protected]
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady
contract ExecutionHelper is IExecutionHelperEventsAndErrors {
    using ExecLib for bytes;

    /// @notice Executes a call to a target address with specified value and data.
    /// @notice calls to an EOA should be counted as successful.
    /// @param target The address to execute the call on.
    /// @param value The amount of wei to send with the call.
    /// @param callData The calldata to send.
    /// @return result The bytes returned from the execution, which contains the returned data from the target address.
    function _execute(
        address target,
        uint256 value,
        bytes calldata callData
    )
        internal
        virtual
        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.
        }
    }

    /// @notice Executes a call to a target address with specified value and data.
    /// same as _execute, but callData can be in memory
    function _executeMemory(
        address target,
        uint256 value,
        bytes memory callData
    )
        internal
        virtual
        returns (bytes memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            if iszero(call(gas(), target, value, add(callData, 0x20), mload(callData), 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.
        }
    }

    /// @notice Executes a call to a target address with specified value and data.
    /// Same as _execute but without return data for gas optimization.
    function _executeNoReturndata(address target, uint256 value, bytes calldata callData) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            let 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(0x40, add(result, callData.length)) //allocate memory
        }
    }

    /// @notice Tries to execute a call and captures if it was successful or not.
    /// @dev Similar to _execute but returns a success boolean and catches reverts instead of propagating them.
    /// @notice calls to an EOA should be counted as successful.
    /// @param target The address to execute the call on.
    /// @param value The amount of wei to send with the call.
    /// @param callData The calldata to send.
    /// @return success True if the execution was successful, false otherwise.
    /// @return result The bytes returned from the execution, which contains the returned data from the target address.
    function _tryExecute(
        address target,
        uint256 value,
        bytes calldata callData
    )
        internal
        virtual
        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.
        }
    }

    /// @notice Executes a batch of calls.
    /// @param executions An array of Execution structs each containing target, value, and calldata.
    /// @return result An array of bytes returned from each executed call, corresponding to the returndata from each
    /// target
    /// address.
    function _executeBatch(Execution[] calldata executions) internal returns (bytes[] memory result) {
        result = new bytes[](executions.length);

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

    /// @notice Executes a batch of calls without returning the result.
    /// @param executions An array of Execution structs each containing target, value, and calldata.
    function _executeBatchNoReturndata(Execution[] calldata executions) internal {
        Execution calldata exec;
        for (uint256 i; i < executions.length; i++) {
            exec = executions[i];
            _executeNoReturndata(exec.target, exec.value, exec.callData);
        }
    }

    /// @notice Tries to execute a batch of calls and emits an event for each unsuccessful call.
    /// @param executions An array of Execution structs.
    /// @return result An array of bytes returned from each executed call, with unsuccessful calls marked by events.
    function _tryExecuteBatch(Execution[] calldata executions) internal returns (bytes[] memory result) {
        result = new bytes[](executions.length);

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

    /// @dev Execute a delegatecall with `delegate` on this account.
    /// @return result The bytes returned from the delegatecall, which contains the returned data from the delegate
    /// contract.
    function _executeDelegatecall(address delegate, bytes calldata callData) internal returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            calldatacopy(result, callData.offset, callData.length)
            // Forwards the `data` to `delegate` via delegatecall.
            if iszero(delegatecall(gas(), delegate, 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.
        }
    }

    /// @dev Execute a delegatecall with `delegate` on this account.
    /// Same as _executeDelegatecall but without return data for gas optimization.
    function _executeDelegatecallNoReturndata(address delegate, bytes calldata callData) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let result := mload(0x40)
            calldatacopy(result, callData.offset, callData.length)
            if iszero(delegatecall(gas(), delegate, result, callData.length, codesize(), 0x00)) {
                // Bubble up the revert if the call reverts.
                returndatacopy(result, 0x00, returndatasize())
                revert(result, returndatasize())
            }
            mstore(0x40, add(result, callData.length)) //allocate memory
        }
    }

    /// @dev Execute a delegatecall with `delegate` on this account and catch reverts.
    /// @return success True if the delegatecall was successful, false otherwise.
    /// @return result The bytes returned from the delegatecall, which contains the returned data from the delegate
    /// contract.
    function _tryExecuteDelegatecall(
        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.
        }
    }

    /// @dev Executes a single transaction based on the specified execution type.
    /// @param executionCalldata The calldata containing the transaction details (target address, value, and data).
    /// @param execType The execution type, which can be DEFAULT (revert on failure) or TRY (return on failure).
    function _handleSingleExecution(bytes calldata executionCalldata, ExecType execType) internal {
        (address target, uint256 value, bytes calldata callData) = executionCalldata.decodeSingle();
        if (execType == EXECTYPE_DEFAULT) {
            _executeNoReturndata(target, value, callData);
        } else if (execType == EXECTYPE_TRY) {
            (bool success, bytes memory result) = _tryExecute(target, value, callData);
            if (!success) emit TryExecuteUnsuccessful(callData, result);
        } else {
            revert UnsupportedExecType(execType);
        }
    }

    /// @dev Executes a batch of transactions based on the specified execution type.
    /// @param executionCalldata The calldata for a batch of transactions.
    /// @param execType The execution type, which can be DEFAULT (revert on failure) or TRY (return on failure).
    function _handleBatchExecution(bytes calldata executionCalldata, ExecType execType) internal {
        Execution[] calldata executions = executionCalldata.decodeBatch();
        if (execType == EXECTYPE_DEFAULT) _executeBatchNoReturndata(executions);
        else if (execType == EXECTYPE_TRY) _tryExecuteBatch(executions);
        else revert UnsupportedExecType(execType);
    }

    /// @dev Executes a single transaction based on the specified execution type.
    /// @param executionCalldata The calldata containing the transaction details (target address, value, and data).
    /// @param execType The execution type, which can be DEFAULT (revert on failure) or TRY (return on failure).
    function _handleDelegateCallExecution(bytes calldata executionCalldata, ExecType execType) internal {
        (address delegate, bytes calldata callData) = executionCalldata.decodeDelegateCall();
        if (execType == EXECTYPE_DEFAULT) {
            _executeDelegatecallNoReturndata(delegate, callData);
        } else if (execType == EXECTYPE_TRY) {
            (bool success, bytes memory result) = _tryExecuteDelegatecall(delegate, callData);
            if (!success) emit TryDelegateCallUnsuccessful(callData, result);
        } else {
            revert UnsupportedExecType(execType);
        }
    }

    /// @dev Executes a single transaction based on the specified execution type.
    /// @param executionCalldata The calldata containing the transaction details (target address, value, and data).
    /// @param execType The execution type, which can be DEFAULT (revert on failure) or TRY (return on failure).
    /// @return returnData An array containing the execution result. In the case of a single transaction, the array
    /// contains one element.
    function _handleSingleExecutionAndReturnData(
        bytes calldata executionCalldata,
        ExecType execType
    )
        internal
        returns (bytes[] memory returnData)
    {
        (address target, uint256 value, bytes calldata callData) = executionCalldata.decodeSingle();
        returnData = new bytes[](1);
        bool success;
        // check if execType is revert(default) 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(callData, returnData[0]);
        } else {
            revert UnsupportedExecType(execType);
        }
    }

    /// @dev Executes a batch of transactions based on the specified execution type.
    /// @param executionCalldata The calldata for a batch of transactions.
    /// @param execType The execution type, which can be DEFAULT (revert on failure) or TRY (return on failure).
    /// @return returnData An array containing the execution results for each transaction in the batch.
    function _handleBatchExecutionAndReturnData(
        bytes calldata executionCalldata,
        ExecType execType
    )
        internal
        returns (bytes[] memory returnData)
    {
        Execution[] calldata executions = executionCalldata.decodeBatch();
        if (execType == EXECTYPE_DEFAULT) returnData = _executeBatch(executions);
        else if (execType == EXECTYPE_TRY) returnData = _tryExecuteBatch(executions);
        else revert UnsupportedExecType(execType);
    }

    /// @dev Executes a single transaction based on the specified execution type.
    /// @param executionCalldata The calldata containing the transaction details (target address, value, and data).
    /// @param execType The execution type, which can be DEFAULT (revert on failure) or TRY (return on failure).
    /// @return returnData An array containing the result of the delegatecall execution.
    function _handleDelegateCallExecutionAndReturnData(
        bytes calldata executionCalldata,
        ExecType execType
    )
        internal
        returns (bytes[] memory returnData)
    {
        (address delegate, bytes calldata callData) = executionCalldata.decodeDelegateCall();
        returnData = new bytes[](1);
        bool success;
        if (execType == EXECTYPE_DEFAULT) {
            returnData[0] = _executeDelegatecall(delegate, callData);
        } else if (execType == EXECTYPE_TRY) {
            (success, returnData[0]) = _tryExecuteDelegatecall(delegate, callData);
            if (!success) emit TryDelegateCallUnsuccessful(callData, returnData[0]);
        } else {
            revert UnsupportedExecType(execType);
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import { ComposableExecutionLib } from "./ComposableExecutionLib.sol";
import { InputParam, OutputParam, ComposableExecution } from "../types/ComposabilityDataTypes.sol";
import { IComposableExecution } from "../interfaces/IComposableExecution.sol";
import { Execution } from "erc7579/interfaces/IERC7579Account.sol";

abstract contract ComposableExecutionBase is IComposableExecution {
    using ComposableExecutionLib for InputParam[];
    using ComposableExecutionLib for OutputParam[];

    /// @dev Override it in the account and introduce additional access control or other checks
    function executeComposable(ComposableExecution[] calldata cExecutions) external payable virtual;

    /// @dev internal function to execute the composable execution flow
    /// First, processes the input parameters and returns the composed calldata
    /// Then, executes the action
    /// Then, processes the output parameters
    function _executeComposable(ComposableExecution[] calldata cExecutions) internal {
        uint256 length = cExecutions.length;
        for (uint256 i; i < length; i++) {
            ComposableExecution calldata cExecution = cExecutions[i];
            Execution memory execution = cExecution.inputParams.processInputs(cExecution.functionSig);
            bytes memory returnData;
            if (execution.target != address(0)) {
                returnData = _executeAction(execution.target, execution.value, execution.callData);
            } else {
                returnData = new bytes(0);
            }
            // TODO: add early sanity check that output params length is > 0
            // so if it is 0, we can not even call processOutputs
            cExecution.outputParams.processOutputs(returnData, address(this));
        }
    }

    /// @dev Override this in the account
    /// using account's native execution approach
    /// we do not use Execution struct as an argument to be as less opinionated as possible
    /// instead we just use standard types
    function _executeAction(
        address to,
        uint256 value,
        bytes memory data
    )
        internal
        virtual
        returns (bytes memory returnData);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// keccak256(abi.encode(uint256(keccak256("initializable.transient.Nexus")) - 1)) & ~bytes32(uint256(0xff));
bytes32 constant INIT_SLOT = 0x90b772c2cb8a51aa7a8a65fc23543c6d022d5b3f8e2b92eed79fba7eef829300;

/// @title Initializable
/// @dev This library provides a way to set a transient flag on a contract to ensure that it is only initialized during
/// the
/// constructor execution. This is useful to prevent a contract from being initialized multiple times.
library Initializable {
    /// @dev Thrown when an attempt to initialize an already initialized contract is made
    error NotInitializable();

    /// @dev Sets the initializable flag in the transient storage slot to true
    function setInitializable() internal {
        bytes32 slot = INIT_SLOT;
        assembly {
            tstore(slot, 0x01)
        }
    }

    /// @dev Checks if the initializable flag is set in the transient storage slot, reverts with NotInitializable if not
    function requireInitializable() internal view {
        bytes32 slot = INIT_SLOT;
        // Load the current value from the slot, revert if 0
        assembly {
            let isInitializable := tload(slot)
            if iszero(isInitializable) {
                mstore(0x0, 0xaed59595) // NotInitializable()
                revert(0x1c, 0x04)
            }
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

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

/// @notice UUPS proxy mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/UUPSUpgradeable.sol)
/// @author Modified from OpenZeppelin
/// (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/utils/UUPSUpgradeable.sol)
///
/// @dev Note:
/// - This implementation is intended to be used with ERC1967 proxies.
/// See: `LibClone.deployERC1967` and related functions.
/// - This implementation is NOT compatible with legacy OpenZeppelin proxies
/// which do not store the implementation at `_ERC1967_IMPLEMENTATION_SLOT`.
abstract contract UUPSUpgradeable is CallContextChecker {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The upgrade failed.
    error UpgradeFailed();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Emitted when the proxy's implementation is upgraded.
    event Upgraded(address indexed implementation);

    /// @dev `keccak256(bytes("Upgraded(address)"))`.
    uint256 private constant _UPGRADED_EVENT_SIGNATURE =
        0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ERC-1967 storage slot for the implementation in the proxy.
    /// `uint256(keccak256("eip1967.proxy.implementation")) - 1`.
    bytes32 internal constant _ERC1967_IMPLEMENTATION_SLOT =
        0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      UUPS OPERATIONS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Please override this function to check if `msg.sender` is authorized
    /// to upgrade the proxy to `newImplementation`, reverting if not.
    /// ```
    ///     function _authorizeUpgrade(address) internal override onlyOwner {}
    /// ```
    function _authorizeUpgrade(address newImplementation) internal virtual;

    /// @dev Returns the storage slot used by the implementation,
    /// as specified in [ERC1822](https://eips.ethereum.org/EIPS/eip-1822).
    ///
    /// Note: The `notDelegated` modifier prevents accidental upgrades to
    /// an implementation that is a proxy contract.
    function proxiableUUID() public view virtual notDelegated returns (bytes32) {
        // This function must always return `_ERC1967_IMPLEMENTATION_SLOT` to comply with ERC1967.
        return _ERC1967_IMPLEMENTATION_SLOT;
    }

    /// @dev Upgrades the proxy's implementation to `newImplementation`.
    /// Emits a {Upgraded} event.
    ///
    /// Note: Passing in empty `data` skips the delegatecall to `newImplementation`.
    function upgradeToAndCall(address newImplementation, bytes calldata data)
        public
        payable
        virtual
        onlyProxy
    {
        _authorizeUpgrade(newImplementation);
        /// @solidity memory-safe-assembly
        assembly {
            newImplementation := shr(96, shl(96, newImplementation)) // Clears upper 96 bits.
            mstore(0x00, returndatasize())
            mstore(0x01, 0x52d1902d) // `proxiableUUID()`.
            let s := _ERC1967_IMPLEMENTATION_SLOT
            // Check if `newImplementation` implements `proxiableUUID` correctly.
            if iszero(eq(mload(staticcall(gas(), newImplementation, 0x1d, 0x04, 0x01, 0x20)), s)) {
                mstore(0x01, 0x55299b49) // `UpgradeFailed()`.
                revert(0x1d, 0x04)
            }
            // Emit the {Upgraded} event.
            log2(codesize(), 0x00, _UPGRADED_EVENT_SIGNATURE, newImplementation)
            sstore(s, newImplementation) // Updates the implementation.

            // Perform a delegatecall to `newImplementation` if `data` is non-empty.
            if data.length {
                // Forwards the `data` to `newImplementation` via delegatecall.
                let m := mload(0x40)
                calldatacopy(m, data.offset, data.length)
                if iszero(
                    delegatecall(gas(), newImplementation, m, data.length, codesize(), 0x00)
                ) {
                    // Bubble up the revert if the call reverts.
                    returndatacopy(m, 0x00, returndatasize())
                    revert(m, returndatasize())
                }
            }
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// ──────────────────────────────────────────────────────────────────────────────
//     _   __    _  __
//    / | / /__ | |/ /_  _______
//   /  |/ / _ \|   / / / / ___/
//  / /|  /  __/   / /_/ (__  )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Accounts compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

import { IAccountConfig } from "./base/IAccountConfig.sol";
import { IExecutionHelper } from "./base/IExecutionHelper.sol";
import { INexusEventsAndErrors } from "./INexusEventsAndErrors.sol";
import { IERC1271 } from "../standard/IERC1271.sol";
import { IAccount } from "account-abstraction/interfaces/IAccount.sol";

/// @title Nexus - INexus Interface
/// @notice Integrates ERC-4337 and ERC-7579 standards to manage smart accounts within the Nexus suite.
/// @dev Consolidates ERC-4337 user operations and ERC-7579 configurations into a unified interface for smart account
/// management.
/// It extends both IERC4337Account and IERC7579Account, enhancing modular capabilities and supporting advanced contract
/// architectures.
/// Includes error definitions for robust handling of common issues such as unsupported module types and execution
/// failures.
/// The initialize function sets up the account with validators and configurations, ensuring readiness for use.
/// @author @livingrockrises | Biconomy | [email protected]
/// @author @aboudjem | Biconomy | [email protected]
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady
interface INexus is IAccountConfig, IExecutionHelper, IERC1271, IAccount, INexusEventsAndErrors {
    /// @notice Initializes the smart account with a validator and custom data.
    /// @dev This method sets up the account for operation, linking it with a validator and initializing it with
    /// specific
    /// data.
    /// Can be called directly or via a factory.
    /// @param initData Encoded data used for the account's configuration during initialization.
    function initializeAccount(bytes calldata initData) external payable;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

import { Execution } from "erc7579/interfaces/IERC7579Account.sol";

/// @title ExecutionLib
/// @author zeroknots.eth | rhinestone.wtf
/// Helper Library for decoding Execution calldata
/// malloc for memory allocation is bad for gas. use this assembly instead
library ExecLib {
    function get2771CallData(bytes calldata cd) internal view returns (bytes memory callData) {
        /// @solidity memory-safe-assembly
        (cd);
        assembly {
            // as per solidity docs
            function allocate(length) -> pos {
                pos := mload(0x40)
                mstore(0x40, add(pos, length))
            }

            callData := allocate(add(calldatasize(), 0x20)) //allocate extra 0x20 to store length
            mstore(callData, add(calldatasize(), 0x14)) //store length, extra 0x14 is for msg.sender address
            calldatacopy(add(callData, 0x20), 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(0x14)
            mstore(senderPtr, shl(96, caller()))
        }
    }

    /**
     * @notice Decode a batch of `Execution` executionBatch from a `bytes` calldata.
     * @dev code is copied from solady's LibERC7579.sol
     * https://github.com/Vectorized/solady/blob/740812cedc9a1fc11e17cb3d4569744367dedf19/src/accounts/LibERC7579.sol#L146
     *      Credits to Vectorized and the Solady Team
     */
    function decodeBatch(bytes calldata executionCalldata) internal pure returns (Execution[] calldata executionBatch) {
        /// @solidity memory-safe-assembly
        assembly {
            let u := calldataload(executionCalldata.offset)
            let s := add(executionCalldata.offset, u)
            let e := sub(add(executionCalldata.offset, executionCalldata.length), 0x20)
            executionBatch.offset := add(s, 0x20)
            executionBatch.length := calldataload(s)
            if or(shr(64, u), gt(add(s, shl(5, executionBatch.length)), e)) {
                mstore(0x00, 0xba597e7e) // `DecodingError()`.
                revert(0x1c, 0x04)
            }
            if executionBatch.length {
                // Perform bounds checks on the decoded `executionBatch`.
                // Loop runs out-of-gas if `executionBatch.length` is big enough to cause overflows.
                for { let i := executionBatch.length } 1 { } {
                    i := sub(i, 1)
                    let p := calldataload(add(executionBatch.offset, shl(5, i)))
                    let c := add(executionBatch.offset, p)
                    let q := calldataload(add(c, 0x40))
                    let o := add(c, q)
                    // forgefmt: disable-next-item
                    if or(shr(64, or(calldataload(o), or(p, q))),
                        or(gt(add(c, 0x40), e), gt(add(o, calldataload(o)), e))) {
                        mstore(0x00, 0xba597e7e) // `DecodingError()`.
                        revert(0x1c, 0x04)
                    }
                    if iszero(i) { break }
                }
            }
        }
    }

    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 decodeDelegateCall(bytes calldata executionCalldata)
        internal
        pure
        returns (address delegate, bytes calldata callData)
    {
        // destructure executionCallData according to single exec
        delegate = address(uint160(bytes20(executionCalldata[0:20])));
        callData = executionCalldata[20:];
    }

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

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// solhint-disable-next-line no-unused-import
import { MODE_MODULE_ENABLE, MODE_PREP, MODE_VALIDATION } from "../../types/Constants.sol";

/**
 * Nonce structure
 *     [3 bytes empty][1 bytes validation mode][20 bytes validator][8 bytes nonce]
 */
library NonceLib {
    /// @dev Parses validator address out of nonce
    /// @param nonce The nonce
    /// @return validator
    function getValidator(uint256 nonce) internal pure returns (address validator) {
        assembly {
            validator := shr(96, shl(32, nonce))
        }
    }

    /// @dev Detects if Validation Mode is Module Enable Mode
    /// @param nonce The nonce
    /// @return res boolean result, true if it is the Module Enable Mode
    function isModuleEnableMode(uint256 nonce) internal pure returns (bool res) {
        assembly {
            let vmode := byte(3, nonce)
            res := eq(shl(248, vmode), MODE_MODULE_ENABLE)
        }
    }

    /// @dev Detects if the validator provided in the nonce is address(0)
    /// which means the default validator is used
    /// @param nonce The nonce
    /// @return res boolean result, true if it is the Default Validator Mode
    function isDefaultValidatorMode(uint256 nonce) internal pure returns (bool res) {
        assembly {
            res := iszero(shr(96, shl(32, nonce)))
        }
    }

    /// @dev Detects if Validation Mode is Prep Mode
    /// @param nonce The nonce
    /// @return res boolean result, true if it is the Prep Mode
    function isPrepMode(uint256 nonce) internal pure returns (bool res) {
        assembly {
            let vmode := byte(3, nonce)
            res := eq(shl(248, vmode), MODE_PREP)
        }
    }

    /// @dev Detects if Validation Mode is Validate Mode
    /// @param nonce The nonce
    /// @return res boolean result, true if it is the Validation Mode
    function isValidateMode(uint256 nonce) internal pure returns (bool res) {
        assembly {
            let vmode := byte(3, nonce)
            res := eq(shl(248, vmode), MODE_VALIDATION)
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Sentinel address
address constant SENTINEL = address(0x1);
// Zero address
address constant ZERO_ADDRESS = address(0x0);

/**
 * @title SentinelListLib
 * @dev Library for managing a linked list of addresses
 * @author Rhinestone
 */
library SentinelListLib {
    // Struct to hold the linked list
    struct SentinelList {
        mapping(address => address) entries;
    }

    error LinkedList_AlreadyInitialized();
    error LinkedList_InvalidPage();
    error LinkedList_InvalidEntry(address entry);
    error LinkedList_EntryAlreadyInList(address entry);

    /**
     * Initialize the linked list
     *
     * @param self The linked list
     */
    function init(SentinelList storage self) internal {
        if (alreadyInitialized(self)) revert LinkedList_AlreadyInitialized();
        self.entries[SENTINEL] = SENTINEL;
    }

    /**
     * Check if the linked list is already initialized
     *
     * @param self The linked list
     *
     * @return bool True if the linked list is already initialized
     */
    function alreadyInitialized(SentinelList storage self) internal view returns (bool) {
        return self.entries[SENTINEL] != ZERO_ADDRESS;
    }

    /**
     * Get the next entry in the linked list
     *
     * @param self The linked list
     * @param entry The current entry
     *
     * @return address The next entry
     */
    function getNext(SentinelList storage self, address entry) internal view returns (address) {
        if (entry == ZERO_ADDRESS) {
            revert LinkedList_InvalidEntry(entry);
        }
        return self.entries[entry];
    }

    /**
     * Push a new entry to the linked list
     *
     * @param self The linked list
     * @param newEntry The new entry
     */
    function push(SentinelList storage self, address newEntry) internal {
        if (newEntry == ZERO_ADDRESS || newEntry == SENTINEL) {
            revert LinkedList_InvalidEntry(newEntry);
        }
        if (self.entries[newEntry] != ZERO_ADDRESS) revert LinkedList_EntryAlreadyInList(newEntry);
        self.entries[newEntry] = self.entries[SENTINEL];
        self.entries[SENTINEL] = newEntry;
    }

    /**
     * Safe push a new entry to the linked list
     * @dev This ensures that the linked list is initialized and initializes it if it is not
     *
     * @param self The linked list
     * @param newEntry The new entry
     */
    function safePush(SentinelList storage self, address newEntry) internal {
        if (!alreadyInitialized({ self: self })) {
            init({ self: self });
        }
        push({ self: self, newEntry: newEntry });
    }

    /**
     * Pop an entry from the linked list
     *
     * @param self The linked list
     * @param prevEntry The entry before the entry to pop
     * @param popEntry The entry to pop
     */
    function pop(SentinelList storage self, address prevEntry, address popEntry) internal {
        if (popEntry == ZERO_ADDRESS || popEntry == SENTINEL) {
            revert LinkedList_InvalidEntry(prevEntry);
        }
        if (self.entries[prevEntry] != popEntry) revert LinkedList_InvalidEntry(popEntry);
        self.entries[prevEntry] = self.entries[popEntry];
        self.entries[popEntry] = ZERO_ADDRESS;
    }

    /**
     * Pop all entries from the linked list
     *
     * @param self The linked list
     */
    function popAll(SentinelList storage self) internal {
        address next = self.entries[SENTINEL];
        while (next != ZERO_ADDRESS) {
            address current = next;
            next = self.entries[next];
            self.entries[current] = ZERO_ADDRESS;
        }
    }

    /**
     * Check if the linked list contains an entry
     *
     * @param self The linked list
     * @param entry The entry to check
     *
     * @return bool True if the linked list contains the entry
     */
    function contains(SentinelList storage self, address entry) internal view returns (bool) {
        return SENTINEL != entry && self.entries[entry] != ZERO_ADDRESS;
    }

    /**
     * Get all entries in the linked list
     *
     * @param self The linked list
     * @param start The start entry
     * @param pageSize The page size
     *
     * @return array All entries in the linked list
     * @return next The next entry
     */
    function getEntriesPaginated(
        SentinelList storage self,
        address start,
        uint256 pageSize
    )
        internal
        view
        returns (address[] memory array, address next)
    {
        if (start != SENTINEL && !contains(self, start)) revert LinkedList_InvalidEntry(start);
        if (pageSize == 0) revert LinkedList_InvalidPage();
        // Init array with max page size
        array = new address[](pageSize);

        // Populate return array
        uint256 entryCount = 0;
        next = self.entries[start];
        while (next != ZERO_ADDRESS && next != SENTINEL && entryCount < pageSize) {
            array[entryCount] = next;
            next = self.entries[next];
            entryCount++;
        }

        /**
         * Because of the argument validation, we can assume that the loop will always iterate over
         * the valid entry list values
         *       and the `next` variable will either be an enabled entry or a sentinel address
         * (signalling the end).
         *
         *       If we haven't reached the end inside the loop, we need to set the next pointer to
         * the last element of the entry array
         *       because the `next` variable (which is a entry by itself) acting as a pointer to the
         * start of the next page is neither
         *       incSENTINELrent page, nor will it be included in the next one if you pass it as a
         * start.
         */
        if (next != SENTINEL && entryCount > 0) {
            next = array[entryCount - 1];
        }
        // Set correct size of returned array
        // solhint-disable-next-line no-inline-assembly
        /// @solidity memory-safe-assembly
        assembly {
            mstore(array, entryCount)
        }
    }
}

File 12 of 44 : DataTypes.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// ──────────────────────────────────────────────────────────────────────────────
//     _   __    _  __
//    / | / /__ | |/ /_  _______
//   /  |/ / _ \|   / / / / ___/
//  / /|  /  __/   / /_/ (__  )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Accounts compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

/// @title Emergency Uninstall
/// @notice Struct to encapsulate emergency uninstall data for a hook
struct EmergencyUninstall {
    /// @notice The address of the hook to be uninstalled
    address hook;
    /// @notice The hook type identifier
    uint256 hookType;
    /// @notice Data used to uninstall the hook
    bytes deInitData;
    /// @notice Nonce used to prevent replay attacks
    uint256 nonce;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import { EfficientHashLib } from "solady/utils/EfficientHashLib.sol";
import { LibBit } from "solady/utils/LibBit.sol";
import { ECDSA } from "solady/utils/ECDSA.sol";
import { LibEIP7702 } from "solady/accounts/LibEIP7702.sol";

/// @title LibPREP
/// @notice A library to encapsulate the PREP (Provably Rootless EIP-7702 Proxy) workflow.
/// See: https://blog.biconomy.io/prep-deep-dive/
library LibPREP {
    /// @dev Validates if `digest` and `saltAndDelegation` results in `target`.
    /// `saltAndDelegation` is `bytes32((uint256(salt) << 160) | uint160(delegation))`.
    /// Returns a non-zero `r` for the PREP signature, if valid.
    /// Otherwise returns 0.
    /// `r` will be less than `2**160`, allowing for optional storage packing.
    function rPREP(address target, bytes32 digest, bytes32 saltAndDelegation) internal view returns (bytes32 r) {
        r = (EfficientHashLib.hash(digest, saltAndDelegation >> 160) << 96) >> 96;
        if (!isValid(target, r, address(uint160(uint256(saltAndDelegation))))) r = 0;
    }

    /// @dev Returns if `r` and `delegation` results in `target`.
    function isValid(address target, bytes32 r, address delegation) internal view returns (bool) {
        bytes32 s = EfficientHashLib.hash(r);
        bytes32 h; // `keccak256(abi.encodePacked(hex"05", LibRLP.p(0).p(delegation).p(0).encode()))`.
        assembly ("memory-safe") {
            mstore(0x20, 0x80)
            mstore(0x1f, delegation)
            mstore(0x0b, 0x05d78094)
            h := keccak256(0x27, 0x19)
        }
        return LibBit.and(target != address(0), ECDSA.tryRecover(h, 27, r, s) == target);
    }

    /// @dev Returns if `target` is a PREP.
    function isPREP(address target, bytes32 r) internal view returns (bool) {
        address delegation = LibEIP7702.delegationOf(target);
        return !LibBit.or(delegation == address(0), r == 0) && isValid(target, r, delegation);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Gas optimized ECDSA wrapper.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)
///
/// @dev Note:
/// - The recovery functions use the ecrecover precompile (0x1).
/// - As of Solady version 0.0.68, the `recover` variants will revert upon recovery failure.
///   This is for more safety by default.
///   Use the `tryRecover` variants if you need to get the zero address back
///   upon recovery failure instead.
/// - As of Solady version 0.0.134, all `bytes signature` variants accept both
///   regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures.
///   See: https://eips.ethereum.org/EIPS/eip-2098
///   This is for calldata efficiency on smart accounts prevalent on L2s.
///
/// WARNING! Do NOT directly use signatures as unique identifiers:
/// - The recovery operations do NOT check if a signature is non-malleable.
/// - Use a nonce in the digest to prevent replay attacks on the same contract.
/// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts.
///   EIP-712 also enables readable signing of typed data for better user safety.
/// - If you need a unique hash from a signature, please use the `canonicalHash` functions.
library ECDSA {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The order of the secp256k1 elliptic curve.
    uint256 internal constant N =
        0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141;

    /// @dev `N/2 + 1`. Used for checking the malleability of the signature.
    uint256 private constant _HALF_N_PLUS_1 =
        0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CUSTOM ERRORS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The signature is invalid.
    error InvalidSignature();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    RECOVERY OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
    function recover(bytes32 hash, bytes memory signature) internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            for { let m := mload(0x40) } 1 {
                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                revert(0x1c, 0x04)
            } {
                switch mload(signature)
                case 64 {
                    let vs := mload(add(signature, 0x40))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                }
                case 65 {
                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                    mstore(0x60, mload(add(signature, 0x40))) // `s`.
                }
                default { continue }
                mstore(0x00, hash)
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                if returndatasize() { break }
            }
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
    function recoverCalldata(bytes32 hash, bytes calldata signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            for { let m := mload(0x40) } 1 {
                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                revert(0x1c, 0x04)
            } {
                switch signature.length
                case 64 {
                    let vs := calldataload(add(signature.offset, 0x20))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x40, calldataload(signature.offset)) // `r`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                }
                case 65 {
                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
                    calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
                }
                default { continue }
                mstore(0x00, hash)
                result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                if returndatasize() { break }
            }
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the EIP-2098 short form signature defined by `r` and `vs`.
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            mstore(0x20, add(shr(255, vs), 27)) // `v`.
            mstore(0x40, r)
            mstore(0x60, shr(1, shl(1, vs))) // `s`.
            result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the signature defined by `v`, `r`, `s`.
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            mstore(0x20, and(v, 0xff))
            mstore(0x40, r)
            mstore(0x60, s)
            result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   TRY-RECOVER OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // WARNING!
    // These functions will NOT revert upon recovery failure.
    // Instead, they will return the zero address upon recovery failure.
    // It is critical that the returned address is NEVER compared against
    // a zero address (e.g. an uninitialized address variable).

    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
    function tryRecover(bytes32 hash, bytes memory signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            for { let m := mload(0x40) } 1 {} {
                switch mload(signature)
                case 64 {
                    let vs := mload(add(signature, 0x40))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                }
                case 65 {
                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                    mstore(0x60, mload(add(signature, 0x40))) // `s`.
                }
                default { break }
                mstore(0x00, hash)
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20))
                mstore(0x60, 0) // Restore the zero slot.
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                result := mload(xor(0x60, returndatasize()))
                mstore(0x40, m) // Restore the free memory pointer.
                break
            }
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
    function tryRecoverCalldata(bytes32 hash, bytes calldata signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            for { let m := mload(0x40) } 1 {} {
                switch signature.length
                case 64 {
                    let vs := calldataload(add(signature.offset, 0x20))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x40, calldataload(signature.offset)) // `r`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                }
                case 65 {
                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
                    calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
                }
                default { break }
                mstore(0x00, hash)
                pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20))
                mstore(0x60, 0) // Restore the zero slot.
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                result := mload(xor(0x60, returndatasize()))
                mstore(0x40, m) // Restore the free memory pointer.
                break
            }
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the EIP-2098 short form signature defined by `r` and `vs`.
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            mstore(0x20, add(shr(255, vs), 27)) // `v`.
            mstore(0x40, r)
            mstore(0x60, shr(1, shl(1, vs))) // `s`.
            pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20))
            mstore(0x60, 0) // Restore the zero slot.
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            result := mload(xor(0x60, returndatasize()))
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the signature defined by `v`, `r`, `s`.
    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            mstore(0x20, and(v, 0xff))
            mstore(0x40, r)
            mstore(0x60, s)
            pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20))
            mstore(0x60, 0) // Restore the zero slot.
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            result := mload(xor(0x60, returndatasize()))
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HASHING OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an Ethereum Signed Message, created from a `hash`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, hash) // Store into scratch space for keccak256.
            mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes.
            result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.
        }
    }

    /// @dev Returns an Ethereum Signed Message, created from `s`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    /// Note: Supports lengths of `s` up to 999999 bytes.
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let sLength := mload(s)
            let o := 0x20
            mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded.
            mstore(0x00, 0x00)
            // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.
            for { let temp := sLength } 1 {} {
                o := sub(o, 1)
                mstore8(o, add(48, mod(temp, 10)))
                temp := div(temp, 10)
                if iszero(temp) { break }
            }
            let n := sub(0x3a, o) // Header length: `26 + 32 - o`.
            // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.
            returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))
            mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.
            result := keccak256(add(s, sub(0x20, n)), add(n, sLength))
            mstore(s, sLength) // Restore the length.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  CANONICAL HASH FUNCTIONS                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // The following functions return the hash of the signature in its canonicalized format,
    // which is the 65-byte `abi.encodePacked(r, s, uint8(v))`, where `v` is either 27 or 28.
    // If `s` is greater than `N / 2` then it will be converted to `N - s`
    // and the `v` value will be flipped.
    // If the signature has an invalid length, or if `v` is invalid,
    // a uniquely corrupt hash will be returned.
    // These functions are useful for "poor-mans-VRF".

    /// @dev Returns the canonical hash of `signature`.
    function canonicalHash(bytes memory signature) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let l := mload(signature)
            for {} 1 {} {
                mstore(0x00, mload(add(signature, 0x20))) // `r`.
                let s := mload(add(signature, 0x40))
                let v := mload(add(signature, 0x41))
                if eq(l, 64) {
                    v := add(shr(255, s), 27)
                    s := shr(1, shl(1, s))
                }
                if iszero(lt(s, _HALF_N_PLUS_1)) {
                    v := xor(v, 7)
                    s := sub(N, s)
                }
                mstore(0x21, v)
                mstore(0x20, s)
                result := keccak256(0x00, 0x41)
                mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
                break
            }

            // If the length is neither 64 nor 65, return a uniquely corrupted hash.
            if iszero(lt(sub(l, 64), 2)) {
                // `bytes4(keccak256("InvalidSignatureLength"))`.
                result := xor(keccak256(add(signature, 0x20), l), 0xd62f1ab2)
            }
        }
    }

    /// @dev Returns the canonical hash of `signature`.
    function canonicalHashCalldata(bytes calldata signature)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            for {} 1 {} {
                mstore(0x00, calldataload(signature.offset)) // `r`.
                let s := calldataload(add(signature.offset, 0x20))
                let v := calldataload(add(signature.offset, 0x21))
                if eq(signature.length, 64) {
                    v := add(shr(255, s), 27)
                    s := shr(1, shl(1, s))
                }
                if iszero(lt(s, _HALF_N_PLUS_1)) {
                    v := xor(v, 7)
                    s := sub(N, s)
                }
                mstore(0x21, v)
                mstore(0x20, s)
                result := keccak256(0x00, 0x41)
                mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
                break
            }
            // If the length is neither 64 nor 65, return a uniquely corrupted hash.
            if iszero(lt(sub(signature.length, 64), 2)) {
                calldatacopy(mload(0x40), signature.offset, signature.length)
                // `bytes4(keccak256("InvalidSignatureLength"))`.
                result := xor(keccak256(mload(0x40), signature.length), 0xd62f1ab2)
            }
        }
    }

    /// @dev Returns the canonical hash of `signature`.
    function canonicalHash(bytes32 r, bytes32 vs) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, r) // `r`.
            let v := add(shr(255, vs), 27)
            let s := shr(1, shl(1, vs))
            mstore(0x21, v)
            mstore(0x20, s)
            result := keccak256(0x00, 0x41)
            mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
        }
    }

    /// @dev Returns the canonical hash of `signature`.
    function canonicalHash(uint8 v, bytes32 r, bytes32 s) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, r) // `r`.
            if iszero(lt(s, _HALF_N_PLUS_1)) {
                v := xor(v, 7)
                s := sub(N, s)
            }
            mstore(0x21, v)
            mstore(0x20, s)
            result := keccak256(0x00, 0x41)
            mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   EMPTY CALLDATA HELPERS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an empty calldata bytes.
    function emptySignature() internal pure returns (bytes calldata signature) {
        /// @solidity memory-safe-assembly
        assembly {
            signature.length := 0
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import { PackedUserOperation } from "account-abstraction/interfaces/PackedUserOperation.sol";

uint256 constant VALIDATION_SUCCESS = 0;
uint256 constant VALIDATION_FAILED = 1;

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_PREVALIDATION_HOOK_ERC1271 = 8;
uint256 constant MODULE_TYPE_PREVALIDATION_HOOK_ERC4337 = 9;

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;

    /**
     * @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;

    /**
     * @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
        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 {
    function preCheck(
        address msgSender,
        uint256 msgValue,
        bytes calldata msgData
    )
        external
        returns (bytes memory hookData);

    function postCheck(bytes calldata hookData) external;
}

interface IFallback is IModule { }

interface IPreValidationHookERC1271 is IModule {
    function preValidationHookERC1271(
        address sender,
        bytes32 hash,
        bytes calldata data
    )
        external
        view
        returns (bytes32 hookHash, bytes memory hookSignature);
}

interface IPreValidationHookERC4337 is IModule {
    function preValidationHookERC4337(
        PackedUserOperation calldata userOp,
        uint256 missingAccountFunds,
        bytes32 userOpHash
    )
        external
        returns (bytes32 hookHash, bytes memory hookSignature);
}

File 16 of 44 : Constants.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// STX Sig types
bytes3 constant SIG_TYPE_MEE_FLOW = 0x177eee;

bytes4 constant SIG_TYPE_SIMPLE = 0x177eee00;
bytes4 constant SIG_TYPE_ON_CHAIN = 0x177eee01;
bytes4 constant SIG_TYPE_ERC20_PERMIT = 0x177eee02;
// ...other sig types: ERC-7683, Permit2, etc

// EIP-1271 constants
bytes4 constant ERC1271_SUCCESS = 0x1626ba7e;
bytes4 constant ERC1271_FAILED = 0xffffffff;

// Node PM constants
bytes4 constant NODE_PM_MODE_USER = 0x170de000; // refund goes to the user
bytes4 constant NODE_PM_MODE_DAPP = 0x170de001; // refund goes to the dApp
bytes4 constant NODE_PM_MODE_KEEP = 0x170de002; // no refund as node sponsored

bytes4 constant NODE_PM_PREMIUM_PERCENT = 0x9ee4ce00; // premium percentage
bytes4 constant NODE_PM_PREMIUM_FIXED = 0x9ee4ce01;

// ERC-4337 validation constants
uint256 constant VALIDATION_SUCCESS = 0;
uint256 constant VALIDATION_FAILED = 1;

// Module type identifiers
uint256 constant MODULE_TYPE_MULTI = 0; // Module type identifier for Multitype install
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_STATELESS_VALIDATOR = 7;
uint256 constant MODULE_TYPE_PREVALIDATION_HOOK_ERC1271 = 8;
uint256 constant MODULE_TYPE_PREVALIDATION_HOOK_ERC4337 = 9;

// Nexus Validation modes
bytes1 constant MODE_VALIDATION = 0x00;
bytes1 constant MODE_MODULE_ENABLE = 0x01;
bytes1 constant MODE_PREP = 0x02;

// ERC-7739 support constants
bytes4 constant SUPPORTS_ERC7739 = 0x77390000;
bytes4 constant SUPPORTS_ERC7739_V1 = 0x77390001;

// Typehashes

// keccak256("ModuleEnableMode(address module,uint256 moduleType,bytes32 userOpHash,bytes initData)")
bytes32 constant MODULE_ENABLE_MODE_TYPE_HASH = 0xf6c866c1cd985ce61f030431e576c0e82887de0643dfa8a2e6efc3463e638ed0;

// keccak256("EmergencyUninstall(address hook,uint256 hookType,bytes deInitData,uint256 nonce)")
bytes32 constant EMERGENCY_UNINSTALL_TYPE_HASH = 0xd3ddfc12654178cc44d4a7b6b969cfdce7ffe6342326ba37825314cffa0fba9c;

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

/// @title ModeLib
/// @author zeroknots.eth | rhinestone.wtf
/// To allow smart accounts to be very simple, but allow for more complex execution, A custom mode
/// encoding is used.
///    Function Signature of execute function:
///           function execute(ExecutionMode mode, bytes calldata executionCalldata) external payable;
/// This allows for a single bytes32 to be used to encode the execution mode, calltype, execType and
/// context.
/// NOTE: Simple Account implementations only have to scope for the most significant byte. Account  that
/// implement
/// more complex execution modes may use the entire bytes32.
///
/// |--------------------------------------------------------------------|
/// | CALLTYPE  | EXECTYPE  |   UNUSED   | ModeSelector  |  ModePayload  |
/// |--------------------------------------------------------------------|
/// | 1 byte    | 1 byte    |   4 bytes  | 4 bytes       |   22 bytes    |
/// |--------------------------------------------------------------------|
///
/// CALLTYPE: 1 byte
/// CallType is used to determine how the executeCalldata paramter of the execute function has to be
/// decoded.
/// It can be either single, batch or delegatecall. In the future different calls could be added.
/// CALLTYPE can be used by a validation module to determine how to decode <userOp.callData[36:]>.
///
/// EXECTYPE: 1 byte
/// ExecType is used to determine how the account should handle the execution.
/// It can indicate if the execution should revert on failure or continue execution.
/// In the future more execution modes may be added.
/// Default Behavior (EXECTYPE = 0x00) is to revert on a single failed execution. If one execution in
/// a batch fails, the entire batch is reverted
///
/// UNUSED: 4 bytes
/// Unused bytes are reserved for future use.
///
/// ModeSelector: bytes4
/// The "optional" mode selector can be used by account vendors, to implement custom behavior in
/// their accounts.
/// the way a ModeSelector is to be calculated is bytes4(keccak256("vendorname.featurename"))
/// this is to prevent collisions between different vendors, while allowing innovation and the
/// development of new features without coordination between ERC-7579 implementing accounts
///
/// ModePayload: 22 bytes
/// Mode payload is used to pass additional data to the smart account execution, this may be
/// interpreted depending on the ModeSelector
///
/// ExecutionCallData: n bytes
/// single, delegatecall or batch exec abi.encoded as bytes

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

type CallType is bytes1;

type ExecType is bytes1;

type ModeSelector is bytes4;

type ModePayload is bytes22;

// 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);

// @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);

ModeSelector constant MODE_DEFAULT = ModeSelector.wrap(bytes4(0x00000000));
// Example declaration of a custom mode selector
ModeSelector constant MODE_OFFSET = ModeSelector.wrap(bytes4(keccak256("default.mode.offset")));

/// @dev ModeLib is a helper library to encode/decode ModeCodes
library ModeLib {
    function decode(ExecutionMode mode)
        internal
        pure
        returns (CallType _calltype, ExecType _execType, ModeSelector _modeSelector, ModePayload _modePayload)
    {
        assembly {
            _calltype := mode
            _execType := shl(8, mode)
            _modeSelector := shl(48, mode)
            _modePayload := shl(80, mode)
        }
    }

    function decodeBasic(ExecutionMode mode) internal pure returns (CallType _calltype, ExecType _execType) {
        assembly {
            _calltype := mode
            _execType := shl(8, mode)
        }
    }

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

    function encodeSimpleBatch() internal pure returns (ExecutionMode mode) {
        mode = encode(CALLTYPE_BATCH, EXECTYPE_DEFAULT, MODE_DEFAULT, ModePayload.wrap(0x00));
    }

    function encodeSimpleSingle() internal pure returns (ExecutionMode mode) {
        mode = encode(CALLTYPE_SINGLE, EXECTYPE_DEFAULT, MODE_DEFAULT, ModePayload.wrap(0x00));
    }

    function encodeTrySingle() internal pure returns (ExecutionMode mode) {
        mode = encode(CALLTYPE_SINGLE, EXECTYPE_TRY, MODE_DEFAULT, ModePayload.wrap(0x00));
    }

    function encodeTryBatch() internal pure returns (ExecutionMode mode) {
        mode = encode(CALLTYPE_BATCH, EXECTYPE_TRY, MODE_DEFAULT, ModePayload.wrap(0x00));
    }

    function encodeCustom(CallType callType, ExecType execType) internal pure returns (ExecutionMode mode) {
        mode = encode(callType, execType, MODE_DEFAULT, ModePayload.wrap(0x00));
    }

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

using { _eqModeSelector as == } for ModeSelector global;
using { _eqCallType as == } for CallType global;
using { _uneqCallType 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 _uneqCallType(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);
}

//slither-disable-next-line dead-code
function _eqModeSelector(ModeSelector a, ModeSelector b) pure returns (bool) {
    return ModeSelector.unwrap(a) == ModeSelector.unwrap(b);
}

File 18 of 44 : 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 maxPriorityFeePerGas and maxFeePerGas - Same as EIP-1559 gas parameters.
 * @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;
    bytes paymasterAndData;
    bytes signature;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// ──────────────────────────────────────────────────────────────────────────────
//     _   __    _  __
//    / | / /__ | |/ /_  _______
//   /  |/ / _ \|   / / / / ___/
//  / /|  /  __/   / /_/ (__  )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Accounts compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

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

/// @title Nexus - IBaseAccount
/// @notice Interface for the BaseAccount functionalities compliant with ERC-7579 and ERC-4337.
/// @dev Interface for organizing the base functionalities using the Nexus suite.
/// @author @livingrockrises | Biconomy | [email protected]
/// @author @aboudjem | Biconomy | [email protected]
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady
interface IBaseAccount is IBaseAccountEventsAndErrors {
    /// @notice Adds deposit to the EntryPoint to fund transactions.
    function addDeposit() external payable;

    /// @notice Withdraws ETH from the EntryPoint to a specified address.
    /// @param to The address to receive the withdrawn funds.
    /// @param amount The amount to withdraw.
    function withdrawDepositTo(address to, uint256 amount) external payable;

    /// @notice Returns the current deposit balance of this account on the EntryPoint.
    /// @return The current balance held at the EntryPoint.
    function getDeposit() external view returns (uint256);

    /// @notice Retrieves the address of the EntryPoint contract, currently using version 0.7.
    /// @return The address of the EntryPoint contract.
    function entryPoint() external view returns (address);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// ──────────────────────────────────────────────────────────────────────────────
//     _   __    _  __
//    / | / /__ | |/ /_  _______
//   /  |/ / _ \|   / / / / ___/
//  / /|  /  __/   / /_/ (__  )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Accounts compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

import { IStorage } from "../../interfaces/nexus/base/IStorage.sol";

/// @title Nexus - Storage
/// @notice Manages isolated storage spaces for Modular Smart Account in compliance with ERC-7201 standard to ensure
/// collision-resistant storage.
/// @dev Implements the ERC-7201 namespaced storage pattern to maintain secure and isolated storage sections for
/// different
/// states within Nexus suite.
/// @author @livingrockrises | Biconomy | [email protected]
/// @author @aboudjem | Biconomy | [email protected]
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady
contract Storage is IStorage {
    /// @custom:storage-location erc7201:biconomy.storage.Nexus
    /// ERC-7201 namespaced via `keccak256(abi.encode(uint256(keccak256(bytes("biconomy.storage.Nexus"))) - 1)) &
    /// ~bytes32(uint256(0xff));`
    bytes32 private constant _STORAGE_LOCATION = 0x0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f00;

    /// @dev Utilizes ERC-7201's namespaced storage pattern for isolated storage access. This method computes
    /// the storage slot based on a predetermined location, ensuring collision-resistant storage for contract states.
    /// @custom:storage-location ERC-7201 formula applied to "biconomy.storage.Nexus", facilitating unique
    /// namespace identification and storage segregation, as detailed in the specification.
    /// @return $ The proxy to the `AccountStorage` struct, providing a reference to the namespaced storage slot.
    function _getAccountStorage() internal pure returns (AccountStorage storage $) {
        assembly {
            $.slot := _STORAGE_LOCATION
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

library LocalCallDataParserLib {
    /// @dev Parses the `userOp.signature` to extract the module type, module initialization data,
    ///      enable mode signature, and user operation signature. The `userOp.signature` must be
    ///      encoded in a specific way to be parsed correctly.
    /// @param packedData The packed signature data, typically coming from `userOp.signature`.
    /// @return module The address of the module.
    /// @return moduleType The type of module as a `uint256`.
    /// @return moduleInitData Initialization data specific to the module.
    /// @return enableModeSignature Signature used to enable the module mode.
    /// @return userOpSignature The remaining user operation signature data.
    function parseEnableModeData(bytes calldata packedData)
        internal
        pure
        returns (
            address module,
            uint256 moduleType,
            bytes calldata moduleInitData,
            bytes calldata enableModeSignature,
            bytes calldata userOpSignature
        )
    {
        uint256 p;
        assembly ("memory-safe") {
            p := packedData.offset
            module := shr(96, calldataload(p))

            p := add(p, 0x14)
            moduleType := calldataload(p)

            moduleInitData.length := shr(224, calldataload(add(p, 0x20)))
            moduleInitData.offset := add(p, 0x24)
            p := add(moduleInitData.offset, moduleInitData.length)

            enableModeSignature.length := shr(224, calldataload(p))
            enableModeSignature.offset := add(p, 0x04)
            p := sub(add(enableModeSignature.offset, enableModeSignature.length), packedData.offset)
        }
        userOpSignature = packedData[p:];
    }

    /// @dev Parses the data to obtain types and initdata's for Multi Type module install mode
    /// @param initData Multi Type module init data, abi.encoded
    function parseMultiTypeInitData(bytes calldata initData)
        internal
        pure
        returns (uint256[] calldata types, bytes[] calldata initDatas)
    {
        // equivalent of:
        // (types, initDatas) = abi.decode(initData,(uint[],bytes[]))
        assembly ("memory-safe") {
            let offset := initData.offset
            let baseOffset := offset
            let dataPointer := add(baseOffset, calldataload(offset))

            types.offset := add(dataPointer, 32)
            types.length := calldataload(dataPointer)
            offset := add(offset, 32)

            dataPointer := add(baseOffset, calldataload(offset))
            initDatas.offset := add(dataPointer, 32)
            initDatas.length := calldataload(dataPointer)
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// ──────────────────────────────────────────────────────────────────────────────
//     _   __    _  __
//    / | / /__ | |/ /_  _______
//   /  |/ / _ \|   / / / / ___/
//  / /|  /  __/   / /_/ (__  )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Accounts compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

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

/// @title Nexus - IModuleManager
/// @notice Interface for managing modules within Smart Accounts, providing methods for installation and removal of
/// modules.
/// @dev Extends the IModuleManagerEventsAndErrors interface to include event and error definitions.
/// @author @livingrockrises | Biconomy | [email protected]
/// @author @aboudjem | Biconomy | [email protected]
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady
interface IModuleManager is IModuleManagerEventsAndErrors {
    /// @notice Installs a Module of a specific type onto the smart account.
    /// @param moduleTypeId The identifier for the module type.
    /// @param module The address of the module to be installed.
    /// @param initData Initialization data for configuring the module upon installation.
    function installModule(uint256 moduleTypeId, address module, bytes calldata initData) external payable;

    /// @notice Uninstalls a Module of a specific type from the smart account.
    /// @param moduleTypeId The identifier for the module type being uninstalled.
    /// @param module The address of the module to uninstall.
    /// @param deInitData De-initialization data for configuring the module upon uninstallation.
    function uninstallModule(uint256 moduleTypeId, address module, bytes calldata deInitData) external payable;

    /// @notice Checks if a specific module is installed on the smart account.
    /// @param moduleTypeId The module type identifier to check.
    /// @param module The address of the module.
    /// @param additionalContext Additional information that may be required to verify the module's installation.
    /// @return installed True if the module is installed, false otherwise.
    function isModuleInstalled(
        uint256 moduleTypeId,
        address module,
        bytes calldata additionalContext
    )
        external
        view
        returns (bool installed);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Contract for EIP-712 typed structured data hashing and signing.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EIP712.sol)
/// @author Modified from Solbase (https://github.com/Sol-DAO/solbase/blob/main/src/utils/EIP712.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol)
///
/// @dev Note, this implementation:
/// - Uses `address(this)` for the `verifyingContract` field.
/// - Does NOT use the optional EIP-712 salt.
/// - Does NOT use any EIP-712 extensions.
/// This is for simplicity and to save gas.
/// If you need to customize, please fork / modify accordingly.
abstract contract EIP712 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  CONSTANTS AND IMMUTABLES                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`.
    bytes32 internal constant _DOMAIN_TYPEHASH =
        0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

    /// @dev `keccak256("EIP712Domain(string name,string version,address verifyingContract)")`.
    /// This is only used in `_hashTypedDataSansChainId`.
    bytes32 internal constant _DOMAIN_TYPEHASH_SANS_CHAIN_ID =
        0x91ab3d17e3a50a9d89e63fd30b92be7f5336b03b287bb946787a83a9d62a2766;

    /// @dev `keccak256("EIP712Domain(string name,string version)")`.
    /// This is only used in `_hashTypedDataSansChainIdAndVerifyingContract`.
    bytes32 internal constant _DOMAIN_TYPEHASH_SANS_CHAIN_ID_AND_VERIFYING_CONTRACT =
        0xb03948446334eb9b2196d5eb166f69b9d49403eb4a12f36de8d3f9f3cb8e15c3;

    /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId)")`.
    /// This is only used in `_hashTypedDataSansVerifyingContract`.
    bytes32 internal constant _DOMAIN_TYPEHASH_SANS_VERIFYING_CONTRACT =
        0xc2f8787176b8ac6bf7215b4adcc1e069bf4ab82d9ab1df05a57a91d425935b6e;

    uint256 private immutable _cachedThis;
    uint256 private immutable _cachedChainId;
    bytes32 private immutable _cachedNameHash;
    bytes32 private immutable _cachedVersionHash;
    bytes32 private immutable _cachedDomainSeparator;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CONSTRUCTOR                         */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Cache the hashes for cheaper runtime gas costs.
    /// In the case of upgradeable contracts (i.e. proxies),
    /// or if the chain id changes due to a hard fork,
    /// the domain separator will be seamlessly calculated on-the-fly.
    constructor() {
        _cachedThis = uint256(uint160(address(this)));
        _cachedChainId = block.chainid;

        string memory name;
        string memory version;
        if (!_domainNameAndVersionMayChange()) (name, version) = _domainNameAndVersion();
        bytes32 nameHash = _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(name));
        bytes32 versionHash =
            _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(version));
        _cachedNameHash = nameHash;
        _cachedVersionHash = versionHash;

        bytes32 separator;
        if (!_domainNameAndVersionMayChange()) {
            /// @solidity memory-safe-assembly
            assembly {
                let m := mload(0x40) // Load the free memory pointer.
                mstore(m, _DOMAIN_TYPEHASH)
                mstore(add(m, 0x20), nameHash)
                mstore(add(m, 0x40), versionHash)
                mstore(add(m, 0x60), chainid())
                mstore(add(m, 0x80), address())
                separator := keccak256(m, 0xa0)
            }
        }
        _cachedDomainSeparator = separator;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   FUNCTIONS TO OVERRIDE                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Please override this function to return the domain name and version.
    /// ```
    ///     function _domainNameAndVersion()
    ///         internal
    ///         pure
    ///         virtual
    ///         returns (string memory name, string memory version)
    ///     {
    ///         name = "Solady";
    ///         version = "1";
    ///     }
    /// ```
    ///
    /// Note: If the returned result may change after the contract has been deployed,
    /// you must override `_domainNameAndVersionMayChange()` to return true.
    function _domainNameAndVersion()
        internal
        view
        virtual
        returns (string memory name, string memory version);

    /// @dev Returns if `_domainNameAndVersion()` may change
    /// after the contract has been deployed (i.e. after the constructor).
    /// Default: false.
    function _domainNameAndVersionMayChange() internal pure virtual returns (bool result) {}

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HASHING OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the EIP-712 domain separator.
    function _domainSeparator() internal view virtual returns (bytes32 separator) {
        if (_domainNameAndVersionMayChange()) {
            separator = _buildDomainSeparator();
        } else {
            separator = _cachedDomainSeparator;
            if (_cachedDomainSeparatorInvalidated()) separator = _buildDomainSeparator();
        }
    }

    /// @dev Returns the hash of the fully encoded EIP-712 message for this domain,
    /// given `structHash`, as defined in
    /// https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct.
    ///
    /// The hash can be used together with {ECDSA-recover} to obtain the signer of a message:
    /// ```
    ///     bytes32 digest = _hashTypedData(keccak256(abi.encode(
    ///         keccak256("Mail(address to,string contents)"),
    ///         mailTo,
    ///         keccak256(bytes(mailContents))
    ///     )));
    ///     address signer = ECDSA.recover(digest, signature);
    /// ```
    function _hashTypedData(bytes32 structHash) internal view virtual returns (bytes32 digest) {
        // We will use `digest` to store the domain separator to save a bit of gas.
        if (_domainNameAndVersionMayChange()) {
            digest = _buildDomainSeparator();
        } else {
            digest = _cachedDomainSeparator;
            if (_cachedDomainSeparatorInvalidated()) digest = _buildDomainSeparator();
        }
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the digest.
            mstore(0x00, 0x1901000000000000) // Store "\x19\x01".
            mstore(0x1a, digest) // Store the domain separator.
            mstore(0x3a, structHash) // Store the struct hash.
            digest := keccak256(0x18, 0x42)
            // Restore the part of the free memory slot that was overwritten.
            mstore(0x3a, 0)
        }
    }

    /// @dev Variant of `_hashTypedData` that excludes the chain ID.
    /// Included for the niche use case of cross-chain workflows.
    function _hashTypedDataSansChainId(bytes32 structHash)
        internal
        view
        virtual
        returns (bytes32 digest)
    {
        (string memory name, string memory version) = _domainNameAndVersion();
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Load the free memory pointer.
            mstore(0x00, _DOMAIN_TYPEHASH_SANS_CHAIN_ID)
            mstore(0x20, keccak256(add(name, 0x20), mload(name)))
            mstore(0x40, keccak256(add(version, 0x20), mload(version)))
            mstore(0x60, address())
            // Compute the digest.
            mstore(0x20, keccak256(0x00, 0x80)) // Store the domain separator.
            mstore(0x00, 0x1901) // Store "\x19\x01".
            mstore(0x40, structHash) // Store the struct hash.
            digest := keccak256(0x1e, 0x42)
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero pointer.
        }
    }

    /// @dev Variant of `_hashTypedData` that excludes the chain ID and verifying contract.
    /// Included for the niche use case of cross-chain and multi-verifier workflows.
    function _hashTypedDataSansChainIdAndVerifyingContract(bytes32 structHash)
        internal
        view
        virtual
        returns (bytes32 digest)
    {
        (string memory name, string memory version) = _domainNameAndVersion();
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Load the free memory pointer.
            mstore(0x00, _DOMAIN_TYPEHASH_SANS_CHAIN_ID_AND_VERIFYING_CONTRACT)
            mstore(0x20, keccak256(add(name, 0x20), mload(name)))
            mstore(0x40, keccak256(add(version, 0x20), mload(version)))
            // Compute the digest.
            mstore(0x20, keccak256(0x00, 0x60)) // Store the domain separator.
            mstore(0x00, 0x1901) // Store "\x19\x01".
            mstore(0x40, structHash) // Store the struct hash.
            digest := keccak256(0x1e, 0x42)
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero pointer.
        }
    }

    /// @dev Variant of `_hashTypedData` that excludes the chain ID and verifying contract.
    /// Included for the niche use case of multi-verifier workflows.
    function _hashTypedDataSansVerifyingContract(bytes32 structHash)
        internal
        view
        virtual
        returns (bytes32 digest)
    {
        (string memory name, string memory version) = _domainNameAndVersion();
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Load the free memory pointer.
            mstore(0x00, _DOMAIN_TYPEHASH_SANS_VERIFYING_CONTRACT)
            mstore(0x20, keccak256(add(name, 0x20), mload(name)))
            mstore(0x40, keccak256(add(version, 0x20), mload(version)))
            mstore(0x60, chainid())
            // Compute the digest.
            mstore(0x20, keccak256(0x00, 0x80)) // Store the domain separator.
            mstore(0x00, 0x1901) // Store "\x19\x01".
            mstore(0x40, structHash) // Store the struct hash.
            digest := keccak256(0x1e, 0x42)
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero pointer.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    EIP-5267 OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev See: https://eips.ethereum.org/EIPS/eip-5267
    function eip712Domain()
        public
        view
        virtual
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        )
    {
        fields = hex"0f"; // `0b01111`.
        (name, version) = _domainNameAndVersion();
        chainId = block.chainid;
        verifyingContract = address(this);
        salt = salt; // `bytes32(0)`.
        extensions = extensions; // `new uint256[](0)`.
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the EIP-712 domain separator.
    function _buildDomainSeparator() private view returns (bytes32 separator) {
        // We will use `separator` to store the name hash to save a bit of gas.
        bytes32 versionHash;
        if (_domainNameAndVersionMayChange()) {
            (string memory name, string memory version) = _domainNameAndVersion();
            separator = keccak256(bytes(name));
            versionHash = keccak256(bytes(version));
        } else {
            separator = _cachedNameHash;
            versionHash = _cachedVersionHash;
        }
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Load the free memory pointer.
            mstore(m, _DOMAIN_TYPEHASH)
            mstore(add(m, 0x20), separator) // Name hash.
            mstore(add(m, 0x40), versionHash)
            mstore(add(m, 0x60), chainid())
            mstore(add(m, 0x80), address())
            separator := keccak256(m, 0xa0)
        }
    }

    /// @dev Returns if the cached domain separator has been invalidated.
    function _cachedDomainSeparatorInvalidated() private view returns (bool result) {
        uint256 cachedChainId = _cachedChainId;
        uint256 cachedThis = _cachedThis;
        /// @solidity memory-safe-assembly
        assembly {
            result := iszero(and(eq(chainid(), cachedChainId), eq(address(), cachedThis)))
        }
    }
}

// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.7.6;

library ExcessivelySafeCall {
    uint256 constant LOW_28_MASK =
        0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff;

    /// @notice Use when you _really_ really _really_ don't trust the called
    /// contract. This prevents the called contract from causing reversion of
    /// the caller in as many ways as we can.
    /// @dev The main difference between this and a solidity low-level call is
    /// that we limit the number of bytes that the callee can cause to be
    /// copied to caller memory. This prevents stupid things like malicious
    /// contracts returning 10,000,000 bytes causing a local OOG when copying
    /// to memory.
    /// @param _target The address to call
    /// @param _gas The amount of gas to forward to the remote contract
    /// @param _value The value in wei to send to the remote contract
    /// @param _maxCopy The maximum number of bytes of returndata to copy
    /// to memory.
    /// @param _calldata The data to send to the remote contract
    /// @return success and returndata, as `.call()`. Returndata is capped to
    /// `_maxCopy` bytes.
    function excessivelySafeCall(
        address _target,
        uint256 _gas,
        uint256 _value,
        uint16 _maxCopy,
        bytes memory _calldata
    ) internal returns (bool, bytes memory) {
        // set up for assembly call
        uint256 _toCopy;
        bool _success;
        bytes memory _returnData = new bytes(_maxCopy);
        // dispatch message to recipient
        // by assembly calling "handle" function
        // we call via assembly to avoid memcopying a very large returndata
        // returned by a malicious contract
        assembly {
            _success := call(
                _gas, // gas
                _target, // recipient
                _value, // ether value
                add(_calldata, 0x20), // inloc
                mload(_calldata), // inlen
                0, // outloc
                0 // outlen
            )
            // limit our copy to 256 bytes
            _toCopy := returndatasize()
            if gt(_toCopy, _maxCopy) {
                _toCopy := _maxCopy
            }
            // Store the length of the copied bytes
            mstore(_returnData, _toCopy)
            // copy the bytes from returndata[0:_toCopy]
            returndatacopy(add(_returnData, 0x20), 0, _toCopy)
        }
        return (_success, _returnData);
    }

    /// @notice Use when you _really_ really _really_ don't trust the called
    /// contract. This prevents the called contract from causing reversion of
    /// the caller in as many ways as we can.
    /// @dev The main difference between this and a solidity low-level call is
    /// that we limit the number of bytes that the callee can cause to be
    /// copied to caller memory. This prevents stupid things like malicious
    /// contracts returning 10,000,000 bytes causing a local OOG when copying
    /// to memory.
    /// @param _target The address to call
    /// @param _gas The amount of gas to forward to the remote contract
    /// @param _maxCopy The maximum number of bytes of returndata to copy
    /// to memory.
    /// @param _calldata The data to send to the remote contract
    /// @return success and returndata, as `.call()`. Returndata is capped to
    /// `_maxCopy` bytes.
    function excessivelySafeStaticCall(
        address _target,
        uint256 _gas,
        uint16 _maxCopy,
        bytes memory _calldata
    ) internal view returns (bool, bytes memory) {
        // set up for assembly call
        uint256 _toCopy;
        bool _success;
        bytes memory _returnData = new bytes(_maxCopy);
        // dispatch message to recipient
        // by assembly calling "handle" function
        // we call via assembly to avoid memcopying a very large returndata
        // returned by a malicious contract
        assembly {
            _success := staticcall(
                _gas, // gas
                _target, // recipient
                add(_calldata, 0x20), // inloc
                mload(_calldata), // inlen
                0, // outloc
                0 // outlen
            )
            // limit our copy to 256 bytes
            _toCopy := returndatasize()
            if gt(_toCopy, _maxCopy) {
                _toCopy := _maxCopy
            }
            // Store the length of the copied bytes
            mstore(_returnData, _toCopy)
            // copy the bytes from returndata[0:_toCopy]
            returndatacopy(add(_returnData, 0x20), 0, _toCopy)
        }
        return (_success, _returnData);
    }

    /**
     * @notice Swaps function selectors in encoded contract calls
     * @dev Allows reuse of encoded calldata for functions with identical
     * argument types but different names. It simply swaps out the first 4 bytes
     * for the new selector. This function modifies memory in place, and should
     * only be used with caution.
     * @param _newSelector The new 4-byte selector
     * @param _buf The encoded contract args
     */
    function swapSelector(bytes4 _newSelector, bytes memory _buf)
        internal
        pure
    {
        require(_buf.length >= 4);
        uint256 _mask = LOW_28_MASK;
        assembly {
            // load the first word of
            let _word := mload(add(_buf, 0x20))
            // mask out the top 4 bytes
            // /x
            _word := and(_word, _mask)
            _word := or(_newSelector, _word)
            mstore(add(_buf, 0x20), _word)
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import { CallType, ExecType, ModeCode } from "../lib/ModeLib.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(ModeCode 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(
        ModeCode 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(ModeCode 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);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// ──────────────────────────────────────────────────────────────────────────────
//     _   __    _  __
//    / | / /__ | |/ /_  _______
//   /  |/ / _ \|   / / / / ___/
//  / /|  /  __/   / /_/ (__  )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Accounts compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

import { ExecutionMode } from "../../../lib/erc-7579/ModeLib.sol";
import { IExecutionHelperEventsAndErrors } from "./IExecutionHelperEventsAndErrors.sol";
import { PackedUserOperation } from "account-abstraction/interfaces/PackedUserOperation.sol";

/// @title Nexus - IExecutionHelper
/// @notice Interface for executing transactions on behalf of smart accounts within the Nexus system.
/// @dev Extends functionality for transaction execution with error handling as defined in
/// IExecutionHelperEventsAndErrors.
/// @author @livingrockrises | Biconomy | [email protected]
/// @author @aboudjem | Biconomy | [email protected]
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady
interface IExecutionHelper is IExecutionHelperEventsAndErrors {
    /// @notice Executes a transaction with specified execution mode and calldata.
    /// @param mode The execution mode, defining how the transaction is processed.
    /// @param executionCalldata The calldata to execute.
    /// @dev This function ensures that the execution complies with smart account execution policies and handles errors
    /// appropriately.
    function execute(ExecutionMode mode, bytes calldata executionCalldata) external payable;

    /// @notice Allows an executor module to perform transactions on behalf of the account.
    /// @param mode The execution mode that details how the transaction should be handled.
    /// @param executionCalldata The transaction data to be executed.
    /// @return returnData The result of the execution, allowing for error handling and results interpretation by the
    /// executor module.
    function executeFromExecutor(
        ExecutionMode mode,
        bytes calldata executionCalldata
    )
        external
        payable
        returns (bytes[] memory returnData);

    /**
     * Account may implement this execute method.
     * passing this methodSig at the beginning of callData will cause the entryPoint to pass the full UserOp (and hash)
     * to the account.
     * The account should skip the methodSig, and use the callData (and optionally, other UserOp fields)
     *
     * @param userOp              - The operation that was just validated.
     * @param userOpHash          - Hash of the user's request data.
     */
    function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external payable;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import { ComposableStorage } from "./ComposableStorage.sol";
import {
    InputParam,
    OutputParam,
    Constraint,
    ConstraintType,
    InputParamType,
    InputParamFetcherType,
    OutputParamFetcherType
} from "../types/ComposabilityDataTypes.sol";
import { Execution } from "erc7579/interfaces/IERC7579Account.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

// Library for composable execution handling
library ComposableExecutionLib {
    error ConstraintNotMet(ConstraintType constraintType);
    error Output_StaticCallFailed();
    error InvalidParameterEncoding(string message);
    error InvalidOutputParamFetcherType();
    error InvalidConstraintType();
    error InvalidSetOfInputParams(string message);

    // Process the input parameters and return the composed calldata
    function processInputs(
        InputParam[] calldata inputParams,
        bytes4 functionSig
    )
        internal
        view
        returns (Execution memory)
    {
        address composedTarget;
        uint256 composedValue;
        bytes memory composedCalldata = abi.encodePacked(functionSig);
        uint256 length = inputParams.length;

        // Bit 0: TARGET param type set, Bit 1: VALUE param type set
        uint256 paramTypeFlags = 0;
        for (uint256 i; i < length; i++) {
            bytes memory processedInput = processInput(inputParams[i]);
            if (inputParams[i].paramType == InputParamType.TARGET) {
                if (inputParams[i].fetcherType == InputParamFetcherType.BALANCE) {
                    revert InvalidParameterEncoding("BALANCE fetcher type is not supported for TARGET param type");
                }
                // Check if TARGET has already been set (bit 0)
                if (paramTypeFlags & 1 != 0) {
                    revert InvalidSetOfInputParams("TARGET param type can only be set once");
                }
                paramTypeFlags |= 1; // Set bit 0
                composedTarget = abi.decode(processedInput, (address));
            } else if (inputParams[i].paramType == InputParamType.VALUE) {
                // Check if VALUE has already been set (bit 1)
                if (paramTypeFlags & 2 != 0) {
                    revert InvalidSetOfInputParams("VALUE param type can only be set once");
                }
                paramTypeFlags |= 2; // Set bit 1
                composedValue = abi.decode(processedInput, (uint256));
            } else if (inputParams[i].paramType == InputParamType.CALL_DATA) {
                composedCalldata = bytes.concat(composedCalldata, processedInput);
            } else {
                revert InvalidParameterEncoding("Invalid param type");
            }
        }
        // if a param with TARGET type was not provided, it will be address(0)
        // we don't restrict it since some calls may want to call address(0)
        // if a param with VALUE type was not provided, it will be 0
        // this is even more often case, as many calls happen with 0 value
        return Execution({ target: composedTarget, value: composedValue, callData: composedCalldata });
    }

    // Process a single input parameter and return the composed calldata
    function processInput(InputParam calldata param) internal view returns (bytes memory) {
        if (param.fetcherType == InputParamFetcherType.RAW_BYTES) {
            _validateConstraints(param.paramData, param.constraints);
            return param.paramData;
        } else if (param.fetcherType == InputParamFetcherType.STATIC_CALL) {
            address contractAddr;
            bytes calldata callData;
            bytes calldata paramData = param.paramData;
            // expect paramData to be abi.encode(address contractAddr, bytes callData)
            assembly {
                contractAddr := calldataload(paramData.offset)
                let s := calldataload(add(paramData.offset, 0x20))
                let u := add(paramData.offset, s)
                callData.offset := add(u, 0x20)
                callData.length := calldataload(u)
            }
            (bool success, bytes memory returnData) = contractAddr.staticcall(callData);
            assembly {
                if iszero(success) {
                    // revert ComposableExecutionFailed()
                    mstore(0x00, 0x6533cc8d)
                    revert(0x1c, 0x04)
                }
            }
            _validateConstraints(returnData, param.constraints);
            return returnData;
        } else if (param.fetcherType == InputParamFetcherType.BALANCE) {
            address tokenAddr;
            address account;
            bytes calldata paramData = param.paramData;

            // expect paramData to be abi.encodePacked(address token, address account)
            // Validate exact length requirement
            require(paramData.length == 40, InvalidParameterEncoding("Invalid paramData length"));
            assembly {
                tokenAddr := shr(96, calldataload(paramData.offset))
                account := shr(96, calldataload(add(paramData.offset, 0x14)))
            }

            uint256 balance;
            if (tokenAddr == address(0)) {
                balance = account.balance;
            } else {
                balance = IERC20(tokenAddr).balanceOf(account);
            }
            _validateConstraints(abi.encode(balance), param.constraints);
            return abi.encode(balance);
        } else {
            revert InvalidParameterEncoding("Invalid param fetcher type");
        }
    }

    // Process the output parameters
    function processOutputs(OutputParam[] calldata outputParams, bytes memory returnData, address account) internal {
        uint256 length = outputParams.length;
        for (uint256 i; i < length; i++) {
            processOutput(outputParams[i], returnData, account);
        }
    }

    // Process a single output parameter and write to storage
    function processOutput(OutputParam calldata param, bytes memory returnData, address account) internal {
        // only static types are supported for now as return values
        // can also process all the static return values which are before the first dynamic return value in the
        // returnData
        if (param.fetcherType == OutputParamFetcherType.EXEC_RESULT) {
            uint256 returnValues;
            address targetStorageContract;
            bytes32 targetStorageSlot;
            bytes calldata paramData = param.paramData;
            assembly {
                returnValues := calldataload(paramData.offset)
                targetStorageContract := calldataload(add(paramData.offset, 0x20))
                targetStorageSlot := calldataload(add(paramData.offset, 0x40))
            }
            _parseReturnDataAndWriteToStorage(
                returnValues, returnData, targetStorageContract, targetStorageSlot, account
            );
            // same for static calls
        } else if (param.fetcherType == OutputParamFetcherType.STATIC_CALL) {
            uint256 returnValues;
            address sourceContract;
            bytes calldata sourceCallData;
            address targetStorageContract;
            bytes32 targetStorageSlot;
            bytes calldata paramData = param.paramData;
            assembly {
                returnValues := calldataload(paramData.offset)
                sourceContract := calldataload(add(paramData.offset, 0x20))
                let s := calldataload(add(paramData.offset, 0x40))
                let u := add(paramData.offset, s)
                sourceCallData.offset := add(u, 0x20)
                sourceCallData.length := calldataload(u)
                targetStorageContract := calldataload(add(paramData.offset, 0x60))
                targetStorageSlot := calldataload(add(paramData.offset, 0x80))
            }
            (bool outputSuccess, bytes memory outputReturnData) = sourceContract.staticcall(sourceCallData);
            if (!outputSuccess) {
                revert Output_StaticCallFailed();
            }
            _parseReturnDataAndWriteToStorage(
                returnValues, outputReturnData, targetStorageContract, targetStorageSlot, account
            );
        } else {
            revert InvalidOutputParamFetcherType();
        }
    }

    /// @dev Validate the constraints => compare the value with the reference data
    function _validateConstraints(bytes memory rawValue, Constraint[] calldata constraints) private pure {
        if (constraints.length > 0) {
            for (uint256 i; i < constraints.length; i++) {
                Constraint memory constraint = constraints[i];
                bytes32 returnValue;
                assembly {
                    returnValue := mload(add(rawValue, add(0x20, mul(i, 0x20))))
                }
                if (constraint.constraintType == ConstraintType.EQ) {
                    require(returnValue == bytes32(constraint.referenceData), ConstraintNotMet(ConstraintType.EQ));
                } else if (constraint.constraintType == ConstraintType.GTE) {
                    require(returnValue >= bytes32(constraint.referenceData), ConstraintNotMet(ConstraintType.GTE));
                } else if (constraint.constraintType == ConstraintType.LTE) {
                    require(returnValue <= bytes32(constraint.referenceData), ConstraintNotMet(ConstraintType.LTE));
                } else if (constraint.constraintType == ConstraintType.IN) {
                    (bytes32 lowerBound, bytes32 upperBound) = abi.decode(constraint.referenceData, (bytes32, bytes32));
                    require(returnValue >= lowerBound && returnValue <= upperBound, ConstraintNotMet(ConstraintType.IN));
                } else {
                    revert InvalidConstraintType();
                }
            }
        }
    }

    /// @dev Parse the return data and write to the appropriate storage contract
    function _parseReturnDataAndWriteToStorage(
        uint256 returnValues,
        bytes memory returnData,
        address targetStorageContract,
        bytes32 targetStorageSlot,
        address account
    )
        internal
    {
        for (uint256 i; i < returnValues; i++) {
            bytes32 value;
            assembly {
                value := mload(add(returnData, add(0x20, mul(i, 0x20))))
            }
            ComposableStorage(targetStorageContract)
                .writeStorage({
                    slot: keccak256(abi.encodePacked(targetStorageSlot, i)), value: value, account: account
                });
        }
    }
}

File 28 of 44 : ComposabilityDataTypes.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

// Type of the input parameter
enum InputParamType {
    TARGET, // The target address
    VALUE, // The value
    CALL_DATA // The call data
}

// Parameter type for composition
enum InputParamFetcherType {
    RAW_BYTES, // Already encoded bytes
    STATIC_CALL, // Perform a static call
    BALANCE // Get the balance of an address
}

enum OutputParamFetcherType {
    EXEC_RESULT, // The return of the execution call
    STATIC_CALL // Call to some other function
}

// Constraint type for parameter validation
enum ConstraintType {
    EQ, // Equal to
    GTE, // Greater than or equal to
    LTE, // Less than or equal to
    IN // In range
}

// Constraint for parameter validation
struct Constraint {
    ConstraintType constraintType;
    bytes referenceData;
}

// Structure to define parameter composition
struct InputParam {
    InputParamType paramType;
    InputParamFetcherType fetcherType; // How to fetch the parameter
    bytes paramData;
    Constraint[] constraints;
}

// Structure to define return value handling
struct OutputParam {
    OutputParamFetcherType fetcherType; // How to fetch the parameter
    bytes paramData;
}

// Structure to define a composable execution
struct ComposableExecution {
    bytes4 functionSig;
    InputParam[] inputParams;
    OutputParam[] outputParams;
}

// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.23;

import { ComposableExecution } from "../types/ComposabilityDataTypes.sol";

interface IComposableExecution {
    function executeComposable(ComposableExecution[] calldata cExecutions) external payable;
}

interface IComposableExecutionModule is IComposableExecution {
    function executeComposableCall(ComposableExecution[] calldata cExecutions) external;
    function executeComposableDelegateCall(ComposableExecution[] calldata cExecutions) external;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Call context checker mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/CallContextChecker.sol)
contract CallContextChecker {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The call is from an unauthorized call context.
    error UnauthorizedCallContext();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         IMMUTABLES                         */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev For checking if the context is a delegate call.
    ///
    /// Note: To enable use cases with an immutable default implementation in the bytecode,
    /// (see: ERC6551Proxy), we don't require that the proxy address must match the
    /// value stored in the implementation slot, which may not be initialized.
    uint256 private immutable __self = uint256(uint160(address(this)));

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    CALL CONTEXT CHECKS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // A proxy call can be either via a `delegatecall` to an implementation,
    // or a 7702 call on an authority that points to a delegation.

    /// @dev Returns whether the current call context is on a EIP7702 authority
    /// (i.e. externally owned account).
    function _onEIP7702Authority() internal view virtual returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            extcodecopy(address(), 0x00, 0x00, 0x20)
            // Note: Checking that it starts with hex"ef01" is the most general and futureproof.
            // 7702 bytecode is `abi.encodePacked(hex"ef01", uint8(version), address(delegation))`.
            result := eq(0xef01, shr(240, mload(0x00)))
        }
    }

    /// @dev Returns the implementation of this contract.
    function _selfImplementation() internal view virtual returns (address) {
        return address(uint160(__self));
    }

    /// @dev Returns whether the current call context is on the implementation itself.
    function _onImplementation() internal view virtual returns (bool) {
        return __self == uint160(address(this));
    }

    /// @dev Requires that the current call context is performed via a EIP7702 authority.
    function _checkOnlyEIP7702Authority() internal view virtual {
        if (!_onEIP7702Authority()) _revertUnauthorizedCallContext();
    }

    /// @dev Requires that the current call context is performed via a proxy.
    function _checkOnlyProxy() internal view virtual {
        if (_onImplementation()) _revertUnauthorizedCallContext();
    }

    /// @dev Requires that the current call context is NOT performed via a proxy.
    /// This is the opposite of `checkOnlyProxy`.
    function _checkNotDelegated() internal view virtual {
        if (!_onImplementation()) _revertUnauthorizedCallContext();
    }

    /// @dev Requires that the current call context is performed via a EIP7702 authority.
    modifier onlyEIP7702Authority() virtual {
        _checkOnlyEIP7702Authority();
        _;
    }

    /// @dev Requires that the current call context is performed via a proxy.
    modifier onlyProxy() virtual {
        _checkOnlyProxy();
        _;
    }

    /// @dev Requires that the current call context is NOT performed via a proxy.
    /// This is the opposite of `onlyProxy`.
    modifier notDelegated() virtual {
        _checkNotDelegated();
        _;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function _revertUnauthorizedCallContext() private pure {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x9f03a026) // `UnauthorizedCallContext()`.
            revert(0x1c, 0x04)
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// ──────────────────────────────────────────────────────────────────────────────
//     _   __    _  __
//    / | / /__ | |/ /_  _______
//   /  |/ / _ \|   / / / / ___/
//  / /|  /  __/   / /_/ (__  )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Accounts compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

import { ExecutionMode } from "../../../lib/erc-7579/ModeLib.sol";

/// @title Nexus - ERC-7579 Account Configuration Interface
/// @notice Interface for querying and verifying configurations of Smart Accounts compliant with ERC-7579.
/// @dev Provides methods to check supported execution modes and module types for Smart Accounts, ensuring flexible and
/// extensible configuration.
/// @author @livingrockrises | Biconomy | [email protected]
/// @author @aboudjem | Biconomy | [email protected]
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady
interface IAccountConfig {
    /// @notice Returns the account ID in a structured format: "vendorname.accountname.semver"
    /// @return accountImplementationId The account ID of the smart account
    function accountId() external view returns (string memory accountImplementationId);

    /// @notice Checks if the account supports a certain execution mode.
    /// @param encodedMode The encoded mode to verify.
    /// @return supported True if the account supports the mode, false otherwise.
    function supportsExecutionMode(ExecutionMode encodedMode) external view returns (bool supported);

    /// @notice Checks if the account supports a specific module type.
    /// @param moduleTypeId The module type ID to verify.
    /// @return supported True if the account supports the module type, false otherwise.
    function supportsModule(uint256 moduleTypeId) external view returns (bool supported);
}

File 32 of 44 : INexusEventsAndErrors.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// ──────────────────────────────────────────────────────────────────────────────
//     _   __    _  __
//    / | / /__ | |/ /_  _______
//   /  |/ / _ \|   / / / / ___/
//  / /|  /  __/   / /_/ (__  )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Accounts compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

/// @title Nexus - INexus Events and Errors
/// @notice Defines common errors for the Nexus smart account management interface.
/// @author @livingrockrises | Biconomy | [email protected]
/// @author @aboudjem | Biconomy | [email protected]
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady
interface INexusEventsAndErrors {
    /// @notice Error thrown when an unsupported ModuleType is requested.
    /// @param moduleTypeId The ID of the unsupported module type.
    error UnsupportedModuleType(uint256 moduleTypeId);

    /// @notice Error thrown when a zero address is provided as the Entry Point address.
    error EntryPointCanNotBeZero();

    /// @notice Error thrown when the provided implementation address is invalid.
    error InvalidImplementationAddress();

    /// @notice Error thrown when attempted to emergency-uninstall a hook
    error EmergencyTimeLockNotExpired();

    /// @notice Error thrown when attempted to upgrade an ERC7702 account via UUPS proxy upgrade mechanism
    error ERC7702AccountCannotBeUpgradedThisWay();

    /// @notice Error thrown when the provided initData is invalid.
    error InvalidInitData();

    /// @notice Error thrown when the account is already initialized.
    error AccountAlreadyInitialized();

    /// @notice Error thrown when the account is not initialized but expected to be.
    error AccountNotInitialized();

    /// @notice Error thrown when the provided signature is invalid.
    error InvalidSignature();
}

// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.27;

interface IERC1271 {
    /**
     * @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 calldata _signature) external view returns (bytes4);
}

File 34 of 44 : IAccount.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.5;

import "./PackedUserOperation.sol";

interface IAccount {
    /**
     * Validate user's signature and nonce
     * the entryPoint will make the call to the recipient only if this validation call returns successfully.
     * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).
     * This allows making a "simulation call" without a valid signature
     * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.
     *
     * @dev Must validate caller is the entryPoint.
     *      Must validate the signature and nonce
     * @param userOp              - The operation that is about to be executed.
     * @param userOpHash          - Hash of the user's request data. can be used as the basis for signature.
     * @param missingAccountFunds - Missing funds on the account's deposit in the entrypoint.
     *                              This is the minimum amount to transfer to the sender(entryPoint) to be
     *                              able to make the call. The excess is left as a deposit in the entrypoint
     *                              for future calls. Can be withdrawn anytime using "entryPoint.withdrawTo()".
     *                              In case there is a paymaster in the request (or the current deposit is high
     *                              enough), this value will be zero.
     * @return validationData       - Packaged ValidationData structure. use `_packValidationData` and
     *                              `_unpackValidationData` to encode and decode.
     *                              <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,
     *                                 otherwise, an address of an "authorizer" contract.
     *                              <6-byte> validUntil - Last timestamp this operation is valid. 0 for "indefinite"
     *                              <6-byte> validAfter - First timestamp this operation is valid
     *                                                    If an account doesn't use time-range, it is enough to
     *                                                    return SIG_VALIDATION_FAILED value (1) for signature failure.
     *                              Note that the validation code cannot use block.timestamp (or block.number) directly.
     */
    function validateUserOp(
        PackedUserOperation calldata userOp,
        bytes32 userOpHash,
        uint256 missingAccountFunds
    ) external returns (uint256 validationData);
}

File 35 of 44 : EfficientHashLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Library for efficiently performing keccak256 hashes.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EfficientHashLib.sol)
/// @dev To avoid stack-too-deep, you can use:
/// ```
/// bytes32[] memory buffer = EfficientHashLib.malloc(10);
/// EfficientHashLib.set(buffer, 0, value0);
/// ..
/// EfficientHashLib.set(buffer, 9, value9);
/// bytes32 finalHash = EfficientHashLib.hash(buffer);
/// ```
library EfficientHashLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*               MALLOC-LESS HASHING OPERATIONS               */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `keccak256(abi.encode(v0))`.
    function hash(bytes32 v0) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, v0)
            result := keccak256(0x00, 0x20)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0))`.
    function hash(uint256 v0) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, v0)
            result := keccak256(0x00, 0x20)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1))`.
    function hash(bytes32 v0, bytes32 v1) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, v0)
            mstore(0x20, v1)
            result := keccak256(0x00, 0x40)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1))`.
    function hash(uint256 v0, uint256 v1) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, v0)
            mstore(0x20, v1)
            result := keccak256(0x00, 0x40)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1, v2))`.
    function hash(bytes32 v0, bytes32 v1, bytes32 v2) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            result := keccak256(m, 0x60)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1, v2))`.
    function hash(uint256 v0, uint256 v1, uint256 v2) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            result := keccak256(m, 0x60)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1, v2, v3))`.
    function hash(bytes32 v0, bytes32 v1, bytes32 v2, bytes32 v3)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            result := keccak256(m, 0x80)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1, v2, v3))`.
    function hash(uint256 v0, uint256 v1, uint256 v2, uint256 v3)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            result := keccak256(m, 0x80)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v4))`.
    function hash(bytes32 v0, bytes32 v1, bytes32 v2, bytes32 v3, bytes32 v4)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            result := keccak256(m, 0xa0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v4))`.
    function hash(uint256 v0, uint256 v1, uint256 v2, uint256 v3, uint256 v4)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            result := keccak256(m, 0xa0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v5))`.
    function hash(bytes32 v0, bytes32 v1, bytes32 v2, bytes32 v3, bytes32 v4, bytes32 v5)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            result := keccak256(m, 0xc0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v5))`.
    function hash(uint256 v0, uint256 v1, uint256 v2, uint256 v3, uint256 v4, uint256 v5)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            result := keccak256(m, 0xc0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v6))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            result := keccak256(m, 0xe0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v6))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            result := keccak256(m, 0xe0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v7))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            result := keccak256(m, 0x100)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v7))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            result := keccak256(m, 0x100)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v8))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            result := keccak256(m, 0x120)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v8))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            result := keccak256(m, 0x120)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v9))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8,
        bytes32 v9
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            result := keccak256(m, 0x140)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v9))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8,
        uint256 v9
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            result := keccak256(m, 0x140)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v10))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8,
        bytes32 v9,
        bytes32 v10
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            result := keccak256(m, 0x160)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v10))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8,
        uint256 v9,
        uint256 v10
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            result := keccak256(m, 0x160)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v11))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8,
        bytes32 v9,
        bytes32 v10,
        bytes32 v11
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            result := keccak256(m, 0x180)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v11))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8,
        uint256 v9,
        uint256 v10,
        uint256 v11
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            result := keccak256(m, 0x180)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v12))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8,
        bytes32 v9,
        bytes32 v10,
        bytes32 v11,
        bytes32 v12
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            mstore(add(m, 0x180), v12)
            result := keccak256(m, 0x1a0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v12))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8,
        uint256 v9,
        uint256 v10,
        uint256 v11,
        uint256 v12
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            mstore(add(m, 0x180), v12)
            result := keccak256(m, 0x1a0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v13))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8,
        bytes32 v9,
        bytes32 v10,
        bytes32 v11,
        bytes32 v12,
        bytes32 v13
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            mstore(add(m, 0x180), v12)
            mstore(add(m, 0x1a0), v13)
            result := keccak256(m, 0x1c0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v13))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8,
        uint256 v9,
        uint256 v10,
        uint256 v11,
        uint256 v12,
        uint256 v13
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            mstore(add(m, 0x180), v12)
            mstore(add(m, 0x1a0), v13)
            result := keccak256(m, 0x1c0)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*             BYTES32 BUFFER HASHING OPERATIONS              */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `keccak256(abi.encode(buffer[0], .., buffer[buffer.length - 1]))`.
    function hash(bytes32[] memory buffer) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := keccak256(add(buffer, 0x20), shl(5, mload(buffer)))
        }
    }

    /// @dev Sets `buffer[i]` to `value`, without a bounds check.
    /// Returns the `buffer` for function chaining.
    function set(bytes32[] memory buffer, uint256 i, bytes32 value)
        internal
        pure
        returns (bytes32[] memory)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(add(buffer, shl(5, add(1, i))), value)
        }
        return buffer;
    }

    /// @dev Sets `buffer[i]` to `value`, without a bounds check.
    /// Returns the `buffer` for function chaining.
    function set(bytes32[] memory buffer, uint256 i, uint256 value)
        internal
        pure
        returns (bytes32[] memory)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(add(buffer, shl(5, add(1, i))), value)
        }
        return buffer;
    }

    /// @dev Returns `new bytes32[](n)`, without zeroing out the memory.
    function malloc(uint256 n) internal pure returns (bytes32[] memory buffer) {
        /// @solidity memory-safe-assembly
        assembly {
            buffer := mload(0x40)
            mstore(buffer, n)
            mstore(0x40, add(shl(5, add(1, n)), buffer))
        }
    }

    /// @dev Frees memory that has been allocated for `buffer`.
    /// No-op if `buffer.length` is zero, or if new memory has been allocated after `buffer`.
    function free(bytes32[] memory buffer) internal pure {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(buffer)
            mstore(shl(6, lt(iszero(n), eq(add(shl(5, add(1, n)), buffer), mload(0x40)))), buffer)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      EQUALITY CHECKS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `a == abi.decode(b, (bytes32))`.
    function eq(bytes32 a, bytes memory b) internal pure returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := and(eq(0x20, mload(b)), eq(a, mload(add(b, 0x20))))
        }
    }

    /// @dev Returns `abi.decode(a, (bytes32)) == b`.
    function eq(bytes memory a, bytes32 b) internal pure returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := and(eq(0x20, mload(a)), eq(b, mload(add(a, 0x20))))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*               BYTE SLICE HASHING OPERATIONS                */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the keccak256 of the slice from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets.
    function hash(bytes memory b, uint256 start, uint256 end)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(b)
            end := xor(end, mul(xor(end, n), lt(n, end)))
            start := xor(start, mul(xor(start, n), lt(n, start)))
            result := keccak256(add(add(b, 0x20), start), mul(gt(end, start), sub(end, start)))
        }
    }

    /// @dev Returns the keccak256 of the slice from `start` to the end of the bytes.
    function hash(bytes memory b, uint256 start) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(b)
            start := xor(start, mul(xor(start, n), lt(n, start)))
            result := keccak256(add(add(b, 0x20), start), mul(gt(n, start), sub(n, start)))
        }
    }

    /// @dev Returns the keccak256 of the bytes.
    function hash(bytes memory b) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := keccak256(add(b, 0x20), mload(b))
        }
    }

    /// @dev Returns the keccak256 of the slice from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets.
    function hashCalldata(bytes calldata b, uint256 start, uint256 end)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            end := xor(end, mul(xor(end, b.length), lt(b.length, end)))
            start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
            let n := mul(gt(end, start), sub(end, start))
            calldatacopy(mload(0x40), add(b.offset, start), n)
            result := keccak256(mload(0x40), n)
        }
    }

    /// @dev Returns the keccak256 of the slice from `start` to the end of the bytes.
    function hashCalldata(bytes calldata b, uint256 start) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
            let n := mul(gt(b.length, start), sub(b.length, start))
            calldatacopy(mload(0x40), add(b.offset, start), n)
            result := keccak256(mload(0x40), n)
        }
    }

    /// @dev Returns the keccak256 of the bytes.
    function hashCalldata(bytes calldata b) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            calldatacopy(mload(0x40), b.offset, b.length)
            result := keccak256(mload(0x40), b.length)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      SHA2-256 HELPERS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `sha256(abi.encode(b))`. Yes, it's more efficient.
    function sha2(bytes32 b) internal view returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, b)
            result := mload(staticcall(gas(), 2, 0x00, 0x20, 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the slice from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets.
    function sha2(bytes memory b, uint256 start, uint256 end)
        internal
        view
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(b)
            end := xor(end, mul(xor(end, n), lt(n, end)))
            start := xor(start, mul(xor(start, n), lt(n, start)))
            // forgefmt: disable-next-item
            result := mload(staticcall(gas(), 2, add(add(b, 0x20), start),
                mul(gt(end, start), sub(end, start)), 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the slice from `start` to the end of the bytes.
    function sha2(bytes memory b, uint256 start) internal view returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(b)
            start := xor(start, mul(xor(start, n), lt(n, start)))
            // forgefmt: disable-next-item
            result := mload(staticcall(gas(), 2, add(add(b, 0x20), start),
                mul(gt(n, start), sub(n, start)), 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the bytes.
    function sha2(bytes memory b) internal view returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(staticcall(gas(), 2, add(b, 0x20), mload(b), 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the slice from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets.
    function sha2Calldata(bytes calldata b, uint256 start, uint256 end)
        internal
        view
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            end := xor(end, mul(xor(end, b.length), lt(b.length, end)))
            start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
            let n := mul(gt(end, start), sub(end, start))
            calldatacopy(mload(0x40), add(b.offset, start), n)
            result := mload(staticcall(gas(), 2, mload(0x40), n, 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the slice from `start` to the end of the bytes.
    function sha2Calldata(bytes calldata b, uint256 start) internal view returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
            let n := mul(gt(b.length, start), sub(b.length, start))
            calldatacopy(mload(0x40), add(b.offset, start), n)
            result := mload(staticcall(gas(), 2, mload(0x40), n, 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the bytes.
    function sha2Calldata(bytes calldata b) internal view returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            calldatacopy(mload(0x40), b.offset, b.length)
            result := mload(staticcall(gas(), 2, mload(0x40), b.length, 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Library for bit twiddling and boolean operations.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibBit.sol)
/// @author Inspired by (https://graphics.stanford.edu/~seander/bithacks.html)
library LibBit {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  BIT TWIDDLING OPERATIONS                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Find last set.
    /// Returns the index of the most significant bit of `x`,
    /// counting from the least significant bit position.
    /// If `x` is zero, returns 256.
    function fls(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            r := or(shl(8, iszero(x)), shl(7, lt(0xffffffffffffffffffffffffffffffff, x)))
            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffff, shr(r, x))))
            r := or(r, shl(3, lt(0xff, shr(r, x))))
            // forgefmt: disable-next-item
            r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),
                0x0706060506020504060203020504030106050205030304010505030400000000))
        }
    }

    /// @dev Count leading zeros.
    /// Returns the number of zeros preceding the most significant one bit.
    /// If `x` is zero, returns 256.
    function clz(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffff, shr(r, x))))
            r := or(r, shl(3, lt(0xff, shr(r, x))))
            // forgefmt: disable-next-item
            r := add(xor(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),
                0xf8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff)), iszero(x))
        }
    }

    /// @dev Find first set.
    /// Returns the index of the least significant bit of `x`,
    /// counting from the least significant bit position.
    /// If `x` is zero, returns 256.
    /// Equivalent to `ctz` (count trailing zeros), which gives
    /// the number of zeros following the least significant one bit.
    function ffs(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            // Isolate the least significant bit.
            x := and(x, add(not(x), 1))
            // For the upper 3 bits of the result, use a De Bruijn-like lookup.
            // Credit to adhusson: https://blog.adhusson.com/cheap-find-first-set-evm/
            // forgefmt: disable-next-item
            r := shl(5, shr(252, shl(shl(2, shr(250, mul(x,
                0xb6db6db6ddddddddd34d34d349249249210842108c6318c639ce739cffffffff))),
                0x8040405543005266443200005020610674053026020000107506200176117077)))
            // For the lower 5 bits of the result, use a De Bruijn lookup.
            // forgefmt: disable-next-item
            r := or(r, byte(and(div(0xd76453e0, shr(r, x)), 0x1f),
                0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405))
        }
    }

    /// @dev Returns the number of set bits in `x`.
    function popCount(uint256 x) internal pure returns (uint256 c) {
        /// @solidity memory-safe-assembly
        assembly {
            let max := not(0)
            let isMax := eq(x, max)
            x := sub(x, and(shr(1, x), div(max, 3)))
            x := add(and(x, div(max, 5)), and(shr(2, x), div(max, 5)))
            x := and(add(x, shr(4, x)), div(max, 17))
            c := or(shl(8, isMax), shr(248, mul(x, div(max, 255))))
        }
    }

    /// @dev Returns the number of zero bytes in `x`.
    /// To get the number of non-zero bytes, simply do `32 - countZeroBytes(x)`.
    function countZeroBytes(uint256 x) internal pure returns (uint256 c) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := 0x7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f
            c := byte(0, mul(shr(7, not(m)), shr(7, not(or(or(add(and(x, m), m), x), m)))))
        }
    }

    /// @dev Returns the number of zero bytes in `s`.
    /// To get the number of non-zero bytes, simply do `s.length - countZeroBytes(s)`.
    function countZeroBytes(bytes memory s) internal pure returns (uint256 c) {
        /// @solidity memory-safe-assembly
        assembly {
            function czb(x_) -> _c {
                let _m := 0x7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f
                _c := shr(7, not(or(or(add(and(x_, _m), _m), x_), _m)))
                _c := byte(0, mul(shr(7, not(_m)), _c))
            }
            let n := mload(s)
            let l := shl(5, shr(5, n))
            s := add(s, 0x20)
            for { let i } xor(i, l) { i := add(i, 0x20) } { c := add(czb(mload(add(s, i))), c) }
            if lt(l, n) { c := add(czb(or(shr(shl(3, sub(n, l)), not(0)), mload(add(s, l)))), c) }
        }
    }

    /// @dev Returns the number of zero bytes in `s`.
    /// To get the number of non-zero bytes, simply do `s.length - countZeroBytes(s)`.
    function countZeroBytesCalldata(bytes calldata s) internal pure returns (uint256 c) {
        /// @solidity memory-safe-assembly
        assembly {
            function czb(x_) -> _c {
                let _m := 0x7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f
                _c := shr(7, not(or(or(add(and(x_, _m), _m), x_), _m)))
                _c := byte(0, mul(shr(7, not(_m)), _c))
            }
            let l := shl(5, shr(5, s.length))
            for { let i } xor(i, l) { i := add(i, 0x20) } {
                c := add(czb(calldataload(add(s.offset, i))), c)
            }
            if lt(l, s.length) {
                let m := shr(shl(3, sub(s.length, l)), not(0))
                c := add(czb(or(m, calldataload(add(s.offset, l)))), c)
            }
        }
    }

    /// @dev Returns whether `x` is a power of 2.
    function isPo2(uint256 x) internal pure returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to `x && !(x & (x - 1))`.
            result := iszero(add(and(x, sub(x, 1)), iszero(x)))
        }
    }

    /// @dev Returns `x` reversed at the bit level.
    function reverseBits(uint256 x) internal pure returns (uint256 r) {
        uint256 m0 = 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f;
        uint256 m1 = m0 ^ (m0 << 2);
        uint256 m2 = m1 ^ (m1 << 1);
        r = reverseBytes(x);
        r = (m2 & (r >> 1)) | ((m2 & r) << 1);
        r = (m1 & (r >> 2)) | ((m1 & r) << 2);
        r = (m0 & (r >> 4)) | ((m0 & r) << 4);
    }

    /// @dev Returns `x` reversed at the byte level.
    function reverseBytes(uint256 x) internal pure returns (uint256 r) {
        unchecked {
            // Computing masks on-the-fly reduces bytecode size by about 200 bytes.
            uint256 m0 = 0x100000000000000000000000000000001 * (~toUint(x == uint256(0)) >> 192);
            uint256 m1 = m0 ^ (m0 << 32);
            uint256 m2 = m1 ^ (m1 << 16);
            uint256 m3 = m2 ^ (m2 << 8);
            r = (m3 & (x >> 8)) | ((m3 & x) << 8);
            r = (m2 & (r >> 16)) | ((m2 & r) << 16);
            r = (m1 & (r >> 32)) | ((m1 & r) << 32);
            r = (m0 & (r >> 64)) | ((m0 & r) << 64);
            r = (r >> 128) | (r << 128);
        }
    }

    /// @dev Returns the common prefix of `x` and `y` at the bit level.
    function commonBitPrefix(uint256 x, uint256 y) internal pure returns (uint256) {
        unchecked {
            uint256 s = 256 - clz(x ^ y);
            return (x >> s) << s;
        }
    }

    /// @dev Returns the common prefix of `x` and `y` at the nibble level.
    function commonNibblePrefix(uint256 x, uint256 y) internal pure returns (uint256) {
        unchecked {
            uint256 s = (64 - (clz(x ^ y) >> 2)) << 2;
            return (x >> s) << s;
        }
    }

    /// @dev Returns the common prefix of `x` and `y` at the byte level.
    function commonBytePrefix(uint256 x, uint256 y) internal pure returns (uint256) {
        unchecked {
            uint256 s = (32 - (clz(x ^ y) >> 3)) << 3;
            return (x >> s) << s;
        }
    }

    /// @dev hex"ABCD" -> hex"0A0B0C0D".
    function toNibbles(bytes memory s) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            let n := mload(s)
            mstore(result, add(n, n)) // Store the new length.
            s := add(s, 0x20)
            let o := add(result, 0x20)
            // forgefmt: disable-next-item
            for { let i := 0 } lt(i, n) { i := add(i, 0x10) } {
                let x := shr(128, mload(add(s, i)))
                x := and(0x0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff, or(shl(64, x), x))
                x := and(0x00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff, or(shl(32, x), x))
                x := and(0x0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff, or(shl(16, x), x))
                x := and(0x00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff, or(shl(8, x), x))
                mstore(add(o, add(i, i)),
                    and(0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f, or(shl(4, x), x)))
            }
            mstore(add(o, add(s, s)), 0) // Zeroize slot after result.
            mstore(0x40, add(0x40, add(o, add(s, s)))) // Allocate memory.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     BOOLEAN OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // A Solidity bool on the stack or memory is represented as a 256-bit word.
    // Non-zero values are true, zero is false.
    // A clean bool is either 0 (false) or 1 (true) under the hood.
    // Usually, if not always, the bool result of a regular Solidity expression,
    // or the argument of a public/external function will be a clean bool.
    // You can usually use the raw variants for more performance.
    // If uncertain, test (best with exact compiler settings).
    // Or use the non-raw variants (compiler can sometimes optimize out the double `iszero`s).

    /// @dev Returns `x & y`. Inputs must be clean.
    function rawAnd(bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := and(x, y)
        }
    }

    /// @dev Returns `x & y`.
    function and(bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := and(iszero(iszero(x)), iszero(iszero(y)))
        }
    }

    /// @dev Returns `w & x & y`.
    function and(bool w, bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := iszero(or(iszero(w), or(iszero(x), iszero(y))))
        }
    }

    /// @dev Returns `v & w & x & y`.
    function and(bool v, bool w, bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := iszero(or(or(iszero(v), iszero(w)), or(iszero(x), iszero(y))))
        }
    }

    /// @dev Returns `x | y`. Inputs must be clean.
    function rawOr(bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := or(x, y)
        }
    }

    /// @dev Returns `x | y`.
    function or(bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := iszero(iszero(or(x, y)))
        }
    }

    /// @dev Returns `w | x | y`.
    function or(bool w, bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := iszero(iszero(or(w, or(x, y))))
        }
    }

    /// @dev Returns `v | w | x | y`.
    function or(bool v, bool w, bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := iszero(iszero(or(v, or(w, or(x, y)))))
        }
    }

    /// @dev Returns 1 if `b` is true, else 0. Input must be clean.
    function rawToUint(bool b) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := b
        }
    }

    /// @dev Returns 1 if `b` is true, else 0.
    function toUint(bool b) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := iszero(iszero(b))
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

/// @notice Library for EIP7702 operations.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/accounts/LibEIP7702.sol)
library LibEIP7702 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Failed to deploy the EIP7702Proxy.
    error DeploymentFailed();

    /// @dev The proxy query has failed.
    error ProxyQueryFailed();

    /// @dev Failed to change the proxy admin.
    error ChangeProxyAdminFailed();

    /// @dev Failed to upgrade the proxy.
    error UpgradeProxyFailed();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ERC-1967 storage slot for the implementation in the proxy.
    /// `uint256(keccak256("eip1967.proxy.implementation")) - 1`.
    bytes32 internal constant ERC1967_IMPLEMENTATION_SLOT =
        0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /// @dev The transient storage slot for requesting the proxy to initialize the implementation.
    /// `uint256(keccak256("eip7702.proxy.delegation.initialization.request")) - 1`.
    /// While we would love to use a smaller constant, this slot is used in both the proxy
    /// and the delegation, so we shall just use bytes32 in case we want to standardize this.
    bytes32 internal constant EIP7702_PROXY_DELEGATION_INITIALIZATION_REQUEST_SLOT =
        0x94e11c6e41e7fb92cb8bb65e13fdfbd4eba8b831292a1a220f7915c78c7c078f;

    /// @dev The creation code for the EIP7702Proxy.
    /// This is generated from `EIP7702Proxy.sol` with exact compilation settings.
    bytes internal constant EIP7702_PROXY_CREATION_CODE =
        hex"60c06040819052306080526102d63881900390819083398101604081905261002691610096565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8290557fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103819055811515110260a0526100c7565b80516001600160a01b0381168114610091575f5ffd5b919050565b5f5f604083850312156100a7575f5ffd5b6100b08361007b565b91506100be6020840161007b565b90509250929050565b60805160a0516101f06100e65f395f602701525f600601526101f05ff3fe60016040527f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc361960601c30841861010a576001361161008657815481165f5260205ff35b5f3560e01c80635c60da1b036100a157825482165f5260205ff35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038163f851a440036100d65780545f5260205ff35b80543303610106578382630900f01014028183638f2839701402178015610104576004358416815560206040f35b505b5f5ffd5b815481163660010361013b5780610133575082806101335760205f5f5f885afa15610106573d5ff35b805f5260205ff35b365f5f37806101a7575082806101a7576020365f5f885afa5f5f365f36515af416610168573d5f5f3e3d5ffd5b7f94e11c6e41e7fb92cb8bb65e13fdfbd4eba8b831292a1a220f7915c78c7c078f805c1561019e57365184548419161784555f815d5b503d5f5f3e3d5ff35b5f5f365f845af461019e573d5f5f3e3d5ffdfea2646970667358221220e8b1a2a38594baf32c154aa7dd7743c9cd741d4f386b5ab588a5dcd613c3a00e64736f6c634300081c0033";

    /// @dev The keccak256 of runtime code for `EIP7702Proxy.sol` with exact compilation settings,
    /// with immutables zeroized and without the CBOR metadata.
    bytes32 internal constant EIP7702_PROXY_MINIMAL_CODE_HASH =
        0xf8710866f390ac7c12640457f9cb9663657ac8168b7d4ce6418a982932b3043e;

    /// @dev The length of the runtime code for `EIP7702Proxy.sol` with exact compilation settings,
    /// with immutables zeroized and without the CBOR metadata.
    uint256 internal constant EIP7702_PROXY_MINIMAL_CODE_LENGTH = 0x1ba;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*               AUTHORITY AND PROXY OPERATIONS               */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the delegation of the account.
    /// If the account is not an EIP7702 authority, returns `address(0)`.
    function delegationOf(address account) internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            extcodecopy(account, 0x00, 0x00, 0x20)
            // Note: Checking that it starts with hex"ef01" is the most general and futureproof.
            // 7702 bytecode is `abi.encodePacked(hex"ef01", uint8(version), address(delegation))`.
            result := mul(shr(96, mload(0x03)), eq(0xef01, shr(240, mload(0x00))))
        }
    }

    /// @dev Returns the delegation and the implementation of the account.
    /// If the account delegation is not a valid EIP7702Proxy, returns `address(0)`.
    function delegationAndImplementationOf(address account)
        internal
        view
        returns (address delegation, address implementation)
    {
        delegation = delegationOf(account);
        if (isEIP7702Proxy(delegation)) {
            /// @solidity memory-safe-assembly
            assembly {
                mstore(0x00, 0)
                if iszero(staticcall(gas(), account, 0x00, 0x01, 0x00, 0x20)) { revert(0x00, 0x00) }
                implementation := mload(0x00)
            }
        }
    }

    /// @dev Returns the implementation of `target`.
    /// If `target` is neither an EIP7702Proxy nor an EOA delegated to an EIP7702Proxy, returns `address(0)`.
    function implementationOf(address target) internal view returns (address result) {
        if (!isEIP7702Proxy(target)) if (!isEIP7702Proxy(delegationOf(target))) return address(0);
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0)
            if iszero(staticcall(gas(), target, 0x00, 0x01, 0x00, 0x20)) { revert(0x00, 0x00) }
            result := mload(0x00)
        }
    }

    /// @dev Returns if `target` is an valid EIP7702Proxy based on a bytecode hash check.
    function isEIP7702Proxy(address target) internal view returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            // Copy the runtime bytecode without the CBOR metadata.
            extcodecopy(target, m, 0x00, EIP7702_PROXY_MINIMAL_CODE_LENGTH)
            // Zeroize the immutables.
            mstore(add(m, 0x06), 0) // The first `7f<immutable_word>`.
            mstore(add(m, 0x27), 0) // The second `7f<immutable_word>`.
            let h := keccak256(m, EIP7702_PROXY_MINIMAL_CODE_LENGTH)
            result := eq(EIP7702_PROXY_MINIMAL_CODE_HASH, h)
        }
    }

    /// @dev Returns the initialization code for the EIP7702Proxy.
    function proxyInitCode(address initialImplementation, address initialAdmin)
        internal
        pure
        returns (bytes memory)
    {
        return abi.encodePacked(
            EIP7702_PROXY_CREATION_CODE,
            uint256(uint160(initialImplementation)),
            uint256(uint160(initialAdmin))
        );
    }

    /// @dev Deploys an EIP7702Proxy.
    function deployProxy(address initialImplementation, address initialAdmin)
        internal
        returns (address instance)
    {
        bytes memory initCode = proxyInitCode(initialImplementation, initialAdmin);
        /// @solidity memory-safe-assembly
        assembly {
            instance := create(0, add(initCode, 0x20), mload(initCode))
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Deploys an EIP7702Proxy to a deterministic address with `salt`.
    function deployProxyDeterministic(
        address initialImplementation,
        address initialAdmin,
        bytes32 salt
    ) internal returns (address instance) {
        bytes memory initCode = proxyInitCode(initialImplementation, initialAdmin);
        /// @solidity memory-safe-assembly
        assembly {
            instance := create2(0, add(initCode, 0x20), mload(initCode), salt)
            if iszero(instance) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Returns the admin of the proxy.
    /// Assumes that the proxy is a proper EIP7702Proxy, if it exists.
    function proxyAdmin(address proxy) internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0xf851a440) // `admin()`.
            let t := staticcall(gas(), proxy, 0x1c, 0x04, 0x00, 0x20)
            if iszero(and(gt(returndatasize(), 0x1f), t)) {
                mstore(0x00, 0x26ec9b6a) // `ProxyQueryFailed()`.
                revert(0x1c, 0x04)
            }
            result := mload(0x00)
        }
    }

    /// @dev Changes the admin on the proxy. The caller must be the admin.
    /// Assumes that the proxy is a proper EIP7702Proxy, if it exists.
    function changeProxyAdmin(address proxy, address newAdmin) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x8f283970) // `changeAdmin(address)`.
            mstore(0x20, newAdmin) // The implementation will clean the upper 96 bits.
            if iszero(and(eq(mload(0x00), 1), call(gas(), proxy, 0, 0x1c, 0x24, 0x00, 0x20))) {
                mstore(0x00, 0xc502e37e) // `ChangeProxyAdminFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Changes the implementation on the proxy. The caller must be the admin.
    /// Assumes that the proxy is a proper EIP7702Proxy, if it exists.
    function upgradeProxy(address proxy, address newImplementation) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x0900f010) // `upgrade(address)`.
            mstore(0x20, newImplementation) // The implementation will clean the upper 96 bits.
            if iszero(and(eq(mload(0x00), 1), call(gas(), proxy, 0, 0x1c, 0x24, 0x00, 0x20))) {
                mstore(0x00, 0xc6edd882) // `UpgradeProxyFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      UUPS OPERATIONS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Upgrades the implementation.
    /// The new implementation will NOT be active until the next UserOp or transaction.
    /// To "auto-upgrade" to the latest implementation on the proxy, pass in `address(0)` to reset
    /// the implementation slot. This causes the proxy to use the latest default implementation,
    /// which may be optionally reinitialized via `requestProxyDelegationInitialization()`.
    /// This function is intended to be used on the authority of an EIP7702Proxy delegation.
    /// The most intended usage pattern is to wrap this in an access-gated admin function.
    function upgradeProxyDelegation(address newImplementation) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let s := ERC1967_IMPLEMENTATION_SLOT
            // Preserve the upper 96 bits when updating in case they are used for some stuff.
            mstore(0x00, sload(s))
            mstore(0x0c, shl(96, newImplementation))
            sstore(s, mload(0x00))
        }
    }

    /// @dev Requests the implementation to be initialized to the latest implementation on the proxy.
    /// This function is intended to be used on the authority of an EIP7702Proxy delegation.
    /// The most intended usage pattern is to place it at the end of an `execute` function.
    function requestProxyDelegationInitialization() internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(shl(96, sload(ERC1967_IMPLEMENTATION_SLOT))) {
                // Use a dedicated transient storage slot for better Swiss-cheese-model safety.
                tstore(EIP7702_PROXY_DELEGATION_INITIALIZATION_REQUEST_SLOT, address())
            }
        }
    }
}

File 38 of 44 : IBaseAccountEventsAndErrors.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// ──────────────────────────────────────────────────────────────────────────────
//     _   __    _  __
//    / | / /__ | |/ /_  _______
//   /  |/ / _ \|   / / / / ___/
//  / /|  /  __/   / /_/ (__  )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Accounts compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

/// @title Execution Manager Events and Errors Interface
/// @notice Interface for defining events and errors related to transaction execution processes within smart accounts.
/// @dev This interface defines events and errors used by execution manager to handle and report the operational status
/// of
/// smart account transactions.
/// It is a part of the Nexus suite of contracts aimed at implementing flexible and secure smart account operations.
/// @author @livingrockrises | Biconomy | [email protected]
/// @author @aboudjem | Biconomy | [email protected]
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady
interface IBaseAccountEventsAndErrors {
    /// @dev Throws an error when a caller is not authorized to access an account.
    error AccountAccessUnauthorized();
}

File 39 of 44 : IStorage.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// ──────────────────────────────────────────────────────────────────────────────
//     _   __    _  __
//    / | / /__ | |/ /_  _______
//   /  |/ / _ \|   / / / / ___/
//  / /|  /  __/   / /_/ (__  )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Accounts compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

import { SentinelListLib } from "sentinellist/SentinelList.sol";
import { IHook, IPreValidationHookERC1271, IPreValidationHookERC4337 } from "erc7579/interfaces/IERC7579Module.sol";
import { CallType } from "../../../lib/erc-7579/ModeLib.sol";

/// @title Nexus - IStorage Interface
/// @notice Provides structured storage for Modular Smart Account under the Nexus suite, compliant with ERC-7579 and
/// ERC-4337.
/// @dev Manages structured storage using SentinelListLib for validators and executors, and a mapping for fallback
/// handlers.
/// This interface utilizes ERC-7201 storage location practices to ensure isolated and collision-resistant storage
/// spaces
/// within smart contracts.
/// It is designed to support dynamic execution and modular management strategies essential for advanced smart account
/// architectures.
/// @custom:storage-location erc7201:biconomy.storage.Nexus
/// @author @livingrockrises | Biconomy | [email protected]
/// @author @aboudjem | Biconomy | [email protected]
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady
interface IStorage {
    /// @notice Struct storing validators and executors using Sentinel lists, and fallback handlers via mapping.
    struct AccountStorage {
        ///< List of validators, initialized upon contract deployment.
        SentinelListLib.SentinelList validators;
        ///< List of executors, similarly initialized.
        SentinelListLib.SentinelList executors;
        ///< Mapping of selectors to their respective fallback handlers.
        mapping(bytes4 => FallbackHandler) fallbacks;
        ///< Current hook module associated with this account.
        IHook hook;
        ///< Mapping of hooks to requested timelocks.
        mapping(address hook => uint256) emergencyUninstallTimelock;
        ///< PreValidation hook for validateUserOp
        IPreValidationHookERC4337 preValidationHookERC4337;
        ///< PreValidation hook for isValidSignature
        IPreValidationHookERC1271 preValidationHookERC1271;
        ///< Mapping of used nonces for replay protection.
        mapping(uint256 => bool) nonces;
        ///< ERC-7484 registry
        address registry; // keeping this to avoid collisions b/w versions
        ///< Mapping of used 7702 init hashes for replay protection.
        mapping(bytes32 => bool) erc7702InitHashes;
    }

    /// @notice Defines a fallback handler with an associated handler address and a call type.
    struct FallbackHandler {
        ///< The address of the fallback function handler.
        address handler;
        ///< The type of call this handler supports (e.g., static or call).
        CallType calltype;
    }
}

File 40 of 44 : IModuleManagerEventsAndErrors.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// ──────────────────────────────────────────────────────────────────────────────
//     _   __    _  __
//    / | / /__ | |/ /_  _______
//   /  |/ / _ \|   / / / / ___/
//  / /|  /  __/   / /_/ (__  )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Accounts compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

import { CallType } from "../../../lib/erc-7579/ModeLib.sol";

/// @title ERC-7579 Module Manager Events and Errors Interface
/// @notice Provides event and error definitions for actions related to module management in smart accounts.
/// @dev Used by IModuleManager to define the events and errors associated with the installation and management of
/// modules.
/// @author @livingrockrises | Biconomy | [email protected]
/// @author @aboudjem | Biconomy | [email protected]
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady
interface IModuleManagerEventsAndErrors {
    /// @notice Emitted when a module is installed onto a smart account.
    /// @param moduleTypeId The identifier for the type of module installed.
    /// @param module The address of the installed module.
    event ModuleInstalled(uint256 moduleTypeId, address module);

    /// @notice Emitted when a module is uninstalled from a smart account.
    /// @param moduleTypeId The identifier for the type of module uninstalled.
    /// @param module The address of the uninstalled module.
    event ModuleUninstalled(uint256 moduleTypeId, address module);

    /// @dev Thrown when the specified module address is not recognized as valid.
    error InvalidModule(address module);

    /// @dev Thrown when an invalid module type identifier is provided.
    error InvalidModuleTypeId(uint256 moduleTypeId);

    /// @dev Thrown when there is an attempt to install a module that is already installed.
    error ModuleAlreadyInstalled(uint256 moduleTypeId, address module);

    /// @dev Thrown when an operation is performed by an unauthorized operator.
    error UnauthorizedOperation(address operator);

    /// @dev Thrown when there is an attempt to uninstall a module that is not installed.
    error ModuleNotInstalled(uint256 moduleTypeId, address module);

    /// @dev Thrown when a module address is set to zero.
    error ModuleAddressCanNotBeZero();

    /// @dev Thrown when a post-check fails after hook execution.
    error HookPostCheckFailed();

    /// @dev Thrown when there is an attempt to install a hook while another is already installed.
    error HookAlreadyInstalled(address currentHook);

    /// @dev Thrown when there is an attempt to install a PreValidationHook while another is already installed.
    error PrevalidationHookAlreadyInstalled(address currentPreValidationHook);

    /// @dev Thrown when there is an attempt to install a fallback handler for a selector already having one.
    error FallbackAlreadyInstalledForSelector(bytes4 selector);

    /// @dev Thrown when there is an attempt to uninstall a fallback handler for a selector that does not have one
    /// installed.
    error FallbackNotInstalledForSelector(bytes4 selector);

    /// @dev Thrown when Invalid data is provided for MultiType install flow
    error InvalidInput();

    /// @dev Thrown when unable to validate Emergency Uninstall signature
    error EmergencyUninstallSigError();

    /// @notice Error thrown when an invalid nonce is used
    error InvalidNonce();

    /// Error thrown when account installs/uninstalls module with mismatched moduleTypeId
    error MismatchModuleTypeId();

    /// @dev Thrown when there is an attempt to install a forbidden selector as a fallback handler.
    error FallbackSelectorForbidden();

    /// @dev Thrown when there is an attempt to install a fallback handler with an invalid calltype for a given
    /// selector.
    error FallbackCallTypeInvalid();

    /// @notice Error thrown when an execution with an unsupported CallType was made.
    /// @param callType The unsupported call type.
    error UnsupportedCallType(CallType callType);

    /// @notice Error thrown when the default validator is already installed.
    error DefaultValidatorAlreadyInstalled();
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

/**
 * @title ModeLib
 * To allow smart accounts to be very simple, but allow for more complex execution, A custom mode
 * encoding is used.
 *    Function Signature of execute function:
 *           function execute(ModeCode mode, bytes calldata executionCalldata) external payable;
 * This allows for a single bytes32 to be used to encode the execution mode, calltype, execType and
 * context.
 * NOTE: Simple Account implementations only have to scope for the most significant byte. Account  that
 * implement
 * more complex execution modes may use the entire bytes32.
 *
 * |--------------------------------------------------------------------|
 * | CALLTYPE  | EXECTYPE  |   UNUSED   | ModeSelector  |  ModePayload  |
 * |--------------------------------------------------------------------|
 * | 1 byte    | 1 byte    |   4 bytes  | 4 bytes       |   22 bytes    |
 * |--------------------------------------------------------------------|
 *
 * CALLTYPE: 1 byte
 * CallType is used to determine how the executeCalldata paramter of the execute function has to be
 * decoded.
 * It can be either single, batch or delegatecall. In the future different calls could be added.
 * CALLTYPE can be used by a validation module to determine how to decode <userOp.callData[36:]>.
 *
 * EXECTYPE: 1 byte
 * ExecType is used to determine how the account should handle the execution.
 * It can indicate if the execution should revert on failure or continue execution.
 * In the future more execution modes may be added.
 * Default Behavior (EXECTYPE = 0x00) is to revert on a single failed execution. If one execution in
 * a batch fails, the entire batch is reverted
 *
 * UNUSED: 4 bytes
 * Unused bytes are reserved for future use.
 *
 * ModeSelector: bytes4
 * The "optional" mode selector can be used by account vendors, to implement custom behavior in
 * their accounts.
 * the way a ModeSelector is to be calculated is bytes4(keccak256("vendorname.featurename"))
 * this is to prevent collisions between different vendors, while allowing innovation and the
 * development of new features without coordination between ERC-7579 implementing accounts
 *
 * ModePayload: 22 bytes
 * Mode payload is used to pass additional data to the smart account execution, this may be
 * interpreted depending on the ModeSelector
 *
 * ExecutionCallData: n bytes
 * single, delegatecall or batch exec abi.encoded as bytes
 */
import { Execution } from "../interfaces/IERC7579Account.sol";

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

type CallType is bytes1;

type ExecType is bytes1;

type ModeSelector is bytes4;

type ModePayload is bytes22;

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

// @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);

ModeSelector constant MODE_DEFAULT = ModeSelector.wrap(bytes4(0x00000000));
// Example declaration of a custom mode selector
ModeSelector constant MODE_OFFSET = ModeSelector.wrap(bytes4(keccak256("default.mode.offset")));

/**
 * @dev ModeLib is a helper library to encode/decode ModeCodes
 */
library ModeLib {
    function decode(ModeCode mode)
        internal
        pure
        returns (
            CallType _calltype,
            ExecType _execType,
            ModeSelector _modeSelector,
            ModePayload _modePayload
        )
    {
        assembly {
            _calltype := mode
            _execType := shl(8, mode)
            _modeSelector := shl(48, mode)
            _modePayload := shl(80, mode)
        }
    }

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

    function encodeSimpleBatch() internal pure returns (ModeCode mode) {
        mode = encode(CALLTYPE_BATCH, EXECTYPE_DEFAULT, MODE_DEFAULT, ModePayload.wrap(0x00));
    }

    function encodeSimpleSingle() internal pure returns (ModeCode mode) {
        mode = encode(CALLTYPE_SINGLE, EXECTYPE_DEFAULT, MODE_DEFAULT, ModePayload.wrap(0x00));
    }

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

using { eqModeSelector as == } for ModeSelector global;
using { eqCallType 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 eqExecType(ExecType a, ExecType b) pure returns (bool) {
    return ExecType.unwrap(a) == ExecType.unwrap(b);
}

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

File 42 of 44 : IExecutionHelperEventsAndErrors.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

// ──────────────────────────────────────────────────────────────────────────────
//     _   __    _  __
//    / | / /__ | |/ /_  _______
//   /  |/ / _ \|   / / / / ___/
//  / /|  /  __/   / /_/ (__  )
// /_/ |_/\___/_/|_\__,_/____/
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Accounts compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

/// @title Execution Manager Events and Errors Interface
/// @notice Interface for defining events and errors related to transaction execution processes within smart accounts.
/// @dev This interface defines events and errors used by execution manager to handle and report the operational status
/// of
/// smart account transactions.
/// It is a part of the Nexus suite of contracts aimed at implementing flexible and secure smart account operations.
/// @author @livingrockrises | Biconomy | [email protected]
/// @author @aboudjem | Biconomy | [email protected]
/// @author @filmakarov | Biconomy | [email protected]
/// @author @zeroknots | Rhinestone.wtf | zeroknots.eth
/// Special thanks to the Solady team for foundational contributions: https://github.com/Vectorized/solady

import { ExecType } from "../../../lib/erc-7579/ModeLib.sol";

interface IExecutionHelperEventsAndErrors {
    /// @notice Event emitted when a transaction fails to execute successfully.
    event TryExecuteUnsuccessful(bytes callData, bytes result);

    /// @notice Event emitted when a transaction fails to execute successfully.
    event TryDelegateCallUnsuccessful(bytes callData, bytes result);

    /// @notice Error thrown when an execution with an unsupported ExecType was made.
    /// @param execType The unsupported execution type.
    error UnsupportedExecType(ExecType execType);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import { EfficientHashLib } from "solady/utils/EfficientHashLib.sol";

/**
 * @title ComposableStorage
 * @dev Contract to handle generic storage operations with cross-chain support
 */
contract ComposableStorage {
    using EfficientHashLib for *;

    error SlotNotInitialized();

    // Mapping to track initialized slots
    mapping(bytes32 => bool) private initializedSlots;

    // Mapping to track length of dynamic data
    mapping(bytes32 => uint256) private dynamicDataLength;

    /**
     * @dev Internal function to write a value to a specific storage slot
     */
    function _writeStorage(bytes32 slot, bytes32 value, bytes32 namespace) private {
        bytes32 namespacedSlot = getNamespacedSlot(namespace, slot);
        initializedSlots[namespacedSlot] = true;
        assembly {
            sstore(namespacedSlot, value)
        }
    }

    /**
     * @dev Write a value to a specific storage slot
     * @param slot The storage slot to write to
     * @param value The value to write
     */
    function writeStorage(bytes32 slot, bytes32 value, address account) external {
        bytes32 namespace = getNamespace(account, msg.sender);
        _writeStorage(slot, value, namespace);
    }

    /**
     * @dev Read a value from a specific namespace and slot
     * @param namespace The namespace (typically a contract address)
     * @param slot The storage slot to read from
     * @return The value stored at the specified namespaced slot
     */
    function readStorage(bytes32 namespace, bytes32 slot) external view returns (bytes32) {
        bytes32 namespacedSlot = getNamespacedSlot(namespace, slot);
        if (!initializedSlots[namespacedSlot]) {
            revert SlotNotInitialized();
        }
        bytes32 value;
        assembly {
            value := sload(namespacedSlot)
        }
        return value;
    }

    /**
     * @dev Generates a namespaced slot
     * @param namespace The namespace (typically a contract address)
     * @param slot The storage slot to read from
     * return The namespaced slot
     */
    function getNamespacedSlot(bytes32 namespace, bytes32 slot) public pure returns (bytes32 result) {
        assembly {
            mstore(0x00, namespace)
            mstore(0x20, slot)
            result := keccak256(0x00, 0x40)
        }
    }

    /**
     * @dev Generates a namespace for a given account and caller
     * @param account The account address
     * @param _caller The caller address
     * return The generated namespace
     */
    function getNamespace(address account, address _caller) public pure returns (bytes32 result) {
        assembly {
            mstore(0x00, account)
            mstore(0x14, _caller)
            result := keccak256(0x0c, 0x28)
        }
    }

    /**
     * @dev Check if a slot has been initialized
     */
    function isSlotInitialized(bytes32 namespace, bytes32 slot) external view returns (bool) {
        bytes32 namespacedSlot = getNamespacedSlot(namespace, slot);
        return initializedSlots[namespacedSlot];
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

Settings
{
  "remappings": [
    "forge-std/=node_modules/forge-std/src/",
    "account-abstraction/=node_modules/account-abstraction/contracts/",
    "solady/=node_modules/solady/src/",
    "sentinellist/=node_modules/@rhinestone/sentinellist/src/",
    "module-bases/=node_modules/@rhinestone/module-bases/src/",
    "erc7739Validator/=node_modules/@erc7579/erc7739-validator-base/src/",
    "EnumerableSet4337/=node_modules/@erc7579/enumerablemap4337/src/",
    "erc7579/=node_modules/@erc7579/implementation/src/",
    "byteslib/=node_modules/solidity-bytes-utils/contracts/",
    "rlp-reader/=node_modules/solidity-rlp/contracts/",
    "murky-trees/=node_modules/murky/src/",
    "solarray/=node_modules/solarray/src/",
    "excessively-safe-call/=node_modules/excessively-safe-call/src/",
    "@ERC4337/=node_modules/@ERC4337/",
    "@erc7579/=node_modules/@erc7579/",
    "@gnosis.pm/=node_modules/@gnosis.pm/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "@prb/=node_modules/@prb/",
    "@rhinestone/=node_modules/@rhinestone/",
    "@safe-global/=node_modules/@safe-global/",
    "@zerodev/=node_modules/@zerodev/",
    "account-abstraction-v0.6/=node_modules/account-abstraction-v0.6/",
    "ds-test/=node_modules/ds-test/",
    "hardhat-deploy/=node_modules/hardhat-deploy/",
    "hardhat/=node_modules/hardhat/",
    "solidity-bytes-utils/=node_modules/solidity-bytes-utils/",
    "solidity-rlp/=node_modules/solidity-rlp/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 999
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": true
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"anEntryPoint","type":"address"},{"internalType":"address","name":"defaultValidator","type":"address"},{"internalType":"bytes","name":"initData","type":"bytes"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccountAccessUnauthorized","type":"error"},{"inputs":[],"name":"AccountAlreadyInitialized","type":"error"},{"inputs":[],"name":"AccountNotInitialized","type":"error"},{"inputs":[{"internalType":"enum ConstraintType","name":"constraintType","type":"uint8"}],"name":"ConstraintNotMet","type":"error"},{"inputs":[],"name":"DefaultValidatorAlreadyInstalled","type":"error"},{"inputs":[],"name":"ERC7702AccountCannotBeUpgradedThisWay","type":"error"},{"inputs":[],"name":"EmergencyTimeLockNotExpired","type":"error"},{"inputs":[],"name":"EmergencyUninstallSigError","type":"error"},{"inputs":[],"name":"EntryPointCanNotBeZero","type":"error"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"FallbackAlreadyInstalledForSelector","type":"error"},{"inputs":[],"name":"FallbackCallTypeInvalid","type":"error"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"FallbackNotInstalledForSelector","type":"error"},{"inputs":[],"name":"FallbackSelectorForbidden","type":"error"},{"inputs":[{"internalType":"address","name":"currentHook","type":"address"}],"name":"HookAlreadyInstalled","type":"error"},{"inputs":[],"name":"HookPostCheckFailed","type":"error"},{"inputs":[],"name":"InvalidConstraintType","type":"error"},{"inputs":[],"name":"InvalidImplementationAddress","type":"error"},{"inputs":[],"name":"InvalidInitData","type":"error"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[{"internalType":"address","name":"module","type":"address"}],"name":"InvalidModule","type":"error"},{"inputs":[{"internalType":"uint256","name":"moduleTypeId","type":"uint256"}],"name":"InvalidModuleTypeId","type":"error"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"InvalidOutputParamFetcherType","type":"error"},{"inputs":[{"internalType":"string","name":"message","type":"string"}],"name":"InvalidParameterEncoding","type":"error"},{"inputs":[{"internalType":"string","name":"message","type":"string"}],"name":"InvalidSetOfInputParams","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"LinkedList_AlreadyInitialized","type":"error"},{"inputs":[{"internalType":"address","name":"entry","type":"address"}],"name":"LinkedList_EntryAlreadyInList","type":"error"},{"inputs":[{"internalType":"address","name":"entry","type":"address"}],"name":"LinkedList_InvalidEntry","type":"error"},{"inputs":[],"name":"LinkedList_InvalidPage","type":"error"},{"inputs":[],"name":"MismatchModuleTypeId","type":"error"},{"inputs":[],"name":"ModuleAddressCanNotBeZero","type":"error"},{"inputs":[{"internalType":"uint256","name":"moduleTypeId","type":"uint256"},{"internalType":"address","name":"module","type":"address"}],"name":"ModuleAlreadyInstalled","type":"error"},{"inputs":[{"internalType":"uint256","name":"moduleTypeId","type":"uint256"},{"internalType":"address","name":"module","type":"address"}],"name":"ModuleNotInstalled","type":"error"},{"inputs":[],"name":"Output_StaticCallFailed","type":"error"},{"inputs":[{"internalType":"address","name":"currentPreValidationHook","type":"address"}],"name":"PrevalidationHookAlreadyInstalled","type":"error"},{"inputs":[],"name":"UnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"UnauthorizedOperation","type":"error"},{"inputs":[{"internalType":"CallType","name":"callType","type":"bytes1"}],"name":"UnsupportedCallType","type":"error"},{"inputs":[{"internalType":"ExecType","name":"execType","type":"bytes1"}],"name":"UnsupportedExecType","type":"error"},{"inputs":[{"internalType":"uint256","name":"moduleTypeId","type":"uint256"}],"name":"UnsupportedModuleType","type":"error"},{"inputs":[],"name":"UpgradeFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"hook","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"EmergencyHookUninstallRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"hook","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"EmergencyHookUninstallRequestReset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"moduleTypeId","type":"uint256"},{"indexed":false,"internalType":"address","name":"module","type":"address"}],"name":"ModuleInstalled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"moduleTypeId","type":"uint256"},{"indexed":false,"internalType":"address","name":"module","type":"address"}],"name":"ModuleUninstalled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"callData","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"result","type":"bytes"}],"name":"TryDelegateCallUnsuccessful","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"callData","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"result","type":"bytes"}],"name":"TryExecuteUnsuccessful","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"accountId","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"addDeposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"hook","type":"address"},{"internalType":"uint256","name":"hookType","type":"uint256"},{"internalType":"bytes","name":"deInitData","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct EmergencyUninstall","name":"data","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"emergencyUninstallHook","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"entryPoint","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ExecutionMode","name":"mode","type":"bytes32"},{"internalType":"bytes","name":"executionCalldata","type":"bytes"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes4","name":"functionSig","type":"bytes4"},{"components":[{"internalType":"enum InputParamType","name":"paramType","type":"uint8"},{"internalType":"enum InputParamFetcherType","name":"fetcherType","type":"uint8"},{"internalType":"bytes","name":"paramData","type":"bytes"},{"components":[{"internalType":"enum ConstraintType","name":"constraintType","type":"uint8"},{"internalType":"bytes","name":"referenceData","type":"bytes"}],"internalType":"struct Constraint[]","name":"constraints","type":"tuple[]"}],"internalType":"struct InputParam[]","name":"inputParams","type":"tuple[]"},{"components":[{"internalType":"enum OutputParamFetcherType","name":"fetcherType","type":"uint8"},{"internalType":"bytes","name":"paramData","type":"bytes"}],"internalType":"struct OutputParam[]","name":"outputParams","type":"tuple[]"}],"internalType":"struct ComposableExecution[]","name":"executions","type":"tuple[]"}],"name":"executeComposable","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"ExecutionMode","name":"mode","type":"bytes32"},{"internalType":"bytes","name":"executionCalldata","type":"bytes"}],"name":"executeFromExecutor","outputs":[{"internalType":"bytes[]","name":"returnData","type":"bytes[]"}],"stateMutability":"payable","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":"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"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"executeUserOp","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getActiveHook","outputs":[{"internalType":"address","name":"hook","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDefaultValidator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDeposit","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"cursor","type":"address"},{"internalType":"uint256","name":"size","type":"uint256"}],"name":"getExecutorsPaginated","outputs":[{"internalType":"address[]","name":"array","type":"address[]"},{"internalType":"address","name":"next","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"getFallbackHandlerBySelector","outputs":[{"internalType":"CallType","name":"","type":"bytes1"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getImplementation","outputs":[{"internalType":"address","name":"implementation","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"cursor","type":"address"},{"internalType":"uint256","name":"size","type":"uint256"}],"name":"getValidatorsPaginated","outputs":[{"internalType":"address[]","name":"array","type":"address[]"},{"internalType":"address","name":"next","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"initData","type":"bytes"}],"name":"initializeAccount","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"moduleTypeId","type":"uint256"},{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"initData","type":"bytes"}],"name":"installModule","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"isInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"moduleTypeId","type":"uint256"},{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"additionalContext","type":"bytes"}],"name":"isModuleInstalled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"ExecutionMode","name":"mode","type":"bytes32"}],"name":"supportsExecutionMode","outputs":[{"internalType":"bool","name":"isSupported","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"moduleTypeId","type":"uint256"}],"name":"supportsModule","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"moduleTypeId","type":"uint256"},{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"deInitData","type":"bytes"}],"name":"uninstallModule","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","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":"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":"op","type":"tuple"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"uint256","name":"missingAccountFunds","type":"uint256"}],"name":"validateUserOp","outputs":[{"internalType":"uint256","name":"validationData","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawDepositTo","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]

610180806040523461030a5761637d803803809161001d8285610376565b833981019060608183031261030a5761003581610399565b9061004260208201610399565b604082015190916001600160401b03821161030a57019280601f8501121561030a5783516001600160401b038111610362576040519461008c601f8301601f191660200187610376565b81865260208601926020838301011161030a57815f926020809301855e860101523060a0524660c05260409360a085516100c68782610376565b600581526020810190644e6578757360d81b82528751916100e78984610376565b6005835264312e332e3160d81b6020938401529051902060e08190527fd6f9477f1bbaaf55b72b2869a6c4697af6529f6af9f67d87058f1bf5bec0188761010081905288517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815280840192909252818901524660608201523060808201529190912061012052855163ecd0596160e01b8152600160048201526001600160a01b038516939181602481875afa908115610358575f9161031d575b501561030e57823b1561030a576044925f928388519586809581946306d61fe760e41b8352602060048401525180918160248501528484015e8181018301849052601f01601f191681010301925af18015610300576102f0575b506101405230610160526001600160a01b038116156102e15760805251615fcf90816103ae82396080518181816103c90152818161068f0152818161082301528181610f5e0152818161113401528181611206015281816113db0152818161152d015281816115760152818161184501526121a2015260a051816144d2015260c051816144f5015260e051816145650152610100518161458b015261012051816144b101526101405181818161024101528181611fb101528181612b9101528181612bee01528181613dc001526153420152610160518181816109de01526121710152f35b6307e355bf60e31b5f5260045ffd5b5f6102fa91610376565b5f6101fc565b84513d5f823e3d90fd5b5f80fd5b631c4f83bb60e31b5f5260045ffd5b90506020813d602011610350575b8161033860209383610376565b8101031261030a5751801515810361030a575f6101a2565b3d915061032b565b87513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b601f909101601f19168101906001600160401b0382119082101761036257604052565b51906001600160a01b038216820361030a5756fe60806040526004361015610015575b366127fd57005b5f3560e01c80630a664dba146101d45780630b3dc354146101cf578063112d3a7d146101ca5780631626ba7e146101c557806319822f7c146101c0578063392e53cd146101bb578063481ddd23146101b65780634a58db19146101b15780634b6a1419146101ac5780634d44560d146101a75780634f1ef286146101a257806352d1902d1461019d5780635bfeadbb146101985780635faac46b146101935780637eba07b81461018e57806384b0196e146101895780638dd7712f146101845780639517e29f1461017f5780639cfd7cff1461017a578063a71763a814610175578063aaf10f4214610170578063b0d691fe1461016b578063c399ec8814610166578063d03c791414610161578063d691c9641461015c578063e9ae5c5314610157578063ea5f61d0146101525763f2dc691d0361000e57611a00565b611904565b61182e565b6116e7565b6115a7565b611551565b61150e565b6114b0565b6113c7565b611368565b6111ef565b6110fb565b611041565b610f00565b610d41565b610a39565b6109cb565b6108a3565b610808565b6106b7565b61067d565b6105e8565b6105bc565b610378565b610317565b6102f1565b610222565b6101e7565b5f9103126101e357565b5f80fd5b346101e3575f3660031901126101e35760206001600160a01b035f516020615f835f395f51905f5254166001600160a01b0360405191168152f35b346101e3575f3660031901126101e35760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b6001600160a01b038116036101e357565b359061028182610265565b565b9181601f840112156101e35782359167ffffffffffffffff83116101e357602083818601950101116101e357565b60606003198201126101e357600435916024356102cd81610265565b916044359067ffffffffffffffff82116101e3576102ed91600401610283565b9091565b346101e357602061030d610304366102b1565b92919091612a56565b6040519015158152f35b346101e35760403660031901126101e35760043560243567ffffffffffffffff81116101e357602091610351610357923690600401610283565b91611bd5565b6001600160e01b031960405191168152f35b90816101209103126101e35790565b346101e35760603660031901126101e35760043567ffffffffffffffff81116101e3576103ac61047a913690600401610369565b602061042960243561043460443580956103f06001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163314611cac565b61042e6103fd3683611d76565b95869288810135906104138260031a60f81b1590565b156104f3575b5060401c6001600160a01b031690565b612bdd565b9361301b565b61010084929401525f6001600160a01b036040518098819682957f9700320300000000000000000000000000000000000000000000000000000000845260048401611f5a565b0393165af19081156104ee576104a9925f926104bd575b50806104ad575b506040519081529081906020820190565b0390f35b5f9081803892335af1505f610498565b8192506104e19060203d6020116104e7575b6104d98183611b6b565b810190611eb8565b91610491565b503d6104cf565b611bca565b600382901a60f81b600160f81b036105355761052161051a82610100610528940190611e85565b908a612f27565b3691611d25565b6101008501525b5f610419565b600382901a60f81b7f02000000000000000000000000000000000000000000000000000000000000001461056a575b5061052f565b6105ab61059f6105996105b69361058e610589610585611f8e565b1590565b611e56565b610100810190611e85565b90612d39565b93919290923691611d25565b610100880152612e50565b5f610564565b346101e3575f3660031901126101e357602061030d611f8e565b6001600160e01b03198116036101e357565b346101e35760203660031901126101e3576040602061064360043561060c816105d6565b6001600160e01b0319165f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0260205260405f2090565b82519061064f82611b4a565b54906001600160f81b03196001600160a01b0383169283835260581b16928391015282519182526020820152f35b5f3660031901126101e3575f388180347f00000000000000000000000000000000000000000000000000000000000000005af1156101e357005b60203660031901126101e35760043567ffffffffffffffff81116101e3576106e66106f8913690600401610283565b9081813033036106fa575b5050612e50565b005b91610706939193613154565b156107f75750506107f06107e38261072d85610725816107b697611a58565b979093611a66565b9490956107b06107a461079e8998809a816040519182372095610754610589610585611f8e565b61079561058961058561078e8a5f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0960205260405f2090565b5460ff1690565b30943691611d25565b8561319f565b6001600160a01b031690565b14612023565b5f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0960205260405f2090565b805460ff19166001179055565b5f806106f1565b91509150610803613176565b6107f0565b60403660031901126101e35760043561082081610265565b5f7f0000000000000000000000000000000000000000000000000000000000000000602435336001600160a01b03831614801561089a575b61086190611cac565b604051936014526034526f205c28780000000000000000000000008252604460108338935af115610892575f603452005b3d5f823e3d90fd5b50333014610858565b60403660031901126101e3576004356108bb81610265565b60243567ffffffffffffffff81116101e3576108db903690600401610283565b906001600160a01b036109026001600160a01b035f516020615f835f395f51905f52541690565b168061091257506106f892612144565b90916040519263d68f602560e01b84525f8480610934363433600485016120de565b038183875af19384156104ee575f946109a3575b50610954929394612144565b803b156101e35761097f5f92918392604051948580948193630b9dfbed60e11b835260048301612104565b03925af180156104ee5761098f57005b8061099d5f6106f893611b6b565b806101d9565b6109549394506109c4903d805f833e6109bc8183611b6b565b810190612098565b9392610948565b346101e3575f3660031901126101e357307f000000000000000000000000000000000000000000000000000000000000000003610a2c5760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b639f03a0265f526004601cfd5b60403660031901126101e35760043567ffffffffffffffff81116101e3578060040190608060031982360301126101e35760243567ffffffffffffffff81116101e357610a8d610a94913690600401610283565b908461329e565b610ab06024820135926044610aa8826122c4565b930190611e85565b929060048214828115610cdb575b610ac7916122ce565b610add8383610ad887858484612a56565b612301565b610b17836001600160a01b03165f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0460205260405f2090565b5480610ba8575050507f2841d18703faaff388732165e48fe431468531b1b1e626b1b7cbcbfc0d79c7409150610ba39042610b82826001600160a01b03165f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0460205260405f2090565b55604080516001600160a01b03909216825242602083015290918291820190565b0390a1005b610bb56203f48082612353565b4210610c20575050507fcbd44a75f6935b5837022648b6c8487db984701200c5381c7c0f8c2b1d69b9da9150610ba39042610b82826001600160a01b03165f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0460205260405f2090565b610c2990612343565b4210610cb3577f341347516a9de374859dfda710fa4828b2d48cb57d4fbe4c1149612b8e02276e93610c98915f610c90866001600160a01b03165f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0460205260405f2090565b558385613461565b604080519182526001600160a01b03929092166020820152a1005b7f07f2f2d2000000000000000000000000000000000000000000000000000000005f5260045ffd5b60026007198201109150610abe565b90929192604082016040835281518091526020606084019201905f5b818110610d22575050506001600160a01b036020919416910152565b82516001600160a01b0316845260209384019390920191600101610d06565b346101e35760403660031901126101e357600435610d5e81610265565b6024359060016001600160a01b038216141580610eee575b610ed3578115610eab5790610d8a8161465a565b610dc2610db55f946001600160a01b03165f525f516020615f635f395f51905f5260205260405f2090565b546001600160a01b031690565b6001600160a01b0381168015159081610e9f575b5080610e96575b15610e3757610e2b610db582610e08610e3194610dfa8988613f46565b906001600160a01b03169052565b6001600160a01b03165f525f516020615f635f395f51905f5260205260405f2090565b9361468c565b92610dc2565b908360016001600160a01b038416141580610e8d575b610e63575b81526104a960405192839283610cea565b9150610e87610e7a610e748461469a565b83613f46565b516001600160a01b031690565b91610e52565b50801515610e4d565b50828410610ddd565b6001915014155f610dd6565b7ff7250817000000000000000000000000000000000000000000000000000000005f5260045ffd5b637c84ecfb60e01b5f526001600160a01b031660045260245ffd5b50610efb61058582613e1e565b610d76565b60203660031901126101e35760043567ffffffffffffffff81116101e357366023820112156101e357806004013567ffffffffffffffff81116101e3576024820191602436918360051b0101116101e357610f856001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163314611cac565b6001600160a01b03610fab6001600160a01b035f516020615f835f395f51905f52541690565b1680610fbb57506106f8916135e1565b906040519263d68f602560e01b84525f8480610fdc363433600485016120de565b038183875af19384156104ee575f94610ffb575b5090610954916135e1565b61095492919450611015903d805f833e6109bc8183611b6b565b939091610ff0565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b346101e3575f3660031901126101e35761109c6110aa61105f613981565b6040929192519384937f0f00000000000000000000000000000000000000000000000000000000000000855260e0602086015260e085019061101d565b90838203604085015261101d565b4660608301523060808301525f60a083015281810360c083015260206060519182815201906080905f5b8181106110e2575050500390f35b82518452859450602093840193909201916001016110d4565b60403660031901126101e35760043567ffffffffffffffff81116101e357611127903690600401610369565b61115b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163314611cac565b6001600160a01b036111816001600160a01b035f516020615f835f395f51905f52541690565b168061119157506106f89061239c565b6040519163d68f602560e01b83525f83806111b1363433600485016120de565b038183865af19283156104ee575f936111cf575b506109549061239c565b6109549193506111e8903d805f833e6109bc8183611b6b565b92906111c5565b6111f8366102b1565b906001600160a01b039392937f0000000000000000000000000000000000000000000000000000000000000000163314801561135f575b61123890611cac565b6112436105856130c4565b611352575b6001600160a01b0384161561132a5760018303611296579061126a9184615260565b5f526020527fd21d0b289f126c4b473ea641963e766833c2f13866e4ff480abd787c100ef12360405fa1005b600283036112ae57906112a99184615160565b61126a565b600383036112c157906112a99184614e7c565b600483036112d457906112a99184614d0f565b6002600719840110156112ed57906112a9918484614b25565b826112fd57906112a991846149fc565b7f098312d2000000000000000000000000000000000000000000000000000000005f52600483905260245ffd5b7f5316c18d000000000000000000000000000000000000000000000000000000005f5260045ffd5b61135a6148c7565b611248565b5033301461122f565b346101e3575f3660031901126101e3576104a9604051611389604082611b6b565b601481527f6269636f6e6f6d792e6e657875732e312e332e31000000000000000000000000602082015260405191829160208352602083019061101d565b6113d0366102b1565b916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016331480156114a7575b61140d90611cac565b6001600160a01b036114336001600160a01b035f516020615f835f395f51905f52541690565b168061144357506106f8936123f6565b916040939193519363d68f602560e01b85525f8580611467363433600485016120de565b038183885af19485156104ee575f95611487575b506109549394956123f6565b6109549495506114a0903d805f833e6109bc8183611b6b565b949361147b565b50333014611404565b346101e3575f3660031901126101e3577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b03811615611506575b6020906001600160a01b0360405191168152f35b5030546114f2565b346101e3575f3660031901126101e35760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101e3575f3660031901126101e357306020526370a082315f52602080806024601c7f00000000000000000000000000000000000000000000000000000000000000005afa601f3d1116815102604051908152f35b346101e35760203660031901126101e3576104a96004358060081b6001600160f81b0319821615918215611640575b821561162b575b50816115f7575b5060405190151581529081906020820190565b6001600160f81b031981161591508115611613575b505f6115e4565b6001600160f81b031916600160f81b1490505f61160c565b6001600160f81b03199081161491505f6115dd565b6001600160f81b03198116600160f81b1492506115d6565b9060406003198301126101e357600435916024359067ffffffffffffffff82116101e3576102ed91600401610283565b602081016020825282518091526040820191602060408360051b8301019401925f915b8383106116ba57505050505090565b90919293946020806116d8600193603f19868203018752895161101d565b970193019301919392906116ab565b6116f036611658565b916116fa33613e5e565b15611802576001600160a01b036117256001600160a01b035f516020615f835f395f51905f52541690565b168061174657509161173a916104a993612598565b60405191829182611688565b90926040519263d68f602560e01b84525f8480611768363433600485016120de565b038183875af19384156104ee575f946117e2575b50611788929394612598565b90803b156101e3576117b45f93918492604051958680948193630b9dfbed60e11b835260048301612104565b03925af19182156104ee576104a9926117ce575b5061173a565b8061099d5f6117dc93611b6b565b5f6117c8565b6117889394506117fb903d805f833e6109bc8183611b6b565b939261177c565b7fb927fe5e000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b61183736611658565b9061186c6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163314611cac565b6001600160a01b036118926001600160a01b035f516020615f835f395f51905f52541690565b16806118a257506106f8926126ea565b90916040519263d68f602560e01b84525f84806118c4363433600485016120de565b038183875af19384156104ee575f946118e4575b506109549293946126ea565b6109549394506118fd903d805f833e6109bc8183611b6b565b93926118d8565b346101e35760403660031901126101e35760043561192181610265565b6024359060016001600160a01b0382161415806119ee575b610ed3578115610eab579061194d8161465a565b611978610db55f946001600160a01b03165f525f516020615fa35f395f51905f5260205260405f2090565b6001600160a01b03811680151590816119e2575b50806119d9575b15610e3757610e2b610db5826119b06119d394610dfa8988613f46565b6001600160a01b03165f525f516020615fa35f395f51905f5260205260405f2090565b92611978565b50828410611993565b6001915014155f61198c565b506119fb61058582613e5e565b611939565b346101e35760203660031901126101e357602060043561031f6001604051921b1615158152f35b634e487b7160e01b5f52601160045260245ffd5b906177398202918083046177391490151715611a5357565b611a27565b906041116101e35790604190565b90929192836041116101e35783116101e357604101916040190190565b906014116101e35790601490565b90929192836014116101e35783116101e357601401916013190190565b906004116101e35790600490565b90929192836004116101e35783116101e357600401916003190190565b90929192836005116101e35783116101e357600501916004190190565b356bffffffffffffffffffffffff19811692919060148210611b16575050565b6bffffffffffffffffffffffff1960149290920360031b82901b16169150565b634e487b7160e01b5f52604160045260245ffd5b6040810190811067ffffffffffffffff821117611b6657604052565b611b36565b90601f8019910116810190811067ffffffffffffffff821117611b6657604052565b908160209103126101e35751611ba2816105d6565b90565b611ba293926001600160a01b036060931682526020820152816040820152019061101d565b6040513d5f823e3d90fd5b918015611c8e575b90611c17611c3e93611c118480611c0b610429611c05611bff60209a8a611a83565b90611af6565b60601c90565b95611a91565b91612c84565b91906001600160a01b03604051809681958294637aa8f17760e11b84523360048501611ba5565b0392165afa5f9181611c5d575b50611ba257506001600160e01b031990565b611c8091925060203d602011611c87575b611c788183611b6b565b810190611b8d565b905f611c4b565b503d611c6e565b611c9c61ffff821904611a3b565b8303611bdd5790611ba292612b0b565b15611cb357565b7fac52ccbe000000000000000000000000000000000000000000000000000000005f5260045ffd5b6040519061028161012083611b6b565b60405190610281606083611b6b565b60405190610281604083611b6b565b67ffffffffffffffff8111611b6657601f01601f191660200190565b929192611d3182611d09565b91611d3f6040519384611b6b565b8294818452818301116101e3578281602093845f960137010152565b9080601f830112156101e357816020611ba293359101611d25565b919091610120818403126101e357611d8c611cdb565b92611d9682610276565b845260208201356020850152604082013567ffffffffffffffff81116101e35781611dc2918401611d5b565b6040850152606082013567ffffffffffffffff81116101e35781611de7918401611d5b565b60608501526080820135608085015260a082013560a085015260c082013560c085015260e082013567ffffffffffffffff81116101e35781611e2a918401611d5b565b60e085015261010082013567ffffffffffffffff81116101e357611e4e9201611d5b565b610100830152565b15611e5d57565b7fae4edb1b000000000000000000000000000000000000000000000000000000005f5260045ffd5b903590601e19813603018212156101e3570180359067ffffffffffffffff82116101e3576020019181360383136101e357565b908160209103126101e3575190565b80516001600160a01b03168252611ba29160208201516020820152610100611f48611f18611f066040860151610120604087015261012086019061101d565b6060860151858203606087015261101d565b6080850151608085015260a085015160a085015260c085015160c085015260e085015184820360e086015261101d565b9201519061010081840391015261101d565b929190611f71602091604086526040860190611ec7565b930152565b908160209103126101e3575180151581036101e35790565b60405163d60b347f60e01b81523060048201526020816024816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa9081156104ee575f91611ff4575b508015611feb5790565b50611ba26130c4565b612016915060203d60201161201c575b61200e8183611b6b565b810190611f76565b5f611fe1565b503d612004565b1561202a57565b7f8baa579f000000000000000000000000000000000000000000000000000000005f5260045ffd5b81601f820112156101e35780519061206982611d09565b926120776040519485611b6b565b828452602083830101116101e357815f9260208093018386015e8301015290565b906020828203126101e357815167ffffffffffffffff81116101e357611ba29201612052565b908060209392818452848401375f828201840152601f01601f1916010190565b611ba293926001600160a01b03606093168252602082015281604082015201905f6120be565b906020611ba292818152019061101d565b1561211c57565b7fc970156c000000000000000000000000000000000000000000000000000000005f5260045ffd5b9190916001600160a01b0381169061215d821515612115565b612169813b1515612115565b3055612194307f00000000000000000000000000000000000000000000000000000000000000001490565b610a2c576001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016331480156122bb575b6121d490611cac565b6121dc613154565b612293573d5f526352d1902d6001527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc602060016004601d855afa510361228557807fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a281817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5561226f57505050565b815f926040519485378338925af4156108925750565b6355299b496001526004601dfd5b7fdc3b8379000000000000000000000000000000000000000000000000000000005f5260045ffd5b503330146121cb565b35611ba281610265565b156122d65750565b7f41c38b30000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b1561230a575050565b6001600160a01b0392507fbe601672000000000000000000000000000000000000000000000000000000005f526004521660245260445ffd5b90620151808201809211611a5357565b91908201809211611a5357565b908092918237015f815290565b3d15612397573d9061237e82611d09565b9161238c6040519384611b6b565b82523d5f602084013e565b606090565b6123aa906060810190611e85565b806004116101e3576040515f9283929060031982019060040183378101826003198201528160031991030190305af46123e161236d565b50156123e957565b63acfdb4445f526004601cfd5b90917f341347516a9de374859dfda710fa4828b2d48cb57d4fbe4c1149612b8e02276e9361242b8484610ad884868484612a56565b600183036124675761243d9184613ba1565b612445613c9b565b604080519182526001600160a01b03909216602082015290819081015b0390a1565b6002830361247e576124799184613a2c565b612445565b600383036125625761255b916125266125559261251e6040516124a081611b4a565b5f81525f60208201526124bf61060c6124b98588611aae565b90612a20565b8151815460209093015174ff000000000000000000000000000000000000000060589190911c167fffffffffffffffffffffff0000000000000000000000000000000000000000009093166001600160a01b0390911617919091179055565b805a93611abc565b9290612547604051948592638a91b0e360e01b602085015260248401613450565b03601f198101845283611b6b565b84614602565b5050612445565b60048314801561258a575b612578575050612445565b612583918385613461565b5f8061255b565b50600260071984011061256d565b91908260081b926125b1816001600160f81b0319161590565b156125c2575090611ba29291614047565b6001600160f81b03198116600160f81b036125e3575090611ba29291613f80565b6001600160f81b0319808216036126cd5750906125ff916153b8565b9091612609613eb6565b936001600160f81b0319811661263b575091612624926153f7565b61262d82613f39565b5261263781613f39565b5090565b6001600160f81b03198116600160f81b036126b15750818361265c926153d2565b61266585613f39565b521561267057505090565b7f5bd4c60b4b38b664d8fb5944eb974e3d85083d79afe5ce934ccabcc913707c10916126ab61269e85613f39565b5160405193849384613f5a565b0390a190565b6308c3ee0360e11b5f526001600160f81b03191660045260245ffd5b6001600160f81b031990632e5bf3f960e21b5f521660045260245ffd5b91908260081b92612703816001600160f81b0319161590565b15612714575090610281929161417d565b6001600160f81b03198116600160f81b0361273557509061028192916140f4565b6001600160f81b0319808216036126cd575090612751916153b8565b929091906001600160f81b0319811661277f57505f9083604051938437838338925af4156108925701604052565b9192916001600160f81b03198116600160f81b036127e0575081836127a3926153d2565b9290156127af57505050565b6124627f5bd4c60b4b38b664d8fb5944eb974e3d85083d79afe5ce934ccabcc913707c109360405193849384613f5a565b6001600160f81b0319906308c3ee0360e11b5f521660045260245ffd5b5f356001600160e01b0319811690612846826001600160e01b0319165f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0260205260405f2090565b546128656001600160a01b0382169160581b6001600160f81b03191690565b906001600160a01b0381166128ae57505060e01c63bc197c81811463f23a6e6182141763150b7a028214176128a557506308c63e275f526020526024601cfd5b6020526020603cf35b5f516020615f835f395f51905f52546001600160a01b03168015159260609290846129ca575b6001600160f81b03198116607f60f91b0361297857505f80916128f56155f2565b90602082519201905afa9261290861236d565b935b156129705761291c575b825160208401f35b803b156101e3576129475f92918392604051948580948193630b9dfbed60e11b835260048301612104565b03925af180156104ee5761295c575b80612914565b8061099d5f61296a93611b6b565b81612956565b835160208501fd5b6001600160f81b031981166129ae57505f80916129936155f2565b906020825192019034905af1926129a861236d565b9361290a565b632e5bf3f960e21b5f526001600160f81b03191660045260245ffd5b925060405163d68f602560e01b81525f81806129eb363433600485016120de565b038183875af19081156104ee575f91612a06575b50926128d4565b612a1a91503d805f833e6109bc8183611b6b565b856129ff565b919091356001600160e01b031981169260048110612a3c575050565b6001600160e01b0319929350829060040360031b1b161690565b92909160018403612a6d575050611ba29150613e1e565b60028403612a81575050611ba29150613e5e565b60038403612ab057611ba2935060048210612aa857612aa3916124b991611aae565b614273565b50505f614273565b505090600481145f14612ade57505f516020615f835f395f51905f52546001600160a01b0391821691161490565b600260071982011015612b05576001600160a01b03612afd8192614210565b921691161490565b50505f90565b60015f9081525f516020615f635f395f51905f526020527ffe44ceacbf4f03c6ac19f86826dd265fa9ec25125e8b1766c207f24cd3bc73c7546001600160a01b031694939291905b6001600160a01b0386168015159081612bd1575b5015612b8957612b7d848484612b83948a6142bf565b95614397565b94612b53565b612bb59495507f00000000000000000000000000000000000000000000000000000000000000006142bf565b6001600160e01b03198116611ba257506001600160e01b031990565b6001915014155f612b67565b6001600160a01b038116612c1057507f000000000000000000000000000000000000000000000000000000000000000090565b612c1981613e1e565b15612c215790565b636859e01e5f526020526024601cfd5b9190916040818403126101e357805192602082015167ffffffffffffffff81116101e357611ba29201612052565b611ba294926001600160a01b03606093168252602082015281604082015201916120be565b7f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f06549293926001600160a01b031680612cc5575090611ba291933691611d25565b6040517f7a0468b7000000000000000000000000000000000000000000000000000000008152945f93869384928392612d02923360048601612c5f565b03915afa9182156104ee575f905f93612d1a57509190565b90506102ed9192503d805f833e612d318183611b6b565b810190612c31565b9060f911612e43578035906020810135810190602082019135906040810135019360208501943593612d6c368486611d25565b602081519101205f528060a01c602052612dfb6105856001600160a01b0360405f201692835f526001600160a01b0360205f2091608060205216601f526305d78094600b52601960272090604051915f52601b602052846040526060526020604060805f60015afa505f6060523d6060185190604052612df330916001600160a01b031690565b143015151690565b612e3c575b8015612e2f575f527f4f058962bce244bca6c9be42f256083afc66f1f63a1f9a04e31a3042311af38d60205fa1565b63e483bbcb5f526004601cfd5b505f612e00565b63aed595955f526004601cfd5b90601811612eda575f8160208083940135820180358060405193849301833781018481520391355af4612e8161236d565b5015612ecd57612e8f613154565b15612e9657565b612e9e611f8e565b15612ea557565b7f7556034e000000000000000000000000000000000000000000000000000000005f5260045ffd5b63315927c55f526004601cfd5b7ff9c42c60000000000000000000000000000000000000000000000000000000005f5260045ffd5b6001600160a01b03611ba29593606093835216602082015281604082015201916120be565b9290803560601c601482013590603483013560e01c916038840193838101603881013560e01c976038838a603c850194010301998160048c01116101e357612fa387612f998a9460048f612fa89901019e6003199103019c80612f93610429611c05611bff848c611a83565b97611a91565b949093888a6143dc565b61442a565b1561300e57303b156101e357612fed5f9360405195869485947f9517e29f00000000000000000000000000000000000000000000000000000000865260048601612f02565b038183305af180156104ee576130005750565b8061099d5f61028193611b6b565b6346fdc3335f526004601cfd5b92916001600160a01b037f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f05541680155f1461305a575050610100015190565b60405f80948297949751978895869485937fe24f8f930000000000000000000000000000000000000000000000000000000085526130a46004860191606083526060830190611ec7565b936020820152015203925af19182156104ee575f905f93612d1a57509190565b60015f525f516020615f635f395f51905f526020527ffe44ceacbf4f03c6ac19f86826dd265fa9ec25125e8b1766c207f24cd3bc73c7546001600160a01b031615158061310e5790565b5060015f525f516020615fa35f395f51905f526020527fbdfeb076d903611fa58576955630d640569633049bcf40ad9c22db9251b54a13546001600160a01b0316151590565b5f906017303b1461316157565b905060035f80303c5f5160e81c62ef01001490565b7f90b772c2cb8a51aa7a8a65fc23543c6d022d5b3f8e2b92eed79fba7eef8293005c15612e4357565b91909160405192805180604014613204576041146131c957505050505b638baa579f5f526004601cfd5b60209160608201515f1a835260408201516060525b5f5201516040526020600160805f825afa51915f6060526040523d6102815750506131bc565b506020917f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040830151601b8160ff1c018552166060526131de565b1561324757565b7f756688fe000000000000000000000000000000000000000000000000000000005f5260045ffd5b1561327657565b7fbf6b5843000000000000000000000000000000000000000000000000000000005f5260045ffd5b6020916001600160a01b03916133e061340195806132c5610429611c05611bff8489611a83565b946133db6107e361336e6132d8886122c4565b8b8901359861336660606132f26105216040850185611e85565b8f81519101209201359a6133588c60405194602093869485019788909493926080926001600160a01b0360a08401977fd3ddfc12654178cc44d4a7b6b969cfdce7ffe6342326ba37825314cffa0fba9c8552166020840152604083015260608201520152565b03601f198101835282611b6b565b5190206144af565b966133ae6133a961058561078e845f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0760205260405f2090565b613240565b5f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0760205260405f2090565b611a91565b93909160405196879586948593637aa8f17760e11b85523060048601612c5f565b0392165afa80156104ee576001600160e01b0319630b135d3f60e11b91610281935f91613431575b50161461326f565b61344a915060203d602011611c8757611c788183611b6b565b5f613429565b916020611ba29381815201916120be565b6134c4939291600481036134c857505f516020615f835f395f51905f5280546001600160a01b03191690555b6134bf5a926134b1604051958692638a91b0e360e01b602085015260248401613450565b03601f198101855284611b6b565b614602565b5050565b60026007198201106134db575b5061348d565b6008810361351a57507f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0680546001600160a01b03191690555b5f6134d5565b600903613514577f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0580546001600160a01b0319169055613514565b634e487b7160e01b5f52603260045260245ffd5b919081101561358b5760051b81013590605e19813603018212156101e3570190565b613555565b903590601e19813603018212156101e3570180359067ffffffffffffffff82116101e357602001918160051b360383136101e357565b604051906135d5602083611b6b565b5f808352366020840137565b91905f5b8181106135f25750509050565b6135fd818386613569565b61360a6020820182613590565b908235613616816105d6565b61361e6146a8565b506040516001600160e01b031990911660208201525f9283916136448160248101613358565b925f91825b8184106136f057505050509160019493916136d893613678613669611ceb565b6001600160a01b039094168452565b602083015260408201526136966107a482516001600160a01b031690565b156136de576136c4816136b36136d093516001600160a01b031690565b906040602082015191015191615995565b915b6040810190613590565b309291614795565b016135e5565b506136d06136ea6135c6565b916136c6565b6137066137018584869a979a6146d8565b61574c565b9361371a6137158985876146d8565b61471d565b6137238161470e565b61385257506002613740602061373a8a86886146d8565b0161471d565b6137498161470e565b146137e6576001811661377a576137716107a46001809317956020808251830101910161475e565b965b0192613649565b604051634d038a6760e11b815260206004820152602660248201527f54415247455420706172616d20747970652063616e206f6e6c7920626520736560448201527f74206f6e636500000000000000000000000000000000000000000000000000006064820152608490fd5b604051635107885760e11b815260206004820152603b60248201527f42414c414e434520666574636865722074797065206973206e6f74207375707060448201527f6f7274656420666f722054415247455420706172616d207479706500000000006064820152608490fd5b969460016138646137158886886146d8565b61386d8161470e565b0361390657506002811661389a576138946002600192179460208082518301019101611eb8565b94613773565b604051634d038a6760e11b815260206004820152602560248201527f56414c554520706172616d20747970652063616e206f6e6c792062652073657460448201527f206f6e63650000000000000000000000000000000000000000000000000000006064820152608490fd5b9495600261391b6137158986889996996146d8565b6139248161470e565b0361393b576001916139359161473c565b95613773565b604051635107885760e11b815260206004820152601260248201527f496e76616c696420706172616d207479706500000000000000000000000000006044820152606490fd5b60405161398f604082611b6b565b600581527f4e657875730000000000000000000000000000000000000000000000000000006020820152906040516139c8604082611b6b565b600581527f312e332e31000000000000000000000000000000000000000000000000000000602082015290565b9190916040818403126101e3578035613a0d81610265565b92602082013567ffffffffffffffff81116101e357611ba29201611d5b565b90613a42906001600160a01b03938101906139f5565b92166001600160a01b03821680158015613b97575b613b84576001600160a01b03613a8b835f516020615fa35f395f51905f52906001600160a01b03165f5260205260405f2090565b541603613b68579181613b0c6134c494613af1613acc610db56134b1975f516020615fa35f395f51905f52906001600160a01b03165f5260205260405f2090565b915f516020615fa35f395f51905f52906001600160a01b03165f5260205260405f2090565b906001600160a01b03166001600160a01b0319825416179055565b613b47613b37825f516020615fa35f395f51905f52906001600160a01b03165f5260205260405f2090565b6001600160a01b03198154169055565b6134bf5a92604051948591638a91b0e360e01b602084015260248301612104565b637c84ecfb60e01b5f526001600160a01b03821660045260245ffd5b50637c84ecfb60e01b5f5260045260245ffd5b5060018114613a57565b90613bb7906001600160a01b03938101906139f5565b92166001600160a01b03821680158015613c91575b613b84576001600160a01b03613c00835f516020615f635f395f51905f52906001600160a01b03165f5260205260405f2090565b541603613b68579181613c666134c494613af1613c41610db56134b1975f516020615f635f395f51905f52906001600160a01b03165f5260205260405f2090565b915f516020615f635f395f51905f52906001600160a01b03165f5260205260405f2090565b613b47613b37825f516020615f635f395f51905f52906001600160a01b03165f5260205260405f2090565b5060018114613bcc565b613ca6610585613154565b80613da4575b613cb257565b60015f525f516020615f635f395f51905f52602052613cf07ffe44ceacbf4f03c6ac19f86826dd265fa9ec25125e8b1766c207f24cd3bc73c7610db5565b6001600160a01b03811680151580613d99575b15613d885760405163d60b347f60e01b815230600482015290602090829060249082905afa9081156104ee575f91613d6a575b50613d4957613d4490614397565b613cf0565b6001600160a01b036001915b1614613d5d57565b63cc319d845f526004601cfd5b613d82915060203d811161201c5761200e8183611b6b565b5f613d36565b506001600160a01b03600191613d55565b506001811415613d03565b5060405163d60b347f60e01b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104ee575f91613dff575b5015613cac565b613e18915060203d60201161201c5761200e8183611b6b565b5f613df8565b6001600160a01b031680600114159081613e36575090565b90505f525f516020615f635f395f51905f526020526001600160a01b0360405f205416151590565b6001600160a01b031680600114159081613e76575090565b90505f525f516020615fa35f395f51905f526020526001600160a01b0360405f205416151590565b67ffffffffffffffff8111611b665760051b60200190565b60408051909190613ec78382611b6b565b6001815291601f1901825f5b828110613edf57505050565b806060602080938501015201613ed3565b90613efa82613e9e565b613f076040519182611b6b565b8281528092613f18601f1991613e9e565b01905f5b828110613f2857505050565b806060602080938501015201613f1c565b80511561358b5760200190565b805182101561358b5760209160051b010190565b91611ba29391613f72916040855260408501916120be565b91602081840391015261101d565b90613f8a9161542a565b916001600160f81b031981166140075750613fa482613ef0565b915f5b818110613fb45750505090565b80613feb613fc56001938587613569565b8035613fd081610265565b613fe36020830135926040810190611e85565b9290916155a9565b613ff58287613f46565b526140008186613f46565b5001613fa7565b9291906001600160f81b03198416600160f81b0361402a57611ba29293506154aa565b6001600160f81b0319846308c3ee0360e11b5f521660045260245ffd5b906140549193929361555a565b91909261405f613eb6565b956001600160f81b0319811661409157509061407b93916155a9565b61408483613f39565b5261408e82613f39565b50565b6001600160f81b03198116600160f81b036127e05750836140b3928492615582565b6140bc86613f39565b52156140c6575050565b7fb5282692b8c578af7fb880895d599035496b5e64d1f14bf428a1ed3bc406f6629161246261269e86613f39565b906140fe9161542a565b90916001600160f81b0319811661415b57505f5b81811061411e57505050565b8061415561412f6001938587613569565b803561413a81610265565b61414d6020830135926040810190611e85565b9290916155d6565b01614112565b92916001600160f81b03198416600160f81b0361402a5761408e9293506154aa565b6001600160f81b0319916141909161555a565b9094909391929116806141a957509061028193916155d6565b600160f81b81036141fe5750836141c1928492615582565b9290156141cd57505050565b6124627fb5282692b8c578af7fb880895d599035496b5e64d1f14bf428a1ed3bc406f6629360405193849384613f5a565b6308c3ee0360e11b5f5260045260245ffd5b600803614245576001600160a01b037f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f06541690565b6001600160a01b037f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f05541690565b6001600160a01b036142b781926001600160e01b0319165f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0260205260405f2090565b541691161490565b6142ef936001600160a01b0360209496939660405196879586948593637aa8f17760e11b85523360048601612c5f565b0392165afa9081156104ee575f91614378575b507f77390000000000000000000000000000000000000000000000000000000000007fffff0000000000000000000000000000000000000000000000000000000000008216148061435b575b614356575090565b905090565b506001600160e01b031982166001600160e01b031982161161434e565b614391915060203d602011611c8757611c788183611b6b565b5f614302565b6001600160a01b031680156143ca575f525f516020615f635f395f51905f526020526001600160a01b0360405f20541690565b637c84ecfb60e01b5f5260045260245ffd5b92909160a09492604051947ff6c866c1cd985ce61f030431e576c0e82887de0643dfa8a2e6efc3463e638ed08652602086015260408501526060840152818484019182372060808201522090565b92602092916001600160a01b03614443614461966144af565b60405196879586948593637aa8f17760e11b85523060048601612c5f565b0392165afa5f918161448e575b5061447857505f90565b6001600160e01b031916630b135d3f60e11b1490565b6144a891925060203d602011611c8757611c788183611b6b565b905f61446e565b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000030147f00000000000000000000000000000000000000000000000000000000000000004614161561453a575b6719010000000000005f52601a52603a526042601820905f603a52565b5060a06040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f000000000000000000000000000000000000000000000000000000000000000060208201527f000000000000000000000000000000000000000000000000000000000000000060408201524660608201523060808201522061451d565b6001600160a01b0361028191166001600160a01b03166001600160a01b03195f516020615f835f395f51905f525416175f516020615f835f395f51905f5255565b92915f919082918261461381611d09565b966146216040519889611b6b565b818852601f1961463083611d09565b013660208a013760208451940192f13d80614653575b8084525f602085013e9190565b505f614646565b9061466482613e9e565b6146716040519182611b6b565b8281528092614682601f1991613e9e565b0190602036910137565b5f198114611a535760010190565b5f19810191908211611a5357565b604051906060820182811067ffffffffffffffff821117611b665760405260606040835f81525f60208201520152565b919081101561358b5760051b81013590607e19813603018212156101e3570190565b634e487b7160e01b5f52602160045260245ffd5b6003111561471857565b6146fa565b3560038110156101e35790565b805191908290602001825e015f815290565b610281906125476147589493604051958693602085019061472a565b9061472a565b908160209103126101e35751611ba281610265565b919081101561358b5760051b81013590603e19813603018212156101e3570190565b91905f5b8181106147a7575050505050565b6147b2818386614773565b90856147bd836159cd565b6147c6816159c3565b6147f8576147f2906147de8460206001960190611e85565b506040810135908760208201359135615e8e565b01614799565b50906001614805826159cd565b61480e816159c3565b0361489f57806020614821920190611e85565b50905f806148416040850135850160405191828260208294359101612360565b039060208601355afa61485261236d565b901561487757866148729184608060019601359160608201359135615e8e565b6147f2565b7f6e47f619000000000000000000000000000000000000000000000000000000005f5260045ffd5b7fe2121978000000000000000000000000000000000000000000000000000000005f5260045ffd5b60015f525f516020615fa35f395f51905f526020527fbdfeb076d903611fa58576955630d640569633049bcf40ad9c22db9251b54a13546001600160a01b03166149ad5760015f525f516020615fa35f395f51905f5260205261493a60405f2060016001600160a01b0319825416179055565b60015f525f516020615f635f395f51905f526020526001600160a01b037ffe44ceacbf4f03c6ac19f86826dd265fa9ec25125e8b1766c207f24cd3bc73c754166149ad5760015f525f516020615f635f395f51905f5260205261028160405f2060016001600160a01b0319825416179055565b7f53c85e66000000000000000000000000000000000000000000000000000000005f5260045ffd5b919081101561358b5760051b0190565b9082101561358b576102ed9160051b810190611e85565b9150614a1e908035810191602083019235916020810135019060208201913590565b929391808403614afd575f5b818110614a3957505050505050565b80614a4760019284896149d5565b35828103614a6b5750614a65614a5e8288876149e5565b9087615260565b01614a2a565b60028103614a8e5750614a89614a828288876149e5565b9087615160565b614a65565b60038103614aac5750614a89614aa58288876149e5565b9087614e7c565b60048103614aca5750614a89614ac38288876149e5565b9087614d0f565b856002600719830110614adf575b5050614a65565b614af691614aee848a896149e5565b929091614b25565b5f85614ad8565b7fb4fa3fb3000000000000000000000000000000000000000000000000000000005f5260045ffd5b9291906001600160a01b03614b4e6001600160a01b035f516020615f835f395f51905f52541690565b1680614b5e575061028193614c3b565b916040939193519363d68f602560e01b85525f8580614b82363433600485016120de565b038183885af19485156104ee575f95614bde575b50614ba2939495614c3b565b803b156101e357614bcd5f92918392604051948580948193630b9dfbed60e11b835260048301612104565b03925af180156104ee576130005750565b614ba2949550614bf7903d805f833e6109bc8183611b6b565b9493614b96565b15614c065750565b6001600160a01b03907fc689cd97000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b60405163ecd0596160e01b8152600481018290526001600160a01b038316949290602081602481895afa9081156104ee575f91614cf0575b5015614cc85781614c99614c89614c9e94614210565b6001600160a01b03811615614bfe565b61561f565b823b156101e357614bcd925f92836040518096819582946306d61fe760e41b845260048401613450565b7fe27c1dd8000000000000000000000000000000000000000000000000000000005f5260045ffd5b614d09915060203d60201161201c5761200e8183611b6b565b5f614c73565b91906001600160a01b03614d376001600160a01b035f516020615f835f395f51905f52541690565b1680614d47575061028192614de6565b90916040519263d68f602560e01b84525f8480614d69363433600485016120de565b038183875af19384156104ee575f94614d89575b50614ba2929394614de6565b614ba2939450614da2903d805f833e6109bc8183611b6b565b9392614d7d565b15614db15750565b6001600160a01b03907f741cbe03000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b60405163ecd0596160e01b81526004808201526001600160a01b038216939190602081602481885afa9081156104ee575f91614e5d575b5015614cc857614c9e90614e58614e486001600160a01b035f516020615f835f395f51905f52541690565b6001600160a01b03811615614da9565b6145c1565b614e76915060203d60201161201c5761200e8183611b6b565b5f614e1d565b91906001600160a01b03614ea46001600160a01b035f516020615f835f395f51905f52541690565b1680614eb4575061028192614fc1565b90916040519263d68f602560e01b84525f8480614ed6363433600485016120de565b038183875af19384156104ee575f94614ef6575b50614ba2929394614fc1565b614ba2939450614f0f903d805f833e6109bc8183611b6b565b9392614eea565b906004101561358b5760040190565b15614f2c57565b7f867a1dcf000000000000000000000000000000000000000000000000000000005f5260045ffd5b15614f5b57565b7fc001660b000000000000000000000000000000000000000000000000000000005f5260045ffd5b15614f8b5750565b6001600160e01b0319907fa56a04dd000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b90916001600160a01b0382169160405163ecd0596160e01b815260208180614ff160048201906003602083019252565b0381875afa9081156104ee575f91615141575b5015614cc8576124bf8461060c6150766105218680615054615047615039836150336124b96150e59e8c611aae565b99614f16565b356001600160f81b03191690565b6001600160f81b03191690565b9a6001600160f81b03198c1615801561512a575b61507190614f25565b611ad9565b966150a56001600160e01b031984166306d61fe760e41b8114908115615119575b8115615110575b5015614f54565b6150ba836150b5610585826159da565b614f83565b6150d46150c5611cfa565b6001600160a01b039096168652565b6001600160f81b0319166020850152565b803b156101e357614bcd5f929183926040519485809481936306d61fe760e41b835260048301612104565b9050155f61509e565b638a91b0e360e01b81149150615097565b50607f60f91b6001600160f81b03198d1614615068565b61515a915060203d60201161201c5761200e8183611b6b565b5f615004565b91906001600160a01b036151886001600160a01b035f516020615f835f395f51905f52541690565b16806151985750610281926151fa565b90916040519263d68f602560e01b84525f84806151ba363433600485016120de565b038183875af19384156104ee575f946151da575b50614ba29293946151fa565b614ba29394506151f3903d805f833e6109bc8183611b6b565b93926151ce565b60405163ecd0596160e01b8152600260048201526001600160a01b038216939190602081602481885afa9081156104ee575f91615241575b5015614cc857614c9e90615a24565b61525a915060203d60201161201c5761200e8183611b6b565b5f615232565b91906001600160a01b036152886001600160a01b035f516020615f835f395f51905f52541690565b16806152985750610281926152fa565b90916040519263d68f602560e01b84525f84806152ba363433600485016120de565b038183875af19384156104ee575f946152da575b50614ba29293946152fa565b614ba29394506152f3903d805f833e6109bc8183611b6b565b93926152ce565b60405163ecd0596160e01b8152600160048201526001600160a01b038216939190602081602481885afa9081156104ee575f91615399575b5015614cc8576001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016841461537157614c9e90615b48565b7fabc3af79000000000000000000000000000000000000000000000000000000005f5260045ffd5b6153b2915060203d60201161201c5761200e8183611b6b565b5f615332565b91816014116101e357823560601c92601401916013190190565b5f9192806040519485378338925af4913d82523d5f602084013e60203d830101604052565b5f919392806040519586378438925af415615421573d82523d5f602084013e60203d830101604052565b503d5f823e3d90fd5b909181359182810193601f199101016020840193803593828560051b8301119060401c1761549d578361545b575050565b835b5f190160208160051b8301013580830160608101908135809101918680602080860135809601011191111792171760401c1761549d578061545d57505050565b63ba597e7e5f526004601cfd5b9190916154b683613ef0565b925f5b8181106154c557505050565b806154d36001928486613569565b8035906154df82610265565b6154fe602082013560408301936154f68585611e85565b929091615582565b615508858b613f46565b5215615517575b5050016154b9565b7fb5282692b8c578af7fb880895d599035496b5e64d1f14bf428a1ed3bc406f6629161554291611e85565b9061555061269e858b613f46565b0390a15f8061550f565b90806014116101e357813560601c92603482106101e357601483013592603401916033190190565b905f928491604051958692833738935af1913d82523d5f602084013e60203d830101604052565b90925f92819594604051968792833738935af115615421573d82523d5f602084013e60203d830101604052565b8380935f93604051958692833738935af1156108925701604052565b60405190602036830101604052816014360181525f602036920137604051601481016040523360601b9052565b6008810361568f57506001600160a01b0361028191166001600160a01b03166001600160a01b03197f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f065416177f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0655565b6009146156995750565b6001600160a01b0361028191166001600160a01b03166001600160a01b03197f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f055416177f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0555565b1561570757565b6064604051635107885760e11b815260206004820152601860248201527f496e76616c696420706172616d44617461206c656e67746800000000000000006044820152fd5b6060906020810161575c8161471d565b6157658161470e565b6157a95750611ba291508060406105219201906157a46157858383611e85565b61579f6157956060860186613590565b9390923691611d25565b615d32565b611e85565b60016157b48261471d565b6157bd8161470e565b03615827575090505f806157d46040840184611e85565b50604051806157ee81602085810135860180359101612360565b0391355afa906157fc61236d565b911561581a57615813816060611ba2930190613590565b9083615d32565b636533cc8d5f526004601cfd5b61583260029161471d565b61583b8161470e565b0361594f57602861585a6158526040840184611e85565b909214615700565b6014810135831c9035831c806158c75750906158b3613358936158ad611ba29431935b604051926158a58461589788602083019190602083019252565b03601f198101865285611b6b565b810190613590565b91615d32565b604051928391602083019190602083019252565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b03929092166004830152909190602090839060249082905afa80156104ee57613358936158ad6158b392611ba2955f91615930575b509361587d565b615949915060203d6020116104e7576104d98183611b6b565b5f615929565b604051635107885760e11b815260206004820152601a60248201527f496e76616c696420706172616d206665746368657220747970650000000000006044820152606490fd5b9291905f91604051943892602083519301915af115615421573d82523d5f602084013e60203d830101604052565b6002111561471857565b3560028110156101e35790565b615a1d6001600160a01b03916001600160e01b0319165f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0260205260405f2090565b5416151590565b6001600160a01b03811680158015615b3e575b6143ca575f9081525f516020615fa35f395f51905f5260205260409020546001600160a01b0316615b0a5760015f525f516020615fa35f395f51905f5260205261028190615acf615aa77fbdfeb076d903611fa58576955630d640569633049bcf40ad9c22db9251b54a13610db5565b613af1835f516020615fa35f395f51905f52906001600160a01b03165f5260205260405f2090565b60015f525f516020615fa35f395f51905f526020527fbdfeb076d903611fa58576955630d640569633049bcf40ad9c22db9251b54a13613af1565b7f40d3d1a4000000000000000000000000000000000000000000000000000000005f526001600160a01b031660045260245ffd5b5060018114615a37565b6001600160a01b03811680158015615c2e575b6143ca575f9081525f516020615f635f395f51905f5260205260409020546001600160a01b0316615b0a5760015f525f516020615f635f395f51905f5260205261028190615bf3615bcb7ffe44ceacbf4f03c6ac19f86826dd265fa9ec25125e8b1766c207f24cd3bc73c7610db5565b613af1835f516020615f635f395f51905f52906001600160a01b03165f5260205260405f2090565b60015f525f516020615f635f395f51905f526020527ffe44ceacbf4f03c6ac19f86826dd265fa9ec25125e8b1766c207f24cd3bc73c7613af1565b5060018114615b5b565b6040813603126101e35760405190615c4f82611b4a565b803560048110156101e357825260208101359067ffffffffffffffff82116101e357615c7d91369101611d5b565b602082015290565b6004111561471857565b91908260409103126101e3576020825192015190565b15615cac57565b630a31844b60e41b5f52600360045260245ffd5b15615cc757565b630a31844b60e41b5f52600260045260245ffd5b15615ce257565b630a31844b60e41b5f52600160045260245ffd5b15615cfd57565b630a31844b60e41b5f525f60045260245ffd5b602081519101519060208110615d24575090565b5f199060200360031b1b1690565b9180615d3d57505050565b5f5b818110615d4c5750505050565b615d5f615d5a828486614773565b615c38565b9060208160051b86010151918051615d7681615c85565b615d7f81615c85565b615da257600192615d966020615d9c930151615d10565b14615cf6565b01615d3f565b60018151615daf81615c85565b615db881615c85565b03615ddc57600192615dd06020615dd7930151615d10565b1115615cdb565b615d9c565b60028151615de981615c85565b615df281615c85565b03615e1157600192615e0a6020615dd7930151615d10565b1015615cc0565b60038151615e1e81615c85565b615e2781615c85565b03615e6657600192615e496020615dd793015160208082518301019101615c8f565b908210159182615e5b575b5050615ca5565b111590505f80615e54565b7f2c50c45e000000000000000000000000000000000000000000000000000000005f5260045ffd5b929193905f5b848110615ea357505050505050565b60208160051b83010151906001600160a01b038716916040516020810190615edb81613358868b869091604092825260208201520190565b519020833b156101e3576040517fa39e0787000000000000000000000000000000000000000000000000000000008152600481019190915260248101919091526001600160a01b0385166044820152915f908390606490829084905af19182156104ee57600192615f4e575b5001615e94565b8061099d5f615f5c93611b6b565b5f615f4756fe0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f000bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f030bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f01a164736f6c634300081b000a0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da0320000000000000000000000000000000055c766a7060797fbc7be40c08b296b7200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000014eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000

Deployed Bytecode

0x60806040526004361015610015575b366127fd57005b5f3560e01c80630a664dba146101d45780630b3dc354146101cf578063112d3a7d146101ca5780631626ba7e146101c557806319822f7c146101c0578063392e53cd146101bb578063481ddd23146101b65780634a58db19146101b15780634b6a1419146101ac5780634d44560d146101a75780634f1ef286146101a257806352d1902d1461019d5780635bfeadbb146101985780635faac46b146101935780637eba07b81461018e57806384b0196e146101895780638dd7712f146101845780639517e29f1461017f5780639cfd7cff1461017a578063a71763a814610175578063aaf10f4214610170578063b0d691fe1461016b578063c399ec8814610166578063d03c791414610161578063d691c9641461015c578063e9ae5c5314610157578063ea5f61d0146101525763f2dc691d0361000e57611a00565b611904565b61182e565b6116e7565b6115a7565b611551565b61150e565b6114b0565b6113c7565b611368565b6111ef565b6110fb565b611041565b610f00565b610d41565b610a39565b6109cb565b6108a3565b610808565b6106b7565b61067d565b6105e8565b6105bc565b610378565b610317565b6102f1565b610222565b6101e7565b5f9103126101e357565b5f80fd5b346101e3575f3660031901126101e35760206001600160a01b035f516020615f835f395f51905f5254166001600160a01b0360405191168152f35b346101e3575f3660031901126101e35760206040516001600160a01b037f0000000000000000000000000000000055c766a7060797fbc7be40c08b296b72168152f35b6001600160a01b038116036101e357565b359061028182610265565b565b9181601f840112156101e35782359167ffffffffffffffff83116101e357602083818601950101116101e357565b60606003198201126101e357600435916024356102cd81610265565b916044359067ffffffffffffffff82116101e3576102ed91600401610283565b9091565b346101e357602061030d610304366102b1565b92919091612a56565b6040519015158152f35b346101e35760403660031901126101e35760043560243567ffffffffffffffff81116101e357602091610351610357923690600401610283565b91611bd5565b6001600160e01b031960405191168152f35b90816101209103126101e35790565b346101e35760603660031901126101e35760043567ffffffffffffffff81116101e3576103ac61047a913690600401610369565b602061042960243561043460443580956103f06001600160a01b037f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da032163314611cac565b61042e6103fd3683611d76565b95869288810135906104138260031a60f81b1590565b156104f3575b5060401c6001600160a01b031690565b612bdd565b9361301b565b61010084929401525f6001600160a01b036040518098819682957f9700320300000000000000000000000000000000000000000000000000000000845260048401611f5a565b0393165af19081156104ee576104a9925f926104bd575b50806104ad575b506040519081529081906020820190565b0390f35b5f9081803892335af1505f610498565b8192506104e19060203d6020116104e7575b6104d98183611b6b565b810190611eb8565b91610491565b503d6104cf565b611bca565b600382901a60f81b600160f81b036105355761052161051a82610100610528940190611e85565b908a612f27565b3691611d25565b6101008501525b5f610419565b600382901a60f81b7f02000000000000000000000000000000000000000000000000000000000000001461056a575b5061052f565b6105ab61059f6105996105b69361058e610589610585611f8e565b1590565b611e56565b610100810190611e85565b90612d39565b93919290923691611d25565b610100880152612e50565b5f610564565b346101e3575f3660031901126101e357602061030d611f8e565b6001600160e01b03198116036101e357565b346101e35760203660031901126101e3576040602061064360043561060c816105d6565b6001600160e01b0319165f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0260205260405f2090565b82519061064f82611b4a565b54906001600160f81b03196001600160a01b0383169283835260581b16928391015282519182526020820152f35b5f3660031901126101e3575f388180347f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da0325af1156101e357005b60203660031901126101e35760043567ffffffffffffffff81116101e3576106e66106f8913690600401610283565b9081813033036106fa575b5050612e50565b005b91610706939193613154565b156107f75750506107f06107e38261072d85610725816107b697611a58565b979093611a66565b9490956107b06107a461079e8998809a816040519182372095610754610589610585611f8e565b61079561058961058561078e8a5f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0960205260405f2090565b5460ff1690565b30943691611d25565b8561319f565b6001600160a01b031690565b14612023565b5f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0960205260405f2090565b805460ff19166001179055565b5f806106f1565b91509150610803613176565b6107f0565b60403660031901126101e35760043561082081610265565b5f7f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da032602435336001600160a01b03831614801561089a575b61086190611cac565b604051936014526034526f205c28780000000000000000000000008252604460108338935af115610892575f603452005b3d5f823e3d90fd5b50333014610858565b60403660031901126101e3576004356108bb81610265565b60243567ffffffffffffffff81116101e3576108db903690600401610283565b906001600160a01b036109026001600160a01b035f516020615f835f395f51905f52541690565b168061091257506106f892612144565b90916040519263d68f602560e01b84525f8480610934363433600485016120de565b038183875af19384156104ee575f946109a3575b50610954929394612144565b803b156101e35761097f5f92918392604051948580948193630b9dfbed60e11b835260048301612104565b03925af180156104ee5761098f57005b8061099d5f6106f893611b6b565b806101d9565b6109549394506109c4903d805f833e6109bc8183611b6b565b810190612098565b9392610948565b346101e3575f3660031901126101e357307f00000000000000000000000000000000561dd60aea485cdb26e4618b1e40fd6e03610a2c5760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b639f03a0265f526004601cfd5b60403660031901126101e35760043567ffffffffffffffff81116101e3578060040190608060031982360301126101e35760243567ffffffffffffffff81116101e357610a8d610a94913690600401610283565b908461329e565b610ab06024820135926044610aa8826122c4565b930190611e85565b929060048214828115610cdb575b610ac7916122ce565b610add8383610ad887858484612a56565b612301565b610b17836001600160a01b03165f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0460205260405f2090565b5480610ba8575050507f2841d18703faaff388732165e48fe431468531b1b1e626b1b7cbcbfc0d79c7409150610ba39042610b82826001600160a01b03165f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0460205260405f2090565b55604080516001600160a01b03909216825242602083015290918291820190565b0390a1005b610bb56203f48082612353565b4210610c20575050507fcbd44a75f6935b5837022648b6c8487db984701200c5381c7c0f8c2b1d69b9da9150610ba39042610b82826001600160a01b03165f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0460205260405f2090565b610c2990612343565b4210610cb3577f341347516a9de374859dfda710fa4828b2d48cb57d4fbe4c1149612b8e02276e93610c98915f610c90866001600160a01b03165f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0460205260405f2090565b558385613461565b604080519182526001600160a01b03929092166020820152a1005b7f07f2f2d2000000000000000000000000000000000000000000000000000000005f5260045ffd5b60026007198201109150610abe565b90929192604082016040835281518091526020606084019201905f5b818110610d22575050506001600160a01b036020919416910152565b82516001600160a01b0316845260209384019390920191600101610d06565b346101e35760403660031901126101e357600435610d5e81610265565b6024359060016001600160a01b038216141580610eee575b610ed3578115610eab5790610d8a8161465a565b610dc2610db55f946001600160a01b03165f525f516020615f635f395f51905f5260205260405f2090565b546001600160a01b031690565b6001600160a01b0381168015159081610e9f575b5080610e96575b15610e3757610e2b610db582610e08610e3194610dfa8988613f46565b906001600160a01b03169052565b6001600160a01b03165f525f516020615f635f395f51905f5260205260405f2090565b9361468c565b92610dc2565b908360016001600160a01b038416141580610e8d575b610e63575b81526104a960405192839283610cea565b9150610e87610e7a610e748461469a565b83613f46565b516001600160a01b031690565b91610e52565b50801515610e4d565b50828410610ddd565b6001915014155f610dd6565b7ff7250817000000000000000000000000000000000000000000000000000000005f5260045ffd5b637c84ecfb60e01b5f526001600160a01b031660045260245ffd5b50610efb61058582613e1e565b610d76565b60203660031901126101e35760043567ffffffffffffffff81116101e357366023820112156101e357806004013567ffffffffffffffff81116101e3576024820191602436918360051b0101116101e357610f856001600160a01b037f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da032163314611cac565b6001600160a01b03610fab6001600160a01b035f516020615f835f395f51905f52541690565b1680610fbb57506106f8916135e1565b906040519263d68f602560e01b84525f8480610fdc363433600485016120de565b038183875af19384156104ee575f94610ffb575b5090610954916135e1565b61095492919450611015903d805f833e6109bc8183611b6b565b939091610ff0565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b346101e3575f3660031901126101e35761109c6110aa61105f613981565b6040929192519384937f0f00000000000000000000000000000000000000000000000000000000000000855260e0602086015260e085019061101d565b90838203604085015261101d565b4660608301523060808301525f60a083015281810360c083015260206060519182815201906080905f5b8181106110e2575050500390f35b82518452859450602093840193909201916001016110d4565b60403660031901126101e35760043567ffffffffffffffff81116101e357611127903690600401610369565b61115b6001600160a01b037f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da032163314611cac565b6001600160a01b036111816001600160a01b035f516020615f835f395f51905f52541690565b168061119157506106f89061239c565b6040519163d68f602560e01b83525f83806111b1363433600485016120de565b038183865af19283156104ee575f936111cf575b506109549061239c565b6109549193506111e8903d805f833e6109bc8183611b6b565b92906111c5565b6111f8366102b1565b906001600160a01b039392937f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da032163314801561135f575b61123890611cac565b6112436105856130c4565b611352575b6001600160a01b0384161561132a5760018303611296579061126a9184615260565b5f526020527fd21d0b289f126c4b473ea641963e766833c2f13866e4ff480abd787c100ef12360405fa1005b600283036112ae57906112a99184615160565b61126a565b600383036112c157906112a99184614e7c565b600483036112d457906112a99184614d0f565b6002600719840110156112ed57906112a9918484614b25565b826112fd57906112a991846149fc565b7f098312d2000000000000000000000000000000000000000000000000000000005f52600483905260245ffd5b7f5316c18d000000000000000000000000000000000000000000000000000000005f5260045ffd5b61135a6148c7565b611248565b5033301461122f565b346101e3575f3660031901126101e3576104a9604051611389604082611b6b565b601481527f6269636f6e6f6d792e6e657875732e312e332e31000000000000000000000000602082015260405191829160208352602083019061101d565b6113d0366102b1565b916001600160a01b037f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da03216331480156114a7575b61140d90611cac565b6001600160a01b036114336001600160a01b035f516020615f835f395f51905f52541690565b168061144357506106f8936123f6565b916040939193519363d68f602560e01b85525f8580611467363433600485016120de565b038183885af19485156104ee575f95611487575b506109549394956123f6565b6109549495506114a0903d805f833e6109bc8183611b6b565b949361147b565b50333014611404565b346101e3575f3660031901126101e3577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b03811615611506575b6020906001600160a01b0360405191168152f35b5030546114f2565b346101e3575f3660031901126101e35760206040516001600160a01b037f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da032168152f35b346101e3575f3660031901126101e357306020526370a082315f52602080806024601c7f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da0325afa601f3d1116815102604051908152f35b346101e35760203660031901126101e3576104a96004358060081b6001600160f81b0319821615918215611640575b821561162b575b50816115f7575b5060405190151581529081906020820190565b6001600160f81b031981161591508115611613575b505f6115e4565b6001600160f81b031916600160f81b1490505f61160c565b6001600160f81b03199081161491505f6115dd565b6001600160f81b03198116600160f81b1492506115d6565b9060406003198301126101e357600435916024359067ffffffffffffffff82116101e3576102ed91600401610283565b602081016020825282518091526040820191602060408360051b8301019401925f915b8383106116ba57505050505090565b90919293946020806116d8600193603f19868203018752895161101d565b970193019301919392906116ab565b6116f036611658565b916116fa33613e5e565b15611802576001600160a01b036117256001600160a01b035f516020615f835f395f51905f52541690565b168061174657509161173a916104a993612598565b60405191829182611688565b90926040519263d68f602560e01b84525f8480611768363433600485016120de565b038183875af19384156104ee575f946117e2575b50611788929394612598565b90803b156101e3576117b45f93918492604051958680948193630b9dfbed60e11b835260048301612104565b03925af19182156104ee576104a9926117ce575b5061173a565b8061099d5f6117dc93611b6b565b5f6117c8565b6117889394506117fb903d805f833e6109bc8183611b6b565b939261177c565b7fb927fe5e000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b61183736611658565b9061186c6001600160a01b037f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da032163314611cac565b6001600160a01b036118926001600160a01b035f516020615f835f395f51905f52541690565b16806118a257506106f8926126ea565b90916040519263d68f602560e01b84525f84806118c4363433600485016120de565b038183875af19384156104ee575f946118e4575b506109549293946126ea565b6109549394506118fd903d805f833e6109bc8183611b6b565b93926118d8565b346101e35760403660031901126101e35760043561192181610265565b6024359060016001600160a01b0382161415806119ee575b610ed3578115610eab579061194d8161465a565b611978610db55f946001600160a01b03165f525f516020615fa35f395f51905f5260205260405f2090565b6001600160a01b03811680151590816119e2575b50806119d9575b15610e3757610e2b610db5826119b06119d394610dfa8988613f46565b6001600160a01b03165f525f516020615fa35f395f51905f5260205260405f2090565b92611978565b50828410611993565b6001915014155f61198c565b506119fb61058582613e5e565b611939565b346101e35760203660031901126101e357602060043561031f6001604051921b1615158152f35b634e487b7160e01b5f52601160045260245ffd5b906177398202918083046177391490151715611a5357565b611a27565b906041116101e35790604190565b90929192836041116101e35783116101e357604101916040190190565b906014116101e35790601490565b90929192836014116101e35783116101e357601401916013190190565b906004116101e35790600490565b90929192836004116101e35783116101e357600401916003190190565b90929192836005116101e35783116101e357600501916004190190565b356bffffffffffffffffffffffff19811692919060148210611b16575050565b6bffffffffffffffffffffffff1960149290920360031b82901b16169150565b634e487b7160e01b5f52604160045260245ffd5b6040810190811067ffffffffffffffff821117611b6657604052565b611b36565b90601f8019910116810190811067ffffffffffffffff821117611b6657604052565b908160209103126101e35751611ba2816105d6565b90565b611ba293926001600160a01b036060931682526020820152816040820152019061101d565b6040513d5f823e3d90fd5b918015611c8e575b90611c17611c3e93611c118480611c0b610429611c05611bff60209a8a611a83565b90611af6565b60601c90565b95611a91565b91612c84565b91906001600160a01b03604051809681958294637aa8f17760e11b84523360048501611ba5565b0392165afa5f9181611c5d575b50611ba257506001600160e01b031990565b611c8091925060203d602011611c87575b611c788183611b6b565b810190611b8d565b905f611c4b565b503d611c6e565b611c9c61ffff821904611a3b565b8303611bdd5790611ba292612b0b565b15611cb357565b7fac52ccbe000000000000000000000000000000000000000000000000000000005f5260045ffd5b6040519061028161012083611b6b565b60405190610281606083611b6b565b60405190610281604083611b6b565b67ffffffffffffffff8111611b6657601f01601f191660200190565b929192611d3182611d09565b91611d3f6040519384611b6b565b8294818452818301116101e3578281602093845f960137010152565b9080601f830112156101e357816020611ba293359101611d25565b919091610120818403126101e357611d8c611cdb565b92611d9682610276565b845260208201356020850152604082013567ffffffffffffffff81116101e35781611dc2918401611d5b565b6040850152606082013567ffffffffffffffff81116101e35781611de7918401611d5b565b60608501526080820135608085015260a082013560a085015260c082013560c085015260e082013567ffffffffffffffff81116101e35781611e2a918401611d5b565b60e085015261010082013567ffffffffffffffff81116101e357611e4e9201611d5b565b610100830152565b15611e5d57565b7fae4edb1b000000000000000000000000000000000000000000000000000000005f5260045ffd5b903590601e19813603018212156101e3570180359067ffffffffffffffff82116101e3576020019181360383136101e357565b908160209103126101e3575190565b80516001600160a01b03168252611ba29160208201516020820152610100611f48611f18611f066040860151610120604087015261012086019061101d565b6060860151858203606087015261101d565b6080850151608085015260a085015160a085015260c085015160c085015260e085015184820360e086015261101d565b9201519061010081840391015261101d565b929190611f71602091604086526040860190611ec7565b930152565b908160209103126101e3575180151581036101e35790565b60405163d60b347f60e01b81523060048201526020816024816001600160a01b037f0000000000000000000000000000000055c766a7060797fbc7be40c08b296b72165afa9081156104ee575f91611ff4575b508015611feb5790565b50611ba26130c4565b612016915060203d60201161201c575b61200e8183611b6b565b810190611f76565b5f611fe1565b503d612004565b1561202a57565b7f8baa579f000000000000000000000000000000000000000000000000000000005f5260045ffd5b81601f820112156101e35780519061206982611d09565b926120776040519485611b6b565b828452602083830101116101e357815f9260208093018386015e8301015290565b906020828203126101e357815167ffffffffffffffff81116101e357611ba29201612052565b908060209392818452848401375f828201840152601f01601f1916010190565b611ba293926001600160a01b03606093168252602082015281604082015201905f6120be565b906020611ba292818152019061101d565b1561211c57565b7fc970156c000000000000000000000000000000000000000000000000000000005f5260045ffd5b9190916001600160a01b0381169061215d821515612115565b612169813b1515612115565b3055612194307f00000000000000000000000000000000561dd60aea485cdb26e4618b1e40fd6e1490565b610a2c576001600160a01b037f0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da03216331480156122bb575b6121d490611cac565b6121dc613154565b612293573d5f526352d1902d6001527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc602060016004601d855afa510361228557807fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a281817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5561226f57505050565b815f926040519485378338925af4156108925750565b6355299b496001526004601dfd5b7fdc3b8379000000000000000000000000000000000000000000000000000000005f5260045ffd5b503330146121cb565b35611ba281610265565b156122d65750565b7f41c38b30000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b1561230a575050565b6001600160a01b0392507fbe601672000000000000000000000000000000000000000000000000000000005f526004521660245260445ffd5b90620151808201809211611a5357565b91908201809211611a5357565b908092918237015f815290565b3d15612397573d9061237e82611d09565b9161238c6040519384611b6b565b82523d5f602084013e565b606090565b6123aa906060810190611e85565b806004116101e3576040515f9283929060031982019060040183378101826003198201528160031991030190305af46123e161236d565b50156123e957565b63acfdb4445f526004601cfd5b90917f341347516a9de374859dfda710fa4828b2d48cb57d4fbe4c1149612b8e02276e9361242b8484610ad884868484612a56565b600183036124675761243d9184613ba1565b612445613c9b565b604080519182526001600160a01b03909216602082015290819081015b0390a1565b6002830361247e576124799184613a2c565b612445565b600383036125625761255b916125266125559261251e6040516124a081611b4a565b5f81525f60208201526124bf61060c6124b98588611aae565b90612a20565b8151815460209093015174ff000000000000000000000000000000000000000060589190911c167fffffffffffffffffffffff0000000000000000000000000000000000000000009093166001600160a01b0390911617919091179055565b805a93611abc565b9290612547604051948592638a91b0e360e01b602085015260248401613450565b03601f198101845283611b6b565b84614602565b5050612445565b60048314801561258a575b612578575050612445565b612583918385613461565b5f8061255b565b50600260071984011061256d565b91908260081b926125b1816001600160f81b0319161590565b156125c2575090611ba29291614047565b6001600160f81b03198116600160f81b036125e3575090611ba29291613f80565b6001600160f81b0319808216036126cd5750906125ff916153b8565b9091612609613eb6565b936001600160f81b0319811661263b575091612624926153f7565b61262d82613f39565b5261263781613f39565b5090565b6001600160f81b03198116600160f81b036126b15750818361265c926153d2565b61266585613f39565b521561267057505090565b7f5bd4c60b4b38b664d8fb5944eb974e3d85083d79afe5ce934ccabcc913707c10916126ab61269e85613f39565b5160405193849384613f5a565b0390a190565b6308c3ee0360e11b5f526001600160f81b03191660045260245ffd5b6001600160f81b031990632e5bf3f960e21b5f521660045260245ffd5b91908260081b92612703816001600160f81b0319161590565b15612714575090610281929161417d565b6001600160f81b03198116600160f81b0361273557509061028192916140f4565b6001600160f81b0319808216036126cd575090612751916153b8565b929091906001600160f81b0319811661277f57505f9083604051938437838338925af4156108925701604052565b9192916001600160f81b03198116600160f81b036127e0575081836127a3926153d2565b9290156127af57505050565b6124627f5bd4c60b4b38b664d8fb5944eb974e3d85083d79afe5ce934ccabcc913707c109360405193849384613f5a565b6001600160f81b0319906308c3ee0360e11b5f521660045260245ffd5b5f356001600160e01b0319811690612846826001600160e01b0319165f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0260205260405f2090565b546128656001600160a01b0382169160581b6001600160f81b03191690565b906001600160a01b0381166128ae57505060e01c63bc197c81811463f23a6e6182141763150b7a028214176128a557506308c63e275f526020526024601cfd5b6020526020603cf35b5f516020615f835f395f51905f52546001600160a01b03168015159260609290846129ca575b6001600160f81b03198116607f60f91b0361297857505f80916128f56155f2565b90602082519201905afa9261290861236d565b935b156129705761291c575b825160208401f35b803b156101e3576129475f92918392604051948580948193630b9dfbed60e11b835260048301612104565b03925af180156104ee5761295c575b80612914565b8061099d5f61296a93611b6b565b81612956565b835160208501fd5b6001600160f81b031981166129ae57505f80916129936155f2565b906020825192019034905af1926129a861236d565b9361290a565b632e5bf3f960e21b5f526001600160f81b03191660045260245ffd5b925060405163d68f602560e01b81525f81806129eb363433600485016120de565b038183875af19081156104ee575f91612a06575b50926128d4565b612a1a91503d805f833e6109bc8183611b6b565b856129ff565b919091356001600160e01b031981169260048110612a3c575050565b6001600160e01b0319929350829060040360031b1b161690565b92909160018403612a6d575050611ba29150613e1e565b60028403612a81575050611ba29150613e5e565b60038403612ab057611ba2935060048210612aa857612aa3916124b991611aae565b614273565b50505f614273565b505090600481145f14612ade57505f516020615f835f395f51905f52546001600160a01b0391821691161490565b600260071982011015612b05576001600160a01b03612afd8192614210565b921691161490565b50505f90565b60015f9081525f516020615f635f395f51905f526020527ffe44ceacbf4f03c6ac19f86826dd265fa9ec25125e8b1766c207f24cd3bc73c7546001600160a01b031694939291905b6001600160a01b0386168015159081612bd1575b5015612b8957612b7d848484612b83948a6142bf565b95614397565b94612b53565b612bb59495507f0000000000000000000000000000000055c766a7060797fbc7be40c08b296b726142bf565b6001600160e01b03198116611ba257506001600160e01b031990565b6001915014155f612b67565b6001600160a01b038116612c1057507f0000000000000000000000000000000055c766a7060797fbc7be40c08b296b7290565b612c1981613e1e565b15612c215790565b636859e01e5f526020526024601cfd5b9190916040818403126101e357805192602082015167ffffffffffffffff81116101e357611ba29201612052565b611ba294926001600160a01b03606093168252602082015281604082015201916120be565b7f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f06549293926001600160a01b031680612cc5575090611ba291933691611d25565b6040517f7a0468b7000000000000000000000000000000000000000000000000000000008152945f93869384928392612d02923360048601612c5f565b03915afa9182156104ee575f905f93612d1a57509190565b90506102ed9192503d805f833e612d318183611b6b565b810190612c31565b9060f911612e43578035906020810135810190602082019135906040810135019360208501943593612d6c368486611d25565b602081519101205f528060a01c602052612dfb6105856001600160a01b0360405f201692835f526001600160a01b0360205f2091608060205216601f526305d78094600b52601960272090604051915f52601b602052846040526060526020604060805f60015afa505f6060523d6060185190604052612df330916001600160a01b031690565b143015151690565b612e3c575b8015612e2f575f527f4f058962bce244bca6c9be42f256083afc66f1f63a1f9a04e31a3042311af38d60205fa1565b63e483bbcb5f526004601cfd5b505f612e00565b63aed595955f526004601cfd5b90601811612eda575f8160208083940135820180358060405193849301833781018481520391355af4612e8161236d565b5015612ecd57612e8f613154565b15612e9657565b612e9e611f8e565b15612ea557565b7f7556034e000000000000000000000000000000000000000000000000000000005f5260045ffd5b63315927c55f526004601cfd5b7ff9c42c60000000000000000000000000000000000000000000000000000000005f5260045ffd5b6001600160a01b03611ba29593606093835216602082015281604082015201916120be565b9290803560601c601482013590603483013560e01c916038840193838101603881013560e01c976038838a603c850194010301998160048c01116101e357612fa387612f998a9460048f612fa89901019e6003199103019c80612f93610429611c05611bff848c611a83565b97611a91565b949093888a6143dc565b61442a565b1561300e57303b156101e357612fed5f9360405195869485947f9517e29f00000000000000000000000000000000000000000000000000000000865260048601612f02565b038183305af180156104ee576130005750565b8061099d5f61028193611b6b565b6346fdc3335f526004601cfd5b92916001600160a01b037f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f05541680155f1461305a575050610100015190565b60405f80948297949751978895869485937fe24f8f930000000000000000000000000000000000000000000000000000000085526130a46004860191606083526060830190611ec7565b936020820152015203925af19182156104ee575f905f93612d1a57509190565b60015f525f516020615f635f395f51905f526020527ffe44ceacbf4f03c6ac19f86826dd265fa9ec25125e8b1766c207f24cd3bc73c7546001600160a01b031615158061310e5790565b5060015f525f516020615fa35f395f51905f526020527fbdfeb076d903611fa58576955630d640569633049bcf40ad9c22db9251b54a13546001600160a01b0316151590565b5f906017303b1461316157565b905060035f80303c5f5160e81c62ef01001490565b7f90b772c2cb8a51aa7a8a65fc23543c6d022d5b3f8e2b92eed79fba7eef8293005c15612e4357565b91909160405192805180604014613204576041146131c957505050505b638baa579f5f526004601cfd5b60209160608201515f1a835260408201516060525b5f5201516040526020600160805f825afa51915f6060526040523d6102815750506131bc565b506020917f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040830151601b8160ff1c018552166060526131de565b1561324757565b7f756688fe000000000000000000000000000000000000000000000000000000005f5260045ffd5b1561327657565b7fbf6b5843000000000000000000000000000000000000000000000000000000005f5260045ffd5b6020916001600160a01b03916133e061340195806132c5610429611c05611bff8489611a83565b946133db6107e361336e6132d8886122c4565b8b8901359861336660606132f26105216040850185611e85565b8f81519101209201359a6133588c60405194602093869485019788909493926080926001600160a01b0360a08401977fd3ddfc12654178cc44d4a7b6b969cfdce7ffe6342326ba37825314cffa0fba9c8552166020840152604083015260608201520152565b03601f198101835282611b6b565b5190206144af565b966133ae6133a961058561078e845f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0760205260405f2090565b613240565b5f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0760205260405f2090565b611a91565b93909160405196879586948593637aa8f17760e11b85523060048601612c5f565b0392165afa80156104ee576001600160e01b0319630b135d3f60e11b91610281935f91613431575b50161461326f565b61344a915060203d602011611c8757611c788183611b6b565b5f613429565b916020611ba29381815201916120be565b6134c4939291600481036134c857505f516020615f835f395f51905f5280546001600160a01b03191690555b6134bf5a926134b1604051958692638a91b0e360e01b602085015260248401613450565b03601f198101855284611b6b565b614602565b5050565b60026007198201106134db575b5061348d565b6008810361351a57507f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0680546001600160a01b03191690555b5f6134d5565b600903613514577f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0580546001600160a01b0319169055613514565b634e487b7160e01b5f52603260045260245ffd5b919081101561358b5760051b81013590605e19813603018212156101e3570190565b613555565b903590601e19813603018212156101e3570180359067ffffffffffffffff82116101e357602001918160051b360383136101e357565b604051906135d5602083611b6b565b5f808352366020840137565b91905f5b8181106135f25750509050565b6135fd818386613569565b61360a6020820182613590565b908235613616816105d6565b61361e6146a8565b506040516001600160e01b031990911660208201525f9283916136448160248101613358565b925f91825b8184106136f057505050509160019493916136d893613678613669611ceb565b6001600160a01b039094168452565b602083015260408201526136966107a482516001600160a01b031690565b156136de576136c4816136b36136d093516001600160a01b031690565b906040602082015191015191615995565b915b6040810190613590565b309291614795565b016135e5565b506136d06136ea6135c6565b916136c6565b6137066137018584869a979a6146d8565b61574c565b9361371a6137158985876146d8565b61471d565b6137238161470e565b61385257506002613740602061373a8a86886146d8565b0161471d565b6137498161470e565b146137e6576001811661377a576137716107a46001809317956020808251830101910161475e565b965b0192613649565b604051634d038a6760e11b815260206004820152602660248201527f54415247455420706172616d20747970652063616e206f6e6c7920626520736560448201527f74206f6e636500000000000000000000000000000000000000000000000000006064820152608490fd5b604051635107885760e11b815260206004820152603b60248201527f42414c414e434520666574636865722074797065206973206e6f74207375707060448201527f6f7274656420666f722054415247455420706172616d207479706500000000006064820152608490fd5b969460016138646137158886886146d8565b61386d8161470e565b0361390657506002811661389a576138946002600192179460208082518301019101611eb8565b94613773565b604051634d038a6760e11b815260206004820152602560248201527f56414c554520706172616d20747970652063616e206f6e6c792062652073657460448201527f206f6e63650000000000000000000000000000000000000000000000000000006064820152608490fd5b9495600261391b6137158986889996996146d8565b6139248161470e565b0361393b576001916139359161473c565b95613773565b604051635107885760e11b815260206004820152601260248201527f496e76616c696420706172616d207479706500000000000000000000000000006044820152606490fd5b60405161398f604082611b6b565b600581527f4e657875730000000000000000000000000000000000000000000000000000006020820152906040516139c8604082611b6b565b600581527f312e332e31000000000000000000000000000000000000000000000000000000602082015290565b9190916040818403126101e3578035613a0d81610265565b92602082013567ffffffffffffffff81116101e357611ba29201611d5b565b90613a42906001600160a01b03938101906139f5565b92166001600160a01b03821680158015613b97575b613b84576001600160a01b03613a8b835f516020615fa35f395f51905f52906001600160a01b03165f5260205260405f2090565b541603613b68579181613b0c6134c494613af1613acc610db56134b1975f516020615fa35f395f51905f52906001600160a01b03165f5260205260405f2090565b915f516020615fa35f395f51905f52906001600160a01b03165f5260205260405f2090565b906001600160a01b03166001600160a01b0319825416179055565b613b47613b37825f516020615fa35f395f51905f52906001600160a01b03165f5260205260405f2090565b6001600160a01b03198154169055565b6134bf5a92604051948591638a91b0e360e01b602084015260248301612104565b637c84ecfb60e01b5f526001600160a01b03821660045260245ffd5b50637c84ecfb60e01b5f5260045260245ffd5b5060018114613a57565b90613bb7906001600160a01b03938101906139f5565b92166001600160a01b03821680158015613c91575b613b84576001600160a01b03613c00835f516020615f635f395f51905f52906001600160a01b03165f5260205260405f2090565b541603613b68579181613c666134c494613af1613c41610db56134b1975f516020615f635f395f51905f52906001600160a01b03165f5260205260405f2090565b915f516020615f635f395f51905f52906001600160a01b03165f5260205260405f2090565b613b47613b37825f516020615f635f395f51905f52906001600160a01b03165f5260205260405f2090565b5060018114613bcc565b613ca6610585613154565b80613da4575b613cb257565b60015f525f516020615f635f395f51905f52602052613cf07ffe44ceacbf4f03c6ac19f86826dd265fa9ec25125e8b1766c207f24cd3bc73c7610db5565b6001600160a01b03811680151580613d99575b15613d885760405163d60b347f60e01b815230600482015290602090829060249082905afa9081156104ee575f91613d6a575b50613d4957613d4490614397565b613cf0565b6001600160a01b036001915b1614613d5d57565b63cc319d845f526004601cfd5b613d82915060203d811161201c5761200e8183611b6b565b5f613d36565b506001600160a01b03600191613d55565b506001811415613d03565b5060405163d60b347f60e01b81523060048201526020816024817f0000000000000000000000000000000055c766a7060797fbc7be40c08b296b726001600160a01b03165afa9081156104ee575f91613dff575b5015613cac565b613e18915060203d60201161201c5761200e8183611b6b565b5f613df8565b6001600160a01b031680600114159081613e36575090565b90505f525f516020615f635f395f51905f526020526001600160a01b0360405f205416151590565b6001600160a01b031680600114159081613e76575090565b90505f525f516020615fa35f395f51905f526020526001600160a01b0360405f205416151590565b67ffffffffffffffff8111611b665760051b60200190565b60408051909190613ec78382611b6b565b6001815291601f1901825f5b828110613edf57505050565b806060602080938501015201613ed3565b90613efa82613e9e565b613f076040519182611b6b565b8281528092613f18601f1991613e9e565b01905f5b828110613f2857505050565b806060602080938501015201613f1c565b80511561358b5760200190565b805182101561358b5760209160051b010190565b91611ba29391613f72916040855260408501916120be565b91602081840391015261101d565b90613f8a9161542a565b916001600160f81b031981166140075750613fa482613ef0565b915f5b818110613fb45750505090565b80613feb613fc56001938587613569565b8035613fd081610265565b613fe36020830135926040810190611e85565b9290916155a9565b613ff58287613f46565b526140008186613f46565b5001613fa7565b9291906001600160f81b03198416600160f81b0361402a57611ba29293506154aa565b6001600160f81b0319846308c3ee0360e11b5f521660045260245ffd5b906140549193929361555a565b91909261405f613eb6565b956001600160f81b0319811661409157509061407b93916155a9565b61408483613f39565b5261408e82613f39565b50565b6001600160f81b03198116600160f81b036127e05750836140b3928492615582565b6140bc86613f39565b52156140c6575050565b7fb5282692b8c578af7fb880895d599035496b5e64d1f14bf428a1ed3bc406f6629161246261269e86613f39565b906140fe9161542a565b90916001600160f81b0319811661415b57505f5b81811061411e57505050565b8061415561412f6001938587613569565b803561413a81610265565b61414d6020830135926040810190611e85565b9290916155d6565b01614112565b92916001600160f81b03198416600160f81b0361402a5761408e9293506154aa565b6001600160f81b0319916141909161555a565b9094909391929116806141a957509061028193916155d6565b600160f81b81036141fe5750836141c1928492615582565b9290156141cd57505050565b6124627fb5282692b8c578af7fb880895d599035496b5e64d1f14bf428a1ed3bc406f6629360405193849384613f5a565b6308c3ee0360e11b5f5260045260245ffd5b600803614245576001600160a01b037f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f06541690565b6001600160a01b037f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f05541690565b6001600160a01b036142b781926001600160e01b0319165f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0260205260405f2090565b541691161490565b6142ef936001600160a01b0360209496939660405196879586948593637aa8f17760e11b85523360048601612c5f565b0392165afa9081156104ee575f91614378575b507f77390000000000000000000000000000000000000000000000000000000000007fffff0000000000000000000000000000000000000000000000000000000000008216148061435b575b614356575090565b905090565b506001600160e01b031982166001600160e01b031982161161434e565b614391915060203d602011611c8757611c788183611b6b565b5f614302565b6001600160a01b031680156143ca575f525f516020615f635f395f51905f526020526001600160a01b0360405f20541690565b637c84ecfb60e01b5f5260045260245ffd5b92909160a09492604051947ff6c866c1cd985ce61f030431e576c0e82887de0643dfa8a2e6efc3463e638ed08652602086015260408501526060840152818484019182372060808201522090565b92602092916001600160a01b03614443614461966144af565b60405196879586948593637aa8f17760e11b85523060048601612c5f565b0392165afa5f918161448e575b5061447857505f90565b6001600160e01b031916630b135d3f60e11b1490565b6144a891925060203d602011611c8757611c788183611b6b565b905f61446e565b7fd9a30f025a2615d2b3b61eed8380b0fd3193295a7bff5c2e5e0519b092f0ee7e7f00000000000000000000000000000000561dd60aea485cdb26e4618b1e40fd6e30147f00000000000000000000000000000000000000000000000000000000000b67d24614161561453a575b6719010000000000005f52601a52603a526042601820905f603a52565b5060a06040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527ff3fbaf4e62ef217b8151b366cdaba8fa578e78940637d6c1ec320d10a718877260208201527fd6f9477f1bbaaf55b72b2869a6c4697af6529f6af9f67d87058f1bf5bec0188760408201524660608201523060808201522061451d565b6001600160a01b0361028191166001600160a01b03166001600160a01b03195f516020615f835f395f51905f525416175f516020615f835f395f51905f5255565b92915f919082918261461381611d09565b966146216040519889611b6b565b818852601f1961463083611d09565b013660208a013760208451940192f13d80614653575b8084525f602085013e9190565b505f614646565b9061466482613e9e565b6146716040519182611b6b565b8281528092614682601f1991613e9e565b0190602036910137565b5f198114611a535760010190565b5f19810191908211611a5357565b604051906060820182811067ffffffffffffffff821117611b665760405260606040835f81525f60208201520152565b919081101561358b5760051b81013590607e19813603018212156101e3570190565b634e487b7160e01b5f52602160045260245ffd5b6003111561471857565b6146fa565b3560038110156101e35790565b805191908290602001825e015f815290565b610281906125476147589493604051958693602085019061472a565b9061472a565b908160209103126101e35751611ba281610265565b919081101561358b5760051b81013590603e19813603018212156101e3570190565b91905f5b8181106147a7575050505050565b6147b2818386614773565b90856147bd836159cd565b6147c6816159c3565b6147f8576147f2906147de8460206001960190611e85565b506040810135908760208201359135615e8e565b01614799565b50906001614805826159cd565b61480e816159c3565b0361489f57806020614821920190611e85565b50905f806148416040850135850160405191828260208294359101612360565b039060208601355afa61485261236d565b901561487757866148729184608060019601359160608201359135615e8e565b6147f2565b7f6e47f619000000000000000000000000000000000000000000000000000000005f5260045ffd5b7fe2121978000000000000000000000000000000000000000000000000000000005f5260045ffd5b60015f525f516020615fa35f395f51905f526020527fbdfeb076d903611fa58576955630d640569633049bcf40ad9c22db9251b54a13546001600160a01b03166149ad5760015f525f516020615fa35f395f51905f5260205261493a60405f2060016001600160a01b0319825416179055565b60015f525f516020615f635f395f51905f526020526001600160a01b037ffe44ceacbf4f03c6ac19f86826dd265fa9ec25125e8b1766c207f24cd3bc73c754166149ad5760015f525f516020615f635f395f51905f5260205261028160405f2060016001600160a01b0319825416179055565b7f53c85e66000000000000000000000000000000000000000000000000000000005f5260045ffd5b919081101561358b5760051b0190565b9082101561358b576102ed9160051b810190611e85565b9150614a1e908035810191602083019235916020810135019060208201913590565b929391808403614afd575f5b818110614a3957505050505050565b80614a4760019284896149d5565b35828103614a6b5750614a65614a5e8288876149e5565b9087615260565b01614a2a565b60028103614a8e5750614a89614a828288876149e5565b9087615160565b614a65565b60038103614aac5750614a89614aa58288876149e5565b9087614e7c565b60048103614aca5750614a89614ac38288876149e5565b9087614d0f565b856002600719830110614adf575b5050614a65565b614af691614aee848a896149e5565b929091614b25565b5f85614ad8565b7fb4fa3fb3000000000000000000000000000000000000000000000000000000005f5260045ffd5b9291906001600160a01b03614b4e6001600160a01b035f516020615f835f395f51905f52541690565b1680614b5e575061028193614c3b565b916040939193519363d68f602560e01b85525f8580614b82363433600485016120de565b038183885af19485156104ee575f95614bde575b50614ba2939495614c3b565b803b156101e357614bcd5f92918392604051948580948193630b9dfbed60e11b835260048301612104565b03925af180156104ee576130005750565b614ba2949550614bf7903d805f833e6109bc8183611b6b565b9493614b96565b15614c065750565b6001600160a01b03907fc689cd97000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b60405163ecd0596160e01b8152600481018290526001600160a01b038316949290602081602481895afa9081156104ee575f91614cf0575b5015614cc85781614c99614c89614c9e94614210565b6001600160a01b03811615614bfe565b61561f565b823b156101e357614bcd925f92836040518096819582946306d61fe760e41b845260048401613450565b7fe27c1dd8000000000000000000000000000000000000000000000000000000005f5260045ffd5b614d09915060203d60201161201c5761200e8183611b6b565b5f614c73565b91906001600160a01b03614d376001600160a01b035f516020615f835f395f51905f52541690565b1680614d47575061028192614de6565b90916040519263d68f602560e01b84525f8480614d69363433600485016120de565b038183875af19384156104ee575f94614d89575b50614ba2929394614de6565b614ba2939450614da2903d805f833e6109bc8183611b6b565b9392614d7d565b15614db15750565b6001600160a01b03907f741cbe03000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b60405163ecd0596160e01b81526004808201526001600160a01b038216939190602081602481885afa9081156104ee575f91614e5d575b5015614cc857614c9e90614e58614e486001600160a01b035f516020615f835f395f51905f52541690565b6001600160a01b03811615614da9565b6145c1565b614e76915060203d60201161201c5761200e8183611b6b565b5f614e1d565b91906001600160a01b03614ea46001600160a01b035f516020615f835f395f51905f52541690565b1680614eb4575061028192614fc1565b90916040519263d68f602560e01b84525f8480614ed6363433600485016120de565b038183875af19384156104ee575f94614ef6575b50614ba2929394614fc1565b614ba2939450614f0f903d805f833e6109bc8183611b6b565b9392614eea565b906004101561358b5760040190565b15614f2c57565b7f867a1dcf000000000000000000000000000000000000000000000000000000005f5260045ffd5b15614f5b57565b7fc001660b000000000000000000000000000000000000000000000000000000005f5260045ffd5b15614f8b5750565b6001600160e01b0319907fa56a04dd000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b90916001600160a01b0382169160405163ecd0596160e01b815260208180614ff160048201906003602083019252565b0381875afa9081156104ee575f91615141575b5015614cc8576124bf8461060c6150766105218680615054615047615039836150336124b96150e59e8c611aae565b99614f16565b356001600160f81b03191690565b6001600160f81b03191690565b9a6001600160f81b03198c1615801561512a575b61507190614f25565b611ad9565b966150a56001600160e01b031984166306d61fe760e41b8114908115615119575b8115615110575b5015614f54565b6150ba836150b5610585826159da565b614f83565b6150d46150c5611cfa565b6001600160a01b039096168652565b6001600160f81b0319166020850152565b803b156101e357614bcd5f929183926040519485809481936306d61fe760e41b835260048301612104565b9050155f61509e565b638a91b0e360e01b81149150615097565b50607f60f91b6001600160f81b03198d1614615068565b61515a915060203d60201161201c5761200e8183611b6b565b5f615004565b91906001600160a01b036151886001600160a01b035f516020615f835f395f51905f52541690565b16806151985750610281926151fa565b90916040519263d68f602560e01b84525f84806151ba363433600485016120de565b038183875af19384156104ee575f946151da575b50614ba29293946151fa565b614ba29394506151f3903d805f833e6109bc8183611b6b565b93926151ce565b60405163ecd0596160e01b8152600260048201526001600160a01b038216939190602081602481885afa9081156104ee575f91615241575b5015614cc857614c9e90615a24565b61525a915060203d60201161201c5761200e8183611b6b565b5f615232565b91906001600160a01b036152886001600160a01b035f516020615f835f395f51905f52541690565b16806152985750610281926152fa565b90916040519263d68f602560e01b84525f84806152ba363433600485016120de565b038183875af19384156104ee575f946152da575b50614ba29293946152fa565b614ba29394506152f3903d805f833e6109bc8183611b6b565b93926152ce565b60405163ecd0596160e01b8152600160048201526001600160a01b038216939190602081602481885afa9081156104ee575f91615399575b5015614cc8576001600160a01b037f0000000000000000000000000000000055c766a7060797fbc7be40c08b296b7216841461537157614c9e90615b48565b7fabc3af79000000000000000000000000000000000000000000000000000000005f5260045ffd5b6153b2915060203d60201161201c5761200e8183611b6b565b5f615332565b91816014116101e357823560601c92601401916013190190565b5f9192806040519485378338925af4913d82523d5f602084013e60203d830101604052565b5f919392806040519586378438925af415615421573d82523d5f602084013e60203d830101604052565b503d5f823e3d90fd5b909181359182810193601f199101016020840193803593828560051b8301119060401c1761549d578361545b575050565b835b5f190160208160051b8301013580830160608101908135809101918680602080860135809601011191111792171760401c1761549d578061545d57505050565b63ba597e7e5f526004601cfd5b9190916154b683613ef0565b925f5b8181106154c557505050565b806154d36001928486613569565b8035906154df82610265565b6154fe602082013560408301936154f68585611e85565b929091615582565b615508858b613f46565b5215615517575b5050016154b9565b7fb5282692b8c578af7fb880895d599035496b5e64d1f14bf428a1ed3bc406f6629161554291611e85565b9061555061269e858b613f46565b0390a15f8061550f565b90806014116101e357813560601c92603482106101e357601483013592603401916033190190565b905f928491604051958692833738935af1913d82523d5f602084013e60203d830101604052565b90925f92819594604051968792833738935af115615421573d82523d5f602084013e60203d830101604052565b8380935f93604051958692833738935af1156108925701604052565b60405190602036830101604052816014360181525f602036920137604051601481016040523360601b9052565b6008810361568f57506001600160a01b0361028191166001600160a01b03166001600160a01b03197f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f065416177f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0655565b6009146156995750565b6001600160a01b0361028191166001600160a01b03166001600160a01b03197f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f055416177f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0555565b1561570757565b6064604051635107885760e11b815260206004820152601860248201527f496e76616c696420706172616d44617461206c656e67746800000000000000006044820152fd5b6060906020810161575c8161471d565b6157658161470e565b6157a95750611ba291508060406105219201906157a46157858383611e85565b61579f6157956060860186613590565b9390923691611d25565b615d32565b611e85565b60016157b48261471d565b6157bd8161470e565b03615827575090505f806157d46040840184611e85565b50604051806157ee81602085810135860180359101612360565b0391355afa906157fc61236d565b911561581a57615813816060611ba2930190613590565b9083615d32565b636533cc8d5f526004601cfd5b61583260029161471d565b61583b8161470e565b0361594f57602861585a6158526040840184611e85565b909214615700565b6014810135831c9035831c806158c75750906158b3613358936158ad611ba29431935b604051926158a58461589788602083019190602083019252565b03601f198101865285611b6b565b810190613590565b91615d32565b604051928391602083019190602083019252565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b03929092166004830152909190602090839060249082905afa80156104ee57613358936158ad6158b392611ba2955f91615930575b509361587d565b615949915060203d6020116104e7576104d98183611b6b565b5f615929565b604051635107885760e11b815260206004820152601a60248201527f496e76616c696420706172616d206665746368657220747970650000000000006044820152606490fd5b9291905f91604051943892602083519301915af115615421573d82523d5f602084013e60203d830101604052565b6002111561471857565b3560028110156101e35790565b615a1d6001600160a01b03916001600160e01b0319165f527f0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f0260205260405f2090565b5416151590565b6001600160a01b03811680158015615b3e575b6143ca575f9081525f516020615fa35f395f51905f5260205260409020546001600160a01b0316615b0a5760015f525f516020615fa35f395f51905f5260205261028190615acf615aa77fbdfeb076d903611fa58576955630d640569633049bcf40ad9c22db9251b54a13610db5565b613af1835f516020615fa35f395f51905f52906001600160a01b03165f5260205260405f2090565b60015f525f516020615fa35f395f51905f526020527fbdfeb076d903611fa58576955630d640569633049bcf40ad9c22db9251b54a13613af1565b7f40d3d1a4000000000000000000000000000000000000000000000000000000005f526001600160a01b031660045260245ffd5b5060018114615a37565b6001600160a01b03811680158015615c2e575b6143ca575f9081525f516020615f635f395f51905f5260205260409020546001600160a01b0316615b0a5760015f525f516020615f635f395f51905f5260205261028190615bf3615bcb7ffe44ceacbf4f03c6ac19f86826dd265fa9ec25125e8b1766c207f24cd3bc73c7610db5565b613af1835f516020615f635f395f51905f52906001600160a01b03165f5260205260405f2090565b60015f525f516020615f635f395f51905f526020527ffe44ceacbf4f03c6ac19f86826dd265fa9ec25125e8b1766c207f24cd3bc73c7613af1565b5060018114615b5b565b6040813603126101e35760405190615c4f82611b4a565b803560048110156101e357825260208101359067ffffffffffffffff82116101e357615c7d91369101611d5b565b602082015290565b6004111561471857565b91908260409103126101e3576020825192015190565b15615cac57565b630a31844b60e41b5f52600360045260245ffd5b15615cc757565b630a31844b60e41b5f52600260045260245ffd5b15615ce257565b630a31844b60e41b5f52600160045260245ffd5b15615cfd57565b630a31844b60e41b5f525f60045260245ffd5b602081519101519060208110615d24575090565b5f199060200360031b1b1690565b9180615d3d57505050565b5f5b818110615d4c5750505050565b615d5f615d5a828486614773565b615c38565b9060208160051b86010151918051615d7681615c85565b615d7f81615c85565b615da257600192615d966020615d9c930151615d10565b14615cf6565b01615d3f565b60018151615daf81615c85565b615db881615c85565b03615ddc57600192615dd06020615dd7930151615d10565b1115615cdb565b615d9c565b60028151615de981615c85565b615df281615c85565b03615e1157600192615e0a6020615dd7930151615d10565b1015615cc0565b60038151615e1e81615c85565b615e2781615c85565b03615e6657600192615e496020615dd793015160208082518301019101615c8f565b908210159182615e5b575b5050615ca5565b111590505f80615e54565b7f2c50c45e000000000000000000000000000000000000000000000000000000005f5260045ffd5b929193905f5b848110615ea357505050505050565b60208160051b83010151906001600160a01b038716916040516020810190615edb81613358868b869091604092825260208201520190565b519020833b156101e3576040517fa39e0787000000000000000000000000000000000000000000000000000000008152600481019190915260248101919091526001600160a01b0385166044820152915f908390606490829084905af19182156104ee57600192615f4e575b5001615e94565b8061099d5f615f5c93611b6b565b5f615f4756fe0bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f000bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f030bb70095b32b9671358306b0339b4c06e7cbd8cb82505941fba30d1eb5b82f01a164736f6c634300081b000a

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da0320000000000000000000000000000000055c766a7060797fbc7be40c08b296b7200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000014eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000

-----Decoded View---------------
Arg [0] : anEntryPoint (address): 0x0000000071727De22E5E9d8BAf0edAc6f37da032
Arg [1] : defaultValidator (address): 0x0000000055C766a7060797FBc7Be40c08B296b72
Arg [2] : initData (bytes): 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000071727de22e5e9d8baf0edac6f37da032
Arg [1] : 0000000000000000000000000000000055c766a7060797fbc7be40c08b296b72
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000014
Arg [4] : eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000


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.