Skip to content

fix(BOP-274): port Rust parity fixes into Solidity mocks #140

Open
stevieraykatz wants to merge 5 commits into
mainfrom
stevekatzman/bop-274-port-rust-parity-fixes-into-solidity-mocks
Open

fix(BOP-274): port Rust parity fixes into Solidity mocks #140
stevieraykatz wants to merge 5 commits into
mainfrom
stevekatzman/bop-274-port-rust-parity-fixes-into-solidity-mocks

Conversation

@stevieraykatz
Copy link
Copy Markdown
Member

@stevieraykatz stevieraykatz commented Jun 3, 2026

Summary

Brings two Solidity-mock behaviors back into parity with the Rust precompile after Roger flagged the divergences:

  • Mint receiver policy_mint no longer skips MINT_RECEIVER_POLICY when called from the factory bootstrap window. Rust enforces the policy unconditionally; the policy itself defaults to ALWAYS_ALLOW_ID for an unconfigured slot, so existing bootstrap flows are unaffected.
  • Burn-blocked target checkburnBlocked no longer skips the "target is blocked" check during bootstrap. Same shape as the mint fix: unconditional enforcement, default-allow when unconfigured.

The third subtask (is_announcement_active view) was explored but dropped — announce(...) only self-delegatecalls, so there is no external reentrancy surface that would want to detect a bracket-in-progress.

Linear: BOP-274.

Test plan

  • forge build clean
  • forge test — 607 tests pass, no regressions

Rust precompile enforces MINT_RECEIVER_POLICY unconditionally on every
mint, including factory-originated mints in the bootstrap window. The
Solidity mock previously bypassed the check whenever `_isPrivileged()`
held, which let initCalls mint to non-authorized accounts. Drop the
bypass so the mock matches Rust semantics. An unconfigured slot still
reads as ALWAYS_ALLOW_ID, so default-deploy bootstrap flows are
unaffected.
…rap (BOP-274)

Rust precompile enforces the "target account must be blocked under
TRANSFER_SENDER_POLICY" guard unconditionally on burnBlocked. The
Solidity mock previously bypassed the check whenever `_isPrivileged()`
held. Drop the bypass so factory-originated burnBlocked calls during the
bootstrap window also revert AccountNotBlocked unless the target is
actually blocked, matching Rust.
…OP-274)

The Rust precompile exposes an is_announcement_active runtime flag that
flips true for the lifetime of an announce(...) bracket and false at all
other times. The Solidity mock did not surface the same view, leaving
inner-call contracts no way to detect they were executing inside a
disclosed corp action.

Add the IB20Asset.isAnnouncementActive() interface entry and back it in
MockB20Asset with an EIP-1153 transient bool set at the top of announce
and cleared at the bottom. Transient storage auto-clears at tx end, so a
revert anywhere in the bracket cannot leave the flag stuck true.
@linear
Copy link
Copy Markdown

linear Bot commented Jun 3, 2026

BOP-274

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

Interface Coverage

✅ All interface functions have test coverage.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

📊 Forge Coverage (src/lib/)

🟢 ≥99% across all metrics.

File Lines Stmts Branches Funcs
🟢 B20FactoryLib.sol 100.00% 100.00% 100.00% 100.00%
🟢 MockActivationRegistry.sol 100.00% 100.00% 100.00% 100.00%
🟢 MockActivationRegistryStorage.sol 100.00% 100.00% 100.00% 100.00%
🟢 MockB20.sol 100.00% 100.00% 100.00% 100.00%
🟢 MockB20Asset.sol 100.00% 100.00% 100.00% 100.00%
🟡 MockB20Factory.sol 98.95% 99.08% 100.00% 100.00%
🟢 MockB20Stablecoin.sol 100.00% 100.00% 100.00% 100.00%
🟢 MockB20Storage.sol 100.00% 100.00% 100.00% 100.00%
🟢 MockPolicyRegistry.sol 100.00% 100.00% 100.00% 100.00%
🟢 MockPolicyRegistryStorage.sol 100.00% 100.00% 100.00% 100.00%
Total 99.86% 99.88% 100.00% 100.00%

Full report: download artifact. To browse locally: make coverage (runs forge coverage + genhtml + opens the HTML report).

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

✅ Fork tests: all 602 passed

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

@stevieraykatz stevieraykatz changed the title port Rust parity fixes into Solidity mocks (BOP-274) fix(BOP-274): port Rust parity fixes into Solidity mocks Jun 3, 2026
Comment thread test/lib/mocks/MockB20Asset.sol Outdated
Comment thread src/interfaces/IB20Asset.sol Outdated
The previous commit added an isAnnouncementActive() view backed by an
EIP-1153 transient flag, aiming for parity with the Rust precompile's
is_announcement_active runtime flag. On review the check is unnecessary:
inner-call dispatch in announce(...) is self-delegatecall only, so there
is no reentrancy surface for an external contract to want to detect a
bracket-in-progress against.

Removes the view from IB20Asset, the flag and its set/clear from
MockB20Asset.announce, and the boundary tests.
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.

3 participants