diff --git a/packages/localnet/src/handleOnZEVMCalled.ts b/packages/localnet/src/handleOnZEVMCalled.ts index 836f185..d8729ee 100644 --- a/packages/localnet/src/handleOnZEVMCalled.ts +++ b/packages/localnet/src/handleOnZEVMCalled.ts @@ -30,7 +30,6 @@ export const handleOnZEVMCalled = async ({ const messageContext = { sender: isArbitraryCall ? ethers.ZeroAddress : sender, }; - console.log(messageContext); log("EVM", `Calling ${receiver} with message ${message}`); const executeTx = await protocolContracts.gatewayEVM diff --git a/packages/localnet/src/handleOnZEVMWithdrawn.ts b/packages/localnet/src/handleOnZEVMWithdrawn.ts index ded8934..c1f2d89 100644 --- a/packages/localnet/src/handleOnZEVMWithdrawn.ts +++ b/packages/localnet/src/handleOnZEVMWithdrawn.ts @@ -45,54 +45,29 @@ export const handleOnZEVMWithdrawn = async ({ const coinType = await zrc20Contract.COIN_TYPE(); const isGasToken = coinType === 1n; const isERC20orZETA = coinType === 2n; - if (message !== "0x") { - // The message is not empty, so this is a withdrawAndCall operation - log("EVM", `Calling ${receiver} with message ${message}`); - if (isGasToken) { - const executeTx = await protocolContracts.gatewayEVM - .connect(tss) - .execute(receiver, message, { value: amount, ...deployOpts }); - await executeTx.wait(); - } else { - const erc20 = getERC20ByZRC20(zrc20); - const executeTx = await protocolContracts.custody - .connect(tss) - .withdrawAndCall(receiver, erc20, amount, message, deployOpts); - await executeTx.wait(); - } - const logs = await provider.getLogs({ - address: receiver, - fromBlock: "latest", + if (isGasToken) { + const tx = await tss.sendTransaction({ + to: receiver, + value: amount, + ...deployOpts, }); - logs.forEach((data) => { - log("EVM", `Event from contract: ${JSON.stringify(data)}`); - }); - } else { - // The message is empty, so this is a withdraw operation - if (isGasToken) { - const tx = await tss.sendTransaction({ - to: receiver, - value: amount, - ...deployOpts, - }); - await tx.wait(); - log( - "EVM", - `Transferred ${ethers.formatEther( - amount - )} native gas tokens from TSS to ${receiver}` - ); - } else if (isERC20orZETA) { - const erc20 = getERC20ByZRC20(zrc20); - const tx = await protocolContracts.custody - .connect(tss) - .withdraw(receiver, erc20, amount, deployOpts); - await tx.wait(); - log( - "EVM", - `Transferred ${amount} ERC-20 tokens from Custody to ${receiver}` - ); - } + await tx.wait(); + log( + "EVM", + `Transferred ${ethers.formatEther( + amount + )} native gas tokens from TSS to ${receiver}` + ); + } else if (isERC20orZETA) { + const erc20 = getERC20ByZRC20(zrc20); + const tx = await protocolContracts.custody + .connect(tss) + .withdraw(receiver, erc20, amount, deployOpts); + await tx.wait(); + log( + "EVM", + `Transferred ${amount} ERC-20 tokens from Custody to ${receiver}` + ); } } catch (err) { const revertOptions = args[9]; diff --git a/packages/localnet/src/handleOnZEVMWithdrawnAndCalled.ts b/packages/localnet/src/handleOnZEVMWithdrawnAndCalled.ts new file mode 100644 index 0000000..f87789b --- /dev/null +++ b/packages/localnet/src/handleOnZEVMWithdrawnAndCalled.ts @@ -0,0 +1,101 @@ +import { ethers, NonceManager } from "ethers"; +import { handleOnRevertZEVM } from "./handleOnRevertZEVM"; +import { log, logErr } from "./log"; +import { deployOpts } from "./deployOpts"; +import * as ZRC20 from "@zetachain/protocol-contracts/abi/ZRC20.sol/ZRC20.json"; + +export const handleOnZEVMWithdrawnAndCalled = async ({ + tss, + provider, + protocolContracts, + args, + fungibleModuleSigner, + deployer, + foreignCoins, + exitOnError = false, +}: { + tss: any; + provider: ethers.JsonRpcProvider; + protocolContracts: any; + args: any; + fungibleModuleSigner: any; + deployer: any; + foreignCoins: any[]; + exitOnError: boolean; +}) => { + log("ZetaChain", "Gateway: 'WithdrawnAndCalled' event emitted"); + console.log(args); + const getERC20ByZRC20 = (zrc20: string) => { + const foreignCoin = foreignCoins.find( + (coin: any) => coin.zrc20_contract_address === zrc20 + ); + if (!foreignCoin) { + logErr("EVM", `Foreign coin not found for ZRC20 address: ${zrc20}`); + return; + } + return foreignCoin.asset; + }; + const sender = args[0]; + const zrc20 = args[3]; + const amount = args[4]; + const callOptions = args[8]; + const isArbitraryCall = callOptions[1]; + const messageContext = { + sender: isArbitraryCall ? ethers.ZeroAddress : sender, + }; + try { + const receiver = args[2]; + const message = args[7]; + (tss as NonceManager).reset(); + const zrc20Contract = new ethers.Contract(zrc20, ZRC20.abi, deployer); + const coinType = await zrc20Contract.COIN_TYPE(); + const isGasToken = coinType === 1n; + const isERC20orZETA = coinType === 2n; + // The message is not empty, so this is a withdrawAndCall operation + log("EVM", `Calling ${receiver} with message ${message}`); + if (isGasToken) { + const executeTx = await protocolContracts.gatewayEVM + .connect(tss) + .execute(messageContext, receiver, message, { + value: amount, + ...deployOpts, + }); + await executeTx.wait(); + } else { + const erc20 = getERC20ByZRC20(zrc20); + const executeTx = await protocolContracts.custody + .connect(tss) + .withdrawAndCall( + messageContext, + receiver, + erc20, + amount, + message, + deployOpts + ); + await executeTx.wait(); + } + const logs = await provider.getLogs({ + address: receiver, + fromBlock: "latest", + }); + logs.forEach((data) => { + log("EVM", `Event from contract: ${JSON.stringify(data)}`); + }); + } catch (err) { + const revertOptions = args[9]; + return await handleOnRevertZEVM({ + revertOptions, + err, + provider, + tss, + asset: getERC20ByZRC20(zrc20), + amount, + log, + fungibleModuleSigner, + protocolContracts, + deployOpts, + exitOnError, + }); + } +}; diff --git a/packages/localnet/src/index.ts b/packages/localnet/src/index.ts index 6d11dc6..b4b5d7a 100755 --- a/packages/localnet/src/index.ts +++ b/packages/localnet/src/index.ts @@ -15,6 +15,7 @@ import { deployOpts } from "./deployOpts"; import { handleOnEVMDeposited } from "./handleOnEVMDeposited"; import { handleOnZEVMWithdrawn } from "./handleOnZEVMWithdrawn"; import { createToken } from "./createToken"; +import { handleOnZEVMWithdrawnAndCalled } from "./handleOnZEVMWithdrawnAndCalled"; const FUNGIBLE_MODULE_ADDRESS = "0x735b14BB79463307AAcBED86DAf3322B1e6226aB"; @@ -353,6 +354,22 @@ export const initLocalnet = async ({ }); }); + protocolContracts.gatewayZEVM.on( + "WithdrawnAndCalled", + async (...args: Array) => { + handleOnZEVMWithdrawnAndCalled({ + tss, + provider, + protocolContracts, + args, + deployer, + fungibleModuleSigner, + foreignCoins, + exitOnError, + }); + } + ); + protocolContracts.gatewayEVM.on("Called", async (...args: Array) => { return await handleOnEVMCalled({ tss,