Skip to content

Latest commit

 

History

History
63 lines (40 loc) · 3.22 KB

097.md

File metadata and controls

63 lines (40 loc) · 3.22 KB

Stable Midnight Canary

Medium

Using loanId as the only input in function call is vulnerable to reorg attacks

Summary

Transactions are published to Ethereum typically within 5-10 minutes, up to 24 hours based on the Blast docs. This means that the newly created loan may initially have loanId = X, but due to reorg it loanId may be different when transaction is finalized. Load ids are incremented sequentially and users expect that their loan id remains unchanged. In case a transaction which creates a new load is not included in the final state all sequentially created loans will have id = initial id - 1. This can lead to unexpected result for the users when calling repay(), call(), auction() and seize().

Root Cause

Using only loanId as identifier in repay(), call(), auction() and seize() functions.

https://github.com/sherlock-audit/2024-09-predict-fun/blob/41e70f9eed3f00dd29aba4038544150f5b35dccb/predict-dot-loan/contracts/PredictDotLoan.sol#L454 https://github.com/sherlock-audit/2024-09-predict-fun/blob/41e70f9eed3f00dd29aba4038544150f5b35dccb/predict-dot-loan/contracts/PredictDotLoan.sol#L534 https://github.com/sherlock-audit/2024-09-predict-fun/blob/41e70f9eed3f00dd29aba4038544150f5b35dccb/predict-dot-loan/contracts/PredictDotLoan.sol#L561 https://github.com/sherlock-audit/2024-09-predict-fun/blob/41e70f9eed3f00dd29aba4038544150f5b35dccb/predict-dot-loan/contracts/PredictDotLoan.sol#L610

Internal pre-conditions

User repay(), call(), auction() and seize() with a loanId which wont correspond to the intended loan because of reorg.

External pre-conditions

Blockchain reorg. Blast is an optimistic rollup, just like Arbritrum, Base, Optimism, etc and Optimistic rollups are known for having re-org issues.

Attack Path

Depending on the called function and checks implemented in it there are two options :

  • The provided loanId will make the transaction revert due to internal checks.
  • The provided loanId will be a valid one and will lead to unexpected result for users.
  1. Loans are created via accept offers, match proposal, refinance.
  2. User send a transaction to one of the problematic functions
  3. Reorg happens
  4. Loan Id will be different from the moment the user submitted his transaction
  5. User transaction will be executed against a loan different than the intended one.

Possible attack on Ethereum mainnet:

  1. Loan with id = X is called shortly after it was created.
  2. User calls auction() to bid for loadId = X
  3. reorg happens
  4. Attacker frontrun the loan creation with id = X and creates unfavorable loan which will have id = X now, because ids are incremented sequentially.
  5. Attacker call the newly created loan.
  6. User will bid for the attacker's loan instead of the desired one.

Impact

Unexpected results for users.

PoC

N/A

Mitigation

Provide additional identifiers for the loan apart from the id and verify they match the  Loan storage loan = loans[loanId]; properties.

Another approach would be instead of using a number for the loanId, to use an identifier which is constructed from the number of the loan, lender and lets say block.timestamp. This will prevent the issue which comes from reorgs.