Sepolia Testnet

Contract

0xBC8c14D7F4640f52f3a1CceC27164340215Da74C

Overview

ETH Balance

0 ETH

More Info

Multichain Info

N/A
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Advanced mode:
Parent Transaction Hash Method Block
From
To
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
OPF7702v11

Compiler Version
v0.8.29+commit.ab55807c

Optimization Enabled:
Yes with 2000 runs

Other Settings:
cancun EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 31 : OPF7702v11.sol
/*
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░     ░░░░░░        ░░░         ░    ░░░░░   ░        ░░░░░░     ░░░░░░        ░░░░░           ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
▒▒▒   ▒▒▒▒   ▒▒▒   ▒▒▒▒   ▒   ▒▒▒▒▒▒▒  ▒   ▒▒▒   ▒   ▒▒▒▒▒▒▒▒▒   ▒▒▒▒   ▒▒▒   ▒▒▒▒   ▒▒▒▒▒▒▒   ▒▒▒▒▒      ▒   ▒      ▒   ▒▒▒▒▒   ▒▒▒▒▒▒▒   ▒  ▒▒▒
▒   ▒▒▒▒▒▒▒▒   ▒   ▒▒▒▒   ▒   ▒▒▒▒▒▒▒   ▒   ▒▒   ▒   ▒▒▒▒▒▒▒   ▒▒▒▒▒▒▒▒   ▒   ▒▒▒▒   ▒▒▒▒▒▒▒   ▒▒▒▒▒▒▒▒▒▒▒   ▒▒▒▒▒▒▒▒   ▒▒▒▒   ▒▒   ▒▒▒  ▒▒▒▒▒   
▓   ▓▓▓▓▓▓▓▓   ▓        ▓▓▓       ▓▓▓   ▓▓   ▓   ▓       ▓▓▓   ▓▓▓▓▓▓▓▓   ▓  ▓   ▓▓▓▓▓▓▓▓▓▓▓   ▓▓▓▓▓▓▓▓▓▓   ▓▓▓▓▓▓▓▓   ▓▓▓   ▓▓▓▓▓   ▓▓▓▓▓▓▓   ▓▓
▓   ▓▓▓▓▓▓▓▓   ▓   ▓▓▓▓▓▓▓▓   ▓▓▓▓▓▓▓   ▓▓▓  ▓   ▓   ▓▓▓▓▓▓▓   ▓▓▓▓▓▓▓▓   ▓   ▓▓   ▓▓▓▓▓▓▓▓▓   ▓▓▓▓▓▓▓▓▓   ▓▓▓▓▓▓▓▓   ▓▓▓▓   ▓▓▓▓▓▓   ▓▓▓▓   ▓▓▓▓
▓▓▓   ▓▓▓▓▓   ▓▓   ▓▓▓▓▓▓▓▓   ▓▓▓▓▓▓▓   ▓▓▓▓  ▓  ▓   ▓▓▓▓▓▓▓▓▓   ▓▓▓▓▓   ▓▓   ▓▓▓▓   ▓▓▓▓▓▓▓   ▓▓▓▓▓▓▓▓▓   ▓▓▓▓▓▓▓▓   ▓▓▓▓▓   ▓▓▓▓   ▓▓▓   ▓▓▓▓▓▓
█████     ██████   ████████         █   ██████   █   ███████████     ██████   ██████   █████   █████████   ████████   ████████    █████         █
█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
 */

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.29;

import {SpendLimit} from "src/utils/SpendLimit.sol";
import {IValidation} from "src/interfaces/IValidation.sol";
import {ISessionKey} from "src/interfaces/ISessionkey.sol";
import {WebAuthnVerifier} from "src/utils/WebAuthnVerifier.sol";
import {BaseAccount} from "lib/account-abstraction/contracts/core/BaseAccount.sol";
import {IAccount} from "lib/account-abstraction/contracts/interfaces/IAccount.sol";
import {SafeCast} from "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol";
import {ECDSA} from "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol";
import {IEntryPoint} from "lib/account-abstraction/contracts/interfaces/IEntryPoint.sol";
import {ReentrancyGuard} from "lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol";
import {Initializable} from "lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol";
import {PackedUserOperation} from "lib/account-abstraction/contracts/interfaces/PackedUserOperation.sol";
import {SIG_VALIDATION_FAILED, SIG_VALIDATION_SUCCESS, _packValidationData} from "lib/account-abstraction/contracts/core/Helpers.sol";

import "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol";
import "lib/openzeppelin-contracts/contracts/interfaces/IERC1271.sol";
import "lib/openzeppelin-contracts/contracts/token/ERC1155/utils/ERC1155Holder.sol";
import "lib/openzeppelin-contracts/contracts/token/ERC721/utils/ERC721Holder.sol";

/**
 * @title Openfort Base Account 7702 with ERC-4337 Support
 * @author Openfort@0xkoiner
 * @notice This contract implements an EIP-7702 compatible account with EIP-712 signatures and ERC-4337 support
 * @dev Implements EIP-7702, EIP-712, ERC-4337, and various token handling capabilities
 */
 
// address: 0xD24af0109E31F238440E2d6A6d49935d499274b7 14/05/2025
// keccak256("openfort.baseAccount.7702.v1") = 0x801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f368
contract OPF7702v11 layout at 0x801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f368 is
    IAccount,
    SpendLimit,
    BaseAccount,
    ISessionKey,
    Initializable, 
    ReentrancyGuard,
    WebAuthnVerifier,
    IERC165, IERC1271, ERC1155Holder, ERC721Holder 
{
    using ECDSA for bytes32;

    /**
     * @notice Structure for representing a transaction to be executed by the account
     * @dev Contains destination address, ETH value, and calldata
     */
    struct Transaction {
        address to;
        uint256 value;
        bytes data;
    }

    address public constant DEAD_ADDRESS = 0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF;
    uint256 public constant MAX_SELECTORS = 10;
    bytes4 internal constant EXECUTE_SELECTOR = 0xb61d27f6;
    bytes4 internal constant EXECUTEBATCH_SELECTOR = 0x47e1da2a;
    bytes32 private constant P256_VERIFIER = 0x2562256225622562256225622562256225622562256225622562256225622562;

    /// @notice Address of the implementation contract
    address public immutable _OPENFORT_CONTRACT_ADDRESS;

    /// @notice The EntryPoint singleton contract
    address private immutable ENTRY_POINT;

    /// @notice Current transaction nonce, used to prevent replay attacks
    uint256 public nonce;

    uint256 public id;
    mapping(uint256 id => Key key) public idSessionKeys;
    mapping(bytes32 sessionKey => SessionKey sessionKeyData) public sessionKeys;
    mapping(address sessionKeyEOA => SessionKey sessionKeyData) public sessionKeysEOA;
    mapping(bytes challenge => bool isUsed) public usedChallenges;

    error OpenfortBaseAccount7702V1__InvalidNonce();
    error OpenfortBaseAccount7702V1__InvalidSignature();
    error OpenfortBaseAccount7702V1__ValidationExpired();
    error OpenfortBaseAccount7702V1__InvalidTransactionLength();
    error OpenfortBaseAccount7702V1__InvalidTransactionTarget();
    error OpenfortBaseAccount7702V1__TransactionFailed(bytes returnData);

    error SessionKeyManager__InvalidTimestamp();
    error SessionKeyManager__AddressCantBeZero();
    error SessionKeyManager__SessionKeyInactive();
    error SessionKeyManager__SelectorsListTooBig();
    error SessionKeyManager__SessionKeyRegistered();

    /// @notice Emitted when the account is initialized with an masterKey
    event Initialized(Key indexed masterKey);

    /// @notice Emitted when a transaction is executed
    event TransactionExecuted(address indexed target, uint256 value, bytes data);

    event SessionKeyRevoked(bytes32 indexed sessionKey);
    event SessionKeyRegistrated(bytes32 indexed sessionKey);

    /**
     * @notice Sets up the contract with EIP-712 domain and the EntryPoint
     * @param _entryPoint Address of the ERC-4337 EntryPoint contract
     */
    constructor(address _entryPoint) {
        ENTRY_POINT = _entryPoint;
        _OPENFORT_CONTRACT_ADDRESS = address(this);
        _disableInitializers();
    }

    fallback() external payable {
    }

    receive() external payable {
    }

    
    /**
     * @notice Initializes the account
     * @dev Can only be called via EntryPoint or during contract creation
     * @param _validUntil The timestamp until which the initialization is valid
     * @param _hash Hash of the user operation
     * @param _signature Signature to validate ownership
     * @param _nonce Nonce to prevent replay attacks
     */
    function initialize(Key calldata _key, SpendTokenInfo calldata _spendTokenInfo, bytes4[] calldata _allowedSelectors, bytes32 _hash, bytes memory _signature, uint256 _validUntil, uint256 _nonce) external initializer {
        _requireForExecute();
        _clearStorage();
        _validateNonce(_nonce);
        _notExpired(_validUntil);

        if (!_checkSignature(_hash, _signature)) {
            revert OpenfortBaseAccount7702V1__InvalidSignature();
        }

        nonce = _nonce;
        registerSessionKey(_key, uint48(block.timestamp + 10000), uint48(0), uint48(0), false, DEAD_ADDRESS, _spendTokenInfo, _allowedSelectors, 0);
        
        emit Initialized(_key);
    }

   
    /**
     * @notice Registers a new session key with specified permissions
     * @param _key Key information (EOA or WebAuthn)
     * @param _validUntil Timestamp until which the key is valid
     * @param _validAfter Timestamp after which the key becomes valid
     * @param _limit Number of transactions allowed (0 for unlimited/master key)
     * @param _whitelisting Whether contract address whitelisting is enabled
     * @param _contractAddress Initial whitelisted contract address
     * @param _spendTokenInfo Token spending limit information
     * @param _allowedSelectors List of allowed function selectors
     * @param _ethLimit Maximum amount of ETH that can be spent
     * @dev Only callable by accounts with ADMIN_ROLE
     */
    function registerSessionKey(
        Key calldata _key,
        uint48 _validUntil,
        uint48 _validAfter,
        uint48 _limit,
        bool _whitelisting,
        address _contractAddress,
        SpendTokenInfo calldata _spendTokenInfo,
        bytes4[] calldata _allowedSelectors,
        uint256 _ethLimit
    ) public {
        _requireForExecute();
        if (_validUntil <= block.timestamp) revert SessionKeyManager__InvalidTimestamp();
        if (_validAfter > _validUntil) revert SessionKeyManager__InvalidTimestamp();

        idSessionKeys[id] = _key;
        id++;

        if (_key.keyType == KeyType.WEBAUTHN) {
            bytes32 keyHash = keccak256(abi.encodePacked(_key.pubKey.x, _key.pubKey.y));

            if (sessionKeys[keyHash].isActive) revert SessionKeyManager__SessionKeyRegistered();

            SessionKey storage sKey = sessionKeys[keyHash];
            _addSessionKey(
                sKey,
                _key,
                _validUntil,
                _validAfter,
                _limit,
                _whitelisting,
                _contractAddress,
                _spendTokenInfo,
                _allowedSelectors,
                _ethLimit
            );

            emit SessionKeyRegistrated(keyHash);
        } else if (_key.keyType == KeyType.EOA) {
            if (_key.eoaAddress == address(0)) revert SessionKeyManager__AddressCantBeZero();
            if (sessionKeysEOA[_key.eoaAddress].isActive) revert SessionKeyManager__SessionKeyRegistered();

            SessionKey storage sKey = sessionKeysEOA[_key.eoaAddress];

            _addSessionKey(
                sKey,
                _key,
                _validUntil,
                _validAfter,
                _limit,
                _whitelisting,
                _contractAddress,
                _spendTokenInfo,
                _allowedSelectors,
                _ethLimit
            );

            emit SessionKeyRegistrated(keccak256(abi.encodePacked(_key.eoaAddress)));
        }
    }

    /**
     * @notice Internal function to add a session key with all parameters
     * @param sKey Storage reference to the session key data
     * @param _key Key information
     * @param _validUntil Timestamp until which the key is valid
     * @param _validAfter Timestamp after which the key becomes valid
     * @param _limit Number of transactions allowed
     * @param _whitelisting Whether contract address whitelisting is enabled
     * @param _contractAddress Initial whitelisted contract address
     * @param _spendTokenInfo Token spending limit information
     * @param _allowedSelectors List of allowed function selectors
     * @param _ethLimit Maximum amount of ETH that can be spent
     */
    function _addSessionKey(
        SessionKey storage sKey,
        Key calldata _key,
        uint48 _validUntil,
        uint48 _validAfter,
        uint48 _limit,
        bool _whitelisting,
        address _contractAddress,
        SpendTokenInfo calldata _spendTokenInfo,
        bytes4[] calldata _allowedSelectors,
        uint256 _ethLimit
    ) internal {
        sKey.pubKey = _key.pubKey;
        sKey.isActive = true;
        sKey.validUntil = _validUntil;
        sKey.validAfter = _validAfter;
        sKey.limit = _limit;
        sKey.masterSessionKey = (_limit == 0);
        sKey.whoRegistrated = address(this);

        if (_limit > 0) {
            sKey.whitelisting = _whitelisting;
            sKey.ethLimit = _ethLimit;

            if (_whitelisting) {
                if (_contractAddress == address(0)) revert SessionKeyManager__AddressCantBeZero();
                sKey.whitelist[_contractAddress] = true;
                sKey.whitelist[_spendTokenInfo.token] = true;

                uint256 len = _allowedSelectors.length;
                if (len > MAX_SELECTORS) revert SessionKeyManager__SelectorsListTooBig();

                for (uint256 i = 0; i < len;) {
                    sKey.allowedSelectors.push(_allowedSelectors[i]);
                    unchecked {
                        ++i;
                    }
                }
            }

            if (_spendTokenInfo.token == address(0)) revert SessionKeyManager__AddressCantBeZero();
            sKey.spendTokenInfo.token = _spendTokenInfo.token;
            sKey.spendTokenInfo.limit = _spendTokenInfo.limit;
        }
    }

    /**
     * @notice Revokes a specific session key
     * @param _key Key information of the session key to revoke
     * @dev Only callable by accounts with ADMIN_ROLE
     */
    function revokeSessionKey(Key calldata _key) external {
        _requireForExecute();
        if (_key.keyType == KeyType.WEBAUTHN) {
            bytes32 keyHash = keccak256(abi.encodePacked(_key.pubKey.x, _key.pubKey.y));
            SessionKey storage sKey = sessionKeys[keyHash];
            _revokeSessionKey(sKey);
            emit SessionKeyRevoked(keyHash);
        } else if (_key.keyType == KeyType.EOA) {
            if (_key.eoaAddress == address(0)) revert SessionKeyManager__AddressCantBeZero();
            SessionKey storage sKey = sessionKeysEOA[_key.eoaAddress];
            _revokeSessionKey(sKey);
            emit SessionKeyRevoked(keccak256(abi.encodePacked(_key.eoaAddress)));
        }
    }

    /**
     * @notice Internal function to revoke a session key
     * @param sKey Storage reference to the session key to revoke
     */
    function _revokeSessionKey(SessionKey storage sKey) internal {
        if (!sKey.isActive) revert SessionKeyManager__SessionKeyInactive();

        sKey.isActive = false;
        sKey.validUntil = 0;
        sKey.validAfter = 0;
        sKey.limit = 0;
        sKey.masterSessionKey = false;
        sKey.ethLimit = 0;
        sKey.whoRegistrated = address(0);
        sKey.spendTokenInfo.limit = 0;
        sKey.spendTokenInfo.token = address(0);
        delete sKey.allowedSelectors;
    }

    /**
     * @notice Revokes all registered session keys
     * @dev Only callable by accounts with ADMIN_ROLE
     */
    function revokeAllSessionKeys() external {
        _requireForExecute();
        for (uint256 i = 0; i < id; i++) {
            Key memory _key = getKeyById(i);

            if (_key.keyType == KeyType.WEBAUTHN) {
                bytes32 keyHash = keccak256(abi.encodePacked(_key.pubKey.x, _key.pubKey.y));
                SessionKey storage sKey = sessionKeys[keyHash];
                _revokeSessionKey(sKey);
                emit SessionKeyRevoked(keyHash);
            } else if (_key.keyType == KeyType.EOA) {
                if (_key.eoaAddress == address(0)) continue;
                SessionKey storage sKey = sessionKeysEOA[_key.eoaAddress];
                _revokeSessionKey(sKey);
                emit SessionKeyRevoked(keccak256(abi.encodePacked(_key.eoaAddress)));
            }
        }
    }

   /**
     * @notice Executes a batch of transactions
     * @dev Can only be called via EntryPoint or by self
     * @param _transactions Array of transactions to execute
     */
    function execute(Transaction[] calldata _transactions) payable external nonReentrant {
        _requireForExecute();
        if (_transactions.length == 0 || _transactions.length > 9) {
            revert OpenfortBaseAccount7702V1__InvalidTransactionLength();
        }

        uint256 transactionsLength = _transactions.length;
        Transaction calldata transactionCall;

        for (uint256 i = 0; i < transactionsLength; i++) {
            transactionCall = _transactions[i];
            address target = transactionCall.to;
            uint256 value = transactionCall.value;
            bytes memory data = transactionCall.data;

            if (target == address(this)) {
                revert OpenfortBaseAccount7702V1__InvalidTransactionTarget();
            }

            (bool success, bytes memory returnData) = target.call{value: value}(data);
            
            if (!success) {
                revert OpenfortBaseAccount7702V1__TransactionFailed(returnData);
            }

            emit TransactionExecuted(target, value, data);      
        }
    }

    /**
     * Execute a transaction (called directly from owner, or by entryPoint)
     */
    function execute(address _target, uint256 _value, bytes calldata _calldata) public payable virtual nonReentrant {
        _requireForExecute();
        _call(_target, _value, _calldata);
    }

    /**
     * Execute a sequence of transactions. Maximum 9.
     */
    function executeBatch(address[] calldata _target, uint256[] calldata _value, bytes[] calldata _calldata)
        public
        payable
        virtual
        nonReentrant
    {
        _requireForExecute();
        if (_target.length > 9 || _target.length != _calldata.length || _target.length != _value.length) {
            revert OpenfortBaseAccount7702V1__InvalidTransactionLength();
        }
        uint256 i;
        for (i; i < _target.length;) {
            _call(_target[i], _value[i], _calldata[i]);
            unchecked {
                ++i;
            }
        }
    }

    /**
     * @dev Call a target contract and reverts if it fails.
     */
    function _call(address _target, uint256 _value, bytes calldata _calldata) internal virtual {
        emit TransactionExecuted(_target, _value, _calldata);  
        (bool success, bytes memory result) = _target.call{value: _value}(_calldata);
        if (!success) {
            assembly {
                revert(add(result, 32), mload(result))
            }
        }
    }

    /**
     * @notice ERC-4337 signature validation
     * @dev Validates the signature for a user operation
     * @param userOp The user operation to validate
     * @param userOpHash Hash of the user operation
     * @return validationData Packed validation data (success, validUntil, validAfter) or SIG_VALIDATION_SUCCESS | SIG_VALIDATION_FAILED
     */
    function _validateSignature(
        PackedUserOperation calldata userOp,
        bytes32 userOpHash
    ) internal virtual override returns (uint256 validationData) {
        (KeyType sigType, bytes memory sigData) = abi.decode(userOp.signature, (KeyType, bytes));
    
        if (sigType == KeyType.EOA) {
            bytes memory signature = sigData;

            address signer = ECDSA.recover(userOpHash, signature);

            if (address(this) == signer) return 0;

            SessionKey storage sKey = sessionKeysEOA[signer];
            
            PubKey memory _pubKey = PubKey({x: sKey.pubKey.x, y: sKey.pubKey.y});
            Key memory _key = Key({pubKey: _pubKey, eoaAddress: signer, keyType: KeyType.EOA});

            if (isValidSessionKey(_key, userOp.callData)) {
                return _packValidationData(false, sKey.validUntil, sKey.validAfter);
            }
        } else if (sigType == KeyType.WEBAUTHN) {
            (
                ,
                bytes memory challenge,
                bool requireUserVerification,
                bytes memory authenticatorData,
                string memory clientDataJSON,
                uint256 challengeIndex,
                uint256 typeIndex,
                bytes32 r,
                bytes32 s,
                PubKey memory pubKey
            ) = abi.decode(userOp.signature, (KeyType, bytes, bool, bytes, string, uint256, uint256, bytes32, bytes32, PubKey));

            if (usedChallenges[challenge]) return SIG_VALIDATION_FAILED;

            bool isValid = verifySoladySignature(
                challenge,
                requireUserVerification,
                authenticatorData,
                clientDataJSON,
                challengeIndex,
                typeIndex,
                r,
                s,
                pubKey.x,
                pubKey.y
            );

            if (!isValid) return SIG_VALIDATION_FAILED;

            bytes32 keyHash = keccak256(abi.encodePacked(pubKey.x, pubKey.y));
            SessionKey storage sKey = sessionKeys[keyHash];

            Key memory _key = Key({
                pubKey: PubKey({x: sKey.pubKey.x, y: sKey.pubKey.y}),
                eoaAddress: address(0),
                keyType: KeyType.WEBAUTHN
            });

            if (sKey.masterSessionKey) return 0;

            if (isValidSessionKey(_key, userOp.callData)) {
                usedChallenges[challenge] = true;
                return _packValidationData(false, sKey.validUntil, sKey.validAfter);
            }
        }

        return SIG_VALIDATION_FAILED;
    }

    /**
     * @notice Validates if a session key is allowed to execute the given call data
     * @param _key Key information
     * @param _callData Call data to be executed
     * @return True if the session key is allowed to execute the call, false otherwise
     */
    function isValidSessionKey(Key memory _key, bytes calldata _callData) internal virtual returns (bool) {
        // 1. Get the session key based on key type
        SessionKey storage sessionKey;
        if (_key.keyType == KeyType.WEBAUTHN) {
            bytes32 keyHash = keccak256(abi.encodePacked(_key.pubKey.x, _key.pubKey.y));
            sessionKey = sessionKeys[keyHash];
        } else if (_key.keyType == KeyType.EOA) {
            if (_key.eoaAddress == address(0)) return false;
            sessionKey = sessionKeysEOA[_key.eoaAddress];
        } else {
            return false;
        }

        // 2. Basic validation for all key types
        if (sessionKey.validUntil == 0 || !sessionKey.isActive) return false;
        if (sessionKey.whoRegistrated != address(this)) return false;

        // 3. Extract function selector from callData
        bytes4 funcSelector = bytes4(_callData[:4]);

        // 4. Handle EXECUTE_SELECTOR
        if (funcSelector == EXECUTE_SELECTOR) {
            return _validateExecuteCall(sessionKey, _callData);
        }

        // 5. Handle EXECUTEBATCH_SELECTOR
        if (funcSelector == EXECUTEBATCH_SELECTOR) {
            return _validateExecuteBatchCall(sessionKey, _callData);
        }

        return false;
    }

   /**
     * @notice Validates a single execute call
     * @param sessionKey Session key data
     * @param _callData Call data to validate
     * @return True if the call is valid, false otherwise
     */
    function _validateExecuteCall(SessionKey storage sessionKey, bytes calldata _callData) internal returns (bool) {
        // Decode the execute call parameters
        address toContract;
        bytes memory innerData;
        uint256 amount;
        (toContract, amount, innerData) = abi.decode(_callData[4:], (address, uint256, bytes));

        // Basic validation
        if (toContract == address(this)) return false;
        if (sessionKey.masterSessionKey) return true;
        if (sessionKey.limit == 0) return false;
        if (sessionKey.ethLimit < amount) return false;

        // Validate selector
        bytes4 innerSelector = bytes4(innerData);
        if (!_isAllowedSelector(sessionKey.allowedSelectors, innerSelector)) {
            return false;
        }

        // Update limits
        unchecked {
            sessionKey.limit--;
        }
        if (amount > 0) sessionKey.ethLimit = sessionKey.ethLimit - amount;

        // Handle token spend limits
        if (sessionKey.spendTokenInfo.token == toContract) {
            bool validSpend = _validateTokenSpend(sessionKey, innerData);
            if (!validSpend) return false;
        }

        // Check whitelisting
        if (!sessionKey.whitelisting || sessionKey.whitelist[toContract]) {
            return true;
        }
        return false;
    }

    /**
     * @notice Validates a batch of execute calls
     * @param sessionKey Session key data
     * @param _callData Call data containing batch execution data
     * @return True if all calls in the batch are valid, false otherwise
     */
    function _validateExecuteBatchCall(SessionKey storage sessionKey, bytes calldata _callData)
        internal
        returns (bool)
    {
        // Decode the batch call parameters
        (address[] memory toContracts, uint256[] memory amounts, bytes[] memory innerDataArray) =
            abi.decode(_callData[4:], (address[], uint256[], bytes[]));

        uint256 numberOfInteractions = toContracts.length;
        if (numberOfInteractions > 9) return false;

        // Check if session key has enough limit for all interactions
        if (!sessionKey.masterSessionKey) {
            if (sessionKey.limit < numberOfInteractions) return false;
            unchecked {
                sessionKey.limit = sessionKey.limit - SafeCast.toUint48(numberOfInteractions);
            }
        }

        // Validate each interaction
        for (uint256 i = 0; i < numberOfInteractions; ++i) {
            if (toContracts[i] == address(this)) return false;

            if (!sessionKey.masterSessionKey) {
                // Validate selector
                bytes4 innerSelector = bytes4(innerDataArray[i]);
                if (!_isAllowedSelector(sessionKey.allowedSelectors, innerSelector)) {
                    return false;
                }

                // Check ETH limit
                if (sessionKey.ethLimit < amounts[i]) return false;
                if (amounts[i] > 0) sessionKey.ethLimit = sessionKey.ethLimit - amounts[i];

                // Handle token spend limits
                if (sessionKey.spendTokenInfo.token == toContracts[i]) {
                    bool validSpend = _validateTokenSpend(sessionKey, innerDataArray[i]);
                    if (!validSpend) return false;
                }

                // Check whitelisting
                if (sessionKey.whitelisting && !sessionKey.whitelist[toContracts[i]]) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * @notice Validates token spending against limits
     * @param sessionKey Session key data
     * @param innerData Call data containing token transfer details
     * @return True if the token spend is valid, false otherwise
     */
    function _validateTokenSpend(SessionKey storage sessionKey, bytes memory innerData)
        internal
        returns (bool)
    {
        uint256 startPos = innerData.length - 32;
        bytes32 value;
        assembly {
            value := mload(add(add(innerData, 0x20), startPos))
        }

        if (uint256(value) > sessionKey.spendTokenInfo.limit) return false;

        if (uint256(value) > 0) {
            sessionKey.spendTokenInfo.limit = sessionKey.spendTokenInfo.limit - uint256(value);
        }

        return true;
    }

    /**
     * @notice Checks if a function selector is in the allowed list
     * @param selectors List of allowed selectors
     * @param selector Selector to check
     * @return True if the selector is allowed, false otherwise
     */
    function _isAllowedSelector(bytes4[] storage selectors, bytes4 selector) internal view returns (bool) {
        for (uint256 i = 0; i < selectors.length; ++i) {
            if (selectors[i] == selector) {
                return true;
            }
        }
        return false;
    }

    /**
     * @notice Implements EIP-1271 signature validation
     * @param _hash Hash that was signed
     * @param _signature Signature to verify
     * @return magicValue Magic value indicating whether signature is valid
     */
    function isValidSignature(bytes32 _hash, bytes memory _signature) public view returns (bytes4 magicValue) {
        if (_hash == P256_VERIFIER && _signature.length > 65) {
            uint256 key;
            assembly {
                key := mload(add(_signature, 32))
            }

            if (key == uint256(KeyType.WEBAUTHN)) {
                return _validateWebAuthnSignature(_signature);
            }
        } else if (_signature.length == 64 || _signature.length == 65) {

            address signer = ECDSA.recover(_hash, _signature);

            if (address(this) == signer) return this.isValidSignature.selector;
            SessionKey storage sessionKey = sessionKeysEOA[signer];

            if (
                sessionKey.validUntil == 0 || sessionKey.validAfter > block.timestamp
                    || sessionKey.validUntil < block.timestamp || (!sessionKey.masterSessionKey && sessionKey.limit < 1)
            ) {
                return bytes4(0xffffffff);
            } else if (sessionKey.whoRegistrated != address(this)) {
                return bytes4(0xffffffff);
            } else {
                return this.isValidSignature.selector;
            }
        }

        return bytes4(0xffffffff);
    }

    /**
     * @notice Internal function to validate WebAuthn signatures
     * @param _signature WebAuthn signature data
     * @return Magic value if the signature is valid, otherwise 0xffffffff
     */
    function _validateWebAuthnSignature(bytes memory _signature) internal view returns (bytes4) {

        (
            KeyType sigType,
            bytes memory challenge,
            bool requireUserVerification,
            bytes memory authenticatorData,
            string memory clientDataJSON,
            uint256 challengeIndex,
            uint256 typeIndex,
            bytes32 r,
            bytes32 s,
            PubKey memory pubKey
        ) = abi.decode(_signature, (KeyType, bytes, bool, bytes, string, uint256, uint256, bytes32, bytes32, PubKey));

        if (sigType != KeyType.WEBAUTHN) {
            return bytes4(0xffffffff);
        }

        if (usedChallenges[challenge]) return bytes4(0xffffffff);

        bool isValid = verifySoladySignature(
            challenge,
            requireUserVerification,
            authenticatorData,
            clientDataJSON,
            challengeIndex,
            typeIndex,
            r,
            s,
            pubKey.x,
            pubKey.y
        );

        if (!isValid) return bytes4(0xffffffff);

        bytes32 keyHash = keccak256(abi.encodePacked(pubKey.x, pubKey.y));
        SessionKey storage sessionKey = sessionKeys[keyHash];

        if (
            sessionKey.validUntil == 0 || sessionKey.validAfter > block.timestamp
                || sessionKey.validUntil < block.timestamp || (!sessionKey.masterSessionKey && sessionKey.limit < 1)
        ) {
            return bytes4(0xffffffff);
        } else if (sessionKey.whoRegistrated != address(this)) {
            return bytes4(0xffffffff);
        } else {
            return this.isValidSignature.selector;
        }
    }

    function _checkSignature(bytes32 hash, bytes memory signature) internal view returns (bool) {
        return ECDSA.recover(hash, signature) == address(this);
    }
    
    /**
     * @notice Verifies that the validation has not expired
     * @dev Compares current timestamp with validUntil timestamp
     * @param _validUntil The timestamp until which the validation is valid
     */
    function _notExpired(uint256 _validUntil) internal view {
        if (block.timestamp > _validUntil) {
            revert OpenfortBaseAccount7702V1__ValidationExpired();
        }
    }

    /**
     * @notice Validates that the provided nonce is not equal to the current nonce
     * @dev Ensures nonce is different to prevent replay attacks
     * @param _nonce The nonce to validate
     */
    function _validateNonce(uint256 _nonce) internal override view {
        if (_nonce == nonce) {
            revert OpenfortBaseAccount7702V1__InvalidNonce();
        }
    }

    /**
     * @notice Return the EntryPoint used by this account
     * @return The EntryPoint contract
     */
    function entryPoint() public pure override returns (IEntryPoint) {
        return IEntryPoint(0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108);
    }

    /**
     * @notice Check if caller is authorized to execute functions
     * @dev Only self-calls and EntryPoint calls are allowed
     */
    function _requireForExecute() internal view virtual override {
        require(
            msg.sender == address(this) ||
            msg.sender == address(entryPoint()),
            "not from self or EntryPoint"
        );
    }

    /**
     * @notice Clears the contract's storage slots for reinitialization
     * @dev Uses inline assembly to directly clear storage at specific slots
     */
    function _clearStorage() internal {
        bytes32 baseSlot = keccak256("openfort.baseAccount.7702.v1");
        
        for (uint256 i = 2; i < 6; i++) {
            bytes32 slot = bytes32(uint256(baseSlot) + i);
            assembly {
                sstore(slot, 0)
            }
        }
    }

    /**
     * @notice Retrieves registration information for a key
     * @param _id ID of the key
     * @return keyType Type of the key
     * @return registeredBy Address that registered the key
     * @return isActive Whether the key is active
     */
    function getKeyRegistrationInfo(uint256 _id)
        external
        view
        returns (KeyType keyType, address registeredBy, bool isActive)
    {
        Key memory key = getKeyById(_id);
        if (key.keyType == KeyType.WEBAUTHN) {
            bytes32 keyHash = keccak256(abi.encodePacked(key.pubKey.x, key.pubKey.y));
            return (key.keyType, sessionKeys[keyHash].whoRegistrated, sessionKeys[keyHash].isActive);
        } else if (key.keyType == KeyType.EOA) {
            return (key.keyType, sessionKeysEOA[key.eoaAddress].whoRegistrated, sessionKeysEOA[key.eoaAddress].isActive);
        }
        return (key.keyType, address(0), false);
    }

    /**
     * @notice Retrieves key information by ID
     * @param _id ID of the key to retrieve
     * @return Key information
     */
    function getKeyById(uint256 _id) public view returns (Key memory) {
        Key storage _key = idSessionKeys[_id];
        return _key;
    }

    /**
     * @notice Retrieves session key data for a WebAuthn key
     * @param _keyHash Hash of the WebAuthn public key
     * @return isActive Whether the key is active
     * @return validUntil Timestamp until which the key is valid
     * @return validAfter Timestamp after which the key becomes valid
     * @return limit Number of transactions allowed
     */
    function getSessionKeyData(bytes32 _keyHash) external view returns (bool, uint48, uint48, uint48) {
        bool isActive = sessionKeys[_keyHash].isActive;
        uint48 validUntil = sessionKeys[_keyHash].validUntil;
        uint48 validAfter = sessionKeys[_keyHash].validAfter;
        uint48 limit = sessionKeys[_keyHash].limit;

        return (isActive, validUntil, validAfter, limit);
    }

    /**
     * @notice Retrieves session key data for a WebAuthn key
     * @param _key Address of EOA Session Key
     * @return isActive Whether the key is active
     * @return validUntil Timestamp until which the key is valid
     * @return validAfter Timestamp after which the key becomes valid
     * @return limit Number of transactions allowed
     */
    function getSessionKeyData(address _key) external view returns (bool, uint48, uint48, uint48) {
        bool isActive = sessionKeysEOA[_key].isActive;
        uint48 validUntil = sessionKeysEOA[_key].validUntil;
        uint48 validAfter = sessionKeysEOA[_key].validAfter;
        uint48 limit = sessionKeysEOA[_key].limit;

        return (isActive, validUntil, validAfter, limit);
    }

    /**
     * @notice Checks if an EOA session key is active
     * @param eoaKey EOA address to check
     * @return True if the session key is active, false otherwise
     */
    function isSessionKeyActive(address eoaKey) external view returns (bool) {
        return sessionKeysEOA[eoaKey].isActive;
    }

    /**
     * @notice Checks if a WebAuthn session key is active
     * @param keyHash Hash of the WebAuthn public key
     * @return True if the session key is active, false otherwise
     */
    function isSessionKeyActive(bytes32 keyHash) external view returns (bool) {
        return sessionKeys[keyHash].isActive;
    }

    /**
     * @notice Encodes WebAuthn signature data for use in transaction submission
     * @param challenge Challenge that was signed
     * @param requireUserVerification Whether user verification is required
     * @param authenticatorData Authenticator data from WebAuthn
     * @param clientDataJSON Client data JSON from WebAuthn
     * @param challengeIndex Index of challenge in client data
     * @param typeIndex Index of type in client data
     * @param r R component of the signature
     * @param s S component of the signature
     * @param pubKey Public key used for signing
     * @return Encoded signature data
     */
    function encodeWebAuthnSignature(
        bytes memory challenge,
        bool requireUserVerification,
        bytes memory authenticatorData,
        string memory clientDataJSON,
        uint256 challengeIndex,
        uint256 typeIndex,
        bytes32 r,
        bytes32 s,
        PubKey memory pubKey
    ) external pure returns (bytes memory) {
        return abi.encode(
            KeyType.WEBAUTHN,
            challenge,
            requireUserVerification,
            authenticatorData,
            clientDataJSON,
            challengeIndex,
            typeIndex,
            r,
            s,
            pubKey
        );
    }

    /**
     * @notice Encodes EOA signature data for use in transaction submission
     * @param _signature Signed digest of UserOp
     * @return Encoded signature data
     */
    function encodeEOASignature(bytes calldata _signature) external pure returns (bytes memory) {
        return abi.encode(KeyType.EOA, _signature);
    }

    function supportsInterface(bytes4 _interfaceId) public override(ERC1155Holder, IERC165) pure returns (bool) {
        return
            _interfaceId == type(IERC165).interfaceId ||
            _interfaceId == type(IAccount).interfaceId ||
            _interfaceId == type(IERC1271).interfaceId ||
            _interfaceId == type(IERC1155Receiver).interfaceId ||
            _interfaceId == type(IERC721Receiver).interfaceId;
    }
}

File 2 of 31 : SpendLimit.sol
// SPDX-License-Identifier: MIR

pragma solidity ^0.8.0;

import {ISessionKey} from "src/interfaces/ISessionKey.sol";

abstract contract SpendLimit {
    /**
     * @notice Token spending limit information
     * @param token ERC20 Token Address
     * @param limit Spending Limit
     */
    struct SpendTokenInfo {
        address token;
        uint256 limit;
    }

    /**
     * @notice Validates token spending against limits
     * @param sessionKey Session key data
     * @param innerData Call data containing token transfer details
     * @return True if the token spend is valid, false otherwise
     */
    function _validateTokenSpend(ISessionKey.SessionKey storage sessionKey, bytes memory innerData)
        internal
        returns (bool)
    {
        uint256 startPos = innerData.length - 32;
        bytes32 value;
        assembly {
            value := mload(add(add(innerData, 0x20), startPos))
        }

        if (uint256(value) > sessionKey.spendTokenInfo.limit) return false;

        if (uint256(value) > 0) {
            sessionKey.spendTokenInfo.limit = sessionKey.spendTokenInfo.limit - uint256(value);
        }

        return true;
    }
}

File 3 of 31 : IValidation.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.29;

/**
 * @title IValidation Interface
 * @author Openfort@0xkoiner
 * @notice Interface defining validation structures for signature verification
 * @dev Contains structs used for signature validation in account initialization
 */
interface IValidation {
    /**
     * @notice Structure containing signature and validation data
     * @dev Used for general signature validation
     */
    struct Validation {
        uint256 nonce;
        uint8 v;
        bytes32 r;
        bytes32 s;
        uint256 validUntil;
    }
}

File 4 of 31 : ISessionkey.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.29;

import {SpendLimit} from "src/utils/SpendLimit.sol";

interface ISessionKey {
    /**
     * @notice Types of session keys supported by the contract
     * @param EOA Standard Ethereum account key
     * @param WEBAUTHN WebAuthn-based key (using P256 curve)
     */
    enum KeyType {
        EOA,
        WEBAUTHN
    }

    /**
     * @notice Public key structure for P256 curve used in WebAuthn
     * @param x X-coordinate of the public key
     * @param y Y-coordinate of the public key
     */
    struct PubKey {
        bytes32 x;
        bytes32 y;
    }

    /**
     * @notice Key structure containing all necessary key information
     * @param pubKey Public key information for WebAuthn keys
     * @param eoaAddress EOA address for standard Ethereum accounts
     * @param keyType Type of the key (EOA or WebAuthn)
     */
    struct Key {
        PubKey pubKey;
        address eoaAddress;
        KeyType keyType;
    }

    /**
     * @notice Session key data structure containing permissions and limits
     * @param pubKey Public key information
     * @param isActive Whether the session key is currently active
     * @param validUntil Timestamp until which the key is valid
     * @param validAfter Timestamp after which the key becomes valid
     * @param limit Number of transactions allowed (0 for unlimited/master key)
     * @param masterSessionKey Whether this is a master session key with unlimited permissions
     * @param whitelisting Whether contract address whitelisting is enabled
     * @param whitelist Mapping of whitelisted contract addresses
     * @param spendTokenInfo Token spending limit information
     * @param allowedSelectors List of allowed function selectors
     * @param ethLimit Maximum amount of ETH that can be spent
     * @param whoRegistrated Address that registered this session key
     */
    struct SessionKey {
        PubKey pubKey;
        bool isActive;
        uint48 validUntil;
        uint48 validAfter;
        uint48 limit;
        bool masterSessionKey;
        bool whitelisting;
        mapping(address contractAddress => bool allowed) whitelist;
        SpendLimit.SpendTokenInfo spendTokenInfo;
        bytes4[] allowedSelectors;
        uint256 ethLimit;
        address whoRegistrated;
    }
}

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

import {WebAuthn} from "src/libs/WebAuthn.sol";
import {P256} from "src/libs/P256.sol";

/**
 * @title WebAuthnVerifier
 * @author openfort@0xkoiner
 * @notice A simple contract to verify WebAuthn signatures
 * @dev Uses Solady's WebAuthn and P256 libraries for verification
 */
contract WebAuthnVerifier {
    /**
     * @notice Verifies a WebAuthn signature using the Solady library
     * @param challenge The challenge that was signed
     * @param requireUserVerification Whether to require user verification
     * @param authenticatorData The authenticator data from the WebAuthn response
     * @param clientDataJSON The client data JSON from the WebAuthn response
     * @param challengeIndex Index of the challenge in the client data JSON
     * @param typeIndex Index of the type in the client data JSON
     * @param r The r-component of the signature
     * @param s The s-component of the signature
     * @param x The x-coordinate of the public key
     * @param y The y-coordinate of the public key
     * @return isValid Whether the signature is valid
     */
    function verifySoladySignature(
        bytes memory challenge,
        bool requireUserVerification,
        bytes memory authenticatorData,
        string memory clientDataJSON,
        uint256 challengeIndex,
        uint256 typeIndex,
        bytes32 r,
        bytes32 s,
        bytes32 x,
        bytes32 y
    ) public view returns (bool isValid) {
        WebAuthn.WebAuthnAuth memory auth = WebAuthn.WebAuthnAuth({
            authenticatorData: authenticatorData,
            clientDataJSON: clientDataJSON,
            challengeIndex: challengeIndex,
            typeIndex: typeIndex,
            r: r,
            s: s
        });

        isValid = WebAuthn.verify(challenge, requireUserVerification, auth, x, y);

        return isValid;
    }

    /**
     * @notice Verifies a WebAuthn signature using encoded auth data
     * @param challenge The challenge that was signed
     * @param requireUserVerification Whether to require user verification
     * @param encodedAuth The encoded WebAuthn auth data
     * @param x The x-coordinate of the public key
     * @param y The y-coordinate of the public key
     * @return isValid Whether the signature is valid
     */
    function verifyEncodedSignature(
        bytes memory challenge,
        bool requireUserVerification,
        bytes memory encodedAuth,
        bytes32 x,
        bytes32 y
    ) public view returns (bool isValid) {
        WebAuthn.WebAuthnAuth memory auth = WebAuthn.tryDecodeAuth(encodedAuth);

        isValid = WebAuthn.verify(challenge, requireUserVerification, auth, x, y);

        return isValid;
    }

    /**
     * @notice Verifies a WebAuthn signature using compact encoded auth data
     * @param challenge The challenge that was signed
     * @param requireUserVerification Whether to require user verification
     * @param encodedAuth The compact encoded WebAuthn auth data
     * @param x The x-coordinate of the public key
     * @param y The y-coordinate of the public key
     * @return isValid Whether the signature is valid
     */
    function verifyCompactSignature(
        bytes memory challenge,
        bool requireUserVerification,
        bytes memory encodedAuth,
        bytes32 x,
        bytes32 y
    ) public view returns (bool isValid) {
        WebAuthn.WebAuthnAuth memory auth = WebAuthn.tryDecodeAuthCompact(encodedAuth);

        isValid = WebAuthn.verify(challenge, requireUserVerification, auth, x, y);

        return isValid;
    }

    /**
     * @notice Verifies a P256 signature directly (without WebAuthn)
     * @param hash The hash to verify
     * @param r The r-component of the signature
     * @param s The s-component of the signature
     * @param x The x-coordinate of the public key
     * @param y The y-coordinate of the public key
     * @return isValid Whether the signature is valid
     */
    function verifyP256Signature(bytes32 hash, bytes32 r, bytes32 s, bytes32 x, bytes32 y)
        public
        view
        returns (bool isValid)
    {
        return P256.verifySignature(hash, r, s, x, y);
    }
}

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

/* solhint-disable avoid-low-level-calls */
/* solhint-disable no-empty-blocks */
/* solhint-disable no-inline-assembly */

import "../interfaces/IAccount.sol";
import "../interfaces/IEntryPoint.sol";
import "../utils/Exec.sol";
import "./UserOperationLib.sol";

/**
 * Basic account implementation.
 * This contract provides the basic logic for implementing the IAccount interface - validateUserOp
 * Specific account implementation should inherit it and provide the account-specific logic.
 */
abstract contract BaseAccount is IAccount {
    using UserOperationLib for PackedUserOperation;

    struct Call {
        address target;
        uint256 value;
        bytes data;
    }

    error ExecuteError(uint256 index, bytes error);

    /**
     * Return the account nonce.
     * This method returns the next sequential nonce.
     * For a nonce of a specific key, use `entrypoint.getNonce(account, key)`
     */
    function getNonce() public view virtual returns (uint256) {
        return entryPoint().getNonce(address(this), 0);
    }

    /**
     * Return the entryPoint used by this account.
     * Subclass should return the current entryPoint used by this account.
     */
    function entryPoint() public view virtual returns (IEntryPoint);

    /**
     * execute a single call from the account.
     */
    // function execute(address target, uint256 value, bytes calldata data) virtual external {
    //     _requireForExecute();

    //     bool ok = Exec.call(target, value, data, gasleft());
    //     if (!ok) {
    //         Exec.revertWithReturnData();
    //     }
    // }

    /**
     * execute a batch of calls.
     * revert on the first call that fails.
     * If the batch reverts, and it contains more than a single call, then wrap the revert with ExecuteError,
     *  to mark the failing call index.
     */
    function executeBatch(Call[] calldata calls) virtual external {
        _requireForExecute();

        uint256 callsLength = calls.length;
        for (uint256 i = 0; i < callsLength; i++) {
            Call calldata call = calls[i];
            bool ok = Exec.call(call.target, call.value, call.data, gasleft());
            if (!ok) {
                if (callsLength == 1) {
                    Exec.revertWithReturnData();
                } else {
                    revert ExecuteError(i, Exec.getReturnData(0));
                }
            }
        }
    }

    /// @inheritdoc IAccount
    function validateUserOp(
        PackedUserOperation calldata userOp,
        bytes32 userOpHash,
        uint256 missingAccountFunds
    ) external virtual override returns (uint256 validationData) {
        _requireFromEntryPoint();
        validationData = _validateSignature(userOp, userOpHash);
        _validateNonce(userOp.nonce);
        _payPrefund(missingAccountFunds);
    }

    /**
     * Ensure the request comes from the known entrypoint.
     */
    function _requireFromEntryPoint() internal view virtual {
        require(
            msg.sender == address(entryPoint()),
            "account: not from EntryPoint"
        );
    }

    function _requireForExecute() internal view virtual {
        _requireFromEntryPoint();
    }

    /**
     * Validate the signature is valid for this message.
     * @param userOp          - Validate the userOp.signature field.
     * @param userOpHash      - Convenient field: the hash of the request, to check the signature against.
     *                          (also hashes the entrypoint and chain id)
     * @return validationData - Signature and time-range of this operation.
     *                          <20-byte> aggregatorOrSigFail - 0 for valid signature, 1 to mark signature failure,
     *                                    otherwise, an address of an aggregator contract.
     *                          <6-byte> validUntil - Last timestamp this operation is valid at, or 0 for "indefinitely"
     *                          <6-byte> validAfter - first timestamp this operation is valid
     *                          If the 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 _validateSignature(
        PackedUserOperation calldata userOp,
        bytes32 userOpHash
    ) internal virtual returns (uint256 validationData);

    /**
     * Validate the nonce of the UserOperation.
     * This method may validate the nonce requirement of this account.
     * e.g.
     * To limit the nonce to use sequenced UserOps only (no "out of order" UserOps):
     *      `require(nonce < type(uint64).max)`
     * For a hypothetical account that *requires* the nonce to be out-of-order:
     *      `require(nonce & type(uint64).max == 0)`
     *
     * The actual nonce uniqueness is managed by the EntryPoint, and thus no other
     * action is needed by the account itself.
     *
     * @param nonce to validate
     *
     * solhint-disable-next-line no-empty-blocks
     */
    function _validateNonce(uint256 nonce) internal view virtual {
    }

    /**
     * Sends to the entrypoint (msg.sender) the missing funds for this transaction.
     * SubClass MAY override this method 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).
     * @param missingAccountFunds - The minimum value this method should send the entrypoint.
     *                              This value MAY be zero, in case there is enough deposit,
     *                              or the userOp has a paymaster.
     */
    function _payPrefund(uint256 missingAccountFunds) internal virtual {
        if (missingAccountFunds != 0) {
            (bool success,) = payable(msg.sender).call{
                    value: missingAccountFunds
                }("");
            (success);
            // Ignore failure (its EntryPoint's job to verify, not account.)
        }
    }
}

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

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> aggregatorOrSigFail - 0 for valid signature, 1 to mark signature failure,
     *                                 otherwise, an address of an "aggregator" contract.
     *                              <6-byte> validUntil - Last timestamp this operation is valid at, or 0 for "indefinitely"
     *                              <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 8 of 31 : SafeCast.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

pragma solidity ^0.8.20;

/**
 * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeCast {
    /**
     * @dev Value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);

    /**
     * @dev An int value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedIntToUint(int256 value);

    /**
     * @dev Value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);

    /**
     * @dev An uint value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedUintToInt(uint256 value);

    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        if (value > type(uint248).max) {
            revert SafeCastOverflowedUintDowncast(248, value);
        }
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        if (value > type(uint240).max) {
            revert SafeCastOverflowedUintDowncast(240, value);
        }
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        if (value > type(uint232).max) {
            revert SafeCastOverflowedUintDowncast(232, value);
        }
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        if (value > type(uint224).max) {
            revert SafeCastOverflowedUintDowncast(224, value);
        }
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        if (value > type(uint216).max) {
            revert SafeCastOverflowedUintDowncast(216, value);
        }
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        if (value > type(uint208).max) {
            revert SafeCastOverflowedUintDowncast(208, value);
        }
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        if (value > type(uint200).max) {
            revert SafeCastOverflowedUintDowncast(200, value);
        }
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        if (value > type(uint192).max) {
            revert SafeCastOverflowedUintDowncast(192, value);
        }
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        if (value > type(uint184).max) {
            revert SafeCastOverflowedUintDowncast(184, value);
        }
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        if (value > type(uint176).max) {
            revert SafeCastOverflowedUintDowncast(176, value);
        }
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        if (value > type(uint168).max) {
            revert SafeCastOverflowedUintDowncast(168, value);
        }
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        if (value > type(uint160).max) {
            revert SafeCastOverflowedUintDowncast(160, value);
        }
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        if (value > type(uint152).max) {
            revert SafeCastOverflowedUintDowncast(152, value);
        }
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        if (value > type(uint144).max) {
            revert SafeCastOverflowedUintDowncast(144, value);
        }
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        if (value > type(uint136).max) {
            revert SafeCastOverflowedUintDowncast(136, value);
        }
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        if (value > type(uint128).max) {
            revert SafeCastOverflowedUintDowncast(128, value);
        }
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        if (value > type(uint120).max) {
            revert SafeCastOverflowedUintDowncast(120, value);
        }
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        if (value > type(uint112).max) {
            revert SafeCastOverflowedUintDowncast(112, value);
        }
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        if (value > type(uint104).max) {
            revert SafeCastOverflowedUintDowncast(104, value);
        }
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        if (value > type(uint96).max) {
            revert SafeCastOverflowedUintDowncast(96, value);
        }
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        if (value > type(uint88).max) {
            revert SafeCastOverflowedUintDowncast(88, value);
        }
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        if (value > type(uint80).max) {
            revert SafeCastOverflowedUintDowncast(80, value);
        }
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        if (value > type(uint72).max) {
            revert SafeCastOverflowedUintDowncast(72, value);
        }
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        if (value > type(uint64).max) {
            revert SafeCastOverflowedUintDowncast(64, value);
        }
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        if (value > type(uint56).max) {
            revert SafeCastOverflowedUintDowncast(56, value);
        }
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        if (value > type(uint48).max) {
            revert SafeCastOverflowedUintDowncast(48, value);
        }
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        if (value > type(uint40).max) {
            revert SafeCastOverflowedUintDowncast(40, value);
        }
        return uint40(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        if (value > type(uint32).max) {
            revert SafeCastOverflowedUintDowncast(32, value);
        }
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        if (value > type(uint24).max) {
            revert SafeCastOverflowedUintDowncast(24, value);
        }
        return uint24(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        if (value > type(uint16).max) {
            revert SafeCastOverflowedUintDowncast(16, value);
        }
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        if (value > type(uint8).max) {
            revert SafeCastOverflowedUintDowncast(8, value);
        }
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        if (value < 0) {
            revert SafeCastOverflowedIntToUint(value);
        }
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     */
    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(248, value);
        }
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     */
    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(240, value);
        }
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     */
    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(232, value);
        }
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(224, value);
        }
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     */
    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(216, value);
        }
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     */
    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(208, value);
        }
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     */
    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(200, value);
        }
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     */
    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(192, value);
        }
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     */
    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(184, value);
        }
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     */
    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(176, value);
        }
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     */
    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(168, value);
        }
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     */
    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(160, value);
        }
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     */
    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(152, value);
        }
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     */
    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(144, value);
        }
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     */
    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(136, value);
        }
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(128, value);
        }
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     */
    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(120, value);
        }
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     */
    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(112, value);
        }
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     */
    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(104, value);
        }
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(96, value);
        }
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     */
    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(88, value);
        }
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     */
    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(80, value);
        }
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     */
    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(72, value);
        }
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(64, value);
        }
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     */
    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(56, value);
        }
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     */
    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(48, value);
        }
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     */
    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(40, value);
        }
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(32, value);
        }
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     */
    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(24, value);
        }
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(16, value);
        }
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     */
    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(8, value);
        }
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        if (value > uint256(type(int256).max)) {
            revert SafeCastOverflowedUintToInt(value);
        }
        return int256(value);
    }

    /**
     * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
     */
    function toUint(bool b) internal pure returns (uint256 u) {
        assembly ("memory-safe") {
            u := iszero(iszero(b))
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.20;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS
    }

    /**
     * @dev The signature derives the `address(0)`.
     */
    error ECDSAInvalidSignature();

    /**
     * @dev The signature has an invalid length.
     */
    error ECDSAInvalidSignatureLength(uint256 length);

    /**
     * @dev The signature has an S value that is in the upper half order.
     */
    error ECDSAInvalidSignatureS(bytes32 s);

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
     * return address(0) without also returning an error description. Errors are documented using an enum (error type)
     * and a bytes32 providing additional information about the error.
     *
     * If no error is returned, then the address can be used for verification purposes.
     *
     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     */
    function tryRecover(
        bytes32 hash,
        bytes memory signature
    ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly ("memory-safe") {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures]
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
        unchecked {
            bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
            // We do not check for an overflow here since the shift operation results in 0 or 1.
            uint8 v = uint8((uint256(vs) >> 255) + 27);
            return tryRecover(hash, v, r, s);
        }
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     */
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS, s);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature, bytes32(0));
        }

        return (signer, RecoverError.NoError, bytes32(0));
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
     */
    function _throwError(RecoverError error, bytes32 errorArg) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert ECDSAInvalidSignature();
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert ECDSAInvalidSignatureLength(uint256(errorArg));
        } else if (error == RecoverError.InvalidSignatureS) {
            revert ECDSAInvalidSignatureS(errorArg);
        }
    }
}

/**
 ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.
 ** Only one instance required on each chain.
 **/
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

/* solhint-disable avoid-low-level-calls */
/* solhint-disable no-inline-assembly */
/* solhint-disable reason-string */

import "./PackedUserOperation.sol";
import "./IStakeManager.sol";
import "./IAggregator.sol";
import "./INonceManager.sol";
import "./ISenderCreator.sol";

interface IEntryPoint is IStakeManager, INonceManager {
    /***
     * An event emitted after each successful request.
     * @param userOpHash    - Unique identifier for the request (hash its entire content, except signature).
     * @param sender        - The account that generates this request.
     * @param paymaster     - If non-null, the paymaster that pays for this request.
     * @param nonce         - The nonce value from the request.
     * @param success       - True if the sender transaction succeeded, false if reverted.
     * @param actualGasCost - Actual amount paid (by account or paymaster) for this UserOperation.
     * @param actualGasUsed - Total gas used by this UserOperation (including preVerification, creation,
     *                        validation and execution).
     */
    event UserOperationEvent(
        bytes32 indexed userOpHash,
        address indexed sender,
        address indexed paymaster,
        uint256 nonce,
        bool success,
        uint256 actualGasCost,
        uint256 actualGasUsed
    );

    /**
     * Account "sender" was deployed.
     * @param userOpHash - The userOp that deployed this account. UserOperationEvent will follow.
     * @param sender     - The account that is deployed
     * @param factory    - The factory used to deploy this account (in the initCode)
     * @param paymaster  - The paymaster used by this UserOp
     */
    event AccountDeployed(
        bytes32 indexed userOpHash,
        address indexed sender,
        address factory,
        address paymaster
    );

    /**
     * An event emitted if the UserOperation "callData" reverted with non-zero length.
     * @param userOpHash   - The request unique identifier.
     * @param sender       - The sender of this request.
     * @param nonce        - The nonce used in the request.
     * @param revertReason - The return bytes from the reverted "callData" call.
     */
    event UserOperationRevertReason(
        bytes32 indexed userOpHash,
        address indexed sender,
        uint256 nonce,
        bytes revertReason
    );

    /**
     * An event emitted if the UserOperation Paymaster's "postOp" call reverted with non-zero length.
     * @param userOpHash   - The request unique identifier.
     * @param sender       - The sender of this request.
     * @param nonce        - The nonce used in the request.
     * @param revertReason - The return bytes from the reverted call to "postOp".
     */
    event PostOpRevertReason(
        bytes32 indexed userOpHash,
        address indexed sender,
        uint256 nonce,
        bytes revertReason
    );

    /**
     * UserOp consumed more than prefund. The UserOperation is reverted, and no refund is made.
     * @param userOpHash   - The request unique identifier.
     * @param sender       - The sender of this request.
     * @param nonce        - The nonce used in the request.
     */
    event UserOperationPrefundTooLow(
        bytes32 indexed userOpHash,
        address indexed sender,
        uint256 nonce
    );

    /**
     * An event emitted by handleOps() and handleAggregatedOps(), before starting the execution loop.
     * Any event emitted before this event, is part of the validation.
     */
    event BeforeExecution();

    /**
     * Signature aggregator used by the following UserOperationEvents within this bundle.
     * @param aggregator - The aggregator used for the following UserOperationEvents.
     */
    event SignatureAggregatorChanged(address indexed aggregator);

    /**
     * A custom revert error of handleOps andhandleAggregatedOps, to identify the offending op.
     * Should be caught in off-chain handleOps/handleAggregatedOps simulation and not happen on-chain.
     * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.
     * NOTE: If simulateValidation passes successfully, there should be no reason for handleOps to fail on it.
     * @param opIndex - Index into the array of ops to the failed one (in simulateValidation, this is always zero).
     * @param reason  - Revert reason. The string starts with a unique code "AAmn",
     *                  where "m" is "1" for factory, "2" for account and "3" for paymaster issues,
     *                  so a failure can be attributed to the correct entity.
     */
    error FailedOp(uint256 opIndex, string reason);

    /**
     * A custom revert error of handleOps and handleAggregatedOps, to report a revert by account or paymaster.
     * @param opIndex - Index into the array of ops to the failed one (in simulateValidation, this is always zero).
     * @param reason  - Revert reason. see FailedOp(uint256,string), above
     * @param inner   - data from inner cought revert reason
     * @dev note that inner is truncated to 2048 bytes
     */
    error FailedOpWithRevert(uint256 opIndex, string reason, bytes inner);

    error PostOpReverted(bytes returnData);

    /**
     * Error case when a signature aggregator fails to verify the aggregated signature it had created.
     * @param aggregator The aggregator that failed to verify the signature
     */
    error SignatureValidationFailed(address aggregator);

    // Return value of getSenderAddress.
    error SenderAddressResult(address sender);

    // UserOps handled, per aggregator.
    struct UserOpsPerAggregator {
        PackedUserOperation[] userOps;
        // Aggregator address
        IAggregator aggregator;
        // Aggregated signature
        bytes signature;
    }

    /**
     * Execute a batch of UserOperations.
     * No signature aggregator is used.
     * If any account requires an aggregator (that is, it returned an aggregator when
     * performing simulateValidation), then handleAggregatedOps() must be used instead.
     * @param ops         - The operations to execute.
     * @param beneficiary - The address to receive the fees.
     */
    function handleOps(
        PackedUserOperation[] calldata ops,
        address payable beneficiary
    ) external;

    /**
     * Execute a batch of UserOperation with Aggregators
     * @param opsPerAggregator - The operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts).
     * @param beneficiary      - The address to receive the fees.
     */
    function handleAggregatedOps(
        UserOpsPerAggregator[] calldata opsPerAggregator,
        address payable beneficiary
    ) external;

    /**
     * Generate a request Id - unique identifier for this request.
     * The request ID is a hash over the content of the userOp (except the signature), entrypoint address, chainId and (optionally) 7702 delegate address
     * @param userOp - The user operation to generate the request ID for.
     * @return hash the hash of this UserOperation
     */
    function getUserOpHash(
        PackedUserOperation calldata userOp
    ) external view returns (bytes32);

    /**
     * Gas and return values during simulation.
     * @param preOpGas         - The gas used for validation (including preValidationGas)
     * @param prefund          - The required prefund for this operation
     * @param accountValidationData   - returned validationData from account.
     * @param paymasterValidationData - return validationData from paymaster.
     * @param paymasterContext - Returned by validatePaymasterUserOp (to be passed into postOp)
     */
    struct ReturnInfo {
        uint256 preOpGas;
        uint256 prefund;
        uint256 accountValidationData;
        uint256 paymasterValidationData;
        bytes paymasterContext;
    }

    /**
     * Get counterfactual sender address.
     * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.
     * This method always revert, and returns the address in SenderAddressResult error.
     * @notice this method cannot be used for EIP-7702 derived contracts.
     *
     * @param initCode - The constructor code to be passed into the UserOperation.
     */
    function getSenderAddress(bytes memory initCode) external;

    error DelegateAndRevert(bool success, bytes ret);

    /**
     * Helper method for dry-run testing.
     * @dev calling this method, the EntryPoint will make a delegatecall to the given data, and report (via revert) the result.
     *  The method always revert, so is only useful off-chain for dry run calls, in cases where state-override to replace
     *  actual EntryPoint code is less convenient.
     * @param target a target contract to make a delegatecall from entrypoint
     * @param data data to pass to target in a delegatecall
     */
    function delegateAndRevert(address target, bytes calldata data) external;

    /**
     * @notice Retrieves the immutable SenderCreator contract which is responsible for deployment of sender contracts.
     */
    function senderCreator() external view returns (ISenderCreator);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
 * consider using {ReentrancyGuardTransient} instead.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        _status = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.20;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```solidity
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 *
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Storage of the initializable contract.
     *
     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
     * when using with upgradeable contracts.
     *
     * @custom:storage-location erc7201:openzeppelin.storage.Initializable
     */
    struct InitializableStorage {
        /**
         * @dev Indicates that the contract has been initialized.
         */
        uint64 _initialized;
        /**
         * @dev Indicates that the contract is in the process of being initialized.
         */
        bool _initializing;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;

    /**
     * @dev The contract is already initialized.
     */
    error InvalidInitialization();

    /**
     * @dev The contract is not initializing.
     */
    error NotInitializing();

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint64 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
     * production.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        // Cache values to avoid duplicated sloads
        bool isTopLevelCall = !$._initializing;
        uint64 initialized = $._initialized;

        // Allowed calls:
        // - initialSetup: the contract is not in the initializing state and no previous version was
        //                 initialized
        // - construction: the contract is initialized at version 1 (no reinitialization) and the
        //                 current contract is just being deployed
        bool initialSetup = initialized == 0 && isTopLevelCall;
        bool construction = initialized == 1 && address(this).code.length == 0;

        if (!initialSetup && !construction) {
            revert InvalidInitialization();
        }
        $._initialized = 1;
        if (isTopLevelCall) {
            $._initializing = true;
        }
        _;
        if (isTopLevelCall) {
            $._initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint64 version) {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing || $._initialized >= version) {
            revert InvalidInitialization();
        }
        $._initialized = version;
        $._initializing = true;
        _;
        $._initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        _checkInitializing();
        _;
    }

    /**
     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
     */
    function _checkInitializing() internal view virtual {
        if (!_isInitializing()) {
            revert NotInitializing();
        }
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing) {
            revert InvalidInitialization();
        }
        if ($._initialized != type(uint64).max) {
            $._initialized = type(uint64).max;
            emit Initialized(type(uint64).max);
        }
    }

    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint64) {
        return _getInitializableStorage()._initialized;
    }

    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _getInitializableStorage()._initializing;
    }

    /**
     * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.
     *
     * NOTE: Consider following the ERC-7201 formula to derive storage locations.
     */
    function _initializableStorageSlot() internal pure virtual returns (bytes32) {
        return INITIALIZABLE_STORAGE;
    }

    /**
     * @dev Returns a pointer to the storage namespace.
     */
    // solhint-disable-next-line var-name-mixedcase
    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
        bytes32 slot = _initializableStorageSlot();
        assembly {
            $.slot := slot
        }
    }
}

File 13 of 31 : PackedUserOperation.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

/**
 * 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.28;

/* solhint-disable no-inline-assembly */


 /*
  * For simulation purposes, validateUserOp (and validatePaymasterUserOp)
  * must return this value in case of signature failure, instead of revert.
  */
uint256 constant SIG_VALIDATION_FAILED = 1;


/*
 * For simulation purposes, validateUserOp (and validatePaymasterUserOp)
 * return this value on success.
 */
uint256 constant SIG_VALIDATION_SUCCESS = 0;


/**
 * Returned data from validateUserOp.
 * validateUserOp returns a uint256, which is created by `_packedValidationData` and
 * parsed by `_parseValidationData`.
 * @param aggregator  - address(0) - The account validated the signature by itself.
 *                      address(1) - The account failed to validate the signature.
 *                      otherwise - This is an address of a signature aggregator that must
 *                                  be used to validate the signature.
 * @param validAfter  - This UserOp is valid only after this timestamp.
 * @param validUntil - Last timestamp this operation is valid at, or 0 for "indefinitely".
 */
struct ValidationData {
    address aggregator;
    uint48 validAfter;
    uint48 validUntil;
}

/**
 * Extract aggregator/sigFailed, validAfter, validUntil.
 * Also convert zero validUntil to type(uint48).max.
 * @param validationData - The packed validation data.
 * @return data - The unpacked in-memory validation data.
 */
function _parseValidationData(
    uint256 validationData
) pure returns (ValidationData memory data) {
    address aggregator = address(uint160(validationData));
    uint48 validUntil = uint48(validationData >> 160);
    if (validUntil == 0) {
        validUntil = type(uint48).max;
    }
    uint48 validAfter = uint48(validationData >> (48 + 160));
    return ValidationData(aggregator, validAfter, validUntil);
}

/**
 * Helper to pack the return value for validateUserOp.
 * @param data - The ValidationData to pack.
 * @return the packed validation data.
 */
function _packValidationData(
    ValidationData memory data
) pure returns (uint256) {
    return
        uint160(data.aggregator) |
        (uint256(data.validUntil) << 160) |
        (uint256(data.validAfter) << (160 + 48));
}

/**
 * Helper to pack the return value for validateUserOp, when not using an aggregator.
 * @param sigFailed  - True for signature failure, false for success.
 * @param validUntil - Last timestamp this operation is valid at, or 0 for "indefinitely".
 * @param validAfter - First timestamp this UserOperation is valid.
 * @return the packed validation data.
 */
function _packValidationData(
    bool sigFailed,
    uint48 validUntil,
    uint48 validAfter
) pure returns (uint256) {
    return
        (sigFailed ?  SIG_VALIDATION_FAILED : SIG_VALIDATION_SUCCESS) |
        (uint256(validUntil) << 160) |
        (uint256(validAfter) << (160 + 48));
}

/**
 * keccak function over calldata.
 * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.
 *
 * @param data - the calldata bytes array to perform keccak on.
 * @return ret - the keccak hash of the 'data' array.
 */
    function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {
        assembly ("memory-safe") {
            let mem := mload(0x40)
            let len := data.length
            calldatacopy(mem, data.offset, len)
            ret := keccak256(mem, len)
        }
    }


/**
 * The minimum of two numbers.
 * @param a - First number.
 * @param b - Second number.
 * @return - the minimum value.
 */
    function min(uint256 a, uint256 b) pure returns (uint256) {
        return a < b ? a : b;
    }

/**
 * standard solidity memory allocation finalization.
 * copied from solidity generated code
 * @param memPointer - The current memory pointer
 * @param allocationSize - Bytes allocated from memPointer.
 */
    function finalizeAllocation(uint256 memPointer, uint256 allocationSize) pure {

        assembly ("memory-safe"){
            finalize_allocation(memPointer, allocationSize)

            function finalize_allocation(memPtr, size) {
                let newFreePtr := add(memPtr, round_up_to_mul_of_32(size))
                mstore(64, newFreePtr)
            }

            function round_up_to_mul_of_32(value) -> result {
                result := and(add(value, 31), not(31))
            }
        }
    }

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;

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

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/IERC1271.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-1271 standard signature validation method for
 * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
 */
interface IERC1271 {
    /**
     * @dev Should return whether the signature provided is valid for the provided data
     * @param hash      Hash of the data to be signed
     * @param signature Signature byte array associated with `hash`
     */
    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/utils/ERC1155Holder.sol)

pragma solidity ^0.8.20;

import {IERC165, ERC165} from "../../../utils/introspection/ERC165.sol";
import {IERC1155Receiver} from "../IERC1155Receiver.sol";

/**
 * @dev Simple implementation of `IERC1155Receiver` that will allow a contract to hold ERC-1155 tokens.
 *
 * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be
 * stuck.
 */
abstract contract ERC1155Holder is ERC165, IERC1155Receiver {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
    }

    function onERC1155Received(
        address,
        address,
        uint256,
        uint256,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155Received.selector;
    }

    function onERC1155BatchReceived(
        address,
        address,
        uint256[] memory,
        uint256[] memory,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155BatchReceived.selector;
    }
}

File 18 of 31 : ERC721Holder.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/utils/ERC721Holder.sol)

pragma solidity ^0.8.20;

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

/**
 * @dev Implementation of the {IERC721Receiver} interface.
 *
 * Accepts all token transfers.
 * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or
 * {IERC721-setApprovalForAll}.
 */
abstract contract ERC721Holder is IERC721Receiver {
    /**
     * @dev See {IERC721Receiver-onERC721Received}.
     *
     * Always returns `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) {
        return this.onERC721Received.selector;
    }
}

File 19 of 31 : ISessionKey.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.29;

import {SpendLimit} from "src/utils/SpendLimit.sol";

interface ISessionKey {
    /**
     * @notice Types of session keys supported by the contract
     * @param EOA Standard Ethereum account key
     * @param WEBAUTHN WebAuthn-based key (using P256 curve)
     */
    enum KeyType {
        EOA,
        WEBAUTHN
    }

    /**
     * @notice Public key structure for P256 curve used in WebAuthn
     * @param x X-coordinate of the public key
     * @param y Y-coordinate of the public key
     */
    struct PubKey {
        bytes32 x;
        bytes32 y;
    }

    /**
     * @notice Key structure containing all necessary key information
     * @param pubKey Public key information for WebAuthn keys
     * @param eoaAddress EOA address for standard Ethereum accounts
     * @param keyType Type of the key (EOA or WebAuthn)
     */
    struct Key {
        PubKey pubKey;
        address eoaAddress;
        KeyType keyType;
    }

    /**
     * @notice Session key data structure containing permissions and limits
     * @param pubKey Public key information
     * @param isActive Whether the session key is currently active
     * @param validUntil Timestamp until which the key is valid
     * @param validAfter Timestamp after which the key becomes valid
     * @param limit Number of transactions allowed (0 for unlimited/master key)
     * @param masterSessionKey Whether this is a master session key with unlimited permissions
     * @param whitelisting Whether contract address whitelisting is enabled
     * @param whitelist Mapping of whitelisted contract addresses
     * @param spendTokenInfo Token spending limit information
     * @param allowedSelectors List of allowed function selectors
     * @param ethLimit Maximum amount of ETH that can be spent
     * @param whoRegistrated Address that registered this session key
     */
    struct SessionKey {
        PubKey pubKey;
        bool isActive;
        uint48 validUntil;
        uint48 validAfter;
        uint48 limit;
        bool masterSessionKey;
        bool whitelisting;
        mapping(address contractAddress => bool allowed) whitelist;
        SpendLimit.SpendTokenInfo spendTokenInfo;
        bytes4[] allowedSelectors;
        uint256 ethLimit;
        address whoRegistrated;
    }
}

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

import {Base64} from "src/libs/Base64.sol";
import {P256} from "src/libs/P256.sol";

/// @notice WebAuthn helper.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/WebAuthn.sol)
/// @author Modified from Daimo WebAuthn (https://github.com/daimo-eth/p256-verifier/blob/master/src/WebAuthn.sol)
/// @author Modified from Coinbase WebAuthn (https://github.com/base-org/webauthn-sol/blob/main/src/WebAuthn.sol)
library WebAuthn {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STRUCTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Helps make encoding and decoding easier, alleviates stack-too-deep.
    struct WebAuthnAuth {
        // The WebAuthn authenticator data.
        // See: https://www.w3.org/TR/webauthn-2/#dom-authenticatorassertionresponse-authenticatordata.
        bytes authenticatorData;
        // The WebAuthn client data JSON.
        // See: https://www.w3.org/TR/webauthn-2/#dom-authenticatorresponse-clientdatajson.
        string clientDataJSON;
        // Start index of "challenge":"..." in `clientDataJSON`.
        uint256 challengeIndex;
        // Start index of "type":"..." in `clientDataJSON`.
        uint256 typeIndex;
        // The r value of secp256r1 signature.
        bytes32 r;
        // The s value of secp256r1 signature.
        bytes32 s;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*              WEBAUTHN VERIFICATION OPERATIONS              */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Verifies a Webauthn Authentication Assertion.
    /// See: https://www.w3.org/TR/webauthn-2/#sctn-verifying-assertion.
    ///
    /// We do not verify all the steps as described in the specification, only ones
    /// relevant to our context. Please carefully read through this list before usage.
    ///
    /// Specifically, we do verify the following:
    /// - Verify that `authenticatorData` (which comes from the authenticator,
    ///   such as iCloud Keychain) indicates a well-formed assertion with the
    ///   "User Present" bit set. If `requireUserVerification` is set, checks that the
    ///   authenticator enforced user verification. User verification should be required
    ///   if, and only if, `options.userVerification` is set to required in the request.
    /// - Verifies that the client JSON is of type "webauthn.get",
    ///   i.e. the client was responding to a request to assert authentication.
    /// - Verifies that the client JSON contains the requested challenge.
    /// - Verifies that (r, s) constitute a valid signature over both the
    ///   `authData` and client JSON, for public key (x, y).
    ///
    /// We make some assumptions about the particular use case of this verifier,
    /// so we do NOT verify the following:
    /// - Does NOT verify that the origin in the `clientDataJSON` matches the
    ///   Relying Party's origin: it is considered the authenticator's responsibility to
    ///   ensure that the user is interacting with the correct RP. This is enforced by
    ///   most high quality authenticators properly, particularly the iCloud Keychain
    ///   and Google Password Manager were tested.
    /// - Does NOT verify That `topOrigin` in `clientDataJSON` is well-formed:
    ///   We assume it would never be present, i.e. the credentials are never used in a
    ///   cross-origin/iframe context. The website/app set up should disallow cross-origin
    ///   usage of the credentials. This is the default behavior for created credentials
    ///   in common settings.
    /// - Does NOT verify that the `rpIdHash` in `authenticatorData` is the SHA-256 hash
    ///   of the RP ID expected by the Relying Party:
    ///   this means that we rely on the authenticator to properly enforce
    ///   credentials to be used only by the correct RP.
    ///   This is generally enforced with features like Apple App Site Association
    ///   and Google Asset Links. To protect from edge cases in which a previously-linked
    ///   RP ID is removed from the authorized RP IDs, we recommend that messages
    ///   signed by the authenticator include some expiry mechanism.
    /// - Does NOT verify the credential backup state: this assumes the credential backup
    ///   state is NOT used as part of Relying Party business logic or policy.
    /// - Does NOT verify the values of the client extension outputs:
    ///   this assumes that the Relying Party does not use client extension outputs.
    /// - Does NOT verify the signature counter: signature counters are intended to enable
    ///   risk scoring for the Relying Party. This assumes risk scoring is not used as part
    ///   of Relying Party business logic or policy.
    /// - Does NOT verify the attestation object: this assumes that
    ///   response.attestationObject is NOT present in the response,
    ///   i.e. the RP does not intend to verify an attestation.
    function verify(
        bytes memory challenge,
        bool requireUserVerification,
        WebAuthnAuth memory auth,
        bytes32 x,
        bytes32 y
    ) internal view returns (bool result) {
        bytes32 messageHash;
        string memory encoded = Base64.encode(challenge, true, true);
        /// @solidity memory-safe-assembly
        assembly {
            let clientDataJSON := mload(add(auth, 0x20))
            let n := mload(clientDataJSON) // `clientDataJSON`'s length.
            let o := add(clientDataJSON, 0x20) // Start of `clientData`'s bytes.
            {
                let c := mload(add(auth, 0x40)) // Challenge index in `clientDataJSON`.
                let t := mload(add(auth, 0x60)) // Type index in `clientDataJSON`.
                let l := mload(encoded) // Cache `encoded`'s length.
                let q := add(l, 0x0d) // Length of `encoded` prefixed with '"challenge":"'.
                mstore(encoded, shr(152, '"challenge":"')) // Temp prefix with '"challenge":"'.
                result :=
                    and(
                        // 11. Verify JSON's type. Also checks for possible addition overflows.
                        and(
                            eq(shr(88, mload(add(o, t))), shr(88, '"type":"webauthn.get"')),
                            lt(shr(128, or(t, c)), lt(add(0x14, t), n))
                        ),
                        // 12. Verify JSON's challenge. Includes a check for the closing '"'.
                        and(
                            eq(keccak256(add(o, c), q), keccak256(add(encoded, 0x13), q)),
                            and(eq(byte(0, mload(add(add(o, c), q))), 34), lt(add(q, c), n))
                        )
                    )
                mstore(encoded, l) // Restore `encoded`'s length, in case of string interning.
            }
            // Skip 13., 14., 15.
            let l := mload(mload(auth)) // Length of `authenticatorData`.
            // 16. Verify that the "User Present" flag is set (bit 0).
            // 17. Verify that the "User Verified" flag is set (bit 2), if required.
            // See: https://www.w3.org/TR/webauthn-2/#flags.
            let u := or(1, shl(2, iszero(iszero(requireUserVerification))))
            result := and(and(result, gt(l, 0x20)), eq(and(mload(add(mload(auth), 0x21)), u), u))
            if result {
                let p := add(mload(auth), 0x20) // Start of `authenticatorData`'s bytes.
                let e := add(p, l) // Location of the word after `authenticatorData`.
                let w := mload(e) // Cache the word after `authenticatorData`.
                // 19. Compute `sha256(clientDataJSON)`.
                // 20. Compute `sha256(authenticatorData ‖ sha256(clientDataJSON))`.
                // forgefmt: disable-next-item
                messageHash := mload(staticcall(gas(),
                    shl(1, staticcall(gas(), 2, o, n, e, 0x20)), p, add(l, 0x20), 0x01, 0x20))
                mstore(e, w) // Restore the word after `authenticatorData`, in case of reuse.
                // `returndatasize()` is `0x20` on `sha256` success, and `0x00` otherwise.
                if iszero(returndatasize()) { invalid() }
            }
        }
        // `P256.verifySignature` returns false if `s > N/2` due to the malleability check.
        if (result) result = P256.verifySignature(messageHash, auth.r, auth.s, x, y);
    }

    /// @dev Plain variant of verify.
    function verify(
        bytes memory challenge,
        bool requireUserVerification,
        bytes memory authenticatorData,
        string memory clientDataJSON,
        uint256 challengeIndex,
        uint256 typeIndex,
        bytes32 r,
        bytes32 s,
        bytes32 x,
        bytes32 y
    ) internal view returns (bool) {
        return verify(
            challenge,
            requireUserVerification,
            WebAuthnAuth(authenticatorData, clientDataJSON, challengeIndex, typeIndex, r, s),
            x,
            y
        );
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                ENCODING / DECODING HELPERS                 */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `abi.encode(auth)`.
    function encodeAuth(WebAuthnAuth memory auth) internal pure returns (bytes memory) {
        return abi.encode(auth);
    }

    /// @dev Performs a best-effort attempt to `abi.decode(auth)`. Won't revert.
    /// If any fields cannot be successfully extracted, `decoded` will not be populated,
    /// which will cause `verify` to return false (as `clientDataJSON` is empty).
    function tryDecodeAuth(bytes memory encodedAuth) internal pure returns (WebAuthnAuth memory decoded) {
        /// @solidity memory-safe-assembly
        assembly {
            for { let n := mload(encodedAuth) } iszero(lt(n, 0xc0)) {} {
                let o := add(encodedAuth, 0x20) // Start of `encodedAuth`'s bytes.
                let e := add(o, n) // End of `encodedAuth` in memory.
                let p := add(mload(o), o) // Start of `encodedAuth`.
                if or(gt(add(p, 0xc0), e), lt(p, o)) { break }
                let authenticatorData := add(mload(p), p)
                let clientDataJSON := add(mload(add(p, 0x20)), p)
                if or(
                    or(gt(authenticatorData, e), lt(authenticatorData, p)),
                    or(gt(clientDataJSON, e), lt(clientDataJSON, p))
                ) { break }
                if or(
                    gt(add(add(authenticatorData, 0x20), mload(authenticatorData)), e),
                    gt(add(add(clientDataJSON, 0x20), mload(clientDataJSON)), e)
                ) { break }
                mstore(decoded, authenticatorData) // `authenticatorData`.
                mstore(add(decoded, 0x20), clientDataJSON) // `clientDataJSON`.
                mstore(add(decoded, 0x40), mload(add(p, 0x40))) // `challengeIndex`.
                mstore(add(decoded, 0x60), mload(add(p, 0x60))) // `typeIndex`.
                mstore(add(decoded, 0x80), mload(add(p, 0x80))) // `r`.
                mstore(add(decoded, 0xa0), mload(add(p, 0xa0))) // `s`.
                break
            }
        }
    }

    /// @dev Returns the compact encoding of `auth`:
    /// ```
    ///     abi.encodePacked(
    ///         uint16(auth.authenticatorData.length),
    ///         bytes(auth.authenticatorData),
    ///         bytes(auth.clientDataJSON),
    ///         uint16(auth.challengeIndex),
    ///         uint16(auth.typeIndex),
    ///         bytes32(auth.r),
    ///         bytes32(auth.s)
    ///     )
    /// ```
    /// Returns the empty string if any length or index exceeds 16 bits.
    function tryEncodeAuthCompact(WebAuthnAuth memory auth) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            function copyBytes(o_, s_, c_) -> _e {
                mstore(o_, shl(240, mload(s_)))
                o_ := add(o_, c_)
                _e := add(o_, mload(s_)) // The end of the bytes.
                for { let d_ := sub(add(0x20, s_), o_) } 1 {} {
                    mstore(o_, mload(add(d_, o_)))
                    o_ := add(o_, 0x20)
                    if iszero(lt(o_, _e)) { break }
                }
            }
            let clientDataJSON := mload(add(0x20, auth))
            let c := mload(add(0x40, auth)) // `challengeIndex`.
            let t := mload(add(0x60, auth)) // `typeIndex`.
            // If none of the lengths are more than `0xffff`.
            if iszero(shr(16, or(or(t, c), or(mload(mload(auth)), mload(clientDataJSON))))) {
                result := mload(0x40)
                // `authenticatorData`, `clientDataJSON`.
                let o := copyBytes(copyBytes(add(result, 0x20), mload(auth), 2), clientDataJSON, 0)
                mstore(o, or(shl(240, c), shl(224, t))) // `challengeIndex`, `typeIndex`.
                mstore(add(o, 0x04), mload(add(0x80, auth))) // `r`.
                mstore(add(o, 0x24), mload(add(0xa0, auth))) // `s`.
                mstore(result, sub(add(o, 0x24), result)) // Store the length.
                mstore(add(o, 0x44), 0) // Zeroize the slot after the string.
                mstore(0x40, add(o, 0x64)) // Allocate memory .
            }
        }
    }

    /// @dev Approximately the same gas as `tryDecodeAuth`, but helps save on calldata.
    /// If any fields cannot be successfully extracted, `decoded` will not be populated,
    /// which will cause `verify` to return false (as `clientDataJSON` is empty).
    function tryDecodeAuthCompact(bytes memory encodedAuth) internal pure returns (WebAuthnAuth memory decoded) {
        /// @solidity memory-safe-assembly
        assembly {
            function extractBytes(o_, l_) -> _m {
                _m := mload(0x40) // Grab the free memory pointer.
                let s_ := add(_m, 0x20)
                for { let i_ := 0 } 1 {} {
                    mstore(add(s_, i_), mload(add(o_, i_)))
                    i_ := add(i_, 0x20)
                    if iszero(lt(i_, l_)) { break }
                }
                mstore(_m, l_) // Store the length.
                mstore(add(l_, s_), 0) // Zeroize the slot after the string.
                mstore(0x40, add(0x20, add(l_, s_))) // Allocate memory.
            }
            let n := mload(encodedAuth)
            if iszero(lt(n, 0x46)) {
                let o := add(encodedAuth, 0x20) // Start of `encodedAuth`'s bytes.
                let e := add(o, n) // End of `encodedAuth` in memory.
                n := shr(240, mload(o)) // Length of `authenticatorData`.
                let a := add(o, 0x02) // Start of `authenticatorData`.
                let c := add(a, n) // Start of `clientDataJSON`.
                let j := sub(e, 0x44) // Start of `challengeIndex`.
                if iszero(gt(c, j)) {
                    mstore(decoded, extractBytes(a, n)) // `authenticatorData`.
                    mstore(add(decoded, 0x20), extractBytes(c, sub(j, c))) // `clientDataJSON`.
                    mstore(add(decoded, 0x40), shr(240, mload(j))) // `challengeIndex`.
                    mstore(add(decoded, 0x60), shr(240, mload(add(j, 0x02)))) // `typeIndex`.
                    mstore(add(decoded, 0x80), mload(add(j, 0x04))) // `r`.
                    mstore(add(decoded, 0xa0), mload(add(j, 0x24))) // `s`.
                }
            }
        }
    }

    /// @dev Calldata variant of `tryDecodeAuthCompact`.
    function tryDecodeAuthCompactCalldata(bytes calldata encodedAuth)
        internal
        pure
        returns (WebAuthnAuth memory decoded)
    {
        /// @solidity memory-safe-assembly
        assembly {
            function extractBytes(o_, l_) -> _m {
                _m := mload(0x40) // Grab the free memory pointer.
                let s_ := add(_m, 0x20)
                calldatacopy(s_, o_, l_)
                mstore(_m, l_) // Store the length.
                mstore(add(l_, s_), 0) // Zeroize the slot after the string.
                mstore(0x40, add(0x20, add(l_, s_))) // Allocate memory.
            }
            if iszero(lt(encodedAuth.length, 0x46)) {
                let e := add(encodedAuth.offset, encodedAuth.length) // End of `encodedAuth`.
                let n := shr(240, calldataload(encodedAuth.offset)) // Length of `authenticatorData`.
                let a := add(encodedAuth.offset, 0x02) // Start of `authenticatorData`.
                let c := add(a, n) // Start of `clientDataJSON`.
                let j := sub(e, 0x44) // Start of `challengeIndex`.
                if iszero(gt(c, j)) {
                    mstore(decoded, extractBytes(a, n)) // `authenticatorData`.
                    mstore(add(decoded, 0x20), extractBytes(c, sub(j, c))) // `clientDataJSON`.
                    mstore(add(decoded, 0x40), shr(240, calldataload(j))) // `challengeIndex`.
                    mstore(add(decoded, 0x60), shr(240, calldataload(add(j, 0x02)))) // `typeIndex`.
                    mstore(add(decoded, 0x80), calldataload(add(j, 0x04))) // `r`.
                    mstore(add(decoded, 0xa0), calldataload(add(j, 0x24))) // `s`.
                }
            }
        }
    }
}

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

/// @notice Gas optimized P256 wrapper.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/P256.sol)
/// @author Modified from Daimo P256 Verifier (https://github.com/daimo-eth/p256-verifier/blob/master/src/P256.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/P256.sol)
library P256 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CUSTOM ERRORS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Unable to verify the P256 signature, due to missing
    /// RIP-7212 P256 verifier precompile and missing Solidity P256 verifier.
    error P256VerificationFailed();

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

    /// @dev Address of the Solidity P256 verifier.
    /// Please make sure the contract is deployed onto the chain you are working on.
    /// See: https://gist.github.com/Vectorized/599b0d8a94d21bc74700eb1354e2f55c
    /// Unlike RIP-7212, this verifier returns `uint256(0)` on failure, to
    /// facilitate easier existence check. This verifier will also never revert.
    address internal constant VERIFIER = 0x000000000000D01eA45F9eFD5c54f037Fa57Ea1a;

    /// @dev Address of the RIP-7212 P256 verifier precompile.
    /// Currently, we don't support EIP-7212's precompile at 0x0b as it has not been finalized.
    /// See: https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md
    address internal constant RIP_PRECOMPILE = 0x0000000000000000000000000000000000000100;

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

    /// @dev `N/2`. Used for checking the malleability of the signature.
    uint256 private constant _HALF_N = 0x7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                P256 VERIFICATION OPERATIONS                */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns if the signature (`r`, `s`) is valid for `hash` and public key (`x`, `y`).
    /// Does NOT include the malleability check.
    function verifySignatureAllowMalleability(bytes32 hash, bytes32 r, bytes32 s, bytes32 x, bytes32 y)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, hash)
            mstore(add(m, 0x20), r)
            mstore(add(m, 0x40), s)
            mstore(add(m, 0x60), x)
            mstore(add(m, 0x80), y)
            mstore(0x00, 0) // Zeroize the return slot before the staticcalls.
            pop(staticcall(gas(), RIP_PRECOMPILE, m, 0xa0, 0x00, 0x20))
            // RIP-7212 dictates that success returns `uint256(1)`.
            // But failure returns zero returndata, which is ambiguous.
            if iszero(returndatasize()) {
                pop(staticcall(gas(), VERIFIER, m, 0xa0, returndatasize(), 0x20))
                // Unlike RIP-7212, the verifier returns `uint256(0)` on failure,
                // allowing us to use the returndatasize to determine existence.
                if iszero(returndatasize()) {
                    mstore(returndatasize(), 0xd0d5039b) // `P256VerificationFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            isValid := eq(1, mload(0x00))
        }
    }

    /// @dev Returns if the signature (`r`, `s`) is valid for `hash` and public key (`x`, `y`).
    /// Includes the malleability check.
    function verifySignature(bytes32 hash, bytes32 r, bytes32 s, bytes32 x, bytes32 y)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, hash)
            mstore(add(m, 0x20), r)
            mstore(add(m, 0x40), s)
            mstore(add(m, 0x60), x)
            mstore(add(m, 0x80), y)
            mstore(0x00, 0) // Zeroize the return slot before the staticcalls.
            pop(staticcall(gas(), RIP_PRECOMPILE, m, 0xa0, 0x00, 0x20))
            // RIP-7212 dictates that success returns `uint256(1)`.
            // But failure returns zero returndata, which is ambiguous.
            if iszero(returndatasize()) {
                pop(staticcall(gas(), VERIFIER, m, 0xa0, returndatasize(), 0x20))
                // Unlike RIP-7212, the verifier returns `uint256(0)` on failure,
                // allowing us to use the returndatasize to determine existence.
                if iszero(returndatasize()) {
                    mstore(returndatasize(), 0xd0d5039b) // `P256VerificationFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            // Optimize for happy path. Users are unlikely to pass in malleable signatures.
            isValid := lt(gt(s, _HALF_N), eq(1, mload(0x00)))
        }
    }

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

    /// @dev Returns `s` normalized to the lower half of the curve.
    function normalized(bytes32 s) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := xor(s, mul(xor(sub(N, s), s), gt(s, _HALF_N)))
        }
    }

    /// @dev Helper function for `abi.decode(encoded, (bytes32, bytes32))`.
    /// If `encoded.length < 64`, `(x, y)` will be `(0, 0)`, which is an invalid point.
    function tryDecodePoint(bytes memory encoded) internal pure returns (bytes32 x, bytes32 y) {
        /// @solidity memory-safe-assembly
        assembly {
            let t := gt(mload(encoded), 0x3f)
            x := mul(mload(add(encoded, 0x20)), t)
            y := mul(mload(add(encoded, 0x40)), t)
        }
    }

    /// @dev Helper function for `abi.decode(encoded, (bytes32, bytes32))`.
    /// If `encoded.length < 64`, `(x, y)` will be `(0, 0)`, which is an invalid point.
    function tryDecodePointCalldata(bytes calldata encoded) internal pure returns (bytes32 x, bytes32 y) {
        /// @solidity memory-safe-assembly
        assembly {
            let t := gt(encoded.length, 0x3f)
            x := mul(calldataload(encoded.offset), t)
            y := mul(calldataload(add(encoded.offset, 0x20)), t)
        }
    }
}

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

// solhint-disable no-inline-assembly

/**
 * Utility functions helpful when making different kinds of contract calls in Solidity.
 */
library Exec {

    function call(
        address to,
        uint256 value,
        bytes memory data,
        uint256 txGas
    ) internal returns (bool success) {
        assembly ("memory-safe") {
            success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)
        }
    }

    function staticcall(
        address to,
        bytes memory data,
        uint256 txGas
    ) internal view returns (bool success) {
        assembly ("memory-safe") {
            success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)
        }
    }

    function delegateCall(
        address to,
        bytes memory data,
        uint256 txGas
    ) internal returns (bool success) {
        assembly ("memory-safe") {
            success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)
        }
    }

    // get returned data from last call or delegateCall
    // maxLen - maximum length of data to return, or zero, for the full length
    function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {
        assembly ("memory-safe") {
            let len := returndatasize()
            if gt(maxLen,0) {
                if gt(len, maxLen) {
                    len := maxLen
                }
            }
            let ptr := mload(0x40)
            mstore(0x40, add(ptr, add(len, 0x20)))
            mstore(ptr, len)
            returndatacopy(add(ptr, 0x20), 0, len)
            returnData := ptr
        }
    }

    // revert with explicit byte array (probably reverted info from call)
    function revertWithData(bytes memory returnData) internal pure {
        assembly ("memory-safe") {
            revert(add(returnData, 32), mload(returnData))
        }
    }

    // Propagate revert data from last call
    function revertWithReturnData() internal pure {
        revertWithData(getReturnData(0));
    }
}

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

/* solhint-disable no-inline-assembly */

import "../interfaces/PackedUserOperation.sol";
import {calldataKeccak, min} from "./Helpers.sol";

/**
 * Utility functions helpful when working with UserOperation structs.
 */
library UserOperationLib {

    uint256 public constant PAYMASTER_VALIDATION_GAS_OFFSET = 20;
    uint256 public constant PAYMASTER_POSTOP_GAS_OFFSET = 36;
    uint256 public constant PAYMASTER_DATA_OFFSET = 52;

    /**
     * Relayer/block builder might submit the TX with higher priorityFee,
     * but the user should not pay above what he signed for.
     * @param userOp - The user operation data.
     */
    function gasPrice(
        PackedUserOperation calldata userOp
    ) internal view returns (uint256) {
        unchecked {
            (uint256 maxPriorityFeePerGas, uint256 maxFeePerGas) = unpackUints(userOp.gasFees);
            return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);
        }
    }

    bytes32 internal constant PACKED_USEROP_TYPEHASH =
    keccak256(
        "PackedUserOperation(address sender,uint256 nonce,bytes initCode,bytes callData,bytes32 accountGasLimits,uint256 preVerificationGas,bytes32 gasFees,bytes paymasterAndData)"
    );

    /**
     * Pack the user operation data into bytes for hashing.
     * @param userOp - The user operation data.
     * @param overrideInitCodeHash - If set, encode this instead of the initCode field in the userOp.
     */
    function encode(
        PackedUserOperation calldata userOp,
        bytes32 overrideInitCodeHash
    ) internal pure returns (bytes memory ret) {
        address sender = userOp.sender;
        uint256 nonce = userOp.nonce;
        bytes32 hashInitCode = overrideInitCodeHash != 0 ? overrideInitCodeHash : calldataKeccak(userOp.initCode);
        bytes32 hashCallData = calldataKeccak(userOp.callData);
        bytes32 accountGasLimits = userOp.accountGasLimits;
        uint256 preVerificationGas = userOp.preVerificationGas;
        bytes32 gasFees = userOp.gasFees;
        bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);

        return abi.encode(
            UserOperationLib.PACKED_USEROP_TYPEHASH,
            sender, nonce,
            hashInitCode, hashCallData,
            accountGasLimits, preVerificationGas, gasFees,
            hashPaymasterAndData
        );
    }

    function unpackUints(
        bytes32 packed
    ) internal pure returns (uint256 high128, uint256 low128) {
        return (unpackHigh128(packed), unpackLow128(packed));
    }

    // Unpack just the high 128-bits from a packed value
    function unpackHigh128(bytes32 packed) internal pure returns (uint256) {
        return uint256(packed) >> 128;
    }

    // Unpack just the low 128-bits from a packed value
    function unpackLow128(bytes32 packed) internal pure returns (uint256) {
        return uint128(uint256(packed));
    }

    function unpackMaxPriorityFeePerGas(PackedUserOperation calldata userOp)
    internal pure returns (uint256) {
        return unpackHigh128(userOp.gasFees);
    }

    function unpackMaxFeePerGas(PackedUserOperation calldata userOp)
    internal pure returns (uint256) {
        return unpackLow128(userOp.gasFees);
    }

    function unpackVerificationGasLimit(PackedUserOperation calldata userOp)
    internal pure returns (uint256) {
        return unpackHigh128(userOp.accountGasLimits);
    }

    function unpackCallGasLimit(PackedUserOperation calldata userOp)
    internal pure returns (uint256) {
        return unpackLow128(userOp.accountGasLimits);
    }

    function unpackPaymasterVerificationGasLimit(PackedUserOperation calldata userOp)
    internal pure returns (uint256) {
        return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET]));
    }

    function unpackPostOpGasLimit(PackedUserOperation calldata userOp)
    internal pure returns (uint256) {
        return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_POSTOP_GAS_OFFSET : PAYMASTER_DATA_OFFSET]));
    }

    function unpackPaymasterStaticFields(
        bytes calldata paymasterAndData
    ) internal pure returns (address paymaster, uint256 validationGasLimit, uint256 postOpGasLimit) {
        return (
            address(bytes20(paymasterAndData[: PAYMASTER_VALIDATION_GAS_OFFSET])),
            uint128(bytes16(paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET])),
            uint128(bytes16(paymasterAndData[PAYMASTER_POSTOP_GAS_OFFSET : PAYMASTER_DATA_OFFSET]))
        );
    }

    /**
     * Hash the user operation data.
     * @param userOp - The user operation data.
     * @param overrideInitCodeHash - If set, the initCode hash will be replaced with this value just for UserOp hashing.
     */
    function hash(
        PackedUserOperation calldata userOp,
        bytes32 overrideInitCodeHash
    ) internal pure returns (bytes32) {
        return keccak256(encode(userOp, overrideInitCodeHash));
    }
}

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

/**
 * Manage deposits and stakes.
 * Deposit is just a balance used to pay for UserOperations (either by a paymaster or an account).
 * Stake is value locked for at least "unstakeDelay" by the staked entity.
 */
interface IStakeManager {
    event Deposited(address indexed account, uint256 totalDeposit);

    event Withdrawn(
        address indexed account,
        address withdrawAddress,
        uint256 amount
    );

    // Emitted when stake or unstake delay are modified.
    event StakeLocked(
        address indexed account,
        uint256 totalStaked,
        uint256 unstakeDelaySec
    );

    // Emitted once a stake is scheduled for withdrawal.
    event StakeUnlocked(address indexed account, uint256 withdrawTime);

    event StakeWithdrawn(
        address indexed account,
        address withdrawAddress,
        uint256 amount
    );

    /**
     * @param deposit         - The entity's deposit.
     * @param staked          - True if this entity is staked.
     * @param stake           - Actual amount of ether staked for this entity.
     * @param unstakeDelaySec - Minimum delay to withdraw the stake.
     * @param withdrawTime    - First block timestamp where 'withdrawStake' will be callable, or zero if already locked.
     * @dev Sizes were chosen so that deposit fits into one cell (used during handleOp)
     *      and the rest fit into a 2nd cell (used during stake/unstake)
     *      - 112 bit allows for 10^15 eth
     *      - 48 bit for full timestamp
     *      - 32 bit allows 150 years for unstake delay
     */
    struct DepositInfo {
        uint256 deposit;
        bool staked;
        uint112 stake;
        uint32 unstakeDelaySec;
        uint48 withdrawTime;
    }

    // API struct used by getStakeInfo and simulateValidation.
    struct StakeInfo {
        uint256 stake;
        uint256 unstakeDelaySec;
    }

    /**
     * Get deposit info.
     * @param account - The account to query.
     * @return info   - Full deposit information of given account.
     */
    function getDepositInfo(
        address account
    ) external view returns (DepositInfo memory info);

    /**
     * Get account balance.
     * @param account - The account to query.
     * @return        - The deposit (for gas payment) of the account.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * Add to the deposit of the given account.
     * @param account - The account to add to.
     */
    function depositTo(address account) external payable;

    /**
     * Add to the account's stake - amount and delay
     * any pending unstake is first cancelled.
     * @param unstakeDelaySec - The new lock duration before the deposit can be withdrawn.
     */
    function addStake(uint32 unstakeDelaySec) external payable;

    /**
     * Attempt to unlock the stake.
     * The value can be withdrawn (using withdrawStake) after the unstake delay.
     */
    function unlockStake() external;

    /**
     * Withdraw from the (unlocked) stake.
     * Must first call unlockStake and wait for the unstakeDelay to pass.
     * @param withdrawAddress - The address to send withdrawn value.
     */
    function withdrawStake(address payable withdrawAddress) external;

    /**
     * Withdraw from the deposit.
     * @param withdrawAddress - The address to send withdrawn value.
     * @param withdrawAmount  - The amount to withdraw.
     */
    function withdrawTo(
        address payable withdrawAddress,
        uint256 withdrawAmount
    ) external;
}

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

import "./PackedUserOperation.sol";

/**
 * Aggregated Signatures validator.
 */
interface IAggregator {
    /**
     * Validate an aggregated signature.
     * Reverts if the aggregated signature does not match the given list of operations.
     * @param userOps   - An array of UserOperations to validate the signature for.
     * @param signature - The aggregated signature.
     */
    function validateSignatures(
        PackedUserOperation[] calldata userOps,
        bytes calldata signature
    ) external;

    /**
     * Validate the signature of a single userOp.
     * This method should be called by bundler after EntryPointSimulation.simulateValidation() returns
     * the aggregator this account uses.
     * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.
     * @param userOp        - The userOperation received from the user.
     * @return sigForUserOp - The value to put into the signature field of the userOp when calling handleOps.
     *                        (usually empty, unless account and aggregator support some kind of "multisig".
     */
    function validateUserOpSignature(
        PackedUserOperation calldata userOp
    ) external view returns (bytes memory sigForUserOp);

    /**
     * Aggregate multiple signatures into a single value.
     * This method is called off-chain to calculate the signature to pass with handleOps()
     * bundler MAY use optimized custom code to perform this aggregation.
     * @param userOps              - An array of UserOperations to collect the signatures from.
     * @return aggregatedSignature - The aggregated signature.
     */
    function aggregateSignatures(
        PackedUserOperation[] calldata userOps
    ) external view returns (bytes memory aggregatedSignature);
}

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

interface INonceManager {

    /**
     * Return the next nonce for this sender.
     * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)
     * But UserOp with different keys can come with arbitrary order.
     *
     * @param sender the account address
     * @param key the high 192 bit of the nonce
     * @return nonce a full nonce to pass for next UserOp with this sender.
     */
    function getNonce(address sender, uint192 key)
    external view returns (uint256 nonce);

    /**
     * Manually increment the nonce of the sender.
     * This method is exposed just for completeness..
     * Account does NOT need to call it, neither during validation, nor elsewhere,
     * as the EntryPoint will update the nonce regardless.
     * Possible use-case is call it with various keys to "initialize" their nonces to one, so that future
     * UserOperations will not pay extra for the first transaction with a given key.
     *
     * @param key - the "nonce key" to increment the "nonce sequence" for.
     */
    function incrementNonce(uint192 key) external;
}

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

interface ISenderCreator {
    /**
     * @dev Creates a new sender contract.
     * @return sender Address of the newly created sender contract.
     */
    function createSender(bytes calldata initCode) external returns (address sender);

    /**
     * Use initCallData to initialize an EIP-7702 account.
     * The caller is the EntryPoint contract and it is already verified to be an EIP-7702 account.
     * Note: Can be called multiple times as long as an appropriate initCode is supplied
     *
     * @param sender - the 'sender' EIP-7702 account to be initialized.
     * @param initCallData - the call data to be passed to the sender account call.
     */
    function initEip7702Sender(address sender, bytes calldata initCallData) external;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../../utils/introspection/IERC165.sol";

/**
 * @dev Interface that must be implemented by smart contracts in order to receive
 * ERC-1155 token transfers.
 */
interface IERC1155Receiver is IERC165 {
    /**
     * @dev Handles the receipt of a single ERC-1155 token type. This function is
     * called at the end of a `safeTransferFrom` after the balance has been updated.
     *
     * NOTE: To accept the transfer, this must return
     * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
     * (i.e. 0xf23a6e61, or its own function selector).
     *
     * @param operator The address which initiated the transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param id The ID of the token being transferred
     * @param value The amount of tokens being transferred
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
     */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);

    /**
     * @dev Handles the receipt of a multiple ERC-1155 token types. This function
     * is called at the end of a `safeBatchTransferFrom` after the balances have
     * been updated.
     *
     * NOTE: To accept the transfer(s), this must return
     * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     * (i.e. 0xbc197c81, or its own function selector).
     *
     * @param operator The address which initiated the batch transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param ids An array containing ids of each token being transferred (order and length must match values array)
     * @param values An array containing amounts of each token being transferred (order and length must match ids array)
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
     */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}

File 30 of 31 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.20;

/**
 * @title ERC-721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC-721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be
     * reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

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

/// @notice Library to encode strings in Base64.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Base64.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Base64.sol)
/// @author Modified from (https://github.com/Brechtpd/base64/blob/main/base64.sol) by Brecht Devos - <[email protected]>.
library Base64 {
    /// @dev Encodes `data` using the base64 encoding described in RFC 4648.
    /// See: https://datatracker.ietf.org/doc/html/rfc4648
    /// @param fileSafe  Whether to replace '+' with '-' and '/' with '_'.
    /// @param noPadding Whether to strip away the padding.
    function encode(bytes memory data, bool fileSafe, bool noPadding) internal pure returns (string memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            let dataLength := mload(data)

            if dataLength {
                // Multiply by 4/3 rounded up.
                // The `shl(2, ...)` is equivalent to multiplying by 4.
                let encodedLength := shl(2, div(add(dataLength, 2), 3))

                // Set `result` to point to the start of the free memory.
                result := mload(0x40)

                // Store the table into the scratch space.
                // Offsetted by -1 byte so that the `mload` will load the character.
                // We will rewrite the free memory pointer at `0x40` later with
                // the allocated size.
                // The magic constant 0x0670 will turn "-_" into "+/".
                mstore(0x1f, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef")
                mstore(0x3f, xor("ghijklmnopqrstuvwxyz0123456789-_", mul(iszero(fileSafe), 0x0670)))

                // Skip the first slot, which stores the length.
                let ptr := add(result, 0x20)
                let end := add(ptr, encodedLength)

                let dataEnd := add(add(0x20, data), dataLength)
                let dataEndValue := mload(dataEnd) // Cache the value at the `dataEnd` slot.
                mstore(dataEnd, 0x00) // Zeroize the `dataEnd` slot to clear dirty bits.

                // Run over the input, 3 bytes at a time.
                for {} 1 {} {
                    data := add(data, 3) // Advance 3 bytes.
                    let input := mload(data)

                    // Write 4 bytes. Optimized for fewer stack operations.
                    mstore8(0, mload(and(shr(18, input), 0x3F)))
                    mstore8(1, mload(and(shr(12, input), 0x3F)))
                    mstore8(2, mload(and(shr(6, input), 0x3F)))
                    mstore8(3, mload(and(input, 0x3F)))
                    mstore(ptr, mload(0x00))

                    ptr := add(ptr, 4) // Advance 4 bytes.
                    if iszero(lt(ptr, end)) { break }
                }
                mstore(dataEnd, dataEndValue) // Restore the cached value at `dataEnd`.
                mstore(0x40, add(end, 0x20)) // Allocate the memory.
                // Equivalent to `o = [0, 2, 1][dataLength % 3]`.
                let o := div(2, mod(dataLength, 3))
                // Offset `ptr` and pad with '='. We can simply write over the end.
                mstore(sub(ptr, o), shl(240, 0x3d3d))
                // Set `o` to zero if there is padding.
                o := mul(iszero(iszero(noPadding)), o)
                mstore(sub(ptr, o), 0) // Zeroize the slot after the string.
                mstore(result, sub(encodedLength, o)) // Store the length.
            }
        }
    }

    /// @dev Encodes `data` using the base64 encoding described in RFC 4648.
    /// Equivalent to `encode(data, false, false)`.
    function encode(bytes memory data) internal pure returns (string memory result) {
        result = encode(data, false, false);
    }

    /// @dev Encodes `data` using the base64 encoding described in RFC 4648.
    /// Equivalent to `encode(data, fileSafe, false)`.
    function encode(bytes memory data, bool fileSafe) internal pure returns (string memory result) {
        result = encode(data, fileSafe, false);
    }

    /// @dev Decodes base64 encoded `data`.
    ///
    /// Supports:
    /// - RFC 4648 (both standard and file-safe mode).
    /// - RFC 3501 (63: ',').
    ///
    /// Does not support:
    /// - Line breaks.
    ///
    /// Note: For performance reasons,
    /// this function will NOT revert on invalid `data` inputs.
    /// Outputs for invalid inputs will simply be undefined behaviour.
    /// It is the user's responsibility to ensure that the `data`
    /// is a valid base64 encoded string.
    function decode(string memory data) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            let dataLength := mload(data)

            if dataLength {
                let decodedLength := mul(shr(2, dataLength), 3)

                for {} 1 {} {
                    // If padded.
                    if iszero(and(dataLength, 3)) {
                        let t := xor(mload(add(data, dataLength)), 0x3d3d)
                        // forgefmt: disable-next-item
                        decodedLength := sub(
                            decodedLength,
                            add(iszero(byte(30, t)), iszero(byte(31, t)))
                        )
                        break
                    }
                    // If non-padded.
                    decodedLength := add(decodedLength, sub(and(dataLength, 3), 1))
                    break
                }
                result := mload(0x40)

                // Write the length of the bytes.
                mstore(result, decodedLength)

                // Skip the first slot, which stores the length.
                let ptr := add(result, 0x20)
                let end := add(ptr, decodedLength)

                // Load the table into the scratch space.
                // Constants are optimized for smaller bytecode with zero gas overhead.
                // `m` also doubles as the mask of the upper 6 bits.
                let m := 0xfc000000fc00686c7074787c8084888c9094989ca0a4a8acb0b4b8bcc0c4c8cc
                mstore(0x5b, m)
                mstore(0x3b, 0x04080c1014181c2024282c3034383c4044484c5054585c6064)
                mstore(0x1a, 0xf8fcf800fcd0d4d8dce0e4e8ecf0f4)

                for {} 1 {} {
                    // Read 4 bytes.
                    data := add(data, 4)
                    let input := mload(data)

                    // Write 3 bytes.
                    // forgefmt: disable-next-item
                    mstore(ptr, or(
                        and(m, mload(byte(28, input))),
                        shr(6, or(
                            and(m, mload(byte(29, input))),
                            shr(6, or(
                                and(m, mload(byte(30, input))),
                                shr(6, mload(byte(31, input)))
                            ))
                        ))
                    ))
                    ptr := add(ptr, 3)
                    if iszero(lt(ptr, end)) { break }
                }
                mstore(0x40, add(end, 0x20)) // Allocate the memory.
                mstore(end, 0) // Zeroize the slot after the bytes.
                mstore(0x60, 0) // Restore the zero slot.
            }
        }
    }
}

Settings
{
  "remappings": [
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "account-abstraction/=lib/account-abstraction/contracts/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 2000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": true,
  "libraries": {}
}

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_entryPoint","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bytes","name":"error","type":"bytes"}],"name":"ExecuteError","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"OpenfortBaseAccount7702V1__InvalidNonce","type":"error"},{"inputs":[],"name":"OpenfortBaseAccount7702V1__InvalidSignature","type":"error"},{"inputs":[],"name":"OpenfortBaseAccount7702V1__InvalidTransactionLength","type":"error"},{"inputs":[],"name":"OpenfortBaseAccount7702V1__InvalidTransactionTarget","type":"error"},{"inputs":[{"internalType":"bytes","name":"returnData","type":"bytes"}],"name":"OpenfortBaseAccount7702V1__TransactionFailed","type":"error"},{"inputs":[],"name":"OpenfortBaseAccount7702V1__ValidationExpired","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"inputs":[],"name":"SessionKeyManager__AddressCantBeZero","type":"error"},{"inputs":[],"name":"SessionKeyManager__InvalidTimestamp","type":"error"},{"inputs":[],"name":"SessionKeyManager__SelectorsListTooBig","type":"error"},{"inputs":[],"name":"SessionKeyManager__SessionKeyInactive","type":"error"},{"inputs":[],"name":"SessionKeyManager__SessionKeyRegistered","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"components":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct ISessionKey.PubKey","name":"pubKey","type":"tuple"},{"internalType":"address","name":"eoaAddress","type":"address"},{"internalType":"enum ISessionKey.KeyType","name":"keyType","type":"uint8"}],"indexed":true,"internalType":"struct ISessionKey.Key","name":"masterKey","type":"tuple"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"sessionKey","type":"bytes32"}],"name":"SessionKeyRegistrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"sessionKey","type":"bytes32"}],"name":"SessionKeyRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"TransactionExecuted","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"DEAD_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SELECTORS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_OPENFORT_CONTRACT_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"encodeEOASignature","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"challenge","type":"bytes"},{"internalType":"bool","name":"requireUserVerification","type":"bool"},{"internalType":"bytes","name":"authenticatorData","type":"bytes"},{"internalType":"string","name":"clientDataJSON","type":"string"},{"internalType":"uint256","name":"challengeIndex","type":"uint256"},{"internalType":"uint256","name":"typeIndex","type":"uint256"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct ISessionKey.PubKey","name":"pubKey","type":"tuple"}],"name":"encodeWebAuthnSignature","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"entryPoint","outputs":[{"internalType":"contract IEntryPoint","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct OPF7702v11.Transaction[]","name":"_transactions","type":"tuple[]"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_calldata","type":"bytes"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BaseAccount.Call[]","name":"calls","type":"tuple[]"}],"name":"executeBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_target","type":"address[]"},{"internalType":"uint256[]","name":"_value","type":"uint256[]"},{"internalType":"bytes[]","name":"_calldata","type":"bytes[]"}],"name":"executeBatch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"getKeyById","outputs":[{"components":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct ISessionKey.PubKey","name":"pubKey","type":"tuple"},{"internalType":"address","name":"eoaAddress","type":"address"},{"internalType":"enum ISessionKey.KeyType","name":"keyType","type":"uint8"}],"internalType":"struct ISessionKey.Key","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"getKeyRegistrationInfo","outputs":[{"internalType":"enum ISessionKey.KeyType","name":"keyType","type":"uint8"},{"internalType":"address","name":"registeredBy","type":"address"},{"internalType":"bool","name":"isActive","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_key","type":"address"}],"name":"getSessionKeyData","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint48","name":"","type":"uint48"},{"internalType":"uint48","name":"","type":"uint48"},{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_keyHash","type":"bytes32"}],"name":"getSessionKeyData","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint48","name":"","type":"uint48"},{"internalType":"uint48","name":"","type":"uint48"},{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"id","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"idSessionKeys","outputs":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct ISessionKey.PubKey","name":"pubKey","type":"tuple"},{"internalType":"address","name":"eoaAddress","type":"address"},{"internalType":"enum ISessionKey.KeyType","name":"keyType","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct ISessionKey.PubKey","name":"pubKey","type":"tuple"},{"internalType":"address","name":"eoaAddress","type":"address"},{"internalType":"enum ISessionKey.KeyType","name":"keyType","type":"uint8"}],"internalType":"struct ISessionKey.Key","name":"_key","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"limit","type":"uint256"}],"internalType":"struct SpendLimit.SpendTokenInfo","name":"_spendTokenInfo","type":"tuple"},{"internalType":"bytes4[]","name":"_allowedSelectors","type":"bytes4[]"},{"internalType":"bytes32","name":"_hash","type":"bytes32"},{"internalType":"bytes","name":"_signature","type":"bytes"},{"internalType":"uint256","name":"_validUntil","type":"uint256"},{"internalType":"uint256","name":"_nonce","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"keyHash","type":"bytes32"}],"name":"isSessionKeyActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"eoaKey","type":"address"}],"name":"isSessionKeyActive","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":"magicValue","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct ISessionKey.PubKey","name":"pubKey","type":"tuple"},{"internalType":"address","name":"eoaAddress","type":"address"},{"internalType":"enum ISessionKey.KeyType","name":"keyType","type":"uint8"}],"internalType":"struct ISessionKey.Key","name":"_key","type":"tuple"},{"internalType":"uint48","name":"_validUntil","type":"uint48"},{"internalType":"uint48","name":"_validAfter","type":"uint48"},{"internalType":"uint48","name":"_limit","type":"uint48"},{"internalType":"bool","name":"_whitelisting","type":"bool"},{"internalType":"address","name":"_contractAddress","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"limit","type":"uint256"}],"internalType":"struct SpendLimit.SpendTokenInfo","name":"_spendTokenInfo","type":"tuple"},{"internalType":"bytes4[]","name":"_allowedSelectors","type":"bytes4[]"},{"internalType":"uint256","name":"_ethLimit","type":"uint256"}],"name":"registerSessionKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revokeAllSessionKeys","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct ISessionKey.PubKey","name":"pubKey","type":"tuple"},{"internalType":"address","name":"eoaAddress","type":"address"},{"internalType":"enum ISessionKey.KeyType","name":"keyType","type":"uint8"}],"internalType":"struct ISessionKey.Key","name":"_key","type":"tuple"}],"name":"revokeSessionKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"sessionKey","type":"bytes32"}],"name":"sessionKeys","outputs":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct ISessionKey.PubKey","name":"pubKey","type":"tuple"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint48","name":"validUntil","type":"uint48"},{"internalType":"uint48","name":"validAfter","type":"uint48"},{"internalType":"uint48","name":"limit","type":"uint48"},{"internalType":"bool","name":"masterSessionKey","type":"bool"},{"internalType":"bool","name":"whitelisting","type":"bool"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"limit","type":"uint256"}],"internalType":"struct SpendLimit.SpendTokenInfo","name":"spendTokenInfo","type":"tuple"},{"internalType":"uint256","name":"ethLimit","type":"uint256"},{"internalType":"address","name":"whoRegistrated","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sessionKeyEOA","type":"address"}],"name":"sessionKeysEOA","outputs":[{"components":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"internalType":"struct ISessionKey.PubKey","name":"pubKey","type":"tuple"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint48","name":"validUntil","type":"uint48"},{"internalType":"uint48","name":"validAfter","type":"uint48"},{"internalType":"uint48","name":"limit","type":"uint48"},{"internalType":"bool","name":"masterSessionKey","type":"bool"},{"internalType":"bool","name":"whitelisting","type":"bool"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"limit","type":"uint256"}],"internalType":"struct SpendLimit.SpendTokenInfo","name":"spendTokenInfo","type":"tuple"},{"internalType":"uint256","name":"ethLimit","type":"uint256"},{"internalType":"address","name":"whoRegistrated","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"challenge","type":"bytes"}],"name":"usedChallenges","outputs":[{"internalType":"bool","name":"isUsed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"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":"userOpHash","type":"bytes32"},{"internalType":"uint256","name":"missingAccountFunds","type":"uint256"}],"name":"validateUserOp","outputs":[{"internalType":"uint256","name":"validationData","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"challenge","type":"bytes"},{"internalType":"bool","name":"requireUserVerification","type":"bool"},{"internalType":"bytes","name":"encodedAuth","type":"bytes"},{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"verifyCompactSignature","outputs":[{"internalType":"bool","name":"isValid","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"challenge","type":"bytes"},{"internalType":"bool","name":"requireUserVerification","type":"bool"},{"internalType":"bytes","name":"encodedAuth","type":"bytes"},{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"verifyEncodedSignature","outputs":[{"internalType":"bool","name":"isValid","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"verifyP256Signature","outputs":[{"internalType":"bool","name":"isValid","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"challenge","type":"bytes"},{"internalType":"bool","name":"requireUserVerification","type":"bool"},{"internalType":"bytes","name":"authenticatorData","type":"bytes"},{"internalType":"string","name":"clientDataJSON","type":"string"},{"internalType":"uint256","name":"challengeIndex","type":"uint256"},{"internalType":"uint256","name":"typeIndex","type":"uint256"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"verifySoladySignature","outputs":[{"internalType":"bool","name":"isValid","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60c03461013057601f6149e038819003918201601f19168301916001600160401b038311848410176101345780849260209460405283398101031261013057516001600160a01b03811681036101305760017f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f3685560a052306080525f5160206149c05f395f51905f525460ff8160401c16610121576002600160401b03196001600160401b038216016100cb575b60405161487790816101498239608051816107e4015260a051815050f35b6001600160401b0319166001600160401b039081175f5160206149c05f395f51905f52556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a15f6100ad565b63f92ee8a960e01b5f5260045ffd5b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe60806040526004361015610010575b005b5f3560e01c806301ffc9a71461025f5780630c3b1ae91461025a578063110891c114610255578063150b7a02146102505780631626ba7e1461024b57806317f976721461024657806318f991021461024157806319822f7c1461023c57806325c1c3c31461023757806334fcd5be146102325780633f707e6b1461022d57806347e1da2a146102285780634e6fd6c4146102235780635a880de31461021e57806369d3c8651461021957806394c11608146102145780639c241abd1461020f578063a04b3e161461020a578063a2e8cf4014610205578063a7dc0fe614610200578063af640d0f146101fb578063affed0e0146101f6578063b0d691fe146101f1578063b2aa3f13146101ec578063b3ee7f11146101e7578063b61d27f6146101e2578063b75c8b78146101dd578063bc197c81146101d8578063bed5df4a146101d3578063c77d7805146101ce578063ce9124f3146101c9578063d087d288146101c4578063d180b1fc146101bf578063d86c2585146101ba578063eaf0188f146101b5578063f23a6e61146101b05763f4d2a1940361000e57611ea6565b611e34565b611d93565b611d42565b611c31565b611b7d565b6119ba565b61194d565b611904565b611811565b6116fe565b61166c565b61159d565b61145d565b6113cc565b611390565b611354565b6112cd565b611299565b611229565b61117c565b611099565b611054565b610ff9565b610f9b565b610e68565b610cdf565b610c20565b6109dd565b6108df565b610808565b6107c5565b610773565b610701565b6105df565b61050c565b61027a565b6001600160e01b031981160361027657565b5f80fd5b34610276576020600319360112610276576001600160e01b03196004356102a081610264565b167f01ffc9a7000000000000000000000000000000000000000000000000000000008114908115610354575b8115610343575b8115610319575b81156102ef575b506040519015158152602090f35b7f150b7a02000000000000000000000000000000000000000000000000000000009150145f6102e1565b7f4e2312e000000000000000000000000000000000000000000000000000000000811491506102da565b630b135d3f60e11b811491506102d3565b7f19822f7c00000000000000000000000000000000000000000000000000000000811491506102cc565b634e487b7160e01b5f52604160045260245ffd5b6040810190811067ffffffffffffffff8211176103ae57604052565b61037e565b6060810190811067ffffffffffffffff8211176103ae57604052565b60c0810190811067ffffffffffffffff8211176103ae57604052565b90601f601f19910116810190811067ffffffffffffffff8211176103ae57604052565b6040519061041d6040836103eb565b565b6040519061041d6060836103eb565b9060405161043b81610392565b602060018294805484520154910152565b9060405161045981610392565b6020600182946001600160a01b0381541684520154910152565b9a999896949290918b989694926101808a019c6104999160208091805184520151910152565b1515604089015265ffffffffffff16606088015265ffffffffffff16608087015265ffffffffffff1660a0860152151560c0850152151560e084015261010083019080516001600160a01b031682526020015190602001526101408201526101600161041d916001600160a01b03169052565b34610276576020600319360112610276576004355f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f206105538161042e565b6105ca6002830154926105686004820161044c565b90610582600860078301549201546001600160a01b031690565b9160405195869560ff8260a01c169160ff8160981c169165ffffffffffff8260681c169165ffffffffffff8160381c169160ff65ffffffffffff8360081c169216908b610473565b0390f35b6001600160a01b0381160361027657565b34610276576020600319360112610276576004356105fc816105ce565b6001600160a01b03165f9081527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36d602052604090206002015465ffffffffffff600882901c81169160ff8116916105ca91603881901c82169160689190911c165b9060405194859485929365ffffffffffff809296958160609560808801991515885216602087015216604085015216910152565b67ffffffffffffffff81116103ae57601f01601f191660200190565b9291926106b982610691565b916106c760405193846103eb565b829481845281830111610276578281602093845f960137010152565b9080601f83011215610276578160206106fe933591016106ad565b90565b346102765760806003193601126102765761071d6004356105ce565b6107286024356105ce565b60643567ffffffffffffffff8111610276576107489036906004016106e3565b5060206040517f150b7a02000000000000000000000000000000000000000000000000000000008152f35b346102765760406003193601126102765760043560243567ffffffffffffffff8111610276576020916107ad6107b39236906004016106e3565b90611f09565b6001600160e01b031960405191168152f35b34610276575f6003193601126102765760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610276576020600319360112610276576001600160a01b0360043561082d816105ce565b165f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36d60205260405f206108618161042e565b906105ca6002820154916108798360ff9060a01c1690565b906108866004820161044c565b61089f600860078401549301546001600160a01b031690565b92604051968660ff899860981c169165ffffffffffff8260681c169165ffffffffffff8160381c169160ff65ffffffffffff8360081c169216908b610473565b346102765760606003193601126102765760043567ffffffffffffffff81116102765761012060031982360301126102765760243590604435734337084d9e255ff0702461cf8895ce9e3b5ff108330361097f5761095060246109486105ca958560040161326d565b930135613507565b80610967575b506040519081529081906020820190565b5f80808093335af150610978612181565b505f610956565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f6163636f756e743a206e6f742066726f6d20456e747279506f696e74000000006044820152fd5b34610276575f600319360112610276576109f5613558565b5f5b7f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36a5481101561000e5780610a2c6001926121c0565b60408101838151610a3c81610fdd565b610a4581610fdd565b03610ae057505180516020918201516040805193840192835283015290610a7981606081015b03601f1981018352826103eb565b519020610ab5610ab0825f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b61361a565b7fa6293d3e6a2b62cf1a2218754c516fcf944f744d8794bb85842d57f0b1aa38a75f80a25b016109f7565b51610aea81610fdd565b610af381610fdd565b15610aff575b50610ada565b60200180516001600160a01b0316908115610bb957610b54610ab0610b61936001600160a01b03165f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36d60205260405f2090565b516001600160a01b031690565b604051610b8c81610a6b6020820194856bffffffffffffffffffffffff1960149260601b1681520190565b5190207fa6293d3e6a2b62cf1a2218754c516fcf944f744d8794bb85842d57f0b1aa38a75f80a25f610af9565b5050610ada565b9181601f840112156102765782359167ffffffffffffffff8311610276576020808501948460051b01011161027657565b6020600319820112610276576004359067ffffffffffffffff821161027657610c1c91600401610bc0565b9091565b3461027657610c2e36610bf1565b610c36613558565b5f5b818110610c4157005b610c87610c83610c7d610c558486886120cf565b610c5e8161210f565b90610c726020820135916040810190612119565b93905a9436916106ad565b916136b7565b1590565b610c9357600101610c38565b600182145f036136e357610ca56136c9565b90610cdb6040519283927f5a1546750000000000000000000000000000000000000000000000000000000084526004840161216a565b0390fd5b610ce836610bf1565b610cf06136f3565b610cf8613558565b80158015610e5e575b610e36575f5b818110610d375761000e60017f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36855565b610d428183856120cf565b610d4b8161210f565b90610d69610d626020830135926040810190612119565b36916106ad565b906001600160a01b03831692308414610e0e575f80918451908460208701915af1610d92612181565b9015610dd8575060019392917f47d99ad340f52da66535aff7e10da1ceb85a32bcbd9fa1c42314d194545e14d291610dcf6040519283928361216a565b0390a201610d07565b610cdb906040519182917faf05250e0000000000000000000000000000000000000000000000000000000083526004830161116b565b7f793426ed000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f1d453126000000000000000000000000000000000000000000000000000000005f5260045ffd5b5060098111610d01565b60606003193601126102765760043567ffffffffffffffff811161027657610e94903690600401610bc0565b9060243567ffffffffffffffff811161027657610eb5903690600401610bc0565b91909260443567ffffffffffffffff811161027657610ed8903690600401610bc0565b919092610ee36136f3565b610eeb613558565b600982118015610f91575b8015610f87575b610e36575f5b828110610f335761000e60017f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36855565b610f3e8184846121b0565b3590610f49826105ce565b610f5481888a6121b0565b359185821015610f8257600192610f7c91610f748460051b8a018a612119565b92909161376a565b01610f03565b6120bb565b5084821415610efd565b5082821415610ef6565b34610276575f60031936011261027657602060405173deadbeefdeadbeefdeadbeefdeadbeefdeadbeef8152f35b634e487b7160e01b5f52602160045260245ffd5b60021115610fe757565b610fc9565b906002821015610fe75752565b346102765760206003193601126102765760806110176004356121c0565b611052604080519261103484825160208091805184520151910152565b6001600160a01b036020820151168285015201516060830190610fec565bf35b346102765760206003193601126102765760606001600160a01b0361107a600435612258565b91929061108a6040518095610fec565b16602083015215156040820152f35b34610276575f600319360112610276576020604051600a8152f35b8015150361027657565b6024359061041d826110b4565b359061041d826110b4565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefc6040910112610276576040519061110d82610392565b610104358252610124356020830152565b91908260409103126102765760405161113681610392565b6020808294803584520135910152565b90601f19601f602080948051918291828752018686015e5f8582860101520116010190565b9060206106fe928181520190611146565b34610276576101406003193601126102765760043567ffffffffffffffff8111610276576111ae9036906004016106e3565b6111b66110be565b60443567ffffffffffffffff8111610276576111d69036906004016106e3565b916064359167ffffffffffffffff8311610276576105ca936111ff61121d9436906004016106e3565b60843560a4359160c4359360e43595611217366110d6565b976123ad565b6040519182918261116b565b34610276576020600319360112610276576004355f9081527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c602052604090206002015465ffffffffffff600882901c81169160ff8116916105ca91603881901c82169160689190911c1661065d565b346102765760a06003193601126102765760206112c36084356064356044356024356004356137de565b6040519015158152f35b34610276576020600319360112610276576004355f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36b602052608060405f20611052600261131b8361042e565b920154611335604051809460208091805184520151910152565b6001600160a01b038116604084015260ff606084019160a01c16610fec565b34610276575f6003193601126102765760207f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36a54604051908152f35b34610276575f6003193601126102765760207f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36954604051908152f35b34610276575f600319360112610276576020604051734337084d9e255ff0702461cf8895ce9e3b5ff1088152f35b60a06003198201126102765760043567ffffffffffffffff81116102765781611425916004016106e3565b91602435611432816110b4565b916044359067ffffffffffffffff821161027657611452916004016106e3565b906064359060843590565b34610276576105ca6114ba611471366113fa565b9361147d939193613873565b92805160c08110906020860190604087016060880190608089019260a08a019660208082019282010196156114cc575b50505050505050506138a5565b60405190151581529081906020820190565b81510194602086019182108760e08801111761154f5785825101602081019787604081015101602081019480861083871117908b10838c1117176115545760208281808094895101010111938b51010101111761154f5760c0968b5252606084015190526080830151905260a08201519052015190525f808080808080806114ad565b6114ad565b5050506114ad565b600319608091011261027657600490565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedc60409101126102765761012490565b3461027657610160600319360112610276576115b83661155c565b60407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c3601126102765760c43567ffffffffffffffff811161027657611602903690600401610bc0565b6101043592919060e43567ffffffffffffffff85116102765761162c61000e9536906004016106e3565b91610124359360846101443596612443565b9181601f840112156102765782359167ffffffffffffffff8311610276576020838186019501011161027657565b606060031936011261027657600435611684816105ce565b6024356044359167ffffffffffffffff8311610276576116ab6116c393369060040161163e565b9290916116b66136f3565b6116be613558565b61376a565b60017f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36855005b60c4359065ffffffffffff8216820361027657565b34610276576101a0600319360112610276576117193661155c565b6084359065ffffffffffff821682036102765760a43565ffffffffffff81168103610276576117466116e9565b9260e435611753816110b4565b61010435611760816105ce565b6117693661156d565b91610164359667ffffffffffffffff88116102765761178f61000e983690600401610bc0565b9690956101843598612c00565b67ffffffffffffffff81116103ae5760051b60200190565b9080601f830112156102765781356117cb8161179c565b926117d960405194856103eb565b81845260208085019260051b82010192831161027657602001905b8282106118015750505090565b81358152602091820191016117f4565b346102765760a06003193601126102765761182d6004356105ce565b6118386024356105ce565b60443567ffffffffffffffff8111610276576118589036906004016117b4565b5060643567ffffffffffffffff8111610276576118799036906004016117b4565b5060843567ffffffffffffffff81116102765761189a9036906004016106e3565b506040517fbc197c81000000000000000000000000000000000000000000000000000000008152602090f35b60208091604051928184925191829101835e81017f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36e81520301902090565b346102765760206003193601126102765760043567ffffffffffffffff81116102765760ff61194161193c60209336906004016106e3565b6118c6565b54166040519015158152f35b346102765760206003193601126102765760043567ffffffffffffffff8111610276576119a66119846105ca92369060040161163e565b610a6b6040939293519384925f60208501526040808501526060840191612e40565b604051918291602083526020830190611146565b34610276576080600319360112610276576119d43661155c565b6119dc613558565b6060810160016119eb8261284c565b6119f481610fdd565b03611a805750610a6b611a23602083359301356040519283916020830195869091604092825260208201520190565b519020611a5a610ab0825f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b7fa6293d3e6a2b62cf1a2218754c516fcf944f744d8794bb85842d57f0b1aa38a75f80a2005b611a899061284c565b611a9281610fdd565b15611a9957005b6040016001600160a01b03611aad8261210f565b1615611b555780611afc610ab0611ac6611b019461210f565b6001600160a01b03165f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36d60205260405f2090565b61210f565b604051611b2c81610a6b6020820194856bffffffffffffffffffffffff1960149260601b1681520190565b5190207fa6293d3e6a2b62cf1a2218754c516fcf944f744d8794bb85842d57f0b1aa38a75f80a2005b7faa093569000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610276575f600319360112610276576040517f35567e1a0000000000000000000000000000000000000000000000000000000081523060048201525f6024820152602081604481734337084d9e255ff0702461cf8895ce9e3b5ff1085afa8015611c2c576105ca915f91611bfd57506040519081529081906020820190565b611c1f915060203d602011611c25575b611c1781836103eb565b810190612e60565b5f610956565b503d611c0d565b612e6f565b34610276576105ca6114ba611c45366113fa565b93611c51939193613873565b9280516046811015611c65575b50506138a5565b810190602081015160f01c908181019160228301907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc85019384831115611cb0575b50505050611c5e565b611ce17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffba926022611cec9601613d46565b895285030190613d46565b60208601525160f01c60408501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffde81015160f01c6060850152601f1981015160808501525160a08401525f8080808080611ca7565b34610276576020600319360112610276576004355f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c602052602060ff600260405f200154166040519015158152f35b34610276576101406003193601126102765760043567ffffffffffffffff811161027657611dc59036906004016106e3565b611dcd6110be565b60443567ffffffffffffffff811161027657611ded9036906004016106e3565b916064359167ffffffffffffffff8311610276576105ca93611e166114ba9436906004016106e3565b60843560a4359060c4359260e4359461010435966101243598612e7a565b346102765760a060031936011261027657611e506004356105ce565b611e5b6024356105ce565b60843567ffffffffffffffff811161027657611e7b9036906004016106e3565b5060206040517ff23a6e61000000000000000000000000000000000000000000000000000000008152f35b34610276576020600319360112610276576001600160a01b03600435611ecb816105ce565b165f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36d602052602060ff600260405f200154166040519015158152f35b7f25622562256225622562256225622562256225622562256225622562256225628114806120b0575b15611f5b57506001602082015114611f5257505b6001600160e01b031990565b6106fe90612ff7565b908051604081149081156120a5575b50611f76575050611f46565b611f7f91612eb5565b6001600160a01b038116301461209957611fc9906001600160a01b03165f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36d60205260405f2090565b6002810154600881901c65ffffffffffff16801591908215612083575b8215612079575b508115612048575b501561200857506001600160e01b031990565b61202c6120206008309301546001600160a01b031690565b6001600160a01b031690565b1461203d576001600160e01b031990565b630b135d3f60e11b90565b609881901c60ff1615915081612060575b505f611ff5565b6001915065ffffffffffff9060681c811616105f612059565b421191505f611fed565b4265ffffffffffff603884901c16119250611fe6565b50630b135d3f60e11b90565b60419150145f611f6a565b506041825111611f32565b634e487b7160e01b5f52603260045260245ffd5b9190811015610f825760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610276570190565b356106fe816105ce565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610276570180359067ffffffffffffffff82116102765760200191813603831361027657565b6040906106fe939281528160208201520190611146565b3d156121ab573d9061219282610691565b916121a060405193846103eb565b82523d5f602084013e565b606090565b9190811015610f825760051b0190565b5f604080516121ce816103b3565b81516121d981610392565b838152836020820152815282602082015201525f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36b60205260405f2060ff600260405192612227846103b3565b6122308161042e565b845201546001600160a01b038116602084015260a01c166002811015610fe757604082015290565b612261906121c0565b9060408201916001835161227481610fdd565b61227d81610fdd565b0361233d5751805160209182015160408051938401928352830152906122a68160608101610a6b565b5190209151906122b582610fdd565b612337600261232f61230160086122f3885f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b01546001600160a01b031690565b955f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b015460ff1690565b91929190565b8291925161234a81610fdd565b61235381610fdd565b1561236a57505161236381610fdd565b905f905f90565b90602090519161237983610fdd565b0191612337600261232f611ac661239f60086122f3611ac68a516001600160a01b031690565b96516001600160a01b031690565b979294612416610a6b959661240461018099946106fe9b966123eb6040519e8f9d8e6123dc6020820160019052565b61016060408201520190611146565b91151560608d0152601f198c83030160808d0152611146565b90601f198a83030160a08b0152611146565b60c088019690965260e0870152610100860152610120850152805161014085015260200151610160840152565b95939196949290967ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549767ffffffffffffffff61249861248a60ff8c60401c1615151590565b9a67ffffffffffffffff1690565b168015908161265f575b6001149081612655575b15908161264c575b5061262457612535978961252c60017fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000007ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005416177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055565b6125bf576126f3565b61253b57565b61259068ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055565b604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1565b61261f6801000000000000000068ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005416177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055565b6126f3565b7ff92ee8a9000000000000000000000000000000000000000000000000000000005f5260045ffd5b9050155f6124b4565b303b1591506124ac565b8a91506124a2565b634e487b7160e01b5f52601160045260245ffd5b90612710820180921161268a57565b612667565b6002111561027657565b359061041d8261268f565b6080906126ef60606040519280358452602081013560208501526001600160a01b0360408201356126d4816105ce565b16604085015201356126e58161268f565b6060830190610fec565b2090565b9596949192939096612703613558565b60025b600681106127f6575061271886613507565b42116127ce5761272b91610c83916139ee565b6127a6576127809461275e61277b947f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36955565b61277561276a4261267b565b65ffffffffffff1690565b8561290d565b6126a4565b7f9be0ddb3ac5d6261cc8d736bf39c29feb13498533b6c9f960d8e175bf70e6a1a5f80a2565b7f91cc5825000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f032c52a5000000000000000000000000000000000000000000000000000000005f5260045ffd5b807ff3acd96a9d0e27e4323229f52dd3234ce23fb8133871d002e7cbb32c4a47a5c40190817ff3acd96a9d0e27e4323229f52dd3234ce23fb8133871d002e7cbb32c4a47a5c41161268a575f6001925501612706565b356106fe8161268f565b6002606091833581556020840135600182015501916128a5604082013561287c816105ce565b84906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b01356128b08161268f565b6002811015610fe75781547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1660a09190911b74ff000000000000000000000000000000000000000016179055565b5f19811461268a5760010190565b909193612918613558565b4265ffffffffffff84161115612bd8576129838261297e7f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36a545f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36b60205260405f2090565b612856565b6129d46129b07f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36a546128ff565b7f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36a55565b6060820160016129e38261284c565b6129ec81610fdd565b03612afe57509091928235610a6b612a1e60208601356040519283916020830195869091604092825260208201520190565b51902094612a58600261232f885f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b612ad65773deadbeefdeadbeefdeadbeefdeadbeefdeadbeef5f8080612ab0988198612aab8c5f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b613a72565b7fcd7f4163a8248a579c58031f40b757bb4998ed5f01c78bfb6ae1cd42edb95fb05f80a2565b7f2eb93649000000000000000000000000000000000000000000000000000000005f5260045ffd5b612b079061284c565b612b1081610fdd565b15612b1d575b5050505050565b60408201936001600160a01b03612b338661210f565b1615611b5557612b4a600261232f611ac68861210f565b612ad657612b7c9573deadbeefdeadbeefdeadbeefdeadbeefdeadbeef5f8080611afc988198612aab611ac68d61210f565b604051612ba781610a6b6020820194856bffffffffffffffffffffffff1960149260601b1681520190565b5190207fcd7f4163a8248a579c58031f40b757bb4998ed5f01c78bfb6ae1cd42edb95fb05f80a25f80808080612b16565b7ff5bab791000000000000000000000000000000000000000000000000000000005f5260045ffd5b96939098959297949197612c12613558565b65ffffffffffff8a1642811115612bd85765ffffffffffff8a1611612bd857612c878861297e7f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36a545f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36b60205260405f2090565b612cb46129b07f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36a546128ff565b606088016001612cc38261284c565b612ccc81610fdd565b03612d76575090919293949596978835610a6b612d0360208c01356040519283916020830195869091604092825260208201520190565b51902099612d3d600261232f8d5f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b612ad657612ab099612aab8c5f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b612d7f9061284c565b612d8881610fdd565b15612d9a575b50505050505050505050565b60408801986001600160a01b03612db08b61210f565b1615611b5557612dc7600261232f611ac68d61210f565b612ad657612ddf9a611afc99612aab611ac68d61210f565b604051612e0a81610a6b6020820194856bffffffffffffffffffffffff1960149260601b1681520190565b5190207fcd7f4163a8248a579c58031f40b757bb4998ed5f01c78bfb6ae1cd42edb95fb05f80a25f808080808080808080612d8e565b601f8260209493601f1993818652868601375f8582860101520116010190565b90816020910312610276575190565b6040513d5f823e3d90fd5b936106fe9998979396929695919560405197612e95896103cf565b8852602088015260408701526060860152608085015260a08401526138a5565b6106fe91612ec291613d85565b90929192613dc9565b519061041d8261268f565b81601f8201121561027657602081519101612ef082610691565b92612efe60405194856103eb565b8284528282011161027657815f926020928386015e8301015290565b519061041d826110b4565b919082604091031261027657604051612f3d81610392565b6020808294805184520151910152565b6101608183031261027657612f6181612ecb565b92602082015167ffffffffffffffff81116102765783612f82918401612ed6565b92612f8f60408401612f1a565b92606081015167ffffffffffffffff81116102765782612fb0918301612ed6565b92608082015167ffffffffffffffff81116102765783612fd1918401612ed6565b9260a08301519260c0810151926106fe60e0830151936101206101008501519401612f25565b61300c60019160208082518301019101612f4d565b999093979594969861302081949394610fdd565b0361317757613038613031866118c6565b5460ff1690565b6131775761305496610c83968a519560208c019a8b5198612e7a565b61316957610a6b6130816130b1935192516040519283916020830195869091604092825260208201520190565b5190205f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b6002810154600881901c65ffffffffffff16801591908215613153575b8215613149575b508115613118575b50156130f057506001600160e01b031990565b600801546001600160a01b03166001600160a01b0316301461203d576001600160e01b031990565b609881901c60ff1615915081613130575b505f6130dd565b6001915065ffffffffffff9060681c811616105f613129565b421191505f6130d5565b4265ffffffffffff603884901c161192506130ce565b50506001600160e01b031990565b5050505050505050506001600160e01b031990565b9190916040818403126102765780356131a48161268f565b92602082013567ffffffffffffffff8111610276576106fe92016106e3565b61016081830312610276576131d781612699565b92602082013567ffffffffffffffff811161027657836131f89184016106e3565b92613205604084016110cb565b92606081013567ffffffffffffffff811161027657826132269183016106e3565b92608082013567ffffffffffffffff811161027657836132479184016106e3565b9260a08301359260c0810135926106fe60e083013593610120610100850135940161111e565b906101008201906132896132818385612119565b81019061318c565b919061329481610fdd565b806133c457506132a49250612eb5565b6001600160a01b03811630146133be578061333c6132f5613342936001600160a01b03165f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36d60205260405f2090565b9361332c855493600187015461330961040e565b958652602086015261331961041f565b9485526001600160a01b03166020850152565b5f60408401526060810190612119565b91613ef1565b61334c5750600190565b600201546106fe90613374600882901c65ffffffffffff165b9160381c65ffffffffffff1690565b7fffffffffffff000000000000000000000000000000000000000000000000000079ffffffffffff00000000000000000000000000000000000000009160d01b169160a01b161790565b50505f90565b9050600191506133d381610fdd565b146133e0575b5050600190565b6133ed6133f59183612119565b8101906131c3565b979998509061340c6130318b9794979695966118c6565b6134f85761342a95610c83958b958a519560208c019a8b5198612e7a565b6134ef57610a6b613081613457935192516040519283916020830195869091604092825260208201520190565b906002825492600181015461346a61040e565b948552602085015261347a61041f565b9384525f602085015260016040850152019161349b835460ff9060981c1690565b6134e75761333c8260606134b0940190612119565b156133d9576134d16134c46106fe936118c6565b600160ff19825416179055565b54613374600882901c65ffffffffffff16613365565b505050505f90565b50505050600190565b50505050505050505050600190565b7f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f369541461353057565b7f42a22abd000000000000000000000000000000000000000000000000000000005f5260045ffd5b30331480156135c7575b1561356957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f6e6f742066726f6d2073656c66206f7220456e747279506f696e7400000000006044820152fd5b50734337084d9e255ff0702461cf8895ce9e3b5ff1083314613562565b8054905f8155816135f3575050565b5f52600760205f20910160031c8101905b81811061360f575050565b5f8155600101613604565b600281019081549060ff82161561368f5773ffffffffffffffffffffffffffffffffffffffff199182169092555f6007830155600882018054909116905561041d906006905f60058201556136896004820173ffffffffffffffffffffffffffffffffffffffff198154169055565b016135e4565b7fc5b98844000000000000000000000000000000000000000000000000000000005f5260045ffd5b925f939184939260208451940192f190565b3d604051906020818301016040528082525f602083013e90565b6136eb6136c9565b602081519101fd5b60027f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36854146137425760027f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36855565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b90925f938493604051828152604060208201527f47d99ad340f52da66535aff7e10da1ceb85a32bcbd9fa1c42314d194545e14d26001600160a01b03861691806137b8604082018887612e40565b0390a2826040519384928337810185815203925af16137d5612181565b90156136eb5750565b92909391936040519384526020840152836040840152606083015260808201525f805260205f60a0836101005afa503d15613841575b507f7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a85f5160011491111090565b60209060a03d916dd01ea45f9efd5c54f037fa57ea1a5afa503d15613866575f613814565b63d0d5039b3d526004601cfd5b60405190613880826103cf565b5f60a08360608152606060208201528260408201528260608201528260808201520152565b90949392916138b45f92614074565b9560208201519081519060408401516060850151908a51918b600d84017f226368616c6c656e6765223a220000000000000000000000000000000000000060981c82528388019060208160138a600d898b0101106022602d8b880101515f1a141695012092012014169185826014011090821760801c109060207f2274797065223a22776562617574686e2e67657422000000000000000000000060581c918801015160581c1416169952835198895191151560021b6001178060218c0151161490602083111616988993846139b4575b50505050613994575b50505050565b6139aa94955060a06080820151910151916137de565b905f80808061398e565b60208080959850846001959750840101809882808084519a019601940160025afa831b5afa5192523d156139ec57855f808080613985565bfe5b6139fb91612ec291613d85565b6001600160a01b0316301490565b356106fe81610264565b9190918054831015610f82575f52601c60205f208360031c019260021b1690565b8054680100000000000000008110156103ae57613a5691600182018155613a13565b63ffffffff829392549160031b9260e01c831b921b1916179055565b99939065ffffffffffff9293613a9a613b29929b999b8d906020600191803584550135910155565b613aeb60028d0195613ab387600160ff19825416179055565b86547fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000ff1660089190911b66ffffffffffff0016178655565b84547fffffffffffffffffffffffffffffffffffffff000000000000ffffffffffffff1660389190911b6cffffffffffff0000000000000016178455565b825472ffffffffffff000000000000000000000000001916606882901b72ffffffffffff000000000000000000000000001617835582547fffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffff16911615609881901b73ff000000000000000000000000000000000000001691909117825560088901805473ffffffffffffffffffffffffffffffffffffffff19163017905515613bd7575b5050505050505050565b80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1683151560a01b74ff0000000000000000000000000000000000000000161790556007870155613c8e575b5050506001600160a01b03613c398261210f565b1615611b5557602081613c7c613c5060059461210f565b60048601906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b01359101555f80808080808080613bcd565b6001600160a01b03811615611b55576134c4613ce491613cc66134c4600389019283906001600160a01b03165f5260205260405f2090565b613ccf8661210f565b6001600160a01b03165f5260205260405f2090565b600a8111613d1e575f5b81811015613c255780613d18613d0f613d0a60019486886121b0565b613a09565b60068801613a34565b01613cee565b7f3c147f37000000000000000000000000000000000000000000000000000000005f5260045ffd5b91906040519260205f5b8083015182828801015201908483831015613d6f575090602090613d50565b915050604091808252015f602082015201604052565b8151919060418303613db557613dae9250602082015190606060408401519301515f1a9061417d565b9192909190565b50505f9160029190565b60041115610fe757565b613dd281613dbf565b80613ddb575050565b613de481613dbf565b60018103613e14577ff645eedf000000000000000000000000000000000000000000000000000000005f5260045ffd5b613e1d81613dbf565b60028103613e5157507ffce698f7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b80613e5d600392613dbf565b14613e655750565b7fd78bce0c000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b906004116102765790600490565b909291928360041161027657831161027657600401916003190190565b919091356001600160e01b031981169260048110613ed7575050565b6001600160e01b0319929350829060040360031b1b161690565b9190916040810160018151613f0581610fdd565b613f0e81610fdd565b0361400a575051805160209182015160408051938401928352830152613f3b916130818160608101610a6b565b915b6002830154600881901c65ffffffffffff1615908115613ffe575b50613ff7576008830154306001600160a01b0390911603613ff7576001600160e01b0319613f8f613f898484613e90565b90613ebb565b167fb61d27f6000000000000000000000000000000000000000000000000000000008114613fed577f47e1da2a0000000000000000000000000000000000000000000000000000000014613fe4575050505f90565b6106fe9261454d565b506106fe92614267565b5050505f90565b60ff161590505f613f58565b5161401481610fdd565b61401d81610fdd565b613ff757602001516001600160a01b03168015613ff75761406e906001600160a01b03165f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36d60205260405f2090565b91613f3d565b80516060929181614083575050565b9092506003600284010460021b604051937f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5f603f52602085019282860191602083019460208284010190600460038351955f85525b0191603f8351818160121c16515f538181600c1c1651600153818160061c165160025316516003535f51815201908782101561413d576004906003906140fc565b5095505f936003936040925201604052066002048093037f3d3d000000000000000000000000000000000000000000000000000000000000815252038252565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116141f4579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa15611c2c575f516001600160a01b038116156141ea57905f905f90565b505f906001905f90565b5050505f9160039190565b91606083830312610276578235614215816105ce565b92602081013592604082013567ffffffffffffffff8111610276576106fe92016106e3565b90602082519201516001600160e01b031981169260048110613ed7575050565b9190820391821161268a57565b9161427e81614286926001600160a01b0394613e9e565b8101906141ff565b92909116913083146134e757600284019182546142a78160ff9060981c1690565b6143ec5760681c65ffffffffffff169065ffffffffffff8216156143e2576007860191818354106143d7576142ea610c836142e18661423a565b60068a01614778565b6143d757614335905f190165ffffffffffff16855472ffffffffffff00000000000000000000000000191660689190911b72ffffffffffff0000000000000000000000000016178555565b806143c3575b50508261435561202060048701546001600160a01b031690565b146143ac575b505461436b9060a01c60ff161590565b918215614382575b505061437d575f90565b600190565b6143a592509060036130319201906001600160a01b03165f5260205260405f2090565b5f80614373565b610c836143b991856147bb565b613ff7575f61435b565b6143ce90825461425a565b90555f8061433b565b505050505050505f90565b5050505050505f90565b505050505050600190565b9080601f8301121561027657813561440e8161179c565b9261441c60405194856103eb565b81845260208085019260051b820101918383116102765760208201905b83821061444857505050505090565b813567ffffffffffffffff81116102765760209161446b878480948801016106e3565b815201910190614439565b9160608383031261027657823567ffffffffffffffff811161027657830182601f82011215610276578035906144ab8261179c565b916144b960405193846103eb565b80835260208084019160051b8301019185831161027657602001905b82821061451f5750505092602081013567ffffffffffffffff811161027657836145009183016117b4565b92604082013567ffffffffffffffff8111610276576106fe92016143f7565b60208091833561452e816105ce565b8152019101906144d5565b8051821015610f825760209160051b010190565b918061455c9161456493613e9e565b810190614476565b92908251936009851161476f5760028301908154614589610c838260ff9060981c1690565b6146fa575b505f5b8681106145a45750505050505050600190565b306145b5612020610b54848a614539565b146143d75782546145ca9060981c60ff161590565b6145d7575b600101614591565b6145f9610c836145f06145ea8486614539565b5161423a565b60068801614778565b6143d75760078501805461460d8387614539565b5181106146ed5761461e8387614539565b516146cf575b505060048501546001600160a01b03166001600160a01b0361464c612020610b54858b614539565b9116146146a8575b825460a01c60ff1680614672575b156145cf57505050505050505f90565b506146a3610c83613031614689610b54858b614539565b60038901906001600160a01b03165f5260205260405f2090565b614662565b6146bf610c836146b88385614539565b51876147bb565b1561465457505050505050505f90565b6146e4906146dd8488614539565b519061425a565b90555f80614624565b5050505050505050505f90565b60681c65ffffffffffff168665ffffffffffff8216106143d75761473161476991614724896147f9565b65ffffffffffff91031690565b835472ffffffffffff00000000000000000000000000191660689190911b72ffffffffffff0000000000000000000000000016178355565b5f61458e565b50505050505f90565b905f5b8254811015613ff75761478e8184613a13565b90549060031b1c60e01b6001600160e01b03198084169116146147b35760010161477b565b505050600190565b90805180601f1981011161268a5760059101519101805491828111613ff757806147e757505050600190565b820391821161268a57555f80806147b3565b65ffffffffffff81116148115765ffffffffffff1690565b7f6dfcc650000000000000000000000000000000000000000000000000000000005f52603060045260245260445ffdfea26469706673582212202ed48e20985b1a043e9d3f207cd8c1690cf99301b78ad59f31b7230d3252bb1664736f6c634300081d0033f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a000000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff108

Deployed Bytecode

0x60806040526004361015610010575b005b5f3560e01c806301ffc9a71461025f5780630c3b1ae91461025a578063110891c114610255578063150b7a02146102505780631626ba7e1461024b57806317f976721461024657806318f991021461024157806319822f7c1461023c57806325c1c3c31461023757806334fcd5be146102325780633f707e6b1461022d57806347e1da2a146102285780634e6fd6c4146102235780635a880de31461021e57806369d3c8651461021957806394c11608146102145780639c241abd1461020f578063a04b3e161461020a578063a2e8cf4014610205578063a7dc0fe614610200578063af640d0f146101fb578063affed0e0146101f6578063b0d691fe146101f1578063b2aa3f13146101ec578063b3ee7f11146101e7578063b61d27f6146101e2578063b75c8b78146101dd578063bc197c81146101d8578063bed5df4a146101d3578063c77d7805146101ce578063ce9124f3146101c9578063d087d288146101c4578063d180b1fc146101bf578063d86c2585146101ba578063eaf0188f146101b5578063f23a6e61146101b05763f4d2a1940361000e57611ea6565b611e34565b611d93565b611d42565b611c31565b611b7d565b6119ba565b61194d565b611904565b611811565b6116fe565b61166c565b61159d565b61145d565b6113cc565b611390565b611354565b6112cd565b611299565b611229565b61117c565b611099565b611054565b610ff9565b610f9b565b610e68565b610cdf565b610c20565b6109dd565b6108df565b610808565b6107c5565b610773565b610701565b6105df565b61050c565b61027a565b6001600160e01b031981160361027657565b5f80fd5b34610276576020600319360112610276576001600160e01b03196004356102a081610264565b167f01ffc9a7000000000000000000000000000000000000000000000000000000008114908115610354575b8115610343575b8115610319575b81156102ef575b506040519015158152602090f35b7f150b7a02000000000000000000000000000000000000000000000000000000009150145f6102e1565b7f4e2312e000000000000000000000000000000000000000000000000000000000811491506102da565b630b135d3f60e11b811491506102d3565b7f19822f7c00000000000000000000000000000000000000000000000000000000811491506102cc565b634e487b7160e01b5f52604160045260245ffd5b6040810190811067ffffffffffffffff8211176103ae57604052565b61037e565b6060810190811067ffffffffffffffff8211176103ae57604052565b60c0810190811067ffffffffffffffff8211176103ae57604052565b90601f601f19910116810190811067ffffffffffffffff8211176103ae57604052565b6040519061041d6040836103eb565b565b6040519061041d6060836103eb565b9060405161043b81610392565b602060018294805484520154910152565b9060405161045981610392565b6020600182946001600160a01b0381541684520154910152565b9a999896949290918b989694926101808a019c6104999160208091805184520151910152565b1515604089015265ffffffffffff16606088015265ffffffffffff16608087015265ffffffffffff1660a0860152151560c0850152151560e084015261010083019080516001600160a01b031682526020015190602001526101408201526101600161041d916001600160a01b03169052565b34610276576020600319360112610276576004355f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f206105538161042e565b6105ca6002830154926105686004820161044c565b90610582600860078301549201546001600160a01b031690565b9160405195869560ff8260a01c169160ff8160981c169165ffffffffffff8260681c169165ffffffffffff8160381c169160ff65ffffffffffff8360081c169216908b610473565b0390f35b6001600160a01b0381160361027657565b34610276576020600319360112610276576004356105fc816105ce565b6001600160a01b03165f9081527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36d602052604090206002015465ffffffffffff600882901c81169160ff8116916105ca91603881901c82169160689190911c165b9060405194859485929365ffffffffffff809296958160609560808801991515885216602087015216604085015216910152565b67ffffffffffffffff81116103ae57601f01601f191660200190565b9291926106b982610691565b916106c760405193846103eb565b829481845281830111610276578281602093845f960137010152565b9080601f83011215610276578160206106fe933591016106ad565b90565b346102765760806003193601126102765761071d6004356105ce565b6107286024356105ce565b60643567ffffffffffffffff8111610276576107489036906004016106e3565b5060206040517f150b7a02000000000000000000000000000000000000000000000000000000008152f35b346102765760406003193601126102765760043560243567ffffffffffffffff8111610276576020916107ad6107b39236906004016106e3565b90611f09565b6001600160e01b031960405191168152f35b34610276575f6003193601126102765760206040516001600160a01b037f000000000000000000000000bc8c14d7f4640f52f3a1ccec27164340215da74c168152f35b34610276576020600319360112610276576001600160a01b0360043561082d816105ce565b165f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36d60205260405f206108618161042e565b906105ca6002820154916108798360ff9060a01c1690565b906108866004820161044c565b61089f600860078401549301546001600160a01b031690565b92604051968660ff899860981c169165ffffffffffff8260681c169165ffffffffffff8160381c169160ff65ffffffffffff8360081c169216908b610473565b346102765760606003193601126102765760043567ffffffffffffffff81116102765761012060031982360301126102765760243590604435734337084d9e255ff0702461cf8895ce9e3b5ff108330361097f5761095060246109486105ca958560040161326d565b930135613507565b80610967575b506040519081529081906020820190565b5f80808093335af150610978612181565b505f610956565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f6163636f756e743a206e6f742066726f6d20456e747279506f696e74000000006044820152fd5b34610276575f600319360112610276576109f5613558565b5f5b7f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36a5481101561000e5780610a2c6001926121c0565b60408101838151610a3c81610fdd565b610a4581610fdd565b03610ae057505180516020918201516040805193840192835283015290610a7981606081015b03601f1981018352826103eb565b519020610ab5610ab0825f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b61361a565b7fa6293d3e6a2b62cf1a2218754c516fcf944f744d8794bb85842d57f0b1aa38a75f80a25b016109f7565b51610aea81610fdd565b610af381610fdd565b15610aff575b50610ada565b60200180516001600160a01b0316908115610bb957610b54610ab0610b61936001600160a01b03165f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36d60205260405f2090565b516001600160a01b031690565b604051610b8c81610a6b6020820194856bffffffffffffffffffffffff1960149260601b1681520190565b5190207fa6293d3e6a2b62cf1a2218754c516fcf944f744d8794bb85842d57f0b1aa38a75f80a25f610af9565b5050610ada565b9181601f840112156102765782359167ffffffffffffffff8311610276576020808501948460051b01011161027657565b6020600319820112610276576004359067ffffffffffffffff821161027657610c1c91600401610bc0565b9091565b3461027657610c2e36610bf1565b610c36613558565b5f5b818110610c4157005b610c87610c83610c7d610c558486886120cf565b610c5e8161210f565b90610c726020820135916040810190612119565b93905a9436916106ad565b916136b7565b1590565b610c9357600101610c38565b600182145f036136e357610ca56136c9565b90610cdb6040519283927f5a1546750000000000000000000000000000000000000000000000000000000084526004840161216a565b0390fd5b610ce836610bf1565b610cf06136f3565b610cf8613558565b80158015610e5e575b610e36575f5b818110610d375761000e60017f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36855565b610d428183856120cf565b610d4b8161210f565b90610d69610d626020830135926040810190612119565b36916106ad565b906001600160a01b03831692308414610e0e575f80918451908460208701915af1610d92612181565b9015610dd8575060019392917f47d99ad340f52da66535aff7e10da1ceb85a32bcbd9fa1c42314d194545e14d291610dcf6040519283928361216a565b0390a201610d07565b610cdb906040519182917faf05250e0000000000000000000000000000000000000000000000000000000083526004830161116b565b7f793426ed000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f1d453126000000000000000000000000000000000000000000000000000000005f5260045ffd5b5060098111610d01565b60606003193601126102765760043567ffffffffffffffff811161027657610e94903690600401610bc0565b9060243567ffffffffffffffff811161027657610eb5903690600401610bc0565b91909260443567ffffffffffffffff811161027657610ed8903690600401610bc0565b919092610ee36136f3565b610eeb613558565b600982118015610f91575b8015610f87575b610e36575f5b828110610f335761000e60017f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36855565b610f3e8184846121b0565b3590610f49826105ce565b610f5481888a6121b0565b359185821015610f8257600192610f7c91610f748460051b8a018a612119565b92909161376a565b01610f03565b6120bb565b5084821415610efd565b5082821415610ef6565b34610276575f60031936011261027657602060405173deadbeefdeadbeefdeadbeefdeadbeefdeadbeef8152f35b634e487b7160e01b5f52602160045260245ffd5b60021115610fe757565b610fc9565b906002821015610fe75752565b346102765760206003193601126102765760806110176004356121c0565b611052604080519261103484825160208091805184520151910152565b6001600160a01b036020820151168285015201516060830190610fec565bf35b346102765760206003193601126102765760606001600160a01b0361107a600435612258565b91929061108a6040518095610fec565b16602083015215156040820152f35b34610276575f600319360112610276576020604051600a8152f35b8015150361027657565b6024359061041d826110b4565b359061041d826110b4565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefc6040910112610276576040519061110d82610392565b610104358252610124356020830152565b91908260409103126102765760405161113681610392565b6020808294803584520135910152565b90601f19601f602080948051918291828752018686015e5f8582860101520116010190565b9060206106fe928181520190611146565b34610276576101406003193601126102765760043567ffffffffffffffff8111610276576111ae9036906004016106e3565b6111b66110be565b60443567ffffffffffffffff8111610276576111d69036906004016106e3565b916064359167ffffffffffffffff8311610276576105ca936111ff61121d9436906004016106e3565b60843560a4359160c4359360e43595611217366110d6565b976123ad565b6040519182918261116b565b34610276576020600319360112610276576004355f9081527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c602052604090206002015465ffffffffffff600882901c81169160ff8116916105ca91603881901c82169160689190911c1661065d565b346102765760a06003193601126102765760206112c36084356064356044356024356004356137de565b6040519015158152f35b34610276576020600319360112610276576004355f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36b602052608060405f20611052600261131b8361042e565b920154611335604051809460208091805184520151910152565b6001600160a01b038116604084015260ff606084019160a01c16610fec565b34610276575f6003193601126102765760207f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36a54604051908152f35b34610276575f6003193601126102765760207f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36954604051908152f35b34610276575f600319360112610276576020604051734337084d9e255ff0702461cf8895ce9e3b5ff1088152f35b60a06003198201126102765760043567ffffffffffffffff81116102765781611425916004016106e3565b91602435611432816110b4565b916044359067ffffffffffffffff821161027657611452916004016106e3565b906064359060843590565b34610276576105ca6114ba611471366113fa565b9361147d939193613873565b92805160c08110906020860190604087016060880190608089019260a08a019660208082019282010196156114cc575b50505050505050506138a5565b60405190151581529081906020820190565b81510194602086019182108760e08801111761154f5785825101602081019787604081015101602081019480861083871117908b10838c1117176115545760208281808094895101010111938b51010101111761154f5760c0968b5252606084015190526080830151905260a08201519052015190525f808080808080806114ad565b6114ad565b5050506114ad565b600319608091011261027657600490565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedc60409101126102765761012490565b3461027657610160600319360112610276576115b83661155c565b60407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c3601126102765760c43567ffffffffffffffff811161027657611602903690600401610bc0565b6101043592919060e43567ffffffffffffffff85116102765761162c61000e9536906004016106e3565b91610124359360846101443596612443565b9181601f840112156102765782359167ffffffffffffffff8311610276576020838186019501011161027657565b606060031936011261027657600435611684816105ce565b6024356044359167ffffffffffffffff8311610276576116ab6116c393369060040161163e565b9290916116b66136f3565b6116be613558565b61376a565b60017f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36855005b60c4359065ffffffffffff8216820361027657565b34610276576101a0600319360112610276576117193661155c565b6084359065ffffffffffff821682036102765760a43565ffffffffffff81168103610276576117466116e9565b9260e435611753816110b4565b61010435611760816105ce565b6117693661156d565b91610164359667ffffffffffffffff88116102765761178f61000e983690600401610bc0565b9690956101843598612c00565b67ffffffffffffffff81116103ae5760051b60200190565b9080601f830112156102765781356117cb8161179c565b926117d960405194856103eb565b81845260208085019260051b82010192831161027657602001905b8282106118015750505090565b81358152602091820191016117f4565b346102765760a06003193601126102765761182d6004356105ce565b6118386024356105ce565b60443567ffffffffffffffff8111610276576118589036906004016117b4565b5060643567ffffffffffffffff8111610276576118799036906004016117b4565b5060843567ffffffffffffffff81116102765761189a9036906004016106e3565b506040517fbc197c81000000000000000000000000000000000000000000000000000000008152602090f35b60208091604051928184925191829101835e81017f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36e81520301902090565b346102765760206003193601126102765760043567ffffffffffffffff81116102765760ff61194161193c60209336906004016106e3565b6118c6565b54166040519015158152f35b346102765760206003193601126102765760043567ffffffffffffffff8111610276576119a66119846105ca92369060040161163e565b610a6b6040939293519384925f60208501526040808501526060840191612e40565b604051918291602083526020830190611146565b34610276576080600319360112610276576119d43661155c565b6119dc613558565b6060810160016119eb8261284c565b6119f481610fdd565b03611a805750610a6b611a23602083359301356040519283916020830195869091604092825260208201520190565b519020611a5a610ab0825f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b7fa6293d3e6a2b62cf1a2218754c516fcf944f744d8794bb85842d57f0b1aa38a75f80a2005b611a899061284c565b611a9281610fdd565b15611a9957005b6040016001600160a01b03611aad8261210f565b1615611b555780611afc610ab0611ac6611b019461210f565b6001600160a01b03165f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36d60205260405f2090565b61210f565b604051611b2c81610a6b6020820194856bffffffffffffffffffffffff1960149260601b1681520190565b5190207fa6293d3e6a2b62cf1a2218754c516fcf944f744d8794bb85842d57f0b1aa38a75f80a2005b7faa093569000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610276575f600319360112610276576040517f35567e1a0000000000000000000000000000000000000000000000000000000081523060048201525f6024820152602081604481734337084d9e255ff0702461cf8895ce9e3b5ff1085afa8015611c2c576105ca915f91611bfd57506040519081529081906020820190565b611c1f915060203d602011611c25575b611c1781836103eb565b810190612e60565b5f610956565b503d611c0d565b612e6f565b34610276576105ca6114ba611c45366113fa565b93611c51939193613873565b9280516046811015611c65575b50506138a5565b810190602081015160f01c908181019160228301907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc85019384831115611cb0575b50505050611c5e565b611ce17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffba926022611cec9601613d46565b895285030190613d46565b60208601525160f01c60408501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffde81015160f01c6060850152601f1981015160808501525160a08401525f8080808080611ca7565b34610276576020600319360112610276576004355f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c602052602060ff600260405f200154166040519015158152f35b34610276576101406003193601126102765760043567ffffffffffffffff811161027657611dc59036906004016106e3565b611dcd6110be565b60443567ffffffffffffffff811161027657611ded9036906004016106e3565b916064359167ffffffffffffffff8311610276576105ca93611e166114ba9436906004016106e3565b60843560a4359060c4359260e4359461010435966101243598612e7a565b346102765760a060031936011261027657611e506004356105ce565b611e5b6024356105ce565b60843567ffffffffffffffff811161027657611e7b9036906004016106e3565b5060206040517ff23a6e61000000000000000000000000000000000000000000000000000000008152f35b34610276576020600319360112610276576001600160a01b03600435611ecb816105ce565b165f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36d602052602060ff600260405f200154166040519015158152f35b7f25622562256225622562256225622562256225622562256225622562256225628114806120b0575b15611f5b57506001602082015114611f5257505b6001600160e01b031990565b6106fe90612ff7565b908051604081149081156120a5575b50611f76575050611f46565b611f7f91612eb5565b6001600160a01b038116301461209957611fc9906001600160a01b03165f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36d60205260405f2090565b6002810154600881901c65ffffffffffff16801591908215612083575b8215612079575b508115612048575b501561200857506001600160e01b031990565b61202c6120206008309301546001600160a01b031690565b6001600160a01b031690565b1461203d576001600160e01b031990565b630b135d3f60e11b90565b609881901c60ff1615915081612060575b505f611ff5565b6001915065ffffffffffff9060681c811616105f612059565b421191505f611fed565b4265ffffffffffff603884901c16119250611fe6565b50630b135d3f60e11b90565b60419150145f611f6a565b506041825111611f32565b634e487b7160e01b5f52603260045260245ffd5b9190811015610f825760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610276570190565b356106fe816105ce565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610276570180359067ffffffffffffffff82116102765760200191813603831361027657565b6040906106fe939281528160208201520190611146565b3d156121ab573d9061219282610691565b916121a060405193846103eb565b82523d5f602084013e565b606090565b9190811015610f825760051b0190565b5f604080516121ce816103b3565b81516121d981610392565b838152836020820152815282602082015201525f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36b60205260405f2060ff600260405192612227846103b3565b6122308161042e565b845201546001600160a01b038116602084015260a01c166002811015610fe757604082015290565b612261906121c0565b9060408201916001835161227481610fdd565b61227d81610fdd565b0361233d5751805160209182015160408051938401928352830152906122a68160608101610a6b565b5190209151906122b582610fdd565b612337600261232f61230160086122f3885f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b01546001600160a01b031690565b955f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b015460ff1690565b91929190565b8291925161234a81610fdd565b61235381610fdd565b1561236a57505161236381610fdd565b905f905f90565b90602090519161237983610fdd565b0191612337600261232f611ac661239f60086122f3611ac68a516001600160a01b031690565b96516001600160a01b031690565b979294612416610a6b959661240461018099946106fe9b966123eb6040519e8f9d8e6123dc6020820160019052565b61016060408201520190611146565b91151560608d0152601f198c83030160808d0152611146565b90601f198a83030160a08b0152611146565b60c088019690965260e0870152610100860152610120850152805161014085015260200151610160840152565b95939196949290967ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549767ffffffffffffffff61249861248a60ff8c60401c1615151590565b9a67ffffffffffffffff1690565b168015908161265f575b6001149081612655575b15908161264c575b5061262457612535978961252c60017fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000007ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005416177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055565b6125bf576126f3565b61253b57565b61259068ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055565b604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1565b61261f6801000000000000000068ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005416177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055565b6126f3565b7ff92ee8a9000000000000000000000000000000000000000000000000000000005f5260045ffd5b9050155f6124b4565b303b1591506124ac565b8a91506124a2565b634e487b7160e01b5f52601160045260245ffd5b90612710820180921161268a57565b612667565b6002111561027657565b359061041d8261268f565b6080906126ef60606040519280358452602081013560208501526001600160a01b0360408201356126d4816105ce565b16604085015201356126e58161268f565b6060830190610fec565b2090565b9596949192939096612703613558565b60025b600681106127f6575061271886613507565b42116127ce5761272b91610c83916139ee565b6127a6576127809461275e61277b947f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36955565b61277561276a4261267b565b65ffffffffffff1690565b8561290d565b6126a4565b7f9be0ddb3ac5d6261cc8d736bf39c29feb13498533b6c9f960d8e175bf70e6a1a5f80a2565b7f91cc5825000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f032c52a5000000000000000000000000000000000000000000000000000000005f5260045ffd5b807ff3acd96a9d0e27e4323229f52dd3234ce23fb8133871d002e7cbb32c4a47a5c40190817ff3acd96a9d0e27e4323229f52dd3234ce23fb8133871d002e7cbb32c4a47a5c41161268a575f6001925501612706565b356106fe8161268f565b6002606091833581556020840135600182015501916128a5604082013561287c816105ce565b84906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b01356128b08161268f565b6002811015610fe75781547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1660a09190911b74ff000000000000000000000000000000000000000016179055565b5f19811461268a5760010190565b909193612918613558565b4265ffffffffffff84161115612bd8576129838261297e7f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36a545f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36b60205260405f2090565b612856565b6129d46129b07f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36a546128ff565b7f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36a55565b6060820160016129e38261284c565b6129ec81610fdd565b03612afe57509091928235610a6b612a1e60208601356040519283916020830195869091604092825260208201520190565b51902094612a58600261232f885f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b612ad65773deadbeefdeadbeefdeadbeefdeadbeefdeadbeef5f8080612ab0988198612aab8c5f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b613a72565b7fcd7f4163a8248a579c58031f40b757bb4998ed5f01c78bfb6ae1cd42edb95fb05f80a2565b7f2eb93649000000000000000000000000000000000000000000000000000000005f5260045ffd5b612b079061284c565b612b1081610fdd565b15612b1d575b5050505050565b60408201936001600160a01b03612b338661210f565b1615611b5557612b4a600261232f611ac68861210f565b612ad657612b7c9573deadbeefdeadbeefdeadbeefdeadbeefdeadbeef5f8080611afc988198612aab611ac68d61210f565b604051612ba781610a6b6020820194856bffffffffffffffffffffffff1960149260601b1681520190565b5190207fcd7f4163a8248a579c58031f40b757bb4998ed5f01c78bfb6ae1cd42edb95fb05f80a25f80808080612b16565b7ff5bab791000000000000000000000000000000000000000000000000000000005f5260045ffd5b96939098959297949197612c12613558565b65ffffffffffff8a1642811115612bd85765ffffffffffff8a1611612bd857612c878861297e7f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36a545f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36b60205260405f2090565b612cb46129b07f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36a546128ff565b606088016001612cc38261284c565b612ccc81610fdd565b03612d76575090919293949596978835610a6b612d0360208c01356040519283916020830195869091604092825260208201520190565b51902099612d3d600261232f8d5f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b612ad657612ab099612aab8c5f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b612d7f9061284c565b612d8881610fdd565b15612d9a575b50505050505050505050565b60408801986001600160a01b03612db08b61210f565b1615611b5557612dc7600261232f611ac68d61210f565b612ad657612ddf9a611afc99612aab611ac68d61210f565b604051612e0a81610a6b6020820194856bffffffffffffffffffffffff1960149260601b1681520190565b5190207fcd7f4163a8248a579c58031f40b757bb4998ed5f01c78bfb6ae1cd42edb95fb05f80a25f808080808080808080612d8e565b601f8260209493601f1993818652868601375f8582860101520116010190565b90816020910312610276575190565b6040513d5f823e3d90fd5b936106fe9998979396929695919560405197612e95896103cf565b8852602088015260408701526060860152608085015260a08401526138a5565b6106fe91612ec291613d85565b90929192613dc9565b519061041d8261268f565b81601f8201121561027657602081519101612ef082610691565b92612efe60405194856103eb565b8284528282011161027657815f926020928386015e8301015290565b519061041d826110b4565b919082604091031261027657604051612f3d81610392565b6020808294805184520151910152565b6101608183031261027657612f6181612ecb565b92602082015167ffffffffffffffff81116102765783612f82918401612ed6565b92612f8f60408401612f1a565b92606081015167ffffffffffffffff81116102765782612fb0918301612ed6565b92608082015167ffffffffffffffff81116102765783612fd1918401612ed6565b9260a08301519260c0810151926106fe60e0830151936101206101008501519401612f25565b61300c60019160208082518301019101612f4d565b999093979594969861302081949394610fdd565b0361317757613038613031866118c6565b5460ff1690565b6131775761305496610c83968a519560208c019a8b5198612e7a565b61316957610a6b6130816130b1935192516040519283916020830195869091604092825260208201520190565b5190205f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36c60205260405f2090565b6002810154600881901c65ffffffffffff16801591908215613153575b8215613149575b508115613118575b50156130f057506001600160e01b031990565b600801546001600160a01b03166001600160a01b0316301461203d576001600160e01b031990565b609881901c60ff1615915081613130575b505f6130dd565b6001915065ffffffffffff9060681c811616105f613129565b421191505f6130d5565b4265ffffffffffff603884901c161192506130ce565b50506001600160e01b031990565b5050505050505050506001600160e01b031990565b9190916040818403126102765780356131a48161268f565b92602082013567ffffffffffffffff8111610276576106fe92016106e3565b61016081830312610276576131d781612699565b92602082013567ffffffffffffffff811161027657836131f89184016106e3565b92613205604084016110cb565b92606081013567ffffffffffffffff811161027657826132269183016106e3565b92608082013567ffffffffffffffff811161027657836132479184016106e3565b9260a08301359260c0810135926106fe60e083013593610120610100850135940161111e565b906101008201906132896132818385612119565b81019061318c565b919061329481610fdd565b806133c457506132a49250612eb5565b6001600160a01b03811630146133be578061333c6132f5613342936001600160a01b03165f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36d60205260405f2090565b9361332c855493600187015461330961040e565b958652602086015261331961041f565b9485526001600160a01b03166020850152565b5f60408401526060810190612119565b91613ef1565b61334c5750600190565b600201546106fe90613374600882901c65ffffffffffff165b9160381c65ffffffffffff1690565b7fffffffffffff000000000000000000000000000000000000000000000000000079ffffffffffff00000000000000000000000000000000000000009160d01b169160a01b161790565b50505f90565b9050600191506133d381610fdd565b146133e0575b5050600190565b6133ed6133f59183612119565b8101906131c3565b979998509061340c6130318b9794979695966118c6565b6134f85761342a95610c83958b958a519560208c019a8b5198612e7a565b6134ef57610a6b613081613457935192516040519283916020830195869091604092825260208201520190565b906002825492600181015461346a61040e565b948552602085015261347a61041f565b9384525f602085015260016040850152019161349b835460ff9060981c1690565b6134e75761333c8260606134b0940190612119565b156133d9576134d16134c46106fe936118c6565b600160ff19825416179055565b54613374600882901c65ffffffffffff16613365565b505050505f90565b50505050600190565b50505050505050505050600190565b7f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f369541461353057565b7f42a22abd000000000000000000000000000000000000000000000000000000005f5260045ffd5b30331480156135c7575b1561356957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f6e6f742066726f6d2073656c66206f7220456e747279506f696e7400000000006044820152fd5b50734337084d9e255ff0702461cf8895ce9e3b5ff1083314613562565b8054905f8155816135f3575050565b5f52600760205f20910160031c8101905b81811061360f575050565b5f8155600101613604565b600281019081549060ff82161561368f5773ffffffffffffffffffffffffffffffffffffffff199182169092555f6007830155600882018054909116905561041d906006905f60058201556136896004820173ffffffffffffffffffffffffffffffffffffffff198154169055565b016135e4565b7fc5b98844000000000000000000000000000000000000000000000000000000005f5260045ffd5b925f939184939260208451940192f190565b3d604051906020818301016040528082525f602083013e90565b6136eb6136c9565b602081519101fd5b60027f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36854146137425760027f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36855565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b90925f938493604051828152604060208201527f47d99ad340f52da66535aff7e10da1ceb85a32bcbd9fa1c42314d194545e14d26001600160a01b03861691806137b8604082018887612e40565b0390a2826040519384928337810185815203925af16137d5612181565b90156136eb5750565b92909391936040519384526020840152836040840152606083015260808201525f805260205f60a0836101005afa503d15613841575b507f7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a85f5160011491111090565b60209060a03d916dd01ea45f9efd5c54f037fa57ea1a5afa503d15613866575f613814565b63d0d5039b3d526004601cfd5b60405190613880826103cf565b5f60a08360608152606060208201528260408201528260608201528260808201520152565b90949392916138b45f92614074565b9560208201519081519060408401516060850151908a51918b600d84017f226368616c6c656e6765223a220000000000000000000000000000000000000060981c82528388019060208160138a600d898b0101106022602d8b880101515f1a141695012092012014169185826014011090821760801c109060207f2274797065223a22776562617574686e2e67657422000000000000000000000060581c918801015160581c1416169952835198895191151560021b6001178060218c0151161490602083111616988993846139b4575b50505050613994575b50505050565b6139aa94955060a06080820151910151916137de565b905f80808061398e565b60208080959850846001959750840101809882808084519a019601940160025afa831b5afa5192523d156139ec57855f808080613985565bfe5b6139fb91612ec291613d85565b6001600160a01b0316301490565b356106fe81610264565b9190918054831015610f82575f52601c60205f208360031c019260021b1690565b8054680100000000000000008110156103ae57613a5691600182018155613a13565b63ffffffff829392549160031b9260e01c831b921b1916179055565b99939065ffffffffffff9293613a9a613b29929b999b8d906020600191803584550135910155565b613aeb60028d0195613ab387600160ff19825416179055565b86547fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000ff1660089190911b66ffffffffffff0016178655565b84547fffffffffffffffffffffffffffffffffffffff000000000000ffffffffffffff1660389190911b6cffffffffffff0000000000000016178455565b825472ffffffffffff000000000000000000000000001916606882901b72ffffffffffff000000000000000000000000001617835582547fffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffff16911615609881901b73ff000000000000000000000000000000000000001691909117825560088901805473ffffffffffffffffffffffffffffffffffffffff19163017905515613bd7575b5050505050505050565b80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1683151560a01b74ff0000000000000000000000000000000000000000161790556007870155613c8e575b5050506001600160a01b03613c398261210f565b1615611b5557602081613c7c613c5060059461210f565b60048601906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b01359101555f80808080808080613bcd565b6001600160a01b03811615611b55576134c4613ce491613cc66134c4600389019283906001600160a01b03165f5260205260405f2090565b613ccf8661210f565b6001600160a01b03165f5260205260405f2090565b600a8111613d1e575f5b81811015613c255780613d18613d0f613d0a60019486886121b0565b613a09565b60068801613a34565b01613cee565b7f3c147f37000000000000000000000000000000000000000000000000000000005f5260045ffd5b91906040519260205f5b8083015182828801015201908483831015613d6f575090602090613d50565b915050604091808252015f602082015201604052565b8151919060418303613db557613dae9250602082015190606060408401519301515f1a9061417d565b9192909190565b50505f9160029190565b60041115610fe757565b613dd281613dbf565b80613ddb575050565b613de481613dbf565b60018103613e14577ff645eedf000000000000000000000000000000000000000000000000000000005f5260045ffd5b613e1d81613dbf565b60028103613e5157507ffce698f7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b80613e5d600392613dbf565b14613e655750565b7fd78bce0c000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b906004116102765790600490565b909291928360041161027657831161027657600401916003190190565b919091356001600160e01b031981169260048110613ed7575050565b6001600160e01b0319929350829060040360031b1b161690565b9190916040810160018151613f0581610fdd565b613f0e81610fdd565b0361400a575051805160209182015160408051938401928352830152613f3b916130818160608101610a6b565b915b6002830154600881901c65ffffffffffff1615908115613ffe575b50613ff7576008830154306001600160a01b0390911603613ff7576001600160e01b0319613f8f613f898484613e90565b90613ebb565b167fb61d27f6000000000000000000000000000000000000000000000000000000008114613fed577f47e1da2a0000000000000000000000000000000000000000000000000000000014613fe4575050505f90565b6106fe9261454d565b506106fe92614267565b5050505f90565b60ff161590505f613f58565b5161401481610fdd565b61401d81610fdd565b613ff757602001516001600160a01b03168015613ff75761406e906001600160a01b03165f527f801ae8efc2175d3d963e799b27e0e948b9a3fa84e2ce105a370245c8c127f36d60205260405f2090565b91613f3d565b80516060929181614083575050565b9092506003600284010460021b604051937f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5f603f52602085019282860191602083019460208284010190600460038351955f85525b0191603f8351818160121c16515f538181600c1c1651600153818160061c165160025316516003535f51815201908782101561413d576004906003906140fc565b5095505f936003936040925201604052066002048093037f3d3d000000000000000000000000000000000000000000000000000000000000815252038252565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116141f4579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa15611c2c575f516001600160a01b038116156141ea57905f905f90565b505f906001905f90565b5050505f9160039190565b91606083830312610276578235614215816105ce565b92602081013592604082013567ffffffffffffffff8111610276576106fe92016106e3565b90602082519201516001600160e01b031981169260048110613ed7575050565b9190820391821161268a57565b9161427e81614286926001600160a01b0394613e9e565b8101906141ff565b92909116913083146134e757600284019182546142a78160ff9060981c1690565b6143ec5760681c65ffffffffffff169065ffffffffffff8216156143e2576007860191818354106143d7576142ea610c836142e18661423a565b60068a01614778565b6143d757614335905f190165ffffffffffff16855472ffffffffffff00000000000000000000000000191660689190911b72ffffffffffff0000000000000000000000000016178555565b806143c3575b50508261435561202060048701546001600160a01b031690565b146143ac575b505461436b9060a01c60ff161590565b918215614382575b505061437d575f90565b600190565b6143a592509060036130319201906001600160a01b03165f5260205260405f2090565b5f80614373565b610c836143b991856147bb565b613ff7575f61435b565b6143ce90825461425a565b90555f8061433b565b505050505050505f90565b5050505050505f90565b505050505050600190565b9080601f8301121561027657813561440e8161179c565b9261441c60405194856103eb565b81845260208085019260051b820101918383116102765760208201905b83821061444857505050505090565b813567ffffffffffffffff81116102765760209161446b878480948801016106e3565b815201910190614439565b9160608383031261027657823567ffffffffffffffff811161027657830182601f82011215610276578035906144ab8261179c565b916144b960405193846103eb565b80835260208084019160051b8301019185831161027657602001905b82821061451f5750505092602081013567ffffffffffffffff811161027657836145009183016117b4565b92604082013567ffffffffffffffff8111610276576106fe92016143f7565b60208091833561452e816105ce565b8152019101906144d5565b8051821015610f825760209160051b010190565b918061455c9161456493613e9e565b810190614476565b92908251936009851161476f5760028301908154614589610c838260ff9060981c1690565b6146fa575b505f5b8681106145a45750505050505050600190565b306145b5612020610b54848a614539565b146143d75782546145ca9060981c60ff161590565b6145d7575b600101614591565b6145f9610c836145f06145ea8486614539565b5161423a565b60068801614778565b6143d75760078501805461460d8387614539565b5181106146ed5761461e8387614539565b516146cf575b505060048501546001600160a01b03166001600160a01b0361464c612020610b54858b614539565b9116146146a8575b825460a01c60ff1680614672575b156145cf57505050505050505f90565b506146a3610c83613031614689610b54858b614539565b60038901906001600160a01b03165f5260205260405f2090565b614662565b6146bf610c836146b88385614539565b51876147bb565b1561465457505050505050505f90565b6146e4906146dd8488614539565b519061425a565b90555f80614624565b5050505050505050505f90565b60681c65ffffffffffff168665ffffffffffff8216106143d75761473161476991614724896147f9565b65ffffffffffff91031690565b835472ffffffffffff00000000000000000000000000191660689190911b72ffffffffffff0000000000000000000000000016178355565b5f61458e565b50505050505f90565b905f5b8254811015613ff75761478e8184613a13565b90549060031b1c60e01b6001600160e01b03198084169116146147b35760010161477b565b505050600190565b90805180601f1981011161268a5760059101519101805491828111613ff757806147e757505050600190565b820391821161268a57555f80806147b3565b65ffffffffffff81116148115765ffffffffffff1690565b7f6dfcc650000000000000000000000000000000000000000000000000000000005f52603060045260245260445ffdfea26469706673582212202ed48e20985b1a043e9d3f207cd8c1690cf99301b78ad59f31b7230d3252bb1664736f6c634300081d0033

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

0000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff108

-----Decoded View---------------
Arg [0] : _entryPoint (address): 0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000004337084d9e255ff0702461cf8895ce9e3b5ff108


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
Loading...
Loading

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.

OSZAR »