Repository navigation
feat(zones): park forced-exit fees in a separate claimable pool - #8440
adityapk00 wants to merge 10 commits into
Conversation
Pure rename, matching TIP-1012: `FORCED_EXIT_COMPENSATION` → `FORCED_EXIT_FEE`, `ForcedExitCompensationPending` → `ForcedExitFeePending`, and `ForcedExitCompensationRejected` → `ForcedExitFeeRejected`, plus the helpers, tests, metric name, and docs that use them. The T14 `ZonePortal` runtime is regenerated with `forge inspect ZonePortal deployedBytecode`; the local forge reproduces the previous runtime byte-for-byte, so only the renamed selectors, topics, and metadata hash change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A failed admin payout in `requestForcedExit` now credits `pendingForcedExitFees[token][admin]` (new slot 31) instead of the user `refunds` registry. `claimForcedExitFees(token)` pays the caller only, with the same TIP-1028 precheck and `CallbackRejected` revert as `claimRefund`, and emits `ForcedExitFeesClaimed`. It has no `Role.Account` check, so an admin outside the allowlist can still claim after AccessPolicy abdication, and fees stay with the admin credited at admission. The checker and `verify-portal-backing` count parked fees as their own liability. The checker's persisted `TokenState` gains a field, so its schema version moves to 2 and existing checker databases must be resynced. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
exithatch has not shipped, so its checker changes land under one schema version rather than bumping per PR. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…it-fee-pool-ffbf02
📊 Tempo Precompiles Coverage |
|
cyclops audit |
✅ Cyclops Security Review: safe to mergeLast reviewed: bd2a431 (latest) · no open findings
|
`pending_forced_exit_fees` changes the persisted `TokenState`, which ships on main at schema 1 with five fields. Bumping to 2 makes a database written by a main build fail the version check instead of a later token-row decode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`claimRefund` and `claimForcedExitFees` now pay through one `_payClaim` helper; each keeps its own access check and event. Regenerates the T14 `ZonePortal` runtime. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The refund, forced-exit fee, and inbox liability scans now sum through one `sum_amounts` helper, and `outstanding_refunds` becomes `outstanding` so the fee path no longer reports a refund history error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`setAdminReceives` replaces the repeated admin receive-policy toggles, and `assertFeeParked` takes its own balance snapshots. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Self-paying publishes the account as the L1 fee payer, which TIP-1012 says clients should warn about. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
cyclops audit |
There was a problem hiding this comment.
I reviewed this PR and didn't find any bugs. It changes how the ZonePortal holds and pays out funds and adds a new storage slot, and the files are under CODEOWNERS, so a human look would still be worthwhile.
What was reviewed:
- The
requestForcedExitfee parking, the newclaimForcedExitFees, and the shared_payClaimhelper. The helper zeroes the balance before the transfer and reverts withCallbackRejectedif the transfer fails.claimRefundstill runs_requireAllowedfirst and emits the same event as before. - Storage slot 31 for
pendingForcedExitFeesis appended after slot 30, so no existing slot moves. - In the checker, the new
ForcedExitFeeliability is included inliability()with checked addition, and zero-amount fee claims are ignored. ARefundClaimedevent can no longer clear a parked fee (there is a test assertingUnderflow).SCHEMA_VERSIONgoes from 1 to 2 for the newTokenStatefield.
Extended reasoning...
The diff is 22 files (about 900 lines added, 630 removed). It covers the ZonePortal Solidity contract, its storage layout, regenerated bindings and genesis bytecode, the zone checker's accounting and persistence, xtask tooling, and the spec and docs. The security-sensitive part is custody: who can claim parked forced-exit fees. claimForcedExitFees deliberately skips the Role.Account allowlist check, and pays only the admin who was credited when the forced exit was admitted. The paths are owned by CODEOWNERS (crates/zones/contracts, crates/contracts, crates/chainspec, xtask). An earlier inline bot thread on the checker accounting was resolved only by the PR author. Given the size, the change to fund handling and the code ownership, this goes to a human rather than being auto-approved.
Follow-up to #8401 for TIP-1012 (#7593, review thread).
A failed admin payout now parks the fee in
pendingForcedExitFees[token][admin]instead of userrefunds, andclaimForcedExitFees(token)pays it to the caller without aRole.Accountcheck, so an admin outside the allowlist can still claim after AccessPolicy abdication. Fees stay with the admin credited at admission and are paid only to that address, so a TIP-403 block on the admin still holds.claimRefundandclaimForcedExitFeesshare one payout helper;claimRefund's behaviour is unchanged. The checker andverify-portal-backingcount parked fees as a separate liability.The checker's persisted
TokenStategains apending_forced_exit_feesfield, so its schema version moves from 1 to 2. Existing checker databases fail to open with a schema mismatch and need a resync (delete<datadir>/checker).forced-withdrawnow warns when the account pays its own fee, since that publishes the account as the L1 fee payer.The first commit is a pure rename (compensation → fee).
🤖 Generated with Claude Code