Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Method | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|---|
0x61010080 | 22422760 | 153 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
UniversalGaslessDelegate
Compiler Version
v0.8.27+commit.40a35a09
Optimization Enabled:
Yes with 10000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-FileCopyrightText: Copyright (C) 2025 Fireblocks <[email protected]> pragma solidity 0.8.27; import { IERC1271 } from "@openzeppelin/contracts/interfaces/IERC1271.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { ERC7579Utils, Execution, Mode, CallType, ExecType, ModeSelector } from "@openzeppelin/contracts/account/utils/draft-ERC7579Utils.sol"; import { IERC7821 } from "./interface/IERC7821.sol"; import { TokenReceiver } from "./mixins/TokenReceiver.sol"; import { TypedAuthorization } from "./mixins/TypedAuthorization.sol"; import { NonceBitmap } from "./mixins/NonceBitmap.sol"; import { NonceStorage } from "./library/NonceStorageStruct.sol"; import { LibErrors } from "./library/LibErrors.sol"; import { IKillSwitch } from "./interface/IKillSwitch.sol"; /** * @title UniversalGaslessDelegate * @notice An EIP-7702 compatible delegate contract for enabling gasless transactions through delegation. This * contract implements a pattern where logic can execute on behalf of users who have signed authorized payload. * * @dev Implements flexible standards such as EIP-7821 to enhance the EOA experience with contract functionality. It * allows third parties to submit transactions for execution on behalf of users (i.e. gasless operations), as * long as users have provided the necessary authorization. * * Core Features: * - Leverages on EIP-7702 for delegate-based transaction execution * - Supports EIP-7579/EIP-7821 execution modes for single and batch transactions (see {supportsExecutionMode}) * - Integrates EIP-712 typed data signing for structured transaction authorization * - Implements unordered nonces for authorization replay protection * - Provides ERC-1271 signature validation compatibility for existing protocols * - Includes token receiver capabilities (ERC-721 and ERC-1155) * - Emergency pause functionality via KillSwitch contract * * @custom:security-contact [email protected] */ contract UniversalGaslessDelegate is IERC1271, IERC7821, NonceBitmap, TokenReceiver, TypedAuthorization { // ============================================================= // CONSTANTS / IMMUTABLE // ============================================================= /** * @notice The address of the implementation contract * @dev This is used to detect direct calls to the implementation contract. It is set to the address of the * implementation contract at deployment time. */ address private immutable __implementation = address(this); // solhint-disable-line immutable-vars-naming /** * @dev Storage location for the nonce bitmap. Derived from performing the following operation: * keccak256(abi.encode(uint256(keccak256("fireblocks.global.security.nonces")) - 1)) & ~bytes32(uint256(0xff)) */ bytes32 private constant _NONCE_STORAGE_LOCATION = 0xb035242b6a1b64fd1e2d869c03a3cc0e80fe7f55db29c2560bab38e489fab700; /** * @notice Reference to the KillSwitch contract that can pause the Universal Gasless Delegate functionality * @dev This immutable reference points to a contract implementing the IKillSwitch interface * that can pause operations in case of emergencies. The contract is checked for validity * and unpaused status during construction. */ IKillSwitch private immutable _KILLSWITCH_CONTRACT; /** * @notice Enumeration of the different execution modes supported by the contract * @dev These values correspond to the execution modes defined in {supportsExecutionMode}, with INVALID as the * default 0 state * * - INVALID: Represents an invalid/unsupported execution mode (0) * - SINGLE_CALL_OPDATA_AUTH: Single call with authorization via opData (1) * - BATCH_CALL_OPDATA_AUTH: Batch call with authorization via optional opData (2) * - BATCH_CALL: Batch call with self-call authorization (3) */ enum ExecutionModeId { // 0: Invalid mode INVALID, // 1: CallType = Single (0x00), ExecType = Revert (0x00), ModeSelector = Auth via opData (0x78210001) SINGLE_CALL_OPDATA_AUTH, // 2: CallType = Batch (0x01), ExecType = Revert (0x00), ModeSelector = Auth via opData (0x78210001) BATCH_CALL_OPDATA_AUTH, // 3: CallType = Batch (0x01), ExecType = Revert (0x00), ModeSelector = Default (0x00000000) BATCH_CALL } // ============================================================= // STATE STORAGE // // This contract follows ERC-7201 for Namespaced storage // Global storage: // - See {_NONCE_STORAGE_LOCATION} for NonceStorage // ============================================================= // ============================================================= // EVENTS // ============================================================= // ============================================================= // MODIFIERS // ============================================================= /** * @notice This modifier is used to ensure that the function is called through a proxy, which in the EIP-7702 * context means that the function is called on a Delegated EOA. * @dev Prevents direct calls to the implementation. */ modifier onlyProxy() { if (address(this) == __implementation) revert LibErrors.UnauthorizedCallContext(); _; } /** * @notice Restricts function access to calls originating solely from the contract itself * @dev Reverts with {LibErrors.UnauthorizedCaller} if msg.sender is not the Delegated EOA itself, in either the * EOA or contract context. */ modifier onlySelf() { if (msg.sender != address(this)) revert LibErrors.UnauthorizedCaller(); _; } /** * @notice This modifier ensures that the contract is not paused via the KillSwitch * @dev Reverts if the KillSwitch contract indicates the system is paused * This modifier is used to protect state-modifying functions from being executed during * emergency situations. */ modifier whenNotPaused() { if (_KILLSWITCH_CONTRACT.paused()) revert LibErrors.EnforcedPause(); _; } // ============================================================= // FUNCTIONS // ============================================================= /** * @notice Initializes the 7702 delegate implementation contract * * @dev Calling Conditions: * * - `killswitchContract` must not be the zero address * - `killswitchContract` must implement {IKillSwitch} * - `killswitchContract` must not be in paused state * * Reverts with: * - no error data (i.e. standard `revert()`) if the contract does not return a bool value on the * static-call to `paused()` * - `InvalidImplementation()` if the contract is paused * @param killswitchContract Address of the killswitch contract */ constructor(address killswitchContract) TypedAuthorization() { _KILLSWITCH_CONTRACT = IKillSwitch(killswitchContract); // check if it is a valid IKillSwitch contract that is not paused require(!_KILLSWITCH_CONTRACT.paused(), LibErrors.InvalidImplementation()); } // ==================== EXTERNAL AND PUBLIC ==================== /** * @notice Allows direct ETH transfers to the contract * @dev Executed when the contract receives a plain ETH transfer (empty calldata) * * Calling Conditions: * - The function should be called in the context of the Delegated EOA. Calling it directly on the implementation * address will revert due to the `onlyProxy` check. */ receive() external payable onlyProxy { } /** * @notice Handles non-matching function calls with ETH value * @dev Executed when the contract receives a call with non-empty calldata that doesn't match any function. * Ensures backward compatibility with EOA-like behavior for receiving transactions with arbitrary calldata, * like strings on a "value with memo" pattern. * * Calling Conditions: * - The function should be called in the context of the Delegated EOA. Calling it directly on the implementation * address will revert due to the `onlyProxy` check. * * NOTE: Using payable fallback functions for receiving Ether is not recommended, since when calldata is present, * the fallback is invoked and would not fail for interface confusions on the part of the sender. This fallback * exists primarily to ensure backward compatibility with standard EOA behavior. */ fallback() external payable onlyProxy { } /** * @notice Executes one or more calls on behalf of this Delegated EOA, supporting both single and batch operations * with an optional authorization mechanism. The caller can be either the Delegated EOA itself or another account * provided that the latter has a valid signature for the execution(s) to be made. * * @dev Processes execution requests according to the EIP-7579 and EIP-7821 specification, which define the mode * format and execution data structure. This function supports three different execution modes as detailed in * {supportsExecutionMode}. * * The `executionData` parameter follows EIP-7821 encoding rules: * - For modes with opData for authorization (SINGLE_CALL_OPDATA_AUTH and BATCH_CALL_OPDATA_AUTH) the following * encoding is expected `abi.encode(sobExecutionData, opData)`, where: * - in SINGLE_CALL_OPDATA_AUTH, `sobExecutionData` is abi.encodePacked(target, value, callData) * - in BATCH_CALL_OPDATA_AUTH, `sobExecutionData` is abi.encode(calls) * - `opData` is abi.encodePacked(nonce, deadline, signature) * - For self-call mode (BATCH_CALL): `abi.encode(calls)` with no optional `opData` * * Authorization flow: * * Note that while for mode BATCH_CALL_OPDATA_AUTH, opData is optional (fallback to `msg.sender` verification), * for mode SINGLE_CALL_OPDATA_AUTH, opData is required (no fallback to `msg.sender`). For a single call of this * type, the EOA should be making the call to target directly and not through the delegate contract. * * 1. For modes with opData authorization (SINGLE_CALL_OPDATA_AUTH and BATCH_CALL_OPDATA_AUTH): * - Calculate authorization digest using EIP-712 typed data signing * - Validate that the nonce is not already used * - Verify the signature has not expired (current block timestamp <= deadline) * - Verify the caller matches the relayer in the signed authorization * - Verify signature matches the Delegated EOA's * 2. For self-call mode (BATCH_CALL only): * - Verify caller is the delegated EOA itself (`msg.sender == address(this)`) * * Note: This implementation does NOT perform the target replacement gas optimization listed in EIP-7821. * Explicitly, {_call} will NOT replace `address(0)` with `address(this)` as the `target` parameter. * * Note: The ERC7579Utils.decodeBatch function performs validation and will throw * {ERC7579DecodingError} if the input is not properly formatted. * * Calling Conditions: * - The function should be called in the context of the Delegated EOA. Calling it directly on the implementation * address will revert. (checked by `onlyProxy`) * - The implementation contract should not be paused. (checked by `whenNotPaused`) * - If the target of the execution is the Delegated EOA itself, it can only call the `invalidateNonce` function. * * @param mode The execution mode that defines how the execution data should be processed * @param executionData The encoded execution data and optional authorization data (opData) */ function execute(bytes32 mode, bytes calldata executionData) external payable whenNotPaused onlyProxy { // Decode the execution data according to the mode ExecutionModeId modeId = _executionModeId(mode); // Revert if mode is not supported if (modeId == ExecutionModeId.INVALID) _determineExecutionModeRevertCause(mode); bytes calldata sobExecutionData; bytes calldata opData; (sobExecutionData, opData) = _extractExecAndOpData(executionData); // Check if optional opData is present. If not, we rely on the caller being the Delegated EOA itself for auth if (opData.length != 0) { // Decode opData to extract nonce, deadline and signature (uint256 nonce, uint256 deadline, bytes calldata signature) = _decodeOpData(opData); // Check if signature has expired require(block.timestamp <= deadline, LibErrors.ExpiredSignature(deadline)); // irrespective of single or batch, the nonce is always used on modes with opData auth _useUnorderedNonce(nonce); if (modeId == ExecutionModeId.SINGLE_CALL_OPDATA_AUTH) { // Perform authentication using opData and execute single call (address target, uint256 value, bytes calldata callData) = ERC7579Utils.decodeSingle(sobExecutionData); // create AuthorizedExecutions EIP712 hash bytes32 sDigest = _hashTypedSingleExecutionAuthorization(mode, target, value, callData, nonce, deadline, msg.sender); //validate signature require(address(this) == ECDSA.recover(sDigest, signature), LibErrors.UnauthorizedExecution()); // Execute the call _call(target, value, callData); return; } if (modeId == ExecutionModeId.BATCH_CALL_OPDATA_AUTH) { // Perform authentication using opData and execute batch calls Execution[] calldata executionBatch = ERC7579Utils.decodeBatch(sobExecutionData); // create AuthorizedExecutions EIP712 hash bytes32 bDigest = _hashTypedBatchExecutionAuthorization(mode, executionBatch, nonce, deadline, msg.sender); //validate signature require(address(this) == ECDSA.recover(bDigest, signature), LibErrors.UnauthorizedExecution()); // Execute the batch calls _execBatch(executionBatch); return; } // BATCH_CALL mode does not support an opData component if (modeId == ExecutionModeId.BATCH_CALL) revert LibErrors.UnauthorizedExecution(); } else { require(msg.sender == address(this), LibErrors.UnauthorizedCaller()); // For mode SINGLE_CALL_OPDATA_AUTH, opData is required for authorization if (modeId == ExecutionModeId.SINGLE_CALL_OPDATA_AUTH) revert LibErrors.UnauthorizedExecution(); // Evaluate modes BATCH_CALL_OPDATA_AUTH and BATCH_CALL under no opData, self-call authorization Execution[] calldata executionBatch = ERC7579Utils.decodeBatch(executionData); // Execute the batch calls _execBatch(executionBatch); return; } } /** * @notice This function marks a nonce as used * @dev This function is used to invalidate a nonce * * Calling Conditions: * - The caller must be the Delegated EOA or the contract itself (checked by `onlySelf`) * - If the contract context is paused, the call must come from the Delegated EOA directly * * Reverts with {LibErrors.InvalidNonce} if the nonce has already been used. * * @param nonce The nonce to invalidate */ function invalidateNonce(uint256 nonce) external override onlyProxy onlySelf { _useUnorderedNonce(nonce); } /** * @notice Returns the fields and values that describe the domain separator to be used as part of EIP-712 * signatures verified by this contract. * * @dev This function overrides {TypedAuthorization.eip712Domain()} to ensure it can only be called in the context * of a delegated EOA (via proxy). Calling it directly on the implementation address will revert with * {LibErrors.UnauthorizedCallContext}. */ function eip712Domain() public view virtual override onlyProxy returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { return super.eip712Domain(); } /** * @inheritdoc NonceBitmap */ function getNonceBitmap(uint248 wordPos) public view override onlyProxy returns (uint256 bitmap) { return super.getNonceBitmap(wordPos); } /** * @inheritdoc NonceBitmap */ function isNonceUsed(uint256 nonce) public view override onlyProxy returns (bool isUsed) { return super.isNonceUsed(nonce); } /** * @notice This function provides a standard method for external contracts to validate a signature for a given * hash, ensuring that such signatures have been created by the Delegated EOA. * * It also provides legacy (pre EIP-7702) compatibility with the ERC-1271 standard for signature validation, where * protocols might choose to validate signatures using this function, if they find in their logic that it is the * way to do it where the account has code. * * @dev Validates if the provided signature is valid for the given data hash and attributable to the Delegated EOA. * This function is provided for compliance with the ERC-1271 standard for signature validation. * * Calling Conditions: * * - The function should be called in the context of the Delegated EOA. Calling it directly on the implementation * address will revert. * * @param _hash Hash of the data to be signed * @param _signature Signature byte array associated with the hash * @return magicValue The function selector if signature is valid, or 0xffffffff if invalid */ function isValidSignature( bytes32 _hash, bytes calldata _signature ) external view onlyProxy returns (bytes4 magicValue) { if (_isValidRawSignature(_hash, _signature)) { return IERC1271.isValidSignature.selector; } else { return 0xffffffff; } } /** * @notice Returns whether the delegate contract is currently paused * @dev This function checks the pause state of the KillSwitch contract. Unlike most functions, * it can be called both on the implementation contract and on delegated EOAs, as it should convey the same * meaning. It signals if delegate implementation is safe to use. * * @return isPausedState True if the contract is paused via the KillSwitch, false otherwise */ function isPaused() external view returns (bool isPausedState) { return _KILLSWITCH_CONTRACT.paused(); } /** * @notice This function is provided for frontends to detect support. It checks if the contract supports * a specific execution mode. * * @dev Determines whether the contract supports the specified execution mode. Supported execution modes are * detailed in the table below: * * ``` * +------------------+----------+----------+------------+-------------------+-------------+ * | Mode ID | CallType | ExecType | Unused | ModeSelector | ModePayload | * | | (1 byte) | (1 byte) | (4 bytes) | (4 bytes) | (22 bytes) | * +------------------+----------+----------+------------+-------------------+-------------+ * | SINGLE_CALL_ | 0x00 | 0x00 | 0x00000000 | 0x78210001 | ANY | * | OPDATA_AUTH (1) | (Single) | (Revert) | (Empty) | (Auth via opData) | | * +------------------+----------+----------+------------+-------------------+-------------+ * | BATCH_CALL_ | 0x01 | 0x00 | 0x00000000 | 0x78210001 | ANY | * | OPDATA_AUTH (2) | (Batch) | (Revert) | (Empty) | (Auth via opData) | | * +------------------+----------+----------+------------+-------------------+-------------+ * | BATCH_CALL | 0x01 | 0x00 | 0x00000000 | 0x00000000 | ANY | * | (3) | (Batch) | (Revert) | (Empty) | (Default) | | * +------------------+----------+----------+------------+-------------------+-------------+ * ``` * * @param mode The fully-qualified execution mode to check * @return isSupported True if the mode is supported, false otherwise */ function supportsExecutionMode(bytes32 mode) external pure returns (bool isSupported) { return _executionModeId(mode) != ExecutionModeId.INVALID; } /** * @notice This function can be queried to check if the contract implements a specific interface * @dev Interface detection as per ERC-165 standard * * Calling Conditions: * * - The function should be called in the context of the Delegated EOA. Calling it directly on the implementation * address will revert. * * @param interfaceId The interface identifier to check * @return isSupported True when `interfaceId` is either: * - the {IERC7821} interface id * - the {IERC1271} interface id * - the {IERC721Receiver} interface id (checked in TokenReceiver) * - the {IERC1155Receiver} interface id (checked in ERC1155Holder) * - the {IERC165} interface id (checked in ERC1155Holder -> ERC165) */ function supportsInterface(bytes4 interfaceId) public view override onlyProxy returns (bool isSupported) { return interfaceId == type(IERC7821).interfaceId || interfaceId == type(IERC1271).interfaceId || super.supportsInterface(interfaceId); } // ========================= INTERNAL ========================== /** * @notice This function calls the target with specified value and data. It is multipurpose and can be used for * both invoking a function on target contract or for sending ETH to non-contract addresses. * @dev Performs a low-level call to the target contract and verifies the result. * * Note: This function prevents reentrancy when the target is the Delegated EOA. Following a whitelist pattern, * the only function selector allowed in this situation is the `invalidateNonce` function. If any other function, * for example `execute`, is called, it will revert with a `ReentrantCall` error. * * Calling Conditions: * * - The call to perform does not constitute a reentrant call to the execute function. * * @param target The address of the contract to call * @param value The amount of ETH to send with the call * @param data The calldata to send to the target */ function _call(address target, uint256 value, bytes calldata data) internal { // Reject any calls to self that are not the invalidateNonce function if (target == address(this) && data.length >= 4 && bytes4(data[:4]) != this.invalidateNonce.selector) { revert LibErrors.ReentrantCall(); } (bool success, bytes memory returndata) = target.call{ value: value }(data); Address.verifyCallResult(success, returndata); } /** * @notice Internal function that executes a batch of calls sequentially * @dev Processes an array of Execution structs, calling each target with the specified value and calldata. * This function ensures each call is processed in sequence and bubbles up any errors from failed calls. * * Security considerations: * - All calls are made in the context of the Delegated EOA (address(this)) * - This is an internal function without authorization checks * * @param executionBatch An array of Execution structs containing target addresses, values, and calldata */ function _execBatch(Execution[] calldata executionBatch) internal { for (uint256 i = 0; i < executionBatch.length; ++i) { _call(executionBatch[i].target, executionBatch[i].value, executionBatch[i].callData); } } /** * @notice Identifies the type of execution mode * @dev Analyzes the execution mode and returns the {ExecutionModeId} identifier: * * - INVALID if the mode is not supported * - SINGLE_CALL_OPDATA_AUTH for CallType = Single (0x00), ExecType = Revert on failure (0x00), * Unused = EMPTY, ModeSelector = Authorization via **required** `opData` (0x78210001), ModePayload = ANY * - BATCH_CALL_OPDATA_AUTH for CallType = Batch (0x01), ExecType = Revert on failure (0x00), * Unused = EMPTY, ModeSelector = Authorization via optional `opData` (0x78210001), ModePayload = ANY * - BATCH_CALL for CallType = Batch (0x01), ExecType = Revert on failure (0x00), * Unused = EMPTY, ModeSelector = Default (0x00000000), ModePayload = ANY * * @param mode The execution mode to analyze * @return The enum value representing the execution mode type/identifier */ function _executionModeId(bytes32 mode) internal pure returns (ExecutionModeId) { // Check if the mode is supported. Only checks the first 10 bytes of the mode bytes10 execModeMinusPayload = bytes10(mode); if (execModeMinusPayload == bytes10(0x00000000000078210001)) { return ExecutionModeId.SINGLE_CALL_OPDATA_AUTH; } if (execModeMinusPayload == bytes10(0x01000000000078210001)) { return ExecutionModeId.BATCH_CALL_OPDATA_AUTH; } if (execModeMinusPayload == bytes10(0x01000000000000000000)) { return ExecutionModeId.BATCH_CALL; } return ExecutionModeId.INVALID; } /** * @notice Provides a custom error (if possible) to convey information when an execution mode is not supported * @dev Analyzes the components of an execution mode and reverts with a specific error message * based on which component is invalid. * * Reverts with: * - {ERC7579UnsupportedCallType} if CallType is neither Single (0x00) nor Batch (0x01) * - {ERC7579UnsupportedExecType} if ExecType is not Revert (0x00) * - {UnsupportedModeSelector} if ModeSelector is neither Auth (0x78210001) nor Default (0x00000000) * - {UnsupportedExecutionMode} for any other unsupported mode configuration * * @param mode The execution mode to analyze for the revert cause */ function _determineExecutionModeRevertCause(bytes32 mode) internal pure { // Extract the components from the mode (CallType callType, ExecType execType, ModeSelector modeSelector,) = ERC7579Utils.decodeMode(Mode.wrap(mode)); // Check for callType being 0x00 (Single) or 0x01 (Batch) if (!(callType == ERC7579Utils.CALLTYPE_SINGLE || callType == ERC7579Utils.CALLTYPE_BATCH)) { revert ERC7579Utils.ERC7579UnsupportedCallType(callType); } // Check for execType being 0x00 (Revert on failure) if (!(execType == ERC7579Utils.EXECTYPE_DEFAULT)) { revert ERC7579Utils.ERC7579UnsupportedExecType(execType); } // Check for modeSelector being 0x78210001 (Auth via opData) or 0x00000000 (Default) if (!(modeSelector == ModeSelector.wrap(0x78210001) || modeSelector == ModeSelector.wrap(0x00000000))) { revert LibErrors.UnsupportedModeSelector(ModeSelector.unwrap(modeSelector)); } // Revert with default error for other causes revert LibErrors.UnsupportedExecutionMode(); } /** * @notice Extracts single/batch execution data and optional opData from `executionData` * @dev Decodes executionData to separate the call(s) from the optional `opData` according to EIP-7821. * * Here, we perform low-level ABI-decoding of dynamic types with the intent of: * - gracefully handling structural errors that otherwise would result in a generic revert * - maintaining calldata references * * The function determines if opData is present by examining the offset values: * - If only one dynamic type is present, only `singleOrBatchExecutionData` will be relevant, as `opData` is * set to empty * - If two dynamic typed values are present, both execution data and opData are extracted * * Reverts: * - with {LibErrors.ExecutionDataExtractionError} if offsets are invalid * * @param executionData The encoded execution data passed to execute() * @return singleOrBatchExecutionData The extracted singleOrBatchExecutionData data * @return opData The extracted operation data (empty if not provided) */ function _extractExecAndOpData(bytes calldata executionData) internal pure returns (bytes calldata singleOrBatchExecutionData, bytes calldata opData) { // Read the primary offset in a local variable first uint256 cOffset; assembly { cOffset := calldataload(executionData.offset) } if (cOffset < 32) revert LibErrors.ExecutionDataExtractionError(); assembly { let cPos := add(executionData.offset, cOffset) singleOrBatchExecutionData.offset := add(cPos, 0x20) singleOrBatchExecutionData.length := calldataload(cPos) } // If the first offset is 64, we have a second item for opData if (cOffset >= 64) { uint256 oOffset; assembly { oOffset := calldataload(add(executionData.offset, 0x20)) } // Revert if the offset is invalid if (oOffset < 64 || oOffset >= executionData.length) revert LibErrors.ExecutionDataExtractionError(); assembly { let oPos := add(executionData.offset, oOffset) opData.offset := add(oPos, 0x20) opData.length := calldataload(oPos) } } else { assembly { opData.length := 0 } } } /** * @notice Decodes the `opData` parameter, extracting the nonce, deadline and signature components * @dev Parses the opData byte array to extract the nonce, deadline and ECDSA signature according to an expected * packed format. * * The opData is expected to be in ABI packed encoding format: * - 32 bytes for nonce * - 32 bytes for deadline * - 65 bytes for signature (r, s, v) * * Reverts with {LibErrors.OpDataDecodingError} if opData is not at least 129 bytes. * * @param opData The data containing nonce, deadline and signature * @return nonce The extracted nonce value used for replay protection * @return deadline The timestamp after which the signature is no longer valid * @return signature The extracted 65-byte ECDSA signature */ function _decodeOpData(bytes calldata opData) internal pure returns (uint256 nonce, uint256 deadline, bytes calldata signature) { // opData must contain a nonce, deadline and a signature, for a total of 129 bytes require(opData.length == 129, LibErrors.OpDataDecodingError()); // Extract nonce from the first 32 bytes nonce = uint256(bytes32(opData[:32])); // Extract deadline from the next 32 bytes deadline = uint256(bytes32(opData[32:64])); // Extract signature from the remaining bytes signature = opData[64:]; } /** * @notice Verifies if a signature is valid for a given hash in the context of the Delegated EOA, supporting any * ECDSA signature flow including EIP-712. * * @dev Internal implementation for signature validation, reusable to support ERC1271 compatibility and any ECDSA * signature verification requirements, including EIP-712 signatures. * * Note this function does not perform any nonce-validity checks. * * Signature Validity Conditions: * * - The signature does not derive the `address(0)`. * - The signature has invalid length. * - The signature has an S value that is in the lower half order * - The signature must derive `address(this)`. * * @param _hash The hash of the data that was signed * @param _signature A 65-byte ECDSA signature produced by the signer * @return isValid true if the signature is valid, false otherwise */ function _isValidRawSignature(bytes32 _hash, bytes calldata _signature) internal view returns (bool isValid) { (address recovered, ECDSA.RecoverError err,) = ECDSA.tryRecover(_hash, _signature); return address(this) == recovered && err == ECDSA.RecoverError.NoError; } /** * @notice This function is used to get the namespaced, structured nonce storage * @dev This function is used to get the nonce storage pointer * @custom:storage-location erc7201:fireblocks.global.security.nonces * @return $ The reference to the {NonceStorage} struct in storage */ function _nonceStorage() internal pure override returns (NonceStorage storage $) { assembly ("memory-safe") { $.slot := _NONCE_STORAGE_LOCATION } } /** * @notice Returns the address of the verifying contract to be used in the EIP712 domain separator * @dev The verifyingContract used is the address of the implementation contract, set during deployment, to prevent * replay attacks if an EOA re-delegates to a different implementation. * @return verifyingContract The address of the implementation contract */ function _verifyingContractAddress() internal view override returns (address verifyingContract) { // During the construction phase, the value of `__implementation` might be empty, which is not a valid // verifying contract. Therefore, we coalesce to the eventual implementation address. return __implementation == address(0) ? address(this) : __implementation; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1271.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. */ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed * @param signature Signature byte array associated with _data */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover( bytes32 hash, bytes memory signature ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly ("memory-safe") { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures] */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol) pragma solidity ^0.8.20; import {Errors} from "./Errors.sol"; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert Errors.InsufficientBalance(address(this).balance, amount); } (bool success, bytes memory returndata) = recipient.call{value: amount}(""); if (!success) { _revert(returndata); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {Errors.FailedCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case * of an unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {Errors.FailedCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly ("memory-safe") { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert Errors.FailedCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.2.0) (account/utils/draft-ERC7579Utils.sol) pragma solidity ^0.8.20; import {Execution} from "../../interfaces/draft-IERC7579.sol"; import {Packing} from "../../utils/Packing.sol"; import {Address} from "../../utils/Address.sol"; type Mode is bytes32; type CallType is bytes1; type ExecType is bytes1; type ModeSelector is bytes4; type ModePayload is bytes22; /** * @dev Library with common ERC-7579 utility functions. * * See https://eips.ethereum.org/EIPS/eip-7579[ERC-7579]. */ // slither-disable-next-line unused-state library ERC7579Utils { using Packing for *; /// @dev A single `call` execution. CallType internal constant CALLTYPE_SINGLE = CallType.wrap(0x00); /// @dev A batch of `call` executions. CallType internal constant CALLTYPE_BATCH = CallType.wrap(0x01); /// @dev A `delegatecall` execution. CallType internal constant CALLTYPE_DELEGATECALL = CallType.wrap(0xFF); /// @dev Default execution type that reverts on failure. ExecType internal constant EXECTYPE_DEFAULT = ExecType.wrap(0x00); /// @dev Execution type that does not revert on failure. ExecType internal constant EXECTYPE_TRY = ExecType.wrap(0x01); /** * @dev Emits when an {EXECTYPE_TRY} execution fails. * @param batchExecutionIndex The index of the failed call in the execution batch. * @param returndata The returned data from the failed call. */ event ERC7579TryExecuteFail(uint256 batchExecutionIndex, bytes returndata); /// @dev The provided {CallType} is not supported. error ERC7579UnsupportedCallType(CallType callType); /// @dev The provided {ExecType} is not supported. error ERC7579UnsupportedExecType(ExecType execType); /// @dev The provided module doesn't match the provided module type. error ERC7579MismatchedModuleTypeId(uint256 moduleTypeId, address module); /// @dev The module is not installed. error ERC7579UninstalledModule(uint256 moduleTypeId, address module); /// @dev The module is already installed. error ERC7579AlreadyInstalledModule(uint256 moduleTypeId, address module); /// @dev The module type is not supported. error ERC7579UnsupportedModuleType(uint256 moduleTypeId); /// @dev Input calldata not properly formatted and possibly malicious. error ERC7579DecodingError(); /// @dev Executes a single call. function execSingle( bytes calldata executionCalldata, ExecType execType ) internal returns (bytes[] memory returnData) { (address target, uint256 value, bytes calldata callData) = decodeSingle(executionCalldata); returnData = new bytes[](1); returnData[0] = _call(0, execType, target, value, callData); } /// @dev Executes a batch of calls. function execBatch( bytes calldata executionCalldata, ExecType execType ) internal returns (bytes[] memory returnData) { Execution[] calldata executionBatch = decodeBatch(executionCalldata); returnData = new bytes[](executionBatch.length); for (uint256 i = 0; i < executionBatch.length; ++i) { returnData[i] = _call( i, execType, executionBatch[i].target, executionBatch[i].value, executionBatch[i].callData ); } } /// @dev Executes a delegate call. function execDelegateCall( bytes calldata executionCalldata, ExecType execType ) internal returns (bytes[] memory returnData) { (address target, bytes calldata callData) = decodeDelegate(executionCalldata); returnData = new bytes[](1); returnData[0] = _delegatecall(0, execType, target, callData); } /// @dev Encodes the mode with the provided parameters. See {decodeMode}. function encodeMode( CallType callType, ExecType execType, ModeSelector selector, ModePayload payload ) internal pure returns (Mode mode) { return Mode.wrap( CallType .unwrap(callType) .pack_1_1(ExecType.unwrap(execType)) .pack_2_4(bytes4(0)) .pack_6_4(ModeSelector.unwrap(selector)) .pack_10_22(ModePayload.unwrap(payload)) ); } /// @dev Decodes the mode into its parameters. See {encodeMode}. function decodeMode( Mode mode ) internal pure returns (CallType callType, ExecType execType, ModeSelector selector, ModePayload payload) { return ( CallType.wrap(Packing.extract_32_1(Mode.unwrap(mode), 0)), ExecType.wrap(Packing.extract_32_1(Mode.unwrap(mode), 1)), ModeSelector.wrap(Packing.extract_32_4(Mode.unwrap(mode), 6)), ModePayload.wrap(Packing.extract_32_22(Mode.unwrap(mode), 10)) ); } /// @dev Encodes a single call execution. See {decodeSingle}. function encodeSingle( address target, uint256 value, bytes calldata callData ) internal pure returns (bytes memory executionCalldata) { return abi.encodePacked(target, value, callData); } /// @dev Decodes a single call execution. See {encodeSingle}. function decodeSingle( bytes calldata executionCalldata ) internal pure returns (address target, uint256 value, bytes calldata callData) { target = address(bytes20(executionCalldata[0:20])); value = uint256(bytes32(executionCalldata[20:52])); callData = executionCalldata[52:]; } /// @dev Encodes a delegate call execution. See {decodeDelegate}. function encodeDelegate( address target, bytes calldata callData ) internal pure returns (bytes memory executionCalldata) { return abi.encodePacked(target, callData); } /// @dev Decodes a delegate call execution. See {encodeDelegate}. function decodeDelegate( bytes calldata executionCalldata ) internal pure returns (address target, bytes calldata callData) { target = address(bytes20(executionCalldata[0:20])); callData = executionCalldata[20:]; } /// @dev Encodes a batch of executions. See {decodeBatch}. function encodeBatch(Execution[] memory executionBatch) internal pure returns (bytes memory executionCalldata) { return abi.encode(executionBatch); } /// @dev Decodes a batch of executions. See {encodeBatch}. /// /// NOTE: This function runs some checks and will throw a {ERC7579DecodingError} if the input is not properly formatted. function decodeBatch(bytes calldata executionCalldata) internal pure returns (Execution[] calldata executionBatch) { unchecked { uint256 bufferLength = executionCalldata.length; // Check executionCalldata is not empty. if (bufferLength < 32) revert ERC7579DecodingError(); // Get the offset of the array (pointer to the array length). uint256 arrayLengthOffset = uint256(bytes32(executionCalldata[0:32])); // The array length (at arrayLengthOffset) should be 32 bytes long. We check that this is within the // buffer bounds. Since we know bufferLength is at least 32, we can subtract with no overflow risk. if (arrayLengthOffset > bufferLength - 32) revert ERC7579DecodingError(); // Get the array length. arrayLengthOffset + 32 is bounded by bufferLength so it does not overflow. uint256 arrayLength = uint256(bytes32(executionCalldata[arrayLengthOffset:arrayLengthOffset + 32])); // Check that the buffer is long enough to store the array elements as "offset pointer": // - each element of the array is an "offset pointer" to the data. // - each "offset pointer" (to an array element) takes 32 bytes. // - validity of the calldata at that location is checked when the array element is accessed, so we only // need to check that the buffer is large enough to hold the pointers. // // Since we know bufferLength is at least arrayLengthOffset + 32, we can subtract with no overflow risk. // Solidity limits length of such arrays to 2**64-1, this guarantees `arrayLength * 32` does not overflow. if (arrayLength > type(uint64).max || bufferLength - arrayLengthOffset - 32 < arrayLength * 32) revert ERC7579DecodingError(); assembly ("memory-safe") { executionBatch.offset := add(add(executionCalldata.offset, arrayLengthOffset), 32) executionBatch.length := arrayLength } } } /// @dev Executes a `call` to the target with the provided {ExecType}. function _call( uint256 index, ExecType execType, address target, uint256 value, bytes calldata data ) private returns (bytes memory) { (bool success, bytes memory returndata) = target.call{value: value}(data); return _validateExecutionMode(index, execType, success, returndata); } /// @dev Executes a `delegatecall` to the target with the provided {ExecType}. function _delegatecall( uint256 index, ExecType execType, address target, bytes calldata data ) private returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return _validateExecutionMode(index, execType, success, returndata); } /// @dev Validates the execution mode and returns the returndata. function _validateExecutionMode( uint256 index, ExecType execType, bool success, bytes memory returndata ) private returns (bytes memory) { if (execType == ERC7579Utils.EXECTYPE_DEFAULT) { Address.verifyCallResult(success, returndata); } else if (execType == ERC7579Utils.EXECTYPE_TRY) { if (!success) emit ERC7579TryExecuteFail(index, returndata); } else { revert ERC7579UnsupportedExecType(execType); } return returndata; } } // Operators using {eqCallType as ==} for CallType global; using {eqExecType as ==} for ExecType global; using {eqModeSelector as ==} for ModeSelector global; using {eqModePayload as ==} for ModePayload global; /// @dev Compares two `CallType` values for equality. function eqCallType(CallType a, CallType b) pure returns (bool) { return CallType.unwrap(a) == CallType.unwrap(b); } /// @dev Compares two `ExecType` values for equality. function eqExecType(ExecType a, ExecType b) pure returns (bool) { return ExecType.unwrap(a) == ExecType.unwrap(b); } /// @dev Compares two `ModeSelector` values for equality. function eqModeSelector(ModeSelector a, ModeSelector b) pure returns (bool) { return ModeSelector.unwrap(a) == ModeSelector.unwrap(b); } /// @dev Compares two `ModePayload` values for equality. function eqModePayload(ModePayload a, ModePayload b) pure returns (bool) { return ModePayload.unwrap(a) == ModePayload.unwrap(b); }
// SPDX-License-Identifier: MIT // SPDX-FileCopyrightText: Copyright (c) 2016-2025 Zeppelin Group Ltd pragma solidity 0.8.27; /** * @dev Interface for minimal batch executor. * * @custom:source * https://github.com/OpenZeppelin/openzeppelin-community-contracts/blob/e19d51c/contracts/interfaces/IERC7821.sol */ interface IERC7821 { /** * @dev Executes the calls in `executionData`. * Reverts and bubbles up error if any call fails. * * `executionData` encoding: * - If `opData` is empty, `executionData` is simply `abi.encode(calls)`. * - Else, `executionData` is `abi.encode(calls, opData)`. * See: https://eips.ethereum.org/EIPS/eip-7579 * * Supported modes: * - `bytes32(0x01000000000000000000...)`: does not support optional `opData`. * - `bytes32(0x01000000000078210001...)`: supports optional `opData`. * * Authorization checks: * - If `opData` is empty, the implementation SHOULD require that * `msg.sender == address(this)`. * - If `opData` is not empty, the implementation SHOULD use the signature * encoded in `opData` to determine if the caller can perform the execution. * * `opData` may be used to store additional data for authentication, * paymaster data, gas limits, etc. */ function execute(bytes32 mode, bytes calldata executionData) external payable; /** * @dev This function is provided for frontends to detect support. * Only returns true for: * - `bytes32(0x01000000000000000000...)`: does not support optional `opData`. * - `bytes32(0x01000000000078210001...)`: supports optional `opData`. */ function supportsExecutionMode(bytes32 mode) external view returns (bool); }
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-FileCopyrightText: Copyright (C) 2025 Fireblocks <[email protected]> pragma solidity 0.8.27; import { IERC721Receiver } from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import { ERC1155Holder } from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; import { ERC721Holder } from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol"; /** * @title TokenReceiver * @notice This helper contract implements the necessary methods to successfully receive ERC1155 and ERC721 tokens. * It is used as a base contract for accounts that need to handle token transfers. * * @dev This contract implements: * - the {IERC1155Receiver} interface allowing it to receive ERC1155 tokens * - the {IERC721Receiver} interface allowing it to receive ERC721 tokens * - the EIP-165 standard for interface detection of the same and the two above interfaces * * @custom:security-contact [email protected] */ abstract contract TokenReceiver is ERC721Holder, ERC1155Holder { /** * @notice This function can be queried to check if the contract implements a specific interface * @dev Interface detection as per ERC-165 standard * * Returns true when `interfaceId` is either: * - the {IERC721Receiver} interface id * - the {IERC1155Receiver} interface id (checked in ERC1155Holder) * - the {IERC165} interface id (checked in ERC1155Holder -> ERC165) * * @param interfaceId The interface identifier to check * @return isSupported True if the contract supports `interfaceId` */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool isSupported) { return interfaceId == type(IERC721Receiver).interfaceId || super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-FileCopyrightText: Copyright (C) 2025 Fireblocks <[email protected]> pragma solidity 0.8.27; import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import { IERC5267 } from "@openzeppelin/contracts/interfaces/IERC5267.sol"; import { Execution } from "@openzeppelin/contracts/interfaces/draft-IERC7579.sol"; /** * @title Typed Structured Execution Authorization * @notice Implementation of EIP712 that provides structured hashing functions for typed data in the context of * meta-transactions. This contract computes the message digests that off-chain wallets must sign to * authorize executions through the EIP-7702 delegate contract, supporting batch operations out of the box. * * This contract is an implementation of EIP-712 with select elements being part of the EIP712Domain * * @dev https://eips.ethereum.org/EIPS/eip-712[EIP-712] is a standard for hashing and signing of typed structured data. * * This contract implements the EIP-712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest ({_hashTypedDataV4}) that is then signed * via ECDSA. This contract also supports ERC-5267, but such proposal does not have a prerequisite on ERC-165 which * means that there is no need to signal it via a `supportsInterface` function. * * The implementation of the domain separator was designed to be as lean as possible, preserving only the chainId and * verifyingContract fields. It retains logic for properly updating the chain id to protect against replay attacks on * an eventual fork of the chain. The verifyingContract to be used should be defined by deriving contracts, allowing * for flexibility in the verification of EIP-712 signatures. This is particularly useful in the context of EIP-7702 * delegate contracts, where the verifyingContract may be the proxy contract itself or the implementation contract. * This contract implements the version of the encoding known as "signTypedDataV4". * * This contract is derived from the OpenZeppelin Contracts implementation of EIP-712 (utils/cryptography/EIP712.sol). * * @custom:security-contact [email protected] */ abstract contract TypedAuthorization is IERC5267 { // ============================================================= // CONSTANTS / IMMUTABLE // ============================================================= /** * @notice The EIP712 domain typehash used for computing the domain separator * @dev Hash of the type string: "EIP712Domain(uint256 chainId,address verifyingContract)" */ bytes32 private constant _DOMAIN_TYPEHASH = keccak256("EIP712Domain(uint256 chainId,address verifyingContract)"); /** * @notice The typehash for the Execution type used in the structured data * @dev Hash of the type string: "Execution(address target,uint256 value,bytes data)" */ bytes32 internal constant _EXECUTION_TYPEHASH = keccak256("Execution(address target,uint256 value,bytes data)"); /** * @notice The typehash for the AuthorizedExecutions type used in the typed data * @dev Hash of the type string that combines the execution authorization with the execution data * This defines the structure of the typed data that will be signed for authorizing executions */ bytes32 internal constant _EXECUTION_AUTHORIZATION_TYPEHASH = keccak256( // solhint-disable-next-line max-line-length "AuthorizedExecutions(Execution[] calls,uint256 deadline,bytes32 mode,uint256 nonce,address relayer)Execution(address target,uint256 value,bytes data)" ); // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _cachedDomainSeparator; // solhint-disable-line immutable-vars-naming uint256 private immutable _cachedChainId; // solhint-disable-line immutable-vars-naming // ============================================================= // CONSTRUCTOR // ============================================================= /** * @notice Initializes the EIP712 domain separator cache using an internally defined verifying-contract address */ constructor() { _cachedChainId = block.chainid; _cachedDomainSeparator = _buildDomainSeparator(); } // ============================================================= // PUBLIC FUNCTIONS // ============================================================= /** * @inheritdoc IERC5267 */ function eip712Domain() public view virtual returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { return ( hex"0c", // 01100 string(""), // empty name string(""), // empty version block.chainid, _verifyingContractAddress(), bytes32(0), // empty salt new uint256[](0) ); } // ============================================================= // INTERNAL FUNCTIONS // ============================================================= /** * @notice Returns the domain separator for the current chain. * @dev Returns the cached separator if the chain id hasn't changed, otherwise rebuilds it. * @return domainSeparator The domain separator bytes32 value */ function _domainSeparatorV4() internal view returns (bytes32 domainSeparator) { // Use cached value if chainId matches, otherwise rebuild return block.chainid == _cachedChainId ? _cachedDomainSeparator : _buildDomainSeparator(); } /** * @notice Builds the EIP712 domain separator using the current chain ID and the implementation-specific address * as the verifying contract. * @return domainSeparator The domain separator bytes32 value */ function _buildDomainSeparator() private view returns (bytes32 domainSeparator) { return keccak256(abi.encode(_DOMAIN_TYPEHASH, block.chainid, _verifyingContractAddress())); } /** * @notice Given a hashed struct, returns the hash of the fully encoded EIP712 message for this domain. * * See https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[definition of hashed struct]. * * @dev This hash can be used with {ECDSA-recover} to obtain the signer of a message * * @param structHash The hash of the struct being signed * @return hashedData The EIP712 typed data hash */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32 hashedData) { return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @notice Create a hash of the fully encoded EIP712 message for a single authorized execution * @dev Creates a typed hash for a single execution with the given parameters * * @param mode The execution mode * @param target The target address * @param value The value to send * @param data The call data * @param nonce The nonce * @param deadline The timestamp after which the signature is no longer valid * @param relayer The address of the relayer that is authorized to submit this transaction * @return hashedData The `AuthorizedExecutions` typed hash */ function _hashTypedSingleExecutionAuthorization( bytes32 mode, address target, uint256 value, bytes memory data, uint256 nonce, uint256 deadline, address relayer ) internal view returns (bytes32 hashedData) { // Directly calculate the execution hash for the single execution bytes32 seHash = keccak256(abi.encode(_EXECUTION_TYPEHASH, target, value, keccak256(data))); // When there's only one item, the executionsHash (plural) is just the packaged single hash bytes32 executionsHash = keccak256(abi.encodePacked(seHash)); // Create the final hash including the calls, deadline, mode, nonce and relayer bytes32 structHash = keccak256(abi.encode(_EXECUTION_AUTHORIZATION_TYPEHASH, executionsHash, deadline, mode, nonce, relayer)); return _hashTypedDataV4(structHash); } /** * @notice Create a hash of the fully encoded EIP712 message for a batch of executions * @dev Creates a typed hash for multiple executions with the given parameters * * @param mode The execution mode * @param calls The array of executions * @param nonce The nonce * @param deadline The timestamp after which the signature is no longer valid * @param relayer The address of the relayer that is authorized to submit this transaction * @return hashedData The `AuthorizedExecutions` typed hash */ function _hashTypedBatchExecutionAuthorization( bytes32 mode, Execution[] memory calls, uint256 nonce, uint256 deadline, address relayer ) internal view returns (bytes32 hashedData) { // Hash each execution in the batch bytes32[] memory executionHashes = new bytes32[](calls.length); for (uint256 i = 0; i < calls.length; i++) { executionHashes[i] = keccak256( abi.encode(_EXECUTION_TYPEHASH, calls[i].target, calls[i].value, keccak256(calls[i].callData)) ); } // Hash the array of execution hashes bytes32 executionsHash = keccak256(abi.encodePacked(executionHashes)); // Create the final hash including the calls, deadline, mode, nonce and relayer bytes32 structHash = keccak256(abi.encode(_EXECUTION_AUTHORIZATION_TYPEHASH, executionsHash, deadline, mode, nonce, relayer)); return _hashTypedDataV4(structHash); } /** * @notice This function determines the address of the verifying contract to be used in the EIP712 domain separator * @dev This function must be overridden by the deriving contract to provide the appropriate contract address, * which could be the address of the implementation contract or the proxy contract. * @return verifyingContract The address of the verifying contract */ function _verifyingContractAddress() internal view virtual returns (address verifyingContract); }
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-FileCopyrightText: Copyright (C) 2025 Fireblocks <[email protected]> pragma solidity 0.8.27; import { NonceStorage } from "../library/NonceStorageStruct.sol"; import { LibErrors } from "../library/LibErrors.sol"; /** * @title NonceBitmap * @notice This contract manages unordered nonces using a Bitmap approach to efficiently store and track nonce usage. * @dev Provides functionality for managing and querying nonces * @custom:security-contact [email protected] */ abstract contract NonceBitmap { // ============================================================= // FUNCTIONS // ============================================================= // ========================= EXTERNAL ========================== /** * @notice This function marks a nonce as used * @dev This function is used to invalidate a nonce. Reverts with {LibErrors.InvalidNonce} * if the nonce has already been used. * * Deriving contracts must ensure proper access control. * * @param nonce The nonce to invalidate */ function invalidateNonce(uint256 nonce) external virtual { _useUnorderedNonce(nonce); } /** * @notice Returns the nonce bitmap at a given word position * @param wordPos The word position to check * @return bitmap The nonce bitmap at the given position */ function getNonceBitmap(uint248 wordPos) public view virtual returns (uint256 bitmap) { return _nonceStorage().nonceBitmap[wordPos]; } /** * @notice This function checks if a nonce is already used * @dev Checks whether a nonce has been flipped in the bitmap * @param nonce The nonce to check * @return isUsed True if the nonce has been used, false otherwise */ function isNonceUsed(uint256 nonce) public view virtual returns (bool isUsed) { (uint256 wordPos, uint256 bitPos) = _bitmapPositions(nonce); uint256 bit = 1 << bitPos; return _nonceStorage().nonceBitmap[wordPos] & bit != 0; } // ========================= INTERNAL ========================== /** * @notice Returns the index of the bitmap and the bit position within the bitmap * @param nonce The nonce to get the associated word and bit positions * @return wordPos The word position or index into the nonceBitmap * @return bitPos The bit position * @dev The first 248 bits of the nonce value is the index of the desired bitmap * @dev The last 8 bits of the nonce value is the position of the bit in the bitmap */ function _bitmapPositions(uint256 nonce) internal pure returns (uint256 wordPos, uint256 bitPos) { wordPos = uint248(nonce >> 8); bitPos = uint8(nonce); } /** * @notice This represents the function signature to be used when accessing the Nonce Storage * @dev Returns storage reference for nonce bitmap * @return $ Storage reference to the nonce bitmap */ function _nonceStorage() internal pure virtual returns (NonceStorage storage $); /** * @notice Sets the nonce to used * @dev Checks whether a nonce is taken and sets the bit at the bit position in the bitmap. * * Reverts with {LibErrors.InvalidNonce} if the nonce has already been used. * * @param nonce The nonce to spend */ function _useUnorderedNonce(uint256 nonce) internal { (uint256 wordPos, uint256 bitPos) = _bitmapPositions(nonce); uint256 bit = 1 << bitPos; uint256 flipped = _nonceStorage().nonceBitmap[wordPos] ^= bit; if (flipped & bit == 0) revert LibErrors.InvalidNonce(); } }
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-FileCopyrightText: Copyright (C) 2025 Fireblocks <[email protected]> // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. pragma solidity 0.8.27; // ============================================================= // STRUCTS // ============================================================= /** * @notice Storage structure for nonce bitmap that helps prevent replay attacks of off-chain signatures * @dev This structure is used to track used nonces in a memory-efficient way using a bitmap * * The `@custom:storage-location` tag is to be defined by the implementing contract. */ struct NonceStorage { /** * @notice Unordered nonces with a bitmap. The key of the mapping is the "nonce value". * @dev The first 248 bits of the nonce value is the index of the desired bitmap * @dev The last 8 bits of the nonce value is the position of the bit in the bitmap */ mapping(uint256 => uint256) nonceBitmap; }
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-FileCopyrightText: Copyright (C) 2025 Fireblocks <[email protected]> // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. pragma solidity 0.8.27; /** * @title Errors Library * @author Fireblocks * @notice The Errors Library provides error messages for the Fireblocks ecosystem of smart contracts. */ library LibErrors { /** * @notice This error indicates that a signature has expired * @dev Indicates that current block timestamp is past the deadline */ error ExpiredSignature(uint256 deadline); /** * @notice This error indicates that a nonce has already been used. * @dev The nonce has already been used for this account. */ error InvalidNonce(); /** * @notice This error indicates that an address provided does not implement a required interface. * @dev Indicates that a contract does not implement a required interface. */ error InvalidImplementation(); /** * @notice This error indicates that there was an error decoding the opData parameter. * @dev Indicates that there was an error decoding the operation data (opData). */ error OpDataDecodingError(); /** * @notice This error indicates that there was an error extracting data from the execution payload. * @dev Indicates that there was an error decoding the execution payload based on an expected structure. */ error ExecutionDataExtractionError(); /** * @notice This error indicates that a call to the `execute` function on the same Delegate EOA was attempted, from * the context of a running `execute` function. This would indicate a reentrant call, and therefore is blocked. * @dev Thrown when a reentrant call is detected. */ error ReentrantCall(); /** * @notice This error indicates that the function caller is not the expected. For example, not the EOA itself. * @dev Indicates that the function caller is not the expected address. */ error UnauthorizedCaller(); /** * @notice This error indicates that a call is being invoked in the wrong target. For example, the implementation * contract instead of the Delegated EOA address. * @dev Indicates that the call is from an unauthorized context, such as a direct call to the * implementation contract. */ error UnauthorizedCallContext(); /** * @notice This error indicates that an execution request was rejected due to invalid authorization. * @dev Thrown when an execution request fails signature verification checks. * * This can occur when: * - The signature provided cannot be attributed to the expected signer (the EOA that has performed an EIP-7702 * delegation to this contract) * - The provided signature does not match the given execution payload * - The `opData` component was present and non-zero but the mode provided does not support it */ error UnauthorizedExecution(); /** * @notice This error indicates that the requested execution mode is not supported by the contract. * @dev Thrown when an execution request uses an execution mode configuration that is not * recognized or supported by the contract. This is a general error when the specific * component causing the unsupported mode cannot be determined. * * See also: * - {UnsupportedModeSelector}: For more specific errors related to mode selectors * - {ERC7579UnsupportedCallType}: For errors related to call types * - {ERC7579UnsupportedExecType}: For errors related to execution types */ error UnsupportedExecutionMode(); /** * @notice This error indicates that the execution mode selector is not supported by the contract. * @dev Indicates that the execution mode selector is not supported by the contract. * @param modeSelector The function selector that was not recognized as a valid mode. */ error UnsupportedModeSelector(bytes4 modeSelector); // ==================== IMPORTED ERRORS ==================== // These are errors that are observed in inherited contracts // or libraries and therefore are known to be thrown by the // contract. They are collated here for developer convenience. // ========================================================= /** * @notice This error indicates that the operation failed because the contract is paused. * @dev The operation failed because the contract is paused. * * Moved into a library to avoid the need for a contract to inherit/import from {Pausable}. This error is original * from OpenZeppelin's {Pausable} contract: * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Pausable.sol */ error EnforcedPause(); /** * @notice This error indicates that an ERC7579 execute "call type" is not supported. * @dev Thrown when an unsupported call type is used in an EIP-7579 execution mode. * @param callType The unsupported call type byte. */ error ERC7579UnsupportedCallType(bytes1 callType); /** * @notice This error indicates that an ERC7579 execute "execution type" is not supported. * @dev Thrown when an unsupported exec type is used in an EIP-7579 execution mode. * @param execType The unsupported execution type byte. */ error ERC7579UnsupportedExecType(bytes1 execType); }
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-FileCopyrightText: Copyright (C) 2025 Fireblocks <[email protected]> pragma solidity 0.8.27; /** * @title IKillSwitch * @notice Interface for the KillSwitch contract * @dev Defines the standard functions for a KillSwitch that can pause and unpause system functionality */ interface IKillSwitch { // ============================================================= // FUNCTIONS // ============================================================= /** * @notice Pauses delegate contract operations for all delegated EOAs */ function pause() external; /** * @notice Resumes normal operation of delegated EOAs */ function unpause() external; /** * @notice Checks if the delegate contract functionality is paused * @return True if the contract is paused, false otherwise */ function paused() external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol) pragma solidity ^0.8.20; /** * @dev Collection of common custom errors used in multiple contracts * * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. * It is recommended to avoid relying on the error API for critical functionality. * * _Available since v5.1._ */ library Errors { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error InsufficientBalance(uint256 balance, uint256 needed); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedCall(); /** * @dev The deployment failed. */ error FailedDeployment(); /** * @dev A necessary precompile is missing. */ error MissingPrecompile(address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.2.0) (interfaces/draft-IERC7579.sol) pragma solidity ^0.8.20; import {PackedUserOperation} from "./draft-IERC4337.sol"; uint256 constant VALIDATION_SUCCESS = 0; uint256 constant VALIDATION_FAILED = 1; uint256 constant MODULE_TYPE_VALIDATOR = 1; uint256 constant MODULE_TYPE_EXECUTOR = 2; uint256 constant MODULE_TYPE_FALLBACK = 3; uint256 constant MODULE_TYPE_HOOK = 4; /// @dev Minimal configuration interface for ERC-7579 modules interface IERC7579Module { /** * @dev This function is called by the smart account during installation of the module * @param data arbitrary data that may be required on the module during `onInstall` initialization * * MUST revert on error (e.g. if module is already enabled) */ function onInstall(bytes calldata data) external; /** * @dev This function is called by the smart account during uninstallation of the module * @param data arbitrary data that may be required on the module during `onUninstall` de-initialization * * MUST revert on error */ function onUninstall(bytes calldata data) external; /** * @dev Returns boolean value if module is a certain type * @param moduleTypeId the module type ID according the ERC-7579 spec * * MUST return true if the module is of the given type and false otherwise */ function isModuleType(uint256 moduleTypeId) external view returns (bool); } /** * @dev ERC-7579 Validation module (type 1). * * A module that implements logic to validate user operations and signatures. */ interface IERC7579Validator is IERC7579Module { /** * @dev Validates a UserOperation * @param userOp the ERC-4337 PackedUserOperation * @param userOpHash the hash of the ERC-4337 PackedUserOperation * * MUST validate that the signature is a valid signature of the userOpHash * SHOULD return ERC-4337's SIG_VALIDATION_FAILED (and not revert) on signature mismatch * See {IAccount-validateUserOp} for additional information on the return value */ function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external returns (uint256); /** * @dev Validates a signature using ERC-1271 * @param sender the address that sent the ERC-1271 request to the smart account * @param hash the hash of the ERC-1271 request * @param signature the signature of the ERC-1271 request * * MUST return the ERC-1271 `MAGIC_VALUE` if the signature is valid * MUST NOT modify state */ function isValidSignatureWithSender( address sender, bytes32 hash, bytes calldata signature ) external view returns (bytes4); } /** * @dev ERC-7579 Hooks module (type 4). * * A module that implements logic to execute before and after the account executes a user operation, * either individually or batched. */ interface IERC7579Hook is IERC7579Module { /** * @dev Called by the smart account before execution * @param msgSender the address that called the smart account * @param value the value that was sent to the smart account * @param msgData the data that was sent to the smart account * * MAY return arbitrary data in the `hookData` return value */ function preCheck( address msgSender, uint256 value, bytes calldata msgData ) external returns (bytes memory hookData); /** * @dev Called by the smart account after execution * @param hookData the data that was returned by the `preCheck` function * * MAY validate the `hookData` to validate transaction context of the `preCheck` function */ function postCheck(bytes calldata hookData) external; } struct Execution { address target; uint256 value; bytes callData; } /** * @dev ERC-7579 Execution. * * Accounts should implement this interface so that the Entrypoint and ERC-7579 modules can execute operations. */ interface IERC7579Execution { /** * @dev Executes a transaction on behalf of the account. * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details * @param executionCalldata The encoded execution call data * * MUST ensure adequate authorization control: e.g. onlyEntryPointOrSelf if used with ERC-4337 * If a mode is requested that is not supported by the Account, it MUST revert */ function execute(bytes32 mode, bytes calldata executionCalldata) external payable; /** * @dev Executes a transaction on behalf of the account. * This function is intended to be called by Executor Modules * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details * @param executionCalldata The encoded execution call data * @return returnData An array with the returned data of each executed subcall * * MUST ensure adequate authorization control: i.e. onlyExecutorModule * If a mode is requested that is not supported by the Account, it MUST revert */ function executeFromExecutor( bytes32 mode, bytes calldata executionCalldata ) external payable returns (bytes[] memory returnData); } /** * @dev ERC-7579 Account Config. * * Accounts should implement this interface to expose information that identifies the account, supported modules and capabilities. */ interface IERC7579AccountConfig { /** * @dev Returns the account id of the smart account * @return accountImplementationId the account id of the smart account * * MUST return a non-empty string * The accountId SHOULD be structured like so: * "vendorname.accountname.semver" * The id SHOULD be unique across all smart accounts */ function accountId() external view returns (string memory accountImplementationId); /** * @dev Function to check if the account supports a certain execution mode (see above) * @param encodedMode the encoded mode * * MUST return true if the account supports the mode and false otherwise */ function supportsExecutionMode(bytes32 encodedMode) external view returns (bool); /** * @dev Function to check if the account supports a certain module typeId * @param moduleTypeId the module type ID according to the ERC-7579 spec * * MUST return true if the account supports the module type and false otherwise */ function supportsModule(uint256 moduleTypeId) external view returns (bool); } /** * @dev ERC-7579 Module Config. * * Accounts should implement this interface to allow installing and uninstalling modules. */ interface IERC7579ModuleConfig { event ModuleInstalled(uint256 moduleTypeId, address module); event ModuleUninstalled(uint256 moduleTypeId, address module); /** * @dev Installs a Module of a certain type on the smart account * @param moduleTypeId the module type ID according to the ERC-7579 spec * @param module the module address * @param initData arbitrary data that may be required on the module during `onInstall` * initialization. * * MUST implement authorization control * MUST call `onInstall` on the module with the `initData` parameter if provided * MUST emit ModuleInstalled event * MUST revert if the module is already installed or the initialization on the module failed */ function installModule(uint256 moduleTypeId, address module, bytes calldata initData) external; /** * @dev Uninstalls a Module of a certain type on the smart account * @param moduleTypeId the module type ID according the ERC-7579 spec * @param module the module address * @param deInitData arbitrary data that may be required on the module during `onInstall` * initialization. * * MUST implement authorization control * MUST call `onUninstall` on the module with the `deInitData` parameter if provided * MUST emit ModuleUninstalled event * MUST revert if the module is not installed or the deInitialization on the module failed */ function uninstallModule(uint256 moduleTypeId, address module, bytes calldata deInitData) external; /** * @dev Returns whether a module is installed on the smart account * @param moduleTypeId the module type ID according the ERC-7579 spec * @param module the module address * @param additionalContext arbitrary data that may be required to determine if the module is installed * * MUST return true if the module is installed and false otherwise */ function isModuleInstalled( uint256 moduleTypeId, address module, bytes calldata additionalContext ) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.2.0) (utils/Packing.sol) // This file was procedurally generated from scripts/generate/templates/Packing.js. pragma solidity ^0.8.20; /** * @dev Helper library packing and unpacking multiple values into bytesXX. * * Example usage: * * ```solidity * library MyPacker { * type MyType is bytes32; * * function _pack(address account, bytes4 selector, uint64 period) external pure returns (MyType) { * bytes12 subpack = Packing.pack_4_8(selector, bytes8(period)); * bytes32 pack = Packing.pack_20_12(bytes20(account), subpack); * return MyType.wrap(pack); * } * * function _unpack(MyType self) external pure returns (address, bytes4, uint64) { * bytes32 pack = MyType.unwrap(self); * return ( * address(Packing.extract_32_20(pack, 0)), * Packing.extract_32_4(pack, 20), * uint64(Packing.extract_32_8(pack, 24)) * ); * } * } * ``` * * _Available since v5.1._ */ // solhint-disable func-name-mixedcase library Packing { error OutOfRangeAccess(); function pack_1_1(bytes1 left, bytes1 right) internal pure returns (bytes2 result) { assembly ("memory-safe") { left := and(left, shl(248, not(0))) right := and(right, shl(248, not(0))) result := or(left, shr(8, right)) } } function pack_2_2(bytes2 left, bytes2 right) internal pure returns (bytes4 result) { assembly ("memory-safe") { left := and(left, shl(240, not(0))) right := and(right, shl(240, not(0))) result := or(left, shr(16, right)) } } function pack_2_4(bytes2 left, bytes4 right) internal pure returns (bytes6 result) { assembly ("memory-safe") { left := and(left, shl(240, not(0))) right := and(right, shl(224, not(0))) result := or(left, shr(16, right)) } } function pack_2_6(bytes2 left, bytes6 right) internal pure returns (bytes8 result) { assembly ("memory-safe") { left := and(left, shl(240, not(0))) right := and(right, shl(208, not(0))) result := or(left, shr(16, right)) } } function pack_2_8(bytes2 left, bytes8 right) internal pure returns (bytes10 result) { assembly ("memory-safe") { left := and(left, shl(240, not(0))) right := and(right, shl(192, not(0))) result := or(left, shr(16, right)) } } function pack_2_10(bytes2 left, bytes10 right) internal pure returns (bytes12 result) { assembly ("memory-safe") { left := and(left, shl(240, not(0))) right := and(right, shl(176, not(0))) result := or(left, shr(16, right)) } } function pack_2_20(bytes2 left, bytes20 right) internal pure returns (bytes22 result) { assembly ("memory-safe") { left := and(left, shl(240, not(0))) right := and(right, shl(96, not(0))) result := or(left, shr(16, right)) } } function pack_2_22(bytes2 left, bytes22 right) internal pure returns (bytes24 result) { assembly ("memory-safe") { left := and(left, shl(240, not(0))) right := and(right, shl(80, not(0))) result := or(left, shr(16, right)) } } function pack_4_2(bytes4 left, bytes2 right) internal pure returns (bytes6 result) { assembly ("memory-safe") { left := and(left, shl(224, not(0))) right := and(right, shl(240, not(0))) result := or(left, shr(32, right)) } } function pack_4_4(bytes4 left, bytes4 right) internal pure returns (bytes8 result) { assembly ("memory-safe") { left := and(left, shl(224, not(0))) right := and(right, shl(224, not(0))) result := or(left, shr(32, right)) } } function pack_4_6(bytes4 left, bytes6 right) internal pure returns (bytes10 result) { assembly ("memory-safe") { left := and(left, shl(224, not(0))) right := and(right, shl(208, not(0))) result := or(left, shr(32, right)) } } function pack_4_8(bytes4 left, bytes8 right) internal pure returns (bytes12 result) { assembly ("memory-safe") { left := and(left, shl(224, not(0))) right := and(right, shl(192, not(0))) result := or(left, shr(32, right)) } } function pack_4_12(bytes4 left, bytes12 right) internal pure returns (bytes16 result) { assembly ("memory-safe") { left := and(left, shl(224, not(0))) right := and(right, shl(160, not(0))) result := or(left, shr(32, right)) } } function pack_4_16(bytes4 left, bytes16 right) internal pure returns (bytes20 result) { assembly ("memory-safe") { left := and(left, shl(224, not(0))) right := and(right, shl(128, not(0))) result := or(left, shr(32, right)) } } function pack_4_20(bytes4 left, bytes20 right) internal pure returns (bytes24 result) { assembly ("memory-safe") { left := and(left, shl(224, not(0))) right := and(right, shl(96, not(0))) result := or(left, shr(32, right)) } } function pack_4_24(bytes4 left, bytes24 right) internal pure returns (bytes28 result) { assembly ("memory-safe") { left := and(left, shl(224, not(0))) right := and(right, shl(64, not(0))) result := or(left, shr(32, right)) } } function pack_4_28(bytes4 left, bytes28 right) internal pure returns (bytes32 result) { assembly ("memory-safe") { left := and(left, shl(224, not(0))) right := and(right, shl(32, not(0))) result := or(left, shr(32, right)) } } function pack_6_2(bytes6 left, bytes2 right) internal pure returns (bytes8 result) { assembly ("memory-safe") { left := and(left, shl(208, not(0))) right := and(right, shl(240, not(0))) result := or(left, shr(48, right)) } } function pack_6_4(bytes6 left, bytes4 right) internal pure returns (bytes10 result) { assembly ("memory-safe") { left := and(left, shl(208, not(0))) right := and(right, shl(224, not(0))) result := or(left, shr(48, right)) } } function pack_6_6(bytes6 left, bytes6 right) internal pure returns (bytes12 result) { assembly ("memory-safe") { left := and(left, shl(208, not(0))) right := and(right, shl(208, not(0))) result := or(left, shr(48, right)) } } function pack_6_10(bytes6 left, bytes10 right) internal pure returns (bytes16 result) { assembly ("memory-safe") { left := and(left, shl(208, not(0))) right := and(right, shl(176, not(0))) result := or(left, shr(48, right)) } } function pack_6_16(bytes6 left, bytes16 right) internal pure returns (bytes22 result) { assembly ("memory-safe") { left := and(left, shl(208, not(0))) right := and(right, shl(128, not(0))) result := or(left, shr(48, right)) } } function pack_6_22(bytes6 left, bytes22 right) internal pure returns (bytes28 result) { assembly ("memory-safe") { left := and(left, shl(208, not(0))) right := and(right, shl(80, not(0))) result := or(left, shr(48, right)) } } function pack_8_2(bytes8 left, bytes2 right) internal pure returns (bytes10 result) { assembly ("memory-safe") { left := and(left, shl(192, not(0))) right := and(right, shl(240, not(0))) result := or(left, shr(64, right)) } } function pack_8_4(bytes8 left, bytes4 right) internal pure returns (bytes12 result) { assembly ("memory-safe") { left := and(left, shl(192, not(0))) right := and(right, shl(224, not(0))) result := or(left, shr(64, right)) } } function pack_8_8(bytes8 left, bytes8 right) internal pure returns (bytes16 result) { assembly ("memory-safe") { left := and(left, shl(192, not(0))) right := and(right, shl(192, not(0))) result := or(left, shr(64, right)) } } function pack_8_12(bytes8 left, bytes12 right) internal pure returns (bytes20 result) { assembly ("memory-safe") { left := and(left, shl(192, not(0))) right := and(right, shl(160, not(0))) result := or(left, shr(64, right)) } } function pack_8_16(bytes8 left, bytes16 right) internal pure returns (bytes24 result) { assembly ("memory-safe") { left := and(left, shl(192, not(0))) right := and(right, shl(128, not(0))) result := or(left, shr(64, right)) } } function pack_8_20(bytes8 left, bytes20 right) internal pure returns (bytes28 result) { assembly ("memory-safe") { left := and(left, shl(192, not(0))) right := and(right, shl(96, not(0))) result := or(left, shr(64, right)) } } function pack_8_24(bytes8 left, bytes24 right) internal pure returns (bytes32 result) { assembly ("memory-safe") { left := and(left, shl(192, not(0))) right := and(right, shl(64, not(0))) result := or(left, shr(64, right)) } } function pack_10_2(bytes10 left, bytes2 right) internal pure returns (bytes12 result) { assembly ("memory-safe") { left := and(left, shl(176, not(0))) right := and(right, shl(240, not(0))) result := or(left, shr(80, right)) } } function pack_10_6(bytes10 left, bytes6 right) internal pure returns (bytes16 result) { assembly ("memory-safe") { left := and(left, shl(176, not(0))) right := and(right, shl(208, not(0))) result := or(left, shr(80, right)) } } function pack_10_10(bytes10 left, bytes10 right) internal pure returns (bytes20 result) { assembly ("memory-safe") { left := and(left, shl(176, not(0))) right := and(right, shl(176, not(0))) result := or(left, shr(80, right)) } } function pack_10_12(bytes10 left, bytes12 right) internal pure returns (bytes22 result) { assembly ("memory-safe") { left := and(left, shl(176, not(0))) right := and(right, shl(160, not(0))) result := or(left, shr(80, right)) } } function pack_10_22(bytes10 left, bytes22 right) internal pure returns (bytes32 result) { assembly ("memory-safe") { left := and(left, shl(176, not(0))) right := and(right, shl(80, not(0))) result := or(left, shr(80, right)) } } function pack_12_4(bytes12 left, bytes4 right) internal pure returns (bytes16 result) { assembly ("memory-safe") { left := and(left, shl(160, not(0))) right := and(right, shl(224, not(0))) result := or(left, shr(96, right)) } } function pack_12_8(bytes12 left, bytes8 right) internal pure returns (bytes20 result) { assembly ("memory-safe") { left := and(left, shl(160, not(0))) right := and(right, shl(192, not(0))) result := or(left, shr(96, right)) } } function pack_12_10(bytes12 left, bytes10 right) internal pure returns (bytes22 result) { assembly ("memory-safe") { left := and(left, shl(160, not(0))) right := and(right, shl(176, not(0))) result := or(left, shr(96, right)) } } function pack_12_12(bytes12 left, bytes12 right) internal pure returns (bytes24 result) { assembly ("memory-safe") { left := and(left, shl(160, not(0))) right := and(right, shl(160, not(0))) result := or(left, shr(96, right)) } } function pack_12_16(bytes12 left, bytes16 right) internal pure returns (bytes28 result) { assembly ("memory-safe") { left := and(left, shl(160, not(0))) right := and(right, shl(128, not(0))) result := or(left, shr(96, right)) } } function pack_12_20(bytes12 left, bytes20 right) internal pure returns (bytes32 result) { assembly ("memory-safe") { left := and(left, shl(160, not(0))) right := and(right, shl(96, not(0))) result := or(left, shr(96, right)) } } function pack_16_4(bytes16 left, bytes4 right) internal pure returns (bytes20 result) { assembly ("memory-safe") { left := and(left, shl(128, not(0))) right := and(right, shl(224, not(0))) result := or(left, shr(128, right)) } } function pack_16_6(bytes16 left, bytes6 right) internal pure returns (bytes22 result) { assembly ("memory-safe") { left := and(left, shl(128, not(0))) right := and(right, shl(208, not(0))) result := or(left, shr(128, right)) } } function pack_16_8(bytes16 left, bytes8 right) internal pure returns (bytes24 result) { assembly ("memory-safe") { left := and(left, shl(128, not(0))) right := and(right, shl(192, not(0))) result := or(left, shr(128, right)) } } function pack_16_12(bytes16 left, bytes12 right) internal pure returns (bytes28 result) { assembly ("memory-safe") { left := and(left, shl(128, not(0))) right := and(right, shl(160, not(0))) result := or(left, shr(128, right)) } } function pack_16_16(bytes16 left, bytes16 right) internal pure returns (bytes32 result) { assembly ("memory-safe") { left := and(left, shl(128, not(0))) right := and(right, shl(128, not(0))) result := or(left, shr(128, right)) } } function pack_20_2(bytes20 left, bytes2 right) internal pure returns (bytes22 result) { assembly ("memory-safe") { left := and(left, shl(96, not(0))) right := and(right, shl(240, not(0))) result := or(left, shr(160, right)) } } function pack_20_4(bytes20 left, bytes4 right) internal pure returns (bytes24 result) { assembly ("memory-safe") { left := and(left, shl(96, not(0))) right := and(right, shl(224, not(0))) result := or(left, shr(160, right)) } } function pack_20_8(bytes20 left, bytes8 right) internal pure returns (bytes28 result) { assembly ("memory-safe") { left := and(left, shl(96, not(0))) right := and(right, shl(192, not(0))) result := or(left, shr(160, right)) } } function pack_20_12(bytes20 left, bytes12 right) internal pure returns (bytes32 result) { assembly ("memory-safe") { left := and(left, shl(96, not(0))) right := and(right, shl(160, not(0))) result := or(left, shr(160, right)) } } function pack_22_2(bytes22 left, bytes2 right) internal pure returns (bytes24 result) { assembly ("memory-safe") { left := and(left, shl(80, not(0))) right := and(right, shl(240, not(0))) result := or(left, shr(176, right)) } } function pack_22_6(bytes22 left, bytes6 right) internal pure returns (bytes28 result) { assembly ("memory-safe") { left := and(left, shl(80, not(0))) right := and(right, shl(208, not(0))) result := or(left, shr(176, right)) } } function pack_22_10(bytes22 left, bytes10 right) internal pure returns (bytes32 result) { assembly ("memory-safe") { left := and(left, shl(80, not(0))) right := and(right, shl(176, not(0))) result := or(left, shr(176, right)) } } function pack_24_4(bytes24 left, bytes4 right) internal pure returns (bytes28 result) { assembly ("memory-safe") { left := and(left, shl(64, not(0))) right := and(right, shl(224, not(0))) result := or(left, shr(192, right)) } } function pack_24_8(bytes24 left, bytes8 right) internal pure returns (bytes32 result) { assembly ("memory-safe") { left := and(left, shl(64, not(0))) right := and(right, shl(192, not(0))) result := or(left, shr(192, right)) } } function pack_28_4(bytes28 left, bytes4 right) internal pure returns (bytes32 result) { assembly ("memory-safe") { left := and(left, shl(32, not(0))) right := and(right, shl(224, not(0))) result := or(left, shr(224, right)) } } function extract_2_1(bytes2 self, uint8 offset) internal pure returns (bytes1 result) { if (offset > 1) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(248, not(0))) } } function replace_2_1(bytes2 self, bytes1 value, uint8 offset) internal pure returns (bytes2 result) { bytes1 oldValue = extract_2_1(self, offset); assembly ("memory-safe") { value := and(value, shl(248, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_4_1(bytes4 self, uint8 offset) internal pure returns (bytes1 result) { if (offset > 3) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(248, not(0))) } } function replace_4_1(bytes4 self, bytes1 value, uint8 offset) internal pure returns (bytes4 result) { bytes1 oldValue = extract_4_1(self, offset); assembly ("memory-safe") { value := and(value, shl(248, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_4_2(bytes4 self, uint8 offset) internal pure returns (bytes2 result) { if (offset > 2) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(240, not(0))) } } function replace_4_2(bytes4 self, bytes2 value, uint8 offset) internal pure returns (bytes4 result) { bytes2 oldValue = extract_4_2(self, offset); assembly ("memory-safe") { value := and(value, shl(240, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_6_1(bytes6 self, uint8 offset) internal pure returns (bytes1 result) { if (offset > 5) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(248, not(0))) } } function replace_6_1(bytes6 self, bytes1 value, uint8 offset) internal pure returns (bytes6 result) { bytes1 oldValue = extract_6_1(self, offset); assembly ("memory-safe") { value := and(value, shl(248, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_6_2(bytes6 self, uint8 offset) internal pure returns (bytes2 result) { if (offset > 4) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(240, not(0))) } } function replace_6_2(bytes6 self, bytes2 value, uint8 offset) internal pure returns (bytes6 result) { bytes2 oldValue = extract_6_2(self, offset); assembly ("memory-safe") { value := and(value, shl(240, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_6_4(bytes6 self, uint8 offset) internal pure returns (bytes4 result) { if (offset > 2) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(224, not(0))) } } function replace_6_4(bytes6 self, bytes4 value, uint8 offset) internal pure returns (bytes6 result) { bytes4 oldValue = extract_6_4(self, offset); assembly ("memory-safe") { value := and(value, shl(224, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_8_1(bytes8 self, uint8 offset) internal pure returns (bytes1 result) { if (offset > 7) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(248, not(0))) } } function replace_8_1(bytes8 self, bytes1 value, uint8 offset) internal pure returns (bytes8 result) { bytes1 oldValue = extract_8_1(self, offset); assembly ("memory-safe") { value := and(value, shl(248, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_8_2(bytes8 self, uint8 offset) internal pure returns (bytes2 result) { if (offset > 6) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(240, not(0))) } } function replace_8_2(bytes8 self, bytes2 value, uint8 offset) internal pure returns (bytes8 result) { bytes2 oldValue = extract_8_2(self, offset); assembly ("memory-safe") { value := and(value, shl(240, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_8_4(bytes8 self, uint8 offset) internal pure returns (bytes4 result) { if (offset > 4) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(224, not(0))) } } function replace_8_4(bytes8 self, bytes4 value, uint8 offset) internal pure returns (bytes8 result) { bytes4 oldValue = extract_8_4(self, offset); assembly ("memory-safe") { value := and(value, shl(224, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_8_6(bytes8 self, uint8 offset) internal pure returns (bytes6 result) { if (offset > 2) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(208, not(0))) } } function replace_8_6(bytes8 self, bytes6 value, uint8 offset) internal pure returns (bytes8 result) { bytes6 oldValue = extract_8_6(self, offset); assembly ("memory-safe") { value := and(value, shl(208, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_10_1(bytes10 self, uint8 offset) internal pure returns (bytes1 result) { if (offset > 9) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(248, not(0))) } } function replace_10_1(bytes10 self, bytes1 value, uint8 offset) internal pure returns (bytes10 result) { bytes1 oldValue = extract_10_1(self, offset); assembly ("memory-safe") { value := and(value, shl(248, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_10_2(bytes10 self, uint8 offset) internal pure returns (bytes2 result) { if (offset > 8) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(240, not(0))) } } function replace_10_2(bytes10 self, bytes2 value, uint8 offset) internal pure returns (bytes10 result) { bytes2 oldValue = extract_10_2(self, offset); assembly ("memory-safe") { value := and(value, shl(240, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_10_4(bytes10 self, uint8 offset) internal pure returns (bytes4 result) { if (offset > 6) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(224, not(0))) } } function replace_10_4(bytes10 self, bytes4 value, uint8 offset) internal pure returns (bytes10 result) { bytes4 oldValue = extract_10_4(self, offset); assembly ("memory-safe") { value := and(value, shl(224, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_10_6(bytes10 self, uint8 offset) internal pure returns (bytes6 result) { if (offset > 4) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(208, not(0))) } } function replace_10_6(bytes10 self, bytes6 value, uint8 offset) internal pure returns (bytes10 result) { bytes6 oldValue = extract_10_6(self, offset); assembly ("memory-safe") { value := and(value, shl(208, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_10_8(bytes10 self, uint8 offset) internal pure returns (bytes8 result) { if (offset > 2) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(192, not(0))) } } function replace_10_8(bytes10 self, bytes8 value, uint8 offset) internal pure returns (bytes10 result) { bytes8 oldValue = extract_10_8(self, offset); assembly ("memory-safe") { value := and(value, shl(192, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_12_1(bytes12 self, uint8 offset) internal pure returns (bytes1 result) { if (offset > 11) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(248, not(0))) } } function replace_12_1(bytes12 self, bytes1 value, uint8 offset) internal pure returns (bytes12 result) { bytes1 oldValue = extract_12_1(self, offset); assembly ("memory-safe") { value := and(value, shl(248, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_12_2(bytes12 self, uint8 offset) internal pure returns (bytes2 result) { if (offset > 10) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(240, not(0))) } } function replace_12_2(bytes12 self, bytes2 value, uint8 offset) internal pure returns (bytes12 result) { bytes2 oldValue = extract_12_2(self, offset); assembly ("memory-safe") { value := and(value, shl(240, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_12_4(bytes12 self, uint8 offset) internal pure returns (bytes4 result) { if (offset > 8) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(224, not(0))) } } function replace_12_4(bytes12 self, bytes4 value, uint8 offset) internal pure returns (bytes12 result) { bytes4 oldValue = extract_12_4(self, offset); assembly ("memory-safe") { value := and(value, shl(224, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_12_6(bytes12 self, uint8 offset) internal pure returns (bytes6 result) { if (offset > 6) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(208, not(0))) } } function replace_12_6(bytes12 self, bytes6 value, uint8 offset) internal pure returns (bytes12 result) { bytes6 oldValue = extract_12_6(self, offset); assembly ("memory-safe") { value := and(value, shl(208, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_12_8(bytes12 self, uint8 offset) internal pure returns (bytes8 result) { if (offset > 4) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(192, not(0))) } } function replace_12_8(bytes12 self, bytes8 value, uint8 offset) internal pure returns (bytes12 result) { bytes8 oldValue = extract_12_8(self, offset); assembly ("memory-safe") { value := and(value, shl(192, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_12_10(bytes12 self, uint8 offset) internal pure returns (bytes10 result) { if (offset > 2) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(176, not(0))) } } function replace_12_10(bytes12 self, bytes10 value, uint8 offset) internal pure returns (bytes12 result) { bytes10 oldValue = extract_12_10(self, offset); assembly ("memory-safe") { value := and(value, shl(176, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_16_1(bytes16 self, uint8 offset) internal pure returns (bytes1 result) { if (offset > 15) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(248, not(0))) } } function replace_16_1(bytes16 self, bytes1 value, uint8 offset) internal pure returns (bytes16 result) { bytes1 oldValue = extract_16_1(self, offset); assembly ("memory-safe") { value := and(value, shl(248, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_16_2(bytes16 self, uint8 offset) internal pure returns (bytes2 result) { if (offset > 14) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(240, not(0))) } } function replace_16_2(bytes16 self, bytes2 value, uint8 offset) internal pure returns (bytes16 result) { bytes2 oldValue = extract_16_2(self, offset); assembly ("memory-safe") { value := and(value, shl(240, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_16_4(bytes16 self, uint8 offset) internal pure returns (bytes4 result) { if (offset > 12) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(224, not(0))) } } function replace_16_4(bytes16 self, bytes4 value, uint8 offset) internal pure returns (bytes16 result) { bytes4 oldValue = extract_16_4(self, offset); assembly ("memory-safe") { value := and(value, shl(224, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_16_6(bytes16 self, uint8 offset) internal pure returns (bytes6 result) { if (offset > 10) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(208, not(0))) } } function replace_16_6(bytes16 self, bytes6 value, uint8 offset) internal pure returns (bytes16 result) { bytes6 oldValue = extract_16_6(self, offset); assembly ("memory-safe") { value := and(value, shl(208, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_16_8(bytes16 self, uint8 offset) internal pure returns (bytes8 result) { if (offset > 8) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(192, not(0))) } } function replace_16_8(bytes16 self, bytes8 value, uint8 offset) internal pure returns (bytes16 result) { bytes8 oldValue = extract_16_8(self, offset); assembly ("memory-safe") { value := and(value, shl(192, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_16_10(bytes16 self, uint8 offset) internal pure returns (bytes10 result) { if (offset > 6) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(176, not(0))) } } function replace_16_10(bytes16 self, bytes10 value, uint8 offset) internal pure returns (bytes16 result) { bytes10 oldValue = extract_16_10(self, offset); assembly ("memory-safe") { value := and(value, shl(176, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_16_12(bytes16 self, uint8 offset) internal pure returns (bytes12 result) { if (offset > 4) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(160, not(0))) } } function replace_16_12(bytes16 self, bytes12 value, uint8 offset) internal pure returns (bytes16 result) { bytes12 oldValue = extract_16_12(self, offset); assembly ("memory-safe") { value := and(value, shl(160, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_20_1(bytes20 self, uint8 offset) internal pure returns (bytes1 result) { if (offset > 19) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(248, not(0))) } } function replace_20_1(bytes20 self, bytes1 value, uint8 offset) internal pure returns (bytes20 result) { bytes1 oldValue = extract_20_1(self, offset); assembly ("memory-safe") { value := and(value, shl(248, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_20_2(bytes20 self, uint8 offset) internal pure returns (bytes2 result) { if (offset > 18) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(240, not(0))) } } function replace_20_2(bytes20 self, bytes2 value, uint8 offset) internal pure returns (bytes20 result) { bytes2 oldValue = extract_20_2(self, offset); assembly ("memory-safe") { value := and(value, shl(240, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_20_4(bytes20 self, uint8 offset) internal pure returns (bytes4 result) { if (offset > 16) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(224, not(0))) } } function replace_20_4(bytes20 self, bytes4 value, uint8 offset) internal pure returns (bytes20 result) { bytes4 oldValue = extract_20_4(self, offset); assembly ("memory-safe") { value := and(value, shl(224, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_20_6(bytes20 self, uint8 offset) internal pure returns (bytes6 result) { if (offset > 14) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(208, not(0))) } } function replace_20_6(bytes20 self, bytes6 value, uint8 offset) internal pure returns (bytes20 result) { bytes6 oldValue = extract_20_6(self, offset); assembly ("memory-safe") { value := and(value, shl(208, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_20_8(bytes20 self, uint8 offset) internal pure returns (bytes8 result) { if (offset > 12) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(192, not(0))) } } function replace_20_8(bytes20 self, bytes8 value, uint8 offset) internal pure returns (bytes20 result) { bytes8 oldValue = extract_20_8(self, offset); assembly ("memory-safe") { value := and(value, shl(192, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_20_10(bytes20 self, uint8 offset) internal pure returns (bytes10 result) { if (offset > 10) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(176, not(0))) } } function replace_20_10(bytes20 self, bytes10 value, uint8 offset) internal pure returns (bytes20 result) { bytes10 oldValue = extract_20_10(self, offset); assembly ("memory-safe") { value := and(value, shl(176, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_20_12(bytes20 self, uint8 offset) internal pure returns (bytes12 result) { if (offset > 8) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(160, not(0))) } } function replace_20_12(bytes20 self, bytes12 value, uint8 offset) internal pure returns (bytes20 result) { bytes12 oldValue = extract_20_12(self, offset); assembly ("memory-safe") { value := and(value, shl(160, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_20_16(bytes20 self, uint8 offset) internal pure returns (bytes16 result) { if (offset > 4) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(128, not(0))) } } function replace_20_16(bytes20 self, bytes16 value, uint8 offset) internal pure returns (bytes20 result) { bytes16 oldValue = extract_20_16(self, offset); assembly ("memory-safe") { value := and(value, shl(128, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_22_1(bytes22 self, uint8 offset) internal pure returns (bytes1 result) { if (offset > 21) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(248, not(0))) } } function replace_22_1(bytes22 self, bytes1 value, uint8 offset) internal pure returns (bytes22 result) { bytes1 oldValue = extract_22_1(self, offset); assembly ("memory-safe") { value := and(value, shl(248, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_22_2(bytes22 self, uint8 offset) internal pure returns (bytes2 result) { if (offset > 20) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(240, not(0))) } } function replace_22_2(bytes22 self, bytes2 value, uint8 offset) internal pure returns (bytes22 result) { bytes2 oldValue = extract_22_2(self, offset); assembly ("memory-safe") { value := and(value, shl(240, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_22_4(bytes22 self, uint8 offset) internal pure returns (bytes4 result) { if (offset > 18) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(224, not(0))) } } function replace_22_4(bytes22 self, bytes4 value, uint8 offset) internal pure returns (bytes22 result) { bytes4 oldValue = extract_22_4(self, offset); assembly ("memory-safe") { value := and(value, shl(224, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_22_6(bytes22 self, uint8 offset) internal pure returns (bytes6 result) { if (offset > 16) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(208, not(0))) } } function replace_22_6(bytes22 self, bytes6 value, uint8 offset) internal pure returns (bytes22 result) { bytes6 oldValue = extract_22_6(self, offset); assembly ("memory-safe") { value := and(value, shl(208, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_22_8(bytes22 self, uint8 offset) internal pure returns (bytes8 result) { if (offset > 14) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(192, not(0))) } } function replace_22_8(bytes22 self, bytes8 value, uint8 offset) internal pure returns (bytes22 result) { bytes8 oldValue = extract_22_8(self, offset); assembly ("memory-safe") { value := and(value, shl(192, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_22_10(bytes22 self, uint8 offset) internal pure returns (bytes10 result) { if (offset > 12) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(176, not(0))) } } function replace_22_10(bytes22 self, bytes10 value, uint8 offset) internal pure returns (bytes22 result) { bytes10 oldValue = extract_22_10(self, offset); assembly ("memory-safe") { value := and(value, shl(176, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_22_12(bytes22 self, uint8 offset) internal pure returns (bytes12 result) { if (offset > 10) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(160, not(0))) } } function replace_22_12(bytes22 self, bytes12 value, uint8 offset) internal pure returns (bytes22 result) { bytes12 oldValue = extract_22_12(self, offset); assembly ("memory-safe") { value := and(value, shl(160, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_22_16(bytes22 self, uint8 offset) internal pure returns (bytes16 result) { if (offset > 6) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(128, not(0))) } } function replace_22_16(bytes22 self, bytes16 value, uint8 offset) internal pure returns (bytes22 result) { bytes16 oldValue = extract_22_16(self, offset); assembly ("memory-safe") { value := and(value, shl(128, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_22_20(bytes22 self, uint8 offset) internal pure returns (bytes20 result) { if (offset > 2) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(96, not(0))) } } function replace_22_20(bytes22 self, bytes20 value, uint8 offset) internal pure returns (bytes22 result) { bytes20 oldValue = extract_22_20(self, offset); assembly ("memory-safe") { value := and(value, shl(96, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_24_1(bytes24 self, uint8 offset) internal pure returns (bytes1 result) { if (offset > 23) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(248, not(0))) } } function replace_24_1(bytes24 self, bytes1 value, uint8 offset) internal pure returns (bytes24 result) { bytes1 oldValue = extract_24_1(self, offset); assembly ("memory-safe") { value := and(value, shl(248, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_24_2(bytes24 self, uint8 offset) internal pure returns (bytes2 result) { if (offset > 22) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(240, not(0))) } } function replace_24_2(bytes24 self, bytes2 value, uint8 offset) internal pure returns (bytes24 result) { bytes2 oldValue = extract_24_2(self, offset); assembly ("memory-safe") { value := and(value, shl(240, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_24_4(bytes24 self, uint8 offset) internal pure returns (bytes4 result) { if (offset > 20) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(224, not(0))) } } function replace_24_4(bytes24 self, bytes4 value, uint8 offset) internal pure returns (bytes24 result) { bytes4 oldValue = extract_24_4(self, offset); assembly ("memory-safe") { value := and(value, shl(224, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_24_6(bytes24 self, uint8 offset) internal pure returns (bytes6 result) { if (offset > 18) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(208, not(0))) } } function replace_24_6(bytes24 self, bytes6 value, uint8 offset) internal pure returns (bytes24 result) { bytes6 oldValue = extract_24_6(self, offset); assembly ("memory-safe") { value := and(value, shl(208, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_24_8(bytes24 self, uint8 offset) internal pure returns (bytes8 result) { if (offset > 16) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(192, not(0))) } } function replace_24_8(bytes24 self, bytes8 value, uint8 offset) internal pure returns (bytes24 result) { bytes8 oldValue = extract_24_8(self, offset); assembly ("memory-safe") { value := and(value, shl(192, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_24_10(bytes24 self, uint8 offset) internal pure returns (bytes10 result) { if (offset > 14) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(176, not(0))) } } function replace_24_10(bytes24 self, bytes10 value, uint8 offset) internal pure returns (bytes24 result) { bytes10 oldValue = extract_24_10(self, offset); assembly ("memory-safe") { value := and(value, shl(176, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_24_12(bytes24 self, uint8 offset) internal pure returns (bytes12 result) { if (offset > 12) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(160, not(0))) } } function replace_24_12(bytes24 self, bytes12 value, uint8 offset) internal pure returns (bytes24 result) { bytes12 oldValue = extract_24_12(self, offset); assembly ("memory-safe") { value := and(value, shl(160, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_24_16(bytes24 self, uint8 offset) internal pure returns (bytes16 result) { if (offset > 8) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(128, not(0))) } } function replace_24_16(bytes24 self, bytes16 value, uint8 offset) internal pure returns (bytes24 result) { bytes16 oldValue = extract_24_16(self, offset); assembly ("memory-safe") { value := and(value, shl(128, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_24_20(bytes24 self, uint8 offset) internal pure returns (bytes20 result) { if (offset > 4) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(96, not(0))) } } function replace_24_20(bytes24 self, bytes20 value, uint8 offset) internal pure returns (bytes24 result) { bytes20 oldValue = extract_24_20(self, offset); assembly ("memory-safe") { value := and(value, shl(96, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_24_22(bytes24 self, uint8 offset) internal pure returns (bytes22 result) { if (offset > 2) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(80, not(0))) } } function replace_24_22(bytes24 self, bytes22 value, uint8 offset) internal pure returns (bytes24 result) { bytes22 oldValue = extract_24_22(self, offset); assembly ("memory-safe") { value := and(value, shl(80, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_28_1(bytes28 self, uint8 offset) internal pure returns (bytes1 result) { if (offset > 27) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(248, not(0))) } } function replace_28_1(bytes28 self, bytes1 value, uint8 offset) internal pure returns (bytes28 result) { bytes1 oldValue = extract_28_1(self, offset); assembly ("memory-safe") { value := and(value, shl(248, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_28_2(bytes28 self, uint8 offset) internal pure returns (bytes2 result) { if (offset > 26) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(240, not(0))) } } function replace_28_2(bytes28 self, bytes2 value, uint8 offset) internal pure returns (bytes28 result) { bytes2 oldValue = extract_28_2(self, offset); assembly ("memory-safe") { value := and(value, shl(240, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_28_4(bytes28 self, uint8 offset) internal pure returns (bytes4 result) { if (offset > 24) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(224, not(0))) } } function replace_28_4(bytes28 self, bytes4 value, uint8 offset) internal pure returns (bytes28 result) { bytes4 oldValue = extract_28_4(self, offset); assembly ("memory-safe") { value := and(value, shl(224, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_28_6(bytes28 self, uint8 offset) internal pure returns (bytes6 result) { if (offset > 22) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(208, not(0))) } } function replace_28_6(bytes28 self, bytes6 value, uint8 offset) internal pure returns (bytes28 result) { bytes6 oldValue = extract_28_6(self, offset); assembly ("memory-safe") { value := and(value, shl(208, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_28_8(bytes28 self, uint8 offset) internal pure returns (bytes8 result) { if (offset > 20) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(192, not(0))) } } function replace_28_8(bytes28 self, bytes8 value, uint8 offset) internal pure returns (bytes28 result) { bytes8 oldValue = extract_28_8(self, offset); assembly ("memory-safe") { value := and(value, shl(192, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_28_10(bytes28 self, uint8 offset) internal pure returns (bytes10 result) { if (offset > 18) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(176, not(0))) } } function replace_28_10(bytes28 self, bytes10 value, uint8 offset) internal pure returns (bytes28 result) { bytes10 oldValue = extract_28_10(self, offset); assembly ("memory-safe") { value := and(value, shl(176, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_28_12(bytes28 self, uint8 offset) internal pure returns (bytes12 result) { if (offset > 16) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(160, not(0))) } } function replace_28_12(bytes28 self, bytes12 value, uint8 offset) internal pure returns (bytes28 result) { bytes12 oldValue = extract_28_12(self, offset); assembly ("memory-safe") { value := and(value, shl(160, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_28_16(bytes28 self, uint8 offset) internal pure returns (bytes16 result) { if (offset > 12) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(128, not(0))) } } function replace_28_16(bytes28 self, bytes16 value, uint8 offset) internal pure returns (bytes28 result) { bytes16 oldValue = extract_28_16(self, offset); assembly ("memory-safe") { value := and(value, shl(128, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_28_20(bytes28 self, uint8 offset) internal pure returns (bytes20 result) { if (offset > 8) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(96, not(0))) } } function replace_28_20(bytes28 self, bytes20 value, uint8 offset) internal pure returns (bytes28 result) { bytes20 oldValue = extract_28_20(self, offset); assembly ("memory-safe") { value := and(value, shl(96, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_28_22(bytes28 self, uint8 offset) internal pure returns (bytes22 result) { if (offset > 6) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(80, not(0))) } } function replace_28_22(bytes28 self, bytes22 value, uint8 offset) internal pure returns (bytes28 result) { bytes22 oldValue = extract_28_22(self, offset); assembly ("memory-safe") { value := and(value, shl(80, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_28_24(bytes28 self, uint8 offset) internal pure returns (bytes24 result) { if (offset > 4) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(64, not(0))) } } function replace_28_24(bytes28 self, bytes24 value, uint8 offset) internal pure returns (bytes28 result) { bytes24 oldValue = extract_28_24(self, offset); assembly ("memory-safe") { value := and(value, shl(64, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_32_1(bytes32 self, uint8 offset) internal pure returns (bytes1 result) { if (offset > 31) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(248, not(0))) } } function replace_32_1(bytes32 self, bytes1 value, uint8 offset) internal pure returns (bytes32 result) { bytes1 oldValue = extract_32_1(self, offset); assembly ("memory-safe") { value := and(value, shl(248, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_32_2(bytes32 self, uint8 offset) internal pure returns (bytes2 result) { if (offset > 30) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(240, not(0))) } } function replace_32_2(bytes32 self, bytes2 value, uint8 offset) internal pure returns (bytes32 result) { bytes2 oldValue = extract_32_2(self, offset); assembly ("memory-safe") { value := and(value, shl(240, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_32_4(bytes32 self, uint8 offset) internal pure returns (bytes4 result) { if (offset > 28) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(224, not(0))) } } function replace_32_4(bytes32 self, bytes4 value, uint8 offset) internal pure returns (bytes32 result) { bytes4 oldValue = extract_32_4(self, offset); assembly ("memory-safe") { value := and(value, shl(224, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_32_6(bytes32 self, uint8 offset) internal pure returns (bytes6 result) { if (offset > 26) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(208, not(0))) } } function replace_32_6(bytes32 self, bytes6 value, uint8 offset) internal pure returns (bytes32 result) { bytes6 oldValue = extract_32_6(self, offset); assembly ("memory-safe") { value := and(value, shl(208, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_32_8(bytes32 self, uint8 offset) internal pure returns (bytes8 result) { if (offset > 24) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(192, not(0))) } } function replace_32_8(bytes32 self, bytes8 value, uint8 offset) internal pure returns (bytes32 result) { bytes8 oldValue = extract_32_8(self, offset); assembly ("memory-safe") { value := and(value, shl(192, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_32_10(bytes32 self, uint8 offset) internal pure returns (bytes10 result) { if (offset > 22) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(176, not(0))) } } function replace_32_10(bytes32 self, bytes10 value, uint8 offset) internal pure returns (bytes32 result) { bytes10 oldValue = extract_32_10(self, offset); assembly ("memory-safe") { value := and(value, shl(176, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_32_12(bytes32 self, uint8 offset) internal pure returns (bytes12 result) { if (offset > 20) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(160, not(0))) } } function replace_32_12(bytes32 self, bytes12 value, uint8 offset) internal pure returns (bytes32 result) { bytes12 oldValue = extract_32_12(self, offset); assembly ("memory-safe") { value := and(value, shl(160, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_32_16(bytes32 self, uint8 offset) internal pure returns (bytes16 result) { if (offset > 16) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(128, not(0))) } } function replace_32_16(bytes32 self, bytes16 value, uint8 offset) internal pure returns (bytes32 result) { bytes16 oldValue = extract_32_16(self, offset); assembly ("memory-safe") { value := and(value, shl(128, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_32_20(bytes32 self, uint8 offset) internal pure returns (bytes20 result) { if (offset > 12) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(96, not(0))) } } function replace_32_20(bytes32 self, bytes20 value, uint8 offset) internal pure returns (bytes32 result) { bytes20 oldValue = extract_32_20(self, offset); assembly ("memory-safe") { value := and(value, shl(96, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_32_22(bytes32 self, uint8 offset) internal pure returns (bytes22 result) { if (offset > 10) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(80, not(0))) } } function replace_32_22(bytes32 self, bytes22 value, uint8 offset) internal pure returns (bytes32 result) { bytes22 oldValue = extract_32_22(self, offset); assembly ("memory-safe") { value := and(value, shl(80, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_32_24(bytes32 self, uint8 offset) internal pure returns (bytes24 result) { if (offset > 8) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(64, not(0))) } } function replace_32_24(bytes32 self, bytes24 value, uint8 offset) internal pure returns (bytes32 result) { bytes24 oldValue = extract_32_24(self, offset); assembly ("memory-safe") { value := and(value, shl(64, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } function extract_32_28(bytes32 self, uint8 offset) internal pure returns (bytes28 result) { if (offset > 4) revert OutOfRangeAccess(); assembly ("memory-safe") { result := and(shl(mul(8, offset), self), shl(32, not(0))) } } function replace_32_28(bytes32 self, bytes28 value, uint8 offset) internal pure returns (bytes32 result) { bytes28 oldValue = extract_32_28(self, offset); assembly ("memory-safe") { value := and(value, shl(32, not(0))) result := xor(self, shr(mul(8, offset), xor(oldValue, value))) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.20; /** * @title ERC-721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC-721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be * reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/utils/ERC1155Holder.sol) pragma solidity ^0.8.20; import {IERC165, ERC165} from "../../../utils/introspection/ERC165.sol"; import {IERC1155Receiver} from "../IERC1155Receiver.sol"; /** * @dev Simple implementation of `IERC1155Receiver` that will allow a contract to hold ERC-1155 tokens. * * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be * stuck. */ abstract contract ERC1155Holder is ERC165, IERC1155Receiver { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId); } function onERC1155Received( address, address, uint256, uint256, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] memory, uint256[] memory, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/utils/ERC721Holder.sol) pragma solidity ^0.8.20; import {IERC721Receiver} from "../IERC721Receiver.sol"; /** * @dev Implementation of the {IERC721Receiver} interface. * * Accepts all token transfers. * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or * {IERC721-setApprovalForAll}. */ abstract contract ERC721Holder is IERC721Receiver { /** * @dev See {IERC721Receiver-onERC721Received}. * * Always returns `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) { return this.onERC721Received.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/MessageHashUtils.sol) pragma solidity ^0.8.20; import {Strings} from "../Strings.sol"; /** * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. * * The library provides methods for generating a hash of a message that conforms to the * https://eips.ethereum.org/EIPS/eip-191[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] * specifications. */ library MessageHashUtils { /** * @dev Returns the keccak256 digest of an ERC-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing a bytes32 `messageHash` with * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with * keccak256, although any bytes32 value can be safely used because the final digest will * be re-hashed. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { assembly ("memory-safe") { mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) } } /** * @dev Returns the keccak256 digest of an ERC-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing an arbitrary `message` with * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { return keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); } /** * @dev Returns the keccak256 digest of an ERC-191 signed data with version * `0x00` (data with intended validator). * * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended * `validator` address. Then hashing the result. * * See {ECDSA-recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked(hex"19_00", validator, data)); } /** * @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`). * * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with * `\x19\x01` and hashing the result. It corresponds to the hash signed by the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. * * See {ECDSA-recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { assembly ("memory-safe") { let ptr := mload(0x40) mstore(ptr, hex"19_01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) digest := keccak256(ptr, 0x42) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol) pragma solidity ^0.8.20; interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.2.0) (interfaces/draft-IERC4337.sol) pragma solidity ^0.8.20; /** * @dev A https://github.com/ethereum/ercs/blob/master/ERCS/erc-4337.md#useroperation[user operation] is composed of the following elements: * - `sender` (`address`): The account making the operation * - `nonce` (`uint256`): Anti-replay parameter (see “Semi-abstracted Nonce Support” ) * - `factory` (`address`): account factory, only for new accounts * - `factoryData` (`bytes`): data for account factory (only if account factory exists) * - `callData` (`bytes`): The data to pass to the sender during the main execution call * - `callGasLimit` (`uint256`): The amount of gas to allocate the main execution call * - `verificationGasLimit` (`uint256`): The amount of gas to allocate for the verification step * - `preVerificationGas` (`uint256`): Extra gas to pay the bundler * - `maxFeePerGas` (`uint256`): Maximum fee per gas (similar to EIP-1559 max_fee_per_gas) * - `maxPriorityFeePerGas` (`uint256`): Maximum priority fee per gas (similar to EIP-1559 max_priority_fee_per_gas) * - `paymaster` (`address`): Address of paymaster contract, (or empty, if account pays for itself) * - `paymasterVerificationGasLimit` (`uint256`): The amount of gas to allocate for the paymaster validation code * - `paymasterPostOpGasLimit` (`uint256`): The amount of gas to allocate for the paymaster post-operation code * - `paymasterData` (`bytes`): Data for paymaster (only if paymaster exists) * - `signature` (`bytes`): Data passed into the account to verify authorization * * When passed to on-chain contacts, the following packed version is used. * - `sender` (`address`) * - `nonce` (`uint256`) * - `initCode` (`bytes`): concatenation of factory address and factoryData (or empty) * - `callData` (`bytes`) * - `accountGasLimits` (`bytes32`): concatenation of verificationGas (16 bytes) and callGas (16 bytes) * - `preVerificationGas` (`uint256`) * - `gasFees` (`bytes32`): concatenation of maxPriorityFeePerGas (16 bytes) and maxFeePerGas (16 bytes) * - `paymasterAndData` (`bytes`): concatenation of paymaster fields (or empty) * - `signature` (`bytes`) */ struct PackedUserOperation { address sender; uint256 nonce; bytes initCode; // `abi.encodePacked(factory, factoryData)` bytes callData; bytes32 accountGasLimits; // `abi.encodePacked(verificationGasLimit, callGasLimit)` 16 bytes each uint256 preVerificationGas; bytes32 gasFees; // `abi.encodePacked(maxPriorityFeePerGas, maxFeePerGas)` 16 bytes each bytes paymasterAndData; // `abi.encodePacked(paymaster, paymasterVerificationGasLimit, paymasterPostOpGasLimit, paymasterData)` (20 bytes, 16 bytes, 16 bytes, dynamic) bytes signature; } /** * @dev Aggregates and validates multiple signatures for a batch of user operations. * * A contract could implement this interface with custom validation schemes that allow signature aggregation, * enabling significant optimizations and gas savings for execution and transaction data cost. * * Bundlers and clients whitelist supported aggregators. * * See https://eips.ethereum.org/EIPS/eip-7766[ERC-7766] */ interface IAggregator { /** * @dev Validates the signature for a user operation. * Returns an alternative signature that should be used during bundling. */ function validateUserOpSignature( PackedUserOperation calldata userOp ) external view returns (bytes memory sigForUserOp); /** * @dev Returns an aggregated signature for a batch of user operation's signatures. */ function aggregateSignatures( PackedUserOperation[] calldata userOps ) external view returns (bytes memory aggregatesSignature); /** * @dev Validates that the aggregated signature is valid for the user operations. * * Requirements: * * - The aggregated signature MUST match the given list of operations. */ function validateSignatures(PackedUserOperation[] calldata userOps, bytes calldata signature) external view; } /** * @dev Handle nonce management for accounts. * * Nonces are used in accounts as a replay protection mechanism and to ensure the order of user operations. * To avoid limiting the number of operations an account can perform, the interface allows using parallel * nonces by using a `key` parameter. * * See https://eips.ethereum.org/EIPS/eip-4337#semi-abstracted-nonce-support[ERC-4337 semi-abstracted nonce support]. */ interface IEntryPointNonces { /** * @dev Returns the nonce for a `sender` account and a `key`. * * Nonces for a certain `key` are always increasing. */ function getNonce(address sender, uint192 key) external view returns (uint256 nonce); } /** * @dev Handle stake management for entities (i.e. accounts, paymasters, factories). * * The EntryPoint must implement the following API to let entities like paymasters have a stake, * and thus have more flexibility in their storage access * (see https://eips.ethereum.org/EIPS/eip-4337#reputation-scoring-and-throttlingbanning-for-global-entities[reputation, throttling and banning.]) */ interface IEntryPointStake { /** * @dev Returns the balance of the account. */ function balanceOf(address account) external view returns (uint256); /** * @dev Deposits `msg.value` to the account. */ function depositTo(address account) external payable; /** * @dev Withdraws `withdrawAmount` from the account to `withdrawAddress`. */ function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external; /** * @dev Adds stake to the account with an unstake delay of `unstakeDelaySec`. */ function addStake(uint32 unstakeDelaySec) external payable; /** * @dev Unlocks the stake of the account. */ function unlockStake() external; /** * @dev Withdraws the stake of the account to `withdrawAddress`. */ function withdrawStake(address payable withdrawAddress) external; } /** * @dev Entry point for user operations. * * User operations are validated and executed by this contract. */ interface IEntryPoint is IEntryPointNonces, IEntryPointStake { /** * @dev A user operation at `opIndex` failed with `reason`. */ error FailedOp(uint256 opIndex, string reason); /** * @dev A user operation at `opIndex` failed with `reason` and `inner` returned data. */ error FailedOpWithRevert(uint256 opIndex, string reason, bytes inner); /** * @dev Batch of aggregated user operations per aggregator. */ struct UserOpsPerAggregator { PackedUserOperation[] userOps; IAggregator aggregator; bytes signature; } /** * @dev Executes a batch of user operations. * @param beneficiary Address to which gas is refunded up completing the execution. */ function handleOps(PackedUserOperation[] calldata ops, address payable beneficiary) external; /** * @dev Executes a batch of aggregated user operations per aggregator. * @param beneficiary Address to which gas is refunded up completing the execution. */ function handleAggregatedOps( UserOpsPerAggregator[] calldata opsPerAggregator, address payable beneficiary ) external; } /** * @dev Base interface for an ERC-4337 account. */ interface IAccount { /** * @dev Validates a user operation. * * * MUST validate the caller is a trusted EntryPoint * * MUST validate that the signature is a valid signature of the userOpHash, and SHOULD * return SIG_VALIDATION_FAILED (and not revert) on signature mismatch. Any other error MUST revert. * * MUST pay the entryPoint (caller) at least the “missingAccountFunds” (which might * be zero, in case the current account’s deposit is high enough) * * Returns an encoded packed validation data that is composed of the following elements: * * - `authorizer` (`address`): 0 for success, 1 for failure, otherwise the address of an authorizer contract * - `validUntil` (`uint48`): The UserOp is valid only up to this time. Zero for “infinite”. * - `validAfter` (`uint48`): The UserOp is valid only after this time. */ function validateUserOp( PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds ) external returns (uint256 validationData); } /** * @dev Support for executing user operations by prepending the {executeUserOp} function selector * to the UserOperation's `callData`. */ interface IAccountExecute { /** * @dev Executes a user operation. */ function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external; } /** * @dev Interface for a paymaster contract that agrees to pay for the gas costs of a user operation. * * NOTE: A paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction. */ interface IPaymaster { enum PostOpMode { opSucceeded, opReverted, postOpReverted } /** * @dev Validates whether the paymaster is willing to pay for the user operation. See * {IAccount-validateUserOp} for additional information on the return value. * * NOTE: Bundlers will reject this method if it modifies the state, unless it's whitelisted. */ function validatePaymasterUserOp( PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost ) external returns (bytes memory context, uint256 validationData); /** * @dev Verifies the sender is the entrypoint. * @param actualGasCost the actual amount paid (by account or paymaster) for this UserOperation * @param actualUserOpFeePerGas total gas used by this UserOperation (including preVerification, creation, validation and execution) */ function postOp( PostOpMode mode, bytes calldata context, uint256 actualGasCost, uint256 actualUserOpFeePerGas ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Interface that must be implemented by smart contracts in order to receive * ERC-1155 token transfers. */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC-1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC-1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.2.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SafeCast} from "./math/SafeCast.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { using SafeCast for *; bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev The string being parsed contains characters that are not in scope of the given base. */ error StringsInvalidChar(); /** * @dev The string being parsed is not a properly formatted address. */ error StringsInvalidAddressFormat(); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; assembly ("memory-safe") { ptr := add(buffer, add(32, length)) } while (true) { ptr--; assembly ("memory-safe") { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal * representation, according to EIP-55. */ function toChecksumHexString(address addr) internal pure returns (string memory) { bytes memory buffer = bytes(toHexString(addr)); // hash the hex part of buffer (skip length + 2 bytes, length 40) uint256 hashValue; assembly ("memory-safe") { hashValue := shr(96, keccak256(add(buffer, 0x22), 40)) } for (uint256 i = 41; i > 1; --i) { // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f) if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) { // case shift by xoring with 0x20 buffer[i] ^= 0x20; } hashValue >>= 4; } return string(buffer); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } /** * @dev Parse a decimal string and returns the value as a `uint256`. * * Requirements: * - The string must be formatted as `[0-9]*` * - The result must fit into an `uint256` type */ function parseUint(string memory input) internal pure returns (uint256) { return parseUint(input, 0, bytes(input).length); } /** * @dev Variant of {parseUint} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `[0-9]*` * - The result must fit into an `uint256` type */ function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) { (bool success, uint256 value) = tryParseUint(input, begin, end); if (!success) revert StringsInvalidChar(); return value; } /** * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) { return _tryParseUintUncheckedBounds(input, 0, bytes(input).length); } /** * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid * character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseUint( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, uint256 value) { if (end > bytes(input).length || begin > end) return (false, 0); return _tryParseUintUncheckedBounds(input, begin, end); } /** * @dev Implementation of {tryParseUint} that does not check bounds. Caller should make sure that * `begin <= end <= input.length`. Other inputs would result in undefined behavior. */ function _tryParseUintUncheckedBounds( string memory input, uint256 begin, uint256 end ) private pure returns (bool success, uint256 value) { bytes memory buffer = bytes(input); uint256 result = 0; for (uint256 i = begin; i < end; ++i) { uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i))); if (chr > 9) return (false, 0); result *= 10; result += chr; } return (true, result); } /** * @dev Parse a decimal string and returns the value as a `int256`. * * Requirements: * - The string must be formatted as `[-+]?[0-9]*` * - The result must fit in an `int256` type. */ function parseInt(string memory input) internal pure returns (int256) { return parseInt(input, 0, bytes(input).length); } /** * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `[-+]?[0-9]*` * - The result must fit in an `int256` type. */ function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) { (bool success, int256 value) = tryParseInt(input, begin, end); if (!success) revert StringsInvalidChar(); return value; } /** * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if * the result does not fit in a `int256`. * * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`. */ function tryParseInt(string memory input) internal pure returns (bool success, int256 value) { return _tryParseIntUncheckedBounds(input, 0, bytes(input).length); } uint256 private constant ABS_MIN_INT256 = 2 ** 255; /** * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid * character or if the result does not fit in a `int256`. * * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`. */ function tryParseInt( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, int256 value) { if (end > bytes(input).length || begin > end) return (false, 0); return _tryParseIntUncheckedBounds(input, begin, end); } /** * @dev Implementation of {tryParseInt} that does not check bounds. Caller should make sure that * `begin <= end <= input.length`. Other inputs would result in undefined behavior. */ function _tryParseIntUncheckedBounds( string memory input, uint256 begin, uint256 end ) private pure returns (bool success, int256 value) { bytes memory buffer = bytes(input); // Check presence of a negative sign. bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty bool positiveSign = sign == bytes1("+"); bool negativeSign = sign == bytes1("-"); uint256 offset = (positiveSign || negativeSign).toUint(); (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end); if (absSuccess && absValue < ABS_MIN_INT256) { return (true, negativeSign ? -int256(absValue) : int256(absValue)); } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) { return (true, type(int256).min); } else return (false, 0); } /** * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as a `uint256`. * * Requirements: * - The string must be formatted as `(0x)?[0-9a-fA-F]*` * - The result must fit in an `uint256` type. */ function parseHexUint(string memory input) internal pure returns (uint256) { return parseHexUint(input, 0, bytes(input).length); } /** * @dev Variant of {parseHexUint} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `(0x)?[0-9a-fA-F]*` * - The result must fit in an `uint256` type. */ function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) { (bool success, uint256 value) = tryParseHexUint(input, begin, end); if (!success) revert StringsInvalidChar(); return value; } /** * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) { return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length); } /** * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an * invalid character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseHexUint( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, uint256 value) { if (end > bytes(input).length || begin > end) return (false, 0); return _tryParseHexUintUncheckedBounds(input, begin, end); } /** * @dev Implementation of {tryParseHexUint} that does not check bounds. Caller should make sure that * `begin <= end <= input.length`. Other inputs would result in undefined behavior. */ function _tryParseHexUintUncheckedBounds( string memory input, uint256 begin, uint256 end ) private pure returns (bool success, uint256 value) { bytes memory buffer = bytes(input); // skip 0x prefix if present 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 uint256 offset = hasPrefix.toUint() * 2; uint256 result = 0; for (uint256 i = begin + offset; i < end; ++i) { uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i))); if (chr > 15) return (false, 0); result *= 16; unchecked { // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check). // This guaratees that adding a value < 16 will not cause an overflow, hence the unchecked. result += chr; } } return (true, result); } /** * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`. * * Requirements: * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}` */ function parseAddress(string memory input) internal pure returns (address) { return parseAddress(input, 0, bytes(input).length); } /** * @dev Variant of {parseAddress} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}` */ function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) { (bool success, address value) = tryParseAddress(input, begin, end); if (!success) revert StringsInvalidAddressFormat(); return value; } /** * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly * formatted address. See {parseAddress} requirements. */ function tryParseAddress(string memory input) internal pure returns (bool success, address value) { return tryParseAddress(input, 0, bytes(input).length); } /** * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly * formatted address. See {parseAddress} requirements. */ function tryParseAddress( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, address value) { if (end > bytes(input).length || begin > end) return (false, address(0)); 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 uint256 expectedLength = 40 + hasPrefix.toUint() * 2; // check that input is the correct length if (end - begin == expectedLength) { // length guarantees that this does not overflow, and value is at most type(uint160).max (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end); return (s, address(uint160(v))); } else { return (false, address(0)); } } function _tryParseChr(bytes1 chr) private pure returns (uint8) { uint8 value = uint8(chr); // Try to parse `chr`: // - Case 1: [0-9] // - Case 2: [a-f] // - Case 3: [A-F] // - otherwise not supported unchecked { if (value > 47 && value < 58) value -= 48; else if (value > 96 && value < 103) value -= 87; else if (value > 64 && value < 71) value -= 55; else return type(uint8).max; } return value; } /** * @dev Reads a bytes32 from a bytes array without bounds checking. * * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the * assembly block as such would prevent some optimizations. */ function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) { // This is not memory safe in the general case, but all calls to this private function are within bounds. assembly ("memory-safe") { value := mload(add(buffer, add(0x20, offset))) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/Math.sol) pragma solidity ^0.8.20; import {Panic} from "../Panic.sol"; import {SafeCast} from "./SafeCast.sol"; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an success flag (no overflow). */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow). */ function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow). */ function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a success flag (no division by zero). */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero). */ function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute * one branch when needed, making this function more expensive. */ function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) { unchecked { // branchless ternary works because: // b ^ (a ^ b) == a // b ^ 0 == b return b ^ ((a ^ b) * SafeCast.toUint(condition)); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(a > b, a, b); } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(a < b, a, b); } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. Panic.panic(Panic.DIVISION_BY_ZERO); } // The following calculation ensures accurate ceiling division without overflow. // Since a is non-zero, (a - 1) / b will not overflow. // The largest possible result occurs when (a - 1) / b is type(uint256).max, // but the largest value we can obtain is type(uint256).max - 1, which happens // when a = type(uint256).max and b = 1. unchecked { return SafeCast.toUint(a > 0) * ((a - 1) / b + 1); } } /** * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2²⁵⁶ + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0. if (denominator <= prod1) { Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW)); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv ≡ 1 mod 2⁴. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2⁸ inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶ inverse *= 2 - denominator * inverse; // inverse mod 2³² inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴ inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸ inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶ // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @dev Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0); } /** * @dev Calculate the modular multiplicative inverse of a number in Z/nZ. * * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0. * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible. * * If the input value is not inversible, 0 is returned. * * 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 * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}. */ function invMod(uint256 a, uint256 n) internal pure returns (uint256) { unchecked { if (n == 0) return 0; // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version) // Used to compute integers x and y such that: ax + ny = gcd(a, n). // When the gcd is 1, then the inverse of a modulo n exists and it's x. // ax + ny = 1 // ax = 1 + (-y)n // ax ≡ 1 (mod n) # x is the inverse of a modulo n // If the remainder is 0 the gcd is n right away. uint256 remainder = a % n; uint256 gcd = n; // Therefore the initial coefficients are: // ax + ny = gcd(a, n) = n // 0a + 1n = n int256 x = 0; int256 y = 1; while (remainder != 0) { uint256 quotient = gcd / remainder; (gcd, remainder) = ( // The old remainder is the next gcd to try. remainder, // Compute the next remainder. // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd // where gcd is at most n (capped to type(uint256).max) gcd - remainder * quotient ); (x, y) = ( // Increment the coefficient of a. y, // Decrement the coefficient of n. // Can overflow, but the result is casted to uint256 so that the // next value of y is "wrapped around" to a value between 0 and n - 1. x - y * int256(quotient) ); } if (gcd != 1) return 0; // No inverse exists. return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative. } } /** * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`. * * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that * `a**(p-2)` is the modular multiplicative inverse of a in Fp. * * NOTE: this function does NOT check that `p` is a prime greater than `2`. */ function invModPrime(uint256 a, uint256 p) internal view returns (uint256) { unchecked { return Math.modExp(a, p - 2, p); } } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m) * * Requirements: * - modulus can't be zero * - underlying staticcall to precompile must succeed * * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make * sure the chain you're using it on supports the precompiled contract for modular exponentiation * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, * the underlying function will succeed given the lack of a revert, but the result may be incorrectly * interpreted as 0. */ function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) { (bool success, uint256 result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m). * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying * to operate modulo 0 or if the underlying precompile reverted. * * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack * of a revert, but the result may be incorrectly interpreted as 0. */ function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) { if (m == 0) return (false, 0); assembly ("memory-safe") { let ptr := mload(0x40) // | Offset | Content | Content (Hex) | // |-----------|------------|--------------------------------------------------------------------| // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x60:0x7f | value of b | 0x<.............................................................b> | // | 0x80:0x9f | value of e | 0x<.............................................................e> | // | 0xa0:0xbf | value of m | 0x<.............................................................m> | mstore(ptr, 0x20) mstore(add(ptr, 0x20), 0x20) mstore(add(ptr, 0x40), 0x20) mstore(add(ptr, 0x60), b) mstore(add(ptr, 0x80), e) mstore(add(ptr, 0xa0), m) // Given the result < m, it's guaranteed to fit in 32 bytes, // so we can use the memory scratch space located at offset 0. success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20) result := mload(0x00) } } /** * @dev Variant of {modExp} that supports inputs of arbitrary length. */ function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) { (bool success, bytes memory result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Variant of {tryModExp} that supports inputs of arbitrary length. */ function tryModExp( bytes memory b, bytes memory e, bytes memory m ) internal view returns (bool success, bytes memory result) { if (_zeroBytes(m)) return (false, new bytes(0)); uint256 mLen = m.length; // Encode call args in result and move the free memory pointer result = abi.encodePacked(b.length, e.length, mLen, b, e, m); assembly ("memory-safe") { let dataPtr := add(result, 0x20) // Write result on top of args to avoid allocating extra memory. success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen) // Overwrite the length. // result.length > returndatasize() is guaranteed because returndatasize() == m.length mstore(result, mLen) // Set the memory pointer after the returned data. mstore(0x40, add(dataPtr, mLen)) } } /** * @dev Returns whether the provided byte array is zero. */ function _zeroBytes(bytes memory byteArray) private pure returns (bool) { for (uint256 i = 0; i < byteArray.length; ++i) { if (byteArray[i] != 0) { return false; } } return true; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * This method is based on Newton's method for computing square roots; the algorithm is restricted to only * using integer operations. */ function sqrt(uint256 a) internal pure returns (uint256) { unchecked { // Take care of easy edge cases when a == 0 or a == 1 if (a <= 1) { return a; } // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between // the current value as `ε_n = | x_n - sqrt(a) |`. // // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is // bigger than any uint256. // // By noticing that // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)` // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar // to the msb function. uint256 aa = a; uint256 xn = 1; if (aa >= (1 << 128)) { aa >>= 128; xn <<= 64; } if (aa >= (1 << 64)) { aa >>= 64; xn <<= 32; } if (aa >= (1 << 32)) { aa >>= 32; xn <<= 16; } if (aa >= (1 << 16)) { aa >>= 16; xn <<= 8; } if (aa >= (1 << 8)) { aa >>= 8; xn <<= 4; } if (aa >= (1 << 4)) { aa >>= 4; xn <<= 2; } if (aa >= (1 << 2)) { xn <<= 1; } // 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). // // We can refine our estimation by noticing that the middle of that interval minimizes the error. // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2). // This is going to be our x_0 (and ε_0) xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2) // From here, Newton's method give us: // x_{n+1} = (x_n + a / x_n) / 2 // // One should note that: // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a // = ((x_n² + a) / (2 * x_n))² - a // = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a // = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²) // = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²) // = (x_n² - a)² / (2 * x_n)² // = ((x_n² - a) / (2 * x_n))² // ≥ 0 // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n // // This gives us the proof of quadratic convergence of the sequence: // ε_{n+1} = | x_{n+1} - sqrt(a) | // = | (x_n + a / x_n) / 2 - sqrt(a) | // = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) | // = | (x_n - sqrt(a))² / (2 * x_n) | // = | ε_n² / (2 * x_n) | // = ε_n² / | (2 * x_n) | // // For the first iteration, we have a special case where x_0 is known: // ε_1 = ε_0² / | (2 * x_0) | // ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2))) // ≤ 2**(2*e-4) / (3 * 2**(e-1)) // ≤ 2**(e-3) / 3 // ≤ 2**(e-3-log2(3)) // ≤ 2**(e-4.5) // // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n: // ε_{n+1} = ε_n² / | (2 * x_n) | // ≤ (2**(e-k))² / (2 * 2**(e-1)) // ≤ 2**(2*e-2*k) / 2**e // ≤ 2**(e-2*k) xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5 xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9 xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18 xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36 xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72 // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either // sqrt(a) or sqrt(a) + 1. return xn - SafeCast.toUint(xn > a / xn); } } /** * @dev Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; uint256 exp; unchecked { exp = 128 * SafeCast.toUint(value > (1 << 128) - 1); value >>= exp; result += exp; exp = 64 * SafeCast.toUint(value > (1 << 64) - 1); value >>= exp; result += exp; exp = 32 * SafeCast.toUint(value > (1 << 32) - 1); value >>= exp; result += exp; exp = 16 * SafeCast.toUint(value > (1 << 16) - 1); value >>= exp; result += exp; exp = 8 * SafeCast.toUint(value > (1 << 8) - 1); value >>= exp; result += exp; exp = 4 * SafeCast.toUint(value > (1 << 4) - 1); value >>= exp; result += exp; exp = 2 * SafeCast.toUint(value > (1 << 2) - 1); value >>= exp; result += exp; result += SafeCast.toUint(value > 1); } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; uint256 isGt; unchecked { isGt = SafeCast.toUint(value > (1 << 128) - 1); value >>= isGt * 128; result += isGt * 16; isGt = SafeCast.toUint(value > (1 << 64) - 1); value >>= isGt * 64; result += isGt * 8; isGt = SafeCast.toUint(value > (1 << 32) - 1); value >>= isGt * 32; result += isGt * 4; isGt = SafeCast.toUint(value > (1 << 16) - 1); value >>= isGt * 16; result += isGt * 2; result += SafeCast.toUint(value > (1 << 8) - 1); } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, value); } } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, value); } } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, value); } } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, value); } } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, value); } } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, value); } } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, value); } } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, value); } } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, value); } } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, value); } } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, value); } } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, value); } } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, value); } } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, value); } } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, value); } } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, value); } } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, value); } } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, value); } } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, value); } } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, value); } } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, value); } } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, value); } } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, value); } } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, value); } } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, value); } } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, value); } } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, value); } } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, value); } } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, value); } } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, value); } } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } /** * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. */ function toUint(bool b) internal pure returns (uint256 u) { assembly ("memory-safe") { u := iszero(iszero(b)) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; import {SafeCast} from "./SafeCast.sol"; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute * one branch when needed, making this function more expensive. */ function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) { unchecked { // branchless ternary works because: // b ^ (a ^ b) == a // b ^ 0 == b return b ^ ((a ^ b) * int256(SafeCast.toUint(condition))); } } /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return ternary(a > b, a, b); } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return ternary(a < b, a, b); } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson. // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift, // taking advantage of the most significant (or "sign" bit) in two's complement representation. // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result, // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative). int256 mask = n >> 255; // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it. return uint256((n + mask) ^ mask); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol) pragma solidity ^0.8.20; /** * @dev Helper library for emitting standardized panic codes. * * ```solidity * contract Example { * using Panic for uint256; * * // Use any of the declared internal constants * function foo() { Panic.GENERIC.panic(); } * * // Alternatively * function foo() { Panic.panic(Panic.GENERIC); } * } * ``` * * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil]. * * _Available since v5.1._ */ // slither-disable-next-line unused-state library Panic { /// @dev generic / unspecified error uint256 internal constant GENERIC = 0x00; /// @dev used by the assert() builtin uint256 internal constant ASSERT = 0x01; /// @dev arithmetic underflow or overflow uint256 internal constant UNDER_OVERFLOW = 0x11; /// @dev division or modulo by zero uint256 internal constant DIVISION_BY_ZERO = 0x12; /// @dev enum conversion error uint256 internal constant ENUM_CONVERSION_ERROR = 0x21; /// @dev invalid encoding in storage uint256 internal constant STORAGE_ENCODING_ERROR = 0x22; /// @dev empty array pop uint256 internal constant EMPTY_ARRAY_POP = 0x31; /// @dev array out of bounds access uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32; /// @dev resource error (too large allocation or too large array) uint256 internal constant RESOURCE_ERROR = 0x41; /// @dev calling invalid internal function uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51; /// @dev Reverts with a panic code. Recommended to use with /// the internal constants with predefined codes. function panic(uint256 code) internal pure { assembly ("memory-safe") { mstore(0x00, 0x4e487b71) mstore(0x20, code) revert(0x1c, 0x24) } } }
{ "remappings": [ "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", "forge-std/=node_modules/forge-std/src/" ], "optimizer": { "enabled": true, "runs": 10000 }, "metadata": { "useLiteralContent": true, "bytecodeHash": "none", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"killswitchContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[],"name":"ERC7579DecodingError","type":"error"},{"inputs":[{"internalType":"CallType","name":"callType","type":"bytes1"}],"name":"ERC7579UnsupportedCallType","type":"error"},{"inputs":[{"internalType":"ExecType","name":"execType","type":"bytes1"}],"name":"ERC7579UnsupportedExecType","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExecutionDataExtractionError","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ExpiredSignature","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[],"name":"InvalidImplementation","type":"error"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"OpDataDecodingError","type":"error"},{"inputs":[],"name":"OutOfRangeAccess","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"UnauthorizedCallContext","type":"error"},{"inputs":[],"name":"UnauthorizedCaller","type":"error"},{"inputs":[],"name":"UnauthorizedExecution","type":"error"},{"inputs":[],"name":"UnsupportedExecutionMode","type":"error"},{"inputs":[{"internalType":"bytes4","name":"modeSelector","type":"bytes4"}],"name":"UnsupportedModeSelector","type":"error"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mode","type":"bytes32"},{"internalType":"bytes","name":"executionData","type":"bytes"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint248","name":"wordPos","type":"uint248"}],"name":"getNonceBitmap","outputs":[{"internalType":"uint256","name":"bitmap","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"invalidateNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"isNonceUsed","outputs":[{"internalType":"bool","name":"isUsed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"isPausedState","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"magicValue","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mode","type":"bytes32"}],"name":"supportsExecutionMode","outputs":[{"internalType":"bool","name":"isSupported","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"isSupported","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
61010080604052346101b257602081611e83803803809161002082856101b7565b8339810103126101b257516001600160a01b038116908190036101b2574660a05260c0516004916020916001600160a01b0316806101ad5750305b604051838101917f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218835246604083015260018060a01b03166060820152606081526100a76080826101b7565b5190206080523060c0528060e05260405192838092635c975abb60e01b82525afa9081156101a15760009161015f575b5061014e57604051611c9290816101f1823960805181611a1f015260a051816119f9015260c0518181816101c60152818161038d015281816104c60152818161060f015281816106cf01528181610754015281816108740152818161155101526119b4015260e05181818161017901526104430152f35b63340aafcd60e11b60005260046000fd5b6020813d602011610199575b81610178602093836101b7565b8101031261019557519081151582036101925750386100d7565b80fd5b5080fd5b3d915061016b565b6040513d6000823e3d90fd5b61005b565b600080fd5b601f909101601f19168101906001600160401b038211908210176101da57604052565b634e487b7160e01b600052604160045260246000fdfe6080806040526004361015610028575b5036156100205761001e61153a565b005b61001e61153a565b60003560e01c90816301ffc9a71461081e57508063150b7a02146107b05780631626ba7e1461072c5780634abb262a1461067b5780635d00bb12146105e457806384b0196e1461049e578063b187bd26146103ef578063b70e36f014610365578063bc197c81146102b5578063d03c791414610284578063e9ae5c531461012c5763f23a6e61146100b9573861000f565b346101275760a0600319360112610127576100d2610990565b506100db6109b3565b5060843567ffffffffffffffff8111610127576100fc903690600401610a7b565b5060206040517ff23a6e61000000000000000000000000000000000000000000000000000000008152f35b600080fd5b61013536610a99565b906040517f5c975abb00000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa90811561027857600091610249575b5061021f5773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630146101f55761001e92610c8a565b7f9f03a0260000000000000000000000000000000000000000000000000000000060005260046000fd5b7fd93c06650000000000000000000000000000000000000000000000000000000060005260046000fd5b61026b915060203d602011610271575b61026381836109d6565b810190610c39565b846101aa565b503d610259565b6040513d6000823e3d90fd5b346101275760206003193601126101275760206102a26004356115ea565b6102ab81610c51565b6040519015158152f35b346101275760a0600319360112610127576102ce610990565b506102d76109b3565b5060443567ffffffffffffffff8111610127576102f8903690600401610b46565b5060643567ffffffffffffffff811161012757610319903690600401610b46565b5060843567ffffffffffffffff81116101275761033a903690600401610a7b565b5060206040517fbc197c81000000000000000000000000000000000000000000000000000000008152f35b346101275760206003193601126101275773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630146101f5573033036103c55761001e600435611579565b7f5c427cd90000000000000000000000000000000000000000000000000000000060005260046000fd5b34610127576000600319360112610127576040517f5c975abb00000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa801561027857602091600091610481575b506040519015158152f35b6104989150823d84116102715761026381836109d6565b82610476565b346101275760006003193601126101275773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630146101f5576105856020604051906104ff81836109d6565b600082526040519061051181836109d6565b6000825261051d6119b2565b73ffffffffffffffffffffffffffffffffffffffff6105936040519461054385876109d6565b6000865260003681376040519788977f0c00000000000000000000000000000000000000000000000000000000000000895260e0878a015260e0890190610aed565b908782036040890152610aed565b91466060870152166080850152600060a085015283810360c085015281808451928381520193019160005b8281106105cd57505050500390f35b8351855286955093810193928101926001016105be565b346101275760206003193601126101275760043573ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630146101f557600160209160ff8160081c9116906000527fb035242b6a1b64fd1e2d869c03a3cc0e80fe7f55db29c2560bab38e489fab70083521b604060002054161515604051908152f35b34610127576020600319360112610127576004357effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168091036101275773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630146101f5576000527fb035242b6a1b64fd1e2d869c03a3cc0e80fe7f55db29c2560bab38e489fab7006020526020604060002054604051908152f35b346101275761073a36610a99565b73ffffffffffffffffffffffffffffffffffffffff9291927f00000000000000000000000000000000000000000000000000000000000000001630146101f55760209261078692610ba3565b7fffffffff0000000000000000000000000000000000000000000000000000000060405191168152f35b34610127576080600319360112610127576107c9610990565b506107d26109b3565b5060643567ffffffffffffffff8111610127576107f3903690600401610a7b565b5060206040517f150b7a02000000000000000000000000000000000000000000000000000000008152f35b3461012757602060031936011261012757600435907fffffffff0000000000000000000000000000000000000000000000000000000082168092036101275773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630146101f557817f399225470000000000000000000000000000000000000000000000000000000060209314908115610966575b81156108d6575b5015158152f35b7f150b7a0200000000000000000000000000000000000000000000000000000000811491508115610909575b50836108cf565b7f4e2312e00000000000000000000000000000000000000000000000000000000081149150811561093c575b5083610902565b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483610935565b7f1626ba7e00000000000000000000000000000000000000000000000000000000811491506108c8565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361012757565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361012757565b90601f601f19910116810190811067ffffffffffffffff8211176109f957604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b67ffffffffffffffff81116109f957601f01601f191660200190565b929192610a5082610a28565b91610a5e60405193846109d6565b829481845281830111610127578281602093846000960137010152565b9080601f8301121561012757816020610a9693359101610a44565b90565b6040600319820112610127576004359160243567ffffffffffffffff811161012757826023820112156101275780600401359267ffffffffffffffff84116101275760248483010111610127576024019190565b919082519283825260005b848110610b19575050601f19601f8460006020809697860101520116010190565b80602080928401015182828601015201610af8565b67ffffffffffffffff81116109f95760051b60200190565b9080601f83011215610127578135610b5d81610b2e565b92610b6b60405194856109d6565b81845260208085019260051b82010192831161012757602001905b828210610b935750505090565b8135815260209182019101610b86565b610bc7610bcd9273ffffffffffffffffffffffffffffffffffffffff943691610a44565b90611976565b50911630149081610c27575b5015610c03577f1626ba7e0000000000000000000000000000000000000000000000000000000090565b7fffffffff0000000000000000000000000000000000000000000000000000000090565b9050610c3281610c51565b1538610bd9565b90816020910312610127575180151581036101275790565b60041115610c5b57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b90610c94826115ea565b91610c9e83610c51565b82156113a357369180359060208210611366578181019060208201946040833594101560001461139a57506020810135604081108015611390575b61136657810196602088019735915b8215611308575050608181036112de57806020116101275786359281604011610127576020880135957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0604060009a019301938742116112b257610d4b86611579565b610d5489610c51565b6001891461110d5750610d6688610c51565b60028814610db15750505050505050600390610d8181610c51565b14610d895750565b807f7daadde30000000000000000000000000000000000000000000000000000000060049252fd5b610dc392939497509894979598611690565b929091610dcf84610b2e565b98610ddd6040519a8b6109d6565b848a5260208a018560051b85013681116111095785915b81831061103857505050895197610e23610e0d8a610b2e565b99610e1b6040519b8c6109d6565b808b52610b2e565b99601f1960208b019b01368c37885b8c51811015610ee757808b610ee08f938473ffffffffffffffffffffffffffffffffffffffff610e6483600198611962565b515116906040610e83846020610e7a8286611962565b51015193611962565b510151602081519101206040519160208301937fc7893c18b7bfea9418ca400815946cd740f303b74b0ff88fb938f83d0c1bd94e855260408401526060830152608082015260808152610ed760a0826109d6565b51902092611962565b5201610e32565b509295989194979a5092959860405190602082018093519091908d5b818110611022575050509473ffffffffffffffffffffffffffffffffffffffff9794610fcd610bc795610fbf610fe69a9686610f4e610fd598610fdd9d03601f1981018352826109d6565b51902060405194859360208501973393899360a09373ffffffffffffffffffffffffffffffffffffffff939796929760c08701987fddfe073f873bee5d1c9e29281fa37f2d0716a8e75ec88b673b4ec2a7c850ec3f8852602088015260408701526060860152608085015216910152565b03601f1981018352826109d6565b5190206119f3565b923691610a44565b90929192611ae1565b163003610ffa57610ff89293506117a0565b565b6004847f7daadde3000000000000000000000000000000000000000000000000000000008152fd5b8251845260209384019390920191600101610f03565b823567ffffffffffffffff811161110557870160608136031261110557604051906060820182811067ffffffffffffffff8211176110d857604052803573ffffffffffffffffffffffffffffffffffffffff811681036110d457825260208101356020830152604081013567ffffffffffffffff81116110d457916110c4602094928594369101610a7b565b6040820152815201920191610df4565b8c80fd5b60248d7f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b8a80fd5b8880fd5b9591809795985060149a999a116112ae573560601c93866034116112ae57603486013595605401967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcc019736611164908a8a610a44565b8051906020012060405160208101917fc7893c18b7bfea9418ca400815946cd740f303b74b0ff88fb938f83d0c1bd94e83528860408301528960608301526080820152608081526111b660a0826109d6565b51902060405160208101918252602081526111d26040826109d6565b519020604080517fddfe073f873bee5d1c9e29281fa37f2d0716a8e75ec88b673b4ec2a7c850ec3f60208201908152918101929092526060820193909352608081019390935260a08301523360c08084019190915282529061123560e0826109d6565b519020611241906119f3565b91369061124d92610a44565b61125691611976565b61125f91611ae1565b73ffffffffffffffffffffffffffffffffffffffff16300361128657610ff8949550611858565b6004867f7daadde3000000000000000000000000000000000000000000000000000000008152fd5b8980fd5b60248a897fbd2a913c000000000000000000000000000000000000000000000000000000008252600452fd5b7f59d8e20f0000000000000000000000000000000000000000000000000000000060005260046000fd5b9695509650505050503033036103c55760019061132481610c51565b1461133c57610ff89161133691611690565b906117a0565b7f7daadde30000000000000000000000000000000000000000000000000000000060005260046000fd5b7fec3e6d970000000000000000000000000000000000000000000000000000000060005260046000fd5b5087811015610cd9565b96600091610ce8565b7fff000000000000000000000000000000000000000000000000000000000000008116907fffffffff000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008260081b169160301b169180158015611511575b156114e45750806114b757507f7821000100000000000000000000000000000000000000000000000000000000811480156114af575b15611482577f7f1812750000000000000000000000000000000000000000000000000000000060005260046000fd5b7fb73f9c5a0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b508015611453565b7f23a240850000000000000000000000000000000000000000000000000000000060005260045260246000fd5b7fb1be6a960000000000000000000000000000000000000000000000000000000060005260045260246000fd5b507f0100000000000000000000000000000000000000000000000000000000000000811461141d565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630146101f557565b600160ff8260081c92161b906000527fb035242b6a1b64fd1e2d869c03a3cc0e80fe7f55db29c2560bab38e489fab70060205260406000208181541880915516156115c057565b7f756688fe0000000000000000000000000000000000000000000000000000000060005260046000fd5b7fffffffffffffffffffff0000000000000000000000000000000000000000000016797821000100000000000000000000000000000000000000000000811461168a577f01000000000078210001000000000000000000000000000000000000000000008114611684577f01000000000000000000000000000000000000000000000000000000000000001461167f57600090565b600390565b50600290565b50600190565b919091602083106116eb578260201161012757803590601f19840182116116eb5760006020830180841161172d57851061172a575081019081359367ffffffffffffffff8511918215611715575b50506116eb576020019190565b7feb0bcc5d0000000000000000000000000000000000000000000000000000000060005260046000fd5b601f199192508560051b9203011038806116de565b80fd5b5080fd5b91908110156117715760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610127570190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005b8181106117b057505050565b6117bb818385611731565b359073ffffffffffffffffffffffffffffffffffffffff821682036101275760206117e7828587611731565b0135916117f5828587611731565b6040810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610127570180359067ffffffffffffffff82116101275760200181360381136101275760019461185293611858565b016117a4565b9190913073ffffffffffffffffffffffffffffffffffffffff82161480611957575b80611902575b6118d8578360009384936118cd966040519384928337810185815203925af13d156118d0573d906118b082610a28565b916118be60405193846109d6565b82523d6000602084013e611bae565b50565b606090611bae565b7f37ed32e80000000000000000000000000000000000000000000000000000000060005260046000fd5b5083600411610127577fb70e36f0000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008335161415611880565b50600484101561187a565b80518210156117715760209160051b010190565b81519190604183036119a7576119a092506020820151906060604084015193015160001a90611bef565b9192909190565b505060009160029190565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8116610a9657503090565b604290467f000000000000000000000000000000000000000000000000000000000000000003611a75577f0000000000000000000000000000000000000000000000000000000000000000905b604051917f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201522090565b611a7d6119b2565b60405173ffffffffffffffffffffffffffffffffffffffff60208201927f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218845246604084015216606082015260608152611ad86080826109d6565b51902090611a40565b611aea81610c51565b80611af3575050565b611afc81610c51565b60018103611b2e577ff645eedf0000000000000000000000000000000000000000000000000000000060005260046000fd5b611b3781610c51565b60028103611b6d57507ffce698f70000000000000000000000000000000000000000000000000000000060005260045260246000fd5b600390611b7981610c51565b14611b815750565b7fd78bce0c0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b909190610ff85750805115611bc557805190602001fd5b7fd6bda2750000000000000000000000000000000000000000000000000000000060005260046000fd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411611c79579160209360809260ff60009560405194855216868401526040830152606082015282805260015afa156102785760005173ffffffffffffffffffffffffffffffffffffffff811615611c6d5790600090600090565b50600090600190600090565b5050506000916003919056fea164736f6c634300081b000a00000000000000000000000000000000fb2736c301e53904409f03de06c8467a
Deployed Bytecode
0x6080806040526004361015610028575b5036156100205761001e61153a565b005b61001e61153a565b60003560e01c90816301ffc9a71461081e57508063150b7a02146107b05780631626ba7e1461072c5780634abb262a1461067b5780635d00bb12146105e457806384b0196e1461049e578063b187bd26146103ef578063b70e36f014610365578063bc197c81146102b5578063d03c791414610284578063e9ae5c531461012c5763f23a6e61146100b9573861000f565b346101275760a0600319360112610127576100d2610990565b506100db6109b3565b5060843567ffffffffffffffff8111610127576100fc903690600401610a7b565b5060206040517ff23a6e61000000000000000000000000000000000000000000000000000000008152f35b600080fd5b61013536610a99565b906040517f5c975abb00000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000fb2736c301e53904409f03de06c8467a165afa90811561027857600091610249575b5061021f5773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000fb7702036ff9f76044a501ac1aa74cbab16b1630146101f55761001e92610c8a565b7f9f03a0260000000000000000000000000000000000000000000000000000000060005260046000fd5b7fd93c06650000000000000000000000000000000000000000000000000000000060005260046000fd5b61026b915060203d602011610271575b61026381836109d6565b810190610c39565b846101aa565b503d610259565b6040513d6000823e3d90fd5b346101275760206003193601126101275760206102a26004356115ea565b6102ab81610c51565b6040519015158152f35b346101275760a0600319360112610127576102ce610990565b506102d76109b3565b5060443567ffffffffffffffff8111610127576102f8903690600401610b46565b5060643567ffffffffffffffff811161012757610319903690600401610b46565b5060843567ffffffffffffffff81116101275761033a903690600401610a7b565b5060206040517fbc197c81000000000000000000000000000000000000000000000000000000008152f35b346101275760206003193601126101275773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000fb7702036ff9f76044a501ac1aa74cbab16b1630146101f5573033036103c55761001e600435611579565b7f5c427cd90000000000000000000000000000000000000000000000000000000060005260046000fd5b34610127576000600319360112610127576040517f5c975abb00000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000fb2736c301e53904409f03de06c8467a165afa801561027857602091600091610481575b506040519015158152f35b6104989150823d84116102715761026381836109d6565b82610476565b346101275760006003193601126101275773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000fb7702036ff9f76044a501ac1aa74cbab16b1630146101f5576105856020604051906104ff81836109d6565b600082526040519061051181836109d6565b6000825261051d6119b2565b73ffffffffffffffffffffffffffffffffffffffff6105936040519461054385876109d6565b6000865260003681376040519788977f0c00000000000000000000000000000000000000000000000000000000000000895260e0878a015260e0890190610aed565b908782036040890152610aed565b91466060870152166080850152600060a085015283810360c085015281808451928381520193019160005b8281106105cd57505050500390f35b8351855286955093810193928101926001016105be565b346101275760206003193601126101275760043573ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000fb7702036ff9f76044a501ac1aa74cbab16b1630146101f557600160209160ff8160081c9116906000527fb035242b6a1b64fd1e2d869c03a3cc0e80fe7f55db29c2560bab38e489fab70083521b604060002054161515604051908152f35b34610127576020600319360112610127576004357effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168091036101275773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000fb7702036ff9f76044a501ac1aa74cbab16b1630146101f5576000527fb035242b6a1b64fd1e2d869c03a3cc0e80fe7f55db29c2560bab38e489fab7006020526020604060002054604051908152f35b346101275761073a36610a99565b73ffffffffffffffffffffffffffffffffffffffff9291927f0000000000000000000000000000fb7702036ff9f76044a501ac1aa74cbab16b1630146101f55760209261078692610ba3565b7fffffffff0000000000000000000000000000000000000000000000000000000060405191168152f35b34610127576080600319360112610127576107c9610990565b506107d26109b3565b5060643567ffffffffffffffff8111610127576107f3903690600401610a7b565b5060206040517f150b7a02000000000000000000000000000000000000000000000000000000008152f35b3461012757602060031936011261012757600435907fffffffff0000000000000000000000000000000000000000000000000000000082168092036101275773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000fb7702036ff9f76044a501ac1aa74cbab16b1630146101f557817f399225470000000000000000000000000000000000000000000000000000000060209314908115610966575b81156108d6575b5015158152f35b7f150b7a0200000000000000000000000000000000000000000000000000000000811491508115610909575b50836108cf565b7f4e2312e00000000000000000000000000000000000000000000000000000000081149150811561093c575b5083610902565b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483610935565b7f1626ba7e00000000000000000000000000000000000000000000000000000000811491506108c8565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361012757565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361012757565b90601f601f19910116810190811067ffffffffffffffff8211176109f957604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b67ffffffffffffffff81116109f957601f01601f191660200190565b929192610a5082610a28565b91610a5e60405193846109d6565b829481845281830111610127578281602093846000960137010152565b9080601f8301121561012757816020610a9693359101610a44565b90565b6040600319820112610127576004359160243567ffffffffffffffff811161012757826023820112156101275780600401359267ffffffffffffffff84116101275760248483010111610127576024019190565b919082519283825260005b848110610b19575050601f19601f8460006020809697860101520116010190565b80602080928401015182828601015201610af8565b67ffffffffffffffff81116109f95760051b60200190565b9080601f83011215610127578135610b5d81610b2e565b92610b6b60405194856109d6565b81845260208085019260051b82010192831161012757602001905b828210610b935750505090565b8135815260209182019101610b86565b610bc7610bcd9273ffffffffffffffffffffffffffffffffffffffff943691610a44565b90611976565b50911630149081610c27575b5015610c03577f1626ba7e0000000000000000000000000000000000000000000000000000000090565b7fffffffff0000000000000000000000000000000000000000000000000000000090565b9050610c3281610c51565b1538610bd9565b90816020910312610127575180151581036101275790565b60041115610c5b57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b90610c94826115ea565b91610c9e83610c51565b82156113a357369180359060208210611366578181019060208201946040833594101560001461139a57506020810135604081108015611390575b61136657810196602088019735915b8215611308575050608181036112de57806020116101275786359281604011610127576020880135957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0604060009a019301938742116112b257610d4b86611579565b610d5489610c51565b6001891461110d5750610d6688610c51565b60028814610db15750505050505050600390610d8181610c51565b14610d895750565b807f7daadde30000000000000000000000000000000000000000000000000000000060049252fd5b610dc392939497509894979598611690565b929091610dcf84610b2e565b98610ddd6040519a8b6109d6565b848a5260208a018560051b85013681116111095785915b81831061103857505050895197610e23610e0d8a610b2e565b99610e1b6040519b8c6109d6565b808b52610b2e565b99601f1960208b019b01368c37885b8c51811015610ee757808b610ee08f938473ffffffffffffffffffffffffffffffffffffffff610e6483600198611962565b515116906040610e83846020610e7a8286611962565b51015193611962565b510151602081519101206040519160208301937fc7893c18b7bfea9418ca400815946cd740f303b74b0ff88fb938f83d0c1bd94e855260408401526060830152608082015260808152610ed760a0826109d6565b51902092611962565b5201610e32565b509295989194979a5092959860405190602082018093519091908d5b818110611022575050509473ffffffffffffffffffffffffffffffffffffffff9794610fcd610bc795610fbf610fe69a9686610f4e610fd598610fdd9d03601f1981018352826109d6565b51902060405194859360208501973393899360a09373ffffffffffffffffffffffffffffffffffffffff939796929760c08701987fddfe073f873bee5d1c9e29281fa37f2d0716a8e75ec88b673b4ec2a7c850ec3f8852602088015260408701526060860152608085015216910152565b03601f1981018352826109d6565b5190206119f3565b923691610a44565b90929192611ae1565b163003610ffa57610ff89293506117a0565b565b6004847f7daadde3000000000000000000000000000000000000000000000000000000008152fd5b8251845260209384019390920191600101610f03565b823567ffffffffffffffff811161110557870160608136031261110557604051906060820182811067ffffffffffffffff8211176110d857604052803573ffffffffffffffffffffffffffffffffffffffff811681036110d457825260208101356020830152604081013567ffffffffffffffff81116110d457916110c4602094928594369101610a7b565b6040820152815201920191610df4565b8c80fd5b60248d7f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b8a80fd5b8880fd5b9591809795985060149a999a116112ae573560601c93866034116112ae57603486013595605401967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcc019736611164908a8a610a44565b8051906020012060405160208101917fc7893c18b7bfea9418ca400815946cd740f303b74b0ff88fb938f83d0c1bd94e83528860408301528960608301526080820152608081526111b660a0826109d6565b51902060405160208101918252602081526111d26040826109d6565b519020604080517fddfe073f873bee5d1c9e29281fa37f2d0716a8e75ec88b673b4ec2a7c850ec3f60208201908152918101929092526060820193909352608081019390935260a08301523360c08084019190915282529061123560e0826109d6565b519020611241906119f3565b91369061124d92610a44565b61125691611976565b61125f91611ae1565b73ffffffffffffffffffffffffffffffffffffffff16300361128657610ff8949550611858565b6004867f7daadde3000000000000000000000000000000000000000000000000000000008152fd5b8980fd5b60248a897fbd2a913c000000000000000000000000000000000000000000000000000000008252600452fd5b7f59d8e20f0000000000000000000000000000000000000000000000000000000060005260046000fd5b9695509650505050503033036103c55760019061132481610c51565b1461133c57610ff89161133691611690565b906117a0565b7f7daadde30000000000000000000000000000000000000000000000000000000060005260046000fd5b7fec3e6d970000000000000000000000000000000000000000000000000000000060005260046000fd5b5087811015610cd9565b96600091610ce8565b7fff000000000000000000000000000000000000000000000000000000000000008116907fffffffff000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008260081b169160301b169180158015611511575b156114e45750806114b757507f7821000100000000000000000000000000000000000000000000000000000000811480156114af575b15611482577f7f1812750000000000000000000000000000000000000000000000000000000060005260046000fd5b7fb73f9c5a0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b508015611453565b7f23a240850000000000000000000000000000000000000000000000000000000060005260045260246000fd5b7fb1be6a960000000000000000000000000000000000000000000000000000000060005260045260246000fd5b507f0100000000000000000000000000000000000000000000000000000000000000811461141d565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000fb7702036ff9f76044a501ac1aa74cbab16b1630146101f557565b600160ff8260081c92161b906000527fb035242b6a1b64fd1e2d869c03a3cc0e80fe7f55db29c2560bab38e489fab70060205260406000208181541880915516156115c057565b7f756688fe0000000000000000000000000000000000000000000000000000000060005260046000fd5b7fffffffffffffffffffff0000000000000000000000000000000000000000000016797821000100000000000000000000000000000000000000000000811461168a577f01000000000078210001000000000000000000000000000000000000000000008114611684577f01000000000000000000000000000000000000000000000000000000000000001461167f57600090565b600390565b50600290565b50600190565b919091602083106116eb578260201161012757803590601f19840182116116eb5760006020830180841161172d57851061172a575081019081359367ffffffffffffffff8511918215611715575b50506116eb576020019190565b7feb0bcc5d0000000000000000000000000000000000000000000000000000000060005260046000fd5b601f199192508560051b9203011038806116de565b80fd5b5080fd5b91908110156117715760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610127570190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005b8181106117b057505050565b6117bb818385611731565b359073ffffffffffffffffffffffffffffffffffffffff821682036101275760206117e7828587611731565b0135916117f5828587611731565b6040810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610127570180359067ffffffffffffffff82116101275760200181360381136101275760019461185293611858565b016117a4565b9190913073ffffffffffffffffffffffffffffffffffffffff82161480611957575b80611902575b6118d8578360009384936118cd966040519384928337810185815203925af13d156118d0573d906118b082610a28565b916118be60405193846109d6565b82523d6000602084013e611bae565b50565b606090611bae565b7f37ed32e80000000000000000000000000000000000000000000000000000000060005260046000fd5b5083600411610127577fb70e36f0000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008335161415611880565b50600484101561187a565b80518210156117715760209160051b010190565b81519190604183036119a7576119a092506020820151906060604084015193015160001a90611bef565b9192909190565b505060009160029190565b7f0000000000000000000000000000fb7702036ff9f76044a501ac1aa74cbab16b73ffffffffffffffffffffffffffffffffffffffff8116610a9657503090565b604290467f000000000000000000000000000000000000000000000000000000000000000103611a75577f79871c985accdba0e91bb3769ac7881a544c156f9ed801d0b8710c28276b4093905b604051917f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201522090565b611a7d6119b2565b60405173ffffffffffffffffffffffffffffffffffffffff60208201927f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218845246604084015216606082015260608152611ad86080826109d6565b51902090611a40565b611aea81610c51565b80611af3575050565b611afc81610c51565b60018103611b2e577ff645eedf0000000000000000000000000000000000000000000000000000000060005260046000fd5b611b3781610c51565b60028103611b6d57507ffce698f70000000000000000000000000000000000000000000000000000000060005260045260246000fd5b600390611b7981610c51565b14611b815750565b7fd78bce0c0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b909190610ff85750805115611bc557805190602001fd5b7fd6bda2750000000000000000000000000000000000000000000000000000000060005260046000fd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411611c79579160209360809260ff60009560405194855216868401526040830152606082015282805260015afa156102785760005173ffffffffffffffffffffffffffffffffffffffff811615611c6d5790600090600090565b50600090600190600090565b5050506000916003919056fea164736f6c634300081b000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000fb2736c301e53904409f03de06c8467a
-----Decoded View---------------
Arg [0] : killswitchContract (address): 0x00000000FB2736C301E53904409f03De06c8467A
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000fb2736c301e53904409f03de06c8467a
Loading...
Loading
Loading...
Loading

Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.