Skip to content
Last updated: February 06, 2026

SCWE-111: Rebase Token Balance Drift

Stable Version v1.0

This content is in the version-(v1.0) and still under active development, so it is subject to change any time (e.g. structure, IDs, content, URLs, etc.).

Send Feedback

Relationships

Description

Rebasing tokens change user balances over time. Protocols that track deposited amounts as fixed units (instead of shares) can become insolvent or let users withdraw more than their fair share after positive or negative rebases.

Remediation

  • Track user positions using share-based accounting that scales with total supply.
  • Normalize balances on every interaction or use wrappers that expose a non-rebasing interface (e.g., wstETH).
  • Validate integrations against tokens with elastic supply and document unsupported assets.

Examples

Vulnerable

pragma solidity ^0.8.0;

contract Savings {
    IERC20 public rebasingToken;
    mapping(address => uint256) public deposits;

    function deposit(uint256 amount) external {
        rebasingToken.transferFrom(msg.sender, address(this), amount);
        deposits[msg.sender] += amount; // assumes static balance
    }
}

Fixed

pragma solidity ^0.8.0;

contract Savings {
    IERC20 public rebasingToken;
    mapping(address => uint256) public shares;
    uint256 public totalShares;

    function deposit(uint256 amount) external {
        uint256 supply = rebasingToken.totalSupply();
        uint256 share = totalShares == 0 ? amount : amount * totalShares / supply;
        shares[msg.sender] += share;
        totalShares += share;
        rebasingToken.transferFrom(msg.sender, address(this), amount);
    }
}