This document explains the solution to the Tony Lend challenge presented in the Challenge.sol
and TonyLend.sol
contracts.
The Tony Lend challenge involves exploiting vulnerabilities in a lending protocol. The goal is to drain the challenge contract of its USDe tokens.
There are two main vulnerabilities in this challenge:
-
Incorrect Health Factor Calculation: In the
withdraw
function, the health factor is calculated before updating the user's deposited balance. This allows users to withdraw more than they should be able to. -
Insufficient Health Factor Threshold: The protocol considers a health factor of 1 (PRECISION) as healthy, which is too low and allows for full utilization of deposits as collateral.
The solution exploits these vulnerabilities in the following steps:
- Claim the initial "dust" tokens provided by the challenge.
- Deposit USDC into the lending protocol to use as collateral.
- Borrow the maximum amount of USDe against this collateral.
- Deposit the borrowed USDe back into the protocol.
- Withdraw the initially deposited USDe, which is possible due to the incorrect health factor calculation.
- Repeat steps 3-5 to amplify the borrowed amount.
- Transfer the acquired USDe to the specified address to solve the challenge.
The key steps in the Solution.s.sol
script are:
-
Claim initial tokens:
challenge.claimDust();
-
Deposit USDC as collateral:
tonyLend.deposit(1, usdc.balanceOf(vm.addr(privateKey)));
-
Borrow, deposit, and withdraw USDe in a loop:
tonyLend.borrow(0, 10_000e18); tonyLend.deposit(0, 10_000e18); tonyLend.withdraw(0, 10_000e18);
-
Transfer USDe to solve the challenge:
usde.transfer(address(0xc0ffee), 21927 ether);