First depositor can steal funds from subsequent depositors #107
Labels
bug
Something isn't working
downgraded by judge
Judge downgraded the risk level of this issue
duplicate-848
grade-b
Q-101
QA (Quality Assurance)
Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax
satisfactory
satisfies C4 submission criteria; eligible for awards
sponsor disputed
Sponsor cannot duplicate the issue, or otherwise disagrees this is an issue
Lines of code
https://github.com/code-423n4/2023-02-ethos/blob/73687f32b934c9d697b97745356cdf8a1f264955/Ethos-Vault/contracts/ReaperVaultV2.sol#L319
Vulnerability details
First depositor can steal funds from subsequent depositors
Summary
The first vault depositor can deposit a very minimal amount of tokens, such as 1 wei, followed by sending a larger amount of funds directly to the vault contract. This results in subsequent depositors receiving zero LP tokens for their deposit unless it is greater than the amount of funds deposited by the initial bad actor, and the funds will be received by the bad actor.
Detailed description
ReaperVaultV2._deposit()
handles user deposits. The method takes the amount of tokens to be deposited as argument_amount
and credits the corresponding amount of shares / LP tokens. In the special case of a deposit being the first deposit, i.e.totalSupply() == 0
, a different formula for the LP token calculation will be used, and the depositor simply gets the amount of tokens deposited credited as LP tokens,shares = _amount
.A bad actor can abuse this behaviour by depositing a very small amount, such as 1 wei, as the first deposit, and then sending a larger amount of tokens directly to the vault:
withdrawAll()
to receive all deposited funds, including funds from other usersRecommended mitigation
Uniswap V2 solves this problem by a) requiring the initial deposit to have a certain minimum size and b) send the first 1000 wei of LP tokens to the zero address:
I recommend the same solution in this case.
PoC
The PoC is implemented as Hardhat test.
First add the following file as
Import.sol
toEthos-Vault/contracts
. This allows the test to use theERC20PresetMinterPauser
contract:Then add the following code as
Exploit.test.js
toEthos-Vault/test
:Run the test by using
npx hardhat test test/Exploit.test.js
. Note that you should previously set up a private key in a.env
file or hardcode it inhardhat.config.js
asPRIVATE_KEY = ...
. This is due to the existing structure of the codebase.After running the test you should see the following output:
The text was updated successfully, but these errors were encountered: