Skip to content

Handle missed transfers #77

@anhthii

Description

@anhthii

Sui — Missed Transfer Scenarios
Current implementation (sui.go:308-385) picks only the single largest positive BalanceChange to a non-sender. Everything else is dropped.

Note: DEX swaps are out of scope — we only need to track direct token transfers.

  1. Multi-recipient PTB
    Scenario: A PTB sends SUI to address A, USDC to address B, and USDT to address C.
    Impact: Only the largest transfer is captured. The other two are dropped.
    Mitigation: Iterate ALL BalanceChanges with positive amounts to non-sender addresses. Emit one types.Transaction per balance change.

  2. Same-token multi-send
    Scenario: A PTB splits 1000 SUI: sends 600 to A and 400 to B.
    Impact: Only 600 SUI to A is captured. 400 SUI to B is dropped.
    Mitigation: Same as above — each BalanceChange entry is a separate transfer.

  3. Sponsored transactions
    Scenario: A gas sponsor pays the fee. The sponsor appears as a balance change (negative SUI for gas). The actual transfer's sender may differ from the gas payer.
    Impact: t.FromAddress is set from execTx.Transaction.GetSender(). If the sponsor is the sender but not the transferor, the sender filter may incorrectly skip the real recipient's balance change, or attribute the wrong sender.
    Mitigation: Use BalanceChanges to determine actual sender (largest negative non-gas change) rather than relying solely on Transaction.Sender.

  4. Self-transfers / consolidation
    Scenario: User merges coin objects or transfers to themselves. Sender == recipient in BalanceChanges.
    Impact: Filtered out by the sender == address check at line 353.
    Mitigation: If self-transfers matter, remove or relax the sender filter.

  5. Coin minting
    Scenario: A protocol mints tokens to a user. There's a positive BalanceChange for the recipient but no corresponding negative change from a sender.
    Impact: If the mint recipient happens to be the tx sender, it's filtered out.
    Mitigation: Handle the case where sender has no negative balance change for that coin type (mint scenario).

  6. Zero-amount or dust transfers
    Scenario: A PTB sends small amounts to many addresses (common in airdrops or claim txs).
    Impact: These have small BalanceChange amounts and will never be the "largest", so they're always dropped.
    Mitigation: Emit all non-zero balance changes.

Sui fix strategy
Replace the "pick largest" heuristic with "emit all balance changes".

// For each BalanceChange with positive amount to a non-sender:
for i, bc := range execTx.BalanceChanges {
// ... build types.Transaction with TransferIndex = i
txs = append(txs, tx)
}
This single change fixes scenarios 1, 2, and 6. For scenarios 3-5, additionally:

Remove or relax the sender == address filter (scenario 4)
Use balance changes to infer real sender rather than Transaction.Sender (scenario 3)
Note: Sui multisig is just a different signature scheme, not a different contract call path. The PTB and BalanceChanges are identical to single-signer txs, so multisig is automatically covered by the fix above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions