Skip to main content
Sigvex

Balance Accounting Mismatch Remediation

How to record the amount actually received by measuring the balance delta, so fee-on-transfer and rebasing tokens can't desync your books.

Balance Accounting Mismatch Remediation

Overview

Related Detector: Balance Accounting Mismatch

Recording a deposit using the amount passed to transferFrom assumes the contract received exactly that much. For fee-on-transfer, deflationary, or rebasing tokens, the amount received differs from the amount requested — so the books over-credit the user and the vault becomes insolvent. The remediation is to measure the actual balance change and account for that.

Before (Vulnerable)

function deposit(uint256 amount) external {
    token.transferFrom(msg.sender, address(this), amount);
    balances[msg.sender] += amount;   // wrong if the token took a fee
}

After (Fixed — credit the measured delta)

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;   // what actually arrived
    balances[msg.sender] += received;
}

Credit and later pay out the measured received, not the requested amount, so the vault’s liabilities always match its holdings. If your protocol cannot support non-standard tokens, reject them explicitly with an allowlist rather than mis-accounting.

Common Mistakes

  • Measuring the delta on deposit but paying out the nominal amount on withdrawal, reintroducing the mismatch.
  • Using the balance-delta pattern while a reentrant token hook lets the balance change mid-measurement — combine with a reentrancy guard.
  • Assuming a token is standard because it “looks like” ERC-20; fee-on-transfer behaviour is not visible from the interface.

References