Skip to main content
Sigvex

Rebasing Token Remediation

How to support elastic-supply tokens by tracking shares or measuring balances instead of caching amounts.

Rebasing Token Remediation

Overview

Related Detector: Rebasing Token

Elastic-supply tokens (stETH, AMPL, and similar) change holder balances between transactions without a transfer. A vault that records “user deposited 100” and later returns 100 pays out the wrong amount after a rebase — too much, draining the vault, or too little, stranding users. The remediation is to store a rebase-invariant unit (shares) or to measure the actual balance received, rather than caching a nominal amount.

Before (Vulnerable)

mapping(address => uint256) public deposited;

function deposit(uint256 amount) external {
    token.transferFrom(msg.sender, address(this), amount);
    deposited[msg.sender] += amount;   // stale after any rebase
}

After (Fixed — share accounting from measured balances)

mapping(address => uint256) public shares;
uint256 public totalShares;

function deposit(uint256 amount) external {
    uint256 before = token.balanceOf(address(this));
    token.transferFrom(msg.sender, address(this), amount);
    uint256 received = token.balanceOf(address(this)) - before;   // handles fee-on-transfer too

    uint256 minted = totalShares == 0
        ? received
        : (received * totalShares) / before;
    shares[msg.sender] += minted;
    totalShares += minted;
}

Redemptions then pay shares * currentBalance / totalShares, so each user’s claim tracks rebases automatically.

Common Mistakes

  • Storing nominal amounts and assuming balanceOf will still match them after a rebase.
  • Using the transfer argument as the amount received, which breaks for both rebasing and fee-on-transfer tokens; measure the delta.
  • Allowing arbitrary rebasing tokens into a vault designed around fixed balances without an explicit allowlist.

References