I write a test with a flashLoan receiver contract but the compilation fails because IThunderLoan doesn't support Flashloan()
contract POCtest is Test {
ThunderLoan thunderLoanImplementation;
MockPoolFactory mockPoolFactory;
ERC1967Proxy proxy;
ThunderLoan thunderLoan;
ERC20Mock weth;
ERC20Mock tokenA;
ERC20Mock tokenB;
ERC20Mock6Decimals tokenWith6Decimals;
AssetToken assetToken6Decimals;
AssetToken assetTokenA;
AssetToken assetTokenB;
address depositer = makeAddr("depositer");
address flahLoanReceiver = makeAddr("flashLoanReceiver");
address flashLoanAttacker = makeAddr("flashLoanAttacker");
function setUp() public virtual {
thunderLoan = new ThunderLoan();
mockPoolFactory = new MockPoolFactory();
weth = new ERC20Mock();
tokenA = new ERC20Mock();
tokenB = new ERC20Mock();
tokenWith6Decimals = new ERC20Mock6Decimals();
mockPoolFactory.createPool(address(tokenA));
mockPoolFactory.createPool(address(tokenWith6Decimals));
proxy = new ERC1967Proxy(address(thunderLoan), "");
thunderLoan = ThunderLoan(address(proxy));
thunderLoan.initialize(address(mockPoolFactory));
assetTokenB = thunderLoan.setAllowedToken(
IERC20(address(tokenB)),
true
);
assetToken6Decimals = thunderLoan.setAllowedToken(
IERC20(address(tokenWith6Decimals)),
true
);
tokenA.mint(depositer, 50000 * 10 ** tokenA.decimals());
tokenWith6Decimals.mint(
depositer,
5000 * 10 ** tokenWith6Decimals.decimals()
);
}
function testThunderLoanInterface() public {
tokenA.mint(depositer, 50000 * 10 ** tokenA.decimals());
assetTokenA = thunderLoan.setAllowedToken(
IERC20(address(tokenA)),
true
);
vm.startPrank(depositer);
uint256 depositAmount = tokenA.balanceOf(depositer);
tokenA.approve(address(thunderLoan), depositAmount);
thunderLoan.deposit(tokenA, depositAmount);
vm.stopPrank();
vm.startPrank(flahLoanReceiver);
FlashLoanReceiver receiverContract = new FlashLoanReceiver(
address(thunderLoan)
);
tokenA.mint(address(receiverContract), 100 * 10 ** tokenA.decimals());
receiverContract.requestFlashLoan(address(tokenA));
}
}
contract FlashLoanReceiver {
IThunderLoan private immutable i_thunderLoan;
constructor(address thunderLoan) {
i_thunderLoan = IThunderLoan(thunderLoan);
}
function requestFlashLoan(address _underlyingToken) external {
uint256 flashLoanAmount = 1 * 10 ** ERC20Mock(_underlyingToken).decimals();
i_thunderLoan.flashloan(
address(this),
IERC20(_underlyingToken),
flashLoanAmount,
""
);
}
function executeOperation(
address token,
uint256 amount,
uint256 fee,
address initiator,
bytes calldata params
) external {
IERC20(token).approve(address(i_thunderLoan), amount + fee);
i_thunderLoan.repay(token, amount + fee);
}
}
Implement all the public and external functions.
Import IERC20 from openZeppelin and change address token with IERC20 token on repay() function
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
+ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IThunderLoanFixed {
+ function initialize(address tswapAddress) external;
+ function deposit(address token, uint256 amount) external;
+ function redeem(address token, uint256 amountOfAssetToken) external;
+ function flashloan(
+ address receiverAddress,
+ address token,
+ uint256 amount,
+ bytes calldata params
+ ) external;
- function repay(address token, uint256 amount) external;
+ function repay(IERC20 token, uint256 amount) external;
+ function setAllowedToken(address token, bool allowed) external returns (address);
+ function getCalculatedFee(address token, uint256 amount) external view returns (uint256);
+ function updateFlashLoanFee(uint256 newFee) external;
+ function isAllowedToken(address token) external view returns (bool);
+ function getAssetFromToken(address token) external view returns (address);
+ function isCurrentlyFlashLoaning(address token) external view returns (bool);
+ function getFee() external view returns (uint256);
+ function getFeePrecision() external view returns (uint256);
}