Skip to main content

tempo_contracts/precompiles/
account_keychain.rs

1#![allow(clippy::too_many_arguments)]
2
3pub use IAccountKeychain::{
4    IAccountKeychainErrors as AccountKeychainError, IAccountKeychainEvents as AccountKeychainEvent,
5    authorizeAdminKeyCall, authorizeKey_0Call as legacyAuthorizeKeyCall,
6    authorizeKey_1Call as authorizeKeyCall, authorizeKey_2Call as authorizeKeyWithWitnessCall,
7    getAllowedCallsReturn, getRemainingLimitWithPeriodCall,
8    getRemainingLimitWithPeriodReturn as getRemainingLimitReturn,
9};
10
11crate::sol! {
12    /// Account Keychain interface for managing authorized keys
13    ///
14    /// This precompile allows accounts to authorize secondary keys with:
15    /// - Different signature types (secp256k1, P256, WebAuthn)
16    /// - Expiry times for key rotation
17    /// - Per-token spending limits for security
18    ///
19    /// Only the main account key can authorize/revoke keys, while secondary keys
20    /// can be used for regular transactions within their spending limits.
21    #[derive(Debug, PartialEq, Eq)]
22    #[sol(abi)]
23    interface IAccountKeychain {
24        enum SignatureType {
25            Secp256k1,
26            P256,
27            WebAuthn,
28        }
29
30        /// Legacy token spending limit structure used before T3.
31        struct LegacyTokenLimit {
32            address token;
33            uint256 amount;
34        }
35
36        /// Token spending limit structure
37        struct TokenLimit {
38            address token;
39            uint256 amount;
40            uint64 period;
41        }
42
43        /// Selector-level recipient rule.
44        struct SelectorRule {
45            bytes4 selector;
46            /// Empty means no recipient restriction for this selector.
47            /// To block the selector entirely, remove the selector rule instead of passing `[]`.
48            address[] recipients;
49        }
50
51        /// Per-target call scope.
52        struct CallScope {
53            address target;
54            /// Empty means no selector restriction for this target.
55            /// To block the target entirely, omit this scope from `allowedCalls` or call
56            /// `removeAllowedCalls` for incremental updates.
57            SelectorRule[] selectorRules;
58        }
59
60        /// Optional access-key restrictions configured at authorization time.
61        struct KeyRestrictions {
62            uint64 expiry;
63            bool enforceLimits;
64            TokenLimit[] limits;
65            /// `true` means the key is unrestricted and `allowedCalls` must be empty.
66            /// `false` means `allowedCalls` defines the full call scope (including deny-all with `[]`).
67            bool allowAnyCalls;
68            CallScope[] allowedCalls;
69        }
70
71        /// Key information structure
72        struct KeyInfo {
73            SignatureType signatureType;
74            address keyId;
75            uint64 expiry;
76            bool enforceLimits;
77            bool isRevoked;
78        }
79        /// Emitted when a new key is authorized
80        event KeyAuthorized(address indexed account, address indexed publicKey, uint8 signatureType, uint64 expiry);
81
82        /// Emitted when a new admin key is authorized.
83        event AdminKeyAuthorized(address indexed account, address indexed publicKey);
84
85        /// Emitted when a key is revoked
86        event KeyRevoked(address indexed account, address indexed publicKey);
87
88        /// Emitted when a spending limit is updated
89        event SpendingLimitUpdated(address indexed account, address indexed publicKey, address indexed token, uint256 newLimit);
90
91        event AccessKeySpend(
92            address indexed account,
93            address indexed publicKey,
94            address indexed token,
95            uint256 amount,
96            uint256 remainingLimit
97        );
98
99        /// Emitted when a key authorization carries a TIP-1053 witness.
100        event KeyAuthorizationWitness(address indexed account, bytes32 indexed witness);
101
102        /// Emitted when a TIP-1053 key-authorization witness is manually burned.
103        event KeyAuthorizationWitnessBurned(address indexed account, bytes32 indexed witness);
104
105        /// Legacy authorize-key entrypoint used before T3.
106        function authorizeKey(
107            address keyId,
108            SignatureType signatureType,
109            uint64 expiry,
110            bool enforceLimits,
111            LegacyTokenLimit[] calldata limits
112        ) external;
113
114        /// Authorize a new key for the caller's account with T3 extensions.
115        /// @param keyId The key identifier (address derived from public key)
116        /// @param signatureType 0: secp256k1, 1: P256, 2: WebAuthn
117        /// @param config Access-key expiry and optional limits / call restrictions
118        function authorizeKey(
119            address keyId,
120            SignatureType signatureType,
121            KeyRestrictions calldata config
122        ) external;
123
124        /// Authorize a new key with a TIP-1053 witness.
125        /// @dev The witness must not be burned for the caller's account. bytes32(0) is valid.
126        function authorizeKey(
127            address keyId,
128            SignatureType signatureType,
129            KeyRestrictions calldata config,
130            bytes32 witness
131        ) external;
132
133        /// Authorize a new admin key for the caller's account.
134        /// @dev The witness must not be burned for the caller's account. bytes32(0) is valid.
135        function authorizeAdminKey(
136            address keyId,
137            SignatureType signatureType,
138            bytes32 witness
139        ) external;
140
141        /// Burn a TIP-1053 key-authorization witness without authorizing a key.
142        /// @dev Callable only by the account admin key.
143        function burnKeyAuthorizationWitness(bytes32 witness) external;
144
145        /// Revoke an authorized key
146        /// @param publicKey The public key to revoke
147        function revokeKey(address keyId) external;
148
149        /// Update spending limit for a key-token pair
150        /// @param publicKey The public key
151        /// @param token The token address
152        /// @param newLimit The new spending limit
153        function updateSpendingLimit(
154            address keyId,
155            address token,
156            uint256 newLimit
157        ) external;
158
159        /// Set or replace allowed calls for one or more key+target pairs.
160        /// @dev Reverts if `scopes` is empty; use `removeAllowedCalls` to delete target scopes.
161        /// @dev `scope.selectorRules = []` does NOT block the target; it allows any selector on that target.
162        /// @dev To block the target entirely, call `removeAllowedCalls`. To block one selector,
163        ///      omit that selector rule from `scope.selectorRules`.
164        function setAllowedCalls(
165            address keyId,
166            CallScope[] calldata scopes
167        ) external;
168
169        /// Remove any configured call scope for a key+target pair.
170        function removeAllowedCalls(address keyId, address target) external;
171
172        /// Get key information
173        /// @param account The account address
174        /// @param publicKey The public key
175        /// @return Key information
176        function getKey(address account, address keyId) external view returns (KeyInfo memory);
177
178        /// Get remaining spending limit using the legacy pre-T3 return shape.
179        /// @param account The account address
180        /// @param publicKey The public key
181        /// @param token The token address
182        function getRemainingLimit(
183            address account,
184            address keyId,
185            address token
186        ) external view returns (uint256 remaining);
187
188        /// Get remaining spending limit together with the active period end.
189        /// @param account The account address
190        /// @param publicKey The public key
191        /// @param token The token address
192        /// @return remaining Remaining spending amount
193        /// @return periodEnd Period end timestamp for periodic limits (0 for one-time)
194        function getRemainingLimitWithPeriod(
195            address account,
196            address keyId,
197            address token
198        ) external view returns (uint256 remaining, uint64 periodEnd);
199
200        /// Returns whether an account key is call-scoped and, if so, the configured call scopes.
201        /// @dev `isScoped = false` means unrestricted. `isScoped = true && scopes.length == 0`
202        ///      means scoped deny-all.
203        /// @dev Missing, revoked, or expired access keys also return scoped deny-all so callers do
204        ///      not observe stale persisted scope state.
205        function getAllowedCalls(
206            address account,
207            address keyId
208        ) external view returns (bool isScoped, CallScope[] memory scopes);
209
210        /// Returns whether a TIP-1053 key-authorization witness has been manually burned.
211        function isKeyAuthorizationWitnessBurned(address account, bytes32 witness) external view returns (bool);
212
213        /// Returns true if `keyId` is the root key or an active admin key for `account`.
214        function isAdminKey(address account, address keyId) external view returns (bool);
215
216        /// Get the key used in the current transaction
217        /// @return The keyId used in the current transaction
218        function getTransactionKey() external view returns (address);
219
220        // Errors
221        error UnauthorizedCaller();
222        error KeyAlreadyExists();
223        error KeyNotFound();
224        error KeyExpired();
225        error SpendingLimitExceeded();
226        error InvalidSpendingLimit();
227        error InvalidSignatureType();
228        error ZeroPublicKey();
229        error ExpiryInPast();
230        error KeyAlreadyRevoked();
231        error SignatureTypeMismatch(uint8 expected, uint8 actual);
232        error CallNotAllowed();
233        error InvalidCallScope();
234        error InvalidKeyId();
235        error InvalidKeyAuthorizationWitness();
236        error KeyAuthorizationWitnessAlreadyBurned();
237        error LegacyAuthorizeKeySelectorChanged(bytes4 newSelector);
238    }
239}