1use alloy_sol_types::sol;
12
13sol! {
14 #[sol(abi)]
16 interface IActivationRegistry {
17 event FeatureActivated(bytes32 indexed feature, address indexed caller);
18 event FeatureDeactivated(bytes32 indexed feature, address indexed caller);
19 event AdminChanged(
20 address indexed previousAdmin,
21 address indexed newAdmin,
22 address indexed caller
23 );
24
25 error Unauthorized(address caller);
26 error AlreadyActivated(bytes32 feature);
27 error FeatureNotActivated(bytes32 feature);
28 error DelegateCallNotAllowed();
29 error StaticCallNotAllowed();
30 error NonPayable();
31 error AdminStorageNotEnabled();
32 error ZeroAdminAddress();
33
34 function isActivated(bytes32 feature) external view returns (bool);
35 function checkActivated(bytes32 feature) external view;
36 function admin() external view returns (address);
37 function setAdmin(address newAdmin) external;
38 function activate(bytes32 feature) external;
39 function deactivate(bytes32 feature) external;
40 }
41}
42
43sol! {
44 #[sol(abi)]
46 interface IB20Factory {
47 enum B20Variant {
48 ASSET,
49 STABLECOIN
50 }
51
52 struct B20StablecoinCreateParams {
53 uint8 version;
54 string name;
55 string symbol;
56 address initialAdmin;
57 string currency;
58 }
59
60 struct B20AssetCreateParams {
61 uint8 version;
62 string name;
63 string symbol;
64 address initialAdmin;
65 uint8 decimals;
66 }
67
68 error NonPayable();
69 error TokenAlreadyExists(address token);
70 error InvalidVariant();
71 error UnsupportedVersion(uint8 version, B20Variant variant);
72 error MissingRequiredField(string field);
73 error InvalidCurrency(string code);
74 error InvalidDecimals(uint8 decimals);
75 error InitCallFailed(uint256 index);
76
77 event B20Created(
78 address indexed token,
79 B20Variant indexed variant,
80 string name,
81 string symbol,
82 uint8 decimals,
83 bytes variantParams
84 );
85
86 struct B20StablecoinEventParams {
87 uint8 version;
88 string currency;
89 }
90
91 function createB20(
92 B20Variant variant,
93 bytes32 salt,
94 bytes calldata params,
95 bytes[] calldata initCalls
96 ) external returns (address token);
97 function getB20Address(B20Variant variant, address sender, bytes32 salt) external view returns (address);
98 function isB20(address token) external view returns (bool);
99 function isB20Initialized(address token) external view returns (bool);
100 }
101}
102
103sol! {
104 #[sol(abi)]
117 interface IB20Extensions {
118 enum PausableFeature {
119 TRANSFER,
120 MINT,
121 BURN,
122 SEIZE
123 }
124
125 event Memo(address indexed caller, bytes32 indexed memo);
126 event BurnedBlocked(address indexed caller, address indexed from, uint256 amount);
127 event Seized(address indexed caller, address indexed from, address indexed to, uint256 amount);
128 event LastAdminRenounced(address indexed previousAdmin);
129 event Paused(address indexed updater, PausableFeature[] features);
130 event Unpaused(address indexed updater, PausableFeature[] features);
131 event PolicyUpdated(bytes32 indexed policyScope, uint64 oldPolicyId, uint64 newPolicyId);
132
133 function mintWithMemo(address to, uint256 amount, bytes32 memo) external;
134 function burnWithMemo(uint256 amount, bytes32 memo) external;
135 function burnBlocked(address from, uint256 amount) external;
136 function transferWithMemo(address to, uint256 amount, bytes32 memo) external returns (bool);
137 function seizeWithMemo(address from, address to, uint256 amount, bytes32 memo) external;
138 function pausedFeatures() external view returns (PausableFeature[] memory);
139 function isPaused(PausableFeature feature) external view returns (bool);
140 function pause(PausableFeature[] calldata features) external;
141 function unpause(PausableFeature[] calldata features) external;
142 function policyId(bytes32 policyScope) external view returns (uint64);
143 function updatePolicy(bytes32 policyScope, uint64 newPolicyId) external;
144 function contractURI() external view returns (string);
145 function updateContractURI(string calldata newURI) external;
146 }
147}
148
149sol! {
150 #[sol(abi)]
155 interface IPolicyRegistry {
156 enum PolicyType {
157 BLOCKLIST,
158 ALLOWLIST,
159 UNION,
160 INTERSECT
161 }
162
163 error NonPayable();
164 error Unauthorized();
165 error PolicyNotFound();
166 error IncompatiblePolicyType();
167 error ZeroAddress();
168 error BatchSizeTooLarge(uint256 maxBatchSize);
169 error NoPendingAdmin();
170 error ChildPoliciesOutsideOfRange();
171 error InvalidChildPolicy(uint64 childPolicyId);
172
173 event PolicyCreated(uint64 indexed policyId, address indexed creator, PolicyType policyType);
174 event PolicyAdminStaged(uint64 indexed policyId, address indexed currentAdmin, address indexed pendingAdmin);
175 event PolicyAdminUpdated(uint64 indexed policyId, address indexed previousAdmin, address indexed newAdmin);
176 event AllowlistUpdated(uint64 indexed policyId, address indexed updater, bool allowed, address[] accounts);
177 event BlocklistUpdated(uint64 indexed policyId, address indexed updater, bool blocked, address[] accounts);
178 event CompositePolicyUpdated(uint64 indexed policyId, address indexed updater, uint64[] childPolicyIds);
179
180 function createPolicy(address admin, PolicyType policyType) external returns (uint64);
181 function createPolicyWithAccounts(address admin, PolicyType policyType, address[] calldata accounts) external returns (uint64);
182 function createCompositePolicy(address admin, PolicyType policyType, uint64[] calldata childPolicyIds) external returns (uint64);
183 function updateComposite(uint64 policyId, uint64[] calldata childPolicyIds) external;
184 function stageUpdateAdmin(uint64 policyId, address newAdmin) external;
185 function finalizeUpdateAdmin(uint64 policyId) external;
186 function renounceAdmin(uint64 policyId) external;
187 function updateAllowlist(uint64 policyId, bool allowed, address[] calldata accounts) external;
188 function updateBlocklist(uint64 policyId, bool blocked, address[] calldata accounts) external;
189 function isAuthorized(uint64 policyId, address account) external view returns (bool);
190 function MIN_COMPOSITE_CHILD_POLICIES() external view returns (uint256);
191 function MAX_COMPOSITE_CHILD_POLICIES() external view returns (uint256);
192 function policyExists(uint64 policyId) external view returns (bool);
193 function policyAdmin(uint64 policyId) external view returns (address);
194 function pendingPolicyAdmin(uint64 policyId) external view returns (address);
195 function compositePolicyChildIds(uint64 policyId) external view returns (uint64[] memory);
196 }
197}
198
199sol! {
200 #[sol(abi)]
202 interface INonceManager {
203 error DelegateCallNotAllowed();
204 error NonPayable();
205 error ProtocolNonceNotSupported();
206 error InvalidNonceKey();
207 error NonceOverflow();
208 error InvalidExpiringNonceExpiry();
209 error ExpiringNonceReplay();
210 error ExpiringNonceSetFull();
211
212 event NonceIncremented(address indexed account, uint256 indexed nonceKey, uint64 newNonce);
213
214 function getNonce(address account, uint256 nonceKey) external view returns (uint64);
215 }
216}
217
218sol! {
219 #[sol(abi)]
221 interface ITransactionContext {
222 error DelegateCallNotAllowed();
223 error NonPayable();
224
225 function getTransactionSender() external view returns (address);
226 function getTransactionPayer() external view returns (address);
227 function getTransactionSenderActorId() external view returns (bytes32);
228 }
229}
230
231#[cfg(test)]
232mod tests {
233 use crate::{CallTrace, CallTraceDecoderBuilder};
234 use alloy_dyn_abi::{DynSolValue, FunctionExt};
235 use alloy_primitives::{Address, B256, Bytes, U256};
236 use alloy_sol_types::{SolCall, SolEnum, SolError, SolEvent, SolInterface};
237 use base_common_precompiles::{
238 self as canonical, ActivationRegistryStorage, B20FactoryStorage, NonceManagerStorage,
239 TxContextStorage,
240 };
241 use foundry_evm_hardforks::{BaseUpgrade, FoundryHardfork};
242 use foundry_evm_networks::NetworkConfigs;
243 use revm::interpreter::InstructionResult;
244
245 #[tokio::test]
246 async fn registered_abis_decode_base_precompile_calls() {
247 let decoder = CallTraceDecoderBuilder::new()
248 .with_networks(NetworkConfigs::with_base())
249 .with_hardfork(Some(FoundryHardfork::Base(BaseUpgrade::Cobalt)))
250 .build();
251
252 let activate =
253 super::IActivationRegistry::activateCall { feature: B256::repeat_byte(0x11) };
254 let trace = CallTrace {
255 address: ActivationRegistryStorage::ADDRESS,
256 data: activate.abi_encode().into(),
257 success: true,
258 ..Default::default()
259 };
260 let decoded = decoder.decode_function(&trace).await;
261 assert_eq!(decoded.label.as_deref(), Some("ActivationRegistry"));
262 assert_eq!(
263 decoded.call_data.expect("activate should decode").signature,
264 "activate(bytes32)"
265 );
266
267 let get_nonce = super::INonceManager::getNonceCall {
268 account: Address::repeat_byte(0x22),
269 nonceKey: U256::from(7),
270 };
271 let trace = CallTrace {
272 address: NonceManagerStorage::ADDRESS,
273 data: get_nonce.abi_encode().into(),
274 success: true,
275 ..Default::default()
276 };
277 let decoded = decoder.decode_function(&trace).await;
278 assert_eq!(
279 decoded.call_data.expect("getNonce should decode").signature,
280 "getNonce(address,uint256)"
281 );
282
283 let create = super::IB20Factory::createB20Call {
284 variant: super::IB20Factory::B20Variant::ASSET,
285 salt: B256::repeat_byte(0x33),
286 params: Bytes::new(),
287 initCalls: Vec::new(),
288 };
289 let trace = CallTrace {
290 address: B20FactoryStorage::ADDRESS,
291 data: create.abi_encode().into(),
292 success: true,
293 ..Default::default()
294 };
295 let decoded = decoder.decode_function(&trace).await;
296 assert_eq!(decoded.label.as_deref(), Some("B20Factory"));
297 let signature = decoded.call_data.expect("createB20 should decode").signature;
298 assert!(signature.starts_with("createB20("), "{signature}");
299 }
300
301 #[tokio::test]
302 async fn b20_transfer_with_memo_decodes_bool_output() {
303 let call = super::IB20Extensions::transferWithMemoCall {
304 to: Address::repeat_byte(0x11),
305 amount: U256::from(1),
306 memo: B256::repeat_byte(0x22),
307 };
308 let abi = super::IB20Extensions::abi::contract();
309 let function = abi.functions.get("transferWithMemo").unwrap().first().unwrap();
310 let trace = CallTrace {
311 address: Address::repeat_byte(0x33),
312 data: call.abi_encode().into(),
313 output: function.abi_encode_output(&[DynSolValue::Bool(true)]).unwrap().into(),
314 success: true,
315 ..Default::default()
316 };
317
318 let base =
319 CallTraceDecoderBuilder::new().with_networks(NetworkConfigs::with_base()).build();
320 let decoded = base.decode_function(&trace).await;
321 assert_eq!(
322 decoded.call_data.unwrap().signature,
323 "transferWithMemo(address,uint256,bytes32)"
324 );
325 assert_eq!(decoded.return_data.as_deref(), Some("true"));
326
327 let custom_abi = alloy_json_abi::JsonAbi::parse([
328 "function transferWithMemo(address,uint256,bytes32) returns (uint256)",
329 ])
330 .unwrap();
331 let custom_base = CallTraceDecoderBuilder::new()
332 .with_networks(NetworkConfigs::with_base())
333 .with_abi(&custom_abi)
334 .build();
335 assert_eq!(custom_base.decode_function(&trace).await.return_data.as_deref(), Some("1"));
336
337 let tempo =
338 CallTraceDecoderBuilder::new().with_networks(NetworkConfigs::with_tempo()).build();
339 assert_eq!(tempo.decode_function(&trace).await.return_data, None);
340 }
341
342 #[tokio::test]
343 async fn base_precompile_errors_are_address_scoped() {
344 let trace = CallTrace {
345 address: ActivationRegistryStorage::ADDRESS,
346 output: super::IActivationRegistry::NonPayable {}.abi_encode().into(),
347 success: false,
348 status: Some(InstructionResult::Revert),
349 ..Default::default()
350 };
351 let base = CallTraceDecoderBuilder::new()
352 .with_networks(NetworkConfigs::with_base())
353 .with_hardfork(Some(FoundryHardfork::Base(BaseUpgrade::Beryl)))
354 .build();
355 assert_eq!(base.decode_function(&trace).await.return_data.as_deref(), Some("NonPayable()"));
356
357 let ethereum = CallTraceDecoderBuilder::new()
358 .with_networks(NetworkConfigs::with_ethereum())
359 .with_hardfork(Some(FoundryHardfork::Base(BaseUpgrade::Beryl)))
360 .build();
361 assert_ne!(
362 ethereum.decode_function(&trace).await.return_data.as_deref(),
363 Some("NonPayable()")
364 );
365 }
366
367 #[tokio::test]
372 async fn pre_cobalt_decoder_does_not_register_eip8130_surfaces() {
373 let call = super::ITransactionContext::getTransactionSenderActorIdCall {};
374 let trace = CallTrace {
375 address: TxContextStorage::ADDRESS,
376 data: call.abi_encode().into(),
377 success: true,
378 ..Default::default()
379 };
380
381 let beryl = CallTraceDecoderBuilder::new()
382 .with_networks(NetworkConfigs::with_base())
383 .with_hardfork(Some(FoundryHardfork::Base(BaseUpgrade::Beryl)))
384 .build();
385 assert!(
386 beryl.decode_function(&trace).await.call_data.is_none(),
387 "Beryl must not decode a Cobalt-only precompile"
388 );
389
390 let cobalt = CallTraceDecoderBuilder::new()
391 .with_networks(NetworkConfigs::with_base())
392 .with_hardfork(Some(FoundryHardfork::Base(BaseUpgrade::Cobalt)))
393 .build();
394 assert_eq!(
395 cobalt.decode_function(&trace).await.call_data.expect("Cobalt should decode").signature,
396 "getTransactionSenderActorId()"
397 );
398 }
399
400 #[test]
401 fn activation_registry_abi_matches_canonical_selectors() {
402 assert_eq!(
403 super::IActivationRegistry::activateCall::SELECTOR,
404 canonical::IActivationRegistry::activateCall::SELECTOR
405 );
406 assert_eq!(
407 super::IActivationRegistry::deactivateCall::SELECTOR,
408 canonical::IActivationRegistry::deactivateCall::SELECTOR
409 );
410 assert_eq!(
411 super::IActivationRegistry::isActivatedCall::SELECTOR,
412 canonical::IActivationRegistry::isActivatedCall::SELECTOR
413 );
414 assert_eq!(
415 super::IActivationRegistry::checkActivatedCall::SELECTOR,
416 canonical::IActivationRegistry::checkActivatedCall::SELECTOR
417 );
418 assert_eq!(
419 super::IActivationRegistry::adminCall::SELECTOR,
420 canonical::IActivationRegistry::adminCall::SELECTOR
421 );
422 assert_eq!(
423 super::IActivationRegistry::setAdminCall::SELECTOR,
424 canonical::IActivationRegistry::setAdminCall::SELECTOR
425 );
426 assert_eq!(
427 super::IActivationRegistry::Unauthorized::SELECTOR,
428 canonical::IActivationRegistry::Unauthorized::SELECTOR
429 );
430 assert_eq!(
431 super::IActivationRegistry::StaticCallNotAllowed::SELECTOR,
432 canonical::IActivationRegistry::StaticCallNotAllowed::SELECTOR
433 );
434 assert_eq!(
435 super::IActivationRegistry::NonPayable::SELECTOR,
436 canonical::IActivationRegistry::NonPayable::SELECTOR
437 );
438 assert_eq!(
439 super::IActivationRegistry::FeatureActivated::SIGNATURE_HASH,
440 canonical::IActivationRegistry::FeatureActivated::SIGNATURE_HASH
441 );
442 assert_eq!(
443 super::IActivationRegistry::AdminChanged::SIGNATURE_HASH,
444 canonical::IActivationRegistry::AdminChanged::SIGNATURE_HASH
445 );
446 }
447
448 #[test]
454 fn b20_factory_abi_matches_canonical_surface() {
455 assert_eq!(
456 super::IB20Factory::createB20Call::SELECTOR,
457 canonical::IB20Factory::createB20Call::SELECTOR
458 );
459 assert_eq!(
460 super::IB20Factory::getB20AddressCall::SELECTOR,
461 canonical::IB20Factory::getB20AddressCall::SELECTOR
462 );
463 assert_eq!(
464 super::IB20Factory::isB20Call::SELECTOR,
465 canonical::IB20Factory::isB20Call::SELECTOR
466 );
467 assert_eq!(
468 super::IB20Factory::isB20InitializedCall::SELECTOR,
469 canonical::IB20Factory::isB20InitializedCall::SELECTOR
470 );
471 assert_eq!(
472 super::IB20Factory::TokenAlreadyExists::SELECTOR,
473 canonical::IB20Factory::TokenAlreadyExists::SELECTOR
474 );
475 assert_eq!(
476 super::IB20Factory::UnsupportedVersion::SELECTOR,
477 canonical::IB20Factory::UnsupportedVersion::SELECTOR
478 );
479 assert_eq!(
480 super::IB20Factory::B20Created::SIGNATURE_HASH,
481 canonical::IB20Factory::B20Created::SIGNATURE_HASH
482 );
483
484 assert_eq!(
485 super::IB20Factory::B20Variant::COUNT,
486 canonical::IB20Factory::B20Variant::COUNT
487 );
488 assert_eq!(
489 super::IB20Factory::B20Variant::ASSET as u8,
490 canonical::IB20Factory::B20Variant::ASSET as u8
491 );
492 assert_eq!(
493 super::IB20Factory::B20Variant::STABLECOIN as u8,
494 canonical::IB20Factory::B20Variant::STABLECOIN as u8
495 );
496 }
497
498 #[test]
501 fn policy_registry_abi_matches_canonical_surface() {
502 assert_eq!(
503 super::IPolicyRegistry::createPolicyCall::SELECTOR,
504 canonical::IPolicyRegistry::createPolicyCall::SELECTOR
505 );
506 assert_eq!(
507 super::IPolicyRegistry::createCompositePolicyCall::SELECTOR,
508 canonical::IPolicyRegistry::createCompositePolicyCall::SELECTOR
509 );
510 assert_eq!(
511 super::IPolicyRegistry::isAuthorizedCall::SELECTOR,
512 canonical::IPolicyRegistry::isAuthorizedCall::SELECTOR
513 );
514 assert_eq!(
515 super::IPolicyRegistry::updateAllowlistCall::SELECTOR,
516 canonical::IPolicyRegistry::updateAllowlistCall::SELECTOR
517 );
518 assert_eq!(
519 super::IPolicyRegistry::InvalidChildPolicy::SELECTOR,
520 canonical::IPolicyRegistry::InvalidChildPolicy::SELECTOR
521 );
522 assert_eq!(
523 super::IPolicyRegistry::PolicyCreated::SIGNATURE_HASH,
524 canonical::IPolicyRegistry::PolicyCreated::SIGNATURE_HASH
525 );
526 assert_eq!(
527 super::IPolicyRegistry::CompositePolicyUpdated::SIGNATURE_HASH,
528 canonical::IPolicyRegistry::CompositePolicyUpdated::SIGNATURE_HASH
529 );
530
531 assert_eq!(
532 super::IPolicyRegistry::PolicyType::COUNT,
533 canonical::IPolicyRegistry::PolicyType::COUNT
534 );
535 for (mirror, expected) in [
536 (
537 super::IPolicyRegistry::PolicyType::BLOCKLIST as u8,
538 canonical::IPolicyRegistry::PolicyType::BLOCKLIST as u8,
539 ),
540 (
541 super::IPolicyRegistry::PolicyType::ALLOWLIST as u8,
542 canonical::IPolicyRegistry::PolicyType::ALLOWLIST as u8,
543 ),
544 (
545 super::IPolicyRegistry::PolicyType::UNION as u8,
546 canonical::IPolicyRegistry::PolicyType::UNION as u8,
547 ),
548 (
549 super::IPolicyRegistry::PolicyType::INTERSECT as u8,
550 canonical::IPolicyRegistry::PolicyType::INTERSECT as u8,
551 ),
552 ] {
553 assert_eq!(mirror, expected);
554 }
555 }
556
557 #[test]
560 fn policy_registry_covers_v1_selectors() {
561 let mirrored: Vec<[u8; 4]> =
562 super::IPolicyRegistry::IPolicyRegistryCalls::selectors().collect();
563 for selector in canonical::IPolicyRegistryV1::IPolicyRegistryCalls::selectors() {
564 assert!(
565 mirrored.contains(&selector),
566 "Beryl selector {selector:?} is absent from the mirrored Cobalt surface"
567 );
568 }
569 }
570
571 #[test]
572 fn b20_extensions_abi_matches_canonical_surface() {
573 assert_eq!(
574 super::IB20Extensions::mintWithMemoCall::SELECTOR,
575 canonical::IB20::mintWithMemoCall::SELECTOR
576 );
577 assert_eq!(
578 super::IB20Extensions::burnWithMemoCall::SELECTOR,
579 canonical::IB20::burnWithMemoCall::SELECTOR
580 );
581 assert_eq!(
582 super::IB20Extensions::burnBlockedCall::SELECTOR,
583 canonical::IB20::burnBlockedCall::SELECTOR
584 );
585 assert_eq!(
586 super::IB20Extensions::seizeWithMemoCall::SELECTOR,
587 canonical::IB20::seizeWithMemoCall::SELECTOR
588 );
589 assert_eq!(
590 super::IB20Extensions::policyIdCall::SELECTOR,
591 canonical::IB20::policyIdCall::SELECTOR
592 );
593 assert_eq!(
594 super::IB20Extensions::pauseCall::SELECTOR,
595 canonical::IB20::pauseCall::SELECTOR
596 );
597 assert_eq!(
598 super::IB20Extensions::contractURICall::SELECTOR,
599 canonical::IB20::contractURICall::SELECTOR
600 );
601 assert_eq!(
602 super::IB20Extensions::Seized::SIGNATURE_HASH,
603 canonical::IB20::Seized::SIGNATURE_HASH
604 );
605 assert_eq!(
606 super::IB20Extensions::Memo::SIGNATURE_HASH,
607 canonical::IB20::Memo::SIGNATURE_HASH
608 );
609 assert_eq!(
610 super::IB20Extensions::PolicyUpdated::SIGNATURE_HASH,
611 canonical::IB20::PolicyUpdated::SIGNATURE_HASH
612 );
613
614 assert_eq!(
616 super::IB20Extensions::PausableFeature::COUNT,
617 canonical::IB20::PausableFeature::COUNT
618 );
619 assert_eq!(
620 super::IB20Extensions::PausableFeature::SEIZE as u8,
621 canonical::IB20::PausableFeature::SEIZE as u8
622 );
623 }
624
625 #[test]
629 fn b20_surface_excludes_erc20_members() {
630 let mirrored: Vec<[u8; 4]> =
631 super::IB20Extensions::IB20ExtensionsCalls::selectors().collect();
632 for excluded in [
633 canonical::IB20::transferCall::SELECTOR,
634 canonical::IB20::transferFromCall::SELECTOR,
635 canonical::IB20::approveCall::SELECTOR,
636 canonical::IB20::balanceOfCall::SELECTOR,
637 canonical::IB20::allowanceCall::SELECTOR,
638 canonical::IB20::permitCall::SELECTOR,
639 canonical::IB20::hasRoleCall::SELECTOR,
640 canonical::IB20::grantRoleCall::SELECTOR,
641 ] {
642 assert!(
643 !mirrored.contains(&excluded),
644 "standard selector {excluded:?} must stay out of the global map"
645 );
646 }
647 }
648
649 #[test]
650 fn nonce_manager_abi_matches_canonical_selectors() {
651 assert_eq!(
652 super::INonceManager::getNonceCall::SELECTOR,
653 canonical::INonceManager::getNonceCall::SELECTOR
654 );
655 assert_eq!(
656 super::INonceManager::ExpiringNonceReplay::SELECTOR,
657 canonical::INonceManager::ExpiringNonceReplay::SELECTOR
658 );
659 assert_eq!(
660 super::INonceManager::InvalidExpiringNonceExpiry::SELECTOR,
661 canonical::INonceManager::InvalidExpiringNonceExpiry::SELECTOR
662 );
663 assert_eq!(
664 super::INonceManager::NonceIncremented::SIGNATURE_HASH,
665 canonical::INonceManager::NonceIncremented::SIGNATURE_HASH
666 );
667 }
668
669 #[test]
670 fn transaction_context_abi_matches_canonical_selectors() {
671 assert_eq!(
672 super::ITransactionContext::getTransactionSenderCall::SELECTOR,
673 canonical::ITransactionContext::getTransactionSenderCall::SELECTOR
674 );
675 assert_eq!(
676 super::ITransactionContext::getTransactionPayerCall::SELECTOR,
677 canonical::ITransactionContext::getTransactionPayerCall::SELECTOR
678 );
679 assert_eq!(
680 super::ITransactionContext::getTransactionSenderActorIdCall::SELECTOR,
681 canonical::ITransactionContext::getTransactionSenderActorIdCall::SELECTOR
682 );
683 }
684}