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.).
Relationships¶
- CWE-682: Incorrect Calculation
https://cwe.mitre.org/data/definitions/682.html
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);
}
}