Skip to content

fix(retrieve): clear retrieve relation after perform to prevent replay in ForkRetriveAsset branch - #1313

Open
33cn wants to merge 2 commits into
masterfrom
fix-retrieve-perform-replay
Open

fix(retrieve): clear retrieve relation after perform to prevent replay in ForkRetriveAsset branch#1313
33cn wants to merge 2 commits into
masterfrom
fix-retrieve-perform-replay

Conversation

@33cn

@33cn 33cn commented Aug 31, 2026

Copy link
Copy Markdown
Owner

Vulnerability

In plugin/dapp/retrieve/executor/retrievedb.go:292-294, once ForkRetriveAsset is active, RetrievePerform returns directly from the RetrievePerformAssets(...) branch and skips the UnRelateDB + Save cleanup done by the legacy path (lines 310-311).

Consequences after a successful retrieve:

  • The backup<->default relation remains in state, stuck at retrievePrepare status.
  • The delay-period check (blocktime - PrepareTime >= DelayPeriod) stays satisfied forever.
  • The backup address can replay perform at any time — without a new prepare and without waiting the delay period — and drain any assets deposited to the default address later. The default address owner has lost the key by definition and cannot cancel to defend themselves.

Fix

When the new ForkRetrivePerformRelay dapp fork is active, a successful perform in the ForkRetriveAsset branch now also executes UnRelateDB + Save, removing the retrieve relation and aligning with the semantics of the pre-asset-fork path. A second perform is then rejected with ErrRetrieveRelation.

Fork gating

  • New dapp fork ForkRetrivePerformRelay registered in plugin/dapp/retrieve/types (default height 0), following the existing ForkRetrive / ForkRetriveAsset naming style.
  • Behavior before the fork is completely unchanged (consensus-safe for live chains).
  • chain33.fork.toml and chain33.para.toml updated with the corresponding ForkRetrivePerformRelay entry, following the ForkEVMFixOverflow pattern.

Tests

New regression tests in plugin/dapp/retrieve/executor/retrieve_perform_replay_test.go:

  • TestRetrievePerformClearRelationPostFork: after a successful perform the relation is cleared; a second perform is rejected; assets deposited to the default address afterwards stay untouched.
  • TestRetrievePerformReplayPreFork: pre-fork behavior is unchanged (relation kept after perform).
  • TestRetrieveNormalFlowPostFork: normal backup/prepare/perform/cancel flow is unaffected post-fork.

Verified with:

go test -ldflags=-checklinkname=0 -count=1 ./plugin/dapp/retrieve/...

All existing and new tests pass.

king added 2 commits August 31, 2026 11:41
…set branch

After ForkRetriveAsset, RetrievePerform returns directly from the
RetrievePerformAssets branch without removing the backup<->default
relation, so the backup address can replay perform at any time and
drain assets deposited to the default address later.

Gate the fix behind the new ForkRetrivePerformRelay dapp fork: on
successful perform, remove the relation and save it to state, aligned
with the pre-asset-fork path. Pre-fork behavior is unchanged.
After ForkRetrivePerformRelay, a successful perform clears the
backup<->default relation, so the token perform must establish a new
relation and wait the delay period instead of replaying on the old one.
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.

1 participant