Skip to content

Commit c4574d9

Browse files
committed
approveZRC20
1 parent 88635ef commit c4574d9

File tree

8 files changed

+128
-32
lines changed

8 files changed

+128
-32
lines changed

examples/call/commands/common.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import path from "path";
22
import fs from "fs";
33
import { ethers } from "ethers";
44
import { Command } from "commander";
5+
import ZRC20ABI from "@zetachain/protocol-contracts/abi/ZRC20.sol/ZRC20.json";
56

67
export const getAbi = (name: string) => {
78
const abiPath = path.resolve(
@@ -27,6 +28,45 @@ export const createRevertOptions = (options: {
2728
};
2829
};
2930

31+
export const approveZRC20 = async (
32+
zrc20Address: string,
33+
contract: string,
34+
amount: string,
35+
signer: ethers.Wallet,
36+
gasLimit?: number
37+
) => {
38+
const zrc20 = new ethers.Contract(zrc20Address, ZRC20ABI.abi, signer);
39+
const [gasZRC20, gasFee] = gasLimit
40+
? await zrc20.withdrawGasFeeWithGasLimit(gasLimit)
41+
: await zrc20.withdrawGasFee();
42+
43+
const zrc20TransferTx = await zrc20.approve(contract, gasFee);
44+
await zrc20TransferTx.wait();
45+
46+
const decimals = await zrc20.decimals();
47+
if (gasZRC20 === zrc20.target) {
48+
const targetTokenApprove = await zrc20.approve(
49+
contract,
50+
gasFee + ethers.parseUnits(amount, decimals)
51+
);
52+
await targetTokenApprove.wait();
53+
} else {
54+
const targetTokenApprove = await zrc20.approve(
55+
contract,
56+
ethers.parseUnits(amount, decimals)
57+
);
58+
await targetTokenApprove.wait();
59+
const gasZRC20Contract = new ethers.Contract(
60+
gasZRC20,
61+
ZRC20ABI.abi,
62+
signer
63+
);
64+
const gasFeeApprove = await gasZRC20Contract.approve(contract, gasFee);
65+
await gasFeeApprove.wait();
66+
}
67+
return { decimals };
68+
};
69+
3070
export const createCommand = (name: string) => {
3171
return new Command(name)
3272
.requiredOption(
@@ -54,11 +94,12 @@ export const createCommand = (name: string) => {
5494
"Gas limit for revert tx",
5595
"500000"
5696
)
57-
.option("-n, --name <contract>", "Contract name", "Connected")
97+
.option("-n, --name <contract>", "Contract name")
5898
.option(
5999
"--rpc <url>",
60100
"RPC endpoint",
61101
"https://zetachain-athens-evm.blockpi.network/v1/rpc/public"
62102
)
103+
.option("--gas-limit <number>", "Gas limit for the transaction", "1000000")
63104
.option("--private-key <key>", "Private key to sign the transaction");
64105
};

examples/call/commands/connected/call.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ const main = async (options: any) => {
1717
const tx = await contract.call(
1818
options.receiver,
1919
message,
20-
createRevertOptions(options)
20+
createRevertOptions(options),
21+
{ gasLimit: options.gasLimit }
2122
);
2223
await tx.wait();
2324

examples/call/commands/connected/deposit.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const main = async (options: any) => {
1212
const tx = await contract.deposit(
1313
options.receiver,
1414
createRevertOptions(options),
15-
{ value: ethers.parseEther(options.amount) }
15+
{ value: ethers.parseEther(options.amount), gasLimit: options.gasLimit }
1616
);
1717
await tx.wait();
1818

examples/call/commands/connected/depositAndCall.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const main = async (options: any) => {
1818
options.receiver,
1919
message,
2020
createRevertOptions(options),
21-
{ value: ethers.parseEther(options.amount) }
21+
{ value: ethers.parseEther(options.amount), gasLimit: options.gasLimit }
2222
);
2323
await tx.wait();
2424

examples/call/commands/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ import { connectedDepositCommand } from "./connected/deposit";
66
import { connectedDepositAndCallCommand } from "./connected/depositAndCall";
77
import { universalCallCommand } from "./universal/call";
88
import { universalWithdrawCommand } from "./universal/withdraw";
9+
import { universalWithdrawAndCallCommand } from "./universal/withdrawAndCall";
910

1011
const program = new Command()
1112
.helpCommand(false)
1213
.addCommand(connectedCallCommand)
1314
.addCommand(connectedDepositCommand)
1415
.addCommand(connectedDepositAndCallCommand)
1516
.addCommand(universalCallCommand)
16-
.addCommand(universalWithdrawCommand);
17+
.addCommand(universalWithdrawCommand)
18+
.addCommand(universalWithdrawAndCallCommand);
1719

1820
if (require.main === module) program.parse();
1921

examples/call/commands/universal/call.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const main = async (options: any) => {
3636
isArbitraryCall: options.callOptionsIsArbitraryCall,
3737
},
3838
createRevertOptions(options),
39-
{ gasLimit: 2000000 }
39+
{ gasLimit: options.gasLimit }
4040
);
4141
await tx.wait();
4242

examples/call/commands/universal/withdraw.ts

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import { ethers } from "ethers";
22

3-
import { createCommand, createRevertOptions, getAbi } from "../common";
4-
import ZRC20ABI from "@zetachain/protocol-contracts/abi/ZRC20.sol/ZRC20.json";
3+
import {
4+
approveZRC20,
5+
createCommand,
6+
createRevertOptions,
7+
getAbi,
8+
} from "../common";
59

610
const main = async (options: any) => {
711
const provider = new ethers.JsonRpcProvider(options.rpc);
@@ -10,35 +14,19 @@ const main = async (options: any) => {
1014
const { abi } = getAbi(options.name);
1115
const contract = new ethers.Contract(options.contract, abi, signer);
1216

13-
const zrc20 = new ethers.Contract(options.zrc20, ZRC20ABI.abi, signer);
14-
const [gasZRC20, gasFee] = await zrc20.withdrawGasFee();
15-
16-
const zrc20TransferTx = await zrc20.approve(options.contract, gasFee);
17-
18-
await zrc20TransferTx.wait();
19-
20-
const decimals = await zrc20.decimals();
21-
if (gasZRC20 === options.zrc20) {
22-
const targetTokenApprove = await zrc20.approve(
23-
options.contract,
24-
gasFee + ethers.parseUnits(options.amount, decimals)
25-
);
26-
await targetTokenApprove.wait();
27-
} else {
28-
const targetTokenApprove = await zrc20.approve(
29-
options.contract,
30-
ethers.parseUnits(options.amount, decimals)
31-
);
32-
await targetTokenApprove.wait();
33-
const gasFeeApprove = await gasZRC20.approve(options.contract, gasFee);
34-
await gasFeeApprove.wait();
35-
}
17+
const { decimals } = await approveZRC20(
18+
options.zrc20,
19+
options.contract,
20+
options.amount,
21+
signer
22+
);
3623

3724
const tx = await contract.withdraw(
3825
options.receiver,
3926
ethers.parseUnits(options.amount, decimals),
4027
options.zrc20,
41-
createRevertOptions(options)
28+
createRevertOptions(options),
29+
{ gasLimit: options.gasLimit }
4230
);
4331
await tx.wait();
4432

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { ethers } from "ethers";
2+
3+
import {
4+
approveZRC20,
5+
createCommand,
6+
createRevertOptions,
7+
getAbi,
8+
} from "../common";
9+
10+
const main = async (options: any) => {
11+
const provider = new ethers.JsonRpcProvider(options.rpc);
12+
const signer = new ethers.Wallet(options.privateKey, provider);
13+
14+
const message = ethers.AbiCoder.defaultAbiCoder().encode(
15+
options.types,
16+
options.values
17+
);
18+
19+
const functionSignature = ethers.id(options.function).slice(0, 10);
20+
21+
const payload = ethers.hexlify(ethers.concat([functionSignature, message]));
22+
23+
const { abi } = getAbi(options.name);
24+
const contract = new ethers.Contract(options.contract, abi, signer);
25+
26+
const { decimals } = await approveZRC20(
27+
options.zrc20,
28+
options.contract,
29+
options.amount,
30+
signer,
31+
options.callOptionsGasLimit
32+
);
33+
34+
const tx = await contract.withdrawAndCall(
35+
options.receiver,
36+
ethers.parseUnits(options.amount, decimals),
37+
options.zrc20,
38+
payload,
39+
{
40+
gasLimit: options.callOptionsGasLimit,
41+
isArbitraryCall: options.callOptionsIsArbitraryCall,
42+
},
43+
createRevertOptions(options),
44+
{ gasLimit: options.gasLimit }
45+
);
46+
await tx.wait();
47+
48+
console.log(`✅ Transaction sent: ${tx.hash}`);
49+
};
50+
51+
export const universalWithdrawAndCallCommand = createCommand(
52+
"universal-withdraw-and-call"
53+
)
54+
.requiredOption("-t, --types <types...>", "Parameter types as JSON string")
55+
.requiredOption("-v, --values <values...>", "The values of the parameters")
56+
.option("--call-options-is-arbitrary-call", "Call any function", false)
57+
.option("--call-options-gas-limit", "The gas limit for the call", "500000")
58+
.option(
59+
"--function <function>",
60+
`Function to call (example: "hello(string)")`
61+
)
62+
.requiredOption("--amount <number>", "Amount to withdraw")
63+
.option("--zrc20 <address>", "The address of ZRC-20 to pay fees")
64+
.action(main);

0 commit comments

Comments
 (0)