fix(collateralize,issuance): return repaid collateral to borrow record owner - #1308
Open
33cn wants to merge 2 commits into
Open
fix(collateralize,issuance): return repaid collateral to borrow record owner#130833cn wants to merge 2 commits into
33cn wants to merge 2 commits into
Conversation
added 2 commits
August 31, 2026 10:51
…d owner CollateralizeRepay and IssuanceRepay transferred the collateral back to the transaction sender (action.fromaddr) instead of the borrow/debt record owner. Any third party could repay someone else's debt at the cost of principal plus stability fee and steal the borrower's over-collateralized BTY. Gate the fix behind the new dapp forks ForkCollateralizeRepayOwner and ForkIssuanceRepayOwner: after the fork the collateral is returned to record.AccountAddr; before the fork the old behavior is preserved to keep consensus of running chains. Third-party repayment itself remains allowed (repay-on-behalf is a legitimate feature), only the collateral refund target is fixed.
…d proxyminer configs chain33 validates that every registered dapp fork has a config entry on non-local titles; missing entries crash the node at startup, which broke ci_cross2eth/ci_parachain_rollup/ci_paracross/ci_rgbx.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Vulnerability
Third-party repayment steals the borrower's over-collateralized BTY.
plugin/dapp/collateralize/executor/collateralizedb.go:663-769(CollateralizeRepay): at line 742 the collateral is returned viaExecTransferFrozen(coll.CreateAddr, action.fromaddr, ...)— to the transaction sender, not toborrowRecord.AccountAddr. There is no borrower identity check anywhere in the function.plugin/dapp/issuance/executor/issuancedb.go:630-719(IssuanceRepay): same flaw at line 691 — collateral goes toaction.fromaddrinstead ofdebtRecord.AccountAddr.Root cause
Any account can repay an arbitrary borrow/debt record (this itself is a legitimate repay-on-behalf feature), but the collateral refund target was hardcoded to the caller. An attacker therefore pays only the debt principal (plus the small stability fee in collateralize) and receives the borrower's full collateral — about 4x the repayment cost at a 0.25 liquidation ratio.
Fix
Change the collateral refund target, not the repayment permission:
record.AccountAddr); the caller only loses the repayment funds.CollateralizeAppendlets any address add collateral to someone else's record, and neither repay path ever checkedfromaddr == record.AccountAddr. So repay-on-behalf is kept as a feature and only the theft vector (wrong refund target) is closed.Fork gating
New dapp forks registered at height 0, following the
ForkEVMFixOverflowpattern:ForkCollateralizeRepayOwnerinplugin/dapp/collateralize/types(RegisterDappForkinInitFork, gated viacfg.IsDappForkinCollateralizeRepay)ForkIssuanceRepayOwnerinplugin/dapp/issuance/types(same pattern inIssuanceRepay)Both are also added to
chain33.fork.tomlalongside the existing sibling forks. Before the fork the old behavior (refund to caller) is preserved so running chains keep consensus.Tests
New regression tests (no changes to existing tests):
plugin/dapp/collateralize/executor/vuln_fix_test.goTestRepayOwnerForkRepayByNonBorrower: post-fork, a third-party repayer's collateral stays untouched; collateral goes back to the borrower's exec account; repayer only loses debt+fee, which is less than the collateral value.TestRepayOwnerForkRepayByBorrower: borrower self-repay still works and returns the collateral.TestRepayOwnerPreForkRepayByNonBorrower: pre-fork behavior unchanged (collateral to caller).plugin/dapp/issuance/executor/vuln_fix_test.go: same three scenarios (TestRepayOwnerForkRepayByNonDebtor,TestRepayOwnerForkRepayByDebtor,TestRepayOwnerPreForkRepayByNonDebtor).go test -ldflags=-checklinkname=0 ./plugin/dapp/collateralize/... ./plugin/dapp/issuance/...passes, including all pre-existing tests.