diff --git a/.env.example b/.env.example index 6e832bf..2e2ba52 100644 --- a/.env.example +++ b/.env.example @@ -68,4 +68,3 @@ TDOC_IMPLEMENTATION_AMOY=0x_tdoc_implementation_on_amoy # Filled in after running gasless scripts with NETWORK=amoy REGISTRY_ADDRESS_AMOY=0x_filled_after_deployRegistry TITLE_ESCROW_ADDRESS_AMOY=0x_filled_after_mintDocument -FACTORY_ADDRESS_AMOY=0x_filled_after_deployFactory diff --git a/README.md b/README.md index 9d4cc8e..dd27208 100644 --- a/README.md +++ b/README.md @@ -138,16 +138,54 @@ npx hardhat run scripts/mintDocumentGasless.ts --network sepolia ## Environment variables +Deploy/registry/paymaster addresses are network-scoped — suffix the variable with `_SEPOLIA` or `_AMOY` (e.g. `FACTORY_ADDRESS_SEPOLIA`, `FACTORY_ADDRESS_AMOY`). `scripts/lib/network.ts` resolves the suffix from `--network ` (hardhat scripts) or the `NETWORK` env var (viem/permissionless scripts). See `.env.example` for the full annotated list. + +### Wallets & RPC + | Variable | Description | | --- | --- | -| `PRIVATE_KEY` | Deployer wallet private key | +| `PRIVATE_KEY` | Deployer/gas-payer wallet — pays for deployments, delegation txs, staking | +| `PRIVATE_KEY2` | Secondary wallet (optional — testing with a second account) | +| `OWNER_PRIVATE_KEY` | Platform owner / whitelisted user — signs UserOps, needs no ETH for gasless ops | | `SEPOLIA_RPC_URL` | Sepolia RPC endpoint | +| `AMOY_RPC_URL` | Polygon Amoy RPC endpoint | | `PIMLICO_API_KEY` | Pimlico bundler API key | -| `TDOC_DEPLOYER_ADDRESS` | Deployed TDocDeployer address | -| `PAYMASTER_IMPLEMENTATION` | PlatformPaymaster implementation address | -| `FACTORY_ADDRESS` | PlatformAccountFactory address | -| `PAYMASTER_ADDRESS` | Deployed paymaster clone address | -| `EIP7702_IMPL_ADDRESS` | EIP7702Implementation address | +| `NETWORK` | `sepolia` \| `amoy` — target network for viem/permissionless scripts (default: `sepolia`) | +| `ENTRY_POINT` | EntryPoint v0.8 address (default: `0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108`, same on all supported chains) | + +### Deployed addresses (network-suffixed) + +| Variable | Description | +| --- | --- | +| `EIP7702_IMPL_ADDRESS_` | Deployed `EIP7702Implementation` address | +| `PAYMASTER_IMPLEMENTATION_` | Deployed `PlatformPaymaster` implementation address | +| `FACTORY_ADDRESS_` | Deployed `PlatformAccountFactory` address | +| `PAYMASTER_ADDRESS_` | Deployed paymaster clone address | +| `TDOC_DEPLOYER_ADDRESS_` | TrustVC `TDocDeployer` address (pre-deployed infra) | +| `TDOC_IMPLEMENTATION_` | TDoc implementation to clone via `deployRegistry` | +| `REGISTRY_ADDRESS_` | Registry deployed via `deployRegistryGasless.ts` | +| `TITLE_ESCROW_ADDRESS_` | Title escrow captured via `mintDocumentGasless.ts` | + +### Gasless script inputs + +| Variable | Description | +| --- | --- | +| `TOKEN_NAME` / `TOKEN_SYMBOL` | Name/symbol for the TradeTrust token registry (`deployRegistryGasless.ts`) | +| `TOKEN_ID` | Document token ID as `uint256` (`mintDocumentGasless.ts`) | +| `BENEFICIARY_ADDRESS` / `HOLDER_ADDRESS` | Document beneficiary/holder (`mintDocumentGasless.ts`) | +| `REMARK` | Optional remark bytes/text attached to the document | +| `NOMINEE_ADDR` / `NEW_HOLDER_ADDR` | Used by the `scripts/trFunctions/*` title-escrow helpers | + +### Optional deploy/stake overrides + +| Variable | Description | +| --- | --- | +| `PLATFORM_ADDRESS` | Paymaster owner EOA for `deployPlatformPaymaster.ts` (default: deployer) | +| `DAILY_LIMIT_ETH` | Per-user daily gas limit in ETH (default: `0` = unlimited) | +| `DEPLOY_SALT` | Hex `bytes32` CREATE2 salt (default: random) | +| `STAKE_AMOUNT_ETH` | ETH locked as EntryPoint stake (default: `0.01`) | +| `DEPOSIT_AMOUNT_ETH` | ETH deposited into the gas pool (default: `0.05`) | +| `UNSTAKE_DELAY_SEC` | Stake lock period in seconds (default: `86400` = 1 day) | ## Tech stack diff --git a/contracts/Factory.sol b/contracts/Factory.sol index 4a4fdb5..e89e617 100644 --- a/contracts/Factory.sol +++ b/contracts/Factory.sol @@ -8,8 +8,12 @@ import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol"; contract PlatformAccountFactory is Ownable { address public tdocDeployer; address public paymasterImplementation; + mapping(address => address) public attachedPaymaster; - event PlatformOnboarded(address indexed platformAddress, address indexed paymaster); + event PlatformOnboarded( + address indexed platformAddress, + address indexed paymaster + ); event TdocDeployerUpdated(address indexed newDeployer); event ImplementationUpdated(address indexed newImplementation); @@ -17,10 +21,19 @@ contract PlatformAccountFactory is Ownable { address _tdocDeployer, address _paymasterImplementation ) Ownable(msg.sender) { + require(_tdocDeployer != address(0), "Zero address"); + require(_paymasterImplementation != address(0), "Zero address"); tdocDeployer = _tdocDeployer; paymasterImplementation = _paymasterImplementation; } + function setAttachedPaymaster( + address platformAddress + ) external view returns (address) { + address paymaster = attachedPaymaster[platformAddress]; + return paymaster; + } + function updateTdocDeployer(address _tdocDeployer) external onlyOwner { require(_tdocDeployer != address(0), "Zero address"); tdocDeployer = _tdocDeployer; @@ -39,12 +52,23 @@ contract PlatformAccountFactory is Ownable { bytes32 salt ) external returns (address paymaster) { paymaster = Clones.cloneDeterministic(paymasterImplementation, salt); - PlatformPaymaster(payable(paymaster)).initialize(platformAddress, dailyLimit, tdocDeployer); + PlatformPaymaster(payable(paymaster)).initialize( + platformAddress, + dailyLimit, + tdocDeployer + ); emit PlatformOnboarded(platformAddress, paymaster); } // Address is determined solely by implementation + salt (not by constructor args). - function computePaymasterAddress(bytes32 salt) external view returns (address) { - return Clones.predictDeterministicAddress(paymasterImplementation, salt, address(this)); + function computePaymasterAddress( + bytes32 salt + ) external view returns (address) { + return + Clones.predictDeterministicAddress( + paymasterImplementation, + salt, + address(this) + ); } } diff --git a/contracts/PlatformPaymaster.sol b/contracts/PlatformPaymaster.sol index 2be365b..7b10829 100644 --- a/contracts/PlatformPaymaster.sol +++ b/contracts/PlatformPaymaster.sol @@ -49,6 +49,9 @@ contract PlatformPaymaster is BasePaymaster { ); bytes32 private constant DEFAULT_ADMIN_ROLE = bytes32(0); + bytes32 private constant RESTORER_ROLE = keccak256("RESTORER_ROLE"); + bytes32 private constant ACCEPTER_ROLE = keccak256("ACCEPTER_ROLE"); + bytes32 private constant MINTER_ROLE = keccak256("MINTER_ROLE"); ITDocDeployer public tdocDeployer; @@ -141,13 +144,11 @@ contract PlatformPaymaster is BasePaymaster { bytes memory params = abi.encode(name, symbol, address(this)); deployed = tdocDeployer.deploy(implementation, params); - // Hand admin to the calling EOA IAccessControl(deployed).grantRole(DEFAULT_ADMIN_ROLE, msg.sender); + IAccessControl(deployed).grantRole(RESTORER_ROLE, msg.sender); + IAccessControl(deployed).grantRole(ACCEPTER_ROLE, msg.sender); + IAccessControl(deployed).grantRole(MINTER_ROLE, msg.sender); - // Paymaster keeps only the operational roles it needs - // (MINTER_ROLE, RESTORER_ROLE, ACCEPTER_ROLE were granted to address(this) via initialize) - - // Relinquish admin — EOA is now sole admin IAccessControl(deployed).renounceRole( DEFAULT_ADMIN_ROLE, address(this) diff --git a/contracts/mocks/MockRegistry.sol b/contracts/mocks/MockRegistry.sol index e79ab56..5542a59 100644 --- a/contracts/mocks/MockRegistry.sol +++ b/contracts/mocks/MockRegistry.sol @@ -7,19 +7,38 @@ contract MockTitleEscrow {} contract MockRegistry { bytes32 public constant DEFAULT_ADMIN_ROLE = bytes32(0); + bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); + bytes32 public constant RESTORER_ROLE = keccak256("RESTORER_ROLE"); + bytes32 public constant ACCEPTER_ROLE = keccak256("ACCEPTER_ROLE"); + mapping(bytes32 => mapping(address => bool)) private _roles; address public lastTitleEscrow; + error AccessControlUnauthorizedAccount(address account, bytes32 role); + error AccessControlBadConfirmation(); + + // Mirrors RegistryAccess.__RegistryAccess_init: the real registry grants + // all four roles to the single admin address passed at deploy time. constructor(address initialAdmin) { _roles[DEFAULT_ADMIN_ROLE][initialAdmin] = true; + _roles[MINTER_ROLE][initialAdmin] = true; + _roles[RESTORER_ROLE][initialAdmin] = true; + _roles[ACCEPTER_ROLE][initialAdmin] = true; } - // IAccessControl + // IAccessControl — mirrors OZ's default: granting any role requires + // DEFAULT_ADMIN_ROLE, since the real registry never overrides role admins. function grantRole(bytes32 role, address account) external { + if (!_roles[DEFAULT_ADMIN_ROLE][msg.sender]) { + revert AccessControlUnauthorizedAccount(msg.sender, DEFAULT_ADMIN_ROLE); + } _roles[role][account] = true; } - function renounceRole(bytes32 role, address) external { + function renounceRole(bytes32 role, address callerConfirmation) external { + if (callerConfirmation != msg.sender) { + revert AccessControlBadConfirmation(); + } _roles[role][msg.sender] = false; } diff --git a/test/PlatformPaymaster.ts b/test/PlatformPaymaster.ts index 6457abb..5a4ae19 100644 --- a/test/PlatformPaymaster.ts +++ b/test/PlatformPaymaster.ts @@ -278,6 +278,36 @@ describe("PlatformPaymaster", function () { paymasterAsOther.write.deployRegistry([impl.address, "TT", "TT"]), ).to.be.rejectedWith("No deployment credits"); }); + + it("hands admin + all operational roles to msg.sender; paymaster keeps minter/restorer/accepter but not admin", async function () { + const { paymaster, paymasterAsOther, other, impl, publicClient } = + await loadFixture(deployFixture); + await paymaster.write.setUserWhitelist([other.account.address, 1n]); + + const hash = await paymasterAsOther.write.deployRegistry([impl.address, "TT", "TT"]); + await publicClient.waitForTransactionReceipt({ hash }); + + const events = await paymaster.getEvents.RegistryDeployed(); + const deployedAddr = events[0].args.deployed as `0x${string}`; + const registry = await hre.viem.getContractAt("MockRegistry", deployedAddr); + + const DEFAULT_ADMIN_ROLE = await registry.read.DEFAULT_ADMIN_ROLE(); + const MINTER_ROLE = await registry.read.MINTER_ROLE(); + const RESTORER_ROLE = await registry.read.RESTORER_ROLE(); + const ACCEPTER_ROLE = await registry.read.ACCEPTER_ROLE(); + + // msg.sender (the deploying EOA) ends up holding all four roles + expect(await registry.read.hasRole([DEFAULT_ADMIN_ROLE, other.account.address])).to.be.true; + expect(await registry.read.hasRole([RESTORER_ROLE, other.account.address])).to.be.true; + expect(await registry.read.hasRole([ACCEPTER_ROLE, other.account.address])).to.be.true; + expect(await registry.read.hasRole([MINTER_ROLE, other.account.address])).to.be.true; + + // paymaster relinquishes admin but keeps the operational roles + expect(await registry.read.hasRole([DEFAULT_ADMIN_ROLE, paymaster.address])).to.be.false; + expect(await registry.read.hasRole([RESTORER_ROLE, paymaster.address])).to.be.true; + expect(await registry.read.hasRole([ACCEPTER_ROLE, paymaster.address])).to.be.true; + expect(await registry.read.hasRole([MINTER_ROLE, paymaster.address])).to.be.true; + }); }); // ─── mintDocument ───────────────────────────────────────────────────────── diff --git a/upload.json b/upload.json index ec17cf0..9e4908d 100644 --- a/upload.json +++ b/upload.json @@ -4,12 +4,33 @@ "@account-abstraction/contracts/core/BasePaymaster.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/* solhint-disable reason-string */\n\nimport \"@openzeppelin/contracts/access/Ownable2Step.sol\";\nimport \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport \"../interfaces/IPaymaster.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\nimport \"./UserOperationLib.sol\";\n/**\n * Helper class for creating a paymaster.\n * provides helper methods for staking.\n * Validates that the postOp is called only by the entryPoint.\n */\nabstract contract BasePaymaster is IPaymaster, Ownable2Step {\n IEntryPoint public immutable entryPoint;\n\n uint256 internal constant PAYMASTER_VALIDATION_GAS_OFFSET = UserOperationLib.PAYMASTER_VALIDATION_GAS_OFFSET;\n uint256 internal constant PAYMASTER_POSTOP_GAS_OFFSET = UserOperationLib.PAYMASTER_POSTOP_GAS_OFFSET;\n uint256 internal constant PAYMASTER_DATA_OFFSET = UserOperationLib.PAYMASTER_DATA_OFFSET;\n\n constructor(IEntryPoint _entryPoint) Ownable(msg.sender) {\n _validateEntryPointInterface(_entryPoint);\n entryPoint = _entryPoint;\n }\n\n // Sanity check: make sure this EntryPoint was compiled against the same\n // IEntryPoint of this paymaster\n function _validateEntryPointInterface(IEntryPoint _entryPoint) internal virtual {\n require(IERC165(address(_entryPoint)).supportsInterface(type(IEntryPoint).interfaceId), \"IEntryPoint interface mismatch\");\n }\n\n /// @inheritdoc IPaymaster\n function validatePaymasterUserOp(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash,\n uint256 maxCost\n ) external override returns (bytes memory context, uint256 validationData) {\n _requireFromEntryPoint();\n return _validatePaymasterUserOp(userOp, userOpHash, maxCost);\n }\n\n /**\n * Validate a user operation.\n * @param userOp - The user operation.\n * @param userOpHash - The hash of the user operation.\n * @param maxCost - The maximum cost of the user operation.\n */\n function _validatePaymasterUserOp(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash,\n uint256 maxCost\n ) internal virtual returns (bytes memory context, uint256 validationData);\n\n /// @inheritdoc IPaymaster\n function postOp(\n PostOpMode mode,\n bytes calldata context,\n uint256 actualGasCost,\n uint256 actualUserOpFeePerGas\n ) external override {\n _requireFromEntryPoint();\n _postOp(mode, context, actualGasCost, actualUserOpFeePerGas);\n }\n\n /**\n * Post-operation handler.\n * (verified to be called only through the entryPoint)\n * @dev If subclass returns a non-empty context from validatePaymasterUserOp,\n * it must also implement this method.\n * @param mode - Enum with the following options:\n * opSucceeded - User operation succeeded.\n * opReverted - User op reverted. The paymaster still has to pay for gas.\n * postOpReverted - never passed in a call to postOp().\n * @param context - The context value returned by validatePaymasterUserOp\n * @param actualGasCost - Actual cost of gas used so far (without this postOp call).\n * @param actualUserOpFeePerGas - the gas price this UserOp pays. This value is based on the UserOp's maxFeePerGas\n * and maxPriorityFee (and basefee)\n * It is not the same as tx.gasprice, which is what the bundler pays.\n */\n function _postOp(\n PostOpMode mode,\n bytes calldata context,\n uint256 actualGasCost,\n uint256 actualUserOpFeePerGas\n ) internal virtual {\n (mode, context, actualGasCost, actualUserOpFeePerGas); // unused params\n // subclass must override this method if validatePaymasterUserOp returns a context\n revert(\"must override\");\n }\n\n /**\n * Add a deposit for this paymaster, used for paying for transaction fees.\n */\n function deposit() public payable {\n entryPoint.depositTo{value: msg.value}(address(this));\n }\n\n /**\n * Withdraw value from the deposit.\n * @param withdrawAddress - Target to send to.\n * @param amount - Amount to withdraw.\n */\n function withdrawTo(\n address payable withdrawAddress,\n uint256 amount\n ) public onlyOwner {\n entryPoint.withdrawTo(withdrawAddress, amount);\n }\n\n /**\n * Add stake for this paymaster.\n * This method can also carry eth value to add to the current stake.\n * @param unstakeDelaySec - The unstake delay for this paymaster. Can only be increased.\n */\n function addStake(uint32 unstakeDelaySec) external payable onlyOwner {\n entryPoint.addStake{value: msg.value}(unstakeDelaySec);\n }\n\n /**\n * Return current paymaster's deposit on the entryPoint.\n */\n function getDeposit() public view returns (uint256) {\n return entryPoint.balanceOf(address(this));\n }\n\n /**\n * Unlock the stake, in order to withdraw it.\n * The paymaster can't serve requests once unlocked, until it calls addStake again\n */\n function unlockStake() external onlyOwner {\n entryPoint.unlockStake();\n }\n\n /**\n * Withdraw the entire paymaster's stake.\n * stake must be unlocked first (and then wait for the unstakeDelay to be over)\n * @param withdrawAddress - The address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external onlyOwner {\n entryPoint.withdrawStake(withdrawAddress);\n }\n\n /**\n * Validate the call is made from a valid entrypoint\n */\n function _requireFromEntryPoint() internal virtual {\n require(msg.sender == address(entryPoint), \"Sender not EntryPoint\");\n }\n}\n" }, + "@account-abstraction/contracts/core/Eip7702Support.sol": { + "content": "pragma solidity ^0.8.28;\n// SPDX-License-Identifier: MIT\n// solhint-disable no-inline-assembly\n\nimport \"../interfaces/PackedUserOperation.sol\";\nimport \"../core/UserOperationLib.sol\";\n\nlibrary Eip7702Support {\n\n // EIP-7702 code prefix before delegate address.\n bytes3 internal constant EIP7702_PREFIX = 0xef0100;\n\n // EIP-7702 initCode marker, to specify this account is EIP-7702.\n bytes2 internal constant INITCODE_EIP7702_MARKER = 0x7702;\n\n using UserOperationLib for PackedUserOperation;\n\n /**\n * Get the alternative 'InitCodeHash' value for the UserOp hash calculation when using EIP-7702.\n *\n * @param userOp - the UserOperation to for the 'InitCodeHash' calculation.\n * @return the 'InitCodeHash' value.\n */\n function _getEip7702InitCodeHashOverride(PackedUserOperation calldata userOp) internal view returns (bytes32) {\n bytes calldata initCode = userOp.initCode;\n if (!_isEip7702InitCode(initCode)) {\n return 0;\n }\n address delegate = _getEip7702Delegate(userOp.sender);\n if (initCode.length <= 20)\n return keccak256(abi.encodePacked(delegate));\n else\n return keccak256(abi.encodePacked(delegate, initCode[20 :]));\n }\n\n /**\n * Check if this 'initCode' is actually an EIP-7702 authorization.\n * This is indicated by 'initCode' that starts with INITCODE_EIP7702_MARKER.\n *\n * @param initCode - the 'initCode' to check.\n * @return true if the 'initCode' is EIP-7702 authorization, false otherwise.\n */\n function _isEip7702InitCode(bytes calldata initCode) internal pure returns (bool) {\n\n if (initCode.length < 2) {\n return false;\n }\n bytes20 initCodeStart;\n // non-empty calldata bytes are always zero-padded to 32-bytes, so can be safely casted to \"bytes20\"\n assembly (\"memory-safe\") {\n initCodeStart := calldataload(initCode.offset)\n }\n // make sure first 20 bytes of initCode are \"0x7702\" (padded with zeros)\n return initCodeStart == bytes20(INITCODE_EIP7702_MARKER);\n }\n\n /**\n * Get the EIP-7702 delegate from contract code.\n * Must only be used if _isEip7702InitCode(initCode) is true.\n *\n * @param sender - the EIP-7702 'sender' account to get the delegated contract code address.\n * @return the address of the EIP-7702 authorized contract.\n */\n function _getEip7702Delegate(address sender) internal view returns (address) {\n\n bytes32 senderCode;\n\n assembly (\"memory-safe\") {\n extcodecopy(sender, 0, 0, 23)\n senderCode := mload(0)\n }\n // To be a valid EIP-7702 delegate, the first 3 bytes are EIP7702_PREFIX\n // followed by the delegate address\n if (bytes3(senderCode) != EIP7702_PREFIX) {\n // instead of just \"not an EIP-7702 delegate\", if some info.\n require(sender.code.length > 0, \"sender has no code\");\n revert(\"not an EIP-7702 delegate\");\n }\n return address(bytes20(senderCode << 24));\n }\n}\n" + }, + "@account-abstraction/contracts/core/EntryPoint.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IAccountExecute.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\nimport \"../interfaces/IPaymaster.sol\";\n\nimport \"./UserOperationLib.sol\";\nimport \"./StakeManager.sol\";\nimport \"./NonceManager.sol\";\nimport \"./Helpers.sol\";\nimport \"./SenderCreator.sol\";\nimport \"./Eip7702Support.sol\";\nimport \"../utils/Exec.sol\";\n\nimport \"@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol\";\nimport \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/EIP712.sol\";\n\n/**\n * Account-Abstraction (EIP-4337) singleton EntryPoint v0.8 implementation.\n * Only one instance required on each chain.\n * @custom:security-contact https://bounty.ethereum.org\n */\ncontract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardTransient, ERC165, EIP712 {\n\n using UserOperationLib for PackedUserOperation;\n\n /**\n * internal-use constants\n */\n\n // allow some slack for future gas price changes.\n uint256 private constant INNER_GAS_OVERHEAD = 10000;\n\n // Marker for inner call revert on out of gas\n bytes32 private constant INNER_OUT_OF_GAS = hex\"deaddead\";\n bytes32 private constant INNER_REVERT_LOW_PREFUND = hex\"deadaa51\";\n\n uint256 private constant REVERT_REASON_MAX_LEN = 2048;\n // Penalty charged for either unused execution gas or postOp gas\n uint256 private constant UNUSED_GAS_PENALTY_PERCENT = 10;\n // Threshold below which no penalty would be charged\n uint256 private constant PENALTY_GAS_THRESHOLD = 40000;\n\n SenderCreator private immutable _senderCreator = new SenderCreator();\n\n string constant internal DOMAIN_NAME = \"ERC4337\";\n string constant internal DOMAIN_VERSION = \"1\";\n\n constructor() EIP712(DOMAIN_NAME, DOMAIN_VERSION) {\n }\n\n /// @inheritdoc IEntryPoint\n function handleOps(\n PackedUserOperation[] calldata ops,\n address payable beneficiary\n ) external nonReentrant {\n uint256 opslen = ops.length;\n UserOpInfo[] memory opInfos = new UserOpInfo[](opslen);\n unchecked {\n _iterateValidationPhase(ops, opInfos, address(0), 0);\n\n uint256 collected = 0;\n emit BeforeExecution();\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(i, ops[i], opInfos[i]);\n }\n\n _compensate(beneficiary, collected);\n }\n }\n\n /// @inheritdoc IEntryPoint\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) external nonReentrant {\n\n unchecked {\n uint256 opasLen = opsPerAggregator.length;\n uint256 totalOps = 0;\n for (uint256 i = 0; i < opasLen; i++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[i];\n PackedUserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n // address(1) is special marker of \"signature error\"\n require(\n address(aggregator) != address(1),\n SignatureValidationFailed(address(aggregator))\n );\n\n if (address(aggregator) != address(0)) {\n // solhint-disable-next-line no-empty-blocks\n try aggregator.validateSignatures(ops, opa.signature) {} catch {\n revert SignatureValidationFailed(address(aggregator));\n }\n }\n\n totalOps += ops.length;\n }\n\n UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);\n\n uint256 opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n PackedUserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n opIndex += _iterateValidationPhase(ops, opInfos, address(aggregator), opIndex);\n }\n\n emit BeforeExecution();\n\n uint256 collected = 0;\n opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n emit SignatureAggregatorChanged(address(opa.aggregator));\n PackedUserOperation[] calldata ops = opa.userOps;\n uint256 opslen = ops.length;\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]);\n opIndex++;\n }\n }\n\n _compensate(beneficiary, collected);\n }\n }\n\n /// @inheritdoc IEntryPoint\n function getUserOpHash(\n PackedUserOperation calldata userOp\n ) public view returns (bytes32) {\n bytes32 overrideInitCodeHash = Eip7702Support._getEip7702InitCodeHashOverride(userOp);\n return\n MessageHashUtils.toTypedDataHash(getDomainSeparatorV4(), userOp.hash(overrideInitCodeHash));\n }\n\n /// @inheritdoc IEntryPoint\n function getSenderAddress(bytes calldata initCode) external {\n address sender = senderCreator().createSender(initCode);\n revert SenderAddressResult(sender);\n }\n\n /// @inheritdoc IEntryPoint\n function senderCreator() public view virtual returns (ISenderCreator) {\n return _senderCreator;\n }\n\n /// @inheritdoc IEntryPoint\n function delegateAndRevert(address target, bytes calldata data) external {\n (bool success, bytes memory ret) = target.delegatecall(data);\n revert DelegateAndRevert(success, ret);\n }\n\n function getPackedUserOpTypeHash() external pure returns (bytes32) {\n return UserOperationLib.PACKED_USEROP_TYPEHASH;\n }\n\n function getDomainSeparatorV4() public virtual view returns (bytes32) {\n return _domainSeparatorV4();\n }\n\n /// @inheritdoc IERC165\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n // note: solidity \"type(IEntryPoint).interfaceId\" is without inherited methods but we want to check everything\n return interfaceId == (type(IEntryPoint).interfaceId ^ type(IStakeManager).interfaceId ^ type(INonceManager).interfaceId) ||\n interfaceId == type(IEntryPoint).interfaceId ||\n interfaceId == type(IStakeManager).interfaceId ||\n interfaceId == type(INonceManager).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * Compensate the caller's beneficiary address with the collected fees of all UserOperations.\n * @param beneficiary - The address to receive the fees.\n * @param amount - Amount to transfer.\n */\n function _compensate(address payable beneficiary, uint256 amount) internal virtual {\n require(beneficiary != address(0), \"AA90 invalid beneficiary\");\n (bool success,) = beneficiary.call{value: amount}(\"\");\n require(success, \"AA91 failed send to beneficiary\");\n }\n\n /**\n * Execute a user operation.\n * @param opIndex - Index into the opInfo array.\n * @param userOp - The userOp to execute.\n * @param opInfo - The opInfo filled by validatePrepayment for this userOp.\n * @return collected - The total amount this userOp paid.\n */\n function _executeUserOp(\n uint256 opIndex,\n PackedUserOperation calldata userOp,\n UserOpInfo memory opInfo\n )\n internal virtual\n returns (uint256 collected) {\n uint256 preGas = gasleft();\n bytes memory context = _getMemoryBytesFromOffset(opInfo.contextOffset);\n bool success;\n {\n uint256 saveFreePtr = _getFreePtr();\n bytes calldata callData = userOp.callData;\n bytes memory innerCall;\n bytes4 methodSig;\n assembly (\"memory-safe\") {\n let len := callData.length\n if gt(len, 3) {\n methodSig := calldataload(callData.offset)\n }\n }\n if (methodSig == IAccountExecute.executeUserOp.selector) {\n bytes memory executeUserOp = abi.encodeCall(IAccountExecute.executeUserOp, (userOp, opInfo.userOpHash));\n innerCall = abi.encodeCall(this.innerHandleOp, (executeUserOp, opInfo, context));\n } else\n {\n innerCall = abi.encodeCall(this.innerHandleOp, (callData, opInfo, context));\n }\n assembly (\"memory-safe\") {\n success := call(gas(), address(), 0, add(innerCall, 0x20), mload(innerCall), 0, 32)\n collected := mload(0)\n }\n _restoreFreePtr(saveFreePtr);\n }\n if (!success) {\n bytes32 innerRevertCode;\n assembly (\"memory-safe\") {\n let len := returndatasize()\n if eq(32, len) {\n returndatacopy(0, 0, 32)\n innerRevertCode := mload(0)\n }\n }\n if (innerRevertCode == INNER_OUT_OF_GAS) {\n // handleOps was called with gas limit too low. abort entire bundle.\n // can only be caused by bundler (leaving not enough gas for inner call)\n revert FailedOp(opIndex, \"AA95 out of gas\");\n } else if (innerRevertCode == INNER_REVERT_LOW_PREFUND) {\n // innerCall reverted on prefund too low. treat entire prefund as \"gas cost\"\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n uint256 actualGasCost = opInfo.prefund;\n _emitPrefundTooLow(opInfo);\n _emitUserOperationEvent(opInfo, false, actualGasCost, actualGas);\n collected = actualGasCost;\n } else {\n uint256 freePtr = _getFreePtr();\n emit PostOpRevertReason(\n opInfo.userOpHash,\n opInfo.mUserOp.sender,\n opInfo.mUserOp.nonce,\n Exec.getReturnData(REVERT_REASON_MAX_LEN)\n );\n _restoreFreePtr(freePtr);\n\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n collected = _postExecution(\n IPaymaster.PostOpMode.postOpReverted,\n opInfo,\n context,\n actualGas\n );\n }\n }\n }\n\n /**\n * Emit the UserOperationEvent for the given UserOperation.\n *\n * @param opInfo - The details of the current UserOperation.\n * @param success - Whether the execution of the UserOperation has succeeded or not.\n * @param actualGasCost - The actual cost of the consumed gas charged from the sender or the paymaster.\n * @param actualGas - The actual amount of gas used.\n */\n function _emitUserOperationEvent(UserOpInfo memory opInfo, bool success, uint256 actualGasCost, uint256 actualGas) internal virtual {\n emit UserOperationEvent(\n opInfo.userOpHash,\n opInfo.mUserOp.sender,\n opInfo.mUserOp.paymaster,\n opInfo.mUserOp.nonce,\n success,\n actualGasCost,\n actualGas\n );\n }\n\n /**\n * Emit the UserOperationPrefundTooLow event for the given UserOperation.\n *\n * @param opInfo - The details of the current UserOperation.\n */\n function _emitPrefundTooLow(UserOpInfo memory opInfo) internal virtual {\n emit UserOperationPrefundTooLow(\n opInfo.userOpHash,\n opInfo.mUserOp.sender,\n opInfo.mUserOp.nonce\n );\n }\n\n /**\n * Iterate over calldata PackedUserOperation array and perform account and paymaster validation.\n * @notice UserOpInfo is a global array of all UserOps while PackedUserOperation is grouped per aggregator.\n *\n * @param ops - an array of UserOps to be validated\n * @param opInfos - an array of UserOp metadata being read and filled in during this function's execution\n * @param expectedAggregator - an address of the aggregator specified for a given UserOp if any, or address(0)\n * @param opIndexOffset - an offset for the index between 'ops' and 'opInfos' arrays, see the notice.\n * @return opsLen - processed UserOps (length of \"ops\" array)\n */\n function _iterateValidationPhase(\n PackedUserOperation[] calldata ops,\n UserOpInfo[] memory opInfos,\n address expectedAggregator,\n uint256 opIndexOffset\n ) internal returns (uint256 opsLen){\n unchecked {\n opsLen = ops.length;\n for (uint256 i = 0; i < opsLen; i++) {\n UserOpInfo memory opInfo = opInfos[opIndexOffset + i];\n (\n uint256 validationData,\n uint256 pmValidationData\n ) = _validatePrepayment(opIndexOffset + i, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(\n opIndexOffset + i,\n validationData,\n pmValidationData,\n expectedAggregator\n );\n }\n }\n }\n\n /**\n * A memory copy of UserOp static fields only.\n * Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster.\n */\n struct MemoryUserOp {\n address sender;\n uint256 nonce;\n uint256 verificationGasLimit;\n uint256 callGasLimit;\n uint256 paymasterVerificationGasLimit;\n uint256 paymasterPostOpGasLimit;\n uint256 preVerificationGas;\n address paymaster;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n }\n\n struct UserOpInfo {\n MemoryUserOp mUserOp;\n bytes32 userOpHash;\n uint256 prefund;\n uint256 contextOffset;\n uint256 preOpGas;\n }\n\n /**\n * Inner function to handle a UserOperation.\n * Must be declared \"external\" to open a call context, but it can only be called by handleOps.\n * @param callData - The callData to execute.\n * @param opInfo - The UserOpInfo struct.\n * @param context - The context bytes.\n * @return actualGasCost - the actual cost in eth this UserOperation paid for gas\n */\n function innerHandleOp(\n bytes memory callData,\n UserOpInfo memory opInfo,\n bytes calldata context\n ) external returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n require(msg.sender == address(this), \"AA92 internal call only\");\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n\n uint256 callGasLimit = mUserOp.callGasLimit;\n unchecked {\n // handleOps was called with gas limit too low. abort entire bundle.\n if (\n gasleft() * 63 / 64 <\n callGasLimit +\n mUserOp.paymasterPostOpGasLimit +\n INNER_GAS_OVERHEAD\n ) {\n assembly (\"memory-safe\") {\n mstore(0, INNER_OUT_OF_GAS)\n revert(0, 32)\n }\n }\n }\n\n IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;\n if (callData.length > 0) {\n bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit);\n if (!success) {\n uint256 freePtr = _getFreePtr();\n bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);\n if (result.length > 0) {\n emit UserOperationRevertReason(\n opInfo.userOpHash,\n mUserOp.sender,\n mUserOp.nonce,\n result\n );\n }\n _restoreFreePtr(freePtr);\n mode = IPaymaster.PostOpMode.opReverted;\n }\n }\n\n unchecked {\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n return _postExecution(mode, opInfo, context, actualGas);\n }\n }\n\n /**\n * Copy general fields from userOp into the memory opInfo structure.\n * @param userOp - The user operation.\n * @param mUserOp - The memory user operation.\n */\n function _copyUserOpToMemory(\n PackedUserOperation calldata userOp,\n MemoryUserOp memory mUserOp\n ) internal virtual pure {\n mUserOp.sender = userOp.sender;\n mUserOp.nonce = userOp.nonce;\n (mUserOp.verificationGasLimit, mUserOp.callGasLimit) = UserOperationLib.unpackUints(userOp.accountGasLimits);\n mUserOp.preVerificationGas = userOp.preVerificationGas;\n (mUserOp.maxPriorityFeePerGas, mUserOp.maxFeePerGas) = UserOperationLib.unpackUints(userOp.gasFees);\n bytes calldata paymasterAndData = userOp.paymasterAndData;\n if (paymasterAndData.length > 0) {\n require(\n paymasterAndData.length >= UserOperationLib.PAYMASTER_DATA_OFFSET,\n \"AA93 invalid paymasterAndData\"\n );\n address paymaster;\n (paymaster, mUserOp.paymasterVerificationGasLimit, mUserOp.paymasterPostOpGasLimit) = UserOperationLib.unpackPaymasterStaticFields(paymasterAndData);\n require(paymaster != address(0), \"AA98 invalid paymaster\");\n mUserOp.paymaster = paymaster;\n }\n }\n\n /**\n * Get the required prefunded gas fee amount for an operation.\n *\n * @param mUserOp - The user operation in memory.\n * @return requiredPrefund - the required amount.\n */\n function _getRequiredPrefund(\n MemoryUserOp memory mUserOp\n ) internal virtual pure returns (uint256 requiredPrefund) {\n unchecked {\n uint256 requiredGas = mUserOp.verificationGasLimit +\n mUserOp.callGasLimit +\n mUserOp.paymasterVerificationGasLimit +\n mUserOp.paymasterPostOpGasLimit +\n mUserOp.preVerificationGas;\n\n requiredPrefund = requiredGas * mUserOp.maxFeePerGas;\n }\n }\n\n /**\n * Create sender smart contract account if init code is provided.\n * @param opIndex - The operation index.\n * @param opInfo - The operation info.\n * @param initCode - The init code for the smart contract account.\n */\n function _createSenderIfNeeded(\n uint256 opIndex,\n UserOpInfo memory opInfo,\n bytes calldata initCode\n ) internal virtual {\n if (initCode.length != 0) {\n address sender = opInfo.mUserOp.sender;\n if (Eip7702Support._isEip7702InitCode(initCode)) {\n if (initCode.length > 20) {\n // Already validated it is an EIP-7702 delegate (and hence, already has code) - see getUserOpHash()\n // Note: Can be called multiple times as long as an appropriate initCode is supplied\n senderCreator().initEip7702Sender{\n gas: opInfo.mUserOp.verificationGasLimit\n }(sender, initCode[20 :]);\n }\n return;\n }\n if (sender.code.length != 0)\n revert FailedOp(opIndex, \"AA10 sender already constructed\");\n if (initCode.length < 20) {\n revert FailedOp(opIndex, \"AA99 initCode too small\");\n }\n address sender1 = senderCreator().createSender{\n gas: opInfo.mUserOp.verificationGasLimit\n }(initCode);\n if (sender1 == address(0))\n revert FailedOp(opIndex, \"AA13 initCode failed or OOG\");\n if (sender1 != sender)\n revert FailedOp(opIndex, \"AA14 initCode must return sender\");\n if (sender1.code.length == 0)\n revert FailedOp(opIndex, \"AA15 initCode must create sender\");\n address factory = address(bytes20(initCode[0 : 20]));\n emit AccountDeployed(\n opInfo.userOpHash,\n sender,\n factory,\n opInfo.mUserOp.paymaster\n );\n }\n }\n\n /**\n * Call account.validateUserOp.\n * Revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund.\n * Decrement account's deposit if needed.\n * @param opIndex - The operation index.\n * @param op - The user operation.\n * @param opInfo - The operation info.\n * @param requiredPrefund - The required prefund amount.\n * @return validationData - The account's validationData.\n */\n function _validateAccountPrepayment(\n uint256 opIndex,\n PackedUserOperation calldata op,\n UserOpInfo memory opInfo,\n uint256 requiredPrefund\n )\n internal virtual\n returns (\n uint256 validationData\n )\n {\n unchecked {\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n address sender = mUserOp.sender;\n _createSenderIfNeeded(opIndex, opInfo, op.initCode);\n address paymaster = mUserOp.paymaster;\n uint256 missingAccountFunds = 0;\n if (paymaster == address(0)) {\n uint256 bal = balanceOf(sender);\n missingAccountFunds = bal > requiredPrefund\n ? 0\n : requiredPrefund - bal;\n }\n validationData = _callValidateUserOp(opIndex, op, opInfo, missingAccountFunds);\n if (paymaster == address(0)) {\n if (!_tryDecrementDeposit(sender, requiredPrefund)) {\n revert FailedOp(opIndex, \"AA21 didn't pay prefund\");\n }\n }\n }\n }\n\n /**\n * Make a call to the sender.validateUserOp() function.\n * Handle wrong output size by reverting with a FailedOp error.\n *\n * @param opIndex - index of the UserOperation in the bundle.\n * @param op - the packed UserOperation object.\n * @param opInfo - the in-memory UserOperation information.\n * @param missingAccountFunds - the amount of deposit the account has to make to cover the UserOperation gas.\n */\n function _callValidateUserOp(\n uint256 opIndex,\n PackedUserOperation calldata op,\n UserOpInfo memory opInfo,\n uint256 missingAccountFunds\n )\n internal virtual returns (uint256 validationData) {\n uint256 gasLimit = opInfo.mUserOp.verificationGasLimit;\n address sender = opInfo.mUserOp.sender;\n bool success;\n {\n uint256 saveFreePtr = _getFreePtr();\n bytes memory callData = abi.encodeCall(IAccount.validateUserOp, (op, opInfo.userOpHash, missingAccountFunds));\n assembly (\"memory-safe\"){\n success := call(gasLimit, sender, 0, add(callData, 0x20), mload(callData), 0, 32)\n validationData := mload(0)\n // any return data size other than 32 is considered failure\n if iszero(eq(returndatasize(), 32)) {\n success := 0\n }\n }\n _restoreFreePtr(saveFreePtr);\n }\n if (!success) {\n if (sender.code.length == 0) {\n revert FailedOp(opIndex, \"AA20 account not deployed\");\n } else {\n revert FailedOpWithRevert(opIndex, \"AA23 reverted\", Exec.getReturnData(REVERT_REASON_MAX_LEN));\n }\n }\n }\n\n /**\n * In case the request has a paymaster:\n * - Validate paymaster has enough deposit.\n * - Call paymaster.validatePaymasterUserOp.\n * - Revert with proper FailedOp in case paymaster reverts.\n * - Decrement paymaster's deposit.\n * @param opIndex - The operation index.\n * @param op - The user operation.\n * @param opInfo - The operation info.\n * @return context - The Paymaster-provided value to be passed to the 'postOp' function later\n * @return validationData - The Paymaster's validationData.\n */\n function _validatePaymasterPrepayment(\n uint256 opIndex,\n PackedUserOperation calldata op,\n UserOpInfo memory opInfo\n ) internal virtual returns (bytes memory context, uint256 validationData) {\n unchecked {\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n address paymaster = mUserOp.paymaster;\n uint256 requiredPreFund = opInfo.prefund;\n if (!_tryDecrementDeposit(paymaster, requiredPreFund)) {\n revert FailedOp(opIndex, \"AA31 paymaster deposit too low\");\n }\n uint256 pmVerificationGasLimit = mUserOp.paymasterVerificationGasLimit;\n (context, validationData) = _callValidatePaymasterUserOp(opIndex, op, opInfo);\n if (preGas - gasleft() > pmVerificationGasLimit) {\n revert FailedOp(opIndex, \"AA36 over paymasterVerificationGasLimit\");\n }\n }\n }\n\n function _callValidatePaymasterUserOp(\n uint256 opIndex,\n PackedUserOperation calldata op,\n UserOpInfo memory opInfo\n ) internal returns (bytes memory context, uint256 validationData) {\n uint256 freePtr = _getFreePtr();\n bytes memory validatePaymasterCall = abi.encodeCall(\n IPaymaster.validatePaymasterUserOp,\n (op, opInfo.userOpHash, opInfo.prefund)\n );\n address paymaster = opInfo.mUserOp.paymaster;\n uint256 paymasterVerificationGasLimit = opInfo.mUserOp.paymasterVerificationGasLimit;\n bool success;\n uint256 contextLength;\n uint256 contextOffset;\n uint256 maxContextLength;\n uint256 len;\n assembly (\"memory-safe\") {\n success := call(paymasterVerificationGasLimit, paymaster, 0, add(validatePaymasterCall, 0x20), mload(validatePaymasterCall), 0, 0)\n len := returndatasize()\n // return data from validatePaymasterUserOp is (bytes context, validationData)\n // encoded as:\n // 32 bytes offset of context (always 64)\n // 32 bytes of validationData\n // 32 bytes of context length\n // context data (rounded up, to 32 bytes boundary)\n // so entire buffer size is (at least) 96+content.length.\n //\n // we use freePtr, fetched before calling encodeCall, as return data pointer.\n // this way we reuse that memory without unnecessary memory expansion\n returndatacopy(freePtr, 0, len)\n validationData := mload(add(freePtr, 32))\n contextOffset := mload(freePtr)\n maxContextLength := sub(len, 96)\n context := add(freePtr, 64)\n contextLength := mload(context)\n }\n\n unchecked {\n if (!success || contextOffset != 64 || contextLength + 31 < maxContextLength) {\n revert FailedOpWithRevert(opIndex, \"AA33 reverted\", Exec.getReturnData(REVERT_REASON_MAX_LEN));\n }\n }\n finalizeAllocation(freePtr, len);\n }\n\n /**\n * Revert if either account validationData or paymaster validationData is expired.\n * @param opIndex - The operation index.\n * @param validationData - The account validationData.\n * @param paymasterValidationData - The paymaster validationData.\n * @param expectedAggregator - The expected aggregator.\n */\n function _validateAccountAndPaymasterValidationData(\n uint256 opIndex,\n uint256 validationData,\n uint256 paymasterValidationData,\n address expectedAggregator\n ) internal virtual view {\n (address aggregator, bool outOfTimeRange) = _getValidationData(\n validationData\n );\n if (expectedAggregator != aggregator) {\n revert FailedOp(opIndex, \"AA24 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA22 expired or not due\");\n }\n // pmAggregator is not a real signature aggregator: we don't have logic to handle it as address.\n // Non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation).\n address pmAggregator;\n (pmAggregator, outOfTimeRange) = _getValidationData(\n paymasterValidationData\n );\n if (pmAggregator != address(0)) {\n revert FailedOp(opIndex, \"AA34 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA32 paymaster expired or not due\");\n }\n }\n\n /**\n * Parse validationData into its components.\n * @param validationData - The packed validation data (sigFailed, validAfter, validUntil).\n * @return aggregator the aggregator of the validationData\n * @return outOfTimeRange true if current time is outside the time range of this validationData.\n */\n function _getValidationData(\n uint256 validationData\n ) internal virtual view returns (address aggregator, bool outOfTimeRange) {\n if (validationData == 0) {\n return (address(0), false);\n }\n ValidationData memory data = _parseValidationData(validationData);\n // solhint-disable-next-line not-rely-on-time\n outOfTimeRange = block.timestamp > data.validUntil || block.timestamp <= data.validAfter;\n aggregator = data.aggregator;\n }\n\n /**\n * Validate account and paymaster (if defined) and\n * also make sure total validation doesn't exceed verificationGasLimit.\n * This method is called off-chain (simulateValidation()) and on-chain (from handleOps)\n * @param opIndex - The index of this userOp into the \"opInfos\" array.\n * @param userOp - The packed calldata UserOperation structure to validate.\n * @param outOpInfo - The empty unpacked in-memory UserOperation structure that will be filled in here.\n *\n * @return validationData - The account's validationData.\n * @return paymasterValidationData - The paymaster's validationData.\n */\n function _validatePrepayment(\n uint256 opIndex,\n PackedUserOperation calldata userOp,\n UserOpInfo memory outOpInfo\n )\n internal virtual\n returns (uint256 validationData, uint256 paymasterValidationData)\n {\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = outOpInfo.mUserOp;\n _copyUserOpToMemory(userOp, mUserOp);\n\n // getUserOpHash uses temporary allocations, no required after it returns\n uint256 freePtr = _getFreePtr();\n outOpInfo.userOpHash = getUserOpHash(userOp);\n _restoreFreePtr(freePtr);\n\n // Validate all numeric values in userOp are well below 128 bit, so they can safely be added\n // and multiplied without causing overflow.\n uint256 verificationGasLimit = mUserOp.verificationGasLimit;\n uint256 maxGasValues = mUserOp.preVerificationGas |\n verificationGasLimit |\n mUserOp.callGasLimit |\n mUserOp.paymasterVerificationGasLimit |\n mUserOp.paymasterPostOpGasLimit |\n mUserOp.maxFeePerGas |\n mUserOp.maxPriorityFeePerGas;\n require(maxGasValues <= type(uint120).max, FailedOp(opIndex, \"AA94 gas values overflow\"));\n\n uint256 requiredPreFund = _getRequiredPrefund(mUserOp);\n outOpInfo.prefund = requiredPreFund;\n validationData = _validateAccountPrepayment(\n opIndex,\n userOp,\n outOpInfo,\n requiredPreFund\n );\n\n require(\n _validateAndUpdateNonce(mUserOp.sender, mUserOp.nonce),\n FailedOp(opIndex, \"AA25 invalid account nonce\")\n );\n\n unchecked {\n if (preGas - gasleft() > verificationGasLimit) {\n revert FailedOp(opIndex, \"AA26 over verificationGasLimit\");\n }\n }\n\n bytes memory context;\n if (mUserOp.paymaster != address(0)) {\n (context, paymasterValidationData) = _validatePaymasterPrepayment(\n opIndex,\n userOp,\n outOpInfo\n );\n }\n unchecked {\n outOpInfo.contextOffset = _getOffsetOfMemoryBytes(context);\n outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas;\n }\n }\n\n /**\n * Process post-operation, called just after the callData is executed.\n * If a paymaster is defined and its validation returned a non-empty context, its postOp is called.\n * The excess amount is refunded to the account (or paymaster - if it was used in the request).\n * @param mode - Whether is called from innerHandleOp, or outside (postOpReverted).\n * @param opInfo - UserOp fields and info collected during validation.\n * @param context - The context returned in validatePaymasterUserOp.\n * @param actualGas - The gas used so far by this user operation.\n *\n * @return actualGasCost - the actual cost in eth this UserOperation paid for gas\n */\n function _postExecution(\n IPaymaster.PostOpMode mode,\n UserOpInfo memory opInfo,\n bytes memory context,\n uint256 actualGas\n ) internal virtual returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n unchecked {\n address refundAddress;\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 gasPrice = _getUserOpGasPrice(mUserOp);\n\n address paymaster = mUserOp.paymaster;\n // Calculating a penalty for unused execution gas\n {\n uint256 executionGasUsed = actualGas - opInfo.preOpGas;\n // this check is required for the gas used within EntryPoint and not covered by explicit gas limits\n actualGas += _getUnusedGasPenalty(executionGasUsed, mUserOp.callGasLimit);\n }\n uint256 postOpUnusedGasPenalty;\n if (paymaster == address(0)) {\n refundAddress = mUserOp.sender;\n } else {\n refundAddress = paymaster;\n if (context.length > 0) {\n actualGasCost = actualGas * gasPrice;\n uint256 postOpPreGas = gasleft();\n if (mode != IPaymaster.PostOpMode.postOpReverted) {\n try IPaymaster(paymaster).postOp{\n gas: mUserOp.paymasterPostOpGasLimit\n }(mode, context, actualGasCost, gasPrice)\n // solhint-disable-next-line no-empty-blocks\n {} catch {\n bytes memory reason = Exec.getReturnData(REVERT_REASON_MAX_LEN);\n revert PostOpReverted(reason);\n }\n }\n // Calculating a penalty for unused postOp gas\n // note that if postOp is reverted, the maximum penalty (10% of postOpGasLimit) is charged.\n uint256 postOpGasUsed = postOpPreGas - gasleft();\n postOpUnusedGasPenalty = _getUnusedGasPenalty(postOpGasUsed, mUserOp.paymasterPostOpGasLimit);\n }\n }\n actualGas += preGas - gasleft() + postOpUnusedGasPenalty;\n actualGasCost = actualGas * gasPrice;\n uint256 prefund = opInfo.prefund;\n if (prefund < actualGasCost) {\n if (mode == IPaymaster.PostOpMode.postOpReverted) {\n actualGasCost = prefund;\n _emitPrefundTooLow(opInfo);\n _emitUserOperationEvent(opInfo, false, actualGasCost, actualGas);\n } else {\n assembly (\"memory-safe\") {\n mstore(0, INNER_REVERT_LOW_PREFUND)\n revert(0, 32)\n }\n }\n } else {\n uint256 refund = prefund - actualGasCost;\n _incrementDeposit(refundAddress, refund);\n bool success = mode == IPaymaster.PostOpMode.opSucceeded;\n _emitUserOperationEvent(opInfo, success, actualGasCost, actualGas);\n }\n } // unchecked\n }\n\n /**\n * The gas price this UserOp agrees to pay.\n * Relayer/block builder might submit the TX with higher priorityFee, but the user should not be affected.\n * @param mUserOp - The userOp to get the gas price from.\n */\n function _getUserOpGasPrice(\n MemoryUserOp memory mUserOp\n ) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = mUserOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n /**\n * The offset of the given bytes in memory.\n * @param data - The bytes to get the offset of.\n */\n function _getOffsetOfMemoryBytes(\n bytes memory data\n ) internal pure returns (uint256 offset) {\n assembly (\"memory-safe\") {\n offset := data\n }\n }\n\n /**\n * The bytes in memory at the given offset.\n * @param offset - The offset to get the bytes from.\n */\n function _getMemoryBytesFromOffset(\n uint256 offset\n ) internal pure returns (bytes memory data) {\n assembly (\"memory-safe\") {\n data := offset\n }\n }\n\n /**\n * save free memory pointer.\n * save \"free memory\" pointer, so that it can be restored later using restoreFreePtr.\n * This reduce unneeded memory expansion, and reduce memory expansion cost.\n * NOTE: all dynamic allocations between saveFreePtr and restoreFreePtr MUST NOT be used after restoreFreePtr is called.\n */\n function _getFreePtr() internal pure returns (uint256 ptr) {\n assembly (\"memory-safe\") {\n ptr := mload(0x40)\n }\n }\n\n /**\n * restore free memory pointer.\n * any allocated memory since saveFreePtr is cleared, and MUST NOT be accessed later.\n */\n function _restoreFreePtr(uint256 ptr) internal pure {\n assembly (\"memory-safe\") {\n mstore(0x40, ptr)\n }\n }\n\n function _getUnusedGasPenalty(uint256 gasUsed, uint256 gasLimit) internal pure returns (uint256) {\n unchecked {\n if (gasLimit <= gasUsed + PENALTY_GAS_THRESHOLD) {\n return 0;\n }\n uint256 unusedGas = gasLimit - gasUsed;\n uint256 unusedGasPenalty = (unusedGas * UNUSED_GAS_PENALTY_PERCENT) / 100;\n return unusedGasPenalty;\n }\n }\n}\n" + }, "@account-abstraction/contracts/core/Helpers.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/* solhint-disable no-inline-assembly */\n\n\n /*\n * For simulation purposes, validateUserOp (and validatePaymasterUserOp)\n * must return this value in case of signature failure, instead of revert.\n */\nuint256 constant SIG_VALIDATION_FAILED = 1;\n\n\n/*\n * For simulation purposes, validateUserOp (and validatePaymasterUserOp)\n * return this value on success.\n */\nuint256 constant SIG_VALIDATION_SUCCESS = 0;\n\n\n/**\n * Returned data from validateUserOp.\n * validateUserOp returns a uint256, which is created by `_packedValidationData` and\n * parsed by `_parseValidationData`.\n * @param aggregator - address(0) - The account validated the signature by itself.\n * address(1) - The account failed to validate the signature.\n * otherwise - This is an address of a signature aggregator that must\n * be used to validate the signature.\n * @param validAfter - This UserOp is valid only after this timestamp.\n * @param validUntil - Last timestamp this operation is valid at, or 0 for \"indefinitely\".\n */\nstruct ValidationData {\n address aggregator;\n uint48 validAfter;\n uint48 validUntil;\n}\n\n/**\n * Extract aggregator/sigFailed, validAfter, validUntil.\n * Also convert zero validUntil to type(uint48).max.\n * @param validationData - The packed validation data.\n * @return data - The unpacked in-memory validation data.\n */\nfunction _parseValidationData(\n uint256 validationData\n) pure returns (ValidationData memory data) {\n address aggregator = address(uint160(validationData));\n uint48 validUntil = uint48(validationData >> 160);\n if (validUntil == 0) {\n validUntil = type(uint48).max;\n }\n uint48 validAfter = uint48(validationData >> (48 + 160));\n return ValidationData(aggregator, validAfter, validUntil);\n}\n\n/**\n * Helper to pack the return value for validateUserOp.\n * @param data - The ValidationData to pack.\n * @return the packed validation data.\n */\nfunction _packValidationData(\n ValidationData memory data\n) pure returns (uint256) {\n return\n uint160(data.aggregator) |\n (uint256(data.validUntil) << 160) |\n (uint256(data.validAfter) << (160 + 48));\n}\n\n/**\n * Helper to pack the return value for validateUserOp, when not using an aggregator.\n * @param sigFailed - True for signature failure, false for success.\n * @param validUntil - Last timestamp this operation is valid at, or 0 for \"indefinitely\".\n * @param validAfter - First timestamp this UserOperation is valid.\n * @return the packed validation data.\n */\nfunction _packValidationData(\n bool sigFailed,\n uint48 validUntil,\n uint48 validAfter\n) pure returns (uint256) {\n return\n (sigFailed ? SIG_VALIDATION_FAILED : SIG_VALIDATION_SUCCESS) |\n (uint256(validUntil) << 160) |\n (uint256(validAfter) << (160 + 48));\n}\n\n/**\n * keccak function over calldata.\n * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.\n *\n * @param data - the calldata bytes array to perform keccak on.\n * @return ret - the keccak hash of the 'data' array.\n */\n function calldataKeccak(bytes calldata data) 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\n/**\n * The minimum of two numbers.\n * @param a - First number.\n * @param b - Second number.\n * @return - the minimum value.\n */\n function min(uint256 a, uint256 b) pure returns (uint256) {\n return a < b ? a : b;\n }\n\n/**\n * standard solidity memory allocation finalization.\n * copied from solidity generated code\n * @param memPointer - The current memory pointer\n * @param allocationSize - Bytes allocated from memPointer.\n */\n function finalizeAllocation(uint256 memPointer, uint256 allocationSize) pure {\n\n assembly (\"memory-safe\"){\n finalize_allocation(memPointer, allocationSize)\n\n function finalize_allocation(memPtr, size) {\n let newFreePtr := add(memPtr, round_up_to_mul_of_32(size))\n mstore(64, newFreePtr)\n }\n\n function round_up_to_mul_of_32(value) -> result {\n result := and(add(value, 31), not(31))\n }\n }\n }\n" }, + "@account-abstraction/contracts/core/NonceManager.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport \"../interfaces/INonceManager.sol\";\n\n/**\n * nonce management functionality\n */\nabstract contract NonceManager is INonceManager {\n\n /**\n * The next valid sequence number for a given nonce key.\n */\n mapping(address => mapping(uint192 => uint256)) public nonceSequenceNumber;\n\n /// @inheritdoc INonceManager\n function getNonce(address sender, uint192 key)\n public view override returns (uint256 nonce) {\n return nonceSequenceNumber[sender][key] | (uint256(key) << 64);\n }\n\n /// @inheritdoc INonceManager\n function incrementNonce(uint192 key) external override {\n nonceSequenceNumber[msg.sender][key]++;\n }\n\n /**\n * validate nonce uniqueness for this account.\n * called just after validateUserOp()\n * @return true if the nonce was incremented successfully.\n * false if the current nonce doesn't match the given one.\n */\n function _validateAndUpdateNonce(address sender, uint256 nonce) internal returns (bool) {\n\n uint192 key = uint192(nonce >> 64);\n uint64 seq = uint64(nonce);\n return nonceSequenceNumber[sender][key]++ == seq;\n }\n\n}\n" + }, + "@account-abstraction/contracts/core/SenderCreator.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/ISenderCreator.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\nimport \"../utils/Exec.sol\";\n\n/**\n * Helper contract for EntryPoint, to call userOp.initCode from a \"neutral\" address,\n * which is explicitly not the entryPoint itself.\n */\ncontract SenderCreator is ISenderCreator {\n address public immutable entryPoint;\n\n constructor(){\n entryPoint = msg.sender;\n }\n\n uint256 private constant REVERT_REASON_MAX_LEN = 2048;\n\n /**\n * Call the \"initCode\" factory to create and return the sender account address.\n * @param initCode - The initCode value from a UserOp. contains 20 bytes of factory address,\n * followed by calldata.\n * @return sender - The returned address of the created account, or zero address on failure.\n */\n function createSender(\n bytes calldata initCode\n ) external returns (address sender) {\n require(msg.sender == entryPoint, \"AA97 should call from EntryPoint\");\n address factory = address(bytes20(initCode[0 : 20]));\n\n bytes memory initCallData = initCode[20 :];\n bool success;\n assembly (\"memory-safe\") {\n success := call(\n gas(),\n factory,\n 0,\n add(initCallData, 0x20),\n mload(initCallData),\n 0,\n 32\n )\n if success {\n sender := mload(0)\n }\n }\n }\n\n /// @inheritdoc ISenderCreator\n function initEip7702Sender(\n address sender,\n bytes memory initCallData\n ) external {\n require(msg.sender == entryPoint, \"AA97 should call from EntryPoint\");\n bool success;\n assembly (\"memory-safe\") {\n success := call(\n gas(),\n sender,\n 0,\n add(initCallData, 0x20),\n mload(initCallData),\n 0,\n 0\n )\n }\n if (!success) {\n bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);\n revert IEntryPoint.FailedOpWithRevert(0, \"AA13 EIP7702 sender init failed\", result);\n }\n }\n}\n" + }, + "@account-abstraction/contracts/core/StakeManager.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport \"../interfaces/IStakeManager.sol\";\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable not-rely-on-time */\n\n/**\n * Manage deposits and stakes.\n * Deposit is just a balance used to pay for UserOperations (either by a paymaster or an account).\n * Stake is value locked for at least \"unstakeDelay\" by a paymaster.\n */\nabstract contract StakeManager is IStakeManager {\n /// maps paymaster to their deposits and stakes\n mapping(address => DepositInfo) private deposits;\n\n /// @inheritdoc IStakeManager\n function getDepositInfo(\n address account\n ) external view returns (DepositInfo memory info) {\n return deposits[account];\n }\n\n /**\n * Internal method to return just the stake info.\n * @param addr - The account to query.\n */\n function _getStakeInfo(\n address addr\n ) internal view returns (StakeInfo memory info) {\n DepositInfo storage depositInfo = deposits[addr];\n info.stake = depositInfo.stake;\n info.unstakeDelaySec = depositInfo.unstakeDelaySec;\n }\n\n /// @inheritdoc IStakeManager\n function balanceOf(address account) public view returns (uint256) {\n return deposits[account].deposit;\n }\n\n receive() external payable {\n depositTo(msg.sender);\n }\n\n\n /**\n * Increments an account's deposit.\n * @param account - The account to increment.\n * @param amount - The amount to increment by.\n * @return the updated deposit of this account\n */\n function _incrementDeposit(address account, uint256 amount) internal returns (uint256) {\n unchecked {\n DepositInfo storage info = deposits[account];\n uint256 newAmount = info.deposit + amount;\n info.deposit = newAmount;\n return newAmount;\n }\n }\n\n /**\n * Try to decrement the account's deposit.\n * @param account - The account to decrement.\n * @param amount - The amount to decrement by.\n * @return true if the decrement succeeded (that is, previous balance was at least that amount)\n */\n function _tryDecrementDeposit(address account, uint256 amount) internal returns(bool) {\n unchecked {\n DepositInfo storage info = deposits[account];\n uint256 currentDeposit = info.deposit;\n if (currentDeposit < amount) {\n return false;\n }\n info.deposit = currentDeposit - amount;\n return true;\n }\n }\n\n /// @inheritdoc IStakeManager\n function depositTo(address account) public virtual payable {\n uint256 newDeposit = _incrementDeposit(account, msg.value);\n emit Deposited(account, newDeposit);\n }\n\n /// @inheritdoc IStakeManager\n function addStake(uint32 unstakeDelaySec) external payable {\n DepositInfo storage info = deposits[msg.sender];\n require(unstakeDelaySec > 0, \"must specify unstake delay\");\n require(\n unstakeDelaySec >= info.unstakeDelaySec,\n \"cannot decrease unstake time\"\n );\n uint256 stake = info.stake + msg.value;\n require(stake > 0, \"no stake specified\");\n require(stake <= type(uint112).max, \"stake overflow\");\n deposits[msg.sender] = DepositInfo(\n info.deposit,\n true,\n uint112(stake),\n unstakeDelaySec,\n 0\n );\n emit StakeLocked(msg.sender, stake, unstakeDelaySec);\n }\n\n /// @inheritdoc IStakeManager\n function unlockStake() external {\n DepositInfo storage info = deposits[msg.sender];\n require(info.unstakeDelaySec != 0, \"not staked\");\n require(info.staked, \"already unstaking\");\n uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;\n info.withdrawTime = withdrawTime;\n info.staked = false;\n emit StakeUnlocked(msg.sender, withdrawTime);\n }\n\n /// @inheritdoc IStakeManager\n function withdrawStake(address payable withdrawAddress) external {\n DepositInfo storage info = deposits[msg.sender];\n uint256 stake = info.stake;\n require(stake > 0, \"No stake to withdraw\");\n require(info.withdrawTime > 0, \"must call unlockStake() first\");\n require(\n info.withdrawTime <= block.timestamp,\n \"Stake withdrawal is not due\"\n );\n info.unstakeDelaySec = 0;\n info.withdrawTime = 0;\n info.stake = 0;\n emit StakeWithdrawn(msg.sender, withdrawAddress, stake);\n (bool success,) = withdrawAddress.call{value: stake}(\"\");\n require(success, \"failed to withdraw stake\");\n }\n\n /// @inheritdoc IStakeManager\n function withdrawTo(\n address payable withdrawAddress,\n uint256 withdrawAmount\n ) external {\n DepositInfo storage info = deposits[msg.sender];\n uint256 currentDeposit = info.deposit;\n require(withdrawAmount <= currentDeposit, \"Withdraw amount too large\");\n info.deposit = currentDeposit - withdrawAmount;\n emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);\n (bool success,) = withdrawAddress.call{value: withdrawAmount}(\"\");\n require(success, \"failed to withdraw\");\n }\n}\n" + }, "@account-abstraction/contracts/core/UserOperationLib.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/PackedUserOperation.sol\";\nimport {calldataKeccak, min} from \"./Helpers.sol\";\n\n/**\n * Utility functions helpful when working with UserOperation structs.\n */\nlibrary UserOperationLib {\n\n uint256 public constant PAYMASTER_VALIDATION_GAS_OFFSET = 20;\n uint256 public constant PAYMASTER_POSTOP_GAS_OFFSET = 36;\n uint256 public constant PAYMASTER_DATA_OFFSET = 52;\n\n /**\n * Relayer/block builder might submit the TX with higher priorityFee,\n * but the user should not pay above what he signed for.\n * @param userOp - The user operation data.\n */\n function gasPrice(\n PackedUserOperation calldata userOp\n ) internal view returns (uint256) {\n unchecked {\n (uint256 maxPriorityFeePerGas, uint256 maxFeePerGas) = unpackUints(userOp.gasFees);\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n bytes32 internal constant PACKED_USEROP_TYPEHASH =\n keccak256(\n \"PackedUserOperation(address sender,uint256 nonce,bytes initCode,bytes callData,bytes32 accountGasLimits,uint256 preVerificationGas,bytes32 gasFees,bytes paymasterAndData)\"\n );\n\n /**\n * Pack the user operation data into bytes for hashing.\n * @param userOp - The user operation data.\n * @param overrideInitCodeHash - If set, encode this instead of the initCode field in the userOp.\n */\n function encode(\n PackedUserOperation calldata userOp,\n bytes32 overrideInitCodeHash\n ) internal pure returns (bytes memory ret) {\n address sender = userOp.sender;\n uint256 nonce = userOp.nonce;\n bytes32 hashInitCode = overrideInitCodeHash != 0 ? overrideInitCodeHash : calldataKeccak(userOp.initCode);\n bytes32 hashCallData = calldataKeccak(userOp.callData);\n bytes32 accountGasLimits = userOp.accountGasLimits;\n uint256 preVerificationGas = userOp.preVerificationGas;\n bytes32 gasFees = userOp.gasFees;\n bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);\n\n return abi.encode(\n UserOperationLib.PACKED_USEROP_TYPEHASH,\n sender, nonce,\n hashInitCode, hashCallData,\n accountGasLimits, preVerificationGas, gasFees,\n hashPaymasterAndData\n );\n }\n\n function unpackUints(\n bytes32 packed\n ) internal pure returns (uint256 high128, uint256 low128) {\n return (unpackHigh128(packed), unpackLow128(packed));\n }\n\n // Unpack just the high 128-bits from a packed value\n function unpackHigh128(bytes32 packed) internal pure returns (uint256) {\n return uint256(packed) >> 128;\n }\n\n // Unpack just the low 128-bits from a packed value\n function unpackLow128(bytes32 packed) internal pure returns (uint256) {\n return uint128(uint256(packed));\n }\n\n function unpackMaxPriorityFeePerGas(PackedUserOperation calldata userOp)\n internal pure returns (uint256) {\n return unpackHigh128(userOp.gasFees);\n }\n\n function unpackMaxFeePerGas(PackedUserOperation calldata userOp)\n internal pure returns (uint256) {\n return unpackLow128(userOp.gasFees);\n }\n\n function unpackVerificationGasLimit(PackedUserOperation calldata userOp)\n internal pure returns (uint256) {\n return unpackHigh128(userOp.accountGasLimits);\n }\n\n function unpackCallGasLimit(PackedUserOperation calldata userOp)\n internal pure returns (uint256) {\n return unpackLow128(userOp.accountGasLimits);\n }\n\n function unpackPaymasterVerificationGasLimit(PackedUserOperation calldata userOp)\n internal pure returns (uint256) {\n return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET]));\n }\n\n function unpackPostOpGasLimit(PackedUserOperation calldata userOp)\n internal pure returns (uint256) {\n return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_POSTOP_GAS_OFFSET : PAYMASTER_DATA_OFFSET]));\n }\n\n function unpackPaymasterStaticFields(\n bytes calldata paymasterAndData\n ) internal pure returns (address paymaster, uint256 validationGasLimit, uint256 postOpGasLimit) {\n return (\n address(bytes20(paymasterAndData[: PAYMASTER_VALIDATION_GAS_OFFSET])),\n uint128(bytes16(paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET])),\n uint128(bytes16(paymasterAndData[PAYMASTER_POSTOP_GAS_OFFSET : PAYMASTER_DATA_OFFSET]))\n );\n }\n\n /**\n * Hash the user operation data.\n * @param userOp - The user operation data.\n * @param overrideInitCodeHash - If set, the initCode hash will be replaced with this value just for UserOp hashing.\n */\n function hash(\n PackedUserOperation calldata userOp,\n bytes32 overrideInitCodeHash\n ) internal pure returns (bytes32) {\n return keccak256(encode(userOp, overrideInitCodeHash));\n }\n}\n" }, + "@account-abstraction/contracts/interfaces/IAccount.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport \"./PackedUserOperation.sol\";\n\ninterface IAccount {\n /**\n * Validate user's signature and nonce\n * the entryPoint will make the call to the recipient only if this validation call returns successfully.\n * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).\n * This allows making a \"simulation call\" without a valid signature\n * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.\n *\n * @dev Must validate caller is the entryPoint.\n * Must validate the signature and nonce\n * @param userOp - The operation that is about to be executed.\n * @param userOpHash - Hash of the user's request data. can be used as the basis for signature.\n * @param missingAccountFunds - Missing funds on the account's deposit in the entrypoint.\n * This is the minimum amount to transfer to the sender(entryPoint) to be\n * able to make the call. The excess is left as a deposit in the entrypoint\n * for future calls. Can be withdrawn anytime using \"entryPoint.withdrawTo()\".\n * In case there is a paymaster in the request (or the current deposit is high\n * enough), this value will be zero.\n * @return validationData - Packaged ValidationData structure. use `_packValidationData` and\n * `_unpackValidationData` to encode and decode.\n * <20-byte> aggregatorOrSigFail - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"aggregator\" contract.\n * <6-byte> validUntil - Last timestamp this operation is valid at, or 0 for \"indefinitely\"\n * <6-byte> validAfter - First timestamp this operation is valid\n * If an account doesn't use time-range, it is enough to\n * return SIG_VALIDATION_FAILED value (1) for signature failure.\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validateUserOp(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash,\n uint256 missingAccountFunds\n ) external returns (uint256 validationData);\n}\n" + }, + "@account-abstraction/contracts/interfaces/IAccountExecute.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport \"./PackedUserOperation.sol\";\n\ninterface IAccountExecute {\n /**\n * Account may implement this execute method.\n * passing this methodSig at the beginning of callData will cause the entryPoint to pass the full UserOp (and hash)\n * to the account.\n * The account should skip the methodSig, and use the callData (and optionally, other UserOp fields)\n *\n * @param userOp - The operation that was just validated.\n * @param userOpHash - Hash of the user's request data.\n */\n function executeUserOp(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash\n ) external;\n}\n" + }, "@account-abstraction/contracts/interfaces/IAggregator.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport \"./PackedUserOperation.sol\";\n\n/**\n * Aggregated Signatures validator.\n */\ninterface IAggregator {\n /**\n * Validate an aggregated signature.\n * Reverts if the aggregated signature does not match the given list of operations.\n * @param userOps - An array of UserOperations to validate the signature for.\n * @param signature - The aggregated signature.\n */\n function validateSignatures(\n PackedUserOperation[] calldata userOps,\n bytes calldata signature\n ) external;\n\n /**\n * Validate the signature of a single userOp.\n * This method should be called by bundler after EntryPointSimulation.simulateValidation() returns\n * the aggregator this account uses.\n * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.\n * @param userOp - The userOperation received from the user.\n * @return sigForUserOp - The value to put into the signature field of the userOp when calling handleOps.\n * (usually empty, unless account and aggregator support some kind of \"multisig\".\n */\n function validateUserOpSignature(\n PackedUserOperation calldata userOp\n ) external view returns (bytes memory sigForUserOp);\n\n /**\n * Aggregate multiple signatures into a single value.\n * This method is called off-chain to calculate the signature to pass with handleOps()\n * bundler MAY use optimized custom code to perform this aggregation.\n * @param userOps - An array of UserOperations to collect the signatures from.\n * @return aggregatedSignature - The aggregated signature.\n */\n function aggregateSignatures(\n PackedUserOperation[] calldata userOps\n ) external view returns (bytes memory aggregatedSignature);\n}\n" }, @@ -31,35 +52,161 @@ "@account-abstraction/contracts/interfaces/PackedUserOperation.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/**\n * User Operation struct\n * @param sender - The sender account of this request.\n * @param nonce - Unique value the sender uses to verify it is not a replay.\n * @param initCode - If set, the account contract will be created by this constructor\n * @param callData - The method call to execute on this account.\n * @param accountGasLimits - Packed gas limits for validateUserOp and gas limit passed to the callData method call.\n * @param preVerificationGas - Gas not calculated by the handleOps method, but added to the gas paid.\n * Covers batch overhead.\n * @param gasFees - packed gas fields maxPriorityFeePerGas and maxFeePerGas - Same as EIP-1559 gas parameters.\n * @param paymasterAndData - If set, this field holds the paymaster address, verification gas limit, postOp gas limit and paymaster-specific extra data\n * The paymaster will pay for the transaction instead of the sender.\n * @param signature - Sender-verified signature over the entire request, the EntryPoint address and the chain ID.\n */\nstruct PackedUserOperation {\n address sender;\n uint256 nonce;\n bytes initCode;\n bytes callData;\n bytes32 accountGasLimits;\n uint256 preVerificationGas;\n bytes32 gasFees;\n bytes paymasterAndData;\n bytes signature;\n}\n" }, + "@account-abstraction/contracts/utils/Exec.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n// solhint-disable no-inline-assembly\n\n/**\n * Utility functions helpful when making different kinds of contract calls in Solidity.\n */\nlibrary Exec {\n\n function call(\n address to,\n uint256 value,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly (\"memory-safe\") {\n success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function staticcall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal view returns (bool success) {\n assembly (\"memory-safe\") {\n success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function delegateCall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly (\"memory-safe\") {\n success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n // get returned data from last call or delegateCall\n // maxLen - maximum length of data to return, or zero, for the full length\n function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {\n assembly (\"memory-safe\") {\n let len := returndatasize()\n if gt(maxLen,0) {\n if gt(len, maxLen) {\n len := maxLen\n }\n }\n let ptr := mload(0x40)\n mstore(0x40, add(ptr, add(len, 0x20)))\n mstore(ptr, len)\n returndatacopy(add(ptr, 0x20), 0, len)\n returnData := ptr\n }\n }\n\n // revert with explicit byte array (probably reverted info from call)\n function revertWithData(bytes memory returnData) internal pure {\n assembly (\"memory-safe\") {\n revert(add(returnData, 32), mload(returnData))\n }\n }\n\n // Propagate revert data from last call\n function revertWithReturnData() internal pure {\n revertWithData(getReturnData(0));\n }\n}\n" + }, "@openzeppelin/contracts/access/Ownable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n constructor(address initialOwner) {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" }, "@openzeppelin/contracts/access/Ownable2Step.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.20;\n\nimport {Ownable} from \"./Ownable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * This extension of the {Ownable} contract includes a two-step mechanism to transfer\n * ownership, where the new owner must call {acceptOwnership} in order to replace the\n * old one. This can help prevent common mistakes, such as transfers of ownership to\n * incorrect accounts, or to contracts that are unable to interact with the\n * permission system.\n *\n * The initial owner is specified at deployment time in the constructor for `Ownable`. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2Step is Ownable {\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n *\n * Setting `newOwner` to the zero address is allowed; this can be used to cancel an initiated ownership transfer.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n if (pendingOwner() != sender) {\n revert OwnableUnauthorizedAccount(sender);\n }\n _transferOwnership(sender);\n }\n}\n" }, - "@openzeppelin/contracts/proxy/Clones.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (proxy/Clones.sol)\n\npragma solidity ^0.8.20;\n\nimport {Create2} from \"../utils/Create2.sol\";\nimport {Errors} from \"../utils/Errors.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-1167[ERC-1167] is a standard for\n * deploying minimal proxy contracts, also known as \"clones\".\n *\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\n *\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\n * deterministic method.\n */\nlibrary Clones {\n error CloneArgumentsTooLong();\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation`.\n *\n * This function uses the create opcode, which should never revert.\n *\n * WARNING: This function does not check if `implementation` has code. A clone that points to an address\n * without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they\n * have no effect and leave the clone uninitialized, allowing a third party to initialize it later.\n */\n function clone(address implementation) internal returns (address instance) {\n return clone(implementation, 0);\n }\n\n /**\n * @dev Same as {xref-Clones-clone-address-}[clone], but with a `value` parameter to send native currency\n * to the new contract.\n *\n * WARNING: This function does not check if `implementation` has code. A clone that points to an address\n * without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they\n * have no effect and leave the clone uninitialized, allowing a third party to initialize it later.\n *\n * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)\n * to always have enough balance for new deployments. Consider exposing this function under a payable method.\n */\n function clone(address implementation, uint256 value) internal returns (address instance) {\n if (address(this).balance < value) {\n revert Errors.InsufficientBalance(address(this).balance, value);\n }\n assembly (\"memory-safe\") {\n // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes\n // of the `implementation` address with the bytecode before the address.\n mstore(0x00, or(shr(232, shl(96, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))\n // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.\n mstore(0x20, or(shl(120, implementation), 0x5af43d82803e903d91602b57fd5bf3))\n instance := create(value, 0x09, 0x37)\n }\n if (instance == address(0)) {\n revert Errors.FailedDeployment();\n }\n }\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation`.\n *\n * This function uses the create2 opcode and a `salt` to deterministically deploy\n * the clone. Using the same `implementation` and `salt` multiple times will revert, since\n * the clones cannot be deployed twice at the same address.\n *\n * WARNING: This function does not check if `implementation` has code. A clone that points to an address\n * without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they\n * have no effect and leave the clone uninitialized, allowing a third party to initialize it later.\n */\n function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {\n return cloneDeterministic(implementation, salt, 0);\n }\n\n /**\n * @dev Same as {xref-Clones-cloneDeterministic-address-bytes32-}[cloneDeterministic], but with\n * a `value` parameter to send native currency to the new contract.\n *\n * WARNING: This function does not check if `implementation` has code. A clone that points to an address\n * without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they\n * have no effect and leave the clone uninitialized, allowing a third party to initialize it later.\n *\n * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)\n * to always have enough balance for new deployments. Consider exposing this function under a payable method.\n */\n function cloneDeterministic(\n address implementation,\n bytes32 salt,\n uint256 value\n ) internal returns (address instance) {\n if (address(this).balance < value) {\n revert Errors.InsufficientBalance(address(this).balance, value);\n }\n assembly (\"memory-safe\") {\n // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes\n // of the `implementation` address with the bytecode before the address.\n mstore(0x00, or(shr(232, shl(96, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))\n // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.\n mstore(0x20, or(shl(120, implementation), 0x5af43d82803e903d91602b57fd5bf3))\n instance := create2(value, 0x09, 0x37, salt)\n }\n if (instance == address(0)) {\n revert Errors.FailedDeployment();\n }\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(\n address implementation,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n assembly (\"memory-safe\") {\n let ptr := mload(0x40)\n mstore(add(ptr, 0x38), deployer)\n mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff)\n mstore(add(ptr, 0x14), implementation)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73)\n mstore(add(ptr, 0x58), salt)\n mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37))\n predicted := and(keccak256(add(ptr, 0x43), 0x55), 0xffffffffffffffffffffffffffffffffffffffff)\n }\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(\n address implementation,\n bytes32 salt\n ) internal view returns (address predicted) {\n return predictDeterministicAddress(implementation, salt, address(this));\n }\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation` with custom\n * immutable arguments. These are provided through `args` and cannot be changed after deployment. To\n * access the arguments within the implementation, use {fetchCloneArgs}.\n *\n * This function uses the create opcode, which should never revert.\n *\n * WARNING: This function does not check if `implementation` has code. A clone that points to an address\n * without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they\n * have no effect and leave the clone uninitialized, allowing a third party to initialize it later.\n */\n function cloneWithImmutableArgs(address implementation, bytes memory args) internal returns (address instance) {\n return cloneWithImmutableArgs(implementation, args, 0);\n }\n\n /**\n * @dev Same as {xref-Clones-cloneWithImmutableArgs-address-bytes-}[cloneWithImmutableArgs], but with a `value`\n * parameter to send native currency to the new contract.\n *\n * WARNING: This function does not check if `implementation` has code. A clone that points to an address\n * without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they\n * have no effect and leave the clone uninitialized, allowing a third party to initialize it later.\n *\n * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)\n * to always have enough balance for new deployments. Consider exposing this function under a payable method.\n */\n function cloneWithImmutableArgs(\n address implementation,\n bytes memory args,\n uint256 value\n ) internal returns (address instance) {\n if (address(this).balance < value) {\n revert Errors.InsufficientBalance(address(this).balance, value);\n }\n bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args);\n assembly (\"memory-safe\") {\n instance := create(value, add(bytecode, 0x20), mload(bytecode))\n }\n if (instance == address(0)) {\n revert Errors.FailedDeployment();\n }\n }\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation` with custom\n * immutable arguments. These are provided through `args` and cannot be changed after deployment. To\n * access the arguments within the implementation, use {fetchCloneArgs}.\n *\n * This function uses the create2 opcode and a `salt` to deterministically deploy the clone. Using the same\n * `implementation`, `args` and `salt` multiple times will revert, since the clones cannot be deployed twice\n * at the same address.\n *\n * WARNING: This function does not check if `implementation` has code. A clone that points to an address\n * without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they\n * have no effect and leave the clone uninitialized, allowing a third party to initialize it later.\n */\n function cloneDeterministicWithImmutableArgs(\n address implementation,\n bytes memory args,\n bytes32 salt\n ) internal returns (address instance) {\n return cloneDeterministicWithImmutableArgs(implementation, args, salt, 0);\n }\n\n /**\n * @dev Same as {xref-Clones-cloneDeterministicWithImmutableArgs-address-bytes-bytes32-}[cloneDeterministicWithImmutableArgs],\n * but with a `value` parameter to send native currency to the new contract.\n *\n * WARNING: This function does not check if `implementation` has code. A clone that points to an address\n * without code cannot be initialized. Initialization calls may appear to be successful when, in reality, they\n * have no effect and leave the clone uninitialized, allowing a third party to initialize it later.\n *\n * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)\n * to always have enough balance for new deployments. Consider exposing this function under a payable method.\n */\n function cloneDeterministicWithImmutableArgs(\n address implementation,\n bytes memory args,\n bytes32 salt,\n uint256 value\n ) internal returns (address instance) {\n bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args);\n return Create2.deploy(value, salt, bytecode);\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministicWithImmutableArgs}.\n */\n function predictDeterministicAddressWithImmutableArgs(\n address implementation,\n bytes memory args,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args);\n return Create2.computeAddress(salt, keccak256(bytecode), deployer);\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministicWithImmutableArgs}.\n */\n function predictDeterministicAddressWithImmutableArgs(\n address implementation,\n bytes memory args,\n bytes32 salt\n ) internal view returns (address predicted) {\n return predictDeterministicAddressWithImmutableArgs(implementation, args, salt, address(this));\n }\n\n /**\n * @dev Get the immutable args attached to a clone.\n *\n * - If `instance` is a clone that was deployed using `clone` or `cloneDeterministic`, this\n * function will return an empty array.\n * - If `instance` is a clone that was deployed using `cloneWithImmutableArgs` or\n * `cloneDeterministicWithImmutableArgs`, this function will return the args array used at\n * creation.\n * - If `instance` is NOT a clone deployed using this library, the behavior is undefined. This\n * function should only be used to check addresses that are known to be clones.\n */\n function fetchCloneArgs(address instance) internal view returns (bytes memory) {\n bytes memory result = new bytes(instance.code.length - 0x2d); // revert if length is too short\n assembly (\"memory-safe\") {\n extcodecopy(instance, add(result, 0x20), 0x2d, mload(result))\n }\n return result;\n }\n\n /**\n * @dev Helper that prepares the initcode of the proxy with immutable args.\n *\n * An assembly variant of this function requires copying the `args` array, which can be efficiently done using\n * `mcopy`. Unfortunately, that opcode is not available before cancun. A pure solidity implementation using\n * abi.encodePacked is more expensive but also more portable and easier to review.\n *\n * NOTE: https://eips.ethereum.org/EIPS/eip-170[EIP-170] limits the length of the contract code to 24576 bytes.\n * With the proxy code taking 45 bytes, that limits the length of the immutable args to 24531 bytes.\n */\n function _cloneCodeWithImmutableArgs(\n address implementation,\n bytes memory args\n ) private pure returns (bytes memory) {\n if (args.length > 0x5fd3) revert CloneArgumentsTooLong();\n return\n abi.encodePacked(\n hex\"61\",\n uint16(args.length + 0x2d),\n hex\"3d81600a3d39f3363d3d373d3d3d363d73\",\n implementation,\n hex\"5af43d82803e903d91602b57fd5bf3\",\n args\n );\n }\n}\n" + "@openzeppelin/contracts/account/Account.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (account/Account.sol)\n\npragma solidity ^0.8.20;\n\nimport {PackedUserOperation, IAccount, IEntryPoint} from \"../interfaces/draft-IERC4337.sol\";\nimport {ERC4337Utils} from \"./utils/draft-ERC4337Utils.sol\";\nimport {AbstractSigner} from \"../utils/cryptography/signers/AbstractSigner.sol\";\nimport {LowLevelCall} from \"../utils/LowLevelCall.sol\";\n\n/**\n * @dev A simple ERC4337 account implementation. This base implementation only includes the minimal logic to process\n * user operations.\n *\n * Developers must implement the {AbstractSigner-_rawSignatureValidation} function to define the account's validation logic.\n *\n * NOTE: This core account doesn't include any mechanism for performing arbitrary external calls. This is an essential\n * feature that all Account should have. We leave it up to the developers to implement the mechanism of their choice.\n * Common choices include ERC-6900, ERC-7579 and ERC-7821 (among others).\n *\n * IMPORTANT: Implementing a mechanism to validate signatures is a security-sensitive operation as it may allow an\n * attacker to bypass the account's security measures. Check out {SignerECDSA}, {SignerP256}, or {SignerRSA} for\n * digital signature validation implementations.\n *\n * @custom:stateless\n */\nabstract contract Account is AbstractSigner, IAccount {\n /**\n * @dev Unauthorized call to the account.\n */\n error AccountUnauthorized(address sender);\n\n /**\n * @dev Revert if the caller is not the entry point or the account itself.\n */\n modifier onlyEntryPointOrSelf() {\n _checkEntryPointOrSelf();\n _;\n }\n\n /**\n * @dev Revert if the caller is not the entry point.\n */\n modifier onlyEntryPoint() {\n _checkEntryPoint();\n _;\n }\n\n /**\n * @dev Canonical entry point for the account that forwards and validates user operations.\n */\n function entryPoint() public view virtual returns (IEntryPoint) {\n return ERC4337Utils.ENTRYPOINT_V09;\n }\n\n /**\n * @dev Return the account nonce for the canonical sequence.\n */\n function getNonce() public view virtual returns (uint256) {\n return getNonce(0);\n }\n\n /**\n * @dev Return the account nonce for a given sequence (key).\n */\n function getNonce(uint192 key) public view virtual returns (uint256) {\n return entryPoint().getNonce(address(this), key);\n }\n\n /**\n * @inheritdoc IAccount\n */\n function validateUserOp(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash,\n uint256 missingAccountFunds\n ) public virtual onlyEntryPoint returns (uint256) {\n uint256 validationData = _validateUserOp(userOp, userOpHash, userOp.signature);\n _payPrefund(missingAccountFunds);\n return validationData;\n }\n\n /**\n * @dev Returns the validationData for a given user operation. By default, this checks the signature of the\n * signable hash (produced by {_signableUserOpHash}) using the abstract signer ({AbstractSigner-_rawSignatureValidation}).\n *\n * The `signature` parameter is taken directly from the user operation's `signature` field.\n * This design enables derived contracts to implement custom signature handling logic,\n * such as embedding additional data within the signature and processing it by overriding this function\n * and optionally invoking `super`.\n *\n * NOTE: The userOpHash is assumed to be correct. Calling this function with a userOpHash that does not match the\n * userOp will result in undefined behavior.\n */\n function _validateUserOp(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash,\n bytes calldata signature\n ) internal virtual returns (uint256) {\n return\n _rawSignatureValidation(_signableUserOpHash(userOp, userOpHash), signature)\n ? ERC4337Utils.SIG_VALIDATION_SUCCESS\n : ERC4337Utils.SIG_VALIDATION_FAILED;\n }\n\n /**\n * @dev Virtual function that returns the signable hash for a user operations. Since v0.8.0 of the entrypoint,\n * `userOpHash` is an EIP-712 hash that can be signed directly.\n */\n function _signableUserOpHash(\n PackedUserOperation calldata /*userOp*/,\n bytes32 userOpHash\n ) internal view virtual returns (bytes32) {\n return userOpHash;\n }\n\n /**\n * @dev Sends the missing funds for executing the user operation to the {entrypoint}.\n * The `missingAccountFunds` must be defined by the entrypoint when calling {validateUserOp}.\n */\n function _payPrefund(uint256 missingAccountFunds) internal virtual {\n if (missingAccountFunds > 0) {\n LowLevelCall.callNoReturn(msg.sender, missingAccountFunds, \"\"); // The entrypoint should validate the result.\n }\n }\n\n /**\n * @dev Ensures the caller is the {entrypoint}.\n */\n function _checkEntryPoint() internal view virtual {\n address sender = msg.sender;\n if (sender != address(entryPoint())) {\n revert AccountUnauthorized(sender);\n }\n }\n\n /**\n * @dev Ensures the caller is the {entrypoint} or the account itself.\n */\n function _checkEntryPointOrSelf() internal view virtual {\n address sender = msg.sender;\n if (sender != address(this) && sender != address(entryPoint())) {\n revert AccountUnauthorized(sender);\n }\n }\n\n /**\n * @dev Receive Ether.\n */\n receive() external payable virtual {}\n}\n" + }, + "@openzeppelin/contracts/account/extensions/draft-ERC7821.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (account/extensions/draft-ERC7821.sol)\n\npragma solidity ^0.8.20;\n\nimport {ERC7579Utils, Mode, CallType, ExecType, ModeSelector} from \"../utils/draft-ERC7579Utils.sol\";\nimport {IERC7821} from \"../../interfaces/draft-IERC7821.sol\";\nimport {Account} from \"../Account.sol\";\n\n/**\n * @dev Minimal batch executor following ERC-7821.\n *\n * Only supports single batch mode (`0x01000000000000000000`). Does not support optional \"opData\".\n *\n * @custom:stateless\n */\nabstract contract ERC7821 is IERC7821 {\n using ERC7579Utils for *;\n\n error UnsupportedExecutionMode();\n\n /**\n * @dev Executes the calls in `executionData` with no optional `opData` support.\n *\n * NOTE: Access to this function is controlled by {_erc7821AuthorizedExecutor}. Changing access permissions, for\n * example to approve calls by the ERC-4337 entrypoint, should be implemented by overriding it.\n *\n * Reverts and bubbles up error if any call fails.\n */\n function execute(bytes32 mode, bytes calldata executionData) public payable virtual {\n if (!_erc7821AuthorizedExecutor(msg.sender, mode, executionData))\n revert Account.AccountUnauthorized(msg.sender);\n if (!supportsExecutionMode(mode)) revert UnsupportedExecutionMode();\n executionData.execBatch(ERC7579Utils.EXECTYPE_DEFAULT);\n }\n\n /// @inheritdoc IERC7821\n function supportsExecutionMode(bytes32 mode) public view virtual returns (bool result) {\n (CallType callType, ExecType execType, ModeSelector modeSelector, ) = Mode.wrap(mode).decodeMode();\n return\n callType == ERC7579Utils.CALLTYPE_BATCH &&\n execType == ERC7579Utils.EXECTYPE_DEFAULT &&\n modeSelector == ModeSelector.wrap(0x00000000);\n }\n\n /**\n * @dev Access control mechanism for the {execute} function.\n * By default, only the contract itself is allowed to execute.\n *\n * Override this function to implement custom access control, for example to allow the\n * ERC-4337 entrypoint to execute.\n *\n * ```solidity\n * function _erc7821AuthorizedExecutor(\n * address caller,\n * bytes32 mode,\n * bytes calldata executionData\n * ) internal view virtual override returns (bool) {\n * return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData);\n * }\n * ```\n */\n function _erc7821AuthorizedExecutor(\n address caller,\n bytes32 /* mode */,\n bytes calldata /* executionData */\n ) internal view virtual returns (bool) {\n return caller == address(this);\n }\n}\n" + }, + "@openzeppelin/contracts/account/utils/draft-ERC4337Utils.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (account/utils/draft-ERC4337Utils.sol)\n\npragma solidity ^0.8.20;\n\nimport {IEntryPoint, PackedUserOperation} from \"../../interfaces/draft-IERC4337.sol\";\nimport {Math} from \"../../utils/math/Math.sol\";\nimport {Calldata} from \"../../utils/Calldata.sol\";\nimport {Packing} from \"../../utils/Packing.sol\";\n\n/// @dev This is available on all entrypoint since v0.4.0, but is not formally part of the ERC.\ninterface IEntryPointExtra {\n function getUserOpHash(PackedUserOperation calldata userOp) external view returns (bytes32);\n}\n\n/**\n * @dev Library with common ERC-4337 utility functions.\n *\n * See https://eips.ethereum.org/EIPS/eip-4337[ERC-4337].\n */\nlibrary ERC4337Utils {\n using Packing for *;\n\n /// @dev Address of the entrypoint v0.7.0\n IEntryPoint internal constant ENTRYPOINT_V07 = IEntryPoint(0x0000000071727De22E5E9d8BAf0edAc6f37da032);\n\n /// @dev Address of the entrypoint v0.8.0\n IEntryPoint internal constant ENTRYPOINT_V08 = IEntryPoint(0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108);\n\n /// @dev Address of the entrypoint v0.9.0\n IEntryPoint internal constant ENTRYPOINT_V09 = IEntryPoint(0x433709009B8330FDa32311DF1C2AFA402eD8D009);\n\n /// @dev For simulation purposes, validateUserOp (and validatePaymasterUserOp) return this value on success.\n uint256 internal constant SIG_VALIDATION_SUCCESS = 0;\n\n /// @dev For simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value in case of signature failure, instead of revert.\n uint256 internal constant SIG_VALIDATION_FAILED = 1;\n\n /// @dev Magic value used in EntryPoint v0.9+ to detect the presence of a paymaster signature in `paymasterAndData`.\n bytes8 internal constant PAYMASTER_SIG_MAGIC = 0x22e325a297439656; // keccak256(\"PaymasterSignature\")[:8]\n\n /// @dev Highest bit set to 1 in a 6-bytes field.\n uint48 internal constant BLOCK_RANGE_FLAG = 0x800000000000;\n\n /// @dev Mask for the lower 47 bits of a 6-bytes field (equivalent to uint48(~BLOCK_RANGE_FLAG)).\n uint48 internal constant BLOCK_RANGE_MASK = 0x7fffffffffff;\n\n /// @dev Validity range of the validation data.\n enum ValidationRange {\n TIMESTAMP,\n BLOCK\n }\n\n /**\n * @dev Parses the validation data into its components and the validity range. See {packValidationData}.\n * Strips away the highest bit flag from the `validAfter` and `validUntil` fields.\n */\n function parseValidationData(\n uint256 validationData\n ) internal pure returns (address aggregator, uint48 validAfter, uint48 validUntil, ValidationRange range) {\n validAfter = uint48(bytes32(validationData).extract_32_6(0));\n validUntil = uint48(bytes32(validationData).extract_32_6(6));\n aggregator = address(bytes32(validationData).extract_32_20(12));\n range = ((validAfter & validUntil & BLOCK_RANGE_FLAG) == 0) ? ValidationRange.TIMESTAMP : ValidationRange.BLOCK;\n\n validAfter &= BLOCK_RANGE_MASK;\n validUntil &= BLOCK_RANGE_MASK;\n\n if (validUntil == 0) validUntil = BLOCK_RANGE_MASK;\n }\n\n /// @dev Packs the validation data into a single uint256. See {parseValidationData}.\n function packValidationData(\n address aggregator,\n uint48 validAfter,\n uint48 validUntil\n ) internal pure returns (uint256) {\n return\n packValidationData(\n aggregator,\n validAfter,\n validUntil,\n (validAfter & validUntil & BLOCK_RANGE_FLAG) == 0 ? ValidationRange.TIMESTAMP : ValidationRange.BLOCK\n );\n }\n\n /**\n * @dev Variant of {packValidationData} that forces which validity range to use. This overwrites the presence of\n * flags in `validAfter` and `validUntil`).\n */\n function packValidationData(\n address aggregator,\n uint48 validAfter,\n uint48 validUntil,\n ValidationRange range\n ) internal pure returns (uint256) {\n if (range == ValidationRange.TIMESTAMP) {\n validAfter &= BLOCK_RANGE_MASK;\n validUntil &= BLOCK_RANGE_MASK;\n } else if (range == ValidationRange.BLOCK) {\n validAfter |= BLOCK_RANGE_FLAG;\n validUntil |= BLOCK_RANGE_FLAG;\n }\n return uint256(bytes6(validAfter).pack_6_6(bytes6(validUntil)).pack_12_20(bytes20(aggregator)));\n }\n\n /// @dev Variant of {packValidationData} that uses a boolean success flag instead of an aggregator address.\n function packValidationData(bool sigSuccess, uint48 validAfter, uint48 validUntil) internal pure returns (uint256) {\n return\n packValidationData(\n address(uint160(Math.ternary(sigSuccess, SIG_VALIDATION_SUCCESS, SIG_VALIDATION_FAILED))),\n validAfter,\n validUntil\n );\n }\n\n /**\n * @dev Variant of {packValidationData} that uses a boolean success flag instead of an aggregator address and that\n * forces which validity range to use. This overwrites the presence of flags in `validAfter` and `validUntil`).\n */\n function packValidationData(\n bool sigSuccess,\n uint48 validAfter,\n uint48 validUntil,\n ValidationRange range\n ) internal pure returns (uint256) {\n return\n packValidationData(\n address(uint160(Math.ternary(sigSuccess, SIG_VALIDATION_SUCCESS, SIG_VALIDATION_FAILED))),\n validAfter,\n validUntil,\n range\n );\n }\n\n /**\n * @dev Combines two validation data into a single one.\n *\n * The `aggregator` is set to {SIG_VALIDATION_SUCCESS} if both are successful, while\n * the `validAfter` is the maximum and the `validUntil` is the minimum of both.\n *\n * NOTE: Returns `SIG_VALIDATION_FAILED` if the validation ranges differ.\n */\n function combineValidationData(uint256 validationData1, uint256 validationData2) internal pure returns (uint256) {\n (address aggregator1, uint48 validAfter1, uint48 validUntil1, ValidationRange range1) = parseValidationData(\n validationData1\n );\n (address aggregator2, uint48 validAfter2, uint48 validUntil2, ValidationRange range2) = parseValidationData(\n validationData2\n );\n\n if (range1 == range2) {\n bool success = aggregator1 == address(uint160(SIG_VALIDATION_SUCCESS)) &&\n aggregator2 == address(uint160(SIG_VALIDATION_SUCCESS));\n uint48 validAfter = uint48(Math.max(validAfter1, validAfter2));\n uint48 validUntil = uint48(Math.min(validUntil1, validUntil2));\n return packValidationData(success, validAfter, validUntil, range1);\n } else {\n return SIG_VALIDATION_FAILED;\n }\n }\n\n /// @dev Returns the aggregator of the `validationData` and whether it is out of time range.\n function getValidationData(uint256 validationData) internal view returns (address aggregator, bool outOfTimeRange) {\n (address aggregator_, uint48 validAfter, uint48 validUntil, ValidationRange range) = parseValidationData(\n validationData\n );\n uint256 current = Math.ternary(range == ValidationRange.TIMESTAMP, block.timestamp, block.number);\n return (aggregator_, current <= validAfter || validUntil < current);\n }\n\n /// @dev Get the hash of a user operation for a given entrypoint\n function hash(PackedUserOperation calldata self, address entrypoint) internal view returns (bytes32) {\n // NOTE: getUserOpHash is available since v0.4.0\n //\n // Prior to v0.8.0, this was easy to replicate for any entrypoint and chainId. Since v0.8.0 of the\n // entrypoint, this depends on the Entrypoint's domain separator, which cannot be hardcoded and is complex\n // to recompute. Domain separator could be fetch using the `getDomainSeparatorV4` getter, or recomputed from\n // the ERC-5267 getter, but both operation would require doing a view call to the entrypoint. Overall it feels\n // simpler and less error prone to get that functionality from the entrypoint directly.\n return IEntryPointExtra(entrypoint).getUserOpHash(self);\n }\n\n /// @dev Returns `factory` from the {PackedUserOperation}, or address(0) if the initCode is empty or not properly formatted.\n function factory(PackedUserOperation calldata self) internal pure returns (address) {\n return self.initCode.length < 20 ? address(0) : address(bytes20(self.initCode[0:20]));\n }\n\n /// @dev Returns `factoryData` from the {PackedUserOperation}, or empty bytes if the initCode is empty or not properly formatted.\n function factoryData(PackedUserOperation calldata self) internal pure returns (bytes calldata) {\n return self.initCode.length < 20 ? Calldata.emptyBytes() : self.initCode[20:];\n }\n\n /// @dev Returns `verificationGasLimit` from the {PackedUserOperation}.\n function verificationGasLimit(PackedUserOperation calldata self) internal pure returns (uint256) {\n return uint128(self.accountGasLimits.extract_32_16(0));\n }\n\n /// @dev Returns `callGasLimit` from the {PackedUserOperation}.\n function callGasLimit(PackedUserOperation calldata self) internal pure returns (uint256) {\n return uint128(self.accountGasLimits.extract_32_16(16));\n }\n\n /// @dev Returns the first section of `gasFees` from the {PackedUserOperation}.\n function maxPriorityFeePerGas(PackedUserOperation calldata self) internal pure returns (uint256) {\n return uint128(self.gasFees.extract_32_16(0));\n }\n\n /// @dev Returns the second section of `gasFees` from the {PackedUserOperation}.\n function maxFeePerGas(PackedUserOperation calldata self) internal pure returns (uint256) {\n return uint128(self.gasFees.extract_32_16(16));\n }\n\n /// @dev Returns the total gas price for the {PackedUserOperation} (ie. `maxFeePerGas` or `maxPriorityFeePerGas + basefee`).\n function gasPrice(PackedUserOperation calldata self) internal view returns (uint256) {\n unchecked {\n // Following values are \"per gas\"\n uint256 maxPriorityFee = maxPriorityFeePerGas(self);\n uint256 maxFee = maxFeePerGas(self);\n return Math.min(maxFee, maxPriorityFee + block.basefee);\n }\n }\n\n /// @dev Returns the first section of `paymasterAndData` from the {PackedUserOperation}.\n function paymaster(PackedUserOperation calldata self) internal pure returns (address) {\n return self.paymasterAndData.length < 52 ? address(0) : address(bytes20(self.paymasterAndData[0:20]));\n }\n\n /// @dev Returns the second section of `paymasterAndData` from the {PackedUserOperation}.\n function paymasterVerificationGasLimit(PackedUserOperation calldata self) internal pure returns (uint256) {\n return self.paymasterAndData.length < 52 ? 0 : uint128(bytes16(self.paymasterAndData[20:36]));\n }\n\n /// @dev Returns the third section of `paymasterAndData` from the {PackedUserOperation}.\n function paymasterPostOpGasLimit(PackedUserOperation calldata self) internal pure returns (uint256) {\n return self.paymasterAndData.length < 52 ? 0 : uint128(bytes16(self.paymasterAndData[36:52]));\n }\n\n /**\n * @dev Returns the fourth section of `paymasterAndData` from the {PackedUserOperation}.\n * If a paymaster signature is present, it is excluded from the returned data.\n */\n function paymasterData(PackedUserOperation calldata self) internal pure returns (bytes calldata) {\n bool hasSignature = self.paymasterAndData.length > 9 &&\n bytes8(self.paymasterAndData[self.paymasterAndData.length - 8:]) == PAYMASTER_SIG_MAGIC;\n uint256 suffixLength = hasSignature ? _paymasterSignatureSize(self) + 10 : 0;\n return\n self.paymasterAndData.length < 52 + suffixLength\n ? Calldata.emptyBytes()\n : self.paymasterAndData[52:self.paymasterAndData.length - suffixLength];\n }\n\n /**\n * @dev Returns the paymaster signature from `paymasterAndData` (EntryPoint v0.9+).\n * Returns empty bytes if no paymaster signature is present.\n */\n function paymasterSignature(PackedUserOperation calldata self) internal pure returns (bytes calldata) {\n if (\n self.paymasterAndData.length < 10 ||\n bytes8(self.paymasterAndData[self.paymasterAndData.length - 8:]) != PAYMASTER_SIG_MAGIC\n ) return Calldata.emptyBytes();\n\n uint256 sigSize = _paymasterSignatureSize(self);\n uint256 sigEnd = self.paymasterAndData.length - 10;\n return\n self.paymasterAndData.length < 62 + sigSize\n ? Calldata.emptyBytes()\n : self.paymasterAndData[sigEnd - sigSize:sigEnd];\n }\n\n /**\n * @dev Returns the size of the paymaster signature in `paymasterAndData` (EntryPoint v0.9+).\n * Does not check minimum length of `paymasterAndData`.\n */\n function _paymasterSignatureSize(PackedUserOperation calldata self) private pure returns (uint256) {\n return\n uint16(bytes2(self.paymasterAndData[self.paymasterAndData.length - 10:self.paymasterAndData.length - 8]));\n }\n}\n" + }, + "@openzeppelin/contracts/account/utils/draft-ERC7579Utils.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (account/utils/draft-ERC7579Utils.sol)\n\npragma solidity ^0.8.20;\n\nimport {Execution} from \"../../interfaces/draft-IERC7579.sol\";\nimport {Packing} from \"../../utils/Packing.sol\";\nimport {Address} from \"../../utils/Address.sol\";\n\ntype Mode is bytes32;\ntype CallType is bytes1;\ntype ExecType is bytes1;\ntype ModeSelector is bytes4;\ntype ModePayload is bytes22;\n\n/**\n * @dev Library with common ERC-7579 utility functions.\n *\n * See https://eips.ethereum.org/EIPS/eip-7579[ERC-7579].\n */\n// slither-disable-next-line unused-state\nlibrary ERC7579Utils {\n using Packing for *;\n\n /// @dev A single `call` execution.\n CallType internal constant CALLTYPE_SINGLE = CallType.wrap(0x00);\n\n /// @dev A batch of `call` executions.\n CallType internal constant CALLTYPE_BATCH = CallType.wrap(0x01);\n\n /// @dev A `delegatecall` execution.\n CallType internal constant CALLTYPE_DELEGATECALL = CallType.wrap(0xFF);\n\n /// @dev Default execution type that reverts on failure.\n ExecType internal constant EXECTYPE_DEFAULT = ExecType.wrap(0x00);\n\n /// @dev Execution type that does not revert on failure.\n ExecType internal constant EXECTYPE_TRY = ExecType.wrap(0x01);\n\n /**\n * @dev Emits when an {EXECTYPE_TRY} execution fails.\n * @param batchExecutionIndex The index of the failed call in the execution batch.\n * @param returndata The returned data from the failed call.\n */\n event ERC7579TryExecuteFail(uint256 batchExecutionIndex, bytes returndata);\n\n /// @dev The provided {CallType} is not supported.\n error ERC7579UnsupportedCallType(CallType callType);\n\n /// @dev The provided {ExecType} is not supported.\n error ERC7579UnsupportedExecType(ExecType execType);\n\n /// @dev The provided module doesn't match the provided module type.\n error ERC7579MismatchedModuleTypeId(uint256 moduleTypeId, address module);\n\n /// @dev The module is not installed.\n error ERC7579UninstalledModule(uint256 moduleTypeId, address module);\n\n /// @dev The module is already installed.\n error ERC7579AlreadyInstalledModule(uint256 moduleTypeId, address module);\n\n /// @dev The module type is not supported.\n error ERC7579UnsupportedModuleType(uint256 moduleTypeId);\n\n /// @dev Input calldata not properly formatted and possibly malicious.\n error ERC7579DecodingError();\n\n /// @dev Executes a single call.\n function execSingle(\n bytes calldata executionCalldata,\n ExecType execType\n ) internal returns (bytes[] memory returnData) {\n (address target, uint256 value, bytes calldata callData) = decodeSingle(executionCalldata);\n returnData = new bytes[](1);\n returnData[0] = _call(0, execType, target, value, callData);\n }\n\n /// @dev Executes a batch of calls.\n function execBatch(\n bytes calldata executionCalldata,\n ExecType execType\n ) internal returns (bytes[] memory returnData) {\n Execution[] calldata executionBatch = decodeBatch(executionCalldata);\n returnData = new bytes[](executionBatch.length);\n for (uint256 i = 0; i < executionBatch.length; ++i) {\n returnData[i] = _call(\n i,\n execType,\n executionBatch[i].target,\n executionBatch[i].value,\n executionBatch[i].callData\n );\n }\n }\n\n /// @dev Executes a delegate call.\n function execDelegateCall(\n bytes calldata executionCalldata,\n ExecType execType\n ) internal returns (bytes[] memory returnData) {\n (address target, bytes calldata callData) = decodeDelegate(executionCalldata);\n returnData = new bytes[](1);\n returnData[0] = _delegatecall(0, execType, target, callData);\n }\n\n /// @dev Encodes the mode with the provided parameters. See {decodeMode}.\n function encodeMode(\n CallType callType,\n ExecType execType,\n ModeSelector selector,\n ModePayload payload\n ) internal pure returns (Mode mode) {\n return\n Mode.wrap(\n CallType\n .unwrap(callType)\n .pack_1_1(ExecType.unwrap(execType))\n .pack_2_4(bytes4(0))\n .pack_6_4(ModeSelector.unwrap(selector))\n .pack_10_22(ModePayload.unwrap(payload))\n );\n }\n\n /// @dev Decodes the mode into its parameters. See {encodeMode}.\n function decodeMode(\n Mode mode\n ) internal pure returns (CallType callType, ExecType execType, ModeSelector selector, ModePayload payload) {\n return (\n CallType.wrap(Packing.extract_32_1(Mode.unwrap(mode), 0x00)),\n ExecType.wrap(Packing.extract_32_1(Mode.unwrap(mode), 0x01)),\n ModeSelector.wrap(Packing.extract_32_4(Mode.unwrap(mode), 0x06)),\n ModePayload.wrap(Packing.extract_32_22(Mode.unwrap(mode), 0x0a))\n );\n }\n\n /// @dev Encodes a single call execution. See {decodeSingle}.\n function encodeSingle(\n address target,\n uint256 value,\n bytes calldata callData\n ) internal pure returns (bytes memory executionCalldata) {\n return abi.encodePacked(target, value, callData);\n }\n\n /// @dev Decodes a single call execution. See {encodeSingle}.\n function decodeSingle(\n bytes calldata executionCalldata\n ) internal pure returns (address target, uint256 value, bytes calldata callData) {\n target = address(bytes20(executionCalldata));\n value = uint256(bytes32(executionCalldata[20:52]));\n callData = executionCalldata[52:];\n }\n\n /// @dev Encodes a delegate call execution. See {decodeDelegate}.\n function encodeDelegate(\n address target,\n bytes calldata callData\n ) internal pure returns (bytes memory executionCalldata) {\n return abi.encodePacked(target, callData);\n }\n\n /// @dev Decodes a delegate call execution. See {encodeDelegate}.\n function decodeDelegate(\n bytes calldata executionCalldata\n ) internal pure returns (address target, bytes calldata callData) {\n target = address(bytes20(executionCalldata));\n callData = executionCalldata[20:];\n }\n\n /// @dev Encodes a batch of executions. See {decodeBatch}.\n function encodeBatch(Execution[] memory executionBatch) internal pure returns (bytes memory executionCalldata) {\n return abi.encode(executionBatch);\n }\n\n /// @dev Decodes a batch of executions. See {encodeBatch}.\n ///\n /// NOTE: This function runs some checks and will throw a {ERC7579DecodingError} if the input is not properly formatted.\n function decodeBatch(bytes calldata executionCalldata) internal pure returns (Execution[] calldata executionBatch) {\n unchecked {\n uint256 bufferLength = executionCalldata.length;\n\n // Check executionCalldata is not empty.\n if (bufferLength < 0x20) revert ERC7579DecodingError();\n\n // Get the offset of the array (pointer to the array length).\n uint256 arrayLengthOffset = uint256(bytes32(executionCalldata[0x00:0x20]));\n\n // The array length (at arrayLengthOffset) should be 32 bytes long. We check that this is within the\n // buffer bounds. Since we know bufferLength is at least 32, we can subtract with no overflow risk.\n if (arrayLengthOffset > bufferLength - 0x20) revert ERC7579DecodingError();\n\n // Get the array length. arrayLengthOffset + 32 is bounded by bufferLength so it does not overflow.\n uint256 arrayLength = uint256(bytes32(executionCalldata[arrayLengthOffset:arrayLengthOffset + 0x20]));\n\n // Check that the buffer is long enough to store the array elements as \"offset pointer\":\n // - each element of the array is an \"offset pointer\" to the data.\n // - each \"offset pointer\" (to an array element) takes 32 bytes.\n // - validity of the calldata at that location is checked when the array element is accessed, so we only\n // need to check that the buffer is large enough to hold the pointers.\n //\n // Since we know bufferLength is at least arrayLengthOffset + 32, we can subtract with no overflow risk.\n // Solidity limits length of such arrays to 2**64-1, this guarantees `arrayLength * 32` does not overflow.\n if (arrayLength > type(uint64).max || bufferLength - arrayLengthOffset - 0x20 < arrayLength * 0x20)\n revert ERC7579DecodingError();\n\n assembly (\"memory-safe\") {\n executionBatch.offset := add(add(executionCalldata.offset, arrayLengthOffset), 0x20)\n executionBatch.length := arrayLength\n }\n }\n }\n\n /// @dev Executes a `call` to the target with the provided {ExecType}.\n function _call(\n uint256 index,\n ExecType execType,\n address target,\n uint256 value,\n bytes calldata data\n ) private returns (bytes memory) {\n (bool success, bytes memory returndata) = (target == address(0) ? address(this) : target).call{value: value}(\n data\n );\n return _validateExecutionMode(index, execType, success, returndata);\n }\n\n /// @dev Executes a `delegatecall` to the target with the provided {ExecType}.\n function _delegatecall(\n uint256 index,\n ExecType execType,\n address target,\n bytes calldata data\n ) private returns (bytes memory) {\n (bool success, bytes memory returndata) = (target == address(0) ? address(this) : target).delegatecall(data);\n return _validateExecutionMode(index, execType, success, returndata);\n }\n\n /// @dev Validates the execution mode and returns the returndata.\n function _validateExecutionMode(\n uint256 index,\n ExecType execType,\n bool success,\n bytes memory returndata\n ) private returns (bytes memory) {\n if (execType == ERC7579Utils.EXECTYPE_DEFAULT) {\n Address.verifyCallResult(success, returndata);\n } else if (execType == ERC7579Utils.EXECTYPE_TRY) {\n if (!success) emit ERC7579TryExecuteFail(index, returndata);\n } else {\n revert ERC7579UnsupportedExecType(execType);\n }\n return returndata;\n }\n}\n\n// Operators\nusing {eqCallType as ==} for CallType global;\nusing {eqExecType as ==} for ExecType global;\nusing {eqModeSelector as ==} for ModeSelector global;\nusing {eqModePayload as ==} for ModePayload global;\n\n/// @dev Compares two `CallType` values for equality.\nfunction eqCallType(CallType a, CallType b) pure returns (bool) {\n return CallType.unwrap(a) == CallType.unwrap(b);\n}\n\n/// @dev Compares two `ExecType` values for equality.\nfunction eqExecType(ExecType a, ExecType b) pure returns (bool) {\n return ExecType.unwrap(a) == ExecType.unwrap(b);\n}\n\n/// @dev Compares two `ModeSelector` values for equality.\nfunction eqModeSelector(ModeSelector a, ModeSelector b) pure returns (bool) {\n return ModeSelector.unwrap(a) == ModeSelector.unwrap(b);\n}\n\n/// @dev Compares two `ModePayload` values for equality.\nfunction eqModePayload(ModePayload a, ModePayload b) pure returns (bool) {\n return ModePayload.unwrap(a) == ModePayload.unwrap(b);\n}\n" + }, + "@openzeppelin/contracts/account/utils/EIP7702Utils.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (account/utils/EIP7702Utils.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library with common EIP-7702 utility functions.\n *\n * See https://eips.ethereum.org/EIPS/eip-7702[EIP-7702].\n */\nlibrary EIP7702Utils {\n bytes3 internal constant EIP7702_PREFIX = 0xef0100;\n\n /**\n * @dev Returns the address of the delegate if `account` has an EIP-7702 delegation setup, or address(0) otherwise.\n */\n function fetchDelegate(address account) internal view returns (address) {\n bytes23 delegation = bytes23(account.code);\n return bytes3(delegation) == EIP7702_PREFIX ? address(bytes20(delegation << 24)) : address(0);\n }\n}\n" + }, + "@openzeppelin/contracts/interfaces/draft-IERC4337.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (interfaces/draft-IERC4337.sol)\n\npragma solidity >=0.8.4;\n\n/**\n * @dev A https://github.com/ethereum/ercs/blob/master/ERCS/erc-4337.md#useroperation[user operation] is composed of the following elements:\n * - `sender` (`address`): The account making the operation\n * - `nonce` (`uint256`): Anti-replay parameter (see “Semi-abstracted Nonce Support” )\n * - `factory` (`address`): account factory, only for new accounts\n * - `factoryData` (`bytes`): data for account factory (only if account factory exists)\n * - `callData` (`bytes`): The data to pass to the sender during the main execution call\n * - `callGasLimit` (`uint256`): The amount of gas to allocate the main execution call\n * - `verificationGasLimit` (`uint256`): The amount of gas to allocate for the verification step\n * - `preVerificationGas` (`uint256`): Extra gas to pay the bundler\n * - `maxFeePerGas` (`uint256`): Maximum fee per gas (similar to EIP-1559 max_fee_per_gas)\n * - `maxPriorityFeePerGas` (`uint256`): Maximum priority fee per gas (similar to EIP-1559 max_priority_fee_per_gas)\n * - `paymaster` (`address`): Address of paymaster contract, (or empty, if account pays for itself)\n * - `paymasterVerificationGasLimit` (`uint256`): The amount of gas to allocate for the paymaster validation code\n * - `paymasterPostOpGasLimit` (`uint256`): The amount of gas to allocate for the paymaster post-operation code\n * - `paymasterData` (`bytes`): Data for paymaster (only if paymaster exists)\n * - `signature` (`bytes`): Data passed into the account to verify authorization\n *\n * When passed to on-chain contracts, the following packed version is used.\n * - `sender` (`address`)\n * - `nonce` (`uint256`)\n * - `initCode` (`bytes`): concatenation of factory address and factoryData (or empty)\n * - `callData` (`bytes`)\n * - `accountGasLimits` (`bytes32`): concatenation of verificationGas (16 bytes) and callGas (16 bytes)\n * - `preVerificationGas` (`uint256`)\n * - `gasFees` (`bytes32`): concatenation of maxPriorityFeePerGas (16 bytes) and maxFeePerGas (16 bytes)\n * - `paymasterAndData` (`bytes`): concatenation of paymaster fields (or empty)\n * For EntryPoint v0.9+, may optionally include `paymasterSignature` at the end:\n * `paymaster || paymasterVerificationGasLimit || paymasterPostOpGasLimit || paymasterData || paymasterSignature || paymasterSignatureSize || PAYMASTER_SIG_MAGIC`\n * - `signature` (`bytes`)\n */\nstruct PackedUserOperation {\n address sender;\n uint256 nonce;\n bytes initCode; // `abi.encodePacked(factory, factoryData)`\n bytes callData;\n bytes32 accountGasLimits; // `abi.encodePacked(verificationGasLimit, callGasLimit)` 16 bytes each\n uint256 preVerificationGas;\n bytes32 gasFees; // `abi.encodePacked(maxPriorityFeePerGas, maxFeePerGas)` 16 bytes each\n bytes paymasterAndData; // `abi.encodePacked(paymaster, paymasterVerificationGasLimit, paymasterPostOpGasLimit, paymasterData[, paymasterSignature, paymasterSignatureSize, PAYMASTER_SIG_MAGIC])` (20 bytes, 16 bytes, 16 bytes, dynamic[, dynamic, 2 bytes, 8 bytes])\n bytes signature;\n}\n\n/**\n * @dev Aggregates and validates multiple signatures for a batch of user operations.\n *\n * A contract could implement this interface with custom validation schemes that allow signature aggregation,\n * enabling significant optimizations and gas savings for execution and transaction data cost.\n *\n * Bundlers and clients whitelist supported aggregators.\n *\n * See https://eips.ethereum.org/EIPS/eip-7766[ERC-7766]\n */\ninterface IAggregator {\n /**\n * @dev Validates the signature for a user operation.\n * Returns an alternative signature that should be used during bundling.\n */\n function validateUserOpSignature(\n PackedUserOperation calldata userOp\n ) external view returns (bytes memory sigForUserOp);\n\n /**\n * @dev Returns an aggregated signature for a batch of user operation's signatures.\n */\n function aggregateSignatures(\n PackedUserOperation[] calldata userOps\n ) external view returns (bytes memory aggregatesSignature);\n\n /**\n * @dev Validates that the aggregated signature is valid for the user operations.\n *\n * Requirements:\n *\n * - The aggregated signature MUST match the given list of operations.\n */\n function validateSignatures(PackedUserOperation[] calldata userOps, bytes calldata signature) external view;\n}\n\n/**\n * @dev Handle nonce management for accounts.\n *\n * Nonces are used in accounts as a replay protection mechanism and to ensure the order of user operations.\n * To avoid limiting the number of operations an account can perform, the interface allows using parallel\n * nonces by using a `key` parameter.\n *\n * See https://eips.ethereum.org/EIPS/eip-4337#semi-abstracted-nonce-support[ERC-4337 semi-abstracted nonce support].\n */\ninterface IEntryPointNonces {\n /**\n * @dev Returns the nonce for a `sender` account and a `key`.\n *\n * Nonces for a certain `key` are always increasing.\n */\n function getNonce(address sender, uint192 key) external view returns (uint256 nonce);\n}\n\n/**\n * @dev Handle stake management for entities (i.e. accounts, paymasters, factories).\n *\n * The EntryPoint must implement the following API to let entities like paymasters have a stake,\n * and thus have more flexibility in their storage access\n * (see https://eips.ethereum.org/EIPS/eip-4337#reputation-scoring-and-throttlingbanning-for-global-entities[reputation, throttling and banning.])\n */\ninterface IEntryPointStake {\n /**\n * @dev Returns the balance of the account.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Deposits `msg.value` to the account.\n */\n function depositTo(address account) external payable;\n\n /**\n * @dev Withdraws `withdrawAmount` from the account to `withdrawAddress`.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external;\n\n /**\n * @dev Adds stake to the account with an unstake delay of `unstakeDelaySec`.\n */\n function addStake(uint32 unstakeDelaySec) external payable;\n\n /**\n * @dev Unlocks the stake of the account.\n */\n function unlockStake() external;\n\n /**\n * @dev Withdraws the stake of the account to `withdrawAddress`.\n */\n function withdrawStake(address payable withdrawAddress) external;\n}\n\n/**\n * @dev Entry point for user operations.\n *\n * User operations are validated and executed by this contract.\n */\ninterface IEntryPoint is IEntryPointNonces, IEntryPointStake {\n /**\n * @dev A user operation at `opIndex` failed with `reason`.\n */\n error FailedOp(uint256 opIndex, string reason);\n\n /**\n * @dev A user operation at `opIndex` failed with `reason` and `inner` returned data.\n */\n error FailedOpWithRevert(uint256 opIndex, string reason, bytes inner);\n\n /**\n * @dev Batch of aggregated user operations per aggregator.\n */\n struct UserOpsPerAggregator {\n PackedUserOperation[] userOps;\n IAggregator aggregator;\n bytes signature;\n }\n\n /**\n * @dev Executes a batch of user operations.\n * @param beneficiary Address to which gas is refunded upon completing the execution.\n */\n function handleOps(PackedUserOperation[] calldata ops, address payable beneficiary) external;\n\n /**\n * @dev Executes a batch of aggregated user operations per aggregator.\n * @param beneficiary Address to which gas is refunded upon completing the execution.\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) external;\n}\n\n/**\n * @dev Base interface for an ERC-4337 account.\n */\ninterface IAccount {\n /**\n * @dev Validates a user operation.\n *\n * * MUST validate the caller is a trusted EntryPoint\n * * MUST validate that the signature is a valid signature of the userOpHash, and SHOULD\n * return SIG_VALIDATION_FAILED (and not revert) on signature mismatch. Any other error MUST revert.\n * * MUST pay the entryPoint (caller) at least the “missingAccountFunds” (which might\n * be zero, in case the current account’s deposit is high enough)\n *\n * Returns an encoded packed validation data that is composed of the following elements:\n *\n * - `authorizer` (`address`): 0 for success, 1 for failure, otherwise the address of an authorizer contract\n * - `validUntil` (`uint48`): The UserOp is valid only up to this time. Zero for “infinite”.\n * - `validAfter` (`uint48`): The UserOp is valid only after this time.\n */\n function validateUserOp(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash,\n uint256 missingAccountFunds\n ) external returns (uint256 validationData);\n}\n\n/**\n * @dev Support for executing user operations by prepending the {executeUserOp} function selector\n * to the UserOperation's `callData`.\n */\ninterface IAccountExecute {\n /**\n * @dev Executes a user operation.\n */\n function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external;\n}\n\n/**\n * @dev Interface for a paymaster contract that agrees to pay for the gas costs of a user operation.\n *\n * NOTE: A paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction.\n */\ninterface IPaymaster {\n enum PostOpMode {\n opSucceeded,\n opReverted,\n postOpReverted\n }\n\n /**\n * @dev Validates whether the paymaster is willing to pay for the user operation. See\n * {IAccount-validateUserOp} for additional information on the return value.\n *\n * NOTE: Bundlers will reject this method if it modifies the state, unless it's whitelisted.\n */\n function validatePaymasterUserOp(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash,\n uint256 maxCost\n ) external returns (bytes memory context, uint256 validationData);\n\n /**\n * @dev Verifies the sender is the entrypoint.\n * @param actualGasCost the actual amount paid (by account or paymaster) for this UserOperation\n * @param actualUserOpFeePerGas total gas used by this UserOperation (including preVerification, creation, validation and execution)\n */\n function postOp(\n PostOpMode mode,\n bytes calldata context,\n uint256 actualGasCost,\n uint256 actualUserOpFeePerGas\n ) external;\n}\n" + }, + "@openzeppelin/contracts/interfaces/draft-IERC7579.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (interfaces/draft-IERC7579.sol)\n\npragma solidity >=0.8.4;\n\nimport {PackedUserOperation} from \"./draft-IERC4337.sol\";\n\nuint256 constant VALIDATION_SUCCESS = 0;\nuint256 constant VALIDATION_FAILED = 1;\nuint256 constant MODULE_TYPE_VALIDATOR = 1;\nuint256 constant MODULE_TYPE_EXECUTOR = 2;\nuint256 constant MODULE_TYPE_FALLBACK = 3;\nuint256 constant MODULE_TYPE_HOOK = 4;\n\n/// @dev Minimal configuration interface for ERC-7579 modules\ninterface IERC7579Module {\n /**\n * @dev This function is called by the smart account during installation of the module\n * @param data arbitrary data that may be passed to the module during `onInstall` initialization\n *\n * MUST revert on error (e.g. if module is already enabled)\n */\n function onInstall(bytes calldata data) external;\n\n /**\n * @dev This function is called by the smart account during uninstallation of the module\n * @param data arbitrary data that may be passed to the module during `onUninstall` de-initialization\n *\n * MUST revert on error\n */\n function onUninstall(bytes calldata data) external;\n\n /**\n * @dev Returns boolean value if module is a certain type\n * @param moduleTypeId the module type ID according the ERC-7579 spec\n *\n * MUST return true if the module is of the given type and false otherwise\n */\n function isModuleType(uint256 moduleTypeId) external view returns (bool);\n}\n\n/**\n * @dev ERC-7579 Validation module (type 1).\n *\n * A module that implements logic to validate user operations and signatures.\n */\ninterface IERC7579Validator is IERC7579Module {\n /**\n * @dev Validates a UserOperation\n * @param userOp the ERC-4337 PackedUserOperation\n * @param userOpHash the hash of the ERC-4337 PackedUserOperation\n *\n * MUST validate that the signature is a valid signature of the userOpHash\n * SHOULD return ERC-4337's SIG_VALIDATION_FAILED (and not revert) on signature mismatch\n * See {IAccount-validateUserOp} for additional information on the return value\n */\n function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external returns (uint256);\n\n /**\n * @dev Validates a signature using ERC-1271\n * @param sender the address that sent the ERC-1271 request to the smart account\n * @param hash the hash of the ERC-1271 request\n * @param signature the signature of the ERC-1271 request\n *\n * MUST return the ERC-1271 `MAGIC_VALUE` if the signature is valid\n * MUST NOT modify state\n */\n function isValidSignatureWithSender(\n address sender,\n bytes32 hash,\n bytes calldata signature\n ) external view returns (bytes4);\n}\n\n/**\n * @dev ERC-7579 Hooks module (type 4).\n *\n * A module that implements logic to execute before and after the account executes a user operation,\n * either individually or batched.\n */\ninterface IERC7579Hook is IERC7579Module {\n /**\n * @dev Called by the smart account before execution\n * @param msgSender the address that called the smart account\n * @param value the value that was sent to the smart account\n * @param msgData the data that was sent to the smart account\n *\n * MAY return arbitrary data in the `hookData` return value\n */\n function preCheck(\n address msgSender,\n uint256 value,\n bytes calldata msgData\n ) external returns (bytes memory hookData);\n\n /**\n * @dev Called by the smart account after execution\n * @param hookData the data that was returned by the `preCheck` function\n *\n * MAY validate the `hookData` to validate transaction context of the `preCheck` function\n */\n function postCheck(bytes calldata hookData) external;\n}\n\nstruct Execution {\n address target;\n uint256 value;\n bytes callData;\n}\n\n/**\n * @dev ERC-7579 Execution.\n *\n * Accounts should implement this interface so that the Entrypoint and ERC-7579 modules can execute operations.\n */\ninterface IERC7579Execution {\n /**\n * @dev Executes a transaction on behalf of the account.\n * @param mode The encoded execution mode of the transaction. See account/utils/draft-ERC7579Utils.sol (Mode encoding via encodeMode/decodeMode) for details\n * @param executionCalldata The encoded execution call data\n *\n * MUST ensure adequate authorization control: e.g. onlyEntryPointOrSelf if used with ERC-4337\n * If a mode is requested that is not supported by the Account, it MUST revert\n */\n function execute(bytes32 mode, bytes calldata executionCalldata) external payable;\n\n /**\n * @dev Executes a transaction on behalf of the account.\n * This function is intended to be called by Executor Modules\n * @param mode The encoded execution mode of the transaction. See account/utils/draft-ERC7579Utils.sol (Mode encoding via encodeMode/decodeMode) for details\n * @param executionCalldata The encoded execution call data\n * @return returnData An array with the returned data of each executed subcall\n *\n * MUST ensure adequate authorization control: i.e. onlyExecutorModule\n * If a mode is requested that is not supported by the Account, it MUST revert\n */\n function executeFromExecutor(\n bytes32 mode,\n bytes calldata executionCalldata\n ) external payable returns (bytes[] memory returnData);\n}\n\n/**\n * @dev ERC-7579 Account Config.\n *\n * Accounts should implement this interface to expose information that identifies the account, supported modules and capabilities.\n */\ninterface IERC7579AccountConfig {\n /**\n * @dev Returns the account id of the smart account\n * @return accountImplementationId the account id of the smart account\n *\n * MUST return a non-empty string\n * The accountId SHOULD be structured like so:\n * \"vendorname.accountname.semver\"\n * The id SHOULD be unique across all smart accounts\n */\n function accountId() external view returns (string memory accountImplementationId);\n\n /**\n * @dev Function to check if the account supports a certain execution mode (see above)\n * @param encodedMode the encoded mode\n *\n * MUST return true if the account supports the mode and false otherwise\n */\n function supportsExecutionMode(bytes32 encodedMode) external view returns (bool);\n\n /**\n * @dev Function to check if the account supports a certain module typeId\n * @param moduleTypeId the module type ID according to the ERC-7579 spec\n *\n * MUST return true if the account supports the module type and false otherwise\n */\n function supportsModule(uint256 moduleTypeId) external view returns (bool);\n}\n\n/**\n * @dev ERC-7579 Module Config.\n *\n * Accounts should implement this interface to allow installing and uninstalling modules.\n */\ninterface IERC7579ModuleConfig {\n event ModuleInstalled(uint256 moduleTypeId, address module);\n event ModuleUninstalled(uint256 moduleTypeId, address module);\n\n /**\n * @dev Installs a Module of a certain type on the smart account\n * @param moduleTypeId the module type ID according to the ERC-7579 spec\n * @param module the module address\n * @param initData arbitrary data that may be passed to the module during `onInstall`\n * initialization.\n *\n * MUST implement authorization control\n * MUST call `onInstall` on the module with the `initData` parameter if provided\n * MUST emit ModuleInstalled event\n * MUST revert if the module is already installed or the initialization on the module failed\n */\n function installModule(uint256 moduleTypeId, address module, bytes calldata initData) external;\n\n /**\n * @dev Uninstalls a Module of a certain type on the smart account\n * @param moduleTypeId the module type ID according the ERC-7579 spec\n * @param module the module address\n * @param deInitData arbitrary data that may be passed to the module during `onUninstall`\n * deinitialization.\n *\n * MUST implement authorization control\n * MUST call `onUninstall` on the module with the `deInitData` parameter if provided\n * MUST emit ModuleUninstalled event\n * MUST revert if the module is not installed or the deInitialization on the module failed\n */\n function uninstallModule(uint256 moduleTypeId, address module, bytes calldata deInitData) external;\n\n /**\n * @dev Returns whether a module is installed on the smart account\n * @param moduleTypeId the module type ID according the ERC-7579 spec\n * @param module the module address\n * @param additionalContext arbitrary data that may be passed to determine if the module is installed\n *\n * MUST return true if the module is installed and false otherwise\n */\n function isModuleInstalled(\n uint256 moduleTypeId,\n address module,\n bytes calldata additionalContext\n ) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/interfaces/draft-IERC7821.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC7821.sol)\n\npragma solidity >=0.5.0;\n\n/**\n * @dev Interface for minimal batch executor.\n */\ninterface IERC7821 {\n /**\n * @dev Executes the calls in `executionData`.\n * Reverts and bubbles up error if any call fails.\n *\n * `executionData` encoding:\n * - If `opData` is empty, `executionData` is simply `abi.encode(calls)`.\n * - Else, `executionData` is `abi.encode(calls, opData)`.\n * See: https://eips.ethereum.org/EIPS/eip-7579\n *\n * Supported modes:\n * - `bytes32(0x01000000000000000000...)`: does not support optional `opData`.\n * - `bytes32(0x01000000000078210001...)`: supports optional `opData`.\n *\n * Authorization checks:\n * - If `opData` is empty, the implementation SHOULD require that\n * `msg.sender == address(this)`.\n * - If `opData` is not empty, the implementation SHOULD use the signature\n * encoded in `opData` to determine if the caller can perform the execution.\n *\n * `opData` may be used to store additional data for authentication,\n * paymaster data, gas limits, etc.\n *\n * For calldata compression efficiency, if a Call.to is `address(0)`,\n * it will be replaced with `address(this)`.\n */\n function execute(bytes32 mode, bytes calldata executionData) external payable;\n\n /**\n * @dev This function is provided for frontends to detect support.\n * Only returns true for:\n * - `bytes32(0x01000000000000000000...)`: does not support optional `opData`.\n * - `bytes32(0x01000000000078210001...)`: supports optional `opData`.\n */\n function supportsExecutionMode(bytes32 mode) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC5267.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC5267.sol)\n\npragma solidity >=0.4.16;\n\ninterface IERC5267 {\n /**\n * @dev MAY be emitted to signal that the domain could have changed.\n */\n event EIP712DomainChanged();\n\n /**\n * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712\n * signature.\n */\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\nimport {Errors} from \"./Errors.sol\";\nimport {LowLevelCall} from \"./LowLevelCall.sol\";\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance < amount) {\n revert Errors.InsufficientBalance(address(this).balance, amount);\n }\n if (LowLevelCall.callNoReturn(recipient, amount, \"\")) {\n // call successful, nothing to do\n return;\n } else if (LowLevelCall.returnDataSize() > 0) {\n LowLevelCall.bubbleRevert();\n } else {\n revert Errors.FailedCall();\n }\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 or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {Errors.FailedCall} error.\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 function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\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 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance < value) {\n revert Errors.InsufficientBalance(address(this).balance, value);\n }\n bool success = LowLevelCall.callNoReturn(target, value, data);\n if (success && (LowLevelCall.returnDataSize() > 0 || target.code.length > 0)) {\n return LowLevelCall.returnData();\n } else if (success) {\n revert AddressEmptyCode(target);\n } else if (LowLevelCall.returnDataSize() > 0) {\n LowLevelCall.bubbleRevert();\n } else {\n revert Errors.FailedCall();\n }\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n bool success = LowLevelCall.staticcallNoReturn(target, data);\n if (success && (LowLevelCall.returnDataSize() > 0 || target.code.length > 0)) {\n return LowLevelCall.returnData();\n } else if (success) {\n revert AddressEmptyCode(target);\n } else if (LowLevelCall.returnDataSize() > 0) {\n LowLevelCall.bubbleRevert();\n } else {\n revert Errors.FailedCall();\n }\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n bool success = LowLevelCall.delegatecallNoReturn(target, data);\n if (success && (LowLevelCall.returnDataSize() > 0 || target.code.length > 0)) {\n return LowLevelCall.returnData();\n } else if (success) {\n revert AddressEmptyCode(target);\n } else if (LowLevelCall.returnDataSize() > 0) {\n LowLevelCall.bubbleRevert();\n } else {\n revert Errors.FailedCall();\n }\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case\n * of an unsuccessful call.\n *\n * NOTE: This function is DEPRECATED and may be removed in the next major release.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (success && (returndata.length > 0 || target.code.length > 0)) {\n return returndata;\n } else if (success) {\n revert AddressEmptyCode(target);\n } else if (returndata.length > 0) {\n LowLevelCall.bubbleRevert(returndata);\n } else {\n revert Errors.FailedCall();\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {Errors.FailedCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else if (returndata.length > 0) {\n LowLevelCall.bubbleRevert(returndata);\n } else {\n revert Errors.FailedCall();\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Bytes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (utils/Bytes.sol)\n\npragma solidity ^0.8.24;\n\nimport {Math} from \"./math/Math.sol\";\n\n/**\n * @dev Bytes operations.\n */\nlibrary Bytes {\n /**\n * @dev Forward search for `s` in `buffer`\n * * If `s` is present in the buffer, returns the index of the first instance\n * * If `s` is not present in the buffer, returns type(uint256).max\n *\n * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf[Javascript's `Array.indexOf`]\n */\n function indexOf(bytes memory buffer, bytes1 s) internal pure returns (uint256) {\n return indexOf(buffer, s, 0);\n }\n\n /**\n * @dev Forward search for `s` in `buffer` starting at position `pos`\n * * If `s` is present in the buffer (at or after `pos`), returns the index of the next instance\n * * If `s` is not present in the buffer (at or after `pos`), returns type(uint256).max\n *\n * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf[Javascript's `Array.indexOf`]\n */\n function indexOf(bytes memory buffer, bytes1 s, uint256 pos) internal pure returns (uint256) {\n uint256 length = buffer.length;\n for (uint256 i = pos; i < length; ++i) {\n if (bytes1(_unsafeReadBytesOffset(buffer, i)) == s) {\n return i;\n }\n }\n return type(uint256).max;\n }\n\n /**\n * @dev Backward search for `s` in `buffer`\n * * If `s` is present in the buffer, returns the index of the last instance\n * * If `s` is not present in the buffer, returns type(uint256).max\n *\n * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf[Javascript's `Array.lastIndexOf`]\n */\n function lastIndexOf(bytes memory buffer, bytes1 s) internal pure returns (uint256) {\n return lastIndexOf(buffer, s, type(uint256).max);\n }\n\n /**\n * @dev Backward search for `s` in `buffer` starting at position `pos`\n * * If `s` is present in the buffer (at or before `pos`), returns the index of the previous instance\n * * If `s` is not present in the buffer (at or before `pos`), returns type(uint256).max\n *\n * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf[Javascript's `Array.lastIndexOf`]\n */\n function lastIndexOf(bytes memory buffer, bytes1 s, uint256 pos) internal pure returns (uint256) {\n unchecked {\n uint256 length = buffer.length;\n for (uint256 i = Math.min(Math.saturatingAdd(pos, 1), length); i > 0; --i) {\n if (bytes1(_unsafeReadBytesOffset(buffer, i - 1)) == s) {\n return i - 1;\n }\n }\n return type(uint256).max;\n }\n }\n\n /**\n * @dev Copies the content of `buffer`, from `start` (included) to the end of `buffer` into a new bytes object in\n * memory.\n *\n * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice[Javascript's `Array.slice`]\n */\n function slice(bytes memory buffer, uint256 start) internal pure returns (bytes memory) {\n return slice(buffer, start, buffer.length);\n }\n\n /**\n * @dev Copies the content of `buffer`, from `start` (included) to `end` (excluded) into a new bytes object in\n * memory. The `end` argument is truncated to the length of the `buffer`.\n *\n * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice[Javascript's `Array.slice`]\n */\n function slice(bytes memory buffer, uint256 start, uint256 end) internal pure returns (bytes memory) {\n // sanitize\n end = Math.min(end, buffer.length);\n start = Math.min(start, end);\n\n // allocate and copy\n bytes memory result = new bytes(end - start);\n assembly (\"memory-safe\") {\n mcopy(add(result, 0x20), add(add(buffer, 0x20), start), sub(end, start))\n }\n\n return result;\n }\n\n /**\n * @dev Moves the content of `buffer`, from `start` (included) to the end of `buffer` to the start of that buffer,\n * and shrinks the buffer length accordingly, effectively overriding the content of buffer with buffer[start:].\n *\n * NOTE: This function modifies the provided buffer in place. If you need to preserve the original buffer, use {slice} instead\n */\n function splice(bytes memory buffer, uint256 start) internal pure returns (bytes memory) {\n return splice(buffer, start, buffer.length);\n }\n\n /**\n * @dev Moves the content of `buffer`, from `start` (included) to `end` (excluded) to the start of that buffer,\n * and shrinks the buffer length accordingly, effectively overriding the content of buffer with buffer[start:end].\n * The `end` argument is truncated to the length of the `buffer`.\n *\n * NOTE: This function modifies the provided buffer in place. If you need to preserve the original buffer, use {slice} instead\n */\n function splice(bytes memory buffer, uint256 start, uint256 end) internal pure returns (bytes memory) {\n // sanitize\n end = Math.min(end, buffer.length);\n start = Math.min(start, end);\n\n // move and resize\n assembly (\"memory-safe\") {\n mcopy(add(buffer, 0x20), add(add(buffer, 0x20), start), sub(end, start))\n mstore(buffer, sub(end, start))\n }\n\n return buffer;\n }\n\n /**\n * @dev Replaces bytes in `buffer` starting at `pos` with all bytes from `replacement`.\n *\n * Parameters are clamped to valid ranges (i.e. `pos` is clamped to `[0, buffer.length]`).\n * If `pos >= buffer.length`, no replacement occurs and the buffer is returned unchanged.\n *\n * NOTE: This function modifies the provided buffer in place.\n */\n function replace(bytes memory buffer, uint256 pos, bytes memory replacement) internal pure returns (bytes memory) {\n return replace(buffer, pos, replacement, 0, replacement.length);\n }\n\n /**\n * @dev Replaces bytes in `buffer` starting at `pos` with bytes from `replacement` starting at `offset`.\n * Copies at most `length` bytes from `replacement` to `buffer`.\n *\n * Parameters are clamped to valid ranges (i.e. `pos` is clamped to `[0, buffer.length]`, `offset` is\n * clamped to `[0, replacement.length]`, and `length` is clamped to `min(length, replacement.length - offset,\n * buffer.length - pos))`. If `pos >= buffer.length` or `offset >= replacement.length`, no replacement occurs\n * and the buffer is returned unchanged.\n *\n * NOTE: This function modifies the provided buffer in place.\n */\n function replace(\n bytes memory buffer,\n uint256 pos,\n bytes memory replacement,\n uint256 offset,\n uint256 length\n ) internal pure returns (bytes memory) {\n // sanitize\n pos = Math.min(pos, buffer.length);\n offset = Math.min(offset, replacement.length);\n length = Math.min(length, Math.min(replacement.length - offset, buffer.length - pos));\n\n // replace\n assembly (\"memory-safe\") {\n mcopy(add(add(buffer, 0x20), pos), add(add(replacement, 0x20), offset), length)\n }\n\n return buffer;\n }\n\n /**\n * @dev Concatenate an array of bytes into a single bytes object.\n *\n * For fixed bytes types, we recommend using the solidity built-in `bytes.concat` or (equivalent)\n * `abi.encodePacked`.\n *\n * NOTE: this could be done in assembly with a single loop that expands starting at the FMP, but that would be\n * significantly less readable. It might be worth benchmarking the savings of the full-assembly approach.\n */\n function concat(bytes[] memory buffers) internal pure returns (bytes memory) {\n uint256 length = 0;\n for (uint256 i = 0; i < buffers.length; ++i) {\n length += buffers[i].length;\n }\n\n bytes memory result = new bytes(length);\n\n uint256 offset = 0x20;\n for (uint256 i = 0; i < buffers.length; ++i) {\n bytes memory input = buffers[i];\n assembly (\"memory-safe\") {\n mcopy(add(result, offset), add(input, 0x20), mload(input))\n }\n unchecked {\n offset += input.length;\n }\n }\n\n return result;\n }\n\n /**\n * @dev Split each byte in `input` into two nibbles (4 bits each)\n *\n * Example: hex\"01234567\" → hex\"0001020304050607\"\n */\n function toNibbles(bytes memory input) internal pure returns (bytes memory output) {\n assembly (\"memory-safe\") {\n let length := mload(input)\n output := mload(0x40)\n mstore(0x40, add(add(output, 0x20), mul(length, 2)))\n mstore(output, mul(length, 2))\n for {\n let i := 0\n } lt(i, length) {\n i := add(i, 0x10)\n } {\n let chunk := shr(128, mload(add(add(input, 0x20), i)))\n chunk := and(\n 0x0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff,\n or(shl(64, chunk), chunk)\n )\n chunk := and(\n 0x00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff,\n or(shl(32, chunk), chunk)\n )\n chunk := and(\n 0x0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff,\n or(shl(16, chunk), chunk)\n )\n chunk := and(\n 0x00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff,\n or(shl(8, chunk), chunk)\n )\n chunk := and(\n 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f,\n or(shl(4, chunk), chunk)\n )\n mstore(add(add(output, 0x20), mul(i, 2)), chunk)\n }\n }\n }\n\n /**\n * @dev Returns true if the two byte buffers are equal.\n */\n function equal(bytes memory a, bytes memory b) internal pure returns (bool) {\n return a.length == b.length && keccak256(a) == keccak256(b);\n }\n\n /**\n * @dev Reverses the byte order of a bytes32 value, converting between little-endian and big-endian.\n * Inspired by https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel[Reverse Parallel]\n */\n function reverseBytes32(bytes32 value) internal pure returns (bytes32) {\n value = // swap bytes\n ((value >> 8) & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) |\n ((value & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) << 8);\n value = // swap 2-byte long pairs\n ((value >> 16) & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) |\n ((value & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) << 16);\n value = // swap 4-byte long pairs\n ((value >> 32) & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) |\n ((value & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) << 32);\n value = // swap 8-byte long pairs\n ((value >> 64) & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) |\n ((value & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) << 64);\n return (value >> 128) | (value << 128); // swap 16-byte long pairs\n }\n\n /// @dev Same as {reverseBytes32} but optimized for 128-bit values.\n function reverseBytes16(bytes16 value) internal pure returns (bytes16) {\n value = // swap bytes\n ((value & 0xFF00FF00FF00FF00FF00FF00FF00FF00) >> 8) |\n ((value & 0x00FF00FF00FF00FF00FF00FF00FF00FF) << 8);\n value = // swap 2-byte long pairs\n ((value & 0xFFFF0000FFFF0000FFFF0000FFFF0000) >> 16) |\n ((value & 0x0000FFFF0000FFFF0000FFFF0000FFFF) << 16);\n value = // swap 4-byte long pairs\n ((value & 0xFFFFFFFF00000000FFFFFFFF00000000) >> 32) |\n ((value & 0x00000000FFFFFFFF00000000FFFFFFFF) << 32);\n return (value >> 64) | (value << 64); // swap 8-byte long pairs\n }\n\n /// @dev Same as {reverseBytes32} but optimized for 64-bit values.\n function reverseBytes8(bytes8 value) internal pure returns (bytes8) {\n value = ((value & 0xFF00FF00FF00FF00) >> 8) | ((value & 0x00FF00FF00FF00FF) << 8); // swap bytes\n value = ((value & 0xFFFF0000FFFF0000) >> 16) | ((value & 0x0000FFFF0000FFFF) << 16); // swap 2-byte long pairs\n return (value >> 32) | (value << 32); // swap 4-byte long pairs\n }\n\n /// @dev Same as {reverseBytes32} but optimized for 32-bit values.\n function reverseBytes4(bytes4 value) internal pure returns (bytes4) {\n value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8); // swap bytes\n return (value >> 16) | (value << 16); // swap 2-byte long pairs\n }\n\n /// @dev Same as {reverseBytes32} but optimized for 16-bit values.\n function reverseBytes2(bytes2 value) internal pure returns (bytes2) {\n return (value >> 8) | (value << 8);\n }\n\n /**\n * @dev Counts the number of leading zero bits a bytes array. Returns `8 * buffer.length`\n * if the buffer is all zeros.\n */\n function clz(bytes memory buffer) internal pure returns (uint256) {\n for (uint256 i = 0; i < buffer.length; i += 0x20) {\n bytes32 chunk = _unsafeReadBytesOffset(buffer, i);\n if (chunk != bytes32(0)) {\n return Math.min(8 * i + Math.clz(uint256(chunk)), 8 * buffer.length);\n }\n }\n return 8 * buffer.length;\n }\n\n /**\n * @dev Reads a bytes32 from a bytes array without bounds checking.\n *\n * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the\n * assembly block as such would prevent some optimizations.\n */\n function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {\n // This is not memory safe in the general case, but all calls to this private function are within bounds.\n assembly (\"memory-safe\") {\n value := mload(add(add(buffer, 0x20), offset))\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Calldata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Calldata.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Helper library for manipulating objects in calldata.\n */\nlibrary Calldata {\n // slither-disable-next-line write-after-write\n function emptyBytes() internal pure returns (bytes calldata result) {\n assembly (\"memory-safe\") {\n result.offset := 0\n result.length := 0\n }\n }\n\n // slither-disable-next-line write-after-write\n function emptyString() internal pure returns (string calldata result) {\n assembly (\"memory-safe\") {\n result.offset := 0\n result.length := 0\n }\n }\n}\n" }, "@openzeppelin/contracts/utils/Context.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" }, - "@openzeppelin/contracts/utils/Create2.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (utils/Create2.sol)\n\npragma solidity ^0.8.20;\n\nimport {Errors} from \"./Errors.sol\";\nimport {LowLevelCall} from \"./LowLevelCall.sol\";\n\n/**\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\n * `CREATE2` can be used to compute in advance the address where a smart\n * contract will be deployed, which allows for interesting new mechanisms known\n * as 'counterfactual interactions'.\n *\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\n * information.\n */\nlibrary Create2 {\n /**\n * @dev There's no code to deploy.\n */\n error Create2EmptyBytecode();\n\n /**\n * @dev Deploys a contract using `CREATE2`. The address where the contract\n * will be deployed can be known in advance via {computeAddress}.\n *\n * The bytecode for a contract can be obtained from Solidity with\n * `type(contractName).creationCode`.\n *\n * Requirements:\n *\n * - `bytecode` must not be empty.\n * - `salt` must have not been used for `bytecode` already.\n * - the factory must have a balance of at least `amount`.\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\n */\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) {\n if (address(this).balance < amount) {\n revert Errors.InsufficientBalance(address(this).balance, amount);\n }\n if (bytecode.length == 0) {\n revert Create2EmptyBytecode();\n }\n assembly (\"memory-safe\") {\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\n }\n if (addr == address(0)) {\n if (LowLevelCall.returnDataSize() == 0) {\n revert Errors.FailedDeployment();\n } else {\n LowLevelCall.bubbleRevert();\n }\n }\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\n * `bytecodeHash` or `salt` will result in a new destination address.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\n return computeAddress(salt, bytecodeHash, address(this));\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) {\n assembly (\"memory-safe\") {\n let ptr := mload(0x40) // Get free memory pointer\n\n // | | ↓ ptr ... ↓ ptr + 0x0B (start) ... ↓ ptr + 0x20 ... ↓ ptr + 0x40 ... |\n // |---------------------|---------------------------------------------------------------------------|\n // | bytecodeHash | CCCCCCCCCCCCC...CC |\n // | salt | BBBBBBBBBBBBB...BB |\n // | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA |\n // | 0xFF | FF |\n // |---------------------|---------------------------------------------------------------------------|\n // | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC |\n // | keccak(start, 0x55) | ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ |\n\n mstore(add(ptr, 0x40), bytecodeHash)\n mstore(add(ptr, 0x20), salt)\n mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes\n let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff\n mstore8(start, 0xff)\n addr := and(keccak256(start, 0x55), 0xffffffffffffffffffffffffffffffffffffffff)\n }\n }\n}\n" + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.20;\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 }\n\n /**\n * @dev The signature is invalid.\n */\n error ECDSAInvalidSignature();\n\n /**\n * @dev The signature has an invalid length.\n */\n error ECDSAInvalidSignatureLength(uint256 length);\n\n /**\n * @dev The signature has an S value that is in the upper half order.\n */\n error ECDSAInvalidSignatureS(bytes32 s);\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not\n * return address(0) without also returning an error description. Errors are documented using an enum (error type)\n * and a bytes32 providing additional information about the error.\n *\n * If no error is returned, then the address can be used for verification purposes.\n *\n * The `ecrecover` EVM precompile 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 * NOTE: This function only supports 65-byte signatures. ERC-2098 short signatures are rejected. This restriction\n * is DEPRECATED and will be removed in v6.0. Developers SHOULD NOT use signatures as unique identifiers; use hash\n * invalidation or nonces for replay protection.\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 {MessageHashUtils-toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n *\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 function tryRecover(\n bytes32 hash,\n bytes memory signature\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\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 assembly (\"memory-safe\") {\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, bytes32(signature.length));\n }\n }\n\n /**\n * @dev Variant of {tryRecover} that takes a signature in calldata\n */\n function tryRecoverCalldata(\n bytes32 hash,\n bytes calldata signature\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, calldata slices would work here, but are\n // significantly more expensive (length check) than using calldataload in assembly.\n assembly (\"memory-safe\") {\n r := calldataload(signature.offset)\n s := calldataload(add(signature.offset, 0x20))\n v := byte(0, calldataload(add(signature.offset, 0x40)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));\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 precompile 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 * NOTE: This function only supports 65-byte signatures. ERC-2098 short signatures are rejected. This restriction\n * is DEPRECATED and will be removed in v6.0. Developers SHOULD NOT use signatures as unique identifiers; use hash\n * invalidation or nonces for replay protection.\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 {MessageHashUtils-toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);\n _throwError(error, errorArg);\n return recovered;\n }\n\n /**\n * @dev Variant of {recover} that takes a signature in calldata\n */\n function recoverCalldata(bytes32 hash, bytes calldata signature) internal pure returns (address) {\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecoverCalldata(hash, signature);\n _throwError(error, errorArg);\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[ERC-2098 short signatures]\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\n unchecked {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n // We do not check for an overflow here since the shift operation results in 0 or 1.\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r` and `vs` short-signature fields separately.\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);\n _throwError(error, errorArg);\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 function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\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, s);\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, bytes32(0));\n }\n\n return (signer, RecoverError.NoError, bytes32(0));\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, bytes32 errorArg) = tryRecover(hash, v, r, s);\n _throwError(error, errorArg);\n return recovered;\n }\n\n /**\n * @dev Parse a signature into its `v`, `r` and `s` components. Supports 65-byte and 64-byte (ERC-2098)\n * formats. Returns (0,0,0) for invalid signatures.\n *\n * For 64-byte signatures, `v` is automatically normalized to 27 or 28.\n * For 65-byte signatures, `v` is returned as-is and MUST already be 27 or 28 for use with ecrecover.\n *\n * Consider validating the result before use, or use {tryRecover}/{recover} which perform full validation.\n */\n function parse(bytes memory signature) internal pure returns (uint8 v, bytes32 r, bytes32 s) {\n assembly (\"memory-safe\") {\n // Check the signature length\n switch mload(signature)\n // - case 65: r,s,v signature (standard)\n case 65 {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098)\n case 64 {\n let vs := mload(add(signature, 0x40))\n r := mload(add(signature, 0x20))\n s := and(vs, shr(1, not(0)))\n v := add(shr(255, vs), 27)\n }\n default {\n r := 0\n s := 0\n v := 0\n }\n }\n }\n\n /**\n * @dev Variant of {parse} that takes a signature in calldata\n */\n function parseCalldata(bytes calldata signature) internal pure returns (uint8 v, bytes32 r, bytes32 s) {\n assembly (\"memory-safe\") {\n // Check the signature length\n switch signature.length\n // - case 65: r,s,v signature (standard)\n case 65 {\n r := calldataload(signature.offset)\n s := calldataload(add(signature.offset, 0x20))\n v := byte(0, calldataload(add(signature.offset, 0x40)))\n }\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098)\n case 64 {\n let vs := calldataload(add(signature.offset, 0x20))\n r := calldataload(signature.offset)\n s := and(vs, shr(1, not(0)))\n v := add(shr(255, vs), 27)\n }\n default {\n r := 0\n s := 0\n v := 0\n }\n }\n }\n\n /**\n * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.\n */\n function _throwError(RecoverError error, bytes32 errorArg) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert ECDSAInvalidSignature();\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert ECDSAInvalidSignatureLength(uint256(errorArg));\n } else if (error == RecoverError.InvalidSignatureS) {\n revert ECDSAInvalidSignatureS(errorArg);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.24;\n\nimport {MessageHashUtils} from \"./MessageHashUtils.sol\";\nimport {ShortStrings, ShortString} from \"../ShortStrings.sol\";\nimport {IERC5267} from \"../../interfaces/IERC5267.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP-712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose\n * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract\n * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to\n * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP-712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain\n * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the\n * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.\n *\n * @custom:oz-upgrades-unsafe-allow state-variable-immutable\n */\nabstract contract EIP712 is IERC5267 {\n using ShortStrings for *;\n\n bytes32 private constant TYPE_HASH =\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _cachedDomainSeparator;\n uint256 private immutable _cachedChainId;\n address private immutable _cachedThis;\n\n bytes32 private immutable _hashedName;\n bytes32 private immutable _hashedVersion;\n\n ShortString private immutable _name;\n ShortString private immutable _version;\n // slither-disable-next-line constable-states\n string private _nameFallback;\n // slither-disable-next-line constable-states\n string private _versionFallback;\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP-712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n _name = name.toShortStringWithFallback(_nameFallback);\n _version = version.toShortStringWithFallback(_versionFallback);\n _hashedName = keccak256(bytes(name));\n _hashedVersion = keccak256(bytes(version));\n\n _cachedChainId = block.chainid;\n _cachedDomainSeparator = _buildDomainSeparator();\n _cachedThis = address(this);\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _cachedThis && block.chainid == _cachedChainId) {\n return _cachedDomainSeparator;\n } else {\n return _buildDomainSeparator();\n }\n }\n\n function _buildDomainSeparator() private view returns (bytes32) {\n return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n\n /// @inheritdoc IERC5267\n function eip712Domain()\n public\n view\n virtual\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\"0f\", // 01111\n _EIP712Name(),\n _EIP712Version(),\n block.chainid,\n address(this),\n bytes32(0),\n new uint256[](0)\n );\n }\n\n /**\n * @dev The name parameter for the EIP712 domain.\n *\n * NOTE: By default this function reads _name which is an immutable value.\n * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).\n */\n // solhint-disable-next-line func-name-mixedcase\n function _EIP712Name() internal view returns (string memory) {\n return _name.toStringWithFallback(_nameFallback);\n }\n\n /**\n * @dev The version parameter for the EIP712 domain.\n *\n * NOTE: By default this function reads _version which is an immutable value.\n * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).\n */\n // solhint-disable-next-line func-name-mixedcase\n function _EIP712Version() internal view returns (string memory) {\n return _version.toStringWithFallback(_versionFallback);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (utils/cryptography/MessageHashUtils.sol)\n\npragma solidity ^0.8.24;\n\nimport {Strings} from \"../Strings.sol\";\n\n/**\n * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.\n *\n * The library provides methods for generating a hash of a message that conforms to the\n * https://eips.ethereum.org/EIPS/eip-191[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]\n * specifications.\n */\nlibrary MessageHashUtils {\n error ERC5267ExtensionsNotSupported();\n\n /**\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\n * `0x45` (`personal_sign` messages).\n *\n * The digest is calculated by prefixing a bytes32 `messageHash` with\n * `\"\\x19Ethereum Signed Message:\\n32\"` and hashing the result. It corresponds with the\n * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.\n *\n * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with\n * keccak256, although any bytes32 value can be safely used because the final digest will\n * be re-hashed.\n *\n * See {ECDSA-recover}.\n */\n function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {\n assembly (\"memory-safe\") {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\") // 32 is the bytes-length of messageHash\n mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix\n digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)\n }\n }\n\n /**\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\n * `0x45` (`personal_sign` messages).\n *\n * The digest is calculated by prefixing an arbitrary `message` with\n * `\"\\x19Ethereum Signed Message:\\n\" + len(message)` and hashing the result. It corresponds with the\n * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.\n *\n * See {ECDSA-recover}.\n */\n function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {\n return\n keccak256(bytes.concat(\"\\x19Ethereum Signed Message:\\n\", bytes(Strings.toString(message.length)), message));\n }\n\n /**\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\n * `0x00` (data with intended validator).\n *\n * The digest is calculated by prefixing an arbitrary `data` with `\"\\x19\\x00\"` and the intended\n * `validator` address. Then hashing the result.\n *\n * See {ECDSA-recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(hex\"19_00\", validator, data));\n }\n\n /**\n * @dev Variant of {toDataWithIntendedValidatorHash-address-bytes} optimized for cases where `data` is a bytes32.\n */\n function toDataWithIntendedValidatorHash(\n address validator,\n bytes32 messageHash\n ) internal pure returns (bytes32 digest) {\n assembly (\"memory-safe\") {\n mstore(0x00, hex\"19_00\")\n mstore(0x02, shl(96, validator))\n mstore(0x16, messageHash)\n digest := keccak256(0x00, 0x36)\n }\n }\n\n /**\n * @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`).\n *\n * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with\n * `\\x19\\x01` and hashing the result. It corresponds to the hash signed by the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.\n *\n * See {ECDSA-recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {\n assembly (\"memory-safe\") {\n let ptr := mload(0x40)\n mstore(ptr, hex\"19_01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n digest := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns the EIP-712 domain separator constructed from an `eip712Domain`. See {IERC5267-eip712Domain}\n *\n * This function dynamically constructs the domain separator based on which fields are present in the\n * `fields` parameter. It contains flags that indicate which domain fields are present:\n *\n * * Bit 0 (0x01): name\n * * Bit 1 (0x02): version\n * * Bit 2 (0x04): chainId\n * * Bit 3 (0x08): verifyingContract\n * * Bit 4 (0x10): salt\n *\n * Arguments that correspond to fields which are not present in `fields` are ignored. For example, if `fields` is\n * `0x0f` (`0b01111`), then the `salt` parameter is ignored.\n */\n function toDomainSeparator(\n bytes1 fields,\n string memory name,\n string memory version,\n uint256 chainId,\n address verifyingContract,\n bytes32 salt\n ) internal pure returns (bytes32 hash) {\n return\n toDomainSeparator(\n fields,\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n chainId,\n verifyingContract,\n salt\n );\n }\n\n /// @dev Variant of {toDomainSeparator-bytes1-string-string-uint256-address-bytes32} that uses hashed name and version.\n function toDomainSeparator(\n bytes1 fields,\n bytes32 nameHash,\n bytes32 versionHash,\n uint256 chainId,\n address verifyingContract,\n bytes32 salt\n ) internal pure returns (bytes32 hash) {\n bytes32 domainTypeHash = toDomainTypeHash(fields);\n\n assembly (\"memory-safe\") {\n // align fields to the right for easy processing\n fields := shr(248, fields)\n\n // FMP used as scratch space\n let fmp := mload(0x40)\n mstore(fmp, domainTypeHash)\n\n let ptr := add(fmp, 0x20)\n if and(fields, 0x01) {\n mstore(ptr, nameHash)\n ptr := add(ptr, 0x20)\n }\n if and(fields, 0x02) {\n mstore(ptr, versionHash)\n ptr := add(ptr, 0x20)\n }\n if and(fields, 0x04) {\n mstore(ptr, chainId)\n ptr := add(ptr, 0x20)\n }\n if and(fields, 0x08) {\n mstore(ptr, verifyingContract)\n ptr := add(ptr, 0x20)\n }\n if and(fields, 0x10) {\n mstore(ptr, salt)\n ptr := add(ptr, 0x20)\n }\n\n hash := keccak256(fmp, sub(ptr, fmp))\n }\n }\n\n /// @dev Builds an EIP-712 domain type hash depending on the `fields` provided, following https://eips.ethereum.org/EIPS/eip-5267[ERC-5267]\n function toDomainTypeHash(bytes1 fields) internal pure returns (bytes32 hash) {\n if (fields & 0x20 == 0x20) revert ERC5267ExtensionsNotSupported();\n\n assembly (\"memory-safe\") {\n // align fields to the right for easy processing\n fields := shr(248, fields)\n\n // FMP used as scratch space\n let fmp := mload(0x40)\n mstore(fmp, \"EIP712Domain(\")\n\n let ptr := add(fmp, 0x0d)\n // name field\n if and(fields, 0x01) {\n mstore(ptr, \"string name,\")\n ptr := add(ptr, 0x0c)\n }\n // version field\n if and(fields, 0x02) {\n mstore(ptr, \"string version,\")\n ptr := add(ptr, 0x0f)\n }\n // chainId field\n if and(fields, 0x04) {\n mstore(ptr, \"uint256 chainId,\")\n ptr := add(ptr, 0x10)\n }\n // verifyingContract field\n if and(fields, 0x08) {\n mstore(ptr, \"address verifyingContract,\")\n ptr := add(ptr, 0x1a)\n }\n // salt field\n if and(fields, 0x10) {\n mstore(ptr, \"bytes32 salt,\")\n ptr := add(ptr, 0x0d)\n }\n // if any field is enabled, remove the trailing comma\n ptr := sub(ptr, iszero(iszero(and(fields, 0x1f))))\n // add the closing brace\n mstore8(ptr, 0x29) // add closing brace\n ptr := add(ptr, 1)\n\n hash := keccak256(fmp, sub(ptr, fmp))\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/signers/AbstractSigner.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/signers/AbstractSigner.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Abstract contract for signature validation.\n *\n * Developers must implement {_rawSignatureValidation} and use it as the lowest-level signature validation mechanism.\n *\n * @custom:stateless\n */\nabstract contract AbstractSigner {\n /**\n * @dev Signature validation algorithm.\n *\n * WARNING: Implementing a signature validation algorithm is a security-sensitive operation as it involves\n * cryptographic verification. It is important to review and test thoroughly before deployment. Consider\n * using one of the signature verification libraries (xref:api:utils/cryptography#ECDSA[ECDSA],\n * xref:api:utils/cryptography#P256[P256] or xref:api:utils/cryptography#RSA[RSA]).\n */\n function _rawSignatureValidation(bytes32 hash, bytes calldata signature) internal view virtual returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/signers/SignerEIP7702.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (utils/cryptography/signers/SignerEIP7702.sol)\n\npragma solidity ^0.8.20;\n\nimport {AbstractSigner} from \"./AbstractSigner.sol\";\nimport {ECDSA} from \"../ECDSA.sol\";\n\n/**\n * @dev Implementation of {AbstractSigner} for implementation for an EOA. Useful for EIP-7702 accounts.\n *\n * @custom:stateless\n */\nabstract contract SignerEIP7702 is AbstractSigner {\n /**\n * @dev Validates the signature using the EOA's address (i.e. `address(this)`).\n */\n function _rawSignatureValidation(\n bytes32 hash,\n bytes calldata signature\n ) internal view virtual override returns (bool) {\n (address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecoverCalldata(hash, signature);\n return address(this) == recovered && err == ECDSA.RecoverError.NoError;\n }\n}\n" }, "@openzeppelin/contracts/utils/Errors.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of common custom errors used in multiple contracts\n *\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\n * It is recommended to avoid relying on the error API for critical functionality.\n *\n * _Available since v5.1._\n */\nlibrary Errors {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error InsufficientBalance(uint256 balance, uint256 needed);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedCall();\n\n /**\n * @dev The deployment failed.\n */\n error FailedDeployment();\n\n /**\n * @dev A necessary precompile is missing.\n */\n error MissingPrecompile(address);\n}\n" }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 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 */\nabstract contract ERC165 is IERC165 {\n /// @inheritdoc IERC165\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, "@openzeppelin/contracts/utils/introspection/IERC165.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\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[ERC 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" }, "@openzeppelin/contracts/utils/LowLevelCall.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (utils/LowLevelCall.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library of low level call functions that implement different calling strategies to deal with the return data.\n *\n * WARNING: Using this library requires an advanced understanding of Solidity and how the EVM works. It is recommended\n * to use the {Address} library instead.\n */\nlibrary LowLevelCall {\n /// @dev Performs a Solidity function call using a low level `call` and ignoring the return data.\n function callNoReturn(address target, bytes memory data) internal returns (bool success) {\n return callNoReturn(target, 0, data);\n }\n\n /// @dev Same as {callNoReturn-address-bytes}, but allows specifying the value to be sent in the call.\n function callNoReturn(address target, uint256 value, bytes memory data) internal returns (bool success) {\n assembly (\"memory-safe\") {\n success := call(gas(), target, value, add(data, 0x20), mload(data), 0x00, 0x00)\n }\n }\n\n /// @dev Performs a Solidity function call using a low level `call` and returns the first 64 bytes of the result\n /// in the scratch space of memory. Useful for functions that return a tuple with two single-word values.\n ///\n /// WARNING: Do not assume that the results are zero if `success` is false. Memory can be already allocated\n /// and this function doesn't zero it out.\n function callReturn64Bytes(\n address target,\n bytes memory data\n ) internal returns (bool success, bytes32 result1, bytes32 result2) {\n return callReturn64Bytes(target, 0, data);\n }\n\n /// @dev Same as {callReturn64Bytes-address-bytes}, but allows specifying the value to be sent in the call.\n function callReturn64Bytes(\n address target,\n uint256 value,\n bytes memory data\n ) internal returns (bool success, bytes32 result1, bytes32 result2) {\n assembly (\"memory-safe\") {\n success := call(gas(), target, value, add(data, 0x20), mload(data), 0x00, 0x40)\n result1 := mload(0x00)\n result2 := mload(0x20)\n }\n }\n\n /// @dev Performs a Solidity function call using a low level `staticcall` and ignoring the return data.\n function staticcallNoReturn(address target, bytes memory data) internal view returns (bool success) {\n assembly (\"memory-safe\") {\n success := staticcall(gas(), target, add(data, 0x20), mload(data), 0x00, 0x00)\n }\n }\n\n /// @dev Performs a Solidity function call using a low level `staticcall` and returns the first 64 bytes of the result\n /// in the scratch space of memory. Useful for functions that return a tuple with two single-word values.\n ///\n /// WARNING: Do not assume that the results are zero if `success` is false. Memory can be already allocated\n /// and this function doesn't zero it out.\n function staticcallReturn64Bytes(\n address target,\n bytes memory data\n ) internal view returns (bool success, bytes32 result1, bytes32 result2) {\n assembly (\"memory-safe\") {\n success := staticcall(gas(), target, add(data, 0x20), mload(data), 0x00, 0x40)\n result1 := mload(0x00)\n result2 := mload(0x20)\n }\n }\n\n /// @dev Performs a Solidity function call using a low level `delegatecall` and ignoring the return data.\n function delegatecallNoReturn(address target, bytes memory data) internal returns (bool success) {\n assembly (\"memory-safe\") {\n success := delegatecall(gas(), target, add(data, 0x20), mload(data), 0x00, 0x00)\n }\n }\n\n /// @dev Performs a Solidity function call using a low level `delegatecall` and returns the first 64 bytes of the result\n /// in the scratch space of memory. Useful for functions that return a tuple with two single-word values.\n ///\n /// WARNING: Do not assume that the results are zero if `success` is false. Memory can be already allocated\n /// and this function doesn't zero it out.\n function delegatecallReturn64Bytes(\n address target,\n bytes memory data\n ) internal returns (bool success, bytes32 result1, bytes32 result2) {\n assembly (\"memory-safe\") {\n success := delegatecall(gas(), target, add(data, 0x20), mload(data), 0x00, 0x40)\n result1 := mload(0x00)\n result2 := mload(0x20)\n }\n }\n\n /// @dev Returns the size of the return data buffer.\n function returnDataSize() internal pure returns (uint256 size) {\n assembly (\"memory-safe\") {\n size := returndatasize()\n }\n }\n\n /// @dev Returns a buffer containing the return data from the last call.\n function returnData() internal pure returns (bytes memory result) {\n assembly (\"memory-safe\") {\n result := mload(0x40)\n mstore(result, returndatasize())\n returndatacopy(add(result, 0x20), 0x00, returndatasize())\n mstore(0x40, add(result, add(0x20, returndatasize())))\n }\n }\n\n /// @dev Revert with the return data from the last call.\n function bubbleRevert() internal pure {\n assembly (\"memory-safe\") {\n let fmp := mload(0x40)\n returndatacopy(fmp, 0x00, returndatasize())\n revert(fmp, returndatasize())\n }\n }\n\n function bubbleRevert(bytes memory returndata) internal pure {\n assembly (\"memory-safe\") {\n revert(add(returndata, 0x20), mload(returndata))\n }\n }\n}\n" }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\nimport {Panic} from \"../Panic.sol\";\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Floor, // Toward negative infinity\n Ceil, // Toward positive infinity\n Trunc, // Toward zero\n Expand // Away from zero\n }\n\n /**\n * @dev Return the 512-bit addition of two uint256.\n *\n * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.\n */\n function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n assembly (\"memory-safe\") {\n low := add(a, b)\n high := lt(low, a)\n }\n }\n\n /**\n * @dev Return the 512-bit multiplication of two uint256.\n *\n * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.\n */\n function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = high * 2²⁵⁶ + low.\n assembly (\"memory-safe\") {\n let mm := mulmod(a, b, not(0))\n low := mul(a, b)\n high := sub(sub(mm, low), lt(mm, low))\n }\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n uint256 c = a + b;\n success = c >= a;\n result = c * SafeCast.toUint(success);\n }\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n uint256 c = a - b;\n success = c <= a;\n result = c * SafeCast.toUint(success);\n }\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n uint256 c = a * b;\n assembly (\"memory-safe\") {\n // Only true when the multiplication doesn't overflow\n // (c / a == b) || (a == 0)\n success := or(eq(div(c, a), b), iszero(a))\n }\n // equivalent to: success ? c : 0\n result = c * SafeCast.toUint(success);\n }\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n success = b > 0;\n assembly (\"memory-safe\") {\n // The `DIV` opcode returns zero when the denominator is 0.\n result := div(a, b)\n }\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n success = b > 0;\n assembly (\"memory-safe\") {\n // The `MOD` opcode returns zero when the denominator is 0.\n result := mod(a, b)\n }\n }\n }\n\n /**\n * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.\n */\n function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\n (bool success, uint256 result) = tryAdd(a, b);\n return ternary(success, result, type(uint256).max);\n }\n\n /**\n * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\n */\n function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\n (, uint256 result) = trySub(a, b);\n return result;\n }\n\n /**\n * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.\n */\n function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\n (bool success, uint256 result) = tryMul(a, b);\n return ternary(success, result, type(uint256).max);\n }\n\n /**\n * @dev Branchless ternary evaluation for `condition ? a : b`. Gas costs are constant.\n *\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n * However, the compiler may optimize Solidity ternary operations (i.e. `condition ? a : b`) to only compute\n * one branch when needed, making this function more expensive.\n */\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\n unchecked {\n // branchless ternary works because:\n // b ^ (a ^ b) == a\n // b ^ 0 == b\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\n }\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 ternary(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 ternary(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 unchecked {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\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 towards infinity instead\n * of rounding towards zero.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n if (b == 0) {\n // Guarantee the same behavior as in a regular Solidity division.\n Panic.panic(Panic.DIVISION_BY_ZERO);\n }\n\n // The following calculation ensures accurate ceiling division without overflow.\n // Since a is non-zero, (a - 1) / b will not overflow.\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\n // but the largest value we can obtain is type(uint256).max - 1, which happens\n // when a = type(uint256).max and b = 1.\n unchecked {\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\n }\n }\n\n /**\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n * denominator == 0.\n *\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n * Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n (uint256 high, uint256 low) = mul512(x, y);\n\n // Handle non-overflow cases, 256 by 256 division.\n if (high == 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 low / denominator;\n }\n\n // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.\n if (denominator <= high) {\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\n }\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [high low].\n uint256 remainder;\n assembly (\"memory-safe\") {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n high := sub(high, gt(remainder, low))\n low := sub(low, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n uint256 twos = denominator & (0 - denominator);\n assembly (\"memory-safe\") {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [high low] by twos.\n low := div(low, twos)\n\n // Flip twos such that it is 2²⁵⁶ / 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 high into low.\n low |= high * twos;\n\n // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such\n // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv ≡ 1 mod 2⁴.\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\n // works in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2⁸\n inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶\n inverse *= 2 - denominator * inverse; // inverse mod 2³²\n inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴\n inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸\n inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶\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²⁵⁶. Since the preconditions guarantee that the outcome is\n // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high\n // is no longer required.\n result = low * inverse;\n return result;\n }\n }\n\n /**\n * @dev 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 return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\n }\n\n /**\n * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\n */\n function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\n unchecked {\n (uint256 high, uint256 low) = mul512(x, y);\n if (high >= 1 << n) {\n Panic.panic(Panic.UNDER_OVERFLOW);\n }\n return (high << (256 - n)) | (low >> n);\n }\n }\n\n /**\n * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\n */\n function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\n return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\n }\n\n /**\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\n *\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\n *\n * If the input value is not inversible, 0 is returned.\n *\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\n */\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\n unchecked {\n if (n == 0) return 0;\n\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\n // ax + ny = 1\n // ax = 1 + (-y)n\n // ax ≡ 1 (mod n) # x is the inverse of a modulo n\n\n // If the remainder is 0 the gcd is n right away.\n uint256 remainder = a % n;\n uint256 gcd = n;\n\n // Therefore the initial coefficients are:\n // ax + ny = gcd(a, n) = n\n // 0a + 1n = n\n int256 x = 0;\n int256 y = 1;\n\n while (remainder != 0) {\n uint256 quotient = gcd / remainder;\n\n (gcd, remainder) = (\n // The old remainder is the next gcd to try.\n remainder,\n // Compute the next remainder.\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\n // where gcd is at most n (capped to type(uint256).max)\n gcd - remainder * quotient\n );\n\n (x, y) = (\n // Increment the coefficient of a.\n y,\n // Decrement the coefficient of n.\n // Can overflow, but the result is casted to uint256 so that the\n // next value of y is \"wrapped around\" to a value between 0 and n - 1.\n x - y * int256(quotient)\n );\n }\n\n if (gcd != 1) return 0; // No inverse exists.\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\n }\n }\n\n /**\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\n *\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\n * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\n *\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\n */\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\n unchecked {\n return Math.modExp(a, p - 2, p);\n }\n }\n\n /**\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\n *\n * Requirements:\n * - modulus can't be zero\n * - underlying staticcall to precompile must succeed\n *\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\n * interpreted as 0.\n */\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\n (bool success, uint256 result) = tryModExp(b, e, m);\n if (!success) {\n Panic.panic(Panic.DIVISION_BY_ZERO);\n }\n return result;\n }\n\n /**\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\n * to operate modulo 0 or if the underlying precompile reverted.\n *\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\n * of a revert, but the result may be incorrectly interpreted as 0.\n */\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\n if (m == 0) return (false, 0);\n assembly (\"memory-safe\") {\n let ptr := mload(0x40)\n // | Offset | Content | Content (Hex) |\n // |-----------|------------|--------------------------------------------------------------------|\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\n mstore(ptr, 0x20)\n mstore(add(ptr, 0x20), 0x20)\n mstore(add(ptr, 0x40), 0x20)\n mstore(add(ptr, 0x60), b)\n mstore(add(ptr, 0x80), e)\n mstore(add(ptr, 0xa0), m)\n\n // Given the result < m, it's guaranteed to fit in 32 bytes,\n // so we can use the memory scratch space located at offset 0.\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\n result := mload(0x00)\n }\n }\n\n /**\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\n */\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\n (bool success, bytes memory result) = tryModExp(b, e, m);\n if (!success) {\n Panic.panic(Panic.DIVISION_BY_ZERO);\n }\n return result;\n }\n\n /**\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\n */\n function tryModExp(\n bytes memory b,\n bytes memory e,\n bytes memory m\n ) internal view returns (bool success, bytes memory result) {\n if (_zeroBytes(m)) return (false, new bytes(0));\n\n uint256 mLen = m.length;\n\n // Encode call args in result and move the free memory pointer\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\n\n assembly (\"memory-safe\") {\n let dataPtr := add(result, 0x20)\n // Write result on top of args to avoid allocating extra memory.\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\n // Overwrite the length.\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\n mstore(result, mLen)\n // Set the memory pointer after the returned data.\n mstore(0x40, add(dataPtr, mLen))\n }\n }\n\n /**\n * @dev Returns whether the provided byte array is zero.\n */\n function _zeroBytes(bytes memory buffer) private pure returns (bool) {\n uint256 chunk;\n for (uint256 i = 0; i < buffer.length; i += 0x20) {\n // See _unsafeReadBytesOffset from utils/Bytes.sol\n assembly (\"memory-safe\") {\n chunk := mload(add(add(buffer, 0x20), i))\n }\n if (chunk >> (8 * saturatingSub(i + 0x20, buffer.length)) != 0) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n * towards zero.\n *\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\n * using integer operations.\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n unchecked {\n // Take care of easy edge cases when a == 0 or a == 1\n if (a <= 1) {\n return a;\n }\n\n // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\n // the current value as `ε_n = | x_n - sqrt(a) |`.\n //\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\n // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is\n // bigger than any uint256.\n //\n // By noticing that\n // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\n // to the msb function.\n uint256 aa = a;\n uint256 xn = 1;\n\n if (aa >= (1 << 128)) {\n aa >>= 128;\n xn <<= 64;\n }\n if (aa >= (1 << 64)) {\n aa >>= 64;\n xn <<= 32;\n }\n if (aa >= (1 << 32)) {\n aa >>= 32;\n xn <<= 16;\n }\n if (aa >= (1 << 16)) {\n aa >>= 16;\n xn <<= 8;\n }\n if (aa >= (1 << 8)) {\n aa >>= 8;\n xn <<= 4;\n }\n if (aa >= (1 << 4)) {\n aa >>= 4;\n xn <<= 2;\n }\n if (aa >= (1 << 2)) {\n xn <<= 1;\n }\n\n // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).\n //\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).\n // This is going to be our x_0 (and ε_0)\n xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)\n\n // From here, Newton's method give us:\n // x_{n+1} = (x_n + a / x_n) / 2\n //\n // One should note that:\n // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a\n // = ((x_n² + a) / (2 * x_n))² - a\n // = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a\n // = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)\n // = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)\n // = (x_n² - a)² / (2 * x_n)²\n // = ((x_n² - a) / (2 * x_n))²\n // ≥ 0\n // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n\n //\n // This gives us the proof of quadratic convergence of the sequence:\n // ε_{n+1} = | x_{n+1} - sqrt(a) |\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\n // = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |\n // = | (x_n - sqrt(a))² / (2 * x_n) |\n // = | ε_n² / (2 * x_n) |\n // = ε_n² / | (2 * x_n) |\n //\n // For the first iteration, we have a special case where x_0 is known:\n // ε_1 = ε_0² / | (2 * x_0) |\n // ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))\n // ≤ 2**(2*e-4) / (3 * 2**(e-1))\n // ≤ 2**(e-3) / 3\n // ≤ 2**(e-3-log2(3))\n // ≤ 2**(e-4.5)\n //\n // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:\n // ε_{n+1} = ε_n² / | (2 * x_n) |\n // ≤ (2**(e-k))² / (2 * 2**(e-1))\n // ≤ 2**(2*e-2*k) / 2**e\n // ≤ 2**(e-2*k)\n xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above\n xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5\n xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9\n xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18\n xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36\n xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72\n\n // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision\n // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\n // sqrt(a) or sqrt(a) + 1.\n return xn - SafeCast.toUint(xn > a / xn);\n }\n }\n\n /**\n * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\n }\n }\n\n /**\n * @dev Return the log in base 2 of a positive value rounded towards zero.\n * Returns 0 if given 0.\n */\n function log2(uint256 x) internal pure returns (uint256 r) {\n // If value has upper 128 bits set, log2 result is at least 128\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n // If upper 64 bits of 128-bit half set, add 64 to result\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n // If upper 32 bits of 64-bit half set, add 32 to result\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n // If upper 16 bits of 32-bit half set, add 16 to result\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n // If upper 8 bits of 16-bit half set, add 8 to result\n r |= SafeCast.toUint((x >> r) > 0xff) << 3;\n // If upper 4 bits of 8-bit half set, add 4 to result\n r |= SafeCast.toUint((x >> r) > 0xf) << 2;\n\n // Shifts value right by the current result and use it as an index into this lookup table:\n //\n // | x (4 bits) | index | table[index] = MSB position |\n // |------------|---------|-----------------------------|\n // | 0000 | 0 | table[0] = 0 |\n // | 0001 | 1 | table[1] = 0 |\n // | 0010 | 2 | table[2] = 1 |\n // | 0011 | 3 | table[3] = 1 |\n // | 0100 | 4 | table[4] = 2 |\n // | 0101 | 5 | table[5] = 2 |\n // | 0110 | 6 | table[6] = 2 |\n // | 0111 | 7 | table[7] = 2 |\n // | 1000 | 8 | table[8] = 3 |\n // | 1001 | 9 | table[9] = 3 |\n // | 1010 | 10 | table[10] = 3 |\n // | 1011 | 11 | table[11] = 3 |\n // | 1100 | 12 | table[12] = 3 |\n // | 1101 | 13 | table[13] = 3 |\n // | 1110 | 14 | table[14] = 3 |\n // | 1111 | 15 | table[15] = 3 |\n //\n // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the first 16 bytes (most significant half).\n assembly (\"memory-safe\") {\n r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\n }\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\n }\n }\n\n /**\n * @dev Return the log in base 10 of a positive value rounded towards zero.\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\n }\n }\n\n /**\n * @dev Return the log in base 256 of a positive value rounded towards zero.\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 x) internal pure returns (uint256 r) {\n // If value has upper 128 bits set, log2 result is at least 128\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n // If upper 64 bits of 128-bit half set, add 64 to result\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n // If upper 32 bits of 64-bit half set, add 32 to result\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n // If upper 16 bits of 32-bit half set, add 16 to result\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\n return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\n }\n }\n\n /**\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n */\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n return uint8(rounding) % 2 == 1;\n }\n\n /**\n * @dev Counts the number of leading zero bits in a uint256.\n */\n function clz(uint256 x) internal pure returns (uint256) {\n return ternary(x == 0, 256, 255 - log2(x));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX/bool 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 */\nlibrary SafeCast {\n /**\n * @dev Value doesn't fit in a uint of `bits` size.\n */\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\n\n /**\n * @dev An int value doesn't fit in a uint of `bits` size.\n */\n error SafeCastOverflowedIntToUint(int256 value);\n\n /**\n * @dev Value doesn't fit in an int of `bits` size.\n */\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\n\n /**\n * @dev A uint value doesn't fit in an int of `bits` size.\n */\n error SafeCastOverflowedUintToInt(uint256 value);\n\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 function toUint248(uint256 value) internal pure returns (uint248) {\n if (value > type(uint248).max) {\n revert SafeCastOverflowedUintDowncast(248, value);\n }\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 function toUint240(uint256 value) internal pure returns (uint240) {\n if (value > type(uint240).max) {\n revert SafeCastOverflowedUintDowncast(240, value);\n }\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 function toUint232(uint256 value) internal pure returns (uint232) {\n if (value > type(uint232).max) {\n revert SafeCastOverflowedUintDowncast(232, value);\n }\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 function toUint224(uint256 value) internal pure returns (uint224) {\n if (value > type(uint224).max) {\n revert SafeCastOverflowedUintDowncast(224, value);\n }\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 function toUint216(uint256 value) internal pure returns (uint216) {\n if (value > type(uint216).max) {\n revert SafeCastOverflowedUintDowncast(216, value);\n }\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 function toUint208(uint256 value) internal pure returns (uint208) {\n if (value > type(uint208).max) {\n revert SafeCastOverflowedUintDowncast(208, value);\n }\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 function toUint200(uint256 value) internal pure returns (uint200) {\n if (value > type(uint200).max) {\n revert SafeCastOverflowedUintDowncast(200, value);\n }\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 function toUint192(uint256 value) internal pure returns (uint192) {\n if (value > type(uint192).max) {\n revert SafeCastOverflowedUintDowncast(192, value);\n }\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 function toUint184(uint256 value) internal pure returns (uint184) {\n if (value > type(uint184).max) {\n revert SafeCastOverflowedUintDowncast(184, value);\n }\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 function toUint176(uint256 value) internal pure returns (uint176) {\n if (value > type(uint176).max) {\n revert SafeCastOverflowedUintDowncast(176, value);\n }\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 function toUint168(uint256 value) internal pure returns (uint168) {\n if (value > type(uint168).max) {\n revert SafeCastOverflowedUintDowncast(168, value);\n }\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 function toUint160(uint256 value) internal pure returns (uint160) {\n if (value > type(uint160).max) {\n revert SafeCastOverflowedUintDowncast(160, value);\n }\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 function toUint152(uint256 value) internal pure returns (uint152) {\n if (value > type(uint152).max) {\n revert SafeCastOverflowedUintDowncast(152, value);\n }\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 function toUint144(uint256 value) internal pure returns (uint144) {\n if (value > type(uint144).max) {\n revert SafeCastOverflowedUintDowncast(144, value);\n }\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 function toUint136(uint256 value) internal pure returns (uint136) {\n if (value > type(uint136).max) {\n revert SafeCastOverflowedUintDowncast(136, value);\n }\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 function toUint128(uint256 value) internal pure returns (uint128) {\n if (value > type(uint128).max) {\n revert SafeCastOverflowedUintDowncast(128, value);\n }\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 function toUint120(uint256 value) internal pure returns (uint120) {\n if (value > type(uint120).max) {\n revert SafeCastOverflowedUintDowncast(120, value);\n }\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 function toUint112(uint256 value) internal pure returns (uint112) {\n if (value > type(uint112).max) {\n revert SafeCastOverflowedUintDowncast(112, value);\n }\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 function toUint104(uint256 value) internal pure returns (uint104) {\n if (value > type(uint104).max) {\n revert SafeCastOverflowedUintDowncast(104, value);\n }\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 function toUint96(uint256 value) internal pure returns (uint96) {\n if (value > type(uint96).max) {\n revert SafeCastOverflowedUintDowncast(96, value);\n }\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 function toUint88(uint256 value) internal pure returns (uint88) {\n if (value > type(uint88).max) {\n revert SafeCastOverflowedUintDowncast(88, value);\n }\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 function toUint80(uint256 value) internal pure returns (uint80) {\n if (value > type(uint80).max) {\n revert SafeCastOverflowedUintDowncast(80, value);\n }\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 function toUint72(uint256 value) internal pure returns (uint72) {\n if (value > type(uint72).max) {\n revert SafeCastOverflowedUintDowncast(72, value);\n }\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 function toUint64(uint256 value) internal pure returns (uint64) {\n if (value > type(uint64).max) {\n revert SafeCastOverflowedUintDowncast(64, value);\n }\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 function toUint56(uint256 value) internal pure returns (uint56) {\n if (value > type(uint56).max) {\n revert SafeCastOverflowedUintDowncast(56, value);\n }\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 function toUint48(uint256 value) internal pure returns (uint48) {\n if (value > type(uint48).max) {\n revert SafeCastOverflowedUintDowncast(48, value);\n }\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 function toUint40(uint256 value) internal pure returns (uint40) {\n if (value > type(uint40).max) {\n revert SafeCastOverflowedUintDowncast(40, value);\n }\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 function toUint32(uint256 value) internal pure returns (uint32) {\n if (value > type(uint32).max) {\n revert SafeCastOverflowedUintDowncast(32, value);\n }\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 function toUint24(uint256 value) internal pure returns (uint24) {\n if (value > type(uint24).max) {\n revert SafeCastOverflowedUintDowncast(24, value);\n }\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 function toUint16(uint256 value) internal pure returns (uint16) {\n if (value > type(uint16).max) {\n revert SafeCastOverflowedUintDowncast(16, value);\n }\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 function toUint8(uint256 value) internal pure returns (uint8) {\n if (value > type(uint8).max) {\n revert SafeCastOverflowedUintDowncast(8, value);\n }\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 function toUint256(int256 value) internal pure returns (uint256) {\n if (value < 0) {\n revert SafeCastOverflowedIntToUint(value);\n }\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 function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(248, value);\n }\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 function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(240, value);\n }\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 function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(232, value);\n }\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 function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(224, value);\n }\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 function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(216, value);\n }\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 function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(208, value);\n }\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 function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(200, value);\n }\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 function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(192, value);\n }\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 function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(184, value);\n }\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 function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(176, value);\n }\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 function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(168, value);\n }\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 function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(160, value);\n }\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 function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(152, value);\n }\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 function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(144, value);\n }\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 function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(136, value);\n }\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 function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(128, value);\n }\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 function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(120, value);\n }\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 function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(112, value);\n }\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 function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(104, value);\n }\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 function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(96, value);\n }\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 function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(88, value);\n }\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 function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(80, value);\n }\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 function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(72, value);\n }\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 function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(64, value);\n }\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 function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(56, value);\n }\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 function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(48, value);\n }\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 function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(40, value);\n }\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 function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(32, value);\n }\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 function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(24, value);\n }\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 function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(16, value);\n }\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 function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(8, value);\n }\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 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 if (value > uint256(type(int256).max)) {\n revert SafeCastOverflowedUintToInt(value);\n }\n return int256(value);\n }\n\n /**\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\n */\n function toUint(bool b) internal pure returns (uint256 u) {\n assembly (\"memory-safe\") {\n u := iszero(iszero(b))\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.20;\n\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\n *\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\n * one branch when needed, making this function more expensive.\n */\n function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {\n unchecked {\n // branchless ternary works because:\n // b ^ (a ^ b) == a\n // b ^ 0 == b\n return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));\n }\n }\n\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return ternary(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 ternary(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 // Formula from the \"Bit Twiddling Hacks\" by Sean Eron Anderson.\n // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,\n // taking advantage of the most significant (or \"sign\" bit) in two's complement representation.\n // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,\n // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).\n int256 mask = n >> 255;\n\n // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.\n return uint256((n + mask) ^ mask);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Packing.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.2.0) (utils/Packing.sol)\n// This file was procedurally generated from scripts/generate/templates/Packing.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Helper library packing and unpacking multiple values into bytesXX.\n *\n * Example usage:\n *\n * ```solidity\n * library MyPacker {\n * type MyType is bytes32;\n *\n * function _pack(address account, bytes4 selector, uint64 period) external pure returns (MyType) {\n * bytes12 subpack = Packing.pack_4_8(selector, bytes8(period));\n * bytes32 pack = Packing.pack_20_12(bytes20(account), subpack);\n * return MyType.wrap(pack);\n * }\n *\n * function _unpack(MyType self) external pure returns (address, bytes4, uint64) {\n * bytes32 pack = MyType.unwrap(self);\n * return (\n * address(Packing.extract_32_20(pack, 0)),\n * Packing.extract_32_4(pack, 20),\n * uint64(Packing.extract_32_8(pack, 24))\n * );\n * }\n * }\n * ```\n *\n * _Available since v5.1._\n */\n// solhint-disable func-name-mixedcase\nlibrary Packing {\n error OutOfRangeAccess();\n\n function pack_1_1(bytes1 left, bytes1 right) internal pure returns (bytes2 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(248, not(0)))\n right := and(right, shl(248, not(0)))\n result := or(left, shr(8, right))\n }\n }\n\n function pack_2_2(bytes2 left, bytes2 right) internal pure returns (bytes4 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(240, not(0)))\n right := and(right, shl(240, not(0)))\n result := or(left, shr(16, right))\n }\n }\n\n function pack_2_4(bytes2 left, bytes4 right) internal pure returns (bytes6 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(240, not(0)))\n right := and(right, shl(224, not(0)))\n result := or(left, shr(16, right))\n }\n }\n\n function pack_2_6(bytes2 left, bytes6 right) internal pure returns (bytes8 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(240, not(0)))\n right := and(right, shl(208, not(0)))\n result := or(left, shr(16, right))\n }\n }\n\n function pack_2_8(bytes2 left, bytes8 right) internal pure returns (bytes10 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(240, not(0)))\n right := and(right, shl(192, not(0)))\n result := or(left, shr(16, right))\n }\n }\n\n function pack_2_10(bytes2 left, bytes10 right) internal pure returns (bytes12 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(240, not(0)))\n right := and(right, shl(176, not(0)))\n result := or(left, shr(16, right))\n }\n }\n\n function pack_2_20(bytes2 left, bytes20 right) internal pure returns (bytes22 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(240, not(0)))\n right := and(right, shl(96, not(0)))\n result := or(left, shr(16, right))\n }\n }\n\n function pack_2_22(bytes2 left, bytes22 right) internal pure returns (bytes24 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(240, not(0)))\n right := and(right, shl(80, not(0)))\n result := or(left, shr(16, right))\n }\n }\n\n function pack_4_2(bytes4 left, bytes2 right) internal pure returns (bytes6 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(224, not(0)))\n right := and(right, shl(240, not(0)))\n result := or(left, shr(32, right))\n }\n }\n\n function pack_4_4(bytes4 left, bytes4 right) internal pure returns (bytes8 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(224, not(0)))\n right := and(right, shl(224, not(0)))\n result := or(left, shr(32, right))\n }\n }\n\n function pack_4_6(bytes4 left, bytes6 right) internal pure returns (bytes10 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(224, not(0)))\n right := and(right, shl(208, not(0)))\n result := or(left, shr(32, right))\n }\n }\n\n function pack_4_8(bytes4 left, bytes8 right) internal pure returns (bytes12 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(224, not(0)))\n right := and(right, shl(192, not(0)))\n result := or(left, shr(32, right))\n }\n }\n\n function pack_4_12(bytes4 left, bytes12 right) internal pure returns (bytes16 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(224, not(0)))\n right := and(right, shl(160, not(0)))\n result := or(left, shr(32, right))\n }\n }\n\n function pack_4_16(bytes4 left, bytes16 right) internal pure returns (bytes20 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(224, not(0)))\n right := and(right, shl(128, not(0)))\n result := or(left, shr(32, right))\n }\n }\n\n function pack_4_20(bytes4 left, bytes20 right) internal pure returns (bytes24 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(224, not(0)))\n right := and(right, shl(96, not(0)))\n result := or(left, shr(32, right))\n }\n }\n\n function pack_4_24(bytes4 left, bytes24 right) internal pure returns (bytes28 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(224, not(0)))\n right := and(right, shl(64, not(0)))\n result := or(left, shr(32, right))\n }\n }\n\n function pack_4_28(bytes4 left, bytes28 right) internal pure returns (bytes32 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(224, not(0)))\n right := and(right, shl(32, not(0)))\n result := or(left, shr(32, right))\n }\n }\n\n function pack_6_2(bytes6 left, bytes2 right) internal pure returns (bytes8 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(208, not(0)))\n right := and(right, shl(240, not(0)))\n result := or(left, shr(48, right))\n }\n }\n\n function pack_6_4(bytes6 left, bytes4 right) internal pure returns (bytes10 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(208, not(0)))\n right := and(right, shl(224, not(0)))\n result := or(left, shr(48, right))\n }\n }\n\n function pack_6_6(bytes6 left, bytes6 right) internal pure returns (bytes12 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(208, not(0)))\n right := and(right, shl(208, not(0)))\n result := or(left, shr(48, right))\n }\n }\n\n function pack_6_10(bytes6 left, bytes10 right) internal pure returns (bytes16 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(208, not(0)))\n right := and(right, shl(176, not(0)))\n result := or(left, shr(48, right))\n }\n }\n\n function pack_6_16(bytes6 left, bytes16 right) internal pure returns (bytes22 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(208, not(0)))\n right := and(right, shl(128, not(0)))\n result := or(left, shr(48, right))\n }\n }\n\n function pack_6_22(bytes6 left, bytes22 right) internal pure returns (bytes28 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(208, not(0)))\n right := and(right, shl(80, not(0)))\n result := or(left, shr(48, right))\n }\n }\n\n function pack_8_2(bytes8 left, bytes2 right) internal pure returns (bytes10 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(192, not(0)))\n right := and(right, shl(240, not(0)))\n result := or(left, shr(64, right))\n }\n }\n\n function pack_8_4(bytes8 left, bytes4 right) internal pure returns (bytes12 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(192, not(0)))\n right := and(right, shl(224, not(0)))\n result := or(left, shr(64, right))\n }\n }\n\n function pack_8_8(bytes8 left, bytes8 right) internal pure returns (bytes16 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(192, not(0)))\n right := and(right, shl(192, not(0)))\n result := or(left, shr(64, right))\n }\n }\n\n function pack_8_12(bytes8 left, bytes12 right) internal pure returns (bytes20 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(192, not(0)))\n right := and(right, shl(160, not(0)))\n result := or(left, shr(64, right))\n }\n }\n\n function pack_8_16(bytes8 left, bytes16 right) internal pure returns (bytes24 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(192, not(0)))\n right := and(right, shl(128, not(0)))\n result := or(left, shr(64, right))\n }\n }\n\n function pack_8_20(bytes8 left, bytes20 right) internal pure returns (bytes28 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(192, not(0)))\n right := and(right, shl(96, not(0)))\n result := or(left, shr(64, right))\n }\n }\n\n function pack_8_24(bytes8 left, bytes24 right) internal pure returns (bytes32 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(192, not(0)))\n right := and(right, shl(64, not(0)))\n result := or(left, shr(64, right))\n }\n }\n\n function pack_10_2(bytes10 left, bytes2 right) internal pure returns (bytes12 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(176, not(0)))\n right := and(right, shl(240, not(0)))\n result := or(left, shr(80, right))\n }\n }\n\n function pack_10_6(bytes10 left, bytes6 right) internal pure returns (bytes16 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(176, not(0)))\n right := and(right, shl(208, not(0)))\n result := or(left, shr(80, right))\n }\n }\n\n function pack_10_10(bytes10 left, bytes10 right) internal pure returns (bytes20 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(176, not(0)))\n right := and(right, shl(176, not(0)))\n result := or(left, shr(80, right))\n }\n }\n\n function pack_10_12(bytes10 left, bytes12 right) internal pure returns (bytes22 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(176, not(0)))\n right := and(right, shl(160, not(0)))\n result := or(left, shr(80, right))\n }\n }\n\n function pack_10_22(bytes10 left, bytes22 right) internal pure returns (bytes32 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(176, not(0)))\n right := and(right, shl(80, not(0)))\n result := or(left, shr(80, right))\n }\n }\n\n function pack_12_4(bytes12 left, bytes4 right) internal pure returns (bytes16 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(160, not(0)))\n right := and(right, shl(224, not(0)))\n result := or(left, shr(96, right))\n }\n }\n\n function pack_12_8(bytes12 left, bytes8 right) internal pure returns (bytes20 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(160, not(0)))\n right := and(right, shl(192, not(0)))\n result := or(left, shr(96, right))\n }\n }\n\n function pack_12_10(bytes12 left, bytes10 right) internal pure returns (bytes22 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(160, not(0)))\n right := and(right, shl(176, not(0)))\n result := or(left, shr(96, right))\n }\n }\n\n function pack_12_12(bytes12 left, bytes12 right) internal pure returns (bytes24 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(160, not(0)))\n right := and(right, shl(160, not(0)))\n result := or(left, shr(96, right))\n }\n }\n\n function pack_12_16(bytes12 left, bytes16 right) internal pure returns (bytes28 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(160, not(0)))\n right := and(right, shl(128, not(0)))\n result := or(left, shr(96, right))\n }\n }\n\n function pack_12_20(bytes12 left, bytes20 right) internal pure returns (bytes32 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(160, not(0)))\n right := and(right, shl(96, not(0)))\n result := or(left, shr(96, right))\n }\n }\n\n function pack_16_4(bytes16 left, bytes4 right) internal pure returns (bytes20 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(128, not(0)))\n right := and(right, shl(224, not(0)))\n result := or(left, shr(128, right))\n }\n }\n\n function pack_16_6(bytes16 left, bytes6 right) internal pure returns (bytes22 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(128, not(0)))\n right := and(right, shl(208, not(0)))\n result := or(left, shr(128, right))\n }\n }\n\n function pack_16_8(bytes16 left, bytes8 right) internal pure returns (bytes24 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(128, not(0)))\n right := and(right, shl(192, not(0)))\n result := or(left, shr(128, right))\n }\n }\n\n function pack_16_12(bytes16 left, bytes12 right) internal pure returns (bytes28 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(128, not(0)))\n right := and(right, shl(160, not(0)))\n result := or(left, shr(128, right))\n }\n }\n\n function pack_16_16(bytes16 left, bytes16 right) internal pure returns (bytes32 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(128, not(0)))\n right := and(right, shl(128, not(0)))\n result := or(left, shr(128, right))\n }\n }\n\n function pack_20_2(bytes20 left, bytes2 right) internal pure returns (bytes22 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(96, not(0)))\n right := and(right, shl(240, not(0)))\n result := or(left, shr(160, right))\n }\n }\n\n function pack_20_4(bytes20 left, bytes4 right) internal pure returns (bytes24 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(96, not(0)))\n right := and(right, shl(224, not(0)))\n result := or(left, shr(160, right))\n }\n }\n\n function pack_20_8(bytes20 left, bytes8 right) internal pure returns (bytes28 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(96, not(0)))\n right := and(right, shl(192, not(0)))\n result := or(left, shr(160, right))\n }\n }\n\n function pack_20_12(bytes20 left, bytes12 right) internal pure returns (bytes32 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(96, not(0)))\n right := and(right, shl(160, not(0)))\n result := or(left, shr(160, right))\n }\n }\n\n function pack_22_2(bytes22 left, bytes2 right) internal pure returns (bytes24 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(80, not(0)))\n right := and(right, shl(240, not(0)))\n result := or(left, shr(176, right))\n }\n }\n\n function pack_22_6(bytes22 left, bytes6 right) internal pure returns (bytes28 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(80, not(0)))\n right := and(right, shl(208, not(0)))\n result := or(left, shr(176, right))\n }\n }\n\n function pack_22_10(bytes22 left, bytes10 right) internal pure returns (bytes32 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(80, not(0)))\n right := and(right, shl(176, not(0)))\n result := or(left, shr(176, right))\n }\n }\n\n function pack_24_4(bytes24 left, bytes4 right) internal pure returns (bytes28 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(64, not(0)))\n right := and(right, shl(224, not(0)))\n result := or(left, shr(192, right))\n }\n }\n\n function pack_24_8(bytes24 left, bytes8 right) internal pure returns (bytes32 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(64, not(0)))\n right := and(right, shl(192, not(0)))\n result := or(left, shr(192, right))\n }\n }\n\n function pack_28_4(bytes28 left, bytes4 right) internal pure returns (bytes32 result) {\n assembly (\"memory-safe\") {\n left := and(left, shl(32, not(0)))\n right := and(right, shl(224, not(0)))\n result := or(left, shr(224, right))\n }\n }\n\n function extract_2_1(bytes2 self, uint8 offset) internal pure returns (bytes1 result) {\n if (offset > 1) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(248, not(0)))\n }\n }\n\n function replace_2_1(bytes2 self, bytes1 value, uint8 offset) internal pure returns (bytes2 result) {\n bytes1 oldValue = extract_2_1(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(248, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_4_1(bytes4 self, uint8 offset) internal pure returns (bytes1 result) {\n if (offset > 3) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(248, not(0)))\n }\n }\n\n function replace_4_1(bytes4 self, bytes1 value, uint8 offset) internal pure returns (bytes4 result) {\n bytes1 oldValue = extract_4_1(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(248, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_4_2(bytes4 self, uint8 offset) internal pure returns (bytes2 result) {\n if (offset > 2) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(240, not(0)))\n }\n }\n\n function replace_4_2(bytes4 self, bytes2 value, uint8 offset) internal pure returns (bytes4 result) {\n bytes2 oldValue = extract_4_2(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(240, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_6_1(bytes6 self, uint8 offset) internal pure returns (bytes1 result) {\n if (offset > 5) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(248, not(0)))\n }\n }\n\n function replace_6_1(bytes6 self, bytes1 value, uint8 offset) internal pure returns (bytes6 result) {\n bytes1 oldValue = extract_6_1(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(248, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_6_2(bytes6 self, uint8 offset) internal pure returns (bytes2 result) {\n if (offset > 4) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(240, not(0)))\n }\n }\n\n function replace_6_2(bytes6 self, bytes2 value, uint8 offset) internal pure returns (bytes6 result) {\n bytes2 oldValue = extract_6_2(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(240, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_6_4(bytes6 self, uint8 offset) internal pure returns (bytes4 result) {\n if (offset > 2) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(224, not(0)))\n }\n }\n\n function replace_6_4(bytes6 self, bytes4 value, uint8 offset) internal pure returns (bytes6 result) {\n bytes4 oldValue = extract_6_4(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(224, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_8_1(bytes8 self, uint8 offset) internal pure returns (bytes1 result) {\n if (offset > 7) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(248, not(0)))\n }\n }\n\n function replace_8_1(bytes8 self, bytes1 value, uint8 offset) internal pure returns (bytes8 result) {\n bytes1 oldValue = extract_8_1(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(248, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_8_2(bytes8 self, uint8 offset) internal pure returns (bytes2 result) {\n if (offset > 6) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(240, not(0)))\n }\n }\n\n function replace_8_2(bytes8 self, bytes2 value, uint8 offset) internal pure returns (bytes8 result) {\n bytes2 oldValue = extract_8_2(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(240, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_8_4(bytes8 self, uint8 offset) internal pure returns (bytes4 result) {\n if (offset > 4) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(224, not(0)))\n }\n }\n\n function replace_8_4(bytes8 self, bytes4 value, uint8 offset) internal pure returns (bytes8 result) {\n bytes4 oldValue = extract_8_4(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(224, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_8_6(bytes8 self, uint8 offset) internal pure returns (bytes6 result) {\n if (offset > 2) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(208, not(0)))\n }\n }\n\n function replace_8_6(bytes8 self, bytes6 value, uint8 offset) internal pure returns (bytes8 result) {\n bytes6 oldValue = extract_8_6(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(208, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_10_1(bytes10 self, uint8 offset) internal pure returns (bytes1 result) {\n if (offset > 9) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(248, not(0)))\n }\n }\n\n function replace_10_1(bytes10 self, bytes1 value, uint8 offset) internal pure returns (bytes10 result) {\n bytes1 oldValue = extract_10_1(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(248, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_10_2(bytes10 self, uint8 offset) internal pure returns (bytes2 result) {\n if (offset > 8) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(240, not(0)))\n }\n }\n\n function replace_10_2(bytes10 self, bytes2 value, uint8 offset) internal pure returns (bytes10 result) {\n bytes2 oldValue = extract_10_2(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(240, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_10_4(bytes10 self, uint8 offset) internal pure returns (bytes4 result) {\n if (offset > 6) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(224, not(0)))\n }\n }\n\n function replace_10_4(bytes10 self, bytes4 value, uint8 offset) internal pure returns (bytes10 result) {\n bytes4 oldValue = extract_10_4(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(224, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_10_6(bytes10 self, uint8 offset) internal pure returns (bytes6 result) {\n if (offset > 4) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(208, not(0)))\n }\n }\n\n function replace_10_6(bytes10 self, bytes6 value, uint8 offset) internal pure returns (bytes10 result) {\n bytes6 oldValue = extract_10_6(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(208, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_10_8(bytes10 self, uint8 offset) internal pure returns (bytes8 result) {\n if (offset > 2) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(192, not(0)))\n }\n }\n\n function replace_10_8(bytes10 self, bytes8 value, uint8 offset) internal pure returns (bytes10 result) {\n bytes8 oldValue = extract_10_8(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(192, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_12_1(bytes12 self, uint8 offset) internal pure returns (bytes1 result) {\n if (offset > 11) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(248, not(0)))\n }\n }\n\n function replace_12_1(bytes12 self, bytes1 value, uint8 offset) internal pure returns (bytes12 result) {\n bytes1 oldValue = extract_12_1(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(248, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_12_2(bytes12 self, uint8 offset) internal pure returns (bytes2 result) {\n if (offset > 10) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(240, not(0)))\n }\n }\n\n function replace_12_2(bytes12 self, bytes2 value, uint8 offset) internal pure returns (bytes12 result) {\n bytes2 oldValue = extract_12_2(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(240, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_12_4(bytes12 self, uint8 offset) internal pure returns (bytes4 result) {\n if (offset > 8) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(224, not(0)))\n }\n }\n\n function replace_12_4(bytes12 self, bytes4 value, uint8 offset) internal pure returns (bytes12 result) {\n bytes4 oldValue = extract_12_4(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(224, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_12_6(bytes12 self, uint8 offset) internal pure returns (bytes6 result) {\n if (offset > 6) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(208, not(0)))\n }\n }\n\n function replace_12_6(bytes12 self, bytes6 value, uint8 offset) internal pure returns (bytes12 result) {\n bytes6 oldValue = extract_12_6(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(208, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_12_8(bytes12 self, uint8 offset) internal pure returns (bytes8 result) {\n if (offset > 4) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(192, not(0)))\n }\n }\n\n function replace_12_8(bytes12 self, bytes8 value, uint8 offset) internal pure returns (bytes12 result) {\n bytes8 oldValue = extract_12_8(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(192, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_12_10(bytes12 self, uint8 offset) internal pure returns (bytes10 result) {\n if (offset > 2) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(176, not(0)))\n }\n }\n\n function replace_12_10(bytes12 self, bytes10 value, uint8 offset) internal pure returns (bytes12 result) {\n bytes10 oldValue = extract_12_10(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(176, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_16_1(bytes16 self, uint8 offset) internal pure returns (bytes1 result) {\n if (offset > 15) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(248, not(0)))\n }\n }\n\n function replace_16_1(bytes16 self, bytes1 value, uint8 offset) internal pure returns (bytes16 result) {\n bytes1 oldValue = extract_16_1(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(248, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_16_2(bytes16 self, uint8 offset) internal pure returns (bytes2 result) {\n if (offset > 14) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(240, not(0)))\n }\n }\n\n function replace_16_2(bytes16 self, bytes2 value, uint8 offset) internal pure returns (bytes16 result) {\n bytes2 oldValue = extract_16_2(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(240, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_16_4(bytes16 self, uint8 offset) internal pure returns (bytes4 result) {\n if (offset > 12) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(224, not(0)))\n }\n }\n\n function replace_16_4(bytes16 self, bytes4 value, uint8 offset) internal pure returns (bytes16 result) {\n bytes4 oldValue = extract_16_4(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(224, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_16_6(bytes16 self, uint8 offset) internal pure returns (bytes6 result) {\n if (offset > 10) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(208, not(0)))\n }\n }\n\n function replace_16_6(bytes16 self, bytes6 value, uint8 offset) internal pure returns (bytes16 result) {\n bytes6 oldValue = extract_16_6(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(208, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_16_8(bytes16 self, uint8 offset) internal pure returns (bytes8 result) {\n if (offset > 8) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(192, not(0)))\n }\n }\n\n function replace_16_8(bytes16 self, bytes8 value, uint8 offset) internal pure returns (bytes16 result) {\n bytes8 oldValue = extract_16_8(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(192, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_16_10(bytes16 self, uint8 offset) internal pure returns (bytes10 result) {\n if (offset > 6) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(176, not(0)))\n }\n }\n\n function replace_16_10(bytes16 self, bytes10 value, uint8 offset) internal pure returns (bytes16 result) {\n bytes10 oldValue = extract_16_10(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(176, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_16_12(bytes16 self, uint8 offset) internal pure returns (bytes12 result) {\n if (offset > 4) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(160, not(0)))\n }\n }\n\n function replace_16_12(bytes16 self, bytes12 value, uint8 offset) internal pure returns (bytes16 result) {\n bytes12 oldValue = extract_16_12(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(160, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_20_1(bytes20 self, uint8 offset) internal pure returns (bytes1 result) {\n if (offset > 19) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(248, not(0)))\n }\n }\n\n function replace_20_1(bytes20 self, bytes1 value, uint8 offset) internal pure returns (bytes20 result) {\n bytes1 oldValue = extract_20_1(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(248, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_20_2(bytes20 self, uint8 offset) internal pure returns (bytes2 result) {\n if (offset > 18) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(240, not(0)))\n }\n }\n\n function replace_20_2(bytes20 self, bytes2 value, uint8 offset) internal pure returns (bytes20 result) {\n bytes2 oldValue = extract_20_2(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(240, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_20_4(bytes20 self, uint8 offset) internal pure returns (bytes4 result) {\n if (offset > 16) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(224, not(0)))\n }\n }\n\n function replace_20_4(bytes20 self, bytes4 value, uint8 offset) internal pure returns (bytes20 result) {\n bytes4 oldValue = extract_20_4(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(224, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_20_6(bytes20 self, uint8 offset) internal pure returns (bytes6 result) {\n if (offset > 14) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(208, not(0)))\n }\n }\n\n function replace_20_6(bytes20 self, bytes6 value, uint8 offset) internal pure returns (bytes20 result) {\n bytes6 oldValue = extract_20_6(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(208, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_20_8(bytes20 self, uint8 offset) internal pure returns (bytes8 result) {\n if (offset > 12) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(192, not(0)))\n }\n }\n\n function replace_20_8(bytes20 self, bytes8 value, uint8 offset) internal pure returns (bytes20 result) {\n bytes8 oldValue = extract_20_8(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(192, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_20_10(bytes20 self, uint8 offset) internal pure returns (bytes10 result) {\n if (offset > 10) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(176, not(0)))\n }\n }\n\n function replace_20_10(bytes20 self, bytes10 value, uint8 offset) internal pure returns (bytes20 result) {\n bytes10 oldValue = extract_20_10(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(176, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_20_12(bytes20 self, uint8 offset) internal pure returns (bytes12 result) {\n if (offset > 8) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(160, not(0)))\n }\n }\n\n function replace_20_12(bytes20 self, bytes12 value, uint8 offset) internal pure returns (bytes20 result) {\n bytes12 oldValue = extract_20_12(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(160, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_20_16(bytes20 self, uint8 offset) internal pure returns (bytes16 result) {\n if (offset > 4) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(128, not(0)))\n }\n }\n\n function replace_20_16(bytes20 self, bytes16 value, uint8 offset) internal pure returns (bytes20 result) {\n bytes16 oldValue = extract_20_16(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(128, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_22_1(bytes22 self, uint8 offset) internal pure returns (bytes1 result) {\n if (offset > 21) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(248, not(0)))\n }\n }\n\n function replace_22_1(bytes22 self, bytes1 value, uint8 offset) internal pure returns (bytes22 result) {\n bytes1 oldValue = extract_22_1(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(248, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_22_2(bytes22 self, uint8 offset) internal pure returns (bytes2 result) {\n if (offset > 20) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(240, not(0)))\n }\n }\n\n function replace_22_2(bytes22 self, bytes2 value, uint8 offset) internal pure returns (bytes22 result) {\n bytes2 oldValue = extract_22_2(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(240, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_22_4(bytes22 self, uint8 offset) internal pure returns (bytes4 result) {\n if (offset > 18) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(224, not(0)))\n }\n }\n\n function replace_22_4(bytes22 self, bytes4 value, uint8 offset) internal pure returns (bytes22 result) {\n bytes4 oldValue = extract_22_4(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(224, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_22_6(bytes22 self, uint8 offset) internal pure returns (bytes6 result) {\n if (offset > 16) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(208, not(0)))\n }\n }\n\n function replace_22_6(bytes22 self, bytes6 value, uint8 offset) internal pure returns (bytes22 result) {\n bytes6 oldValue = extract_22_6(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(208, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_22_8(bytes22 self, uint8 offset) internal pure returns (bytes8 result) {\n if (offset > 14) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(192, not(0)))\n }\n }\n\n function replace_22_8(bytes22 self, bytes8 value, uint8 offset) internal pure returns (bytes22 result) {\n bytes8 oldValue = extract_22_8(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(192, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_22_10(bytes22 self, uint8 offset) internal pure returns (bytes10 result) {\n if (offset > 12) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(176, not(0)))\n }\n }\n\n function replace_22_10(bytes22 self, bytes10 value, uint8 offset) internal pure returns (bytes22 result) {\n bytes10 oldValue = extract_22_10(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(176, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_22_12(bytes22 self, uint8 offset) internal pure returns (bytes12 result) {\n if (offset > 10) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(160, not(0)))\n }\n }\n\n function replace_22_12(bytes22 self, bytes12 value, uint8 offset) internal pure returns (bytes22 result) {\n bytes12 oldValue = extract_22_12(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(160, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_22_16(bytes22 self, uint8 offset) internal pure returns (bytes16 result) {\n if (offset > 6) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(128, not(0)))\n }\n }\n\n function replace_22_16(bytes22 self, bytes16 value, uint8 offset) internal pure returns (bytes22 result) {\n bytes16 oldValue = extract_22_16(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(128, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_22_20(bytes22 self, uint8 offset) internal pure returns (bytes20 result) {\n if (offset > 2) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(96, not(0)))\n }\n }\n\n function replace_22_20(bytes22 self, bytes20 value, uint8 offset) internal pure returns (bytes22 result) {\n bytes20 oldValue = extract_22_20(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(96, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_24_1(bytes24 self, uint8 offset) internal pure returns (bytes1 result) {\n if (offset > 23) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(248, not(0)))\n }\n }\n\n function replace_24_1(bytes24 self, bytes1 value, uint8 offset) internal pure returns (bytes24 result) {\n bytes1 oldValue = extract_24_1(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(248, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_24_2(bytes24 self, uint8 offset) internal pure returns (bytes2 result) {\n if (offset > 22) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(240, not(0)))\n }\n }\n\n function replace_24_2(bytes24 self, bytes2 value, uint8 offset) internal pure returns (bytes24 result) {\n bytes2 oldValue = extract_24_2(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(240, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_24_4(bytes24 self, uint8 offset) internal pure returns (bytes4 result) {\n if (offset > 20) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(224, not(0)))\n }\n }\n\n function replace_24_4(bytes24 self, bytes4 value, uint8 offset) internal pure returns (bytes24 result) {\n bytes4 oldValue = extract_24_4(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(224, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_24_6(bytes24 self, uint8 offset) internal pure returns (bytes6 result) {\n if (offset > 18) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(208, not(0)))\n }\n }\n\n function replace_24_6(bytes24 self, bytes6 value, uint8 offset) internal pure returns (bytes24 result) {\n bytes6 oldValue = extract_24_6(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(208, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_24_8(bytes24 self, uint8 offset) internal pure returns (bytes8 result) {\n if (offset > 16) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(192, not(0)))\n }\n }\n\n function replace_24_8(bytes24 self, bytes8 value, uint8 offset) internal pure returns (bytes24 result) {\n bytes8 oldValue = extract_24_8(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(192, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_24_10(bytes24 self, uint8 offset) internal pure returns (bytes10 result) {\n if (offset > 14) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(176, not(0)))\n }\n }\n\n function replace_24_10(bytes24 self, bytes10 value, uint8 offset) internal pure returns (bytes24 result) {\n bytes10 oldValue = extract_24_10(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(176, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_24_12(bytes24 self, uint8 offset) internal pure returns (bytes12 result) {\n if (offset > 12) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(160, not(0)))\n }\n }\n\n function replace_24_12(bytes24 self, bytes12 value, uint8 offset) internal pure returns (bytes24 result) {\n bytes12 oldValue = extract_24_12(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(160, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_24_16(bytes24 self, uint8 offset) internal pure returns (bytes16 result) {\n if (offset > 8) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(128, not(0)))\n }\n }\n\n function replace_24_16(bytes24 self, bytes16 value, uint8 offset) internal pure returns (bytes24 result) {\n bytes16 oldValue = extract_24_16(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(128, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_24_20(bytes24 self, uint8 offset) internal pure returns (bytes20 result) {\n if (offset > 4) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(96, not(0)))\n }\n }\n\n function replace_24_20(bytes24 self, bytes20 value, uint8 offset) internal pure returns (bytes24 result) {\n bytes20 oldValue = extract_24_20(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(96, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_24_22(bytes24 self, uint8 offset) internal pure returns (bytes22 result) {\n if (offset > 2) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(80, not(0)))\n }\n }\n\n function replace_24_22(bytes24 self, bytes22 value, uint8 offset) internal pure returns (bytes24 result) {\n bytes22 oldValue = extract_24_22(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(80, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_28_1(bytes28 self, uint8 offset) internal pure returns (bytes1 result) {\n if (offset > 27) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(248, not(0)))\n }\n }\n\n function replace_28_1(bytes28 self, bytes1 value, uint8 offset) internal pure returns (bytes28 result) {\n bytes1 oldValue = extract_28_1(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(248, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_28_2(bytes28 self, uint8 offset) internal pure returns (bytes2 result) {\n if (offset > 26) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(240, not(0)))\n }\n }\n\n function replace_28_2(bytes28 self, bytes2 value, uint8 offset) internal pure returns (bytes28 result) {\n bytes2 oldValue = extract_28_2(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(240, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_28_4(bytes28 self, uint8 offset) internal pure returns (bytes4 result) {\n if (offset > 24) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(224, not(0)))\n }\n }\n\n function replace_28_4(bytes28 self, bytes4 value, uint8 offset) internal pure returns (bytes28 result) {\n bytes4 oldValue = extract_28_4(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(224, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_28_6(bytes28 self, uint8 offset) internal pure returns (bytes6 result) {\n if (offset > 22) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(208, not(0)))\n }\n }\n\n function replace_28_6(bytes28 self, bytes6 value, uint8 offset) internal pure returns (bytes28 result) {\n bytes6 oldValue = extract_28_6(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(208, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_28_8(bytes28 self, uint8 offset) internal pure returns (bytes8 result) {\n if (offset > 20) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(192, not(0)))\n }\n }\n\n function replace_28_8(bytes28 self, bytes8 value, uint8 offset) internal pure returns (bytes28 result) {\n bytes8 oldValue = extract_28_8(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(192, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_28_10(bytes28 self, uint8 offset) internal pure returns (bytes10 result) {\n if (offset > 18) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(176, not(0)))\n }\n }\n\n function replace_28_10(bytes28 self, bytes10 value, uint8 offset) internal pure returns (bytes28 result) {\n bytes10 oldValue = extract_28_10(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(176, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_28_12(bytes28 self, uint8 offset) internal pure returns (bytes12 result) {\n if (offset > 16) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(160, not(0)))\n }\n }\n\n function replace_28_12(bytes28 self, bytes12 value, uint8 offset) internal pure returns (bytes28 result) {\n bytes12 oldValue = extract_28_12(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(160, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_28_16(bytes28 self, uint8 offset) internal pure returns (bytes16 result) {\n if (offset > 12) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(128, not(0)))\n }\n }\n\n function replace_28_16(bytes28 self, bytes16 value, uint8 offset) internal pure returns (bytes28 result) {\n bytes16 oldValue = extract_28_16(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(128, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_28_20(bytes28 self, uint8 offset) internal pure returns (bytes20 result) {\n if (offset > 8) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(96, not(0)))\n }\n }\n\n function replace_28_20(bytes28 self, bytes20 value, uint8 offset) internal pure returns (bytes28 result) {\n bytes20 oldValue = extract_28_20(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(96, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_28_22(bytes28 self, uint8 offset) internal pure returns (bytes22 result) {\n if (offset > 6) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(80, not(0)))\n }\n }\n\n function replace_28_22(bytes28 self, bytes22 value, uint8 offset) internal pure returns (bytes28 result) {\n bytes22 oldValue = extract_28_22(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(80, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_28_24(bytes28 self, uint8 offset) internal pure returns (bytes24 result) {\n if (offset > 4) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(64, not(0)))\n }\n }\n\n function replace_28_24(bytes28 self, bytes24 value, uint8 offset) internal pure returns (bytes28 result) {\n bytes24 oldValue = extract_28_24(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(64, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_32_1(bytes32 self, uint8 offset) internal pure returns (bytes1 result) {\n if (offset > 31) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(248, not(0)))\n }\n }\n\n function replace_32_1(bytes32 self, bytes1 value, uint8 offset) internal pure returns (bytes32 result) {\n bytes1 oldValue = extract_32_1(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(248, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_32_2(bytes32 self, uint8 offset) internal pure returns (bytes2 result) {\n if (offset > 30) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(240, not(0)))\n }\n }\n\n function replace_32_2(bytes32 self, bytes2 value, uint8 offset) internal pure returns (bytes32 result) {\n bytes2 oldValue = extract_32_2(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(240, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_32_4(bytes32 self, uint8 offset) internal pure returns (bytes4 result) {\n if (offset > 28) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(224, not(0)))\n }\n }\n\n function replace_32_4(bytes32 self, bytes4 value, uint8 offset) internal pure returns (bytes32 result) {\n bytes4 oldValue = extract_32_4(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(224, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_32_6(bytes32 self, uint8 offset) internal pure returns (bytes6 result) {\n if (offset > 26) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(208, not(0)))\n }\n }\n\n function replace_32_6(bytes32 self, bytes6 value, uint8 offset) internal pure returns (bytes32 result) {\n bytes6 oldValue = extract_32_6(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(208, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_32_8(bytes32 self, uint8 offset) internal pure returns (bytes8 result) {\n if (offset > 24) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(192, not(0)))\n }\n }\n\n function replace_32_8(bytes32 self, bytes8 value, uint8 offset) internal pure returns (bytes32 result) {\n bytes8 oldValue = extract_32_8(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(192, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_32_10(bytes32 self, uint8 offset) internal pure returns (bytes10 result) {\n if (offset > 22) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(176, not(0)))\n }\n }\n\n function replace_32_10(bytes32 self, bytes10 value, uint8 offset) internal pure returns (bytes32 result) {\n bytes10 oldValue = extract_32_10(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(176, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_32_12(bytes32 self, uint8 offset) internal pure returns (bytes12 result) {\n if (offset > 20) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(160, not(0)))\n }\n }\n\n function replace_32_12(bytes32 self, bytes12 value, uint8 offset) internal pure returns (bytes32 result) {\n bytes12 oldValue = extract_32_12(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(160, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_32_16(bytes32 self, uint8 offset) internal pure returns (bytes16 result) {\n if (offset > 16) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(128, not(0)))\n }\n }\n\n function replace_32_16(bytes32 self, bytes16 value, uint8 offset) internal pure returns (bytes32 result) {\n bytes16 oldValue = extract_32_16(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(128, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_32_20(bytes32 self, uint8 offset) internal pure returns (bytes20 result) {\n if (offset > 12) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(96, not(0)))\n }\n }\n\n function replace_32_20(bytes32 self, bytes20 value, uint8 offset) internal pure returns (bytes32 result) {\n bytes20 oldValue = extract_32_20(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(96, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_32_22(bytes32 self, uint8 offset) internal pure returns (bytes22 result) {\n if (offset > 10) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(80, not(0)))\n }\n }\n\n function replace_32_22(bytes32 self, bytes22 value, uint8 offset) internal pure returns (bytes32 result) {\n bytes22 oldValue = extract_32_22(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(80, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_32_24(bytes32 self, uint8 offset) internal pure returns (bytes24 result) {\n if (offset > 8) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(64, not(0)))\n }\n }\n\n function replace_32_24(bytes32 self, bytes24 value, uint8 offset) internal pure returns (bytes32 result) {\n bytes24 oldValue = extract_32_24(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(64, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n\n function extract_32_28(bytes32 self, uint8 offset) internal pure returns (bytes28 result) {\n if (offset > 4) revert OutOfRangeAccess();\n assembly (\"memory-safe\") {\n result := and(shl(mul(8, offset), self), shl(32, not(0)))\n }\n }\n\n function replace_32_28(bytes32 self, bytes28 value, uint8 offset) internal pure returns (bytes32 result) {\n bytes28 oldValue = extract_32_28(self, offset);\n assembly (\"memory-safe\") {\n value := and(value, shl(32, not(0)))\n result := xor(self, shr(mul(8, offset), xor(oldValue, value)))\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Panic.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Helper library for emitting standardized panic codes.\n *\n * ```solidity\n * contract Example {\n * using Panic for uint256;\n *\n * // Use any of the declared internal constants\n * function foo() { Panic.GENERIC.panic(); }\n *\n * // Alternatively\n * function foo() { Panic.panic(Panic.GENERIC); }\n * }\n * ```\n *\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\n *\n * _Available since v5.1._\n */\n// slither-disable-next-line unused-state\nlibrary Panic {\n /// @dev generic / unspecified error\n uint256 internal constant GENERIC = 0x00;\n /// @dev used by the assert() builtin\n uint256 internal constant ASSERT = 0x01;\n /// @dev arithmetic underflow or overflow\n uint256 internal constant UNDER_OVERFLOW = 0x11;\n /// @dev division or modulo by zero\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\n /// @dev enum conversion error\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\n /// @dev invalid encoding in storage\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\n /// @dev empty array pop\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\n /// @dev array out of bounds access\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\n /// @dev resource error (too large allocation or too large array)\n uint256 internal constant RESOURCE_ERROR = 0x41;\n /// @dev calling invalid internal function\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\n\n /// @dev Reverts with a panic code. Recommended to use with\n /// the internal constants with predefined codes.\n function panic(uint256 code) internal pure {\n assembly (\"memory-safe\") {\n mstore(0x00, 0x4e487b71)\n mstore(0x20, code)\n revert(0x1c, 0x24)\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (utils/ReentrancyGuardTransient.sol)\n\npragma solidity ^0.8.24;\n\nimport {TransientSlot} from \"./TransientSlot.sol\";\n\n/**\n * @dev Variant of {ReentrancyGuard} that uses transient storage.\n *\n * NOTE: This variant only works on networks where EIP-1153 is available.\n *\n * _Available since v5.1._\n *\n * @custom:stateless\n */\nabstract contract ReentrancyGuardTransient {\n using TransientSlot for *;\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant REENTRANCY_GUARD_STORAGE =\n 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n /**\n * @dev Unauthorized reentrant call.\n */\n error ReentrancyGuardReentrantCall();\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n /**\n * @dev A `view` only version of {nonReentrant}. Use to block view functions\n * from being called, preventing reading from inconsistent contract state.\n *\n * CAUTION: This is a \"view\" modifier and does not change the reentrancy\n * status. Use it only on view functions. For payable or non-payable functions,\n * use the standard {nonReentrant} modifier instead.\n */\n modifier nonReentrantView() {\n _nonReentrantBeforeView();\n _;\n }\n\n function _nonReentrantBeforeView() private view {\n if (_reentrancyGuardEntered()) {\n revert ReentrancyGuardReentrantCall();\n }\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, REENTRANCY_GUARD_STORAGE.asBoolean().tload() will be false\n _nonReentrantBeforeView();\n\n // Any calls to nonReentrant after this point will fail\n _reentrancyGuardStorageSlot().asBoolean().tstore(true);\n }\n\n function _nonReentrantAfter() private {\n _reentrancyGuardStorageSlot().asBoolean().tstore(false);\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _reentrancyGuardStorageSlot().asBoolean().tload();\n }\n\n function _reentrancyGuardStorageSlot() internal pure virtual returns (bytes32) {\n return REENTRANCY_GUARD_STORAGE;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/ShortStrings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (utils/ShortStrings.sol)\n\npragma solidity ^0.8.20;\n\nimport {StorageSlot} from \"./StorageSlot.sol\";\n\n// | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |\n// | length | 0x BB |\ntype ShortString is bytes32;\n\n/**\n * @dev This library provides functions to convert short memory strings\n * into a `ShortString` type that can be used as an immutable variable.\n *\n * Strings of arbitrary length can be optimized using this library if\n * they are short enough (up to 31 bytes) by packing them with their\n * length (1 byte) in a single EVM word (32 bytes). Additionally, a\n * fallback mechanism can be used for every other case.\n *\n * Usage example:\n *\n * ```solidity\n * contract Named {\n * using ShortStrings for *;\n *\n * ShortString private immutable _name;\n * string private _nameFallback;\n *\n * constructor(string memory contractName) {\n * _name = contractName.toShortStringWithFallback(_nameFallback);\n * }\n *\n * function name() external view returns (string memory) {\n * return _name.toStringWithFallback(_nameFallback);\n * }\n * }\n * ```\n */\nlibrary ShortStrings {\n // Used as an identifier for strings longer than 31 bytes.\n bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;\n\n error StringTooLong(string str);\n error InvalidShortString();\n\n /**\n * @dev Encode a string of at most 31 chars into a `ShortString`.\n *\n * This will trigger a `StringTooLong` error is the input string is too long.\n */\n function toShortString(string memory str) internal pure returns (ShortString) {\n bytes memory bstr = bytes(str);\n if (bstr.length > 0x1f) {\n revert StringTooLong(str);\n }\n return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));\n }\n\n /**\n * @dev Decode a `ShortString` back to a \"normal\" string.\n */\n function toString(ShortString sstr) internal pure returns (string memory) {\n uint256 len = byteLength(sstr);\n // using `new string(len)` would work locally but is not memory safe.\n string memory str = new string(0x20);\n assembly (\"memory-safe\") {\n mstore(str, len)\n mstore(add(str, 0x20), sstr)\n }\n return str;\n }\n\n /**\n * @dev Return the length of a `ShortString`.\n */\n function byteLength(ShortString sstr) internal pure returns (uint256) {\n uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;\n if (result > 0x1f) {\n revert InvalidShortString();\n }\n return result;\n }\n\n /**\n * @dev Encode a string into a `ShortString`, or write it to storage if it is too long.\n */\n function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {\n if (bytes(value).length < 0x20) {\n return toShortString(value);\n } else {\n StorageSlot.getStringSlot(store).value = value;\n return ShortString.wrap(FALLBACK_SENTINEL);\n }\n }\n\n /**\n * @dev Decode a string that was encoded to `ShortString` or written to storage using {toShortStringWithFallback}.\n */\n function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {\n if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {\n return toString(value);\n } else {\n return store;\n }\n }\n\n /**\n * @dev Return the length of a string that was encoded to `ShortString` or written to storage using\n * {toShortStringWithFallback}.\n *\n * WARNING: This will return the \"byte length\" of the string. This may not reflect the actual length in terms of\n * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.\n */\n function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {\n if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {\n return byteLength(value);\n } else {\n return bytes(store).length;\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC-1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(newImplementation.code.length > 0);\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct Int256Slot {\n int256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\n */\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n assembly (\"memory-safe\") {\n r.slot := store.slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (utils/Strings.sol)\n\npragma solidity ^0.8.24;\n\nimport {Math} from \"./math/Math.sol\";\nimport {SafeCast} from \"./math/SafeCast.sol\";\nimport {SignedMath} from \"./math/SignedMath.sol\";\nimport {Bytes} from \"./Bytes.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n using SafeCast for *;\n\n bytes16 private constant HEX_DIGITS = \"0123456789abcdef\";\n uint8 private constant ADDRESS_LENGTH = 20;\n uint256 private constant SPECIAL_CHARS_LOOKUP =\n 0xffffffff | // first 32 bits corresponding to the control characters (U+0000 to U+001F)\n (1 << 0x22) | // double quote\n (1 << 0x5c); // backslash\n\n /**\n * @dev The `value` string doesn't fit in the specified `length`.\n */\n error StringsInsufficientHexLength(uint256 value, uint256 length);\n\n /**\n * @dev The string being parsed contains characters that are not in scope of the given base.\n */\n error StringsInvalidChar();\n\n /**\n * @dev The string being parsed is not a properly formatted address.\n */\n error StringsInvalidAddressFormat();\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 assembly (\"memory-safe\") {\n ptr := add(add(buffer, 0x20), length)\n }\n while (true) {\n ptr--;\n assembly (\"memory-safe\") {\n mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))\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 toStringSigned(int256 value) internal pure returns (string memory) {\n return string.concat(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 uint256 localValue = value;\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] = HEX_DIGITS[localValue & 0xf];\n localValue >>= 4;\n }\n if (localValue != 0) {\n revert StringsInsufficientHexLength(value, length);\n }\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\n * 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 Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal\n * representation, according to EIP-55.\n */\n function toChecksumHexString(address addr) internal pure returns (string memory) {\n bytes memory buffer = bytes(toHexString(addr));\n\n // hash the hex part of buffer (skip length + 2 bytes, length 40)\n uint256 hashValue;\n assembly (\"memory-safe\") {\n hashValue := shr(96, keccak256(add(buffer, 0x22), 40))\n }\n\n for (uint256 i = 41; i > 1; --i) {\n // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)\n if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {\n // case shift by xoring with 0x20\n buffer[i] ^= 0x20;\n }\n hashValue >>= 4;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `bytes` buffer to its ASCII `string` hexadecimal representation.\n */\n function toHexString(bytes memory input) internal pure returns (string memory) {\n unchecked {\n bytes memory buffer = new bytes(2 * input.length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 0; i < input.length; ++i) {\n uint8 v = uint8(input[i]);\n buffer[2 * i + 2] = HEX_DIGITS[v >> 4];\n buffer[2 * i + 3] = HEX_DIGITS[v & 0xf];\n }\n return string(buffer);\n }\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 Bytes.equal(bytes(a), bytes(b));\n }\n\n /**\n * @dev Parse a decimal string and returns the value as a `uint256`.\n *\n * Requirements:\n * - The string must be formatted as `[0-9]*`\n * - The result must fit into an `uint256` type\n */\n function parseUint(string memory input) internal pure returns (uint256) {\n return parseUint(input, 0, bytes(input).length);\n }\n\n /**\n * @dev Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and\n * `end` (excluded).\n *\n * Requirements:\n * - The substring must be formatted as `[0-9]*`\n * - The result must fit into an `uint256` type\n */\n function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\n (bool success, uint256 value) = tryParseUint(input, begin, end);\n if (!success) revert StringsInvalidChar();\n return value;\n }\n\n /**\n * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.\n *\n * NOTE: This function will revert if the result does not fit in a `uint256`.\n */\n function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {\n return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);\n }\n\n /**\n * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid\n * character.\n *\n * NOTE: This function will revert if the result does not fit in a `uint256`.\n */\n function tryParseUint(\n string memory input,\n uint256 begin,\n uint256 end\n ) internal pure returns (bool success, uint256 value) {\n if (end > bytes(input).length || begin > end) return (false, 0);\n return _tryParseUintUncheckedBounds(input, begin, end);\n }\n\n /**\n * @dev Implementation of {tryParseUint-string-uint256-uint256} that does not check bounds. Caller should make sure that\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\n */\n function _tryParseUintUncheckedBounds(\n string memory input,\n uint256 begin,\n uint256 end\n ) private pure returns (bool success, uint256 value) {\n bytes memory buffer = bytes(input);\n\n uint256 result = 0;\n for (uint256 i = begin; i < end; ++i) {\n uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\n if (chr > 9) return (false, 0);\n result *= 10;\n result += chr;\n }\n return (true, result);\n }\n\n /**\n * @dev Parse a decimal string and returns the value as a `int256`.\n *\n * Requirements:\n * - The string must be formatted as `[-+]?[0-9]*`\n * - The result must fit in an `int256` type.\n */\n function parseInt(string memory input) internal pure returns (int256) {\n return parseInt(input, 0, bytes(input).length);\n }\n\n /**\n * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and\n * `end` (excluded).\n *\n * Requirements:\n * - The substring must be formatted as `[-+]?[0-9]*`\n * - The result must fit in an `int256` type.\n */\n function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {\n (bool success, int256 value) = tryParseInt(input, begin, end);\n if (!success) revert StringsInvalidChar();\n return value;\n }\n\n /**\n * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if\n * the result does not fit in a `int256`.\n *\n * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\n */\n function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {\n return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);\n }\n\n uint256 private constant ABS_MIN_INT256 = 2 ** 255;\n\n /**\n * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid\n * character or if the result does not fit in a `int256`.\n *\n * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\n */\n function tryParseInt(\n string memory input,\n uint256 begin,\n uint256 end\n ) internal pure returns (bool success, int256 value) {\n if (end > bytes(input).length || begin > end) return (false, 0);\n return _tryParseIntUncheckedBounds(input, begin, end);\n }\n\n /**\n * @dev Implementation of {tryParseInt-string-uint256-uint256} that does not check bounds. Caller should make sure that\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\n */\n function _tryParseIntUncheckedBounds(\n string memory input,\n uint256 begin,\n uint256 end\n ) private pure returns (bool success, int256 value) {\n bytes memory buffer = bytes(input);\n\n // Check presence of a negative sign.\n bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\n bool positiveSign = sign == bytes1(\"+\");\n bool negativeSign = sign == bytes1(\"-\");\n uint256 offset = (positiveSign || negativeSign).toUint();\n\n (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);\n\n if (absSuccess && absValue < ABS_MIN_INT256) {\n return (true, negativeSign ? -int256(absValue) : int256(absValue));\n } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {\n return (true, type(int256).min);\n } else return (false, 0);\n }\n\n /**\n * @dev Parse a hexadecimal string (with or without \"0x\" prefix), and returns the value as a `uint256`.\n *\n * Requirements:\n * - The string must be formatted as `(0x)?[0-9a-fA-F]*`\n * - The result must fit in an `uint256` type.\n */\n function parseHexUint(string memory input) internal pure returns (uint256) {\n return parseHexUint(input, 0, bytes(input).length);\n }\n\n /**\n * @dev Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and\n * `end` (excluded).\n *\n * Requirements:\n * - The substring must be formatted as `(0x)?[0-9a-fA-F]*`\n * - The result must fit in an `uint256` type.\n */\n function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\n (bool success, uint256 value) = tryParseHexUint(input, begin, end);\n if (!success) revert StringsInvalidChar();\n return value;\n }\n\n /**\n * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.\n *\n * NOTE: This function will revert if the result does not fit in a `uint256`.\n */\n function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {\n return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);\n }\n\n /**\n * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an\n * invalid character.\n *\n * NOTE: This function will revert if the result does not fit in a `uint256`.\n */\n function tryParseHexUint(\n string memory input,\n uint256 begin,\n uint256 end\n ) internal pure returns (bool success, uint256 value) {\n if (end > bytes(input).length || begin > end) return (false, 0);\n return _tryParseHexUintUncheckedBounds(input, begin, end);\n }\n\n /**\n * @dev Implementation of {tryParseHexUint-string-uint256-uint256} that does not check bounds. Caller should make sure that\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\n */\n function _tryParseHexUintUncheckedBounds(\n string memory input,\n uint256 begin,\n uint256 end\n ) private pure returns (bool success, uint256 value) {\n bytes memory buffer = bytes(input);\n\n // skip 0x prefix if present\n bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2(\"0x\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\n uint256 offset = hasPrefix.toUint() * 2;\n\n uint256 result = 0;\n for (uint256 i = begin + offset; i < end; ++i) {\n uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\n if (chr > 15) return (false, 0);\n result *= 16;\n unchecked {\n // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).\n // This guarantees that adding a value < 16 will not cause an overflow, hence the unchecked.\n result += chr;\n }\n }\n return (true, result);\n }\n\n /**\n * @dev Parse a hexadecimal string (with or without \"0x\" prefix), and returns the value as an `address`.\n *\n * Requirements:\n * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`\n */\n function parseAddress(string memory input) internal pure returns (address) {\n return parseAddress(input, 0, bytes(input).length);\n }\n\n /**\n * @dev Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and\n * `end` (excluded).\n *\n * Requirements:\n * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`\n */\n function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {\n (bool success, address value) = tryParseAddress(input, begin, end);\n if (!success) revert StringsInvalidAddressFormat();\n return value;\n }\n\n /**\n * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly\n * formatted address. See {parseAddress-string} requirements.\n */\n function tryParseAddress(string memory input) internal pure returns (bool success, address value) {\n return tryParseAddress(input, 0, bytes(input).length);\n }\n\n /**\n * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly\n * formatted address. See {parseAddress-string-uint256-uint256} requirements.\n */\n function tryParseAddress(\n string memory input,\n uint256 begin,\n uint256 end\n ) internal pure returns (bool success, address value) {\n if (end > bytes(input).length || begin > end) return (false, address(0));\n\n bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2(\"0x\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\n uint256 expectedLength = 40 + hasPrefix.toUint() * 2;\n\n // check that input is the correct length\n if (end - begin == expectedLength) {\n // length guarantees that this does not overflow, and value is at most type(uint160).max\n (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);\n return (s, address(uint160(v)));\n } else {\n return (false, address(0));\n }\n }\n\n function _tryParseChr(bytes1 chr) private pure returns (uint8) {\n uint8 value = uint8(chr);\n\n // Try to parse `chr`:\n // - Case 1: [0-9]\n // - Case 2: [a-f]\n // - Case 3: [A-F]\n // - otherwise not supported\n unchecked {\n if (value > 47 && value < 58) value -= 48;\n else if (value > 96 && value < 103) value -= 87;\n else if (value > 64 && value < 71) value -= 55;\n else return type(uint8).max;\n }\n\n return value;\n }\n\n /**\n * @dev Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata.\n *\n * WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped.\n *\n * NOTE: This function escapes backslashes (including those in \\uXXXX sequences) and the characters in ranges\n * defined in section 2.5 of RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). All control characters in U+0000\n * to U+001F are escaped (\\b, \\t, \\n, \\f, \\r use short form; others use \\u00XX). ECMAScript's `JSON.parse` does\n * recover escaped unicode characters that are not in this range, but other tooling may provide different results.\n */\n function escapeJSON(string memory input) internal pure returns (string memory) {\n bytes memory buffer = bytes(input);\n\n // Put output at the FMP. Memory will be reserved later when we figure out the actual length of the escaped\n // string. All write are done using _unsafeWriteBytesOffset, which avoid the (expensive) length checks for\n // each character written.\n bytes memory output;\n assembly (\"memory-safe\") {\n output := mload(0x40)\n }\n uint256 outputLength = 0;\n\n for (uint256 i = 0; i < buffer.length; ++i) {\n uint8 char = uint8(bytes1(_unsafeReadBytesOffset(buffer, i)));\n if (((SPECIAL_CHARS_LOOKUP & (1 << char)) != 0)) {\n _unsafeWriteBytesOffset(output, outputLength++, \"\\\\\");\n if (char == 0x08) _unsafeWriteBytesOffset(output, outputLength++, \"b\");\n else if (char == 0x09) _unsafeWriteBytesOffset(output, outputLength++, \"t\");\n else if (char == 0x0a) _unsafeWriteBytesOffset(output, outputLength++, \"n\");\n else if (char == 0x0c) _unsafeWriteBytesOffset(output, outputLength++, \"f\");\n else if (char == 0x0d) _unsafeWriteBytesOffset(output, outputLength++, \"r\");\n else if (char == 0x5c) _unsafeWriteBytesOffset(output, outputLength++, \"\\\\\");\n else if (char == 0x22) {\n // solhint-disable-next-line quotes\n _unsafeWriteBytesOffset(output, outputLength++, '\"');\n } else {\n // U+0000 to U+001F without short form: output \\u00XX\n _unsafeWriteBytesOffset(output, outputLength++, \"u\");\n _unsafeWriteBytesOffset(output, outputLength++, \"0\");\n _unsafeWriteBytesOffset(output, outputLength++, \"0\");\n _unsafeWriteBytesOffset(output, outputLength++, HEX_DIGITS[char >> 4]);\n _unsafeWriteBytesOffset(output, outputLength++, HEX_DIGITS[char & 0x0f]);\n }\n } else {\n _unsafeWriteBytesOffset(output, outputLength++, bytes1(char));\n }\n }\n // write the actual length and reserve memory\n assembly (\"memory-safe\") {\n mstore(output, outputLength)\n mstore(0x40, add(output, add(outputLength, 0x20)))\n }\n\n return string(output);\n }\n\n /**\n * @dev Reads a bytes32 from a bytes array without bounds checking.\n *\n * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the\n * assembly block as such would prevent some optimizations.\n */\n function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {\n // This is not memory safe in the general case, but all calls to this private function are within bounds.\n assembly (\"memory-safe\") {\n value := mload(add(add(buffer, 0x20), offset))\n }\n }\n\n /**\n * @dev Write a bytes1 to a bytes array without bounds checking.\n *\n * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the\n * assembly block as such would prevent some optimizations.\n */\n function _unsafeWriteBytesOffset(bytes memory buffer, uint256 offset, bytes1 value) private pure {\n // This is not memory safe in the general case, but all calls to this private function are within bounds.\n assembly (\"memory-safe\") {\n mstore8(add(add(buffer, 0x20), offset), shr(248, value))\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/TransientSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/TransientSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/TransientSlot.js.\n\npragma solidity ^0.8.24;\n\n/**\n * @dev Library for reading and writing value-types to specific transient storage slots.\n *\n * Transient slots are often used to store temporary values that are removed after the current transaction.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * * Example reading and writing values using transient storage:\n * ```solidity\n * contract Lock {\n * using TransientSlot for *;\n *\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n * bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;\n *\n * modifier locked() {\n * require(!_LOCK_SLOT.asBoolean().tload());\n *\n * _LOCK_SLOT.asBoolean().tstore(true);\n * _;\n * _LOCK_SLOT.asBoolean().tstore(false);\n * }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary TransientSlot {\n /**\n * @dev UDVT that represents a slot holding an address.\n */\n type AddressSlot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a AddressSlot.\n */\n function asAddress(bytes32 slot) internal pure returns (AddressSlot) {\n return AddressSlot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represents a slot holding a bool.\n */\n type BooleanSlot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a BooleanSlot.\n */\n function asBoolean(bytes32 slot) internal pure returns (BooleanSlot) {\n return BooleanSlot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represents a slot holding a bytes32.\n */\n type Bytes32Slot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a Bytes32Slot.\n */\n function asBytes32(bytes32 slot) internal pure returns (Bytes32Slot) {\n return Bytes32Slot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represents a slot holding a uint256.\n */\n type Uint256Slot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a Uint256Slot.\n */\n function asUint256(bytes32 slot) internal pure returns (Uint256Slot) {\n return Uint256Slot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represents a slot holding a int256.\n */\n type Int256Slot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a Int256Slot.\n */\n function asInt256(bytes32 slot) internal pure returns (Int256Slot) {\n return Int256Slot.wrap(slot);\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(AddressSlot slot) internal view returns (address value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(AddressSlot slot, address value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(BooleanSlot slot) internal view returns (bool value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(BooleanSlot slot, bool value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(Bytes32Slot slot) internal view returns (bytes32 value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(Bytes32Slot slot, bytes32 value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(Uint256Slot slot) internal view returns (uint256 value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(Uint256Slot slot, uint256 value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(Int256Slot slot) internal view returns (int256 value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(Int256Slot slot, int256 value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n}\n" + }, + "contracts/EIP7702Implementation.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport {Account} from \"@openzeppelin/contracts/account/Account.sol\";\nimport {ERC7821} from \"@openzeppelin/contracts/account/extensions/draft-ERC7821.sol\";\nimport {SignerEIP7702} from \"@openzeppelin/contracts/utils/cryptography/signers/SignerEIP7702.sol\";\nimport {EIP7702Utils} from \"@openzeppelin/contracts/account/utils/EIP7702Utils.sol\";\nimport {ERC165} from \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\nimport {IEntryPoint} from \"@openzeppelin/contracts/interfaces/draft-IERC4337.sol\";\n\n/**\n * EIP-7702 smart account implementation using OpenZeppelin base contracts.\n *\n * Inheritance stack:\n * Account — ERC-4337 validateUserOp, onlyEntryPoint guards, pre-fund payment\n * SignerEIP7702 — _rawSignatureValidation: recovers signer and checks == address(this)\n * ERC7821 — standardized batch execute(bytes32 mode, bytes executionData)\n * ERC165 — supportsInterface\n *\n * EIP-7702 flow: deploy this contract once, then have EOAs sign an authorization\n * pointing to this address. The EOA's code becomes `0xef0100 || address(this)`,\n * giving it full smart-account capabilities while keeping the original private key.\n */\ncontract EIP7702Implementation is Account, SignerEIP7702, ERC7821, ERC165 {\n // Baked into bytecode at deploy time so EIP-7702 delegating EOAs inherit\n // the correct EntryPoint without any storage reads.\n IEntryPoint private immutable _entryPoint;\n\n // Takes address so callers don't need OZ's IEntryPoint type in scope.\n constructor(address entryPoint_) {\n _entryPoint = IEntryPoint(entryPoint_);\n }\n\n function entryPoint() public view virtual override returns (IEntryPoint) {\n return _entryPoint;\n }\n\n // -------------------------------------------------------------------------\n // Execution\n // -------------------------------------------------------------------------\n\n /**\n * @dev Allow the EntryPoint (in addition to address(this)) to call the\n * ERC-7821 batch execute function. Without this override only the account\n * itself can trigger execution.\n */\n function _erc7821AuthorizedExecutor(\n address caller,\n bytes32 mode,\n bytes calldata executionData\n ) internal view virtual override returns (bool) {\n return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData);\n }\n\n /**\n * @dev Convenience single-call path. Only callable by the EntryPoint or the\n * account itself — prevents arbitrary callers from draining funds.\n *\n * For batch calls use the ERC-7821 `execute(bytes32 mode, bytes executionData)`\n * inherited from ERC7821 with mode = 0x0100000000000000000000000000000000000000000000000000000000000000\n * and executionData = abi.encode(calls) where calls is (address,uint256,bytes)[].\n */\n function execute(\n address to,\n uint256 value,\n bytes calldata data\n ) external onlyEntryPointOrSelf returns (bytes memory) {\n (bool ok, bytes memory result) = to.call{value: value}(data);\n require(ok, \"execution failed\");\n return result;\n }\n\n // -------------------------------------------------------------------------\n // ERC-165\n // -------------------------------------------------------------------------\n\n /**\n * @dev Advertise ERC-7821 (batch executor) and ERC-165 support.\n * The ERC-7821 interface ID 0x4e49c5c7 is the XOR of:\n * execute(bytes32,bytes).selector ^ supportsExecutionMode(bytes32).selector\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == 0x4e49c5c7 // ERC-7821 batch executor\n || super.supportsInterface(interfaceId); // covers 0x01ffc9a7 (ERC-165)\n }\n\n // -------------------------------------------------------------------------\n // Utilities\n // -------------------------------------------------------------------------\n\n /**\n * @dev Returns the implementation address this EOA has delegated to via\n * EIP-7702, or address(0) if no delegation is active.\n */\n function getDelegate() external view returns (address) {\n return EIP7702Utils.fetchDelegate(address(this));\n }\n}\n" + }, + "contracts/Etherspot/BasePaymaster.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.23;\n\n/* solhint-disable reason-string */\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport \"./interfaces/IPaymaster.sol\";\nimport \"./interfaces/IEntryPoint.sol\";\nimport \"./core/UserOperationLib.sol\";\n\n/**\n * Helper class for creating a paymaster.\n * provides helper methods for staking.\n * Validates that the postOp is called only by the entryPoint.\n */\nabstract contract BasePaymaster is IPaymaster, Ownable {\n IEntryPoint public immutable entryPoint;\n\n uint256 internal constant PAYMASTER_VALIDATION_GAS_OFFSET =\n UserOperationLib.PAYMASTER_VALIDATION_GAS_OFFSET;\n uint256 internal constant PAYMASTER_POSTOP_GAS_OFFSET =\n UserOperationLib.PAYMASTER_POSTOP_GAS_OFFSET;\n uint256 internal constant PAYMASTER_DATA_OFFSET =\n UserOperationLib.PAYMASTER_DATA_OFFSET;\n\n constructor(IEntryPoint _entryPoint) Ownable(msg.sender) {\n _validateEntryPointInterface(_entryPoint);\n entryPoint = _entryPoint;\n }\n\n //sanity check: make sure this EntryPoint was compiled against the same\n // IEntryPoint of this paymaster\n function _validateEntryPointInterface(\n IEntryPoint _entryPoint\n ) internal virtual returns (bool) {\n require(\n IERC165(address(_entryPoint)).supportsInterface(\n type(IEntryPoint).interfaceId\n ),\n \"IEntryPoint interface mismatch\"\n );\n }\n\n /// @inheritdoc IPaymaster\n function validatePaymasterUserOp(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash,\n uint256 maxCost\n ) external override returns (bytes memory context, uint256 validationData) {\n _requireFromEntryPoint();\n return _validatePaymasterUserOp(userOp, userOpHash, maxCost);\n }\n\n /**\n * Validate a user operation.\n * @param userOp - The user operation.\n * @param userOpHash - The hash of the user operation.\n * @param maxCost - The maximum cost of the user operation.\n */\n function _validatePaymasterUserOp(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash,\n uint256 maxCost\n ) internal virtual returns (bytes memory context, uint256 validationData);\n\n /// @inheritdoc IPaymaster\n function postOp(\n PostOpMode mode,\n bytes calldata context,\n uint256 actualGasCost,\n uint256 actualUserOpFeePerGas\n ) external override {\n _requireFromEntryPoint();\n _postOp(mode, context, actualGasCost, actualUserOpFeePerGas);\n }\n\n /**\n * Post-operation handler.\n * (verified to be called only through the entryPoint)\n * @dev If subclass returns a non-empty context from validatePaymasterUserOp,\n * it must also implement this method.\n * @param mode - Enum with the following options:\n * opSucceeded - User operation succeeded.\n * opReverted - User op reverted. The paymaster still has to pay for gas.\n * postOpReverted - never passed in a call to postOp().\n * @param context - The context value returned by validatePaymasterUserOp\n * @param actualGasCost - Actual gas used so far (without this postOp call).\n * @param actualUserOpFeePerGas - the gas price this UserOp pays. This value is based on the UserOp's maxFeePerGas\n * and maxPriorityFee (and basefee)\n * It is not the same as tx.gasprice, which is what the bundler pays.\n */\n function _postOp(\n PostOpMode mode,\n bytes calldata context,\n uint256 actualGasCost,\n uint256 actualUserOpFeePerGas\n ) internal virtual {\n (mode, context, actualGasCost, actualUserOpFeePerGas); // unused params\n // subclass must override this method if validatePaymasterUserOp returns a context\n revert(\"must override\");\n }\n\n // /**\n // * Add a deposit for this paymaster, used for paying for transaction fees.\n // */\n // function deposit() public payable {\n // entryPoint.depositTo{value: msg.value}(address(this));\n // }\n\n // /**\n // * Withdraw value from the deposit.\n // * @param withdrawAddress - Target to send to.\n // * @param amount - Amount to withdraw.\n // */\n // function withdrawTo(\n // address payable withdrawAddress,\n // uint256 amount\n // ) public onlyOwner {\n // entryPoint.withdrawTo(withdrawAddress, amount);\n // }\n\n /**\n * Add stake for this paymaster.\n * This method can also carry eth value to add to the current stake.\n * @param unstakeDelaySec - The unstake delay for this paymaster. Can only be increased.\n */\n function addStake(uint32 unstakeDelaySec) external payable onlyOwner {\n entryPoint.addStake{value: msg.value}(unstakeDelaySec);\n }\n\n /**\n * Return current paymaster's deposit on the entryPoint.\n */\n function getDeposit() public view returns (uint256) {\n return entryPoint.balanceOf(address(this));\n }\n\n /**\n * Unlock the stake, in order to withdraw it.\n * The paymaster can't serve requests once unlocked, until it calls addStake again\n */\n function unlockStake() external onlyOwner {\n entryPoint.unlockStake();\n }\n\n /**\n * Withdraw the entire paymaster's stake.\n * stake must be unlocked first (and then wait for the unstakeDelay to be over)\n * @param withdrawAddress - The address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external onlyOwner {\n entryPoint.withdrawStake(withdrawAddress);\n }\n\n /**\n * Validate the call is made from a valid entrypoint\n */\n function _requireFromEntryPoint() internal virtual {\n require(msg.sender == address(entryPoint), \"Sender not EntryPoint\");\n }\n}\n" + }, + "contracts/Etherspot/core/Helpers.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.23;\n\n/* solhint-disable no-inline-assembly */\n\n/*\n * For simulation purposes, validateUserOp (and validatePaymasterUserOp)\n * must return this value in case of signature failure, instead of revert.\n */\nuint256 constant SIG_VALIDATION_FAILED = 1;\n\n/*\n * For simulation purposes, validateUserOp (and validatePaymasterUserOp)\n * return this value on success.\n */\nuint256 constant SIG_VALIDATION_SUCCESS = 0;\n\n/**\n * Returned data from validateUserOp.\n * validateUserOp returns a uint256, which is created by `_packedValidationData` and\n * parsed by `_parseValidationData`.\n * @param aggregator - address(0) - The account validated the signature by itself.\n * address(1) - The account failed to validate the signature.\n * otherwise - This is an address of a signature aggregator that must\n * be used to validate the signature.\n * @param validAfter - This UserOp is valid only after this timestamp.\n * @param validaUntil - This UserOp is valid only up to this timestamp.\n */\nstruct ValidationData {\n address aggregator;\n uint48 validAfter;\n uint48 validUntil;\n}\n\n/**\n * Extract sigFailed, validAfter, validUntil.\n * Also convert zero validUntil to type(uint48).max.\n * @param validationData - The packed validation data.\n */\nfunction _parseValidationData(\n uint256 validationData\n) pure returns (ValidationData memory data) {\n address aggregator = address(uint160(validationData));\n uint48 validUntil = uint48(validationData >> 160);\n if (validUntil == 0) {\n validUntil = type(uint48).max;\n }\n uint48 validAfter = uint48(validationData >> (48 + 160));\n return ValidationData(aggregator, validAfter, validUntil);\n}\n\n/**\n * Helper to pack the return value for validateUserOp.\n * @param data - The ValidationData to pack.\n */\nfunction _packValidationData(\n ValidationData memory data\n) pure returns (uint256) {\n return\n uint160(data.aggregator) |\n (uint256(data.validUntil) << 160) |\n (uint256(data.validAfter) << (160 + 48));\n}\n\n/**\n * Helper to pack the return value for validateUserOp, when not using an aggregator.\n * @param sigFailed - True for signature failure, false for success.\n * @param validUntil - Last timestamp this UserOperation is valid (or zero for infinite).\n * @param validAfter - First timestamp this UserOperation is valid.\n */\nfunction _packValidationData(\n bool sigFailed,\n uint48 validUntil,\n uint48 validAfter\n) pure returns (uint256) {\n return\n (sigFailed ? 1 : 0) |\n (uint256(validUntil) << 160) |\n (uint256(validAfter) << (160 + 48));\n}\n\n/**\n * keccak function over calldata.\n * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.\n */\nfunction calldataKeccak(bytes calldata data) 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/**\n * The minimum of two numbers.\n * @param a - First number.\n * @param b - Second number.\n */\nfunction min(uint256 a, uint256 b) pure returns (uint256) {\n return a < b ? a : b;\n}\n" + }, + "contracts/Etherspot/core/UserOperationLib.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.23;\n\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/PackedUserOperation.sol\";\nimport {calldataKeccak, min} from \"./Helpers.sol\";\n\n/**\n * Utility functions helpful when working with UserOperation structs.\n */\nlibrary UserOperationLib {\n uint256 public constant PAYMASTER_VALIDATION_GAS_OFFSET = 20;\n uint256 public constant PAYMASTER_POSTOP_GAS_OFFSET = 36;\n uint256 public constant PAYMASTER_DATA_OFFSET = 52;\n /**\n * Get sender from user operation data.\n * @param userOp - The user operation data.\n */\n function getSender(\n PackedUserOperation calldata userOp\n ) internal pure returns (address) {\n address data;\n //read sender from userOp, which is first userOp member (saves 800 gas...)\n assembly {\n data := calldataload(userOp)\n }\n return address(uint160(data));\n }\n\n /**\n * Relayer/block builder might submit the TX with higher priorityFee,\n * but the user should not pay above what he signed for.\n * @param userOp - The user operation data.\n */\n function gasPrice(\n PackedUserOperation calldata userOp\n ) internal view returns (uint256) {\n unchecked {\n (uint256 maxPriorityFeePerGas, uint256 maxFeePerGas) = unpackUints(\n userOp.gasFees\n );\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n /**\n * Pack the user operation data into bytes for hashing.\n * @param userOp - The user operation data.\n */\n function encode(\n PackedUserOperation calldata userOp\n ) internal pure returns (bytes memory ret) {\n address sender = getSender(userOp);\n uint256 nonce = userOp.nonce;\n bytes32 hashInitCode = calldataKeccak(userOp.initCode);\n bytes32 hashCallData = calldataKeccak(userOp.callData);\n bytes32 accountGasLimits = userOp.accountGasLimits;\n uint256 preVerificationGas = userOp.preVerificationGas;\n bytes32 gasFees = userOp.gasFees;\n bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);\n\n return\n abi.encode(\n sender,\n nonce,\n hashInitCode,\n hashCallData,\n accountGasLimits,\n preVerificationGas,\n gasFees,\n hashPaymasterAndData\n );\n }\n\n function unpackUints(\n bytes32 packed\n ) internal pure returns (uint256 high128, uint256 low128) {\n return (uint128(bytes16(packed)), uint128(uint256(packed)));\n }\n\n //unpack just the high 128-bits from a packed value\n function unpackHigh128(bytes32 packed) internal pure returns (uint256) {\n return uint256(packed) >> 128;\n }\n\n // unpack just the low 128-bits from a packed value\n function unpackLow128(bytes32 packed) internal pure returns (uint256) {\n return uint128(uint256(packed));\n }\n\n function unpackMaxPriorityFeePerGas(\n PackedUserOperation calldata userOp\n ) internal pure returns (uint256) {\n return unpackHigh128(userOp.gasFees);\n }\n\n function unpackMaxFeePerGas(\n PackedUserOperation calldata userOp\n ) internal pure returns (uint256) {\n return unpackLow128(userOp.gasFees);\n }\n\n function unpackVerificationGasLimit(\n PackedUserOperation calldata userOp\n ) internal pure returns (uint256) {\n return unpackHigh128(userOp.accountGasLimits);\n }\n\n function unpackCallGasLimit(\n PackedUserOperation calldata userOp\n ) internal pure returns (uint256) {\n return unpackLow128(userOp.accountGasLimits);\n }\n\n function unpackPaymasterVerificationGasLimit(\n PackedUserOperation calldata userOp\n ) internal pure returns (uint256) {\n return\n uint128(\n bytes16(\n userOp.paymasterAndData[\n PAYMASTER_VALIDATION_GAS_OFFSET:PAYMASTER_POSTOP_GAS_OFFSET\n ]\n )\n );\n }\n\n function unpackPostOpGasLimit(\n PackedUserOperation calldata userOp\n ) internal pure returns (uint256) {\n return\n uint128(\n bytes16(\n userOp.paymasterAndData[\n PAYMASTER_POSTOP_GAS_OFFSET:PAYMASTER_DATA_OFFSET\n ]\n )\n );\n }\n\n function unpackPaymasterStaticFields(\n bytes calldata paymasterAndData\n )\n internal\n pure\n returns (\n address paymaster,\n uint256 validationGasLimit,\n uint256 postOpGasLimit\n )\n {\n return (\n address(\n bytes20(paymasterAndData[:PAYMASTER_VALIDATION_GAS_OFFSET])\n ),\n uint128(\n bytes16(\n paymasterAndData[\n PAYMASTER_VALIDATION_GAS_OFFSET:PAYMASTER_POSTOP_GAS_OFFSET\n ]\n )\n ),\n uint128(\n bytes16(\n paymasterAndData[\n PAYMASTER_POSTOP_GAS_OFFSET:PAYMASTER_DATA_OFFSET\n ]\n )\n )\n );\n }\n\n /**\n * Hash the user operation data.\n * @param userOp - The user operation data.\n */\n function hash(\n PackedUserOperation calldata userOp\n ) internal pure returns (bytes32) {\n return keccak256(encode(userOp));\n }\n}\n" + }, + "contracts/Etherspot/EtherspotPaymaster.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.23;\n\nimport \"./BasePaymaster.sol\";\nimport \"./interfaces/IEntryPoint.sol\";\n\n/**\n * A single-owner whitelist paymaster.\n * Owner adds/removes addresses that are allowed to have their gas sponsored.\n * No signature required — whitelist is checked purely on-chain.\n */\ncontract SimpleWhitelistPaymaster is BasePaymaster {\n using UserOperationLib for PackedUserOperation;\n mapping(address => bool) public whitelist;\n\n event AddedToWhitelist(address indexed account);\n event RemovedFromWhitelist(address indexed account);\n\n constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint) {}\n\n // -------------------------------------------------------------------------\n // Owner whitelist management\n // -------------------------------------------------------------------------\n\n function addToWhitelist(address account) external onlyOwner {\n require(account != address(0), \"Zero address\");\n whitelist[account] = true;\n emit AddedToWhitelist(account);\n }\n\n function addBatchToWhitelist(\n address[] calldata accounts\n ) external onlyOwner {\n for (uint256 i; i < accounts.length; ++i) {\n require(accounts[i] != address(0), \"Zero address\");\n whitelist[accounts[i]] = true;\n emit AddedToWhitelist(accounts[i]);\n }\n }\n\n function removeFromWhitelist(address account) external onlyOwner {\n whitelist[account] = false;\n emit RemovedFromWhitelist(account);\n }\n\n // -------------------------------------------------------------------------\n // Deposit management\n // -------------------------------------------------------------------------\n\n function deposit() external payable onlyOwner {\n entryPoint.depositTo{value: msg.value}(address(this));\n }\n\n function withdrawTo(address payable to, uint256 amount) external onlyOwner {\n entryPoint.withdrawTo(to, amount);\n }\n\n // -------------------------------------------------------------------------\n // ERC-4337 paymaster logic\n // -------------------------------------------------------------------------\n\n function _validatePaymasterUserOp(\n PackedUserOperation calldata userOp,\n bytes32 /*userOpHash*/,\n uint256 /*maxCost*/\n )\n internal\n view\n override\n returns (bytes memory context, uint256 validationData)\n {\n require(\n whitelist[userOp.getSender()],\n \"SimpleWhitelistPaymaster: sender not whitelisted\"\n );\n return (\"\", 0); // 0 = validation success, no expiry\n }\n\n // No context returned above so postOp is never called — default impl is fine.\n\n // Etherspot EP9 reports a different interfaceId than what the local IEntryPoint\n // computes — skip the interface check so deployment doesn't revert.\n function _validateEntryPointInterface(\n IEntryPoint\n ) internal pure override returns (bool) {}\n}\n" + }, + "contracts/Etherspot/interfaces/IAggregator.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.7.5;\n\nimport \"./PackedUserOperation.sol\";\n\n/**\n * Aggregated Signatures validator.\n */\ninterface IAggregator {\n /**\n * Validate aggregated signature.\n * Revert if the aggregated signature does not match the given list of operations.\n * @param userOps - Array of UserOperations to validate the signature for.\n * @param signature - The aggregated signature.\n */\n function validateSignatures(\n PackedUserOperation[] calldata userOps,\n bytes calldata signature\n ) external view;\n\n /**\n * Validate signature of a single userOp.\n * This method should be called by bundler after EntryPointSimulation.simulateValidation() returns\n * the aggregator this account uses.\n * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.\n * @param userOp - The userOperation received from the user.\n * @return sigForUserOp - The value to put into the signature field of the userOp when calling handleOps.\n * (usually empty, unless account and aggregator support some kind of \"multisig\".\n */\n function validateUserOpSignature(\n PackedUserOperation calldata userOp\n ) external view returns (bytes memory sigForUserOp);\n\n /**\n * Aggregate multiple signatures into a single value.\n * This method is called off-chain to calculate the signature to pass with handleOps()\n * bundler MAY use optimized custom code perform this aggregation.\n * @param userOps - Array of UserOperations to collect the signatures from.\n * @return aggregatedSignature - The aggregated signature.\n */\n function aggregateSignatures(\n PackedUserOperation[] calldata userOps\n ) external view returns (bytes memory aggregatedSignature);\n}\n" + }, + "contracts/Etherspot/interfaces/IEntryPoint.sol": { + "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.7.5;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n/* solhint-disable reason-string */\n\nimport \"./PackedUserOperation.sol\";\nimport \"./IStakeManager.sol\";\nimport \"./IAggregator.sol\";\nimport \"./INonceManager.sol\";\n\ninterface IEntryPoint is IStakeManager, INonceManager {\n /***\n * An event emitted after each successful request.\n * @param userOpHash - Unique identifier for the request (hash its entire content, except signature).\n * @param sender - The account that generates this request.\n * @param paymaster - If non-null, the paymaster that pays for this request.\n * @param nonce - The nonce value from the request.\n * @param success - True if the sender transaction succeeded, false if reverted.\n * @param actualGasCost - Actual amount paid (by account or paymaster) for this UserOperation.\n * @param actualGasUsed - Total gas used by this UserOperation (including preVerification, creation,\n * validation and execution).\n */\n event UserOperationEvent(\n bytes32 indexed userOpHash,\n address indexed sender,\n address indexed paymaster,\n uint256 nonce,\n bool success,\n uint256 actualGasCost,\n uint256 actualGasUsed\n );\n\n /**\n * Account \"sender\" was deployed.\n * @param userOpHash - The userOp that deployed this account. UserOperationEvent will follow.\n * @param sender - The account that is deployed\n * @param factory - The factory used to deploy this account (in the initCode)\n * @param paymaster - The paymaster used by this UserOp\n */\n event AccountDeployed(\n bytes32 indexed userOpHash,\n address indexed sender,\n address factory,\n address paymaster\n );\n\n /**\n * An event emitted if the UserOperation \"callData\" reverted with non-zero length.\n * @param userOpHash - The request unique identifier.\n * @param sender - The sender of this request.\n * @param nonce - The nonce used in the request.\n * @param revertReason - The return bytes from the (reverted) call to \"callData\".\n */\n event UserOperationRevertReason(\n bytes32 indexed userOpHash,\n address indexed sender,\n uint256 nonce,\n bytes revertReason\n );\n\n /**\n * An event emitted if the UserOperation Paymaster's \"postOp\" call reverted with non-zero length.\n * @param userOpHash - The request unique identifier.\n * @param sender - The sender of this request.\n * @param nonce - The nonce used in the request.\n * @param revertReason - The return bytes from the (reverted) call to \"callData\".\n */\n event PostOpRevertReason(\n bytes32 indexed userOpHash,\n address indexed sender,\n uint256 nonce,\n bytes revertReason\n );\n\n /**\n * UserOp consumed more than prefund. The UserOperation is reverted, and no refund is made.\n * @param userOpHash - The request unique identifier.\n * @param sender - The sender of this request.\n * @param nonce - The nonce used in the request.\n */\n event UserOperationPrefundTooLow(\n bytes32 indexed userOpHash,\n address indexed sender,\n uint256 nonce\n );\n\n /**\n * An event emitted by handleOps(), before starting the execution loop.\n * Any event emitted before this event, is part of the validation.\n */\n event BeforeExecution();\n\n /**\n * Signature aggregator used by the following UserOperationEvents within this bundle.\n * @param aggregator - The aggregator used for the following UserOperationEvents.\n */\n event SignatureAggregatorChanged(address indexed aggregator);\n\n /**\n * A custom revert error of handleOps, to identify the offending op.\n * Should be caught in off-chain handleOps simulation and not happen on-chain.\n * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\n * NOTE: If simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\n * @param opIndex - Index into the array of ops to the failed one (in simulateValidation, this is always zero).\n * @param reason - Revert reason. The string starts with a unique code \"AAmn\",\n * where \"m\" is \"1\" for factory, \"2\" for account and \"3\" for paymaster issues,\n * so a failure can be attributed to the correct entity.\n */\n error FailedOp(uint256 opIndex, string reason);\n\n /**\n * A custom revert error of handleOps, to report a revert by account or paymaster.\n * @param opIndex - Index into the array of ops to the failed one (in simulateValidation, this is always zero).\n * @param reason - Revert reason. see FailedOp(uint256,string), above\n * @param inner - data from inner cought revert reason\n * @dev note that inner is truncated to 2048 bytes\n */\n error FailedOpWithRevert(uint256 opIndex, string reason, bytes inner);\n\n error PostOpReverted(bytes returnData);\n\n /**\n * Error case when a signature aggregator fails to verify the aggregated signature it had created.\n * @param aggregator The aggregator that failed to verify the signature\n */\n error SignatureValidationFailed(address aggregator);\n\n // Return value of getSenderAddress.\n error SenderAddressResult(address sender);\n\n // UserOps handled, per aggregator.\n struct UserOpsPerAggregator {\n PackedUserOperation[] userOps;\n // Aggregator address\n IAggregator aggregator;\n // Aggregated signature\n bytes signature;\n }\n\n /**\n * Execute a batch of UserOperations.\n * No signature aggregator is used.\n * If any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops - The operations to execute.\n * @param beneficiary - The address to receive the fees.\n */\n function handleOps(\n PackedUserOperation[] calldata ops,\n address payable beneficiary\n ) external;\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator - The operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts).\n * @param beneficiary - The address to receive the fees.\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) external;\n\n /**\n * Generate a request Id - unique identifier for this request.\n * The request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n * @param userOp - The user operation to generate the request ID for.\n * @return hash the hash of this UserOperation\n */\n function getUserOpHash(\n PackedUserOperation calldata userOp\n ) external view returns (bytes32);\n\n /**\n * Gas and return values during simulation.\n * @param preOpGas - The gas used for validation (including preValidationGas)\n * @param prefund - The required prefund for this operation\n * @param accountValidationData - returned validationData from account.\n * @param paymasterValidationData - return validationData from paymaster.\n * @param paymasterContext - Returned by validatePaymasterUserOp (to be passed into postOp)\n */\n struct ReturnInfo {\n uint256 preOpGas;\n uint256 prefund;\n uint256 accountValidationData;\n uint256 paymasterValidationData;\n bytes paymasterContext;\n }\n\n /**\n * Returned aggregated signature info:\n * The aggregator returned by the account, and its current stake.\n */\n struct AggregatorStakeInfo {\n address aggregator;\n StakeInfo stakeInfo;\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * This method always revert, and returns the address in SenderAddressResult error\n * @param initCode - The constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes memory initCode) external;\n\n error DelegateAndRevert(bool success, bytes ret);\n\n /**\n * Helper method for dry-run testing.\n * @dev calling this method, the EntryPoint will make a delegatecall to the given data, and report (via revert) the result.\n * The method always revert, so is only useful off-chain for dry run calls, in cases where state-override to replace\n * actual EntryPoint code is less convenient.\n * @param target a target contract to make a delegatecall from entrypoint\n * @param data data to pass to target in a delegatecall\n */\n function delegateAndRevert(address target, bytes calldata data) external;\n}\n" + }, + "contracts/Etherspot/interfaces/INonceManager.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.7.5;\n\ninterface INonceManager {\n /**\n * Return the next nonce for this sender.\n * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)\n * But UserOp with different keys can come with arbitrary order.\n *\n * @param sender the account address\n * @param key the high 192 bit of the nonce\n * @return nonce a full nonce to pass for next UserOp with this sender.\n */\n function getNonce(\n address sender,\n uint192 key\n ) external view returns (uint256 nonce);\n\n /**\n * Manually increment the nonce of the sender.\n * This method is exposed just for completeness..\n * Account does NOT need to call it, neither during validation, nor elsewhere,\n * as the EntryPoint will update the nonce regardless.\n * Possible use-case is call it with various keys to \"initialize\" their nonces to one, so that future\n * UserOperations will not pay extra for the first transaction with a given key.\n */\n function incrementNonce(uint192 key) external;\n}\n" + }, + "contracts/Etherspot/interfaces/IPaymaster.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.7.5;\n\nimport \"./PackedUserOperation.sol\";\n\n/**\n * The interface exposed by a paymaster contract, who agrees to pay the gas for user's operations.\n * A paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction.\n */\ninterface IPaymaster {\n enum PostOpMode {\n // User op succeeded.\n opSucceeded,\n // User op reverted. Still has to pay for gas.\n opReverted,\n // Only used internally in the EntryPoint (cleanup after postOp reverts). Never calling paymaster with this value\n postOpReverted\n }\n\n /**\n * Payment validation: check if paymaster agrees to pay.\n * Must verify sender is the entryPoint.\n * Revert to reject this request.\n * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted).\n * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns.\n * @param userOp - The user operation.\n * @param userOpHash - Hash of the user's request data.\n * @param maxCost - The maximum cost of this transaction (based on maximum gas and gas price from userOp).\n * @return context - Value to send to a postOp. Zero length to signify postOp is not required.\n * @return validationData - Signature and time-range of this operation, encoded the same as the return\n * value of validateUserOperation.\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * other values are invalid for paymaster.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validatePaymasterUserOp(\n PackedUserOperation calldata userOp,\n bytes32 userOpHash,\n uint256 maxCost\n ) external returns (bytes memory context, uint256 validationData);\n\n /**\n * Post-operation handler.\n * Must verify sender is the entryPoint.\n * @param mode - Enum with the following options:\n * opSucceeded - User operation succeeded.\n * opReverted - User op reverted. The paymaster still has to pay for gas.\n * postOpReverted - never passed in a call to postOp().\n * @param context - The context value returned by validatePaymasterUserOp\n * @param actualGasCost - Actual gas used so far (without this postOp call).\n * @param actualUserOpFeePerGas - the gas price this UserOp pays. This value is based on the UserOp's maxFeePerGas\n * and maxPriorityFee (and basefee)\n * It is not the same as tx.gasprice, which is what the bundler pays.\n */\n function postOp(\n PostOpMode mode,\n bytes calldata context,\n uint256 actualGasCost,\n uint256 actualUserOpFeePerGas\n ) external;\n}\n" + }, + "contracts/Etherspot/interfaces/IStakeManager.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity >=0.7.5;\n\n/**\n * Manage deposits and stakes.\n * Deposit is just a balance used to pay for UserOperations (either by a paymaster or an account).\n * Stake is value locked for at least \"unstakeDelay\" by the staked entity.\n */\ninterface IStakeManager {\n event Deposited(address indexed account, uint256 totalDeposit);\n\n event Withdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n // Emitted when stake or unstake delay are modified.\n event StakeLocked(\n address indexed account,\n uint256 totalStaked,\n uint256 unstakeDelaySec\n );\n\n // Emitted once a stake is scheduled for withdrawal.\n event StakeUnlocked(address indexed account, uint256 withdrawTime);\n\n event StakeWithdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /**\n * @param deposit - The entity's deposit.\n * @param staked - True if this entity is staked.\n * @param stake - Actual amount of ether staked for this entity.\n * @param unstakeDelaySec - Minimum delay to withdraw the stake.\n * @param withdrawTime - First block timestamp where 'withdrawStake' will be callable, or zero if already locked.\n * @dev Sizes were chosen so that deposit fits into one cell (used during handleOp)\n * and the rest fit into a 2nd cell (used during stake/unstake)\n * - 112 bit allows for 10^15 eth\n * - 48 bit for full timestamp\n * - 32 bit allows 150 years for unstake delay\n */\n struct DepositInfo {\n uint256 deposit;\n bool staked;\n uint112 stake;\n uint32 unstakeDelaySec;\n uint48 withdrawTime;\n }\n\n // API struct used by getStakeInfo and simulateValidation.\n struct StakeInfo {\n uint256 stake;\n uint256 unstakeDelaySec;\n }\n\n /**\n * Get deposit info.\n * @param account - The account to query.\n * @return info - Full deposit information of given account.\n */\n function getDepositInfo(\n address account\n ) external view returns (DepositInfo memory info);\n\n /**\n * Get account balance.\n * @param account - The account to query.\n * @return - The deposit (for gas payment) of the account.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * Add to the deposit of the given account.\n * @param account - The account to add to.\n */\n function depositTo(address account) external payable;\n\n /**\n * Add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param _unstakeDelaySec - The new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 _unstakeDelaySec) external payable;\n\n /**\n * Attempt to unlock the stake.\n * The value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external;\n\n /**\n * Withdraw from the (unlocked) stake.\n * Must first call unlockStake and wait for the unstakeDelay to pass.\n * @param withdrawAddress - The address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external;\n\n /**\n * Withdraw from the deposit.\n * @param withdrawAddress - The address to send withdrawn value.\n * @param withdrawAmount - The amount to withdraw.\n */\n function withdrawTo(\n address payable withdrawAddress,\n uint256 withdrawAmount\n ) external;\n}\n" + }, + "contracts/Etherspot/interfaces/PackedUserOperation.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.7.5;\n\n/**\n * User Operation struct\n * @param sender - The sender account of this request.\n * @param nonce - Unique value the sender uses to verify it is not a replay.\n * @param initCode - If set, the account contract will be created by this constructor/\n * @param callData - The method call to execute on this account.\n * @param accountGasLimits - Packed gas limits for validateUserOp and gas limit passed to the callData method call.\n * @param preVerificationGas - Gas not calculated by the handleOps method, but added to the gas paid.\n * Covers batch overhead.\n * @param gasFees - packed gas fields maxPriorityFeePerGas and maxFeePerGas - Same as EIP-1559 gas parameters.\n * @param paymasterAndData - If set, this field holds the paymaster address, verification gas limit, postOp gas limit and paymaster-specific extra data\n * The paymaster will pay for the transaction instead of the sender.\n * @param signature - Sender-verified signature over the entire request, the EntryPoint address and the chain ID.\n */\nstruct PackedUserOperation {\n address sender;\n uint256 nonce;\n bytes initCode;\n bytes callData;\n bytes32 accountGasLimits;\n uint256 preVerificationGas;\n bytes32 gasFees;\n bytes paymasterAndData;\n bytes signature;\n}\n" + }, "contracts/Factory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport {PlatformPaymaster} from \"./PlatformPaymaster.sol\";\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport {Clones} from \"@openzeppelin/contracts/proxy/Clones.sol\";\n\ncontract PlatformAccountFactory is Ownable {\n address public tdocDeployer;\n address public paymasterImplementation;\n\n event PlatformOnboarded(address indexed platformAddress, address indexed paymaster);\n event TdocDeployerUpdated(address indexed newDeployer);\n event ImplementationUpdated(address indexed newImplementation);\n\n constructor(\n address _tdocDeployer,\n address _paymasterImplementation\n ) Ownable(msg.sender) {\n tdocDeployer = _tdocDeployer;\n paymasterImplementation = _paymasterImplementation;\n }\n\n function updateTdocDeployer(address _tdocDeployer) external onlyOwner {\n require(_tdocDeployer != address(0), \"Zero address\");\n tdocDeployer = _tdocDeployer;\n emit TdocDeployerUpdated(_tdocDeployer);\n }\n\n function updatePaymasterImplementation(address _impl) external onlyOwner {\n require(_impl != address(0), \"Zero address\");\n paymasterImplementation = _impl;\n emit ImplementationUpdated(_impl);\n }\n\n function deployPlatformPaymaster(\n address platformAddress,\n uint256 dailyLimit,\n bytes32 salt\n ) external returns (address paymaster) {\n paymaster = Clones.cloneDeterministic(paymasterImplementation, salt);\n PlatformPaymaster(payable(paymaster)).initialize(platformAddress, dailyLimit, tdocDeployer);\n emit PlatformOnboarded(platformAddress, paymaster);\n }\n\n // Address is determined solely by implementation + salt (not by constructor args).\n function computePaymasterAddress(bytes32 salt) external view returns (address) {\n return Clones.predictDeterministicAddress(paymasterImplementation, salt, address(this));\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport {PlatformPaymaster} from \"./PlatformPaymaster.sol\";\nimport {\n IEntryPoint\n} from \"@account-abstraction/contracts/interfaces/IEntryPoint.sol\";\n\ncontract PlatformAccountFactory {\n IEntryPoint public immutable entryPoint;\n\n event PlatformOnboarded(\n address indexed platformAddress,\n address indexed paymaster\n );\n\n constructor(IEntryPoint _entryPoint) {\n entryPoint = _entryPoint;\n }\n\n // ── Deploy paymaster for a platform ───────────────────────────────\n // platformAddress = platform's EOA → paymaster owner\n // dailyLimit = wei per user per day (0 = unlimited)\n // salt = for CREATE2\n // Registries are added after deployment via PlatformPaymaster.addRegistry()\n function deployPlatformPaymaster(\n address platformAddress,\n uint256 dailyLimit,\n bytes32 salt\n ) external returns (address paymaster) {\n paymaster = address(\n new PlatformPaymaster{salt: salt}(\n entryPoint,\n platformAddress,\n dailyLimit\n )\n );\n\n emit PlatformOnboarded(platformAddress, paymaster);\n }\n\n // ── Predict address before deploying ─────────────────────────────\n\n function computePaymasterAddress(\n address platformAddress,\n uint256 dailyLimit,\n bytes32 salt\n ) external view returns (address) {\n bytes32 initHash = keccak256(\n abi.encodePacked(\n type(PlatformPaymaster).creationCode,\n abi.encode(entryPoint, platformAddress, dailyLimit)\n )\n );\n return\n address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n bytes1(0xff),\n address(this),\n salt,\n initHash\n )\n )\n )\n )\n );\n }\n}\n" + }, + "contracts/IClientRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n// Matches the existing deployed registry contract\ninterface IClientRegistry {\n function beneficiary() external view returns (address);\n function holder() external view returns (address);\n}\n" + }, + "contracts/Lock.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.28;\n\n// Uncomment this line to use console.log\n// import \"hardhat/console.sol\";\n\ncontract Lock {\n uint public unlockTime;\n address payable public owner;\n\n event Withdrawal(uint amount, uint when);\n\n constructor(uint _unlockTime) payable {\n require(\n block.timestamp < _unlockTime,\n \"Unlock time should be in the future\"\n );\n\n unlockTime = _unlockTime;\n owner = payable(msg.sender);\n }\n\n function withdraw() public {\n // Uncomment this line, and the import of \"hardhat/console.sol\", to print a log in your terminal\n // console.log(\"Unlock time is %o and block timestamp is %o\", unlockTime, block.timestamp);\n\n require(block.timestamp >= unlockTime, \"You can't withdraw yet\");\n require(msg.sender == owner, \"You aren't the owner\");\n\n emit Withdrawal(address(this).balance, block.timestamp);\n\n owner.transfer(address(this).balance);\n }\n}\n" }, "contracts/PlatformPaymaster.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport \"@account-abstraction/contracts/core/BasePaymaster.sol\";\nimport \"@account-abstraction/contracts/core/Helpers.sol\";\n\ninterface ITDocDeployer {\n function deploy(\n address implementation,\n bytes memory params\n ) external returns (address);\n}\n\ninterface ITradeTrustToken {\n function mint(\n address beneficiary,\n address holder,\n uint256 tokenId,\n bytes calldata remark\n ) external returns (address);\n}\n\ninterface IAccessControl {\n function grantRole(bytes32 role, address account) external;\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n/**\n * PlatformPaymaster — validates by inspecting the target contract in callData.\n *\n * Validation strategy (no third-party storage reads → bundler compliant):\n * 1. Decode userOp.callData → must be execute(address to, uint256, bytes)\n * 2. Check `to` is in authorizedRegistries (paymaster's own storage)\n * 3. Check daily spend (paymaster's own storage — always allowed)\n *\n * Access control is enforced by the Storage contract itself:\n * require(msg.sender == beneficiary || msg.sender == holder)\n * so non-beneficiary/holder callers are rejected at execution time.\n * If the call reverts, _postOp skips the spend update.\n */\ncontract PlatformPaymaster is BasePaymaster {\n bytes4 private constant EXECUTE_SEL =\n bytes4(keccak256(\"execute(address,uint256,bytes)\"));\n bytes4 private constant DEPLOY_REGISTRY_SEL =\n bytes4(keccak256(\"deployRegistry(address,string,string)\"));\n bytes4 private constant MINT_DOCUMENT_SEL =\n bytes4(\n keccak256(\"mintDocument(address,address,address,uint256,bytes)\")\n );\n\n bytes32 private constant DEFAULT_ADMIN_ROLE = bytes32(0);\n\n ITDocDeployer public tdocDeployer;\n\n // Paymaster's own storage — always allowed under ERC-7562\n mapping(address => bool) public authorizedRegistries;\n mapping(address => bool) public authorizedTitleEscrows;\n // remaining deployment credits per user; max 3 per user\n mapping(address => uint256) public userWhitelist;\n // Addresses permitted to call title escrow functions via this paymaster\n mapping(address => bool) public authorizedCallers;\n // Count of documents minted per user\n mapping(address => uint256) public documentsMinted;\n\n // Daily spend tracking — paymaster's own storage, always allowed\n mapping(address => uint256) public dailySpend;\n mapping(address => uint256) public lastReset;\n uint256 public dailyLimit;\n\n event RegistryAdded(address indexed registry);\n event RegistryRemoved(address indexed registry);\n event TitleEscrowLinked(\n address indexed titleEscrow,\n address indexed registry\n );\n event TitleEscrowAdded(address indexed titleEscrow);\n event TitleEscrowRemoved(address indexed titleEscrow);\n event UserWhitelistUpdated(address indexed user, uint256 credits);\n event RegistryDeployed(\n address indexed user,\n address indexed deployed,\n uint256 creditsLeft\n );\n event AuthorizedCallerUpdated(address indexed caller, bool authorized);\n event UserOpSponsored(address indexed user, uint256 gasCost);\n event UserOpRejected(address indexed user, string reason);\n event DailyLimitUpdated(uint256 newLimit);\n\n // Deployed once as the shared implementation; BasePaymaster sets owner = msg.sender.\n // That non-zero owner prevents initialize() from running on the implementation itself.\n constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint) {}\n\n // Called by the factory immediately after cloneDeterministic().\n // A fresh clone has all-zero storage, so owner() == address(0) exactly once.\n function initialize(\n address _owner,\n uint256 _dailyLimit,\n address _tdocDeployer\n ) external {\n require(owner() == address(0), \"Already initialized\");\n require(_owner != address(0), \"Zero owner\");\n _transferOwnership(_owner);\n dailyLimit = _dailyLimit;\n tdocDeployer = ITDocDeployer(_tdocDeployer);\n }\n\n // Grant/update deployment credits for a user; credits cannot exceed 3\n function setUserWhitelist(\n address user,\n uint256 credits\n ) external onlyOwner {\n require(user != address(0), \"Zero address\");\n require(credits <= 3, \"Exceeds max credits of 3\");\n userWhitelist[user] = credits;\n emit UserWhitelistUpdated(user, credits);\n }\n\n // add function to remove user from whitelist\n function removeUserFromWhitelist(address user) external onlyOwner {\n require(user != address(0), \"Zero address\");\n userWhitelist[user] = 0;\n emit UserWhitelistUpdated(user, 0);\n }\n\n // Deploys a TDoc clone on behalf of a whitelisted user; consumes one credit.\n // Role setup (atomic, no follow-up txs needed):\n // - msg.sender (EOA) gets DEFAULT_ADMIN_ROLE\n // - paymaster gets MINTER_ROLE + RESTORER_ROLE + ACCEPTER_ROLE\n function deployRegistry(\n address implementation,\n string memory name,\n string memory symbol\n ) external returns (address deployed) {\n require(address(tdocDeployer) != address(0), \"TdocDeployer not set\");\n uint256 credits = userWhitelist[msg.sender];\n require(credits > 0, \"No deployment credits\");\n\n userWhitelist[msg.sender] = credits - 1;\n\n // Paymaster is temporary admin so it can configure roles after deploy\n bytes memory params = abi.encode(name, symbol, address(this));\n deployed = tdocDeployer.deploy(implementation, params);\n\n // Hand admin to the calling EOA\n IAccessControl(deployed).grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n\n // Paymaster keeps only the operational roles it needs\n // (MINTER_ROLE, RESTORER_ROLE, ACCEPTER_ROLE were granted to address(this) via initialize)\n\n // Relinquish admin — EOA is now sole admin\n IAccessControl(deployed).renounceRole(\n DEFAULT_ADMIN_ROLE,\n address(this)\n );\n\n authorizedRegistries[deployed] = true;\n emit RegistryAdded(deployed);\n emit RegistryDeployed(msg.sender, deployed, credits - 1);\n }\n\n // Mints a TradeTrust document, captures the TitleEscrow, and auto-authorizes it.\n // Paymaster must hold MINTER_ROLE on the registry.\n // Callable gaslessly by userWhitelist users (credits not consumed — only deployRegistry uses credits).\n function mintDocument(\n address registry,\n address beneficiary,\n address holder,\n uint256 tokenId,\n bytes calldata remark\n ) external returns (address titleEscrow) {\n require(authorizedRegistries[registry], \"registry not authorized\");\n\n titleEscrow = ITradeTrustToken(registry).mint(\n beneficiary,\n holder,\n tokenId,\n remark\n );\n\n // Auto-authorize beneficiary and holder to call title escrow functions\n authorizedCallers[beneficiary] = true;\n authorizedCallers[holder] = true;\n\n authorizedTitleEscrows[titleEscrow] = true;\n documentsMinted[msg.sender]++;\n emit TitleEscrowLinked(titleEscrow, registry);\n }\n\n function addRegistry(address registry) external onlyOwner {\n require(registry != address(0), \"Zero address\");\n authorizedRegistries[registry] = true;\n emit RegistryAdded(registry);\n }\n\n function removeRegistry(address registry) external onlyOwner {\n authorizedRegistries[registry] = false;\n emit RegistryRemoved(registry);\n }\n\n function addTitleEscrow(address titleEscrow) external onlyOwner {\n require(titleEscrow != address(0), \"Zero address\");\n authorizedTitleEscrows[titleEscrow] = true;\n emit TitleEscrowAdded(titleEscrow);\n }\n\n function removeTitleEscrow(address titleEscrow) external onlyOwner {\n authorizedTitleEscrows[titleEscrow] = false;\n emit TitleEscrowRemoved(titleEscrow);\n }\n\n function addAuthorizedCaller(address caller) external onlyOwner {\n require(caller != address(0), \"Zero address\");\n authorizedCallers[caller] = true;\n emit AuthorizedCallerUpdated(caller, true);\n }\n\n function removeAuthorizedCaller(address caller) external onlyOwner {\n authorizedCallers[caller] = false;\n emit AuthorizedCallerUpdated(caller, false);\n }\n\n function setDailyLimit(uint256 _dailyLimit) external onlyOwner {\n dailyLimit = _dailyLimit;\n emit DailyLimitUpdated(_dailyLimit);\n }\n\n function _validatePaymasterUserOp(\n PackedUserOperation calldata userOp,\n bytes32, // userOpHash — not needed\n uint256 maxCost\n ) internal override returns (bytes memory context, uint256 validationData) {\n address sender = userOp.sender;\n\n // 1. callData must be long enough for selector + one address arg\n if (userOp.callData.length < 36) {\n emit UserOpRejected(sender, \"callData too short\");\n return (\"\", _packValidationData(true, 0, 0));\n }\n\n // 2. Must call execute(address,uint256,bytes)\n bytes4 sel = bytes4(userOp.callData[:4]);\n if (sel != EXECUTE_SEL) {\n emit UserOpRejected(sender, \"wrong selector\");\n return (\"\", _packValidationData(true, 0, 0));\n }\n\n // 3. Decode target and inner calldata\n (address target, , bytes memory innerData) = abi.decode(\n userOp.callData[4:],\n (address, uint256, bytes)\n );\n\n // Path A — calling an authorized registry or title escrow (regular sponsored op)\n // Only authorizedCallers or the platform owner may be sponsored here.\n if (authorizedRegistries[target] || authorizedTitleEscrows[target]) {\n if (!authorizedCallers[sender] && sender != owner()) {\n emit UserOpRejected(sender, \"caller not authorized\");\n return (\"\", _packValidationData(true, 0, 0));\n }\n if (dailyLimit > 0 && dailySpend[sender] + maxCost > dailyLimit) {\n emit UserOpRejected(sender, \"daily limit exceeded\");\n return (\"\", _packValidationData(true, 0, 0));\n }\n return (\n abi.encode(sender, maxCost, false),\n _packValidationData(false, 0, 0)\n );\n }\n\n // Path B — gasless paymaster call (deployRegistry or mintDocument)\n // Double-spend safe: EntryPoint sequential nonces allow only one\n // pending UserOp per sender in the mempool at a time.\n if (target == address(this)) {\n bytes4 innerSel;\n assembly {\n innerSel := mload(add(innerData, 32))\n }\n\n if (innerSel == DEPLOY_REGISTRY_SEL) {\n // deployRegistry requires whitelist credits — platform-level gate\n if (userWhitelist[sender] == 0) {\n emit UserOpRejected(sender, \"not whitelisted\");\n return (\"\", _packValidationData(true, 0, 0));\n }\n // credits consumed inside deployRegistry; flag as deployment to skip daily spend\n return (\n abi.encode(sender, maxCost, true),\n _packValidationData(false, 0, 0)\n );\n }\n\n if (innerSel == MINT_DOCUMENT_SEL) {\n // mintDocument: registry enforces MINTER_ROLE — no extra whitelist needed\n return (\n abi.encode(sender, maxCost, false),\n _packValidationData(false, 0, 0)\n );\n }\n\n emit UserOpRejected(sender, \"unauthorized paymaster call\");\n return (\"\", _packValidationData(true, 0, 0));\n }\n\n emit UserOpRejected(sender, \"unauthorized target\");\n return (\"\", _packValidationData(true, 0, 0));\n }\n\n function _postOp(\n PostOpMode mode,\n bytes calldata context,\n uint256 actualGasCost,\n uint256 /*actualUserOpFeePerGas*/\n ) internal override {\n if (mode == PostOpMode.postOpReverted) return;\n\n (address sender, , bool isDeployment) = abi.decode(\n context,\n (address, uint256, bool)\n );\n\n // Deployment ops are credit-gated; skip daily spend tracking for them\n if (!isDeployment) {\n if (block.timestamp > lastReset[sender] + 1 days) {\n dailySpend[sender] = 0;\n lastReset[sender] = block.timestamp;\n }\n dailySpend[sender] += actualGasCost;\n }\n\n emit UserOpSponsored(sender, actualGasCost);\n }\n\n // v0.8 contracts on Etherspot EntryPoint — skip interface mismatch check\n function _validateEntryPointInterface(IEntryPoint) internal pure override {}\n\n receive() external payable {\n deposit();\n }\n\n function getUserDailySpend(\n address user\n ) external view returns (uint256 spent, uint256 limit, uint256 resetsAt) {\n spent = dailySpend[user];\n limit = dailyLimit;\n resetsAt = lastReset[user] + 1 days;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport \"@account-abstraction/contracts/core/BasePaymaster.sol\";\nimport \"@account-abstraction/contracts/core/Helpers.sol\";\n\ninterface ITDocDeployer {\n function deploy(\n address implementation,\n bytes memory params\n ) external returns (address);\n}\n\ninterface ITradeTrustToken {\n function mint(\n address beneficiary,\n address holder,\n uint256 tokenId,\n bytes calldata remark\n ) external returns (address);\n}\n\ninterface IAccessControl {\n function grantRole(bytes32 role, address account) external;\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n/**\n * PlatformPaymaster — validates by inspecting the target contract in callData.\n *\n * Validation strategy (no third-party storage reads → bundler compliant):\n * 1. Decode userOp.callData → must be execute(address to, uint256, bytes)\n * 2. Check `to` is in authorizedRegistries (paymaster's own storage)\n * 3. Check daily spend (paymaster's own storage — always allowed)\n *\n * Access control is enforced by the Storage contract itself:\n * require(msg.sender == beneficiary || msg.sender == holder)\n * so non-beneficiary/holder callers are rejected at execution time.\n * If the call reverts, _postOp skips the spend update.\n */\ncontract PlatformPaymaster is BasePaymaster {\n bytes4 private constant EXECUTE_SEL =\n bytes4(keccak256(\"execute(address,uint256,bytes)\"));\n bytes4 private constant DEPLOY_REGISTRY_SEL =\n bytes4(keccak256(\"deployRegistry(address,string,string)\"));\n bytes4 private constant MINT_DOCUMENT_SEL =\n bytes4(keccak256(\"mintDocument(address,address,address,uint256,bytes)\"));\n\n bytes32 private constant DEFAULT_ADMIN_ROLE = bytes32(0);\n\n ITDocDeployer public tdocDeployer;\n\n // Paymaster's own storage — always allowed under ERC-7562\n mapping(address => bool) public authorizedRegistries;\n mapping(address => bool) public authorizedTitleEscrows;\n // remaining deployment credits per user; max 3 per user\n mapping(address => uint256) public userWhitelist;\n\n // Daily spend tracking — paymaster's own storage, always allowed\n mapping(address => uint256) public dailySpend;\n mapping(address => uint256) public lastReset;\n uint256 public dailyLimit;\n\n event RegistryAdded(address indexed registry);\n event RegistryRemoved(address indexed registry);\n event TitleEscrowLinked(address indexed titleEscrow, address indexed registry);\n event UserWhitelistUpdated(address indexed user, uint256 credits);\n event RegistryDeployed(\n address indexed user,\n address indexed deployed,\n uint256 creditsLeft\n );\n event UserOpSponsored(address indexed user, uint256 gasCost);\n event UserOpRejected(address indexed user, string reason);\n event DailyLimitUpdated(uint256 newLimit);\n\n constructor(\n IEntryPoint _entryPoint,\n address _owner,\n uint256 _dailyLimit\n ) BasePaymaster(_entryPoint) {\n _transferOwnership(_owner);\n dailyLimit = _dailyLimit;\n }\n\n function setTdocDeployer(address _tdocDeployer) external onlyOwner {\n require(_tdocDeployer != address(0), \"Zero address\");\n tdocDeployer = ITDocDeployer(_tdocDeployer);\n }\n\n // Grant/update deployment credits for a user; credits cannot exceed 3\n function setUserWhitelist(\n address user,\n uint256 credits\n ) external onlyOwner {\n require(user != address(0), \"Zero address\");\n require(credits <= 3, \"Exceeds max credits of 3\");\n userWhitelist[user] = credits;\n emit UserWhitelistUpdated(user, credits);\n }\n\n // Deploys a TDoc clone on behalf of a whitelisted user; consumes one credit.\n // Role setup (atomic, no follow-up txs needed):\n // - msg.sender (EOA) gets DEFAULT_ADMIN_ROLE\n // - paymaster gets MINTER_ROLE + RESTORER_ROLE + ACCEPTER_ROLE\n function deployRegistry(\n address implementation,\n string memory name,\n string memory symbol\n ) external returns (address deployed) {\n require(address(tdocDeployer) != address(0), \"TdocDeployer not set\");\n uint256 credits = userWhitelist[msg.sender];\n require(credits > 0, \"No deployment credits\");\n\n userWhitelist[msg.sender] = credits - 1;\n\n // Paymaster is temporary admin so it can configure roles after deploy\n bytes memory params = abi.encode(name, symbol, address(this));\n deployed = tdocDeployer.deploy(implementation, params);\n\n // Hand admin to the calling EOA\n IAccessControl(deployed).grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n\n // Paymaster keeps only the operational roles it needs\n // (MINTER_ROLE, RESTORER_ROLE, ACCEPTER_ROLE were granted to address(this) via initialize)\n\n // Relinquish admin — EOA is now sole admin\n IAccessControl(deployed).renounceRole(DEFAULT_ADMIN_ROLE, address(this));\n\n authorizedRegistries[deployed] = true;\n emit RegistryAdded(deployed);\n emit RegistryDeployed(msg.sender, deployed, credits - 1);\n }\n\n // Mints a TradeTrust document, captures the TitleEscrow, and auto-authorizes it.\n // Paymaster must hold MINTER_ROLE on the registry.\n // Callable gaslessly by userWhitelist users (credits not consumed — only deployRegistry uses credits).\n function mintDocument(\n address registry,\n address beneficiary,\n address holder,\n uint256 tokenId,\n bytes calldata remark\n ) external returns (address titleEscrow) {\n require(authorizedRegistries[registry], \"registry not authorized\");\n require(userWhitelist[msg.sender] > 0, \"not whitelisted\");\n\n titleEscrow = ITradeTrustToken(registry).mint(beneficiary, holder, tokenId, remark);\n\n authorizedTitleEscrows[titleEscrow] = true;\n emit TitleEscrowLinked(titleEscrow, registry);\n }\n\n function addRegistry(address registry) external onlyOwner {\n require(registry != address(0), \"Zero address\");\n authorizedRegistries[registry] = true;\n emit RegistryAdded(registry);\n }\n\n function removeRegistry(address registry) external onlyOwner {\n authorizedRegistries[registry] = false;\n emit RegistryRemoved(registry);\n }\n\n function setDailyLimit(uint256 _dailyLimit) external onlyOwner {\n dailyLimit = _dailyLimit;\n emit DailyLimitUpdated(_dailyLimit);\n }\n\n function _validatePaymasterUserOp(\n PackedUserOperation calldata userOp,\n bytes32, // userOpHash — not needed\n uint256 maxCost\n ) internal override returns (bytes memory context, uint256 validationData) {\n address sender = userOp.sender;\n\n // 1. callData must be long enough for selector + one address arg\n if (userOp.callData.length < 36) {\n emit UserOpRejected(sender, \"callData too short\");\n return (\"\", _packValidationData(true, 0, 0));\n }\n\n // 2. Must call execute(address,uint256,bytes)\n bytes4 sel = bytes4(userOp.callData[:4]);\n if (sel != EXECUTE_SEL) {\n emit UserOpRejected(sender, \"wrong selector\");\n return (\"\", _packValidationData(true, 0, 0));\n }\n\n // 3. Decode target and inner calldata\n (address target, , bytes memory innerData) = abi.decode(\n userOp.callData[4:],\n (address, uint256, bytes)\n );\n\n // Path A — calling an authorized registry or title escrow (regular sponsored op)\n if (authorizedRegistries[target] || authorizedTitleEscrows[target]) {\n if (dailyLimit > 0 && dailySpend[sender] + maxCost > dailyLimit) {\n emit UserOpRejected(sender, \"daily limit exceeded\");\n return (\"\", _packValidationData(true, 0, 0));\n }\n return (abi.encode(sender, maxCost, false), _packValidationData(false, 0, 0));\n }\n\n // Path B — gasless paymaster call (deployRegistry or mintDocument)\n // Double-spend safe: EntryPoint sequential nonces allow only one\n // pending UserOp per sender in the mempool at a time.\n if (target == address(this)) {\n if (userWhitelist[sender] == 0) {\n emit UserOpRejected(sender, \"not whitelisted\");\n return (\"\", _packValidationData(true, 0, 0));\n }\n bytes4 innerSel;\n assembly { innerSel := mload(add(innerData, 32)) }\n\n if (innerSel == DEPLOY_REGISTRY_SEL) {\n // credits consumed inside deployRegistry; flag as deployment to skip daily spend\n return (abi.encode(sender, maxCost, true), _packValidationData(false, 0, 0));\n }\n if (innerSel == MINT_DOCUMENT_SEL) {\n // credits NOT consumed; track daily spend normally\n return (abi.encode(sender, maxCost, false), _packValidationData(false, 0, 0));\n }\n\n emit UserOpRejected(sender, \"unauthorized paymaster call\");\n return (\"\", _packValidationData(true, 0, 0));\n }\n\n emit UserOpRejected(sender, \"unauthorized target\");\n return (\"\", _packValidationData(true, 0, 0));\n }\n\n function _postOp(\n PostOpMode mode,\n bytes calldata context,\n uint256 actualGasCost,\n uint256 /*actualUserOpFeePerGas*/\n ) internal override {\n if (mode == PostOpMode.postOpReverted) return;\n\n (address sender, , bool isDeployment) = abi.decode(context, (address, uint256, bool));\n\n // Deployment ops are credit-gated; skip daily spend tracking for them\n if (!isDeployment) {\n if (block.timestamp > lastReset[sender] + 1 days) {\n dailySpend[sender] = 0;\n lastReset[sender] = block.timestamp;\n }\n dailySpend[sender] += actualGasCost;\n }\n\n emit UserOpSponsored(sender, actualGasCost);\n }\n\n // v0.8 contracts on Etherspot EntryPoint — skip interface mismatch check\n function _validateEntryPointInterface(IEntryPoint) internal pure override {}\n\n receive() external payable {\n deposit();\n }\n\n function getUserDailySpend(\n address user\n ) external view returns (uint256 spent, uint256 limit, uint256 resetsAt) {\n spent = dailySpend[user];\n limit = dailyLimit;\n resetsAt = lastReset[user] + 1 days;\n }\n}\n" + }, + "contracts/Storage.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.28;\n\ncontract Storage {\n struct Item {\n uint id;\n string data;\n uint256 timestamp;\n bool exists;\n }\n\n address public beneficiary;\n address public holder;\n\n mapping(uint => Item) private items;\n uint private itemCount = 0;\n\n event ItemCreated(uint indexed id, string data, uint256 timestamp);\n event ItemUpdated(uint indexed id, string data, uint256 timestamp);\n event ItemDeleted(uint indexed id);\n event ItemRead(uint indexed id, string data, uint256 timestamp);\n\n constructor(address _beneficiary, address _holder) {\n beneficiary = _beneficiary;\n holder = _holder;\n }\n\n // CREATE\n function create(string memory _data) public returns (uint) {\n require(\n msg.sender == beneficiary || msg.sender == holder,\n \"Storage: only beneficiary or holder can create items\"\n );\n require(bytes(_data).length > 0, \"Storage: data cannot be empty\");\n\n itemCount++;\n items[itemCount] = Item({\n id: itemCount,\n data: _data,\n timestamp: block.timestamp,\n exists: true\n });\n\n emit ItemCreated(itemCount, _data, block.timestamp);\n return itemCount;\n }\n\n // READ\n function read(uint _id) public returns (string memory) {\n require(\n msg.sender == beneficiary || msg.sender == holder,\n \"Storage: only beneficiary or holder can create items\"\n );\n require(_id > 0 && _id <= itemCount, \"Storage: item does not exist\");\n require(items[_id].exists, \"Storage: item has been deleted\");\n\n Item memory item = items[_id];\n emit ItemRead(_id, item.data, item.timestamp);\n return item.data;\n }\n\n // UPDATE\n function update(uint _id, string memory _newData) public {\n require(\n msg.sender == beneficiary || msg.sender == holder,\n \"Storage: only beneficiary or holder can create items\"\n );\n require(_id > 0 && _id <= itemCount, \"Storage: item does not exist\");\n require(items[_id].exists, \"Storage: item has been deleted\");\n require(bytes(_newData).length > 0, \"Storage: data cannot be empty\");\n\n items[_id].data = _newData;\n items[_id].timestamp = block.timestamp;\n\n emit ItemUpdated(_id, _newData, block.timestamp);\n }\n\n // DELETE\n function remove(uint _id) public {\n require(\n msg.sender == beneficiary || msg.sender == holder,\n \"Storage: only beneficiary or holder can create items\"\n );\n require(_id > 0 && _id <= itemCount, \"Storage: item does not exist\");\n require(items[_id].exists, \"Storage: item already deleted\");\n\n items[_id].exists = false;\n emit ItemDeleted(_id);\n }\n\n // Helper function to check if item exists\n function exists(uint _id) public view returns (bool) {\n return _id > 0 && _id <= itemCount && items[_id].exists;\n }\n\n // Get total item count\n function getItemCount() public view returns (uint) {\n return itemCount;\n }\n}\n" + }, + "contracts/TestEntryPoint.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\n// Imported here so Hardhat compiles the EntryPoint and makes it available\n// as a deployable artifact in tests. Not used in production.\nimport \"@account-abstraction/contracts/core/EntryPoint.sol\";\n" } }, "settings": {