This review is based on the rebasing design described in the article βCoding a Solidity rebase tokenβ. It evaluates potential vulnerabilities and provides recommendations within the context of the rebasing mechanism.
- Verify share and asset calculation formulas
- Review slippage calculation logic during share issuance
- Inspect mint, burn, and transfer logic for accurate share/asset handling
- Handle dust rounding errors in
_amountToShare()during burn and transfer
Anyone can directly theft over-rebasing assets that have been inflated donated via burn().
The current implementation is vulnerable to a small deposit attack, where shares may round down to zero:
"Since there is no 0 share check in
burn(), attackers can exploit over-rebasing assets."
β Coding a Solidity rebase token
To mitigate zero-share rounding, the original formula is scaled:
sharesToCreate * 10,000 * address(this).balance >= slippageBp * msg.value * _totalShares
When slippageBp = 0, the user is fully exposed to rebasing volatility.
Actors:
bob: Owneralice: Attackercharlie: Innocent User
Steps:
- Pool starts with 0 shares (no bootstrap).
alicemints with1 weito preempt a small share.charliemints1 ETHwithslippageBp = 0.alicefrontruns and donates100 ETH, causingcharlie's share to round to 0.alicetries toburn()the pool, butcharliefrontruns and burns first.- Result:
charliesteals 101 ETH despite holding 0 shares.
function test_sx() public {
vm.prank(alice);
token.mint{value: 1 wei}(alice, 0);
vm.prank(alice);
address(token).call{value: 100 ether}("");
vm.prank(charlie);
token.mint{value: 1 ether}(charlie, 0);
vm.prank(charlie);
token.burn(charlie, 101 ether);
}Explanation:
In the formula:
(amount * _totalShares) / address(this).balance
If the result is 0 due to integer division, but burn() lacks a zero-share check, then rebased assets can be stolen.
-
Revert
burn()if_amountToShares()returns 0. -
Apply a Virtual Offset in
mint()to prevent early ratio distortion:VOFFSET = 1; sharesToCreate = msg.value * (_totalShares + VOFFSET) / (prevBalance + VOFFSET);
This avoids division by zero and stabilizes minting when balance or
_totalSharesis near 0. -
Do NOT apply offset to
burn()β rebasing effects from donations should be preserved accurately in withdrawals.
check below patch.sol
- Ensure
slippageBpis within (0,10,000] - Revert if
msg.value == 0duringmint()