Skip to content

test(precompiles): add golden tests for asset V1 (BOP-423)#3972

Open
stephancill wants to merge 5 commits into
mainfrom
stephancilliers/bop-423-asset-golden
Open

test(precompiles): add golden tests for asset V1 (BOP-423)#3972
stephancill wants to merge 5 commits into
mainfrom
stephancilliers/bop-423-asset-golden

Conversation

@stephancill

Copy link
Copy Markdown
Contributor

Summary

Adds a golden/snapshot test suite pinning current Asset V1 behavior of the B-20 precompile (BOP-423), before/while it is frozen behind the versioning seam introduced in #3969 (BOP-417). Sibling of the stablecoin golden suite (#3971).

Every op is driven through the version-resolver-gated path (inner(..., BaseUpgrade::Beryl)AssetVersions::from_base_upgrade → V1) against the real EVM-backed B20AssetStorage over HashMapStorageProvider, with InMemoryPolicy for deterministic allow/block. Each mutation case asserts:

  1. exact returned ABI bytes,
  2. resulting state (balances / supply / roles / allowances / multiplier / metadata / storage),
  3. emitted event signature(s), and
  4. a pinned keccak storage state-root over the sorted storage triples — the reference baseline for the CI frozen-manifest check (BOP-421).

Coverage: the shared B-20 surface (transfer / transferFrom / approve + memo variants, mint / burn / burnBlocked, pause / unpause, updateSupplyCap|Name|Symbol|ContractURI, grant/revoke/renounce/renounceLastAdmin/setRoleAdmin, updatePolicy, permit, all reads + role/policy constants), plus the asset-specific ops: updateMultiplier (operator role, zero-reject), updateExtraMetadata (empty-key reject), batchMint (length-mismatch / empty-batch), announce (internal-call loop, reused-id, nested-announce, malformed / failing internal call), and the scaled-balance reads (multiplier, toScaledBalance, toRawBalance, scaledBalanceOf, configurable decimals). Privileged vs unprivileged via inner_with_privilege vs inner; the guard envelope (nonpayable / uninitialized / pre-Beryl) via full dispatch_with_observer.

No source/logic changes — frozen V1 is untouched; only a new integration test file and one [[test]] stanza are added.

Testing

  • cargo test -p base-common-precompiles --features test-utils --test b20_asset_v1_golden → 68 passed
  • cargo test -p base-common-precompiles --features test-utils → 486 + 68 passed
  • clippy (--all-targets) and fmt clean

State-roots are pinned; regenerate with BLESS_GOLDEN=1 cargo test ... -- --nocapture (documented in the file header).

Co-authored-by: OpenCode <opencode-noreply@coinbase.com>
@linear

linear Bot commented Jul 15, 2026

Copy link
Copy Markdown

BOP-423

@cb-heimdall

Copy link
Copy Markdown
Collaborator

🟡 Heimdall Review Status

Requirement Status More Info
Reviews 🟡 0/1
Denominator calculation
Show calculation
1 if user is bot 0
1 if user is external 0
2 if repo is sensitive 0
From .codeflow.yml 1
Additional review requirements
Show calculation
Max 0
0
From CODEOWNERS 0
Global minimum 0
Max 1
1
1 if commit is unverified 0
Sum 1

stephancill and others added 3 commits July 15, 2026 22:41
Co-authored-by: OpenCode <opencode-noreply@coinbase.com>
Co-authored-by: OpenCode <opencode-noreply@coinbase.com>
…pwire

Co-authored-by: OpenCode <opencode-noreply@coinbase.com>
Comment on lines +24 to +29
use alloy_sol_types::{SolCall, SolError, SolEvent, SolInterface, SolValue};
use base_common_genesis::BaseUpgrade;
use base_common_precompiles::{
Asset, AssetAccounting, AssetV1, AssetVersion, AssetVersions, B20_MAX_SUPPLY_CAP, B20AssetInit,
B20AssetStorage, B20AssetToken, B20PolicyType, B20TokenRole, IB20, IB20Asset, InMemoryPolicy,
NoopPrecompileCallObserver, PermitArgs, TokenAccounting,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Three unused imports: SolError (line 24), Asset and TokenAccounting (lines 27, 29). Clippy should catch these — remove them to keep CI clean.

Suggested change
use alloy_sol_types::{SolCall, SolError, SolEvent, SolInterface, SolValue};
use base_common_genesis::BaseUpgrade;
use base_common_precompiles::{
Asset, AssetAccounting, AssetV1, AssetVersion, AssetVersions, B20_MAX_SUPPLY_CAP, B20AssetInit,
B20AssetStorage, B20AssetToken, B20PolicyType, B20TokenRole, IB20, IB20Asset, InMemoryPolicy,
NoopPrecompileCallObserver, PermitArgs, TokenAccounting,
use alloy_sol_types::{SolCall, SolEvent, SolInterface, SolValue};
use base_common_genesis::BaseUpgrade;
use base_common_precompiles::{
AssetAccounting, AssetV1, AssetVersion, AssetVersions, B20_MAX_SUPPLY_CAP, B20AssetInit,
B20AssetStorage, B20AssetToken, B20PolicyType, B20TokenRole, IB20, IB20Asset, InMemoryPolicy,
NoopPrecompileCallObserver, PermitArgs,

Co-authored-by: OpenCode <opencode-noreply@coinbase.com>
@github-actions

Copy link
Copy Markdown
Contributor

Review Summary

Test-only PR adding golden/snapshot tests for Asset V1 — no production code changes.

One finding (already raised inline): three unused imports (SolError, Asset, TokenAccounting) on lines 24/27/29 that will fail CI under -D warnings. Remove them.

No other issues. The test harness is well-designed: each test gets an isolated fresh() provider, the hash_state capacity math is correct (20+32+32=84), the v1_op_coverage_checklist compile-time exhaustive match is a solid pattern for ensuring frozen-surface coverage, and #[track_caller] on assert_root aids debuggability.

@github-actions

Copy link
Copy Markdown
Contributor

✅ base-std fork tests: all 616 passed

base/base is fully in sync with the base-std spec.

Dependency Ref Commit
base-std main 4658f1b7
base-anvil f4370bc97756557d0ef1a6c325ad7d2532e71112 f4370bc9

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants