Skip to content

Make excess tokens withdrawable #177

Description

@michael1011

Summary

Introduce per-token accounting in our swap contracts so that tokens which end up stuck in the contract (but are not backing any active swap) can be withdrawn safely by an admin address.

Background

What happens to tokens that get stuck in a swap contract?

Why tokens get stuck

ERC20 transfers do not call the recipient contract — the contract has no hook and no awareness that a transfer happened. This means anyone can send arbitrary ERC20 tokens to our swap contract address at any time, and we cannot prevent it at the contract level.

Concrete example:

  • You lock 5 USDT in a swap
  • I lock 2 USDT in a swap
  • Someone sends 3 USDT directly to the contract for no reason
  • The contract now holds 10 USDT, but only 7 are backing real swaps
  • The extra 3 USDT are stuck forever unless we do something

We also can't rely on tying withdrawals to specific swap-creation transactions, because ERC20 tokens are fungible by definition — there is no on-chain link between "a swap" and "the tokens that fund it".

Proposed solution: double accounting

Track, inside the contract, the total amount that should be locked per ERC20 token to cover outstanding swaps. Anything the contract holds above that accounted amount is by definition excess and can be withdrawn by an admin address.

  • Source of truth for the locked amount is the contract itself, so it can't be cheated.
  • Our contract is generic over any ERC20; today we happen to use it mainly for tBTC, but the accounting must be per-token.

Example state:

  • tBTC locked for pending swaps: 0.1235233234 → contract must retain at least this much tBTC
  • USDT0 locked for pending swaps: 0 → any USDT0 in the contract is withdrawable
  • ARB locked for pending swaps: 0 → any ARB in the contract is withdrawable
  • USDC locked for pending swaps: 0 → any USDC in the contract is withdrawable

Admin withdrawal is then "withdraw everything in excess of the locked accounting" — per token

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