creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/MultisigPlugin.sol": {
        "content": "// This file is part of Multisig Plugin.\n//\n// Copyright 2024 Alchemy Insights, Inc.\n//\n// SPDX-License-Identifier: GPL-3.0-or-later\n//\n// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General\n// Public License as published by the Free Software Foundation, either version 3 of the License, or (at your\n// option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the\n// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n// more details.\n//\n// You should have received a copy of the GNU General Public License along with this program. If not, see\n// <https://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.22;\n\nimport {IERC1271} from \"@openzeppelin/contracts/interfaces/IERC1271.sol\";\nimport {ECDSA} from \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport {SignatureChecker} from \"@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol\";\nimport {SafeCast} from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\n\nimport {UUPSUpgradeable} from \"@alchemy/modular-account/ext/UUPSUpgradeable.sol\";\nimport {\n    PluginManifest,\n    PluginMetadata,\n    ManifestFunction,\n    ManifestAssociatedFunction,\n    ManifestAssociatedFunctionType,\n    SelectorPermission\n} from \"@alchemy/modular-account/src/interfaces/IPlugin.sol\";\nimport {BasePlugin} from \"@alchemy/modular-account/src/plugins/BasePlugin.sol\";\nimport {\n    AssociatedLinkedListSet,\n    AssociatedLinkedListSetLib\n} from \"@alchemy/modular-account/src/libraries/AssociatedLinkedListSetLib.sol\";\nimport {UserOperation} from \"@alchemy/modular-account/src/interfaces/erc4337/UserOperation.sol\";\nimport {SIG_VALIDATION_FAILED, SIG_VALIDATION_PASSED} from \"@alchemy/modular-account/src/libraries/Constants.sol\";\nimport {CastLib} from \"@alchemy/modular-account/src/helpers/CastLib.sol\";\nimport {IStandardExecutor} from \"@alchemy/modular-account/src/interfaces/IStandardExecutor.sol\";\nimport {UpgradeableModularAccount} from \"@alchemy/modular-account/src/account/UpgradeableModularAccount.sol\";\n\nimport {IMultisigPlugin} from \"./IMultisigPlugin.sol\";\n\n/// @title Multisig Plugin\n/// @author Alchemy\n/// @notice This plugin adds a k of n threshold ownership scheme to a ERC6900 smart contract account\n/// @notice Multisig verification impl is derived from [Safe](https://github.com/safe-global/safe-smart-account)\n///\n/// It supports [ERC-1271](https://eips.ethereum.org/EIPS/eip-1271) signature\n/// validation for both validating the signature on user operations and in\n/// exposing its own `isValidSignature` method. This only works when the owner of\n/// modular account also support ERC-1271.\n///\n/// ERC-4337's bundler validation rules limit the types of contracts that can be\n/// used as owners to validate user operation signatures. For example, the\n/// contract's `isValidSignature` function may not use any forbidden opcodes\n/// such as `TIMESTAMP` or `NUMBER`, and the contract may not be an ERC-1967\n/// proxy as it accesses a constant implementation slot not associated with\n/// the account, violating storage access rules. This also means that the\n/// owner of a modular account may not be another modular account if you want to\n/// send user operations through a bundler.\n\ncontract MultisigPlugin is BasePlugin, IMultisigPlugin, IERC1271 {\n    using AssociatedLinkedListSetLib for AssociatedLinkedListSet;\n    using ECDSA for bytes32;\n    using SafeCast for uint256;\n\n    string internal constant _NAME = \"Multisig Plugin\";\n    string internal constant _VERSION = \"1.0.0\";\n    string internal constant _AUTHOR = \"Alchemy\";\n\n    bytes32 private constant _TYPE_HASH =\n        keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)\");\n    bytes32 private constant _HASHED_NAME = keccak256(bytes(_NAME));\n    bytes32 private constant _HASHED_VERSION = keccak256(bytes(_VERSION));\n    bytes32 private immutable _SALT = bytes32(bytes20(address(this)));\n\n    // bytes4(keccak256(\"isValidSignature(bytes32,bytes)\"))\n    bytes4 internal constant _1271_MAGIC_VALUE = 0x1626ba7e;\n    bytes4 internal constant _1271_MAGIC_VALUE_FAILURE = 0xffffffff;\n\n    bytes32 private constant _MULTISIG_PLUGIN_TYPEHASH = keccak256(\"AlchemyMultisigMessage(bytes message)\");\n\n    AssociatedLinkedListSet internal _owners;\n    mapping(address => OwnershipMetadata) internal _ownerMetadata;\n    address public immutable ENTRYPOINT;\n\n    /// @notice Metadata of the ownership of an account.\n    /// @param numOwners number of owners on the account\n    /// @param threshold number of signatures required to perform an action\n    struct OwnershipMetadata {\n        uint128 numOwners;\n        uint128 threshold;\n    }\n\n    constructor(address entryPoint) {\n        ENTRYPOINT = entryPoint;\n    }\n\n    // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n    // ┃    Execution functions    ┃\n    // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n\n    /// @inheritdoc IMultisigPlugin\n    /// @dev If an owner is present in both ownersToAdd and ownersToRemove, it will be added as owner.\n    /// The owner array cannot have 0 or duplicated addresses.\n    function updateOwnership(address[] memory ownersToAdd, address[] memory ownersToRemove, uint128 newThreshold)\n        public\n        isInitialized(msg.sender)\n    {\n        // update owners array\n        uint256 toRemoveLen = ownersToRemove.length;\n        for (uint256 i = 0; i < toRemoveLen; ++i) {\n            if (!_owners.tryRemove(msg.sender, CastLib.toSetValue(ownersToRemove[i]))) {\n                revert OwnerDoesNotExist(ownersToRemove[i]);\n            }\n        }\n\n        _addOwnersOrRevert(msg.sender, ownersToAdd);\n\n        OwnershipMetadata storage metadata = _ownerMetadata[msg.sender];\n        uint256 numOwners = metadata.numOwners;\n\n        uint256 toAddLen = ownersToAdd.length;\n        if (toAddLen != toRemoveLen) {\n            numOwners = numOwners - toRemoveLen + toAddLen;\n            if (numOwners == 0) {\n                revert EmptyOwnersNotAllowed();\n            }\n            metadata.numOwners = numOwners.toUint128();\n        }\n\n        // If newThreshold is zero, don't update and keep the previous threshold value\n        if (newThreshold != 0) {\n            metadata.threshold = newThreshold;\n        }\n        if (metadata.threshold > numOwners) {\n            revert InvalidThreshold();\n        }\n\n        emit OwnerUpdated(msg.sender, ownersToAdd, ownersToRemove, newThreshold);\n    }\n\n    // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n    // ┃  Execution view functions   ┃\n    // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n\n    /// @inheritdoc IMultisigPlugin\n    function eip712Domain()\n        public\n        view\n        override\n        returns (\n            bytes1 fields,\n            string memory name,\n            string memory version,\n            uint256 chainId,\n            address verifyingContract,\n            bytes32 salt,\n            uint256[] memory extensions\n        )\n    {\n        return (\n            hex\"1f\", // 11111 indicate salt field is also used\n            _NAME,\n            _VERSION,\n            block.chainid,\n            msg.sender,\n            _SALT,\n            new uint256[](0)\n        );\n    }\n\n    /// @inheritdoc IERC1271\n    function isValidSignature(bytes32 digest, bytes memory signature) external view override returns (bytes4) {\n        bytes32 wrappedDigest = getMessageHash(msg.sender, abi.encode(digest));\n        (bool success,) = checkNSignatures(wrappedDigest, wrappedDigest, msg.sender, signature);\n\n        return success ? _1271_MAGIC_VALUE : _1271_MAGIC_VALUE_FAILURE;\n    }\n\n    // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n    // ┃    Plugin interface functions    ┃\n    // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n\n    /// @inheritdoc BasePlugin\n    function onUninstall(bytes calldata) external override {\n        address[] memory ownersToRemove = CastLib.toAddressArray(_owners.getAll(msg.sender));\n        _owners.clear(msg.sender);\n        _ownerMetadata[msg.sender] = OwnershipMetadata(0, 0);\n        emit OwnerUpdated(msg.sender, new address[](0), ownersToRemove, 0);\n    }\n\n    /// @inheritdoc BasePlugin\n    function userOpValidationFunction(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash)\n        external\n        view\n        override\n        returns (uint256)\n    {\n        if (functionId == uint8(FunctionId.USER_OP_VALIDATION_OWNER)) {\n            // UserOp.sig format:\n            // 0-32: upperLimitPreVerificationGas\n            // 32-64: upperLimitMaxFeePerGas\n            // 64-96: upperLimitMaxPriorityFeePerGas\n            // 96-96+n: k signatures, each sig is 65 bytes each (so n = 65 * k)\n            // 96+n-: contract signatures if any\n            if (userOp.signature.length < 96) {\n                revert InvalidSigLength();\n            }\n\n            (\n                uint256 upperLimitPreVerificationGas,\n                uint256 upperLimitMaxFeePerGas,\n                uint256 upperLimitMaxPriorityFeePerGas\n            ) = abi.decode(userOp.signature[0:96], (uint256, uint256, uint256));\n\n            bytes32 actualDigest = userOpHash.toEthSignedMessageHash();\n            bytes32 upperLimitDigest = (\n                upperLimitPreVerificationGas == userOp.preVerificationGas\n                    && upperLimitMaxFeePerGas == userOp.maxFeePerGas\n                    && upperLimitMaxPriorityFeePerGas == userOp.maxPriorityFeePerGas\n            )\n                ? actualDigest\n                : _getUserOpHash(\n                    userOp, upperLimitPreVerificationGas, upperLimitMaxFeePerGas, upperLimitMaxPriorityFeePerGas\n                ).toEthSignedMessageHash();\n            (bool success,) = checkNSignatures(actualDigest, upperLimitDigest, msg.sender, userOp.signature[96:]);\n\n            // make sure userOp doesnt use more than the max fees\n            // we revert here as its better DevEx over silently failing in case a bad dummy sig is used\n            if (upperLimitPreVerificationGas < userOp.preVerificationGas) {\n                revert InvalidPreVerificationGas();\n            }\n            if (upperLimitMaxFeePerGas < userOp.maxFeePerGas) {\n                revert InvalidMaxFeePerGas();\n            }\n            if (upperLimitMaxPriorityFeePerGas < userOp.maxPriorityFeePerGas) {\n                revert InvalidMaxPriorityFeePerGas();\n            }\n\n            return success ? SIG_VALIDATION_PASSED : SIG_VALIDATION_FAILED;\n        }\n\n        revert NotImplemented(msg.sig, functionId);\n    }\n\n    /// @inheritdoc BasePlugin\n    function pluginManifest() external pure override returns (PluginManifest memory) {\n        PluginManifest memory manifest;\n\n        manifest.executionFunctions = new bytes4[](3);\n        manifest.executionFunctions[0] = this.updateOwnership.selector;\n        manifest.executionFunctions[1] = this.eip712Domain.selector;\n        manifest.executionFunctions[2] = this.isValidSignature.selector;\n\n        ManifestFunction memory ownerUserOpValidationFunction = ManifestFunction({\n            functionType: ManifestAssociatedFunctionType.SELF,\n            functionId: uint8(FunctionId.USER_OP_VALIDATION_OWNER),\n            dependencyIndex: 0 // Unused.\n        });\n\n        // Update Modular Account's native functions to use userOpValidationFunction provided by this plugin\n        // The view functions `isValidSignature` and `eip712Domain` are excluded from being assigned a user\n        // operation validation function since they should only be called via the runtime path.\n        manifest.userOpValidationFunctions = new ManifestAssociatedFunction[](6);\n        manifest.userOpValidationFunctions[0] = ManifestAssociatedFunction({\n            executionSelector: this.updateOwnership.selector,\n            associatedFunction: ownerUserOpValidationFunction\n        });\n        manifest.userOpValidationFunctions[1] = ManifestAssociatedFunction({\n            executionSelector: IStandardExecutor.execute.selector,\n            associatedFunction: ownerUserOpValidationFunction\n        });\n        manifest.userOpValidationFunctions[2] = ManifestAssociatedFunction({\n            executionSelector: IStandardExecutor.executeBatch.selector,\n            associatedFunction: ownerUserOpValidationFunction\n        });\n        manifest.userOpValidationFunctions[3] = ManifestAssociatedFunction({\n            executionSelector: UpgradeableModularAccount.installPlugin.selector,\n            associatedFunction: ownerUserOpValidationFunction\n        });\n        manifest.userOpValidationFunctions[4] = ManifestAssociatedFunction({\n            executionSelector: UpgradeableModularAccount.uninstallPlugin.selector,\n            associatedFunction: ownerUserOpValidationFunction\n        });\n        manifest.userOpValidationFunctions[5] = ManifestAssociatedFunction({\n            executionSelector: UUPSUpgradeable.upgradeToAndCall.selector,\n            associatedFunction: ownerUserOpValidationFunction\n        });\n\n        ManifestFunction memory alwaysAllowFunction = ManifestFunction({\n            functionType: ManifestAssociatedFunctionType.RUNTIME_VALIDATION_ALWAYS_ALLOW,\n            functionId: 0, // Unused.\n            dependencyIndex: 0 // Unused.\n        });\n        ManifestFunction memory alwaysRevertFunction = ManifestFunction({\n            functionType: ManifestAssociatedFunctionType.SELF,\n            functionId: 0,\n            dependencyIndex: 0 // Unused.\n        });\n        manifest.runtimeValidationFunctions = new ManifestAssociatedFunction[](8);\n        manifest.runtimeValidationFunctions[0] = ManifestAssociatedFunction({\n            executionSelector: this.isValidSignature.selector,\n            associatedFunction: alwaysAllowFunction\n        });\n        manifest.runtimeValidationFunctions[1] = ManifestAssociatedFunction({\n            executionSelector: this.eip712Domain.selector,\n            associatedFunction: alwaysAllowFunction\n        });\n        manifest.runtimeValidationFunctions[2] = ManifestAssociatedFunction({\n            executionSelector: this.updateOwnership.selector,\n            associatedFunction: alwaysRevertFunction\n        });\n        manifest.runtimeValidationFunctions[3] = ManifestAssociatedFunction({\n            executionSelector: IStandardExecutor.execute.selector,\n            associatedFunction: alwaysRevertFunction\n        });\n        manifest.runtimeValidationFunctions[4] = ManifestAssociatedFunction({\n            executionSelector: IStandardExecutor.executeBatch.selector,\n            associatedFunction: alwaysRevertFunction\n        });\n        manifest.runtimeValidationFunctions[5] = ManifestAssociatedFunction({\n            executionSelector: UpgradeableModularAccount.installPlugin.selector,\n            associatedFunction: alwaysRevertFunction\n        });\n        manifest.runtimeValidationFunctions[6] = ManifestAssociatedFunction({\n            executionSelector: UpgradeableModularAccount.uninstallPlugin.selector,\n            associatedFunction: alwaysRevertFunction\n        });\n        manifest.runtimeValidationFunctions[7] = ManifestAssociatedFunction({\n            executionSelector: UUPSUpgradeable.upgradeToAndCall.selector,\n            associatedFunction: alwaysRevertFunction\n        });\n\n        return manifest;\n    }\n\n    /// @inheritdoc BasePlugin\n    function pluginMetadata() external pure virtual override returns (PluginMetadata memory) {\n        PluginMetadata memory metadata;\n        metadata.name = _NAME;\n        metadata.version = _VERSION;\n        metadata.author = _AUTHOR;\n\n        // Permission strings\n        string memory modifyOwnershipPermission = \"Modify Ownership\";\n\n        // Permission descriptions\n        metadata.permissionDescriptors = new SelectorPermission[](1);\n        metadata.permissionDescriptors[0] = SelectorPermission({\n            functionSelector: this.updateOwnership.selector,\n            permissionDescription: modifyOwnershipPermission\n        });\n\n        return metadata;\n    }\n\n    // ┏━━━━━━━━━━━━━━━┓\n    // ┃    EIP-165    ┃\n    // ┗━━━━━━━━━━━━━━━┛\n\n    /// @inheritdoc BasePlugin\n    function supportsInterface(bytes4 interfaceId) public view override returns (bool) {\n        return interfaceId == type(IMultisigPlugin).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n    // ┃    Plugin only view functions    ┃\n    // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n\n    /// @inheritdoc IMultisigPlugin\n    function checkNSignatures(\n        bytes32 actualDigest,\n        bytes32 upperLimitGasDigest,\n        address account,\n        bytes memory signatures\n    ) public view returns (bool success, uint256 firstFailure) {\n        uint256 threshold = uint256(_ownerMetadata[account].threshold);\n\n        // sig length must be longer than k * 65 bytes\n        uint256 offset = 65 * threshold;\n        if (signatures.length < offset) {\n            revert InvalidSigLength();\n        }\n\n        address lastOwner;\n        address currentOwner;\n        uint8 v;\n        bytes32 r;\n        bytes32 s;\n        // if the digests differ, make sure we have at least 1 sig on the digest using the actual gas values\n        uint256 numSigsOnActualGas = (actualDigest != upperLimitGasDigest) ? 1 : 0;\n        success = true;\n\n        for (uint256 i = 0; i < threshold; i++) {\n            (v, r, s) = _signatureSplit(signatures, i);\n\n            // v >= 32 implies it's signed over the actual digest\n            // if v > 60, it will fail the ecdsa recover check below\n            bytes32 digest;\n            if (v >= 32) {\n                digest = actualDigest;\n                v -= 32;\n                // Can have unchecked since we check against zero at the end\n                unchecked {\n                    numSigsOnActualGas -= 1;\n                }\n            } else {\n                digest = upperLimitGasDigest;\n            }\n\n            // v == 0 is the contract owner case\n            if (v == 0) {\n                // s is the memory offset containing the signature\n                bytes memory contractSignature;\n                {\n                    uint256 sigOffset = uint256(s);\n                    if (offset != sigOffset) {\n                        revert InvalidSigOffset();\n                    }\n\n                    uint256 totalContractSigLen;\n                    assembly (\"memory-safe\") {\n                        contractSignature := add(add(signatures, offset), 0x20)\n                        totalContractSigLen := add(mload(contractSignature), 0x20) // prefixed 32 bytes of len(bytes)\n                    }\n                    offset += totalContractSigLen;\n                }\n\n                // r contains the address to perform 1271 validation on\n                currentOwner = address(uint160(uint256(r)));\n                // make sure upper bits are clean\n                if (uint256(r) > uint256(uint160(currentOwner))) {\n                    revert InvalidAddress();\n                }\n\n                if (!SignatureChecker.isValidERC1271SignatureNow(currentOwner, digest, contractSignature)) {\n                    if (success) {\n                        firstFailure = i;\n                        success = false;\n                    }\n                }\n            } else {\n                // reverts if signature has the wrong s value, wrong v value, or if it's a bad point on the k1 curve\n                currentOwner = digest.recover(v, r, s);\n            }\n\n            if (currentOwner <= lastOwner || !_owners.contains(account, CastLib.toSetValue(currentOwner))) {\n                if (success) {\n                    firstFailure = i;\n                    success = false;\n                }\n            }\n            lastOwner = currentOwner;\n        }\n\n        // if the signature is longer than the offset, it means that there are extra bytes not used in the signature\n        if (signatures.length > offset) {\n            revert InvalidSigOffset();\n        }\n\n        // if we need a signature on the actual gas, and we didn't get one, revert\n        // or if we got more signatures on the actual gas than expected, revert\n        if (numSigsOnActualGas != 0) {\n            revert InvalidNumSigsOnActualGas();\n        }\n    }\n\n    /// @inheritdoc IMultisigPlugin\n    function isOwnerOf(address account, address ownerToCheck) external view returns (bool) {\n        return _owners.contains(account, CastLib.toSetValue(ownerToCheck));\n    }\n\n    /// @inheritdoc IMultisigPlugin\n    function ownershipInfoOf(address account) external view returns (address[] memory, uint256) {\n        return (CastLib.toAddressArray(_owners.getAll(account)), uint256(_ownerMetadata[account].threshold));\n    }\n\n    /// @inheritdoc IMultisigPlugin\n    function encodeMessageData(address account, bytes memory message) public view override returns (bytes memory) {\n        bytes32 messageHash = keccak256(abi.encode(_MULTISIG_PLUGIN_TYPEHASH, keccak256(message)));\n        return abi.encodePacked(\"\\x19\\x01\", _domainSeparator(account), messageHash);\n    }\n\n    /// @inheritdoc IMultisigPlugin\n    function getMessageHash(address account, bytes memory message) public view override returns (bytes32) {\n        return keccak256(encodeMessageData(account, message));\n    }\n\n    // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n    // ┃    Internal Functions    ┃\n    // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n\n    /// @inheritdoc BasePlugin\n    /// @dev The owner array cannot have 0 or duplicated addresses.\n    function _onInstall(bytes calldata data) internal override isNotInitialized(msg.sender) {\n        (address[] memory initialOwners, uint128 threshold) = abi.decode(data, (address[], uint128));\n        if (initialOwners.length == 0) {\n            revert EmptyOwnersNotAllowed();\n        }\n        if (threshold == 0 || threshold > initialOwners.length) {\n            revert InvalidThreshold();\n        }\n\n        _addOwnersOrRevert(msg.sender, initialOwners);\n        _ownerMetadata[msg.sender] = OwnershipMetadata(uint128(initialOwners.length), threshold);\n\n        emit OwnerUpdated(msg.sender, initialOwners, new address[](0), threshold);\n    }\n\n    /// @dev Helper function to get a 65 byte signature from a multi-signature\n    /// @dev Functions using this must make sure the signature is long enough to contain k * 65 bytes\n    function _signatureSplit(bytes memory signatures, uint256 pos)\n        internal\n        pure\n        returns (uint8 v, bytes32 r, bytes32 s)\n    {\n        assembly (\"memory-safe\") {\n            let signaturePos := mul(0x41, pos)\n            r := mload(add(signatures, add(signaturePos, 0x20)))\n            s := mload(add(signatures, add(signaturePos, 0x40)))\n            v := byte(0, mload(add(signatures, add(signaturePos, 0x60))))\n        }\n    }\n\n    function _domainSeparator(address account) internal view returns (bytes32) {\n        return keccak256(abi.encode(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION, block.chainid, account, _SALT));\n    }\n\n    function _addOwnersOrRevert(address account, address[] memory ownersToAdd) internal {\n        uint256 len = ownersToAdd.length;\n        for (uint256 i = 0; i < len; ++i) {\n            if (!_owners.tryAdd(account, CastLib.toSetValue(ownersToAdd[i]))) {\n                revert InvalidOwner(ownersToAdd[i]);\n            }\n        }\n    }\n\n    /// @inheritdoc BasePlugin\n    function _isInitialized(address account) internal view override returns (bool) {\n        return !_owners.isEmpty(account);\n    }\n\n    function _getUserOpHash(\n        UserOperation calldata userOp,\n        uint256 upperLimitPreVerificationGas,\n        uint256 upperLimitMaxFeePerGas,\n        uint256 upperLimitMaxPriorityFeePerGas\n    ) internal view returns (bytes32) {\n        address sender;\n        assembly (\"memory-safe\") {\n            sender := calldataload(userOp)\n        }\n        uint256 nonce = userOp.nonce;\n        bytes32 hashInitCode = _calldataKeccak(userOp.initCode);\n        bytes32 hashCallData = _calldataKeccak(userOp.callData);\n        uint256 callGasLimit = userOp.callGasLimit;\n        uint256 verificationGasLimit = userOp.verificationGasLimit;\n        uint256 preVerificationGas = upperLimitPreVerificationGas;\n        uint256 maxFeePerGas = upperLimitMaxFeePerGas;\n        uint256 maxPriorityFeePerGas = upperLimitMaxPriorityFeePerGas;\n        bytes32 hashPaymasterAndData = _calldataKeccak(userOp.paymasterAndData);\n\n        bytes32 userOpHash = keccak256(\n            abi.encode(\n                sender,\n                nonce,\n                hashInitCode,\n                hashCallData,\n                callGasLimit,\n                verificationGasLimit,\n                preVerificationGas,\n                maxFeePerGas,\n                maxPriorityFeePerGas,\n                hashPaymasterAndData\n            )\n        );\n\n        return keccak256(abi.encode(userOpHash, ENTRYPOINT, block.chainid));\n    }\n\n    function _calldataKeccak(bytes calldata data) internal pure returns (bytes32 ret) {\n        assembly (\"memory-safe\") {\n            let mem := mload(0x40)\n            let len := data.length\n            calldatacopy(mem, data.offset, len)\n            ret := keccak256(mem, len)\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/IERC1271.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC1271 standard signature validation method for\n * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].\n *\n * _Available since v4.1._\n */\ninterface IERC1271 {\n    /**\n     * @dev Should return whether the signature provided is valid for the provided data\n     * @param hash      Hash of the data to be signed\n     * @param signature Signature byte array associated with _data\n     */\n    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n    enum RecoverError {\n        NoError,\n        InvalidSignature,\n        InvalidSignatureLength,\n        InvalidSignatureS,\n        InvalidSignatureV // Deprecated in v4.8\n    }\n\n    function _throwError(RecoverError error) private pure {\n        if (error == RecoverError.NoError) {\n            return; // no error: do nothing\n        } else if (error == RecoverError.InvalidSignature) {\n            revert(\"ECDSA: invalid signature\");\n        } else if (error == RecoverError.InvalidSignatureLength) {\n            revert(\"ECDSA: invalid signature length\");\n        } else if (error == RecoverError.InvalidSignatureS) {\n            revert(\"ECDSA: invalid signature 's' value\");\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature` or error string. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     *\n     * Documentation for signature generation:\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n        if (signature.length == 65) {\n            bytes32 r;\n            bytes32 s;\n            uint8 v;\n            // ecrecover takes the signature parameters, and the only way to get them\n            // currently is to use assembly.\n            /// @solidity memory-safe-assembly\n            assembly {\n                r := mload(add(signature, 0x20))\n                s := mload(add(signature, 0x40))\n                v := byte(0, mload(add(signature, 0x60)))\n            }\n            return tryRecover(hash, v, r, s);\n        } else {\n            return (address(0), RecoverError.InvalidSignatureLength);\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature`. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     */\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, signature);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n     *\n     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n        uint8 v = uint8((uint256(vs) >> 255) + 27);\n        return tryRecover(hash, v, r, s);\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n     *\n     * _Available since v4.2._\n     */\n    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n        //\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n        // these malleable signatures as well.\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n            return (address(0), RecoverError.InvalidSignatureS);\n        }\n\n        // If the signature is valid (and not malleable), return the signer address\n        address signer = ecrecover(hash, v, r, s);\n        if (signer == address(0)) {\n            return (address(0), RecoverError.InvalidSignature);\n        }\n\n        return (signer, RecoverError.NoError);\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n     * produces hash corresponding to the one signed with the\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n     * JSON-RPC method as part of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n        // 32 is the length in bytes of hash,\n        // enforced by the type signature above\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n            mstore(0x1c, hash)\n            message := keccak256(0x00, 0x3c)\n        }\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from `s`. This\n     * produces hash corresponding to the one signed with the\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n     * JSON-RPC method as part of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Typed Data, created from a\n     * `domainSeparator` and a `structHash`. This produces hash corresponding\n     * to the one signed with the\n     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n     * JSON-RPC method as part of EIP-712.\n     *\n     * See {recover}.\n     */\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let ptr := mload(0x40)\n            mstore(ptr, \"\\x19\\x01\")\n            mstore(add(ptr, 0x02), domainSeparator)\n            mstore(add(ptr, 0x22), structHash)\n            data := keccak256(ptr, 0x42)\n        }\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Data with intended validator, created from a\n     * `validator` and `data` according to the version 0 of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/cryptography/SignatureChecker.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/SignatureChecker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\nimport \"../../interfaces/IERC1271.sol\";\n\n/**\n * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA\n * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like\n * Argent and Gnosis Safe.\n *\n * _Available since v4.1._\n */\nlibrary SignatureChecker {\n    /**\n     * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the\n     * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.\n     *\n     * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\n     * change through time. It could return true at block N and false at block N+1 (or the opposite).\n     */\n    function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) {\n        (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);\n        return\n            (error == ECDSA.RecoverError.NoError && recovered == signer) ||\n            isValidERC1271SignatureNow(signer, hash, signature);\n    }\n\n    /**\n     * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated\n     * against the signer smart contract using ERC1271.\n     *\n     * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\n     * change through time. It could return true at block N and false at block N+1 (or the opposite).\n     */\n    function isValidERC1271SignatureNow(\n        address signer,\n        bytes32 hash,\n        bytes memory signature\n    ) internal view returns (bool) {\n        (bool success, bytes memory result) = signer.staticcall(\n            abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)\n        );\n        return (success &&\n            result.length >= 32 &&\n            abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value >= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n"
      },
      "lib/modular-account/ext/UUPSUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice UUPS proxy mixin.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/UUPSUpgradeable.sol)\n/// @author Modified from OpenZeppelin\n/// (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/utils/UUPSUpgradeable.sol)\n///\n/// Note:\n/// - This implementation is intended to be used with ERC1967 proxies.\n/// See: `LibClone.deployERC1967` and related functions.\n/// - This implementation is NOT compatible with legacy OpenZeppelin proxies\n/// which do not store the implementation at `_ERC1967_IMPLEMENTATION_SLOT`.\nabstract contract UUPSUpgradeable {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                       CUSTOM ERRORS                        */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The upgrade failed.\n    error UpgradeFailed();\n\n    /// @dev The call is from an unauthorized call context.\n    error UnauthorizedCallContext();\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                         IMMUTABLES                         */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev For checking if the context is a delegate call.\n    uint256 private immutable __self = uint256(uint160(address(this)));\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                           EVENTS                           */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Emitted when the proxy's implementation is upgraded.\n    event Upgraded(address indexed implementation);\n\n    /// @dev `keccak256(bytes(\"Upgraded(address)\"))`.\n    uint256 private constant _UPGRADED_EVENT_SIGNATURE =\n        0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                          STORAGE                           */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The ERC-1967 storage slot for the implementation in the proxy.\n    /// `uint256(keccak256(\"eip1967.proxy.implementation\")) - 1`.\n    bytes32 internal constant _ERC1967_IMPLEMENTATION_SLOT =\n        0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                      UUPS OPERATIONS                       */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Please override this function to check if `msg.sender` is authorized\n    /// to upgrade the proxy to `newImplementation`, reverting if not.\n    /// ```\n    ///     function _authorizeUpgrade(address) internal override onlyOwner {}\n    /// ```\n    function _authorizeUpgrade(address newImplementation) internal virtual;\n\n    /// @dev Returns the storage slot used by the implementation,\n    /// as specified in [ERC1822](https://eips.ethereum.org/EIPS/eip-1822).\n    ///\n    /// Note: The `notDelegated` modifier prevents accidental upgrades to\n    /// an implementation that is a proxy contract.\n    function proxiableUUID() public view virtual notDelegated returns (bytes32) {\n        // This function must always return `_ERC1967_IMPLEMENTATION_SLOT` to comply with ERC1967.\n        return _ERC1967_IMPLEMENTATION_SLOT;\n    }\n\n    /// @dev Upgrades the proxy's implementation to `newImplementation`.\n    /// Emits a {Upgraded} event.\n    ///\n    /// Note: Passing in empty `data` skips the delegatecall to `newImplementation`.\n    function upgradeToAndCall(address newImplementation, bytes calldata data)\n        public\n        payable\n        virtual\n        onlyProxy\n    {\n        _authorizeUpgrade(newImplementation);\n        /// @solidity memory-safe-assembly\n        assembly {\n            newImplementation := shr(96, shl(96, newImplementation)) // Clears upper 96 bits.\n            mstore(0x01, 0x52d1902d) // `proxiableUUID()`.\n            let s := _ERC1967_IMPLEMENTATION_SLOT\n            // Check if `newImplementation` implements `proxiableUUID` correctly.\n            if iszero(eq(mload(staticcall(gas(), newImplementation, 0x1d, 0x04, 0x01, 0x20)), s)) {\n                mstore(0x01, 0x55299b49) // `UpgradeFailed()`.\n                revert(0x1d, 0x04)\n            }\n            // Emit the {Upgraded} event.\n            log2(codesize(), 0x00, _UPGRADED_EVENT_SIGNATURE, newImplementation)\n            sstore(s, newImplementation) // Updates the implementation.\n\n            // Perform a delegatecall to `newImplementation` if `data` is non-empty.\n            if data.length {\n                // Forwards the `data` to `newImplementation` via delegatecall.\n                let m := mload(0x40)\n                calldatacopy(m, data.offset, data.length)\n                if iszero(delegatecall(gas(), newImplementation, m, data.length, codesize(), 0x00))\n                {\n                    // Bubble up the revert if the call reverts.\n                    returndatacopy(m, 0x00, returndatasize())\n                    revert(m, returndatasize())\n                }\n            }\n        }\n    }\n\n    /// @dev Requires that the execution is performed through a proxy.\n    modifier onlyProxy() {\n        uint256 s = __self;\n        /// @solidity memory-safe-assembly\n        assembly {\n            // To enable use cases with an immutable default implementation in the bytecode,\n            // (see: ERC6551Proxy), we don't require that the proxy address must match the\n            // value stored in the implementation slot, which may not be initialized.\n            if eq(s, address()) {\n                mstore(0x00, 0x9f03a026) // `UnauthorizedCallContext()`.\n                revert(0x1c, 0x04)\n            }\n        }\n        _;\n    }\n\n    /// @dev Requires that the execution is NOT performed via delegatecall.\n    /// This is the opposite of `onlyProxy`.\n    modifier notDelegated() {\n        uint256 s = __self;\n        /// @solidity memory-safe-assembly\n        assembly {\n            if iszero(eq(s, address())) {\n                mstore(0x00, 0x9f03a026) // `UnauthorizedCallContext()`.\n                revert(0x1c, 0x04)\n            }\n        }\n        _;\n    }\n}"
      },
      "lib/modular-account/src/interfaces/IPlugin.sol": {
        "content": "// This work is marked with CC0 1.0 Universal.\n//\n// SPDX-License-Identifier: CC0-1.0\n//\n// To view a copy of this license, visit http://creativecommons.org/publicdomain/zero/1.0\n\npragma solidity ^0.8.22;\n\nimport {UserOperation} from \"../interfaces/erc4337/UserOperation.sol\";\n\n// Forge formatter will displace the first comment for the enum field out of the enum itself,\n// so annotating here to prevent that.\n// forgefmt: disable-start\nenum ManifestAssociatedFunctionType {\n    // Function is not defined.\n    NONE,\n    // Function belongs to this plugin.\n    SELF,\n    // Function belongs to an external plugin provided as a dependency during plugin installation. Plugins MAY depend\n    // on external validation functions. It MUST NOT depend on external hooks, or installation will fail.\n    DEPENDENCY,\n    // Resolves to a magic value to always bypass runtime validation for a given function.\n    // This is only assignable on runtime validation functions. If it were to be used on a user op validation function,\n    // it would risk burning gas from the account. When used as a hook in any hook location, it is equivalent to not\n    // setting a hook and is therefore disallowed.\n    RUNTIME_VALIDATION_ALWAYS_ALLOW,\n    // Resolves to a magic value to always fail in a hook for a given function.\n    // This is only assignable to pre hooks (pre validation and pre execution). It should not be used on\n    // validation functions themselves, because this is equivalent to leaving the validation functions unset.\n    // It should not be used in post-exec hooks, because if it is known to always revert, that should happen\n    // as early as possible to save gas.\n    PRE_HOOK_ALWAYS_DENY\n}\n// forgefmt: disable-end\n\n/// @dev For functions of type `ManifestAssociatedFunctionType.DEPENDENCY`, the MSCA MUST find the plugin address\n/// of the function at `dependencies[dependencyIndex]` during the call to `installPlugin(config)`.\nstruct ManifestFunction {\n    ManifestAssociatedFunctionType functionType;\n    uint8 functionId;\n    uint256 dependencyIndex;\n}\n\nstruct ManifestAssociatedFunction {\n    bytes4 executionSelector;\n    ManifestFunction associatedFunction;\n}\n\nstruct ManifestExecutionHook {\n    bytes4 executionSelector;\n    ManifestFunction preExecHook;\n    ManifestFunction postExecHook;\n}\n\nstruct ManifestExternalCallPermission {\n    address externalAddress;\n    bool permitAnySelector;\n    bytes4[] selectors;\n}\n\nstruct SelectorPermission {\n    bytes4 functionSelector;\n    string permissionDescription;\n}\n\n/// @dev A struct holding fields to describe the plugin in a purely view context. Intended for front end clients.\nstruct PluginMetadata {\n    // A human-readable name of the plugin.\n    string name;\n    // The version of the plugin, following the semantic versioning scheme.\n    string version;\n    // The author field SHOULD be a username representing the identity of the user or organization\n    // that created this plugin.\n    string author;\n    // String descriptions of the relative sensitivity of specific functions. The selectors MUST be selectors for\n    // functions implemented by this plugin.\n    SelectorPermission[] permissionDescriptors;\n}\n\n/// @dev A struct describing how the plugin should be installed on a modular account.\nstruct PluginManifest {\n    // List of ERC-165 interface IDs to add to account to support introspection checks. This MUST NOT include\n    // IPlugin's interface ID.\n    bytes4[] interfaceIds;\n    // If this plugin depends on other plugins' validation functions, the interface IDs of those plugins MUST be\n    // provided here, with its position in the array matching the `dependencyIndex` members of `ManifestFunction`\n    // structs used in the manifest.\n    bytes4[] dependencyInterfaceIds;\n    // Execution functions defined in this plugin to be installed on the MSCA.\n    bytes4[] executionFunctions;\n    // Plugin execution functions already installed on the MSCA that this plugin will be able to call.\n    bytes4[] permittedExecutionSelectors;\n    // Boolean to indicate whether the plugin can call any external address.\n    bool permitAnyExternalAddress;\n    // Boolean to indicate whether the plugin needs access to spend native tokens of the account. If false, the\n    // plugin MUST still be able to spend up to the balance that it sends to the account in the same call.\n    bool canSpendNativeToken;\n    ManifestExternalCallPermission[] permittedExternalCalls;\n    ManifestAssociatedFunction[] userOpValidationFunctions;\n    ManifestAssociatedFunction[] runtimeValidationFunctions;\n    ManifestAssociatedFunction[] preUserOpValidationHooks;\n    ManifestAssociatedFunction[] preRuntimeValidationHooks;\n    ManifestExecutionHook[] executionHooks;\n}\n\n/// @title Plugin Interface\ninterface IPlugin {\n    /// @notice Initialize plugin data for the modular account.\n    /// @dev Called by the modular account during `installPlugin`.\n    /// @param data Optional bytes array to be decoded and used by the plugin to setup initial plugin data for the\n    /// modular account.\n    function onInstall(bytes calldata data) external;\n\n    /// @notice Clear plugin data for the modular account.\n    /// @dev Called by the modular account during `uninstallPlugin`.\n    /// @param data Optional bytes array to be decoded and used by the plugin to clear plugin data for the modular\n    /// account.\n    function onUninstall(bytes calldata data) external;\n\n    /// @notice Run the pre user operation validation hook specified by the `functionId`.\n    /// @dev Pre user operation validation hooks MUST NOT return an authorizer value other than 0 or 1.\n    /// @param functionId An identifier that routes the call to different internal implementations, should there be\n    /// more than one.\n    /// @param userOp The user operation.\n    /// @param userOpHash The user operation hash.\n    /// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes).\n    function preUserOpValidationHook(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash)\n        external\n        returns (uint256);\n\n    /// @notice Run the user operation validationFunction specified by the `functionId`.\n    /// @param functionId An identifier that routes the call to different internal implementations, should there be\n    /// more than one.\n    /// @param userOp The user operation.\n    /// @param userOpHash The user operation hash.\n    /// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes).\n    function userOpValidationFunction(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash)\n        external\n        returns (uint256);\n\n    /// @notice Run the pre runtime validation hook specified by the `functionId`.\n    /// @dev To indicate the entire call should revert, the function MUST revert.\n    /// @param functionId An identifier that routes the call to different internal implementations, should there be\n    /// more than one.\n    /// @param sender The caller address.\n    /// @param value The call value.\n    /// @param data The calldata sent.\n    function preRuntimeValidationHook(uint8 functionId, address sender, uint256 value, bytes calldata data)\n        external;\n\n    /// @notice Run the runtime validationFunction specified by the `functionId`.\n    /// @dev To indicate the entire call should revert, the function MUST revert.\n    /// @param functionId An identifier that routes the call to different internal implementations, should there be\n    /// more than one.\n    /// @param sender The caller address.\n    /// @param value The call value.\n    /// @param data The calldata sent.\n    function runtimeValidationFunction(uint8 functionId, address sender, uint256 value, bytes calldata data)\n        external;\n\n    /// @notice Run the pre execution hook specified by the `functionId`.\n    /// @dev To indicate the entire call should revert, the function MUST revert.\n    /// @param functionId An identifier that routes the call to different internal implementations, should there be\n    /// more than one.\n    /// @param sender The caller address.\n    /// @param value The call value.\n    /// @param data The calldata sent.\n    /// @return Context to pass to a post execution hook, if present. An empty bytes array MAY be returned.\n    function preExecutionHook(uint8 functionId, address sender, uint256 value, bytes calldata data)\n        external\n        returns (bytes memory);\n\n    /// @notice Run the post execution hook specified by the `functionId`.\n    /// @dev To indicate the entire call should revert, the function MUST revert.\n    /// @param functionId An identifier that routes the call to different internal implementations, should there be\n    /// more than one.\n    /// @param preExecHookData The context returned by its associated pre execution hook.\n    function postExecutionHook(uint8 functionId, bytes calldata preExecHookData) external;\n\n    /// @notice Describe the contents and intended configuration of the plugin.\n    /// @dev This manifest MUST stay constant over time.\n    /// @return A manifest describing the contents and intended configuration of the plugin.\n    function pluginManifest() external pure returns (PluginManifest memory);\n\n    /// @notice Describe the metadata of the plugin.\n    /// @dev This metadata MUST stay constant over time.\n    /// @return A metadata struct describing the plugin.\n    function pluginMetadata() external pure returns (PluginMetadata memory);\n}\n"
      },
      "lib/modular-account/src/plugins/BasePlugin.sol": {
        "content": "// This file is part of Modular Account.\n//\n// Copyright 2024 Alchemy Insights, Inc.\n//\n// SPDX-License-Identifier: GPL-3.0-or-later\n//\n// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General\n// Public License as published by the Free Software Foundation, either version 3 of the License, or (at your\n// option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the\n// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n// more details.\n//\n// You should have received a copy of the GNU General Public License along with this program. If not, see\n// <https://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.22;\n\nimport {ERC165} from \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\n\nimport {UserOperation} from \"../interfaces/erc4337/UserOperation.sol\";\nimport {IPlugin, PluginManifest, PluginMetadata} from \"../interfaces/IPlugin.sol\";\n\n/// @title Base contract for plugins\n/// @dev Implements ERC-165 to support IPlugin's interface, which is a requirement\n/// for plugin installation. This also ensures that plugin interactions cannot\n/// happen via the standard execution funtions `execute`, `executeBatch`, and `executeFromPluginExternal`.\n/// Note that the plugins implement BasePlugins cannot be installed when creating an account (aka installed in the\n/// account constructor) unless onInstall is overriden without checking codesize of caller (account). Checking\n/// codesize of account is to prevent EOA from accidentally calling plugin and initiate states which will make it\n/// unusable in the future when EOA can be upgraded into an smart contract account.\nabstract contract BasePlugin is ERC165, IPlugin {\n    error AlreadyInitialized();\n    error InvalidAction();\n    error NotContractCaller(address caller);\n    error NotImplemented(bytes4 selector, uint8 functionId);\n    error NotInitialized();\n\n    modifier isNotInitialized(address account) {\n        if (_isInitialized(account)) {\n            revert AlreadyInitialized();\n        }\n        _;\n    }\n\n    modifier isInitialized(address account) {\n        if (!_isInitialized(account)) {\n            revert NotInitialized();\n        }\n        _;\n    }\n\n    modifier staysInitialized(address account) {\n        if (!_isInitialized(account)) {\n            revert NotInitialized();\n        }\n        _;\n        if (!_isInitialized(account)) {\n            revert InvalidAction();\n        }\n    }\n\n    /// @notice Initialize plugin data for the modular account.\n    /// @dev Called by the modular account during `installPlugin`.\n    /// @param data Optional bytes array to be decoded and used by the plugin to setup initial plugin data for the\n    /// modular account.\n    function onInstall(bytes calldata data) external virtual {\n        if (msg.sender.code.length == 0) {\n            revert NotContractCaller(msg.sender);\n        }\n        _onInstall(data);\n    }\n\n    /// @notice Clear plugin data for the modular account.\n    /// @dev Called by the modular account during `uninstallPlugin`.\n    /// @param data Optional bytes array to be decoded and used by the plugin to clear plugin data for the modular\n    /// account.\n    function onUninstall(bytes calldata data) external virtual {\n        (data);\n        revert NotImplemented(msg.sig, 0);\n    }\n\n    /// @notice Run the pre user operation validation hook specified by the `functionId`.\n    /// @dev Pre user operation validation hooks MUST NOT return an authorizer value other than 0 or 1.\n    /// @param functionId An identifier that routes the call to different internal implementations, should there be\n    /// more than one.\n    /// @param userOp The user operation.\n    /// @param userOpHash The user operation hash.\n    /// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes).\n    function preUserOpValidationHook(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash)\n        external\n        virtual\n        returns (uint256)\n    {\n        (functionId, userOp, userOpHash);\n        revert NotImplemented(msg.sig, functionId);\n    }\n\n    /// @notice Run the user operation validationFunction specified by the `functionId`.\n    /// @param functionId An identifier that routes the call to different internal implementations, should there be\n    /// more than one.\n    /// @param userOp The user operation.\n    /// @param userOpHash The user operation hash.\n    /// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes).\n    function userOpValidationFunction(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash)\n        external\n        virtual\n        returns (uint256)\n    {\n        (functionId, userOp, userOpHash);\n        revert NotImplemented(msg.sig, functionId);\n    }\n\n    /// @notice Run the pre runtime validation hook specified by the `functionId`.\n    /// @dev To indicate the entire call should revert, the function MUST revert.\n    /// @param functionId An identifier that routes the call to different internal implementations, should there be\n    /// more than one.\n    /// @param sender The caller address.\n    /// @param value The call value.\n    /// @param data The calldata sent.\n    function preRuntimeValidationHook(uint8 functionId, address sender, uint256 value, bytes calldata data)\n        external\n        virtual\n    {\n        (functionId, sender, value, data);\n        revert NotImplemented(msg.sig, functionId);\n    }\n\n    /// @notice Run the runtime validationFunction specified by the `functionId`.\n    /// @dev To indicate the entire call should revert, the function MUST revert.\n    /// @param functionId An identifier that routes the call to different internal implementations, should there be\n    /// more than one.\n    /// @param sender The caller address.\n    /// @param value The call value.\n    /// @param data The calldata sent.\n    function runtimeValidationFunction(uint8 functionId, address sender, uint256 value, bytes calldata data)\n        external\n        virtual\n    {\n        (functionId, sender, value, data);\n        revert NotImplemented(msg.sig, functionId);\n    }\n\n    /// @notice Run the pre execution hook specified by the `functionId`.\n    /// @dev To indicate the entire call should revert, the function MUST revert.\n    /// @param functionId An identifier that routes the call to different internal implementations, should there be\n    /// more than one.\n    /// @param sender The caller address.\n    /// @param value The call value.\n    /// @param data The calldata sent.\n    /// @return Context to pass to a post execution hook, if present. An empty bytes array MAY be returned.\n    function preExecutionHook(uint8 functionId, address sender, uint256 value, bytes calldata data)\n        external\n        virtual\n        returns (bytes memory)\n    {\n        (functionId, sender, value, data);\n        revert NotImplemented(msg.sig, functionId);\n    }\n\n    /// @notice Run the post execution hook specified by the `functionId`.\n    /// @dev To indicate the entire call should revert, the function MUST revert.\n    /// @param functionId An identifier that routes the call to different internal implementations, should there be\n    /// more than one.\n    /// @param preExecHookData The context returned by its associated pre execution hook.\n    function postExecutionHook(uint8 functionId, bytes calldata preExecHookData) external virtual {\n        (functionId, preExecHookData);\n        revert NotImplemented(msg.sig, functionId);\n    }\n\n    /// @notice Describe the contents and intended configuration of the plugin.\n    /// @dev This manifest MUST stay constant over time.\n    /// @return A manifest describing the contents and intended configuration of the plugin.\n    function pluginManifest() external pure virtual returns (PluginManifest memory) {\n        revert NotImplemented(msg.sig, 0);\n    }\n\n    /// @notice Describe the metadata of the plugin.\n    /// @dev This metadata MUST stay constant over time.\n    /// @return A metadata struct describing the plugin.\n    function pluginMetadata() external pure virtual returns (PluginMetadata memory);\n\n    /// @dev Returns true if this contract implements the interface defined by\n    /// `interfaceId`. See the corresponding\n    /// https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n    /// to learn more about how these ids are created.\n    ///\n    /// This function call must use less than 30 000 gas.\n    ///\n    /// Supporting the IPlugin interface is a requirement for plugin installation. This is also used\n    /// by the modular account to prevent standard execution functions `execute`, `executeBatch`, and\n    /// `executeFromPluginExternal` from making calls to plugins.\n    /// @param interfaceId The interface ID to check for support.\n    /// @return True if the contract supports `interfaceId`.\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IPlugin).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /// @notice Initialize plugin data for the modular account.\n    /// @dev Called by the modular account during `installPlugin`.\n    /// @param data Optional bytes array to be decoded and used by the plugin to setup initial plugin data for the\n    /// modular account.\n    function _onInstall(bytes calldata data) internal virtual {\n        (data);\n        revert NotImplemented(msg.sig, 0);\n    }\n\n    /// @notice Check if the account has initialized this plugin yet\n    /// @dev This function should be overwritten for plugins that have state-changing onInstall's\n    /// @param account The account to check\n    /// @return True if the account has initialized this plugin\n    // solhint-disable-next-line no-empty-blocks\n    function _isInitialized(address account) internal view virtual returns (bool) {}\n}\n"
      },
      "lib/modular-account/src/libraries/AssociatedLinkedListSetLib.sol": {
        "content": "// This file is part of Modular Account.\n//\n// Copyright 2024 Alchemy Insights, Inc.\n//\n// SPDX-License-Identifier: MIT\n//\n// See LICENSE-MIT file for more information\n\npragma solidity ^0.8.22;\n\nimport {SetValue, SENTINEL_VALUE, HAS_NEXT_FLAG} from \"./Constants.sol\";\n\n/// @dev Type representing the set, which is just a storage slot placeholder like the solidity mapping type.\nstruct AssociatedLinkedListSet {\n    bytes32 placeholder;\n}\n\n/// @title Associated Linked List Set Library\n/// @author Alchemy\n/// @notice Provides a set data structure that is enumerable and held in address-associated storage (per the\n/// ERC-4337 spec)\nlibrary AssociatedLinkedListSetLib {\n    // Mapping Entry Byte Layout\n    // | value | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA____ |\n    // | meta  | 0x____________________________________________________________BBBB |\n\n    // Bit-layout of the meta bytes (2 bytes)\n    // | user flags | 11111111 11111100 |\n    // | has next   | 00000000 00000010 |\n    // | sentinel   | 00000000 00000001 |\n\n    // Mapping keys exclude the upper 15 bits of the meta bytes, which allows keys to be either a value or the\n    // sentinel.\n\n    // This cannot be evaluated at compile time because of its use in inline assembly.\n    bytes4 internal constant _ASSOCIATED_STORAGE_PREFIX = 0xf938c976; // bytes4(keccak256(\"AssociatedLinkedListSet\"))\n\n    // A custom type representing the index of a storage slot\n    type StoragePointer is bytes32;\n\n    // A custom type representing a pointer to a location in memory beyond the current free memory pointer.\n    // Holds a fixed-size buffer similar to \"bytes memory\", but without a length field.\n    // Care must be taken when using these, as they may be overwritten if ANY memory is allocated after allocating\n    // a TempBytesMemory.\n    type TempBytesMemory is bytes32;\n\n    // INTERNAL METHODS\n\n    /// @notice Adds a value to a set.\n    /// @param set The set to add the value to.\n    /// @param associated The address the set is associated with.\n    /// @param value The value to add.\n    /// @return True if the value was added, false if the value cannot be added (already exists or is zero).\n    function tryAdd(AssociatedLinkedListSet storage set, address associated, SetValue value)\n        internal\n        returns (bool)\n    {\n        bytes32 unwrappedKey = bytes32(SetValue.unwrap(value));\n        if (unwrappedKey == bytes32(0)) {\n            // Cannot add the zero value\n            return false;\n        }\n\n        TempBytesMemory keyBuffer = _allocateTempKeyBuffer(set, associated);\n\n        StoragePointer valueSlot = _mapLookup(keyBuffer, unwrappedKey);\n        if (_load(valueSlot) != bytes32(0)) {\n            // Entry already exists\n            return false;\n        }\n\n        // Load the head of the set\n        StoragePointer sentinelSlot = _mapLookup(keyBuffer, SENTINEL_VALUE);\n        bytes32 prev = _load(sentinelSlot);\n        if (prev == bytes32(0) || isSentinel(prev)) {\n            // set is empty, need to do:\n            // map[SENTINEL_VALUE] = unwrappedKey;\n            // map[unwrappedKey] = SENTINEL_VALUE;\n            _store(sentinelSlot, unwrappedKey);\n            _store(valueSlot, SENTINEL_VALUE);\n        } else {\n            // set is not empty, need to do:\n            // map[SENTINEL_VALUE] = unwrappedKey | HAS_NEXT_FLAG;\n            // map[unwrappedKey] = prev;\n            _store(sentinelSlot, unwrappedKey | HAS_NEXT_FLAG);\n            _store(valueSlot, prev);\n        }\n\n        return true;\n    }\n\n    /// @notice Removes a value from a set.\n    /// @dev This is an O(n) operation, where n is the number of elements in the set.\n    /// @param set The set to remove the value from\n    /// @param associated The address the set is associated with\n    /// @param value The value to remove\n    /// @return True if the value was removed, false if the value does not exist\n    function tryRemove(AssociatedLinkedListSet storage set, address associated, SetValue value)\n        internal\n        returns (bool)\n    {\n        bytes32 unwrappedKey = bytes32(SetValue.unwrap(value));\n        TempBytesMemory keyBuffer = _allocateTempKeyBuffer(set, associated);\n\n        StoragePointer valueSlot = _mapLookup(keyBuffer, unwrappedKey);\n        bytes32 nextValue = _load(valueSlot);\n        if (unwrappedKey == bytes32(0) || nextValue == bytes32(0)) {\n            // Entry does not exist\n            return false;\n        }\n\n        bytes32 prevKey = SENTINEL_VALUE;\n        bytes32 currentVal;\n        do {\n            // Load the current entry\n            StoragePointer prevSlot = _mapLookup(keyBuffer, prevKey);\n            currentVal = _load(prevSlot);\n            bytes32 currentKey = clearFlags(currentVal);\n            if (currentKey == unwrappedKey) {\n                // Found the entry\n                // Set the previous value's next value to the next value,\n                // and the flags to the current value's flags.\n                // and the next value's `hasNext` flag to determine whether or not the next value is (or points to)\n                // the sentinel value.\n\n                // Need to do:\n                // map[prevKey] = clearFlags(nextValue) | getUserFlags(currentVal) | (nextValue & HAS_NEXT_FLAG);\n                // map[currentKey] = bytes32(0);\n\n                _store(prevSlot, clearFlags(nextValue) | getUserFlags(currentVal) | (nextValue & HAS_NEXT_FLAG));\n                _store(valueSlot, bytes32(0));\n\n                return true;\n            }\n            prevKey = currentKey;\n        } while (!isSentinel(currentVal) && currentVal != bytes32(0));\n        return false;\n    }\n\n    /// @notice Removes a value from a set, given the previous value in the set.\n    /// @dev This is an O(1) operation but requires additional knowledge.\n    /// @param set The set to remove the value from\n    /// @param associated The address the set is associated with\n    /// @param value The value to remove\n    /// @param prev The previous value in the set\n    /// @return True if the value was removed, false if the value does not exist\n    function tryRemoveKnown(AssociatedLinkedListSet storage set, address associated, SetValue value, bytes32 prev)\n        internal\n        returns (bool)\n    {\n        bytes32 unwrappedKey = bytes32(SetValue.unwrap(value));\n        TempBytesMemory keyBuffer = _allocateTempKeyBuffer(set, associated);\n\n        prev = clearFlags(prev);\n\n        if (prev == bytes32(0) || unwrappedKey == bytes32(0)) {\n            return false;\n        }\n\n        // assert that the previous key's next value is the value to be removed\n        StoragePointer prevSlot = _mapLookup(keyBuffer, prev);\n        bytes32 currentValue = _load(prevSlot);\n        if (clearFlags(currentValue) != unwrappedKey) {\n            return false;\n        }\n\n        StoragePointer valueSlot = _mapLookup(keyBuffer, unwrappedKey);\n        bytes32 next = _load(valueSlot);\n        if (next == bytes32(0)) {\n            // The set didn't actually contain the value\n            return false;\n        }\n\n        // Need to do:\n        // map[prev] = clearUserFlags(next) | getUserFlags(currentValue);\n        // map[unwrappedKey] = bytes32(0);\n        _store(prevSlot, clearUserFlags(next) | getUserFlags(currentValue));\n        _store(valueSlot, bytes32(0));\n\n        return true;\n    }\n\n    /// @notice Removes all values from a set.\n    /// @dev This is an O(n) operation, where n is the number of elements in the set.\n    /// @param set The set to remove the values from\n    /// @param associated The address the set is associated with\n    function clear(AssociatedLinkedListSet storage set, address associated) internal {\n        TempBytesMemory keyBuffer = _allocateTempKeyBuffer(set, associated);\n\n        bytes32 cursor = SENTINEL_VALUE;\n\n        do {\n            StoragePointer cursorSlot = _mapLookup(keyBuffer, cursor);\n            bytes32 next = clearFlags(_load(cursorSlot));\n            _store(cursorSlot, bytes32(0));\n            cursor = next;\n        } while (!isSentinel(cursor) && cursor != bytes32(0));\n    }\n\n    /// @notice Set the flags on a value in the set.\n    /// @dev The user flags can only be set on the upper 14 bits, because the lower two are reserved for the\n    /// sentinel and has next bit.\n    /// @param set The set containing the value.\n    /// @param associated The address the set is associated with.\n    /// @param value The value to set the flags on.\n    /// @param flags The flags to set.\n    /// @return True if the set contains the value and the operation succeeds, false otherwise.\n    function trySetFlags(AssociatedLinkedListSet storage set, address associated, SetValue value, uint16 flags)\n        internal\n        returns (bool)\n    {\n        bytes32 unwrappedKey = SetValue.unwrap(value);\n        TempBytesMemory keyBuffer = _allocateTempKeyBuffer(set, associated);\n\n        // Ignore the lower 2 bits.\n        flags &= 0xFFFC;\n\n        // If the set doesn't actually contain the value, return false;\n        StoragePointer valueSlot = _mapLookup(keyBuffer, unwrappedKey);\n        bytes32 next = _load(valueSlot);\n        if (next == bytes32(0)) {\n            return false;\n        }\n\n        // Set the flags\n        _store(valueSlot, clearUserFlags(next) | bytes32(uint256(flags)));\n\n        return true;\n    }\n\n    /// @notice Set the given flags on a value in the set, preserving the values of other flags.\n    /// @dev The user flags can only be set on the upper 14 bits, because the lower two are reserved for the\n    /// sentinel and has next bit.\n    /// Short-circuits if the flags are already enabled, returning true.\n    /// @param set The set containing the value.\n    /// @param associated The address the set is associated with.\n    /// @param value The value to enable the flags on.\n    /// @param flags The flags to enable.\n    /// @return True if the operation succeeds or short-circuits due to the flags already being enabled. False\n    /// otherwise.\n    function tryEnableFlags(AssociatedLinkedListSet storage set, address associated, SetValue value, uint16 flags)\n        internal\n        returns (bool)\n    {\n        flags &= 0xFFFC; // Allow short-circuit if lower bits are accidentally set\n        uint16 currFlags = getFlags(set, associated, value);\n        if (currFlags & flags == flags) return true; // flags are already enabled\n        return trySetFlags(set, associated, value, currFlags | flags);\n    }\n\n    /// @notice Clear the given flags on a value in the set, preserving the values of other flags.\n    /// @notice If the value is not in the set, this function will still return true.\n    /// @dev The user flags can only be set on the upper 14 bits, because the lower two are reserved for the\n    /// sentinel and has next bit.\n    /// Short-circuits if the flags are already disabled, or if set does not contain the value. Short-circuits\n    /// return true.\n    /// @param set The set containing the value.\n    /// @param associated The address the set is associated with.\n    /// @param value The value to disable the flags on.\n    /// @param flags The flags to disable.\n    /// @return True if the operation succeeds, or short-circuits due to the flags already being disabled or if the\n    /// set does not contain the value. False otherwise.\n    function tryDisableFlags(AssociatedLinkedListSet storage set, address associated, SetValue value, uint16 flags)\n        internal\n        returns (bool)\n    {\n        flags &= 0xFFFC; // Allow short-circuit if lower bits are accidentally set\n        uint16 currFlags = getFlags(set, associated, value);\n        if (currFlags & flags == 0) return true; // flags are already disabled\n        return trySetFlags(set, associated, value, currFlags & ~flags);\n    }\n\n    /// @notice Checks if a set contains a value\n    /// @dev This method does not clear the upper bits of `value`, that is expected to be done as part of casting\n    /// to the correct type. If this function is provided the sentinel value by using the upper bits, this function\n    /// may returns `true`.\n    /// @param set The set to check\n    /// @param associated The address the set is associated with\n    /// @param value The value to check for\n    /// @return True if the set contains the value, false otherwise\n    function contains(AssociatedLinkedListSet storage set, address associated, SetValue value)\n        internal\n        view\n        returns (bool)\n    {\n        bytes32 unwrappedKey = bytes32(SetValue.unwrap(value));\n        TempBytesMemory keyBuffer = _allocateTempKeyBuffer(set, associated);\n\n        StoragePointer slot = _mapLookup(keyBuffer, unwrappedKey);\n        return _load(slot) != bytes32(0);\n    }\n\n    /// @notice Checks if a set is empty\n    /// @param set The set to check\n    /// @param associated The address the set is associated with\n    /// @return True if the set is empty, false otherwise\n    function isEmpty(AssociatedLinkedListSet storage set, address associated) internal view returns (bool) {\n        TempBytesMemory keyBuffer = _allocateTempKeyBuffer(set, associated);\n\n        StoragePointer sentinelSlot = _mapLookup(keyBuffer, SENTINEL_VALUE);\n        bytes32 val = _load(sentinelSlot);\n        return val == bytes32(0) || isSentinel(val); // either the sentinel is unset, or points to itself\n    }\n\n    /// @notice Get the flags on a value in the set.\n    /// @dev The reserved lower 2 bits will not be returned, as those are reserved for the sentinel and has next\n    /// bit.\n    /// @param set The set containing the value.\n    /// @param associated The address the set is associated with.\n    /// @param value The value to get the flags from.\n    /// @return The flags set on the value.\n    function getFlags(AssociatedLinkedListSet storage set, address associated, SetValue value)\n        internal\n        view\n        returns (uint16)\n    {\n        bytes32 unwrappedKey = SetValue.unwrap(value);\n        TempBytesMemory keyBuffer = _allocateTempKeyBuffer(set, associated);\n        return uint16(uint256(_load(_mapLookup(keyBuffer, unwrappedKey))) & 0xFFFC);\n    }\n\n    /// @notice Check if the flags on a value are enabled.\n    /// @dev The reserved lower 2 bits will be ignored, as those are reserved for the sentinel and has next bit.\n    /// @param set The set containing the value.\n    /// @param associated The address the set is associated with.\n    /// @param value The value to check the flags on.\n    /// @param flags The flags to check.\n    /// @return True if all of the flags are enabled, false otherwise.\n    function flagsEnabled(AssociatedLinkedListSet storage set, address associated, SetValue value, uint16 flags)\n        internal\n        view\n        returns (bool)\n    {\n        flags &= 0xFFFC;\n        return getFlags(set, associated, value) & flags == flags;\n    }\n\n    /// @notice Check if the flags on a value are disabled.\n    /// @dev The reserved lower 2 bits will be ignored, as those are reserved for the sentinel and has next bit.\n    /// @param set The set containing the value.\n    /// @param associated The address the set is associated with.\n    /// @param value The value to check the flags on.\n    /// @param flags The flags to check.\n    /// @return True if all of the flags are disabled, false otherwise.\n    function flagsDisabled(AssociatedLinkedListSet storage set, address associated, SetValue value, uint16 flags)\n        internal\n        view\n        returns (bool)\n    {\n        flags &= 0xFFFC;\n        return ~(getFlags(set, associated, value)) & flags == flags;\n    }\n\n    /// @notice Gets all elements in a set.\n    /// @dev This is an O(n) operation, where n is the number of elements in the set.\n    /// @param set The set to get the elements of.\n    /// @return ret An array of all elements in the set.\n    function getAll(AssociatedLinkedListSet storage set, address associated)\n        internal\n        view\n        returns (SetValue[] memory ret)\n    {\n        TempBytesMemory keyBuffer = _allocateTempKeyBuffer(set, associated);\n        uint256 size;\n        bytes32 cursor = _load(_mapLookup(keyBuffer, SENTINEL_VALUE));\n\n        // Dynamically allocate the returned array as we iterate through the set, since we don't know the size\n        // beforehand.\n        // This is accomplished by first writing to memory after the free memory pointer,\n        // then updating the free memory pointer to cover the newly-allocated data.\n        // To the compiler, writes to memory after the free memory pointer are considered \"memory safe\".\n        // See https://docs.soliditylang.org/en/v0.8.22/assembly.html#memory-safety\n        // Stack variable lifting done when compiling with via-ir will only ever place variables into memory\n        // locations below the current free memory pointer, so it is safe to compile this library with via-ir.\n        // See https://docs.soliditylang.org/en/v0.8.22/yul.html#memoryguard\n        assembly (\"memory-safe\") {\n            // It is critical that no other memory allocations occur between:\n            // -  loading the value of the free memory pointer into `ret`\n            // -  updating the free memory pointer to point to the newly-allocated data, which is done after all\n            // the values have been written.\n            ret := mload(0x40)\n            // Add an extra offset of 4 words to account for the length of the keyBuffer, since it will be used\n            // for each lookup. If this value were written back to the free memory pointer, it would effectively\n            // convert the keyBuffer into a \"bytes memory\" type. However, we don't actually write to the free\n            // memory pointer until after all we've also allocated the entire return array.\n            ret := add(ret, 0x80)\n        }\n\n        while (!isSentinel(cursor) && cursor != bytes32(0)) {\n            unchecked {\n                ++size;\n            }\n            bytes32 cleared = clearFlags(cursor);\n            // Place the item into the return array manually. Since the size was just incremented, it will point to\n            // the next location to write to.\n            assembly (\"memory-safe\") {\n                mstore(add(ret, mul(size, 0x20)), cleared)\n            }\n            if (hasNext(cursor)) {\n                cursor = _load(_mapLookup(keyBuffer, cleared));\n            } else {\n                cursor = bytes32(0);\n            }\n        }\n\n        assembly (\"memory-safe\") {\n            // Update the free memory pointer with the now-known length of the array.\n            mstore(0x40, add(ret, mul(add(size, 1), 0x20)))\n            // Set the length of the array.\n            mstore(ret, size)\n        }\n    }\n\n    function isSentinel(bytes32 value) internal pure returns (bool ret) {\n        assembly (\"memory-safe\") {\n            ret := and(value, 1)\n        }\n    }\n\n    function hasNext(bytes32 value) internal pure returns (bool) {\n        return value & HAS_NEXT_FLAG != 0;\n    }\n\n    function clearFlags(bytes32 val) internal pure returns (bytes32) {\n        return val & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0001;\n    }\n\n    /// @dev Preserves the lower two bits\n    function clearUserFlags(bytes32 val) internal pure returns (bytes32) {\n        return val & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0003;\n    }\n\n    function getUserFlags(bytes32 val) internal pure returns (bytes32) {\n        return val & bytes32(uint256(0xFFFC));\n    }\n\n    // PRIVATE METHODS\n\n    /// @notice Given an allocated key buffer, returns the storage slot for a given key\n    function _mapLookup(TempBytesMemory keyBuffer, bytes32 value) private pure returns (StoragePointer slot) {\n        assembly (\"memory-safe\") {\n            // Store the value in the last word.\n            mstore(add(keyBuffer, 0x60), value)\n            slot := keccak256(keyBuffer, 0x80)\n        }\n    }\n\n    /// @notice Allocates a key buffer for a given ID and associated address into scratch space memory.\n    /// @dev The returned buffer must not be used if any additional memory is allocated after calling this\n    /// function.\n    /// @param set The set to allocate the key buffer for.\n    /// @param associated The address the set is associated with.\n    /// @return key A key buffer that can be used to lookup values in the set\n    function _allocateTempKeyBuffer(AssociatedLinkedListSet storage set, address associated)\n        private\n        pure\n        returns (TempBytesMemory key)\n    {\n        // Key derivation for an entry\n        // Note: `||` refers to the concat operator\n        // associated addr (left-padded) || prefix || uint224(0) batchIndex || set storage slot || entry\n        // Word 1:\n        // | zeros              | 0x000000000000000000000000________________________________________ |\n        // | address            | 0x________________________AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |\n        // Word 2:\n        // | prefix             | 0xPPPPPPPP________________________________________________________ |\n        // | batch index (zero) | 0x________00000000000000000000000000000000000000000000000000000000 |\n        // Word 3:\n        // | set storage slot  | 0xSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS |\n        // Word 4:\n        // | entry value        | 0xVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV____ |\n        // | entry meta         | 0x____________________________________________________________MMMM |\n\n        // The batch index is for consistency with PluginStorageLib, and the prefix in front of it is\n        // to prevent any potential crafted collisions where the batch index may be equal to storage slot\n        // of the ALLS. The prefix is set to the upper bits of the batch index to make it infeasible to\n        // reach from just incrementing the value.\n\n        // This segment is memory-safe because it only uses the scratch space memory after the value of the free\n        // memory pointer.\n        // See https://docs.soliditylang.org/en/v0.8.22/assembly.html#memory-safety\n        assembly (\"memory-safe\") {\n            // Clean upper bits of arguments\n            associated := and(associated, 0xffffffffffffffffffffffffffffffffffffffff)\n\n            // Use memory past-the-free-memory-pointer without updating it, as this is just scratch space\n            key := mload(0x40)\n            // Store the associated address in the first word, left-padded with zeroes\n            mstore(key, associated)\n            // Store the prefix and a batch index of 0\n            mstore(add(key, 0x20), _ASSOCIATED_STORAGE_PREFIX)\n            // Store the list's storage slot in the third word\n            mstore(add(key, 0x40), set.slot)\n            // Leaves the last word open for the value entry\n        }\n\n        return key;\n    }\n\n    /// @dev Loads a value from storage\n    function _load(StoragePointer ptr) private view returns (bytes32 val) {\n        assembly (\"memory-safe\") {\n            val := sload(ptr)\n        }\n    }\n\n    /// @dev Writes a value into storage\n    function _store(StoragePointer ptr, bytes32 val) private {\n        assembly (\"memory-safe\") {\n            sstore(ptr, val)\n        }\n    }\n}\n"
      },
      "lib/modular-account/src/interfaces/erc4337/UserOperation.sol": {
        "content": "// This work is marked with CC0 1.0 Universal.\n//\n// SPDX-License-Identifier: CC0-1.0\n//\n// To view a copy of this license, visit http://creativecommons.org/publicdomain/zero/1.0\n\npragma solidity ^0.8.22;\n\n/// @notice User Operation struct as defined in ERC-4337\nstruct UserOperation {\n    address sender;\n    uint256 nonce;\n    bytes initCode;\n    bytes callData;\n    uint256 callGasLimit;\n    uint256 verificationGasLimit;\n    uint256 preVerificationGas;\n    uint256 maxFeePerGas;\n    uint256 maxPriorityFeePerGas;\n    bytes paymasterAndData;\n    bytes signature;\n}\n"
      },
      "lib/modular-account/src/libraries/Constants.sol": {
        "content": "// This file is part of Modular Account.\n//\n// Copyright 2024 Alchemy Insights, Inc.\n//\n// SPDX-License-Identifier: MIT\n//\n// See LICENSE-MIT file for more information\n\npragma solidity ^0.8.22;\n\ntype SetValue is bytes30;\n\n/// @dev The sentinel value is used to indicate the head and tail of the list.\nbytes32 constant SENTINEL_VALUE = bytes32(uint256(1));\n\n/// @dev Removing the last element will result in this flag not being set correctly, but all operations will\n/// function normally, albeit with one extra sload for getAll.\nbytes32 constant HAS_NEXT_FLAG = bytes32(uint256(2));\n\n/// @dev As defined by ERC-4337.\nuint256 constant SIG_VALIDATION_PASSED = 0;\nuint256 constant SIG_VALIDATION_FAILED = 1;\n"
      },
      "lib/modular-account/src/helpers/CastLib.sol": {
        "content": "// This file is part of Modular Account.\n//\n// Copyright 2024 Alchemy Insights, Inc.\n//\n// SPDX-License-Identifier: GPL-3.0-or-later\n//\n// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General\n// Public License as published by the Free Software Foundation, either version 3 of the License, or (at your\n// option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the\n// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n// more details.\n//\n// You should have received a copy of the GNU General Public License along with this program. If not, see\n// <https://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.22;\n\nimport {SetValue} from \"../libraries/Constants.sol\";\nimport {FunctionReference} from \"./FunctionReferenceLib.sol\";\n\n/// @title Cast Library\n/// @author Alchemy\n/// @notice Library for various data type conversions.\nlibrary CastLib {\n    /// @dev Input array is not verified. If called with non FunctionReference type array input, return data will\n    /// be incorrect.\n    function toFunctionReferenceArray(SetValue[] memory vals)\n        internal\n        pure\n        returns (FunctionReference[] memory ret)\n    {\n        assembly (\"memory-safe\") {\n            ret := vals\n        }\n    }\n\n    /// @dev Input array is not verified. If used with non address type array input, return data will be incorrect.\n    function toAddressArray(SetValue[] memory values) internal pure returns (address[] memory addresses) {\n        bytes32[] memory valuesBytes;\n\n        assembly (\"memory-safe\") {\n            valuesBytes := values\n        }\n\n        uint256 length = values.length;\n        for (uint256 i = 0; i < length; ++i) {\n            valuesBytes[i] >>= 96;\n        }\n\n        assembly (\"memory-safe\") {\n            addresses := valuesBytes\n        }\n\n        return addresses;\n    }\n\n    function toSetValue(FunctionReference functionReference) internal pure returns (SetValue) {\n        return SetValue.wrap(bytes30(FunctionReference.unwrap(functionReference)));\n    }\n\n    function toSetValue(address value) internal pure returns (SetValue) {\n        return SetValue.wrap(bytes30(bytes20(value)));\n    }\n}\n"
      },
      "lib/modular-account/src/interfaces/IStandardExecutor.sol": {
        "content": "// This work is marked with CC0 1.0 Universal.\n//\n// SPDX-License-Identifier: CC0-1.0\n//\n// To view a copy of this license, visit http://creativecommons.org/publicdomain/zero/1.0\n\npragma solidity ^0.8.22;\n\nstruct Call {\n    // The target address for the account to call.\n    address target;\n    // The value to send with the call.\n    uint256 value;\n    // The calldata for the call.\n    bytes data;\n}\n\n/// @title Standard Executor Interface\ninterface IStandardExecutor {\n    /// @notice Standard execute method.\n    /// @dev If the target is a plugin, the call SHOULD revert.\n    /// @param target The target address for the account to call.\n    /// @param value The value to send with the call.\n    /// @param data The calldata for the call.\n    /// @return The return data from the call.\n    function execute(address target, uint256 value, bytes calldata data) external payable returns (bytes memory);\n\n    /// @notice Standard executeBatch method.\n    /// @dev If the target is a plugin, the call SHOULD revert. If any of the calls revert, the entire batch MUST\n    /// revert.\n    /// @param calls The array of calls.\n    /// @return An array containing the return data from the calls.\n    function executeBatch(Call[] calldata calls) external payable returns (bytes[] memory);\n}\n"
      },
      "lib/modular-account/src/account/UpgradeableModularAccount.sol": {
        "content": "// This file is part of Modular Account.\n//\n// Copyright 2024 Alchemy Insights, Inc.\n//\n// SPDX-License-Identifier: GPL-3.0-or-later\n//\n// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General\n// Public License as published by the Free Software Foundation, either version 3 of the License, or (at your\n// option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the\n// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n// more details.\n//\n// You should have received a copy of the GNU General Public License along with this program. If not, see\n// <https://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.22;\n\nimport {IERC1155Receiver} from \"@openzeppelin/contracts/interfaces/IERC1155Receiver.sol\";\nimport {IERC777Recipient} from \"@openzeppelin/contracts/interfaces/IERC777Recipient.sol\";\nimport {IERC721Receiver} from \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\nimport {UUPSUpgradeable} from \"../../ext/UUPSUpgradeable.sol\";\nimport {CastLib} from \"../helpers/CastLib.sol\";\nimport {FunctionReferenceLib} from \"../helpers/FunctionReferenceLib.sol\";\nimport {_coalescePreValidation, _coalesceValidation} from \"../helpers/ValidationDataHelpers.sol\";\nimport {IAccount} from \"../interfaces/erc4337/IAccount.sol\";\nimport {IEntryPoint} from \"../interfaces/erc4337/IEntryPoint.sol\";\nimport {UserOperation} from \"../interfaces/erc4337/UserOperation.sol\";\nimport {IAccountInitializable} from \"../interfaces/IAccountInitializable.sol\";\nimport {IAccountView} from \"../interfaces/IAccountView.sol\";\nimport {IPlugin, PluginManifest} from \"../interfaces/IPlugin.sol\";\nimport {IPluginExecutor} from \"../interfaces/IPluginExecutor.sol\";\nimport {FunctionReference, IPluginManager} from \"../interfaces/IPluginManager.sol\";\nimport {Call, IStandardExecutor} from \"../interfaces/IStandardExecutor.sol\";\nimport {CountableLinkedListSetLib} from \"../libraries/CountableLinkedListSetLib.sol\";\nimport {LinkedListSet, LinkedListSetLib} from \"../libraries/LinkedListSetLib.sol\";\nimport {AccountExecutor} from \"./AccountExecutor.sol\";\nimport {AccountLoupe} from \"./AccountLoupe.sol\";\nimport {AccountStorageInitializable} from \"./AccountStorageInitializable.sol\";\nimport {PluginManagerInternals} from \"./PluginManagerInternals.sol\";\n\n/// @title Upgradeable Modular Account\n/// @author Alchemy\n/// @notice A modular smart contract account (MSCA) that supports upgradeability and plugins.\ncontract UpgradeableModularAccount is\n    AccountExecutor,\n    AccountLoupe,\n    AccountStorageInitializable,\n    PluginManagerInternals,\n    IAccount,\n    IAccountInitializable,\n    IAccountView,\n    IERC165,\n    IERC721Receiver,\n    IERC777Recipient,\n    IERC1155Receiver,\n    IPluginExecutor,\n    IStandardExecutor,\n    UUPSUpgradeable\n{\n    using CountableLinkedListSetLib for LinkedListSet;\n    using LinkedListSetLib for LinkedListSet;\n    using FunctionReferenceLib for FunctionReference;\n\n    /// @dev Struct to hold optional configuration data for uninstalling a plugin. This should be encoded and\n    /// passed to the `config` parameter of `uninstallPlugin`.\n    struct UninstallPluginConfig {\n        // ABI-encoding of a `PluginManifest` to specify the original manifest\n        // used to install the plugin now being uninstalled, in cases where the\n        // plugin manifest has changed. If empty, uses the default behavior of\n        // calling the plugin to get its current manifest.\n        bytes serializedManifest;\n        // If true, will complete the uninstall even if the `onUninstall` callback reverts. Available as an escape\n        // hatch if a plugin is blocking uninstall.\n        bool forceUninstall;\n        // Maximum amount of gas allowed for each uninstall callback function\n        // (`onUninstall`), or zero to set no limit. Should\n        // typically be used with `forceUninstall` to remove plugins that are\n        // preventing uninstallation by consuming all remaining gas.\n        uint256 callbackGasLimit;\n    }\n\n    // ERC-4337 v0.6.0 entrypoint address only\n    IEntryPoint private immutable _ENTRY_POINT;\n\n    bytes4 internal constant _IERC165_INTERFACE_ID = 0x01ffc9a7;\n\n    event ModularAccountInitialized(IEntryPoint indexed entryPoint);\n\n    error AlwaysDenyRule();\n    error ExecFromPluginNotPermitted(address plugin, bytes4 selector);\n    error ExecFromPluginExternalNotPermitted(address plugin, address target, uint256 value, bytes data);\n    error NativeTokenSpendingNotPermitted(address plugin);\n    error PostExecHookReverted(address plugin, uint8 functionId, bytes revertReason);\n    error PreExecHookReverted(address plugin, uint8 functionId, bytes revertReason);\n    error PreRuntimeValidationHookFailed(address plugin, uint8 functionId, bytes revertReason);\n    error RuntimeValidationFunctionMissing(bytes4 selector);\n    error RuntimeValidationFunctionReverted(address plugin, uint8 functionId, bytes revertReason);\n    error UnexpectedAggregator(address plugin, uint8 functionId, address aggregator);\n    error UnrecognizedFunction(bytes4 selector);\n    error UserOpNotFromEntryPoint();\n    error UserOpValidationFunctionMissing(bytes4 selector);\n\n    constructor(IEntryPoint anEntryPoint) {\n        _ENTRY_POINT = anEntryPoint;\n        _disableInitializers();\n    }\n\n    // EXTERNAL FUNCTIONS\n\n    /// @inheritdoc IAccountInitializable\n    function initialize(address[] calldata plugins, bytes calldata pluginInitData) external initializer {\n        (bytes32[] memory manifestHashes, bytes[] memory pluginInstallDatas) =\n            abi.decode(pluginInitData, (bytes32[], bytes[]));\n\n        uint256 length = plugins.length;\n\n        if (length != manifestHashes.length || length != pluginInstallDatas.length) {\n            revert ArrayLengthMismatch();\n        }\n\n        FunctionReference[] memory emptyDependencies = new FunctionReference[](0);\n\n        for (uint256 i = 0; i < length; ++i) {\n            _installPlugin(plugins[i], manifestHashes[i], pluginInstallDatas[i], emptyDependencies);\n        }\n\n        emit ModularAccountInitialized(_ENTRY_POINT);\n    }\n\n    receive() external payable {}\n\n    /// @notice Fallback function that routes calls to plugin execution functions.\n    /// @dev We route calls to execution functions based on incoming msg.sig. If there's no plugin associated with\n    /// this function selector, revert.\n    /// @return Data returned from the called execution function.\n    fallback(bytes calldata) external payable returns (bytes memory) {\n        // Either reuse the call buffer from runtime validation, or allocate a new one. It may or may not be used\n        // for pre exec hooks but it will be used for the plugin execution itself.\n        bytes memory callBuffer =\n            (msg.sender != address(_ENTRY_POINT)) ? _doRuntimeValidation() : _allocateRuntimeCallBuffer(msg.data);\n\n        // To comply with ERC-6900 phase rules, defer the loading of execution phase data until the completion of\n        // runtime validation.\n        // Validation may update account state and therefore change execution phase data. These values should also\n        // be loaded before\n        // we run the pre exec hooks, because they may modify which plugin is defined.\n        SelectorData storage selectorData = _getAccountStorage().selectorData[msg.sig];\n        address execPlugin = selectorData.plugin;\n        if (execPlugin == address(0)) {\n            revert UnrecognizedFunction(msg.sig);\n        }\n\n        (FunctionReference[][] memory postHooksToRun, bytes[] memory postHookArgs) =\n            _doPreExecHooks(selectorData, callBuffer);\n\n        // execute the function, bubbling up any reverts\n        bool execSuccess = _executeRaw(execPlugin, _convertRuntimeCallBufferToExecBuffer(callBuffer));\n        bytes memory returnData = _collectReturnData();\n\n        if (!execSuccess) {\n            // Bubble up revert reasons from plugins\n            assembly (\"memory-safe\") {\n                revert(add(returnData, 32), mload(returnData))\n            }\n        }\n\n        _doCachedPostHooks(postHooksToRun, postHookArgs);\n\n        return returnData;\n    }\n\n    /// @inheritdoc IAccount\n    function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\n        external\n        virtual\n        override\n        returns (uint256 validationData)\n    {\n        if (msg.sender != address(_ENTRY_POINT)) {\n            revert UserOpNotFromEntryPoint();\n        }\n\n        bytes4 selector = _selectorFromCallData(userOp.callData);\n        SelectorData storage selectorData = _getAccountStorage().selectorData[selector];\n\n        FunctionReference userOpValidationFunction = selectorData.userOpValidation;\n        bool hasPreValidationHooks = selectorData.hasPreUserOpValidationHooks;\n\n        validationData =\n            _doUserOpValidation(selector, userOpValidationFunction, userOp, userOpHash, hasPreValidationHooks);\n\n        if (missingAccountFunds != 0) {\n            // entry point verifies if call succeeds so we don't need to do here\n            (bool success,) = payable(msg.sender).call{value: missingAccountFunds, gas: type(uint256).max}(\"\");\n            (success);\n        }\n    }\n\n    /// @inheritdoc IStandardExecutor\n    function execute(address target, uint256 value, bytes calldata data)\n        external\n        payable\n        override\n        returns (bytes memory result)\n    {\n        (FunctionReference[][] memory postExecHooks, bytes[] memory postHookArgs) = _preNativeFunction();\n        result = _exec(target, value, data);\n        _postNativeFunction(postExecHooks, postHookArgs);\n    }\n\n    /// @inheritdoc IStandardExecutor\n    function executeBatch(Call[] calldata calls) external payable override returns (bytes[] memory results) {\n        (FunctionReference[][] memory postExecHooks, bytes[] memory postHookArgs) = _preNativeFunction();\n\n        uint256 callsLength = calls.length;\n        results = new bytes[](callsLength);\n\n        for (uint256 i = 0; i < callsLength; ++i) {\n            results[i] = _exec(calls[i].target, calls[i].value, calls[i].data);\n        }\n\n        _postNativeFunction(postExecHooks, postHookArgs);\n    }\n\n    /// @inheritdoc IPluginExecutor\n    function executeFromPlugin(bytes calldata data) external payable override returns (bytes memory returnData) {\n        bytes4 selector = _selectorFromCallData(data);\n        bytes24 permittedCallKey = _getPermittedCallKey(msg.sender, selector);\n\n        AccountStorage storage storage_ = _getAccountStorage();\n\n        if (!storage_.callPermitted[permittedCallKey]) {\n            revert ExecFromPluginNotPermitted(msg.sender, selector);\n        }\n\n        bytes memory callBuffer = _allocateRuntimeCallBuffer(data);\n\n        SelectorData storage selectorData = storage_.selectorData[selector];\n        // Load the plugin address from storage prior to running any hooks, to abide by the ERC-6900 phase rules.\n        address execFunctionPlugin = selectorData.plugin;\n\n        (FunctionReference[][] memory postHooksToRun, bytes[] memory postHookArgs) =\n            _doPreExecHooks(selectorData, callBuffer);\n\n        if (execFunctionPlugin == address(0)) {\n            revert UnrecognizedFunction(selector);\n        }\n\n        bool execSuccess = _executeRaw(execFunctionPlugin, _convertRuntimeCallBufferToExecBuffer(callBuffer));\n        returnData = _collectReturnData();\n\n        if (!execSuccess) {\n            assembly (\"memory-safe\") {\n                revert(add(returnData, 32), mload(returnData))\n            }\n        }\n\n        _doCachedPostHooks(postHooksToRun, postHookArgs);\n\n        return returnData;\n    }\n\n    /// @inheritdoc IPluginExecutor\n    function executeFromPluginExternal(address target, uint256 value, bytes calldata data)\n        external\n        payable\n        returns (bytes memory)\n    {\n        AccountStorage storage storage_ = _getAccountStorage();\n        address callingPlugin = msg.sender;\n\n        // Make sure plugin is allowed to spend native token.\n        if (value > 0 && value > msg.value && !storage_.pluginData[callingPlugin].canSpendNativeToken) {\n            revert NativeTokenSpendingNotPermitted(callingPlugin);\n        }\n\n        // Target cannot be the account itself.\n        if (target == address(this)) {\n            revert ExecFromPluginExternalNotPermitted(callingPlugin, target, value, data);\n        }\n\n        // Check the caller plugin's permission to make this call on the target address.\n        //\n        // 1. Check that the target is permitted at all, and if so check that any one of the following is true:\n        //   a. Is any selector permitted?\n        //   b. Is the calldata empty? (allow empty data calls by default if the target address is permitted)\n        //   c. Is the selector in the call permitted?\n        // 2. If the target is not permitted, instead check whether all external calls are permitted.\n        //\n        // `addressPermitted` can only be true if `anyExternalAddressPermitted` is false, so we can reduce our\n        // worst-case `sloads` by 1 by not checking `anyExternalAddressPermitted` if `addressPermitted` is true.\n        //\n        // We allow calls where the data may be less than 4 bytes - it's up to the calling contract to\n        // determine how to handle this.\n\n        PermittedExternalCallData storage permittedExternalCallData =\n            storage_.permittedExternalCalls[IPlugin(callingPlugin)][target];\n\n        bool isTargetCallPermitted;\n        if (permittedExternalCallData.addressPermitted) {\n            isTargetCallPermitted = (\n                permittedExternalCallData.anySelectorPermitted || data.length == 0\n                    || permittedExternalCallData.permittedSelectors[bytes4(data)]\n            );\n        } else {\n            isTargetCallPermitted = storage_.pluginData[callingPlugin].anyExternalAddressPermitted;\n        }\n\n        // If the target is not permitted, check if the caller plugin is permitted to make any external calls.\n        if (!isTargetCallPermitted) {\n            revert ExecFromPluginExternalNotPermitted(callingPlugin, target, value, data);\n        }\n\n        // Run any pre exec hooks for the `executeFromPluginExternal` selector\n        SelectorData storage selectorData =\n            storage_.selectorData[IPluginExecutor.executeFromPluginExternal.selector];\n\n        (FunctionReference[][] memory postHooksToRun, bytes[] memory postHookArgs) =\n            _doPreExecHooks(selectorData, \"\");\n\n        // Perform the external call\n        bytes memory returnData = _exec(target, value, data);\n\n        _doCachedPostHooks(postHooksToRun, postHookArgs);\n\n        return returnData;\n    }\n\n    /// @inheritdoc IPluginManager\n    function installPlugin(\n        address plugin,\n        bytes32 manifestHash,\n        bytes calldata pluginInstallData,\n        FunctionReference[] calldata dependencies\n    ) external override {\n        (FunctionReference[][] memory postExecHooks, bytes[] memory postHookArgs) = _preNativeFunction();\n        _installPlugin(plugin, manifestHash, pluginInstallData, dependencies);\n        _postNativeFunction(postExecHooks, postHookArgs);\n    }\n\n    /// @inheritdoc IPluginManager\n    function uninstallPlugin(address plugin, bytes calldata config, bytes calldata pluginUninstallData)\n        external\n        override\n    {\n        (FunctionReference[][] memory postExecHooks, bytes[] memory postHookArgs) = _preNativeFunction();\n\n        UninstallPluginArgs memory args;\n        args.plugin = plugin;\n        bool hasSetManifest;\n\n        if (config.length > 0) {\n            UninstallPluginConfig memory decodedConfig = abi.decode(config, (UninstallPluginConfig));\n            if (decodedConfig.serializedManifest.length > 0) {\n                args.manifest = abi.decode(decodedConfig.serializedManifest, (PluginManifest));\n                hasSetManifest = true;\n            }\n            args.forceUninstall = decodedConfig.forceUninstall;\n            args.callbackGasLimit = decodedConfig.callbackGasLimit;\n        }\n        if (!hasSetManifest) {\n            args.manifest = IPlugin(plugin).pluginManifest();\n        }\n        if (args.callbackGasLimit == 0) {\n            args.callbackGasLimit = type(uint256).max;\n        }\n\n        _uninstallPlugin(args, pluginUninstallData);\n\n        _postNativeFunction(postExecHooks, postHookArgs);\n    }\n\n    /// @inheritdoc IERC777Recipient\n    /// @dev Runtime validation is bypassed for this function, but we still allow pre and post exec hooks to be\n    /// assigned and run.\n    function tokensReceived(\n        address operator,\n        address from,\n        address to,\n        uint256 amount,\n        bytes calldata userData,\n        bytes calldata operatorData\n    ) external override {\n        (FunctionReference[][] memory postExecHooks, bytes[] memory postHookArgs) =\n            _doPreExecHooks(_getAccountStorage().selectorData[msg.sig], \"\");\n        _tokensReceived(operator, from, to, amount, userData, operatorData);\n        _postNativeFunction(postExecHooks, postHookArgs);\n    }\n\n    /// @inheritdoc IERC721Receiver\n    /// @dev Runtime validation is bypassed for this function, but we still allow pre and post exec hooks to be\n    /// assigned and run.\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data)\n        external\n        override\n        returns (bytes4 selector)\n    {\n        (FunctionReference[][] memory postExecHooks, bytes[] memory postHookArgs) =\n            _doPreExecHooks(_getAccountStorage().selectorData[msg.sig], \"\");\n        selector = _onERC721Received(operator, from, tokenId, data);\n        _postNativeFunction(postExecHooks, postHookArgs);\n    }\n\n    /// @inheritdoc IERC1155Receiver\n    /// @dev Runtime validation is bypassed for this function, but we still allow pre and post exec hooks to be\n    /// assigned and run.\n    function onERC1155Received(address operator, address from, uint256 id, uint256 value, bytes calldata data)\n        external\n        override\n        returns (bytes4 selector)\n    {\n        (FunctionReference[][] memory postExecHooks, bytes[] memory postHookArgs) =\n            _doPreExecHooks(_getAccountStorage().selectorData[msg.sig], \"\");\n        selector = _onERC1155Received(operator, from, id, value, data);\n        _postNativeFunction(postExecHooks, postHookArgs);\n    }\n\n    /// @inheritdoc IERC1155Receiver\n    /// @dev Runtime validation is bypassed for this function, but we still allow pre and post exec hooks to be\n    /// assigned and run.\n    function onERC1155BatchReceived(\n        address operator,\n        address from,\n        uint256[] calldata ids,\n        uint256[] calldata values,\n        bytes calldata data\n    ) external override returns (bytes4 selector) {\n        (FunctionReference[][] memory postExecHooks, bytes[] memory postHookArgs) =\n            _doPreExecHooks(_getAccountStorage().selectorData[msg.sig], \"\");\n        selector = _onERC1155BatchReceived(operator, from, ids, values, data);\n        _postNativeFunction(postExecHooks, postHookArgs);\n    }\n\n    /// @inheritdoc UUPSUpgradeable\n    function upgradeToAndCall(address newImplementation, bytes calldata data) public payable override onlyProxy {\n        (FunctionReference[][] memory postExecHooks, bytes[] memory postHookArgs) = _preNativeFunction();\n        UUPSUpgradeable.upgradeToAndCall(newImplementation, data);\n        _postNativeFunction(postExecHooks, postHookArgs);\n    }\n\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public view override returns (bool) {\n        if (interfaceId == _INVALID_INTERFACE_ID) {\n            return false;\n        }\n        return interfaceId == _IERC165_INTERFACE_ID || interfaceId == type(IERC721Receiver).interfaceId\n            || interfaceId == type(IERC777Recipient).interfaceId || interfaceId == type(IERC1155Receiver).interfaceId\n            || _getAccountStorage().supportedInterfaces[interfaceId] > 0;\n    }\n\n    /// @inheritdoc IAccountView\n    function entryPoint() public view override returns (IEntryPoint) {\n        return _ENTRY_POINT;\n    }\n\n    /// @inheritdoc IAccountView\n    function getNonce() public view virtual override returns (uint256) {\n        return _ENTRY_POINT.getNonce(address(this), 0);\n    }\n\n    // INTERNAL FUNCTIONS\n\n    /// @dev Wraps execution of a native function with runtime validation and hooks. Used for upgradeToAndCall,\n    /// execute, executeBatch, installPlugin, uninstallPlugin.\n    function _preNativeFunction()\n        internal\n        returns (FunctionReference[][] memory postExecHooks, bytes[] memory postHookArgs)\n    {\n        bytes memory callBuffer = \"\";\n\n        if (msg.sender != address(_ENTRY_POINT)) {\n            callBuffer = _doRuntimeValidation();\n        }\n\n        (postExecHooks, postHookArgs) = _doPreExecHooks(_getAccountStorage().selectorData[msg.sig], callBuffer);\n    }\n\n    /// @dev Wraps execution of a native function with runtime validation and hooks. Used for upgradeToAndCall,\n    /// execute, executeBatch, installPlugin, uninstallPlugin, and the token receiver functions.\n    function _postNativeFunction(FunctionReference[][] memory postExecHooks, bytes[] memory postHookArgs)\n        internal\n    {\n        _doCachedPostHooks(postExecHooks, postHookArgs);\n    }\n\n    /// @dev To support gas estimation, we don't fail early when the failure is caused by a signature failure.\n    function _doUserOpValidation(\n        bytes4 selector,\n        FunctionReference userOpValidationFunction,\n        UserOperation calldata userOp,\n        bytes32 userOpHash,\n        bool doPreValidationHooks\n    ) internal returns (uint256 validationData) {\n        if (userOpValidationFunction.isEmpty()) {\n            revert UserOpValidationFunctionMissing(selector);\n        }\n\n        bytes memory callBuffer =\n            _allocateUserOpCallBuffer(IPlugin.preUserOpValidationHook.selector, userOp, userOpHash);\n\n        uint256 currentValidationData;\n        uint256 preUserOpValidationHooksLength;\n\n        if (doPreValidationHooks) {\n            // Do preUserOpValidation hooks\n            FunctionReference[] memory preUserOpValidationHooks = CastLib.toFunctionReferenceArray(\n                _getAccountStorage().selectorData[selector].preUserOpValidationHooks.getAll()\n            );\n\n            preUserOpValidationHooksLength = preUserOpValidationHooks.length;\n            for (uint256 i = 0; i < preUserOpValidationHooksLength; ++i) {\n                // FunctionReference preUserOpValidationHook = preUserOpValidationHooks[i];\n\n                if (preUserOpValidationHooks[i].isEmptyOrMagicValue()) {\n                    // Empty function reference is impossible here due to the element coming from a LinkedListSet.\n                    // Runtime Validation Always Allow is not assignable here.\n                    // Pre Hook Always Deny is the only assignable magic value here.\n                    revert AlwaysDenyRule();\n                }\n\n                (address plugin, uint8 functionId) = preUserOpValidationHooks[i].unpack();\n\n                _updatePluginCallBufferFunctionId(callBuffer, functionId);\n\n                currentValidationData = _executeUserOpPluginFunction(callBuffer, plugin);\n\n                if (uint160(currentValidationData) > 1) {\n                    // If the aggregator is not 0 or 1, it is an unexpected value\n                    revert UnexpectedAggregator(plugin, functionId, address(uint160(currentValidationData)));\n                }\n                validationData = _coalescePreValidation(validationData, currentValidationData);\n            }\n        }\n\n        // Run the user op validation function\n        {\n            _updatePluginCallBufferSelector(callBuffer, IPlugin.userOpValidationFunction.selector);\n            // No magic values are assignable here, and we already checked whether or not the function was empty,\n            // so we're OK to use the function immediately\n            (address plugin, uint8 functionId) = userOpValidationFunction.unpack();\n\n            _updatePluginCallBufferFunctionId(callBuffer, functionId);\n\n            currentValidationData = _executeUserOpPluginFunction(callBuffer, plugin);\n\n            if (preUserOpValidationHooksLength != 0) {\n                // If we have other validation data we need to coalesce with\n                validationData = _coalesceValidation(validationData, currentValidationData);\n            } else {\n                validationData = currentValidationData;\n            }\n        }\n    }\n\n    function _doRuntimeValidation() internal returns (bytes memory callBuffer) {\n        AccountStorage storage storage_ = _getAccountStorage();\n        FunctionReference runtimeValidationFunction = storage_.selectorData[msg.sig].runtimeValidation;\n        bool doPreRuntimeValidationHooks = storage_.selectorData[msg.sig].hasPreRuntimeValidationHooks;\n\n        // Allocate the call buffer for preRuntimeValidationHook\n        callBuffer = _allocateRuntimeCallBuffer(msg.data);\n\n        if (doPreRuntimeValidationHooks) {\n            _updatePluginCallBufferSelector(callBuffer, IPlugin.preRuntimeValidationHook.selector);\n\n            // run all preRuntimeValidation hooks\n            FunctionReference[] memory preRuntimeValidationHooks = CastLib.toFunctionReferenceArray(\n                _getAccountStorage().selectorData[msg.sig].preRuntimeValidationHooks.getAll()\n            );\n\n            uint256 preRuntimeValidationHooksLength = preRuntimeValidationHooks.length;\n            for (uint256 i = 0; i < preRuntimeValidationHooksLength; ++i) {\n                FunctionReference preRuntimeValidationHook = preRuntimeValidationHooks[i];\n\n                if (preRuntimeValidationHook.isEmptyOrMagicValue()) {\n                    // The function reference must be the Always Deny magic value in this case,\n                    // because zero and any other magic value is unassignable here.\n                    revert AlwaysDenyRule();\n                }\n\n                (address plugin, uint8 functionId) = preRuntimeValidationHook.unpack();\n\n                _updatePluginCallBufferFunctionId(callBuffer, functionId);\n\n                _executeRuntimePluginFunction(callBuffer, plugin, PreRuntimeValidationHookFailed.selector);\n            }\n        }\n\n        // Identifier scope limiting\n        {\n            if (runtimeValidationFunction.isEmptyOrMagicValue()) {\n                if (\n                    runtimeValidationFunction.isEmpty()\n                        && (\n                            (\n                                msg.sig != IPluginManager.installPlugin.selector\n                                    && msg.sig != UUPSUpgradeable.upgradeToAndCall.selector\n                            ) || msg.sender != address(this)\n                        )\n                ) {\n                    // Runtime calls cannot be made against functions with no\n                    // validator, except in the special case of self-calls to\n                    // `installPlugin` and `upgradeToAndCall`, to enable removing the plugin protecting\n                    // `installPlugin` and installing a different one as part of\n                    // a single batch execution, and/or to enable upgrading the account implementation.\n                    revert RuntimeValidationFunctionMissing(msg.sig);\n                }\n                // If _RUNTIME_VALIDATION_ALWAYS_ALLOW, or we're in the\n                // `installPlugin` and `upgradeToAndCall` special case,just let the function finish,\n                // without the else branch.\n            } else {\n                _updatePluginCallBufferSelector(callBuffer, IPlugin.runtimeValidationFunction.selector);\n\n                (address plugin, uint8 functionId) = runtimeValidationFunction.unpack();\n\n                _updatePluginCallBufferFunctionId(callBuffer, functionId);\n\n                _executeRuntimePluginFunction(callBuffer, plugin, RuntimeValidationFunctionReverted.selector);\n            }\n        }\n    }\n\n    /// @dev Executes pre-exec hooks and returns the post-exec hooks to run and their associated args.\n    function _doPreExecHooks(SelectorData storage selectorData, bytes memory callBuffer)\n        internal\n        returns (FunctionReference[][] memory postHooksToRun, bytes[] memory postHookArgs)\n    {\n        FunctionReference[] memory preExecHooks;\n\n        bool hasPreExecHooks = selectorData.hasPreExecHooks;\n        bool hasPostOnlyExecHooks = selectorData.hasPostOnlyExecHooks;\n\n        if (hasPreExecHooks) {\n            preExecHooks = CastLib.toFunctionReferenceArray(selectorData.executionHooks.preHooks.getAll());\n        }\n\n        // Allocate memory for the post hooks and post hook args.\n        // If we have post-only hooks, we allocate an extra FunctionReference[] for them, and one extra element\n        // in the args for their empty `bytes` argument.\n        uint256 postHooksToRunLength = preExecHooks.length + (hasPostOnlyExecHooks ? 1 : 0);\n        postHooksToRun = new FunctionReference[][](postHooksToRunLength);\n        postHookArgs = new bytes[](postHooksToRunLength);\n\n        // If there are no pre exec hooks, this will short-circuit in the length check on `preExecHooks`.\n        _cacheAssociatedPostHooks(preExecHooks, selectorData.executionHooks, postHooksToRun);\n\n        if (hasPostOnlyExecHooks) {\n            // If we have post-only hooks, we allocate an single FunctionReference[] for them, and one element\n            // in the args for their empty `bytes` argument. We put this into the last element of the post\n            // hooks, which means post-only hooks will run before any other post hooks.\n            postHooksToRun[postHooksToRunLength - 1] =\n                CastLib.toFunctionReferenceArray(selectorData.executionHooks.postOnlyHooks.getAll());\n        }\n\n        // Run all pre-exec hooks and capture their outputs.\n        _doPreHooks(preExecHooks, callBuffer, postHooksToRun, postHookArgs);\n    }\n\n    /// @dev Execute all pre hooks provided, using the call buffer if provided.\n    /// Outputs are captured into the `hookReturnData` array, in increasing index starting at 0.\n    /// The `postHooks` array is used to determine whether or not to capture the return data.\n    function _doPreHooks(\n        FunctionReference[] memory preHooks,\n        bytes memory callBuffer,\n        FunctionReference[][] memory postHooks, // Only used to check if any post hooks exist.\n        bytes[] memory hookReturnData\n    ) internal {\n        uint256 preExecHooksLength = preHooks.length;\n\n        // If not running anything, short-circuit before allocating more memory for the call buffers.\n        if (preExecHooksLength == 0) {\n            return;\n        }\n\n        if (callBuffer.length == 0) {\n            // Allocate the call buffer for preExecHook. This case MUST NOT be reached by `executeFromPlugin`,\n            // otherwise the call will execute with the wrong calldata. This case should only be reachable by\n            // native functions with no runtime validation (e.g., token receiver functions or functions called via\n            // a user operation).\n            callBuffer = _allocateRuntimeCallBuffer(msg.data);\n        }\n        _updatePluginCallBufferSelector(callBuffer, IPlugin.preExecutionHook.selector);\n\n        for (uint256 i = 0; i < preExecHooksLength; ++i) {\n            FunctionReference preExecHook = preHooks[i];\n\n            if (preExecHook.isEmptyOrMagicValue()) {\n                // The function reference must be the Always Deny magic value in this case,\n                // because zero and any other magic value is unassignable here.\n                revert AlwaysDenyRule();\n            }\n\n            (address plugin, uint8 functionId) = preExecHook.unpack();\n\n            _updatePluginCallBufferFunctionId(callBuffer, functionId);\n\n            _executeRuntimePluginFunction(callBuffer, plugin, PreExecHookReverted.selector);\n\n            // Only collect the return data if there is at least one post-hook to consume it.\n            if (postHooks[i].length > 0) {\n                hookReturnData[i] = abi.decode(_collectReturnData(), (bytes));\n            }\n        }\n    }\n\n    /// @dev Executes all post hooks in the nested array, using the corresponding args in the nested array.\n    /// Executes the elements in reverse order, so the caller should ensure the correct ordering before calling.\n    function _doCachedPostHooks(FunctionReference[][] memory postHooks, bytes[] memory postHookArgs) internal {\n        // Run post hooks in reverse order of their associated pre hooks.\n        uint256 postHookArrsLength = postHooks.length;\n        for (uint256 i = postHookArrsLength; i > 0;) {\n            uint256 index;\n            unchecked {\n                // i starts as the length of the array and goes to 1, not zero, to avoid underflowing.\n                // To use the index for array access, we need to subtract 1.\n                index = i - 1;\n            }\n            FunctionReference[] memory postHooksToRun = postHooks[index];\n\n            // We don't need to run each associated post-hook in reverse order, because the associativity we want\n            // to maintain is reverse order of associated pre-hooks.\n            uint256 postHooksToRunLength = postHooksToRun.length;\n            for (uint256 j = 0; j < postHooksToRunLength; ++j) {\n                (address plugin, uint8 functionId) = postHooksToRun[j].unpack();\n\n                // Execute the post hook with the current post hook args\n                // solhint-disable-next-line no-empty-blocks\n                try IPlugin(plugin).postExecutionHook(functionId, postHookArgs[index]) {}\n                catch (bytes memory revertReason) {\n                    revert PostExecHookReverted(plugin, functionId, revertReason);\n                }\n            }\n\n            // Solidity v0.8.22 allows the optimizer to automatically remove checking on for loop increments, but\n            // not decrements. Therefore we need to use unchecked here to avoid the extra costs for checked math.\n            unchecked {\n                --i;\n            }\n        }\n    }\n\n    /// @inheritdoc UUPSUpgradeable\n    // solhint-disable-next-line no-empty-blocks\n    function _authorizeUpgrade(address newImplementation) internal override {}\n\n    /// @dev Override to implement custom behavior.\n    function _tokensReceived(address, address, address, uint256, bytes calldata, bytes calldata)\n        internal\n        virtual\n    // solhint-disable-next-line no-empty-blocks\n    {}\n\n    /// @dev Override to implement custom behavior.\n    function _onERC721Received(address, address, uint256, bytes calldata)\n        internal\n        virtual\n        returns (bytes4 selector)\n    {\n        selector = IERC721Receiver.onERC721Received.selector;\n    }\n\n    /// @dev Override to implement custom behavior.\n    function _onERC1155Received(address, address, uint256, uint256, bytes calldata)\n        internal\n        virtual\n        returns (bytes4 selector)\n    {\n        selector = IERC1155Receiver.onERC1155Received.selector;\n    }\n\n    /// @dev Override to implement custom behavior.\n    function _onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata)\n        internal\n        virtual\n        returns (bytes4 selector)\n    {\n        selector = IERC1155Receiver.onERC1155BatchReceived.selector;\n    }\n\n    /// @dev Loads the associated post hooks for the given pre-exec hooks in the `postHooks` array, starting at 0.\n    function _cacheAssociatedPostHooks(\n        FunctionReference[] memory preExecHooks,\n        HookGroup storage hookGroup,\n        FunctionReference[][] memory postHooks\n    ) internal view {\n        uint256 preExecHooksLength = preExecHooks.length;\n        for (uint256 i = 0; i < preExecHooksLength; ++i) {\n            FunctionReference preExecHook = preExecHooks[i];\n\n            // If the pre-exec hook has associated post hooks, cache them in the postHooks array.\n            if (hookGroup.preHooks.flagsEnabled(CastLib.toSetValue(preExecHook), _PRE_EXEC_HOOK_HAS_POST_FLAG)) {\n                postHooks[i] =\n                    CastLib.toFunctionReferenceArray(hookGroup.associatedPostHooks[preExecHook].getAll());\n            }\n            // In no-associated-post-hooks case, we're OK returning the default value, which is an array of length\n            // 0.\n        }\n    }\n\n    /// @dev Revert with an appropriate error if the calldata does not include a function selector.\n    function _selectorFromCallData(bytes calldata data) internal pure returns (bytes4) {\n        if (data.length < 4) {\n            revert UnrecognizedFunction(bytes4(data));\n        }\n        return bytes4(data);\n    }\n}\n"
      },
      "src/IMultisigPlugin.sol": {
        "content": "// This file is part of Multisig Plugin.\n//\n// Copyright 2024 Alchemy Insights, Inc.\n//\n// SPDX-License-Identifier: GPL-3.0-or-later\n//\n// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General\n// Public License as published by the Free Software Foundation, either version 3 of the License, or (at your\n// option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the\n// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n// more details.\n//\n// You should have received a copy of the GNU General Public License along with this program. If not, see\n// <https://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.22;\n\ninterface IMultisigPlugin {\n    enum FunctionId {\n        USER_OP_VALIDATION_OWNER // require owner access\n    }\n\n    /// @notice This event is emitted when owners of the account are updated.\n    /// @param account The account whose ownership changed.\n    /// @param addedOwners The address array of added owners.\n    /// @param removedOwners The address array of removed owners.\n    /// @param threshold The new threshold. A threshold of 0 could mean that there isn't a change in threshold.\n    event OwnerUpdated(address indexed account, address[] addedOwners, address[] removedOwners, uint256 threshold);\n\n    error ECDSARecoverFailure();\n    error EmptyOwnersNotAllowed();\n    error InvalidAddress();\n    error InvalidMaxFeePerGas();\n    error InvalidMaxPriorityFeePerGas();\n    error InvalidNumSigsOnActualGas();\n    error InvalidOwner(address owner);\n    error InvalidPreVerificationGas();\n    error InvalidSigLength();\n    error InvalidSigOffset();\n    error InvalidThreshold();\n    error OwnerDoesNotExist(address owner);\n\n    /// @notice Update owners of the account, and/or threshold\n    /// @dev This function is installed on the account as part of plugin installation, and should\n    /// only be called from an account.\n    /// @param ownersToAdd The address array of owners to be added.\n    /// @param ownersToRemove The address array of owners to be removed.\n    /// @param newThreshold The new threshold. 0 for no change.\n    function updateOwnership(address[] memory ownersToAdd, address[] memory ownersToRemove, uint128 newThreshold)\n        external;\n\n    /// @notice Gets the EIP712 domain\n    /// @dev This implementation is different from typical 712 via its use of msg.sender instead. As such, it\n    /// should only be called from the SCAs that has installed this. See ERC-5267.\n    function eip712Domain()\n        external\n        view\n        returns (\n            bytes1 fields,\n            string memory name,\n            string memory version,\n            uint256 chainId,\n            address verifyingContract,\n            bytes32 salt,\n            uint256[] memory extensions\n        );\n\n    /// @notice Check if the signatures are valid for the account.\n    /// @param actualGasDigest The hash of the message.\n    /// @param maxGasDigest The hash of the digest.\n    /// @param account The account to check the signatures for.\n    /// @param signatures The signatures to check.\n    /// @return success True if the signatures are valid.\n    /// @return firstFailure Index of the first failed signature if the signature failed\n    function checkNSignatures(bytes32 actualGasDigest, bytes32 maxGasDigest, address account, bytes memory signatures)\n        external\n        view\n        returns (bool success, uint256 firstFailure);\n\n    /// @notice Check if an address is an owner of `account`.\n    /// @param account The account to check.\n    /// @param ownerToCheck The owner to check if it is an owner of the provided account.\n    /// @return True if the address is an owner of the account.\n    function isOwnerOf(address account, address ownerToCheck) external view returns (bool);\n\n    /// @notice Get the owners of `account`, and the threshold.\n    /// @param account The account to get the owners of.\n    /// @return The addresses of the owners of the account, and the threshold\n    function ownershipInfoOf(address account) external view returns (address[] memory, uint256);\n\n    /// @notice Returns the pre-image of the message hash\n    /// @dev Assumes that the SCA's implementation of `domainSeparator` is this plugin's\n    /// @param account SCA to build the message encoding for\n    /// @param message Message that should be encoded.\n    /// @return Encoded message.\n    function encodeMessageData(address account, bytes memory message) external view returns (bytes memory);\n\n    /// @notice Returns hash of a message that can be signed by owners.\n    /// @param account SCA to build the message hash for\n    /// @param message Message that should be hashed.\n    /// @return Message hash.\n    function getMessageHash(address account, bytes memory message) external view returns (bytes32);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Strings.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n    uint8 private constant _ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toString(int256 value) internal pure returns (string memory) {\n        return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"
      },
      "lib/modular-account/src/helpers/FunctionReferenceLib.sol": {
        "content": "// This file is part of Modular Account.\n//\n// Copyright 2024 Alchemy Insights, Inc.\n//\n// SPDX-License-Identifier: GPL-3.0-or-later\n//\n// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General\n// Public License as published by the Free Software Foundation, either version 3 of the License, or (at your\n// option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the\n// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n// more details.\n//\n// You should have received a copy of the GNU General Public License along with this program. If not, see\n// <https://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.22;\n\nimport {FunctionReference} from \"../interfaces/IPluginManager.sol\";\n\n/// @title Function Reference Lib\n/// @author Alchemy\nlibrary FunctionReferenceLib {\n    // Empty or unset function reference.\n    FunctionReference internal constant _EMPTY_FUNCTION_REFERENCE = FunctionReference.wrap(bytes21(0));\n    // Magic value for runtime validation functions that always allow access.\n    FunctionReference internal constant _RUNTIME_VALIDATION_ALWAYS_ALLOW =\n        FunctionReference.wrap(bytes21(uint168(1)));\n    // Magic value for hooks that should always revert.\n    FunctionReference internal constant _PRE_HOOK_ALWAYS_DENY = FunctionReference.wrap(bytes21(uint168(2)));\n\n    function pack(address addr, uint8 functionId) internal pure returns (FunctionReference) {\n        return FunctionReference.wrap(bytes21(bytes20(addr)) | bytes21(uint168(functionId)));\n    }\n\n    function unpack(FunctionReference fr) internal pure returns (address addr, uint8 functionId) {\n        bytes21 underlying = FunctionReference.unwrap(fr);\n        addr = address(bytes20(underlying));\n        functionId = uint8(bytes1(underlying << 160));\n    }\n\n    function isEmptyOrMagicValue(FunctionReference fr) internal pure returns (bool) {\n        return FunctionReference.unwrap(fr) <= bytes21(uint168(2));\n    }\n\n    function isEmpty(FunctionReference fr) internal pure returns (bool) {\n        return FunctionReference.unwrap(fr) == bytes21(0);\n    }\n\n    function eq(FunctionReference a, FunctionReference b) internal pure returns (bool) {\n        return FunctionReference.unwrap(a) == FunctionReference.unwrap(b);\n    }\n\n    function notEq(FunctionReference a, FunctionReference b) internal pure returns (bool) {\n        return FunctionReference.unwrap(a) != FunctionReference.unwrap(b);\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/IERC1155Receiver.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../token/ERC1155/IERC1155Receiver.sol\";\n"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/IERC777Recipient.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC777Recipient.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../token/ERC777/IERC777Recipient.sol\";\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n    /**\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n     * by `operator` from `from`, this function is called.\n     *\n     * It must return its Solidity selector to confirm the token transfer.\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n     *\n     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n     */\n    function onERC721Received(\n        address operator,\n        address from,\n        uint256 tokenId,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "lib/modular-account/src/helpers/ValidationDataHelpers.sol": {
        "content": "// This file is part of Modular Account.\n//\n// Copyright 2024 Alchemy Insights, Inc.\n//\n// SPDX-License-Identifier: GPL-3.0-or-later\n//\n// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General\n// Public License as published by the Free Software Foundation, either version 3 of the License, or (at your\n// option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the\n// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n// more details.\n//\n// You should have received a copy of the GNU General Public License along with this program. If not, see\n// <https://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.22;\n\nimport {SIG_VALIDATION_FAILED} from \"../libraries/Constants.sol\";\n\n/// @dev This helper function assumes that uint160(validationData1) and uint160(validationData2) can only be 0 or 1\n// solhint-disable-next-line private-vars-leading-underscore\nfunction _coalescePreValidation(uint256 validationData1, uint256 validationData2)\n    pure\n    returns (uint256 resValidationData)\n{\n    uint48 validUntil1 = uint48(validationData1 >> 160);\n    if (validUntil1 == 0) {\n        validUntil1 = type(uint48).max;\n    }\n    uint48 validUntil2 = uint48(validationData2 >> 160);\n    if (validUntil2 == 0) {\n        validUntil2 = type(uint48).max;\n    }\n    resValidationData = ((validUntil1 > validUntil2) ? uint256(validUntil2) << 160 : uint256(validUntil1) << 160);\n\n    uint48 validAfter1 = uint48(validationData1 >> 208);\n    uint48 validAfter2 = uint48(validationData2 >> 208);\n\n    resValidationData |= ((validAfter1 < validAfter2) ? uint256(validAfter2) << 208 : uint256(validAfter1) << 208);\n\n    // Once we know that the authorizer field is 0 or 1, we can safely bubble up SIG_FAIL with bitwise OR\n    resValidationData |= uint160(validationData1) | uint160(validationData2);\n}\n\n// solhint-disable-next-line private-vars-leading-underscore\nfunction _coalesceValidation(uint256 preValidationData, uint256 validationData)\n    pure\n    returns (uint256 resValidationData)\n{\n    uint48 validUntil1 = uint48(preValidationData >> 160);\n    if (validUntil1 == 0) {\n        validUntil1 = type(uint48).max;\n    }\n    uint48 validUntil2 = uint48(validationData >> 160);\n    if (validUntil2 == 0) {\n        validUntil2 = type(uint48).max;\n    }\n    resValidationData = ((validUntil1 > validUntil2) ? uint256(validUntil2) << 160 : uint256(validUntil1) << 160);\n\n    uint48 validAfter1 = uint48(preValidationData >> 208);\n    uint48 validAfter2 = uint48(validationData >> 208);\n\n    resValidationData |= ((validAfter1 < validAfter2) ? uint256(validAfter2) << 208 : uint256(validAfter1) << 208);\n\n    // If prevalidation failed, bubble up failure\n    resValidationData |=\n        uint160(preValidationData) == SIG_VALIDATION_FAILED ? SIG_VALIDATION_FAILED : uint160(validationData);\n}\n"
      },
      "lib/modular-account/src/interfaces/erc4337/IAccount.sol": {
        "content": "// This work is marked with CC0 1.0 Universal.\n//\n// SPDX-License-Identifier: CC0-1.0\n//\n// To view a copy of this license, visit http://creativecommons.org/publicdomain/zero/1.0\n\npragma solidity ^0.8.22;\n\nimport {IEntryPoint} from \"./IEntryPoint.sol\";\nimport {UserOperation} from \"./UserOperation.sol\";\n\n/// @notice Interface for the ERC-4337 account\ninterface IAccount {\n    /// @notice Validates a user operation, presumably by checking the signature and nonce. The entry point will\n    /// call this function to ensure that a user operation sent to it has been authorized, and thus that it should\n    /// call the account with the operation's call data and charge the account for  gas in the absense of a\n    /// paymaster. If the signature is correctly formatted but invalid, this should return 1; other failures may\n    /// revert instead. In the case of a success, this can optionally return a signature aggregator and/or a time\n    /// range during which the operation is valid.\n    /// @param userOp the operation to be validated\n    /// @param userOpHash hash of the operation\n    /// @param missingAccountFunds amount that the account must send to the entry point as part of validation to\n    /// pay for gas\n    /// @return validationData Either 1 for an invalid signature, or a packed structure containing an optional\n    /// aggregator address in the first 20 bytes followed by two 6-byte timestamps representing the \"validUntil\"\n    /// and \"validAfter\" times at which the operation is valid (a \"validUntil\" of 0 means it is valid forever).\n    function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\n        external\n        returns (uint256 validationData);\n}\n"
      },
      "lib/modular-account/src/interfaces/erc4337/IEntryPoint.sol": {
        "content": "// This work is marked with CC0 1.0 Universal.\n//\n// SPDX-License-Identifier: CC0-1.0\n//\n// To view a copy of this license, visit http://creativecommons.org/publicdomain/zero/1.0\n\npragma solidity ^0.8.22;\n\nimport {UserOperation} from \"./UserOperation.sol\";\n\n/// @notice Interface for the ERC-4337 entry point\ninterface IEntryPoint {\n    error FailedOp(uint256 i, string s);\n\n    function depositTo(address) external payable;\n    function addStake(uint32) external payable;\n    function unlockStake() external;\n    function withdrawStake(address payable) external;\n    function handleOps(UserOperation[] calldata, address payable) external;\n    function getNonce(address, uint192) external view returns (uint256);\n    function getUserOpHash(UserOperation calldata) external view returns (bytes32);\n}\n"
      },
      "lib/modular-account/src/interfaces/IAccountInitializable.sol": {
        "content": "// This work is marked with CC0 1.0 Universal.\n//\n// SPDX-License-Identifier: CC0-1.0\n//\n// To view a copy of this license, visit http://creativecommons.org/publicdomain/zero/1.0\n\npragma solidity ^0.8.22;\n\n/// @title Account Initializable Interface\ninterface IAccountInitializable {\n    /// @notice Initialize the account with a set of plugins.\n    /// @dev No dependencies may be provided with this installation.\n    /// @param plugins The plugins to install.\n    /// @param pluginInitData The plugin init data for each plugin.\n    function initialize(address[] calldata plugins, bytes calldata pluginInitData) external;\n}\n"
      },
      "lib/modular-account/src/interfaces/IAccountView.sol": {
        "content": "// This work is marked with CC0 1.0 Universal.\n//\n// SPDX-License-Identifier: CC0-1.0\n//\n// To view a copy of this license, visit http://creativecommons.org/publicdomain/zero/1.0\n\npragma solidity ^0.8.22;\n\nimport {IEntryPoint} from \"./erc4337/IEntryPoint.sol\";\n\n/// @title Account View Interface\ninterface IAccountView {\n    /// @notice Get the entry point for this account.\n    /// @return entryPoint The entry point for this account.\n    function entryPoint() external view returns (IEntryPoint);\n\n    /// @notice Get the account nonce.\n    /// @dev Uses key 0.\n    /// @return nonce The next account nonce.\n    function getNonce() external view returns (uint256);\n}\n"
      },
      "lib/modular-account/src/interfaces/IPluginExecutor.sol": {
        "content": "// This work is marked with CC0 1.0 Universal.\n//\n// SPDX-License-Identifier: CC0-1.0\n//\n// To view a copy of this license, visit http://creativecommons.org/publicdomain/zero/1.0\n\npragma solidity ^0.8.22;\n\n/// @title Plugin Executor Interface\ninterface IPluginExecutor {\n    /// @notice Execute a call from a plugin to another plugin, via an execution function installed on the account.\n    /// @dev Plugins are not allowed to call native functions on the account. Permissions must be granted to the\n    /// calling plugin for the call to go through.\n    /// @param data The calldata to send to the plugin.\n    /// @return The return data from the call.\n    function executeFromPlugin(bytes calldata data) external payable returns (bytes memory);\n\n    /// @notice Execute a call from a plugin to a non-plugin address.\n    /// @dev If the target is a plugin, the call SHOULD revert. Permissions must be granted to the calling plugin\n    /// for the call to go through.\n    /// @param target The address to be called.\n    /// @param value The value to send with the call.\n    /// @param data The calldata to send to the target.\n    /// @return The return data from the call.\n    function executeFromPluginExternal(address target, uint256 value, bytes calldata data)\n        external\n        payable\n        returns (bytes memory);\n}\n"
      },
      "lib/modular-account/src/interfaces/IPluginManager.sol": {
        "content": "// This work is marked with CC0 1.0 Universal.\n//\n// SPDX-License-Identifier: CC0-1.0\n//\n// To view a copy of this license, visit http://creativecommons.org/publicdomain/zero/1.0\n\npragma solidity ^0.8.22;\n\n// Treats the first 20 bytes as an address, and the last byte as a function identifier.\ntype FunctionReference is bytes21;\n\n/// @title Plugin Manager Interface\ninterface IPluginManager {\n    event PluginInstalled(address indexed plugin, bytes32 manifestHash, FunctionReference[] dependencies);\n    event PluginUninstalled(address indexed plugin, bool indexed onUninstallSucceeded);\n\n    /// @notice Install a plugin to the modular account.\n    /// @param plugin The plugin to install.\n    /// @param manifestHash The hash of the plugin manifest.\n    /// @param pluginInstallData Optional data to be decoded and used by the plugin to setup initial plugin data\n    /// for the modular account.\n    /// @param dependencies The dependencies of the plugin, as described in the manifest. Each FunctionReference\n    /// MUST be composed of an installed plugin's address and a function ID of its validation function.\n    function installPlugin(\n        address plugin,\n        bytes32 manifestHash,\n        bytes calldata pluginInstallData,\n        FunctionReference[] calldata dependencies\n    ) external;\n\n    /// @notice Uninstall a plugin from the modular account.\n    /// @dev Uninstalling owner plugins outside of a replace operation via executeBatch risks losing the account!\n    /// @param plugin The plugin to uninstall.\n    /// @param config An optional, implementation-specific field that accounts may use to ensure consistency\n    /// guarantees.\n    /// @param pluginUninstallData Optional data to be decoded and used by the plugin to clear plugin data for the\n    /// modular account.\n    function uninstallPlugin(address plugin, bytes calldata config, bytes calldata pluginUninstallData) external;\n}\n"
      },
      "lib/modular-account/src/libraries/CountableLinkedListSetLib.sol": {
        "content": "// This file is part of Modular Account.\n//\n// Copyright 2024 Alchemy Insights, Inc.\n//\n// SPDX-License-Identifier: MIT\n//\n// See LICENSE-MIT file for more information\n\npragma solidity ^0.8.22;\n\nimport {SetValue} from \"./Constants.sol\";\nimport {LinkedListSet, LinkedListSetLib} from \"./LinkedListSetLib.sol\";\n\n/// @title Countable Linked List Set Library\n/// @author Alchemy\n/// @notice This library adds the ability to count the number of occurrences of a value in a linked list set.\n/// @dev The counter is stored in the upper 8 bits of the the flag bytes, so the maximum value of the counter\n/// is 255. This means each value can be included a maximum of 256 times in the set, as the counter is 0 when\n/// the value is first added.\nlibrary CountableLinkedListSetLib {\n    using LinkedListSetLib for LinkedListSet;\n\n    /// @notice Increment an existing value in the set, or add it if it doesn't exist.\n    /// @dev The counter is stored in the upper 8 bits of the the flag bytes. Because this library repurposes a\n    /// portion of the flag bytes to store the counter, it's important to not use the upper 8 bits to store flags.\n    /// Any existing flags on the upper 8 bits will be interpreted as part of the counter.\n    /// @param set The set to increment (or add) the value in.\n    /// @param value The value to increment (or add).\n    /// @return True if the value was incremented or added, false otherwise.\n    function tryIncrement(LinkedListSet storage set, SetValue value) internal returns (bool) {\n        if (!set.contains(value)) {\n            return set.tryAdd(value);\n        }\n        uint16 flags = set.getFlags(value);\n        if (flags > 0xFEFF) {\n            // The counter is at its maximum value, so don't increment it.\n            return false;\n        }\n        unchecked {\n            flags += 0x100;\n        }\n        return set.trySetFlags(value, flags);\n    }\n\n    /// @notice Decrement an existing value in the set, or remove it if the count has reached 0.\n    /// @dev The counter is stored in the upper 8 bits of the the flag bytes. Because this library repurposes a\n    /// portion of the flag bytes to store the counter, it's important to not use the upper 8 bits to store flags.\n    /// Any existing flags on the upper 8 bits will be interpreted as part of the counter.\n    /// @param set The set to decrement (or remove) the value in.\n    /// @param value The value to decrement (or remove).\n    /// @return True if the value was decremented or removed, false otherwise.\n    function tryDecrement(LinkedListSet storage set, SetValue value) internal returns (bool) {\n        if (!set.contains(value)) {\n            return false;\n        }\n        uint16 flags = set.getFlags(value);\n        if (flags < 0x100) {\n            // The counter is 0, so remove the value.\n            return set.tryRemove(value);\n        }\n        unchecked {\n            flags -= 0x100;\n        }\n        return set.trySetFlags(value, flags);\n    }\n\n    /// @notice Get the number of occurrences of a value in the set.\n    /// @dev The counter is stored in the upper 8 bits of the the flag bytes. Because this library repurposes a\n    /// portion of the flag bytes to store the counter, it's important to not use the upper 8 bits to store flags.\n    /// Any existing flags on the upper 8 bits will be interpreted as part of the counter.\n    /// @return The number of occurrences of the value in the set.\n    function getCount(LinkedListSet storage set, SetValue value) internal view returns (uint256) {\n        if (!set.contains(value)) {\n            return 0;\n        }\n        unchecked {\n            return (set.getFlags(value) >> 8) + 1;\n        }\n    }\n}\n"
      },
      "lib/modular-account/src/libraries/LinkedListSetLib.sol": {
        "content": "// This file is part of Modular Account.\n//\n// Copyright 2024 Alchemy Insights, Inc.\n//\n// SPDX-License-Identifier: MIT\n//\n// See LICENSE-MIT file for more information\n\npragma solidity ^0.8.22;\n\nimport {SetValue, SENTINEL_VALUE, HAS_NEXT_FLAG} from \"./Constants.sol\";\n\nstruct LinkedListSet {\n    // Byte Layout\n    // | value | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA____ |\n    // | meta  | 0x____________________________________________________________BBBB |\n\n    // Bit-layout of the meta bytes (2 bytes)\n    // | user flags | 11111111 11111100 |\n    // | has next   | 00000000 00000010 |\n    // | sentinel   | 00000000 00000001 |\n\n    // Key excludes the meta bytes, except for the sentinel value, which is 0x1\n    mapping(bytes32 => bytes32) map;\n}\n\n/// @title Linked List Set Library\n/// @author Alchemy\n/// @notice This library provides a set of functions for managing enumerable sets of bytes30 values.\nlibrary LinkedListSetLib {\n    // INTERNAL METHODS\n\n    /// @notice Add a value to a set.\n    /// @param set The set to add the value to.\n    /// @param value The value to add.\n    /// @return True if the value was added, false if the value cannot be added (already exists or is zero).\n    function tryAdd(LinkedListSet storage set, SetValue value) internal returns (bool) {\n        mapping(bytes32 => bytes32) storage map = set.map;\n        bytes32 unwrappedKey = SetValue.unwrap(value);\n        if (unwrappedKey == bytes32(0) || map[unwrappedKey] != bytes32(0)) return false;\n\n        bytes32 prev = map[SENTINEL_VALUE];\n        if (prev == bytes32(0) || isSentinel(prev)) {\n            // Set is empty\n            map[SENTINEL_VALUE] = unwrappedKey;\n            map[unwrappedKey] = SENTINEL_VALUE;\n        } else {\n            // set is not empty\n            map[SENTINEL_VALUE] = unwrappedKey | HAS_NEXT_FLAG;\n            map[unwrappedKey] = prev;\n        }\n\n        return true;\n    }\n\n    /// @notice Remove a value from a set.\n    /// @dev This is an O(n) operation, where n is the number of elements in the set.\n    /// @param set The set to remove the value from.\n    /// @param value The value to remove.\n    /// @return True if the value was removed, false if the value does not exist.\n    function tryRemove(LinkedListSet storage set, SetValue value) internal returns (bool) {\n        mapping(bytes32 => bytes32) storage map = set.map;\n        bytes32 unwrappedKey = SetValue.unwrap(value);\n\n        bytes32 nextValue = map[unwrappedKey];\n        if (unwrappedKey == bytes32(0) || nextValue == bytes32(0)) return false;\n\n        bytes32 prevKey = SENTINEL_VALUE;\n        bytes32 currentVal;\n        do {\n            currentVal = map[prevKey];\n            bytes32 currentKey = clearFlags(currentVal);\n            if (currentKey == unwrappedKey) {\n                // Set the previous value's next value to the next value,\n                // and the flags to the current value's flags.\n                // and the next value's `hasNext` flag to determine whether or not the next value is (or points to)\n                // the sentinel value.\n                map[prevKey] = clearFlags(nextValue) | getUserFlags(currentVal) | (nextValue & HAS_NEXT_FLAG);\n                map[currentKey] = bytes32(0);\n\n                return true;\n            }\n            prevKey = currentKey;\n        } while (!isSentinel(currentVal) && currentVal != bytes32(0));\n        return false;\n    }\n\n    /// @notice Remove a value from a set, given the previous value in the set.\n    /// @dev This is an O(1) operation but requires additional knowledge.\n    /// @param set The set to remove the value from.\n    /// @param value The value to remove.\n    /// @param prev The previous value in the set.\n    /// @return True if the value was removed, false if the value does not exist.\n    function tryRemoveKnown(LinkedListSet storage set, SetValue value, bytes32 prev) internal returns (bool) {\n        mapping(bytes32 => bytes32) storage map = set.map;\n        bytes32 unwrappedKey = SetValue.unwrap(value);\n\n        // Clear the flag bits of prev\n        prev = clearFlags(prev);\n\n        if (prev == bytes32(0) || unwrappedKey == bytes32(0)) {\n            return false;\n        }\n\n        // assert that the previous value's next value is the value to be removed\n        bytes32 currentValue = map[prev];\n        if (clearFlags(currentValue) != unwrappedKey) {\n            return false;\n        }\n\n        bytes32 next = map[unwrappedKey];\n        if (next == bytes32(0)) {\n            // The set didn't actually contain the value\n            return false;\n        }\n\n        map[prev] = clearUserFlags(next) | getUserFlags(currentValue);\n        map[unwrappedKey] = bytes32(0);\n        return true;\n    }\n\n    /// @notice Remove all values from a set.\n    /// @dev This is an O(n) operation, where n is the number of elements in the set.\n    /// @param set The set to remove the values from.\n    function clear(LinkedListSet storage set) internal {\n        mapping(bytes32 => bytes32) storage map = set.map;\n        bytes32 cursor = SENTINEL_VALUE;\n\n        do {\n            bytes32 next = clearFlags(map[cursor]);\n            map[cursor] = bytes32(0);\n            cursor = next;\n        } while (!isSentinel(cursor) && cursor != bytes32(0));\n    }\n\n    /// @notice Set the flags on a value in the set.\n    /// @dev The user flags can only be set on the upper 14 bits, because the lower two are reserved for the\n    /// sentinel and has next bit.\n    /// @param set The set containing the value.\n    /// @param value The value to set the flags on.\n    /// @param flags The flags to set.\n    /// @return True if the set contains the value and the operation succeeds, false otherwise.\n    function trySetFlags(LinkedListSet storage set, SetValue value, uint16 flags) internal returns (bool) {\n        mapping(bytes32 => bytes32) storage map = set.map;\n        bytes32 unwrappedKey = SetValue.unwrap(value);\n\n        // Ignore the lower 2 bits.\n        flags &= 0xFFFC;\n\n        // If the set doesn't actually contain the value, return false;\n        bytes32 next = map[unwrappedKey];\n        if (next == bytes32(0)) {\n            return false;\n        }\n\n        // Set the flags\n        map[unwrappedKey] = clearUserFlags(next) | bytes32(uint256(flags));\n\n        return true;\n    }\n\n    /// @notice Set the given flags on a value in the set, preserving the values of other flags.\n    /// @dev The user flags can only be set on the upper 14 bits, because the lower two are reserved for the\n    /// sentinel and has next bit.\n    /// Short-circuits if the flags are already enabled, returning true.\n    /// @param set The set containing the value.\n    /// @param value The value to enable the flags on.\n    /// @param flags The flags to enable.\n    /// @return True if the operation succeeds or short-circuits due to the flags already being enabled. False\n    /// otherwise.\n    function tryEnableFlags(LinkedListSet storage set, SetValue value, uint16 flags) internal returns (bool) {\n        flags &= 0xFFFC; // Allow short-circuit if lower bits are accidentally set\n        uint16 currFlags = getFlags(set, value);\n        if (currFlags & flags == flags) return true; // flags are already enabled\n        return trySetFlags(set, value, currFlags | flags);\n    }\n\n    /// @notice Clear the given flags on a value in the set, preserving the values of other flags.\n    /// @notice If the value is not in the set, this function will still return true.\n    /// @dev The user flags can only be set on the upper 14 bits, because the lower two are reserved for the\n    /// sentinel and has next bit.\n    /// Short-circuits if the flags are already disabled, or if set does not contain the value. Short-circuits\n    /// return true.\n    /// @param set The set containing the value.\n    /// @param value The value to disable the flags on.\n    /// @param flags The flags to disable.\n    /// @return True if the operation succeeds, or short-circuits due to the flags already being disabled or if the\n    /// set does not contain the value. False otherwise.\n    function tryDisableFlags(LinkedListSet storage set, SetValue value, uint16 flags) internal returns (bool) {\n        flags &= 0xFFFC; // Allow short-circuit if lower bits are accidentally set\n        uint16 currFlags = getFlags(set, value);\n        if (currFlags & flags == 0) return true; // flags are already disabled\n        return trySetFlags(set, value, currFlags & ~flags);\n    }\n\n    /// @notice Check if a set contains a value.\n    /// @dev This method does not clear the upper bits of `value`, that is expected to be done as part of casting\n    /// to the correct type. If this function is provided the sentinel value by using the upper bits, this function\n    /// may returns `true`.\n    /// @param set The set to check.\n    /// @param value The value to check for.\n    /// @return True if the set contains the value, false otherwise.\n    function contains(LinkedListSet storage set, SetValue value) internal view returns (bool) {\n        mapping(bytes32 => bytes32) storage map = set.map;\n        return map[SetValue.unwrap(value)] != bytes32(0);\n    }\n\n    /// @notice Check if a set is empty.\n    /// @param set The set to check.\n    /// @return True if the set is empty, false otherwise.\n    function isEmpty(LinkedListSet storage set) internal view returns (bool) {\n        mapping(bytes32 => bytes32) storage map = set.map;\n        bytes32 val = map[SENTINEL_VALUE];\n        return val == bytes32(0) || isSentinel(val); // either the sentinel is unset, or points to itself\n    }\n\n    /// @notice Get the flags on a value in the set.\n    /// @dev The reserved lower 2 bits will not be returned, as those are reserved for the sentinel and has next\n    /// bit.\n    /// @param set The set containing the value.\n    /// @param value The value to get the flags from.\n    /// @return The flags set on the value.\n    function getFlags(LinkedListSet storage set, SetValue value) internal view returns (uint16) {\n        mapping(bytes32 => bytes32) storage map = set.map;\n        bytes32 unwrappedKey = SetValue.unwrap(value);\n\n        return uint16(uint256(map[unwrappedKey]) & 0xFFFC);\n    }\n\n    /// @notice Check if the flags on a value are enabled.\n    /// @dev The reserved lower 2 bits will be ignored, as those are reserved for the sentinel and has next bit.\n    /// @param set The set containing the value.\n    /// @param value The value to check the flags on.\n    /// @param flags The flags to check.\n    /// @return True if all of the flags are enabled, false otherwise.\n    function flagsEnabled(LinkedListSet storage set, SetValue value, uint16 flags) internal view returns (bool) {\n        flags &= 0xFFFC;\n        return getFlags(set, value) & flags == flags;\n    }\n\n    /// @notice Check if the flags on a value are disabled.\n    /// @dev The reserved lower 2 bits will be ignored, as those are reserved for the sentinel and has next bit.\n    /// @param set The set containing the value.\n    /// @param value The value to check the flags on.\n    /// @param flags The flags to check.\n    /// @return True if all of the flags are disabled, false otherwise.\n    function flagsDisabled(LinkedListSet storage set, SetValue value, uint16 flags) internal view returns (bool) {\n        flags &= 0xFFFC;\n        return ~(getFlags(set, value)) & flags == flags;\n    }\n\n    /// @notice Get all elements in a set.\n    /// @dev This is an O(n) operation, where n is the number of elements in the set.\n    /// @param set The set to get the elements of.\n    /// @return ret An array of all elements in the set.\n    function getAll(LinkedListSet storage set) internal view returns (SetValue[] memory ret) {\n        mapping(bytes32 => bytes32) storage map = set.map;\n        uint256 size;\n        bytes32 cursor = map[SENTINEL_VALUE];\n\n        // Dynamically allocate the returned array as we iterate through the set, since we don't know the size\n        // beforehand.\n        // This is accomplished by first writing to memory after the free memory pointer,\n        // then updating the free memory pointer to cover the newly-allocated data.\n        // To the compiler, writes to memory after the free memory pointer are considered \"memory safe\".\n        // See https://docs.soliditylang.org/en/v0.8.22/assembly.html#memory-safety\n        // Stack variable lifting done when compiling with via-ir will only ever place variables into memory\n        // locations below the current free memory pointer, so it is safe to compile this library with via-ir.\n        // See https://docs.soliditylang.org/en/v0.8.22/yul.html#memoryguard\n        assembly (\"memory-safe\") {\n            // It is critical that no other memory allocations occur between:\n            // -  loading the value of the free memory pointer into `ret`\n            // -  updating the free memory pointer to point to the newly-allocated data, which is done after all\n            // the values have been written.\n            ret := mload(0x40)\n        }\n\n        while (!isSentinel(cursor) && cursor != bytes32(0)) {\n            unchecked {\n                ++size;\n            }\n            bytes32 cleared = clearFlags(cursor);\n            // Place the item into the return array manually. Since the size was just incremented, it will point to\n            // the next location to write to.\n            assembly (\"memory-safe\") {\n                mstore(add(ret, mul(size, 0x20)), cleared)\n            }\n            if (hasNext(cursor)) {\n                cursor = map[cleared];\n            } else {\n                cursor = bytes32(0);\n            }\n        }\n\n        assembly (\"memory-safe\") {\n            // Update the free memory pointer with the now-known length of the array.\n            mstore(0x40, add(ret, mul(add(size, 1), 0x20)))\n            // Set the length of the array.\n            mstore(ret, size)\n        }\n    }\n\n    function isSentinel(bytes32 value) internal pure returns (bool ret) {\n        assembly (\"memory-safe\") {\n            ret := and(value, 1)\n        }\n    }\n\n    function hasNext(bytes32 value) internal pure returns (bool) {\n        return value & HAS_NEXT_FLAG != 0;\n    }\n\n    function clearFlags(bytes32 val) internal pure returns (bytes32) {\n        return val & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0001;\n    }\n\n    /// @dev Preserves the lower two bits\n    function clearUserFlags(bytes32 val) internal pure returns (bytes32) {\n        return val & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0003;\n    }\n\n    function getUserFlags(bytes32 val) internal pure returns (bytes32) {\n        return val & bytes32(uint256(0xFFFC));\n    }\n}\n"
      },
      "lib/modular-account/src/account/AccountExecutor.sol": {
        "content": "// This file is part of Modular Account.\n//\n// Copyright 2024 Alchemy Insights, Inc.\n//\n// SPDX-License-Identifier: GPL-3.0-or-later\n//\n// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General\n// Public License as published by the Free Software Foundation, either version 3 of the License, or (at your\n// option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the\n// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n// more details.\n//\n// You should have received a copy of the GNU General Public License along with this program. If not, see\n// <https://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.22;\n\nimport {ERC165Checker} from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\n\nimport {UserOperation} from \"../interfaces/erc4337/UserOperation.sol\";\nimport {IPlugin} from \"../interfaces/IPlugin.sol\";\n\n/// @title Account Executor\n/// @author Alchemy\n/// @notice Provides internal functions for executing calls on a modular account.\nabstract contract AccountExecutor {\n    error PluginCallDenied(address plugin);\n\n    /// @dev If the target is a plugin (as determined by its support for the IPlugin interface), revert.\n    /// This prevents the modular account from calling plugins (both installed and uninstalled) outside\n    /// of the normal flow (via execution functions installed on the account), which could lead to data\n    /// inconsistencies and unexpected behavior.\n    /// @param target The address of the contract to call.\n    /// @param value The value to send with the call.\n    /// @param data The call data.\n    /// @return result The return data of the call, or the error message from the call if call reverts.\n    function _exec(address target, uint256 value, bytes memory data) internal returns (bytes memory result) {\n        if (ERC165Checker.supportsInterface(target, type(IPlugin).interfaceId)) {\n            revert PluginCallDenied(target);\n        }\n\n        bool success;\n        (success, result) = target.call{value: value}(data);\n\n        if (!success) {\n            // Directly bubble up revert messages\n            assembly (\"memory-safe\") {\n                revert(add(result, 32), mload(result))\n            }\n        }\n    }\n\n    /// @dev Performs an `_executeRaw` for a call buffer holding a call to one of:\n    /// - Pre Runtime Validation Hook\n    /// - Runtime Validation\n    /// - Pre Execution Hook\n    /// And if it fails, reverts with the appropriate custom error.\n    function _executeRuntimePluginFunction(bytes memory buffer, address plugin, bytes4 errorSelector) internal {\n        if (!_executeRaw(plugin, buffer)) {\n            _revertOnRuntimePluginFunctionFail(buffer, plugin, errorSelector);\n        }\n    }\n\n    function _executeRaw(address plugin, bytes memory buffer) internal returns (bool success) {\n        assembly (\"memory-safe\") {\n            success :=\n                call(\n                    gas(),\n                    plugin,\n                    /*value*/\n                    0,\n                    /*argOffset*/\n                    add(buffer, 0x20), // jump over 32 bytes for length\n                    /*argSize*/\n                    mload(buffer),\n                    /*retOffset*/\n                    0,\n                    /*retSize*/\n                    0\n                )\n        }\n    }\n\n    function _executeUserOpPluginFunction(bytes memory buffer, address plugin)\n        internal\n        returns (uint256 validationData)\n    {\n        assembly (\"memory-safe\") {\n            switch and(\n                gt(returndatasize(), 0x1f),\n                call(\n                    /*forward all gas, but can't use gas opcode due to validation opcode restrictions*/\n                    not(0),\n                    plugin,\n                    /*value*/\n                    0,\n                    /*argOffset*/\n                    add(buffer, 0x20), // jump over 32 bytes for length\n                    /*argSize*/\n                    mload(buffer),\n                    /*retOffset*/\n                    0,\n                    /*retSize*/\n                    0x20\n                )\n            )\n            case 0 {\n                // Bubble up the revert if the call reverts.\n                let m := mload(0x40)\n                returndatacopy(m, 0x00, returndatasize())\n                revert(m, returndatasize())\n            }\n            default {\n                // Otherwise, we return the first word of the return data as the validation data\n                validationData := mload(0)\n            }\n        }\n    }\n\n    function _allocateRuntimeCallBuffer(bytes calldata data) internal view returns (bytes memory buffer) {\n        buffer = abi.encodeWithSelector(bytes4(0), 0, msg.sender, msg.value, data);\n    }\n\n    function _allocateUserOpCallBuffer(bytes4 selector, UserOperation calldata userOp, bytes32 userOpHash)\n        internal\n        pure\n        returns (bytes memory buffer)\n    {\n        buffer = abi.encodeWithSelector(selector, 0, userOp, userOpHash);\n    }\n\n    /// @dev Updates which plugin function the buffer will call.\n    function _updatePluginCallBufferSelector(bytes memory buffer, bytes4 pluginSelector) internal pure {\n        assembly (\"memory-safe\") {\n            // We only want to write to the first 4 bytes, so we first load the first word,\n            // mask out the fist 4 bytes, then OR in the new selector.\n            let existingWord := mload(add(buffer, 0x20))\n            // Clear the upper 4 bytes of the existing word\n            existingWord := shr(32, shl(32, existingWord))\n            // Clear the lower 28 bytes of the selector\n            pluginSelector := shl(224, shr(224, pluginSelector))\n            // OR in the new selector\n            existingWord := or(existingWord, pluginSelector)\n            mstore(add(buffer, 0x20), existingWord)\n        }\n    }\n\n    function _updatePluginCallBufferFunctionId(bytes memory buffer, uint8 functionId) internal pure {\n        assembly (\"memory-safe\") {\n            // The function ID is a uint8 type, which is left-padded.\n            // We do want to mask it, however, because this is an internal function and the upper bits may not be\n            // cleared.\n            mstore(add(buffer, 0x24), and(functionId, 0xff))\n        }\n    }\n\n    /// @dev Re-interpret the existing call buffer as just a bytes memory hold msg.data.\n    /// Since it's already there, and we don't plan on using the buffer again, we can write over the other fields\n    /// to store calldata length before the data, then return a new memory pointer holding the length.\n    function _convertRuntimeCallBufferToExecBuffer(bytes memory runtimeCallBuffer)\n        internal\n        pure\n        returns (bytes memory execCallBuffer)\n    {\n        if (runtimeCallBuffer.length == 0) {\n            // There was no existing call buffer. This case is never reached in actual code, but in the event that\n            // it would be, we would need to re-collect all the calldata.\n            execCallBuffer = msg.data;\n        } else {\n            assembly (\"memory-safe\") {\n                // Skip forward to point to the new \"length-holding\" field.\n                // Since the existing buffer is already ABI-encoded, we can just skip to the inner callData field.\n                // This field is location  bytes ahead. It skips over:\n                // - (32 bytes) The original buffer's length field\n                // - (4 bytes) Selector\n                // - (32 bytes) Function id\n                // - (32 bytes) Sender\n                // - (32 bytes) Value\n                // - (32 bytes) data offset\n                // Total: 164 bytes\n                execCallBuffer := add(runtimeCallBuffer, 164)\n            }\n        }\n    }\n\n    /// @dev Used by pre exec hooks to store data for post exec hooks.\n    function _collectReturnData() internal pure returns (bytes memory returnData) {\n        assembly (\"memory-safe\") {\n            // Allocate a buffer of that size, advancing the memory pointer to the nearest word\n            returnData := mload(0x40)\n            mstore(returnData, returndatasize())\n            mstore(0x40, and(add(add(returnData, returndatasize()), 0x3f), not(0x1f)))\n\n            // Copy over the return data\n            returndatacopy(add(returnData, 0x20), 0, returndatasize())\n        }\n    }\n\n    /// @dev This function reverts with one of the following custom error types:\n    /// - PreRuntimeValidationHookFailed\n    /// - RuntimeValidationFunctionReverted\n    /// - PreExecHookReverted\n    /// Since they all take the same parameters, we can just switch the selector as needed.\n    /// The last parameter, revertReason, is copied from return data.\n    function _revertOnRuntimePluginFunctionFail(bytes memory buffer, address plugin, bytes4 errorSelector)\n        internal\n        pure\n    {\n        assembly (\"memory-safe\") {\n            // Call failed, revert with the established error format and the provided selector\n            // The error format is:\n            // - Custom error selector\n            // - plugin address\n            // - function id\n            // - byte offset and length of revert reason\n            // - byte memory revertReason\n            // Total size: 132 bytes (4 byte selector + 4 * 32 byte words) + length of revert reason\n            let errorStart := mload(0x40)\n            // We add the extra size for the abi encoded fields at the same time as the selector,\n            // which is after the word-alignment step.\n            // Pad errorSize to nearest word\n            let errorSize := and(add(returndatasize(), 0x1f), not(0x1f))\n            // Add the abi-encoded fields length (128 bytes) and the selector's size (4 bytes)\n            // to the error size.\n            errorSize := add(errorSize, 132)\n            // Store the selector in the start of the error buffer.\n            // Any set lower bits will be cleared with the subsequest mstore.\n            mstore(errorStart, errorSelector)\n            mstore(add(errorStart, 0x04), plugin)\n            // Store the function id in the next word, as retrieved from the buffer\n            mstore(add(errorStart, 0x24), mload(add(buffer, 0x24)))\n            // Store the offset and length of the revert reason in the next two words\n            mstore(add(errorStart, 0x44), 0x60)\n            mstore(add(errorStart, 0x64), returndatasize())\n\n            // Copy over the revert reason\n            returndatacopy(add(errorStart, 0x84), 0, returndatasize())\n\n            // Revert\n            revert(errorStart, errorSize)\n        }\n    }\n}\n"
      },
      "lib/modular-account/src/account/AccountLoupe.sol": {
        "content": "// This file is part of Modular Account.\n//\n// Copyright 2024 Alchemy Insights, Inc.\n//\n// SPDX-License-Identifier: GPL-3.0-or-later\n//\n// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General\n// Public License as published by the Free Software Foundation, either version 3 of the License, or (at your\n// option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the\n// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n// more details.\n//\n// You should have received a copy of the GNU General Public License along with this program. If not, see\n// <https://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.22;\n\nimport {AccountStorageV1} from \"../account/AccountStorageV1.sol\";\nimport {CastLib} from \"../helpers/CastLib.sol\";\nimport {KnownSelectors} from \"../helpers/KnownSelectors.sol\";\nimport {IAccountLoupe} from \"../interfaces/IAccountLoupe.sol\";\nimport {FunctionReference} from \"../interfaces/IPluginManager.sol\";\nimport {CountableLinkedListSetLib} from \"../libraries/CountableLinkedListSetLib.sol\";\nimport {LinkedListSet, LinkedListSetLib} from \"../libraries/LinkedListSetLib.sol\";\n\n/// @title Account Loupe\n/// @author Alchemy\n/// @notice Provides view functions for querying the configuration of a modular account.\nabstract contract AccountLoupe is IAccountLoupe, AccountStorageV1 {\n    using LinkedListSetLib for LinkedListSet;\n    using CountableLinkedListSetLib for LinkedListSet;\n\n    /// @inheritdoc IAccountLoupe\n    function getExecutionFunctionConfig(bytes4 selector)\n        external\n        view\n        returns (ExecutionFunctionConfig memory config)\n    {\n        AccountStorage storage storage_ = _getAccountStorage();\n\n        if (KnownSelectors.isNativeFunction(selector)) {\n            config.plugin = address(this);\n        } else {\n            config.plugin = storage_.selectorData[selector].plugin;\n        }\n\n        config.userOpValidationFunction = storage_.selectorData[selector].userOpValidation;\n        config.runtimeValidationFunction = storage_.selectorData[selector].runtimeValidation;\n    }\n\n    /// @inheritdoc IAccountLoupe\n    function getExecutionHooks(bytes4 selector) external view returns (ExecutionHooks[] memory execHooks) {\n        execHooks = _getHooks(_getAccountStorage().selectorData[selector].executionHooks);\n    }\n\n    /// @inheritdoc IAccountLoupe\n    function getPreValidationHooks(bytes4 selector)\n        external\n        view\n        returns (\n            FunctionReference[] memory preUserOpValidationHooks,\n            FunctionReference[] memory preRuntimeValidationHooks\n        )\n    {\n        SelectorData storage selectorData = _getAccountStorage().selectorData[selector];\n        preUserOpValidationHooks = CastLib.toFunctionReferenceArray(selectorData.preUserOpValidationHooks.getAll());\n        preRuntimeValidationHooks =\n            CastLib.toFunctionReferenceArray(selectorData.preRuntimeValidationHooks.getAll());\n    }\n\n    /// @inheritdoc IAccountLoupe\n    function getInstalledPlugins() external view returns (address[] memory pluginAddresses) {\n        pluginAddresses = CastLib.toAddressArray(_getAccountStorage().plugins.getAll());\n    }\n\n    /// @dev Collects hook data from stored execution hooks and prepares it for returning as the `ExecutionHooks`\n    /// type defined by `IAccountLoupe`.\n    function _getHooks(HookGroup storage storedHooks) internal view returns (ExecutionHooks[] memory execHooks) {\n        FunctionReference[] memory preExecHooks = CastLib.toFunctionReferenceArray(storedHooks.preHooks.getAll());\n        FunctionReference[] memory postOnlyExecHooks =\n            CastLib.toFunctionReferenceArray(storedHooks.postOnlyHooks.getAll());\n\n        uint256 preExecHooksLength = preExecHooks.length;\n        uint256 postOnlyExecHooksLength = postOnlyExecHooks.length;\n        uint256 maxExecHooksLength = postOnlyExecHooksLength;\n\n        // There can only be as many associated post hooks to run as there are pre hooks.\n        for (uint256 i = 0; i < preExecHooksLength; ++i) {\n            unchecked {\n                maxExecHooksLength += storedHooks.preHooks.getCount(CastLib.toSetValue(preExecHooks[i]));\n            }\n        }\n\n        // Overallocate on length - not all of this may get filled up. We set the correct length later.\n        execHooks = new ExecutionHooks[](maxExecHooksLength);\n        uint256 actualExecHooksLength = 0;\n\n        for (uint256 i = 0; i < preExecHooksLength; ++i) {\n            FunctionReference[] memory associatedPostExecHooks =\n                CastLib.toFunctionReferenceArray(storedHooks.associatedPostHooks[preExecHooks[i]].getAll());\n            uint256 associatedPostExecHooksLength = associatedPostExecHooks.length;\n\n            if (associatedPostExecHooksLength > 0) {\n                for (uint256 j = 0; j < associatedPostExecHooksLength; ++j) {\n                    execHooks[actualExecHooksLength].preExecHook = preExecHooks[i];\n                    execHooks[actualExecHooksLength].postExecHook = associatedPostExecHooks[j];\n\n                    unchecked {\n                        ++actualExecHooksLength;\n                    }\n                }\n            } else {\n                execHooks[actualExecHooksLength].preExecHook = preExecHooks[i];\n\n                unchecked {\n                    ++actualExecHooksLength;\n                }\n            }\n        }\n\n        for (uint256 i = 0; i < postOnlyExecHooksLength; ++i) {\n            execHooks[actualExecHooksLength].postExecHook = postOnlyExecHooks[i];\n\n            unchecked {\n                ++actualExecHooksLength;\n            }\n        }\n\n        // \"Trim\" the exec hooks array to the actual length, since we may have overallocated.\n        assembly (\"memory-safe\") {\n            mstore(execHooks, actualExecHooksLength)\n        }\n    }\n}\n"
      },
      "lib/modular-account/src/account/AccountStorageInitializable.sol": {
        "content": "// This file is part of Modular Account.\n//\n// Copyright 2024 Alchemy Insights, Inc.\n//\n// SPDX-License-Identifier: GPL-3.0-or-later\n//\n// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General\n// Public License as published by the Free Software Foundation, either version 3 of the License, or (at your\n// option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the\n// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n// more details.\n//\n// You should have received a copy of the GNU General Public License along with this program. If not, see\n// <https://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.22;\n\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\n\nimport {AccountStorageV1} from \"../account/AccountStorageV1.sol\";\n\n/// @title Account Storage Initializable\n/// @author Alchemy\n/// @notice This enables functions that can be called only once per implementation with the same storage layout\n/// @dev Adapted from OpenZeppelin's Initializable and modified to use a diamond storage pattern. Removed\n/// Initialized() event since the account already emits an event on initialization.\nabstract contract AccountStorageInitializable is AccountStorageV1 {\n    error AlreadyInitialized();\n    error AlreadyInitializing();\n\n    /// @notice Modifier to put on function intended to be called only once per implementation\n    /// @dev Reverts if the contract has already been initialized\n    modifier initializer() {\n        AccountStorage storage storage_ = _getAccountStorage();\n        bool isTopLevelCall = !storage_.initializing;\n        if (\n            isTopLevelCall && storage_.initialized < 1\n                || !Address.isContract(address(this)) && storage_.initialized == 1\n        ) {\n            storage_.initialized = 1;\n            if (isTopLevelCall) {\n                storage_.initializing = true;\n            }\n            _;\n            if (isTopLevelCall) {\n                storage_.initializing = false;\n            }\n        } else {\n            revert AlreadyInitialized();\n        }\n    }\n\n    /// @notice Internal function to disable calls to initialization functions\n    /// @dev Reverts if the contract has already been initialized\n    function _disableInitializers() internal virtual {\n        AccountStorage storage storage_ = _getAccountStorage();\n        if (storage_.initializing) {\n            revert AlreadyInitializing();\n        }\n        if (storage_.initialized != type(uint8).max) {\n            storage_.initialized = type(uint8).max;\n        }\n    }\n}\n"
      },
      "lib/modular-account/src/account/PluginManagerInternals.sol": {
        "content": "// This file is part of Modular Account.\n//\n// Copyright 2024 Alchemy Insights, Inc.\n//\n// SPDX-License-Identifier: GPL-3.0-or-later\n//\n// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General\n// Public License as published by the Free Software Foundation, either version 3 of the License, or (at your\n// option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the\n// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n// more details.\n//\n// You should have received a copy of the GNU General Public License along with this program. If not, see\n// <https://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.22;\n\nimport {ERC165Checker} from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\n\nimport {AccountStorageV1} from \"../account/AccountStorageV1.sol\";\nimport {CastLib} from \"../helpers/CastLib.sol\";\nimport {FunctionReferenceLib} from \"../helpers/FunctionReferenceLib.sol\";\nimport {KnownSelectors} from \"../helpers/KnownSelectors.sol\";\nimport {\n    IPlugin,\n    ManifestAssociatedFunction,\n    ManifestAssociatedFunctionType,\n    ManifestExecutionHook,\n    ManifestExternalCallPermission,\n    ManifestFunction,\n    PluginManifest\n} from \"../interfaces/IPlugin.sol\";\nimport {FunctionReference, IPluginManager} from \"../interfaces/IPluginManager.sol\";\nimport {CountableLinkedListSetLib} from \"../libraries/CountableLinkedListSetLib.sol\";\nimport {LinkedListSet, LinkedListSetLib} from \"../libraries/LinkedListSetLib.sol\";\n\n/// @title Plugin Manager Internals\n/// @author Alchemy\n/// @notice Contains functions to manage the state and behavior of plugin installs and uninstalls.\nabstract contract PluginManagerInternals is IPluginManager, AccountStorageV1 {\n    using LinkedListSetLib for LinkedListSet;\n    using CountableLinkedListSetLib for LinkedListSet;\n    using FunctionReferenceLib for FunctionReference;\n\n    // Grouping of arguments to `uninstallPlugin` to avoid \"stack too deep\"\n    // errors when building without via-ir.\n    struct UninstallPluginArgs {\n        address plugin;\n        PluginManifest manifest;\n        bool forceUninstall;\n        uint256 callbackGasLimit;\n    }\n\n    // As per the EIP-165 spec, no interface should ever match 0xffffffff\n    bytes4 internal constant _INVALID_INTERFACE_ID = 0xffffffff;\n\n    // These flags are used in LinkedListSet values to optimize lookups.\n    // It's important that they don't overlap with bit 1 and bit 2, which are reserved bits used to indicate\n    // the sentinel value and the existence of a next value, respectively.\n    uint16 internal constant _PRE_EXEC_HOOK_HAS_POST_FLAG = 0x0004; // bit 3\n\n    error ArrayLengthMismatch();\n    error DuplicateHookLimitExceeded(bytes4 selector, FunctionReference hook);\n    error DuplicatePreRuntimeValidationHookLimitExceeded(bytes4 selector, FunctionReference hook);\n    error DuplicatePreUserOpValidationHookLimitExceeded(bytes4 selector, FunctionReference hook);\n    error Erc4337FunctionNotAllowed(bytes4 selector);\n    error ExecutionFunctionAlreadySet(bytes4 selector);\n    error InterfaceNotAllowed();\n    error InvalidDependenciesProvided();\n    error InvalidPluginManifest();\n    error IPluginFunctionNotAllowed(bytes4 selector);\n    error MissingPluginDependency(address dependency);\n    error NativeFunctionNotAllowed(bytes4 selector);\n    error NullFunctionReference();\n    error PluginAlreadyInstalled(address plugin);\n    error PluginDependencyViolation(address plugin);\n    error PluginInstallCallbackFailed(address plugin, bytes revertReason);\n    error PluginInterfaceNotSupported(address plugin);\n    error PluginNotInstalled(address plugin);\n    error PluginUninstallCallbackFailed(address plugin, bytes revertReason);\n    error RuntimeValidationFunctionAlreadySet(bytes4 selector, FunctionReference validationFunction);\n    error UserOpValidationFunctionAlreadySet(bytes4 selector, FunctionReference validationFunction);\n\n    // Storage update operations\n\n    function _setExecutionFunction(bytes4 selector, address plugin) internal {\n        SelectorData storage selectorData = _getAccountStorage().selectorData[selector];\n\n        if (selectorData.plugin != address(0)) {\n            revert ExecutionFunctionAlreadySet(selector);\n        }\n\n        // Make sure incoming execution function does not collide with any native functions (data are stored on the\n        // account implementation contract)\n        if (KnownSelectors.isNativeFunction(selector)) {\n            revert NativeFunctionNotAllowed(selector);\n        }\n\n        // Make sure incoming execution function is not a function in IPlugin\n        if (KnownSelectors.isIPluginFunction(selector)) {\n            revert IPluginFunctionNotAllowed(selector);\n        }\n\n        // Also make sure it doesn't collide with functions defined by ERC-4337\n        // and called by the entry point. This prevents a malicious plugin from\n        // sneaking in a function with the same selector as e.g.\n        // `validatePaymasterUserOp` and turning the account into their own\n        // personal paymaster.\n        if (KnownSelectors.isErc4337Function(selector)) {\n            revert Erc4337FunctionNotAllowed(selector);\n        }\n\n        selectorData.plugin = plugin;\n    }\n\n    function _addUserOpValidationFunction(bytes4 selector, FunctionReference validationFunction) internal {\n        _assertNotNullFunction(validationFunction);\n\n        SelectorData storage selectorData = _getAccountStorage().selectorData[selector];\n\n        if (!selectorData.userOpValidation.isEmpty()) {\n            revert UserOpValidationFunctionAlreadySet(selector, validationFunction);\n        }\n\n        selectorData.userOpValidation = validationFunction;\n    }\n\n    function _addRuntimeValidationFunction(bytes4 selector, FunctionReference validationFunction) internal {\n        _assertNotNullFunction(validationFunction);\n\n        SelectorData storage selectorData = _getAccountStorage().selectorData[selector];\n\n        if (!selectorData.runtimeValidation.isEmpty()) {\n            revert RuntimeValidationFunctionAlreadySet(selector, validationFunction);\n        }\n\n        selectorData.runtimeValidation = validationFunction;\n    }\n\n    function _addExecHooks(bytes4 selector, FunctionReference preExecHook, FunctionReference postExecHook)\n        internal\n    {\n        SelectorData storage selectorData = _getAccountStorage().selectorData[selector];\n\n        _addHooks(selectorData.executionHooks, selector, preExecHook, postExecHook);\n\n        if (!preExecHook.isEmpty()) {\n            selectorData.hasPreExecHooks = true;\n        } else if (!postExecHook.isEmpty()) {\n            // Only set this flag if the pre hook is empty and the post hook is non-empty.\n            selectorData.hasPostOnlyExecHooks = true;\n        }\n    }\n\n    function _removeExecHooks(bytes4 selector, FunctionReference preExecHook, FunctionReference postExecHook)\n        internal\n    {\n        SelectorData storage selectorData = _getAccountStorage().selectorData[selector];\n\n        (bool shouldClearHasPreHooks, bool shouldClearHasPostOnlyHooks) =\n            _removeHooks(selectorData.executionHooks, preExecHook, postExecHook);\n\n        if (shouldClearHasPreHooks) {\n            selectorData.hasPreExecHooks = false;\n        }\n\n        if (shouldClearHasPostOnlyHooks) {\n            selectorData.hasPostOnlyExecHooks = false;\n        }\n    }\n\n    function _addHooks(\n        HookGroup storage hooks,\n        bytes4 selector,\n        FunctionReference preExecHook,\n        FunctionReference postExecHook\n    ) internal {\n        if (!preExecHook.isEmpty()) {\n            // add pre or pre/post pair of exec hooks\n            if (!hooks.preHooks.tryIncrement(CastLib.toSetValue(preExecHook))) {\n                revert DuplicateHookLimitExceeded(selector, preExecHook);\n            }\n\n            if (!postExecHook.isEmpty()) {\n                // can ignore return val of tryEnableFlags here as tryIncrement above must have succeeded\n                hooks.preHooks.tryEnableFlags(CastLib.toSetValue(preExecHook), _PRE_EXEC_HOOK_HAS_POST_FLAG);\n                if (!hooks.associatedPostHooks[preExecHook].tryIncrement(CastLib.toSetValue(postExecHook))) {\n                    revert DuplicateHookLimitExceeded(selector, postExecHook);\n                }\n            }\n        } else {\n            // both pre and post hooks cannot be null\n            _assertNotNullFunction(postExecHook);\n\n            if (!hooks.postOnlyHooks.tryIncrement(CastLib.toSetValue(postExecHook))) {\n                revert DuplicateHookLimitExceeded(selector, postExecHook);\n            }\n        }\n    }\n\n    function _removeHooks(HookGroup storage hooks, FunctionReference preExecHook, FunctionReference postExecHook)\n        internal\n        returns (bool shouldClearHasPreHooks, bool shouldClearHasPostOnlyHooks)\n    {\n        if (!preExecHook.isEmpty()) {\n            // If decrementing results in removal, this also clears the flag _PRE_EXEC_HOOK_HAS_POST_FLAG.\n            // Can ignore the return value because the manifest was checked to match the hash.\n            hooks.preHooks.tryDecrement(CastLib.toSetValue(preExecHook));\n\n            // Update the cached flag value for the pre-exec hooks, as it may change with a removal.\n            if (hooks.preHooks.isEmpty()) {\n                // The \"has pre exec hooks\" flag should be disabled\n                shouldClearHasPreHooks = true;\n            }\n\n            if (!postExecHook.isEmpty()) {\n                // Remove the associated post-exec hook, if it is set to the expected value.\n                // Can ignore the return value because the manifest was checked to match the hash.\n                hooks.associatedPostHooks[preExecHook].tryDecrement(CastLib.toSetValue(postExecHook));\n\n                if (hooks.associatedPostHooks[preExecHook].isEmpty()) {\n                    // We can ignore return val of tryDisableFlags here as tryDecrement above must have succeeded\n                    // in either removing the element or decrementing its count.\n                    hooks.preHooks.tryDisableFlags(CastLib.toSetValue(preExecHook), _PRE_EXEC_HOOK_HAS_POST_FLAG);\n                }\n            }\n        } else {\n            // If this else branch is reached, it must be a post-only exec hook, because installation would fail\n            // when both the pre and post exec hooks are empty.\n\n            // Can ignore the return value because the manifest was checked to match the hash.\n            hooks.postOnlyHooks.tryDecrement(CastLib.toSetValue(postExecHook));\n\n            // Update the cached flag value for the post-only exec hooks, as it may change with a removal.\n            if (hooks.postOnlyHooks.isEmpty()) {\n                // The \"has post only hooks\" flag should be disabled\n                shouldClearHasPostOnlyHooks = true;\n            }\n        }\n    }\n\n    function _addPreUserOpValidationHook(bytes4 selector, FunctionReference preUserOpValidationHook) internal {\n        _assertNotNullFunction(preUserOpValidationHook);\n\n        SelectorData storage selectorData = _getAccountStorage().selectorData[selector];\n        if (!selectorData.preUserOpValidationHooks.tryIncrement(CastLib.toSetValue(preUserOpValidationHook))) {\n            revert DuplicatePreUserOpValidationHookLimitExceeded(selector, preUserOpValidationHook);\n        }\n        // add the pre user op validation hook to the cache for the given selector\n        if (!selectorData.hasPreUserOpValidationHooks) {\n            selectorData.hasPreUserOpValidationHooks = true;\n        }\n    }\n\n    function _removePreUserOpValidationHook(bytes4 selector, FunctionReference preUserOpValidationHook) internal {\n        SelectorData storage selectorData = _getAccountStorage().selectorData[selector];\n        // Can ignore the return value because the manifest was checked to match the hash.\n        selectorData.preUserOpValidationHooks.tryDecrement(CastLib.toSetValue(preUserOpValidationHook));\n\n        if (selectorData.preUserOpValidationHooks.isEmpty()) {\n            selectorData.hasPreUserOpValidationHooks = false;\n        }\n    }\n\n    function _addPreRuntimeValidationHook(bytes4 selector, FunctionReference preRuntimeValidationHook) internal {\n        _assertNotNullFunction(preRuntimeValidationHook);\n\n        SelectorData storage selectorData = _getAccountStorage().selectorData[selector];\n        if (!selectorData.preRuntimeValidationHooks.tryIncrement(CastLib.toSetValue(preRuntimeValidationHook))) {\n            revert DuplicatePreRuntimeValidationHookLimitExceeded(selector, preRuntimeValidationHook);\n        }\n        // add the pre runtime validation hook's existence to the validator cache for the given selector\n        if (!selectorData.hasPreRuntimeValidationHooks) {\n            selectorData.hasPreRuntimeValidationHooks = true;\n        }\n    }\n\n    function _removePreRuntimeValidationHook(bytes4 selector, FunctionReference preRuntimeValidationHook)\n        internal\n    {\n        SelectorData storage selectorData = _getAccountStorage().selectorData[selector];\n        // Can ignore the return value because the manifest was checked to match the hash.\n        selectorData.preRuntimeValidationHooks.tryDecrement(CastLib.toSetValue(preRuntimeValidationHook));\n\n        if (selectorData.preRuntimeValidationHooks.isEmpty()) {\n            selectorData.hasPreRuntimeValidationHooks = false;\n        }\n    }\n\n    function _installPlugin(\n        address plugin,\n        bytes32 manifestHash,\n        bytes memory pluginInstallData,\n        FunctionReference[] memory dependencies\n    ) internal {\n        AccountStorage storage storage_ = _getAccountStorage();\n\n        // Check if the plugin exists, also invalidate null address.\n        if (!storage_.plugins.tryAdd(CastLib.toSetValue(plugin))) {\n            revert PluginAlreadyInstalled(plugin);\n        }\n\n        // Check that the plugin supports the IPlugin interface.\n        if (!ERC165Checker.supportsInterface(plugin, type(IPlugin).interfaceId)) {\n            revert PluginInterfaceNotSupported(plugin);\n        }\n\n        // Check manifest hash.\n        PluginManifest memory manifest = IPlugin(plugin).pluginManifest();\n        if (!_isValidPluginManifest(manifest, manifestHash)) {\n            revert InvalidPluginManifest();\n        }\n\n        // Check that the dependencies match the manifest.\n        uint256 length = dependencies.length;\n        if (length != manifest.dependencyInterfaceIds.length) {\n            revert InvalidDependenciesProvided();\n        }\n\n        for (uint256 i = 0; i < length; ++i) {\n            // Check the dependency interface id over the address of the dependency.\n            (address dependencyAddr,) = dependencies[i].unpack();\n\n            // Check that the dependency is installed. This also blocks self-dependencies.\n            if (storage_.pluginData[dependencyAddr].manifestHash == bytes32(0)) {\n                revert MissingPluginDependency(dependencyAddr);\n            }\n\n            // Check that the dependency supports the expected interface.\n            if (!ERC165Checker.supportsInterface(dependencyAddr, manifest.dependencyInterfaceIds[i])) {\n                revert InvalidDependenciesProvided();\n            }\n\n            // Increment the dependency's dependents counter.\n            storage_.pluginData[dependencyAddr].dependentCount += 1;\n        }\n\n        // Update components according to the manifest.\n\n        // Install execution functions\n        length = manifest.executionFunctions.length;\n        for (uint256 i = 0; i < length; ++i) {\n            _setExecutionFunction(manifest.executionFunctions[i], plugin);\n        }\n\n        // Add installed plugin and selectors this plugin can call\n        length = manifest.permittedExecutionSelectors.length;\n        for (uint256 i = 0; i < length; ++i) {\n            storage_.callPermitted[_getPermittedCallKey(plugin, manifest.permittedExecutionSelectors[i])] = true;\n        }\n\n        // Add the permitted external calls to the account.\n        if (manifest.permitAnyExternalAddress) {\n            storage_.pluginData[plugin].anyExternalAddressPermitted = true;\n        } else {\n            // Only store the specific permitted external calls if \"permit any\" flag was not set.\n            length = manifest.permittedExternalCalls.length;\n            for (uint256 i = 0; i < length; ++i) {\n                ManifestExternalCallPermission memory externalCallPermission = manifest.permittedExternalCalls[i];\n\n                PermittedExternalCallData storage permittedExternalCallData =\n                    storage_.permittedExternalCalls[IPlugin(plugin)][externalCallPermission.externalAddress];\n\n                permittedExternalCallData.addressPermitted = true;\n\n                if (externalCallPermission.permitAnySelector) {\n                    permittedExternalCallData.anySelectorPermitted = true;\n                } else {\n                    uint256 externalContractSelectorsLength = externalCallPermission.selectors.length;\n                    for (uint256 j = 0; j < externalContractSelectorsLength; ++j) {\n                        permittedExternalCallData.permittedSelectors[externalCallPermission.selectors[j]] = true;\n                    }\n                }\n            }\n        }\n\n        // Add user operation validation functions\n        length = manifest.userOpValidationFunctions.length;\n        for (uint256 i = 0; i < length; ++i) {\n            ManifestAssociatedFunction memory mv = manifest.userOpValidationFunctions[i];\n            _addUserOpValidationFunction(\n                mv.executionSelector,\n                _resolveManifestFunction(\n                    mv.associatedFunction, plugin, dependencies, ManifestAssociatedFunctionType.NONE\n                )\n            );\n        }\n\n        // Add runtime validation functions\n        length = manifest.runtimeValidationFunctions.length;\n        for (uint256 i = 0; i < length; ++i) {\n            ManifestAssociatedFunction memory mv = manifest.runtimeValidationFunctions[i];\n            _addRuntimeValidationFunction(\n                mv.executionSelector,\n                _resolveManifestFunction(\n                    mv.associatedFunction,\n                    plugin,\n                    dependencies,\n                    ManifestAssociatedFunctionType.RUNTIME_VALIDATION_ALWAYS_ALLOW\n                )\n            );\n        }\n\n        // Passed to _resolveManifestFunction when DEPENDENCY is not a valid function type.\n        FunctionReference[] memory noDependencies = new FunctionReference[](0);\n\n        // Add pre user operation validation hooks\n        length = manifest.preUserOpValidationHooks.length;\n        for (uint256 i = 0; i < length; ++i) {\n            ManifestAssociatedFunction memory mh = manifest.preUserOpValidationHooks[i];\n            _addPreUserOpValidationHook(\n                mh.executionSelector,\n                _resolveManifestFunction(\n                    mh.associatedFunction,\n                    plugin,\n                    noDependencies,\n                    ManifestAssociatedFunctionType.PRE_HOOK_ALWAYS_DENY\n                )\n            );\n        }\n\n        // Add pre runtime validation hooks\n        length = manifest.preRuntimeValidationHooks.length;\n        for (uint256 i = 0; i < length; ++i) {\n            ManifestAssociatedFunction memory mh = manifest.preRuntimeValidationHooks[i];\n            _addPreRuntimeValidationHook(\n                mh.executionSelector,\n                _resolveManifestFunction(\n                    mh.associatedFunction,\n                    plugin,\n                    noDependencies,\n                    ManifestAssociatedFunctionType.PRE_HOOK_ALWAYS_DENY\n                )\n            );\n        }\n\n        // Add pre and post execution hooks\n        length = manifest.executionHooks.length;\n        for (uint256 i = 0; i < length; ++i) {\n            ManifestExecutionHook memory mh = manifest.executionHooks[i];\n            _addExecHooks(\n                mh.executionSelector,\n                _resolveManifestFunction(\n                    mh.preExecHook, plugin, noDependencies, ManifestAssociatedFunctionType.PRE_HOOK_ALWAYS_DENY\n                ),\n                _resolveManifestFunction(\n                    mh.postExecHook, plugin, noDependencies, ManifestAssociatedFunctionType.NONE\n                )\n            );\n        }\n\n        // Add new interface ids the plugin enabled for the account\n        length = manifest.interfaceIds.length;\n        for (uint256 i = 0; i < length; ++i) {\n            bytes4 interfaceId = manifest.interfaceIds[i];\n            if (interfaceId == type(IPlugin).interfaceId || interfaceId == _INVALID_INTERFACE_ID) {\n                revert InterfaceNotAllowed();\n            }\n            storage_.supportedInterfaces[interfaceId] += 1;\n        }\n\n        // Add the plugin metadata to the account\n        storage_.pluginData[plugin].manifestHash = manifestHash;\n        storage_.pluginData[plugin].dependencies = dependencies;\n\n        // Mark whether or not this plugin may spend native token amounts\n        if (manifest.canSpendNativeToken) {\n            storage_.pluginData[plugin].canSpendNativeToken = true;\n        }\n\n        // Initialize the plugin storage for the account.\n        // solhint-disable-next-line no-empty-blocks\n        try IPlugin(plugin).onInstall(pluginInstallData) {}\n        catch (bytes memory revertReason) {\n            revert PluginInstallCallbackFailed(plugin, revertReason);\n        }\n\n        emit PluginInstalled(plugin, manifestHash, dependencies);\n    }\n\n    function _uninstallPlugin(UninstallPluginArgs memory args, bytes calldata pluginUninstallData) internal {\n        AccountStorage storage storage_ = _getAccountStorage();\n\n        // Check if the plugin exists.\n        if (!storage_.plugins.tryRemove(CastLib.toSetValue(args.plugin))) {\n            revert PluginNotInstalled(args.plugin);\n        }\n\n        PluginData memory pluginData = storage_.pluginData[args.plugin];\n\n        // Check manifest hash.\n        if (!_isValidPluginManifest(args.manifest, pluginData.manifestHash)) {\n            revert InvalidPluginManifest();\n        }\n\n        // Ensure that there are no dependent plugins.\n        if (pluginData.dependentCount != 0) {\n            revert PluginDependencyViolation(args.plugin);\n        }\n\n        // Remove this plugin as a dependent from its dependencies.\n        FunctionReference[] memory dependencies = pluginData.dependencies;\n        uint256 length = dependencies.length;\n        for (uint256 i = 0; i < length; ++i) {\n            FunctionReference dependency = dependencies[i];\n            (address dependencyAddr,) = dependency.unpack();\n\n            // Decrement the dependent count for the dependency function.\n            storage_.pluginData[dependencyAddr].dependentCount -= 1;\n        }\n\n        // Remove the plugin metadata from the account.\n        delete storage_.pluginData[args.plugin];\n\n        // Remove components according to the manifest, in reverse order (by component type) of their installation.\n\n        // Passed to _resolveManifestFunction when DEPENDENCY is not a valid function type.\n        FunctionReference[] memory noDependencies = new FunctionReference[](0);\n\n        // Remove pre and post execution function hooks\n        length = args.manifest.executionHooks.length;\n        for (uint256 i = 0; i < length; ++i) {\n            ManifestExecutionHook memory mh = args.manifest.executionHooks[i];\n            _removeExecHooks(\n                mh.executionSelector,\n                _resolveManifestFunction(\n                    mh.preExecHook,\n                    args.plugin,\n                    noDependencies,\n                    ManifestAssociatedFunctionType.PRE_HOOK_ALWAYS_DENY\n                ),\n                _resolveManifestFunction(\n                    mh.postExecHook, args.plugin, noDependencies, ManifestAssociatedFunctionType.NONE\n                )\n            );\n        }\n\n        // Remove pre runtime validation function hooks\n        length = args.manifest.preRuntimeValidationHooks.length;\n        for (uint256 i = 0; i < length; ++i) {\n            ManifestAssociatedFunction memory mh = args.manifest.preRuntimeValidationHooks[i];\n\n            _removePreRuntimeValidationHook(\n                mh.executionSelector,\n                _resolveManifestFunction(\n                    mh.associatedFunction,\n                    args.plugin,\n                    noDependencies,\n                    ManifestAssociatedFunctionType.PRE_HOOK_ALWAYS_DENY\n                )\n            );\n        }\n\n        // Remove pre user op validation function hooks\n        length = args.manifest.preUserOpValidationHooks.length;\n        for (uint256 i = 0; i < length; ++i) {\n            ManifestAssociatedFunction memory mh = args.manifest.preUserOpValidationHooks[i];\n\n            _removePreUserOpValidationHook(\n                mh.executionSelector,\n                _resolveManifestFunction(\n                    mh.associatedFunction,\n                    args.plugin,\n                    noDependencies,\n                    ManifestAssociatedFunctionType.PRE_HOOK_ALWAYS_DENY\n                )\n            );\n        }\n\n        // Remove runtime validation function hooks\n        length = args.manifest.runtimeValidationFunctions.length;\n        for (uint256 i = 0; i < length; ++i) {\n            bytes4 executionSelector = args.manifest.runtimeValidationFunctions[i].executionSelector;\n            storage_.selectorData[executionSelector].runtimeValidation =\n                FunctionReferenceLib._EMPTY_FUNCTION_REFERENCE;\n        }\n\n        // Remove user op validation function hooks\n        length = args.manifest.userOpValidationFunctions.length;\n        for (uint256 i = 0; i < length; ++i) {\n            bytes4 executionSelector = args.manifest.userOpValidationFunctions[i].executionSelector;\n            storage_.selectorData[executionSelector].userOpValidation =\n                FunctionReferenceLib._EMPTY_FUNCTION_REFERENCE;\n        }\n\n        // Remove permitted external call permissions, anyExternalAddressPermitted is cleared when pluginData being\n        // deleted\n        if (!args.manifest.permitAnyExternalAddress) {\n            // Only clear the specific permitted external calls if \"permit any\" flag was not set.\n            length = args.manifest.permittedExternalCalls.length;\n            for (uint256 i = 0; i < length; ++i) {\n                ManifestExternalCallPermission memory externalCallPermission =\n                    args.manifest.permittedExternalCalls[i];\n\n                PermittedExternalCallData storage permittedExternalCallData =\n                    storage_.permittedExternalCalls[IPlugin(args.plugin)][externalCallPermission.externalAddress];\n\n                permittedExternalCallData.addressPermitted = false;\n\n                // Only clear this flag if it was set in the constructor.\n                if (externalCallPermission.permitAnySelector) {\n                    permittedExternalCallData.anySelectorPermitted = false;\n                } else {\n                    uint256 externalContractSelectorsLength = externalCallPermission.selectors.length;\n                    for (uint256 j = 0; j < externalContractSelectorsLength; ++j) {\n                        permittedExternalCallData.permittedSelectors[externalCallPermission.selectors[j]] = false;\n                    }\n                }\n            }\n        }\n\n        // Remove permitted account execution function call permissions\n        length = args.manifest.permittedExecutionSelectors.length;\n        for (uint256 i = 0; i < length; ++i) {\n            storage_.callPermitted[_getPermittedCallKey(args.plugin, args.manifest.permittedExecutionSelectors[i])]\n            = false;\n        }\n\n        // Remove installed execution function\n        length = args.manifest.executionFunctions.length;\n        for (uint256 i = 0; i < length; ++i) {\n            storage_.selectorData[args.manifest.executionFunctions[i]].plugin = address(0);\n        }\n\n        // Decrease supported interface ids' counters\n        length = args.manifest.interfaceIds.length;\n        for (uint256 i = 0; i < length; ++i) {\n            storage_.supportedInterfaces[args.manifest.interfaceIds[i]] -= 1;\n        }\n\n        // Clear the plugin storage for the account.\n        bool onUninstallSucceeded = true;\n        // solhint-disable-next-line no-empty-blocks\n        try IPlugin(args.plugin).onUninstall{gas: args.callbackGasLimit}(pluginUninstallData) {}\n        catch (bytes memory revertReason) {\n            if (!args.forceUninstall) {\n                revert PluginUninstallCallbackFailed(args.plugin, revertReason);\n            }\n            onUninstallSucceeded = false;\n        }\n\n        emit PluginUninstalled(args.plugin, onUninstallSucceeded);\n    }\n\n    function _isValidPluginManifest(PluginManifest memory manifest, bytes32 manifestHash)\n        internal\n        pure\n        returns (bool)\n    {\n        return manifestHash == keccak256(abi.encode(manifest));\n    }\n\n    function _resolveManifestFunction(\n        ManifestFunction memory manifestFunction,\n        address plugin,\n        // Can be empty to indicate that type DEPENDENCY is invalid for this function.\n        FunctionReference[] memory dependencies,\n        // Indicates which magic value, if any, is permissible for the function to resolve.\n        ManifestAssociatedFunctionType allowedMagicValue\n    ) internal pure returns (FunctionReference) {\n        if (manifestFunction.functionType == ManifestAssociatedFunctionType.SELF) {\n            return FunctionReferenceLib.pack(plugin, manifestFunction.functionId);\n        }\n        if (manifestFunction.functionType == ManifestAssociatedFunctionType.DEPENDENCY) {\n            uint256 index = manifestFunction.dependencyIndex;\n            if (index < dependencies.length) {\n                return dependencies[index];\n            }\n            revert InvalidPluginManifest();\n        }\n        if (manifestFunction.functionType == ManifestAssociatedFunctionType.RUNTIME_VALIDATION_ALWAYS_ALLOW) {\n            if (allowedMagicValue == ManifestAssociatedFunctionType.RUNTIME_VALIDATION_ALWAYS_ALLOW) {\n                return FunctionReferenceLib._RUNTIME_VALIDATION_ALWAYS_ALLOW;\n            }\n            revert InvalidPluginManifest();\n        }\n        if (manifestFunction.functionType == ManifestAssociatedFunctionType.PRE_HOOK_ALWAYS_DENY) {\n            if (allowedMagicValue == ManifestAssociatedFunctionType.PRE_HOOK_ALWAYS_DENY) {\n                return FunctionReferenceLib._PRE_HOOK_ALWAYS_DENY;\n            }\n            revert InvalidPluginManifest();\n        }\n        return FunctionReferenceLib._EMPTY_FUNCTION_REFERENCE; // Empty checks are done elsewhere\n    }\n\n    function _assertNotNullFunction(FunctionReference functionReference) internal pure {\n        if (functionReference.isEmpty()) {\n            revert NullFunctionReference();\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1, \"Math: mulDiv overflow\");\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // must be unchecked in order to support `n = type(int256).min`\n            return uint256(n >= 0 ? n : -n);\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n    /**\n     * @dev Handles the receipt of a single ERC1155 token type. This function is\n     * called at the end of a `safeTransferFrom` after the balance has been updated.\n     *\n     * NOTE: To accept the transfer, this must return\n     * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n     * (i.e. 0xf23a6e61, or its own function selector).\n     *\n     * @param operator The address which initiated the transfer (i.e. msg.sender)\n     * @param from The address which previously owned the token\n     * @param id The ID of the token being transferred\n     * @param value The amount of tokens being transferred\n     * @param data Additional data with no specified format\n     * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n     */\n    function onERC1155Received(\n        address operator,\n        address from,\n        uint256 id,\n        uint256 value,\n        bytes calldata data\n    ) external returns (bytes4);\n\n    /**\n     * @dev Handles the receipt of a multiple ERC1155 token types. This function\n     * is called at the end of a `safeBatchTransferFrom` after the balances have\n     * been updated.\n     *\n     * NOTE: To accept the transfer(s), this must return\n     * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n     * (i.e. 0xbc197c81, or its own function selector).\n     *\n     * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n     * @param from The address which previously owned the token\n     * @param ids An array containing ids of each token being transferred (order and length must match values array)\n     * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n     * @param data Additional data with no specified format\n     * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n     */\n    function onERC1155BatchReceived(\n        address operator,\n        address from,\n        uint256[] calldata ids,\n        uint256[] calldata values,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC777/IERC777Recipient.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC777/IERC777Recipient.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC777TokensRecipient standard as defined in the EIP.\n *\n * Accounts can be notified of {IERC777} tokens being sent to them by having a\n * contract implement this interface (contract holders can be their own\n * implementer) and registering it on the\n * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].\n *\n * See {IERC1820Registry} and {ERC1820Implementer}.\n */\ninterface IERC777Recipient {\n    /**\n     * @dev Called by an {IERC777} token contract whenever tokens are being\n     * moved or created into a registered account (`to`). The type of operation\n     * is conveyed by `from` being the zero address or not.\n     *\n     * This call occurs _after_ the token contract's state is updated, so\n     * {IERC777-balanceOf}, etc., can be used to query the post-operation state.\n     *\n     * This function may revert to prevent the operation from being executed.\n     */\n    function tokensReceived(\n        address operator,\n        address from,\n        address to,\n        uint256 amount,\n        bytes calldata userData,\n        bytes calldata operatorData\n    ) external;\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/introspection/ERC165Checker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Library used to query support of an interface declared via {IERC165}.\n *\n * Note that these functions return the actual result of the query: they do not\n * `revert` if an interface is not supported. It is up to the caller to decide\n * what to do in these cases.\n */\nlibrary ERC165Checker {\n    // As per the EIP-165 spec, no interface should ever match 0xffffffff\n    bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\n\n    /**\n     * @dev Returns true if `account` supports the {IERC165} interface.\n     */\n    function supportsERC165(address account) internal view returns (bool) {\n        // Any contract that implements ERC165 must explicitly indicate support of\n        // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\n        return\n            supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\n            !supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);\n    }\n\n    /**\n     * @dev Returns true if `account` supports the interface defined by\n     * `interfaceId`. Support for {IERC165} itself is queried automatically.\n     *\n     * See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\n        // query support of both ERC165 as per the spec and support of _interfaceId\n        return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\n    }\n\n    /**\n     * @dev Returns a boolean array where each value corresponds to the\n     * interfaces passed in and whether they're supported or not. This allows\n     * you to batch check interfaces for a contract where your expectation\n     * is that some interfaces may not be supported.\n     *\n     * See {IERC165-supportsInterface}.\n     *\n     * _Available since v3.4._\n     */\n    function getSupportedInterfaces(\n        address account,\n        bytes4[] memory interfaceIds\n    ) internal view returns (bool[] memory) {\n        // an array of booleans corresponding to interfaceIds and whether they're supported or not\n        bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\n\n        // query support of ERC165 itself\n        if (supportsERC165(account)) {\n            // query support of each interface in interfaceIds\n            for (uint256 i = 0; i < interfaceIds.length; i++) {\n                interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\n            }\n        }\n\n        return interfaceIdsSupported;\n    }\n\n    /**\n     * @dev Returns true if `account` supports all the interfaces defined in\n     * `interfaceIds`. Support for {IERC165} itself is queried automatically.\n     *\n     * Batch-querying can lead to gas savings by skipping repeated checks for\n     * {IERC165} support.\n     *\n     * See {IERC165-supportsInterface}.\n     */\n    function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\n        // query support of ERC165 itself\n        if (!supportsERC165(account)) {\n            return false;\n        }\n\n        // query support of each interface in interfaceIds\n        for (uint256 i = 0; i < interfaceIds.length; i++) {\n            if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\n                return false;\n            }\n        }\n\n        // all interfaces supported\n        return true;\n    }\n\n    /**\n     * @notice Query if a contract implements an interface, does not check ERC165 support\n     * @param account The address of the contract to query for support of an interface\n     * @param interfaceId The interface identifier, as specified in ERC-165\n     * @return true if the contract at account indicates support of the interface with\n     * identifier interfaceId, false otherwise\n     * @dev Assumes that account contains a contract that supports ERC165, otherwise\n     * the behavior of this method is undefined. This precondition can be checked\n     * with {supportsERC165}.\n     *\n     * Some precompiled contracts will falsely indicate support for a given interface, so caution\n     * should be exercised when using this function.\n     *\n     * Interface identification is specified in ERC-165.\n     */\n    function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\n        // prepare call\n        bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n\n        // perform static call\n        bool success;\n        uint256 returnSize;\n        uint256 returnValue;\n        assembly {\n            success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\n            returnSize := returndatasize()\n            returnValue := mload(0x00)\n        }\n\n        return success && returnSize >= 0x20 && returnValue > 0;\n    }\n}\n"
      },
      "lib/modular-account/src/account/AccountStorageV1.sol": {
        "content": "// This file is part of Modular Account.\n//\n// Copyright 2024 Alchemy Insights, Inc.\n//\n// SPDX-License-Identifier: GPL-3.0-or-later\n//\n// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General\n// Public License as published by the Free Software Foundation, either version 3 of the License, or (at your\n// option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the\n// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n// more details.\n//\n// You should have received a copy of the GNU General Public License along with this program. If not, see\n// <https://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.22;\n\nimport {IPlugin} from \"../interfaces/IPlugin.sol\";\nimport {FunctionReference} from \"../interfaces/IPluginManager.sol\";\nimport {LinkedListSet} from \"../libraries/LinkedListSetLib.sol\";\n\n/// @title Account Storage V1\n/// @author Alchemy\n/// @notice Contains the storage layout for upgradeable modular accounts.\n/// @dev `||` for variables in comments refers to the concat operator\ncontract AccountStorageV1 {\n    /// @custom:storage-location erc7201:Alchemy.UpgradeableModularAccount.Storage_V1\n    struct AccountStorage {\n        // AccountStorageInitializable variables\n        uint8 initialized;\n        bool initializing;\n        // Plugin metadata storage\n        LinkedListSet plugins;\n        mapping(address => PluginData) pluginData;\n        // Execution functions and their associated functions\n        mapping(bytes4 => SelectorData) selectorData;\n        // bytes24 key = address(calling plugin) || bytes4(selector of execution function)\n        mapping(bytes24 => bool) callPermitted;\n        // keys = address(calling plugin), target address\n        mapping(IPlugin => mapping(address => PermittedExternalCallData)) permittedExternalCalls;\n        // For ERC165 introspection, each count indicates support from account or an installed plugin.\n        // 0 indicates the account does not support the interface and all plugins that support this interface have\n        // been uninstalled.\n        mapping(bytes4 => uint256) supportedInterfaces;\n    }\n\n    struct PluginData {\n        bool anyExternalAddressPermitted;\n        // A boolean to indicate if the plugin can spend native tokens, if any of the execution function can spend\n        // native tokens, a plugin is considered to be able to spend native tokens of the accounts\n        bool canSpendNativeToken;\n        bytes32 manifestHash;\n        FunctionReference[] dependencies;\n        // Tracks the number of times this plugin has been used as a dependency function\n        uint256 dependentCount;\n    }\n\n    /// @dev Represents data associated with a plugin's permission to use `executeFromPluginExternal` to interact\n    /// with contracts and addresses external to the account and its plugins.\n    struct PermittedExternalCallData {\n        // Is this address on the permitted addresses list? If it is, we either have a\n        // list of allowed selectors, or the flag that allows any selector.\n        bool addressPermitted;\n        bool anySelectorPermitted;\n        mapping(bytes4 => bool) permittedSelectors;\n    }\n\n    struct HookGroup {\n        // NOTE: this uses the flag _PRE_EXEC_HOOK_HAS_POST_FLAG to indicate whether\n        // an element has an associated post-exec hook.\n        LinkedListSet preHooks;\n        // bytes21 key = pre exec hook function reference\n        mapping(FunctionReference => LinkedListSet) associatedPostHooks;\n        LinkedListSet postOnlyHooks;\n    }\n\n    /// @dev Represents data associated with a specifc function selector.\n    struct SelectorData {\n        // The plugin that implements this execution function.\n        // If this is a native function, the address must remain address(0).\n        address plugin;\n        // Cached flags indicating whether or not this function has pre-execution hooks and\n        // post-only hooks. Flags for pre-validation hooks stored in the same storage word\n        // as the validation function itself, to use a warm storage slot when loading.\n        bool hasPreExecHooks;\n        bool hasPostOnlyExecHooks;\n        // The specified validation functions for this function selector.\n        FunctionReference userOpValidation;\n        bool hasPreUserOpValidationHooks;\n        FunctionReference runtimeValidation;\n        bool hasPreRuntimeValidationHooks;\n        // The pre validation hooks for this function selector.\n        LinkedListSet preUserOpValidationHooks;\n        LinkedListSet preRuntimeValidationHooks;\n        // The execution hooks for this function selector.\n        HookGroup executionHooks;\n    }\n\n    /// @dev the same storage slot will be used versions V1.x.y of upgradeable modular accounts. Follows ERC-7201.\n    /// bytes = keccak256(\n    ///     abi.encode(uint256(keccak256(\"Alchemy.UpgradeableModularAccount.Storage_V1\")) - 1)\n    /// ) & ~bytes32(uint256(0xff));\n    /// This cannot be evaluated at compile time because of its use in inline assembly.\n    bytes32 internal constant _V1_STORAGE_SLOT = 0xade46bbfcf6f898a43d541e42556d456ca0bf9b326df8debc0f29d3f811a0300;\n\n    function _getAccountStorage() internal pure returns (AccountStorage storage storage_) {\n        assembly (\"memory-safe\") {\n            storage_.slot := _V1_STORAGE_SLOT\n        }\n    }\n\n    function _getPermittedCallKey(address addr, bytes4 selector) internal pure returns (bytes24) {\n        return bytes24(bytes20(addr)) | (bytes24(selector) >> 160);\n    }\n}\n"
      },
      "lib/modular-account/src/helpers/KnownSelectors.sol": {
        "content": "// This file is part of Modular Account.\n//\n// Copyright 2024 Alchemy Insights, Inc.\n//\n// SPDX-License-Identifier: GPL-3.0-or-later\n//\n// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General\n// Public License as published by the Free Software Foundation, either version 3 of the License, or (at your\n// option) any later version.\n//\n// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the\n// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n// more details.\n//\n// You should have received a copy of the GNU General Public License along with this program. If not, see\n// <https://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.22;\n\nimport {UUPSUpgradeable} from \"../../ext/UUPSUpgradeable.sol\";\nimport {IERC1155Receiver} from \"@openzeppelin/contracts/interfaces/IERC1155Receiver.sol\";\nimport {IERC777Recipient} from \"@openzeppelin/contracts/interfaces/IERC777Recipient.sol\";\nimport {IERC721Receiver} from \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\nimport {IAccount} from \"../../src/interfaces/erc4337/IAccount.sol\";\nimport {IAggregator} from \"../../src/interfaces/erc4337/IAggregator.sol\";\nimport {IPaymaster} from \"../../src/interfaces/erc4337/IPaymaster.sol\";\nimport {IAccountLoupe} from \"../../src/interfaces/IAccountLoupe.sol\";\nimport {IAccountView} from \"../../src/interfaces/IAccountView.sol\";\nimport {IPluginManager} from \"../../src/interfaces/IPluginManager.sol\";\nimport {IAccountInitializable} from \"../interfaces/IAccountInitializable.sol\";\nimport {IPlugin} from \"../interfaces/IPlugin.sol\";\nimport {IPluginExecutor} from \"../interfaces/IPluginExecutor.sol\";\nimport {IStandardExecutor} from \"../interfaces/IStandardExecutor.sol\";\n\n/// @title Known Selectors\n/// @author Alchemy\n/// @notice Library to help to check if a selector is a know function selector of the modular account or ERC-4337\n/// contract.\nlibrary KnownSelectors {\n    function isNativeFunction(bytes4 selector) internal pure returns (bool) {\n        return\n        // check against IAccount methods\n        selector == IAccount.validateUserOp.selector\n        // check against IAccountView methods\n        || selector == IAccountView.entryPoint.selector || selector == IAccountView.getNonce.selector\n        // check against IPluginManager methods\n        || selector == IPluginManager.installPlugin.selector || selector == IPluginManager.uninstallPlugin.selector\n        // check against IERC165 methods\n        || selector == IERC165.supportsInterface.selector\n        // check against UUPSUpgradeable methods\n        || selector == UUPSUpgradeable.proxiableUUID.selector\n            || selector == UUPSUpgradeable.upgradeToAndCall.selector\n        // check against IStandardExecutor methods\n        || selector == IStandardExecutor.execute.selector || selector == IStandardExecutor.executeBatch.selector\n        // check against IPluginExecutor methods\n        || selector == IPluginExecutor.executeFromPlugin.selector\n            || selector == IPluginExecutor.executeFromPluginExternal.selector\n        // check against IAccountInitializable methods\n        || selector == IAccountInitializable.initialize.selector\n        // check against IAccountLoupe methods\n        || selector == IAccountLoupe.getExecutionFunctionConfig.selector\n            || selector == IAccountLoupe.getExecutionHooks.selector\n            || selector == IAccountLoupe.getPreValidationHooks.selector\n            || selector == IAccountLoupe.getInstalledPlugins.selector\n        // check against token receiver methods\n        || selector == IERC777Recipient.tokensReceived.selector\n            || selector == IERC721Receiver.onERC721Received.selector\n            || selector == IERC1155Receiver.onERC1155Received.selector\n            || selector == IERC1155Receiver.onERC1155BatchReceived.selector;\n    }\n\n    function isErc4337Function(bytes4 selector) internal pure returns (bool) {\n        return selector == IAggregator.validateSignatures.selector\n            || selector == IAggregator.validateUserOpSignature.selector\n            || selector == IAggregator.aggregateSignatures.selector\n            || selector == IPaymaster.validatePaymasterUserOp.selector || selector == IPaymaster.postOp.selector;\n    }\n\n    function isIPluginFunction(bytes4 selector) internal pure returns (bool) {\n        return selector == IPlugin.onInstall.selector || selector == IPlugin.onUninstall.selector\n            || selector == IPlugin.preUserOpValidationHook.selector\n            || selector == IPlugin.userOpValidationFunction.selector\n            || selector == IPlugin.preRuntimeValidationHook.selector\n            || selector == IPlugin.runtimeValidationFunction.selector || selector == IPlugin.preExecutionHook.selector\n            || selector == IPlugin.postExecutionHook.selector || selector == IPlugin.pluginManifest.selector\n            || selector == IPlugin.pluginMetadata.selector;\n    }\n}\n"
      },
      "lib/modular-account/src/interfaces/IAccountLoupe.sol": {
        "content": "// This work is marked with CC0 1.0 Universal.\n//\n// SPDX-License-Identifier: CC0-1.0\n//\n// To view a copy of this license, visit http://creativecommons.org/publicdomain/zero/1.0\n\npragma solidity ^0.8.22;\n\nimport {FunctionReference} from \"./IPluginManager.sol\";\n\n/// @title Account Loupe Interface\ninterface IAccountLoupe {\n    /// @notice Config for an execution function, given a selector.\n    struct ExecutionFunctionConfig {\n        address plugin;\n        FunctionReference userOpValidationFunction;\n        FunctionReference runtimeValidationFunction;\n    }\n\n    /// @notice Pre and post hooks for a given selector.\n    /// @dev It's possible for one of either `preExecHook` or `postExecHook` to be empty.\n    struct ExecutionHooks {\n        FunctionReference preExecHook;\n        FunctionReference postExecHook;\n    }\n\n    /// @notice Get the validation functions and plugin address for a selector.\n    /// @dev If the selector is a native function, the plugin address will be the address of the account.\n    /// @param selector The selector to get the configuration for.\n    /// @return The configuration for this selector.\n    function getExecutionFunctionConfig(bytes4 selector) external view returns (ExecutionFunctionConfig memory);\n\n    /// @notice Get the pre and post execution hooks for a selector.\n    /// @param selector The selector to get the hooks for.\n    /// @return The pre and post execution hooks for this selector.\n    function getExecutionHooks(bytes4 selector) external view returns (ExecutionHooks[] memory);\n\n    /// @notice Get the pre user op and runtime validation hooks associated with a selector.\n    /// @param selector The selector to get the hooks for.\n    /// @return preUserOpValidationHooks The pre user op validation hooks for this selector.\n    /// @return preRuntimeValidationHooks The pre runtime validation hooks for this selector.\n    function getPreValidationHooks(bytes4 selector)\n        external\n        view\n        returns (\n            FunctionReference[] memory preUserOpValidationHooks,\n            FunctionReference[] memory preRuntimeValidationHooks\n        );\n\n    /// @notice Get an array of all installed plugins.\n    /// @return The addresses of all installed plugins.\n    function getInstalledPlugins() external view returns (address[] memory);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      },
      "lib/modular-account/src/interfaces/erc4337/IAggregator.sol": {
        "content": "// This work is marked with CC0 1.0 Universal.\n//\n// SPDX-License-Identifier: CC0-1.0\n//\n// To view a copy of this license, visit http://creativecommons.org/publicdomain/zero/1.0\n\npragma solidity ^0.8.22;\n\nimport {UserOperation} from \"./UserOperation.sol\";\n\n/// @notice Interface for the ERC-4337 aggregator\ninterface IAggregator {\n    function validateSignatures(UserOperation[] calldata, bytes calldata) external view;\n    function validateUserOpSignature(UserOperation calldata) external view returns (bytes memory);\n    function aggregateSignatures(UserOperation[] calldata) external view returns (bytes memory);\n}\n"
      },
      "lib/modular-account/src/interfaces/erc4337/IPaymaster.sol": {
        "content": "// This work is marked with CC0 1.0 Universal.\n//\n// SPDX-License-Identifier: CC0-1.0\n//\n// To view a copy of this license, visit http://creativecommons.org/publicdomain/zero/1.0\n\npragma solidity ^0.8.22;\n\nimport {UserOperation} from \"./UserOperation.sol\";\n\n/// @notice Interface for the ERC-4337 paymaster\ninterface IPaymaster {\n    enum PostOpMode {\n        opSucceeded,\n        opReverted,\n        postOpReverted\n    }\n\n    function validatePaymasterUserOp(UserOperation calldata, bytes32, uint256)\n        external\n        returns (bytes memory, uint256);\n\n    function postOp(PostOpMode, bytes calldata, uint256) external;\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "forge-std/=lib/forge-std/src/",
        "@eth-infinitism/account-abstraction/=lib/account-abstraction/contracts/",
        "@openzeppelin/=lib/openzeppelin-contracts/",
        "@alchemy/modular-account/=lib/modular-account/",
        "@alchemy/light-account/=lib/modular-account/lib/light-account/",
        "account-abstraction/=lib/account-abstraction/contracts/",
        "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
        "light-account/=lib/modular-account/lib/light-account/",
        "modular-account/=lib/modular-account/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "openzeppelin/=lib/openzeppelin-contracts/contracts/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 1000000
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "viaIR": true,
      "libraries": {}
    }
  }}