diff --git a/src/StdPrecompiles.sol b/src/StdPrecompiles.sol index 04d4134..64b109d 100644 --- a/src/StdPrecompiles.sol +++ b/src/StdPrecompiles.sol @@ -4,6 +4,8 @@ pragma solidity >=0.8.20 <0.9.0; import {IActivationRegistry} from "./interfaces/IActivationRegistry.sol"; import {IPolicyRegistry} from "./interfaces/IPolicyRegistry.sol"; import {IB20Factory} from "./interfaces/IB20Factory.sol"; +import {ITransactionContext} from "./interfaces/ITransactionContext.sol"; +import {INonceManager} from "./interfaces/INonceManager.sol"; /// @title StdPrecompiles /// @notice Address constants for Base's singleton precompiles, each paired with an interface-typed @@ -12,8 +14,13 @@ library StdPrecompiles { address internal constant B20_FACTORY_ADDRESS = 0xB20f000000000000000000000000000000000000; address internal constant POLICY_REGISTRY_ADDRESS = 0x8453000000000000000000000000000000000002; address internal constant ACTIVATION_REGISTRY_ADDRESS = 0x8453000000000000000000000000000000000001; + // EIP-8130 system precompiles, in the 0x8130... (EIP number) namespace. + address internal constant NONCE_MANAGER_ADDRESS = 0x813000000000000000000000000000000000aa01; + address internal constant TX_CONTEXT_ADDRESS = 0x813000000000000000000000000000000000aa02; IB20Factory internal constant B20_FACTORY = IB20Factory(B20_FACTORY_ADDRESS); IPolicyRegistry internal constant POLICY_REGISTRY = IPolicyRegistry(POLICY_REGISTRY_ADDRESS); IActivationRegistry internal constant ACTIVATION_REGISTRY = IActivationRegistry(ACTIVATION_REGISTRY_ADDRESS); + ITransactionContext internal constant TX_CONTEXT = ITransactionContext(TX_CONTEXT_ADDRESS); + INonceManager internal constant NONCE_MANAGER = INonceManager(NONCE_MANAGER_ADDRESS); } diff --git a/src/interfaces/INonceManager.sol b/src/interfaces/INonceManager.sol new file mode 100644 index 0000000..a2a2369 --- /dev/null +++ b/src/interfaces/INonceManager.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.20 <0.9.0; + +/// @title INonceManager +/// +/// @notice Singleton precompile managing the EIP-8130 two-dimensional nonces that enable +/// concurrent account-abstraction transaction execution. Each `(account, nonceKey)` +/// channel carries its own independently-ordered sequence nonce. Nonce key `0` is the +/// protocol nonce; it is held in account state and is not served by this precompile. +interface INonceManager { + /*////////////////////////////////////////////////////////////// + ERRORS + //////////////////////////////////////////////////////////////*/ + + /// @notice The precompile was invoked via `DELEGATECALL` or `CALLCODE`. + error DelegateCallNotAllowed(); + + /// @notice Nonce key `0` is the protocol nonce and is not served by this precompile; + /// read it from account state instead. + error ProtocolNonceNotSupported(); + + /// @notice Nonce key `0` is reserved for the protocol nonce and cannot be incremented here. + error InvalidNonceKey(); + + /// @notice The `(account, nonceKey)` channel nonce is already at its maximum value. + error NonceOverflow(); + + /// @notice An expiring nonce's `validBefore` is outside the allowed `(now, now + maxExpiry]` window. + error InvalidExpiringNonceExpiry(); + + /// @notice An expiring-nonce replay hash has already been recorded and has not yet expired. + error ExpiringNonceReplay(); + + /// @notice The expiring-nonce set is full of unexpired entries and cannot accept more. + error ExpiringNonceSetFull(); + + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + /// @notice Emitted when the 2D nonce for `(account, nonceKey)` is incremented to `newNonce`. + event NonceIncremented(address indexed account, uint256 indexed nonceKey, uint64 newNonce); + + /*////////////////////////////////////////////////////////////// + NONCE QUERIES + //////////////////////////////////////////////////////////////*/ + + /// @notice Returns the current 2D nonce for `account` at `nonceKey`. A never-used channel + /// reads as `0`. + /// + /// @dev Reverts with `ProtocolNonceNotSupported` for nonce key `0`. + /// + /// @param account Account whose channel nonce is being queried. + /// @param nonceKey Non-zero nonce channel to query. + /// + /// @return The current sequence nonce for the channel. + function getNonce(address account, uint256 nonceKey) external view returns (uint64); +} diff --git a/src/interfaces/ITransactionContext.sol b/src/interfaces/ITransactionContext.sol new file mode 100644 index 0000000..d63124b --- /dev/null +++ b/src/interfaces/ITransactionContext.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.20 <0.9.0; + +/// @title ITransactionContext +/// +/// @notice Singleton precompile exposing the resolved context of the in-flight EIP-8130 +/// account-abstraction transaction: its sender, payer, and the actor id resolved while +/// authenticating the sender. On non-EIP-8130 transactions the context is not populated and +/// the getters fall back to `tx.origin`: `getTransactionSender` and `getTransactionPayer` +/// return `tx.origin`, and `getTransactionSenderActorId` returns `bytes32(bytes20(tx.origin))`. +interface ITransactionContext { + /*////////////////////////////////////////////////////////////// + ERRORS + //////////////////////////////////////////////////////////////*/ + + /// @notice The precompile was invoked via `DELEGATECALL` or `CALLCODE`. + error DelegateCallNotAllowed(); + + /*////////////////////////////////////////////////////////////// + CONTEXT QUERIES + //////////////////////////////////////////////////////////////*/ + + /// @notice The resolved sender of the in-flight transaction. Never reverts; returns + /// `tx.origin` outside of an EIP-8130 transaction. + /// + /// @return The resolved sender, or `tx.origin`. + function getTransactionSender() external view returns (address); + + /// @notice The resolved payer of the in-flight transaction, equal to the sender when the + /// transaction is self-paying. Never reverts; returns `tx.origin` outside of an + /// EIP-8130 transaction. + /// + /// @return The resolved payer, or `tx.origin`. + function getTransactionPayer() external view returns (address); + + /// @notice The actor id resolved while authenticating the sender of the in-flight + /// transaction. Never reverts; returns `bytes32(bytes20(tx.origin))` outside of an + /// EIP-8130 transaction. + /// + /// @return The resolved sender actor id, or `bytes32(bytes20(tx.origin))`. + function getTransactionSenderActorId() external view returns (bytes32); +}