Another fun challenge, this one with a real world hack example:
The one thing I don't understand in this solution is how the second-order call to approve on a separate ERC20 contract after calling target.functionCall(data)
is run in the context of the pool
given that under the hood functionCall
uses the call
opcode, not delegatecall
Would the call chain look like this?:
EOA -> (msg.sender = attacker EOA) pool.flashLoan -> (msg.sender == pool) attackContract -> (msg.sender == attackContract) erc20.approve
Aha, I see now - we're not passing the attack contract as the target param. Just the token address. Nice!