Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 38 additions & 8 deletions examples/hello/README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,45 @@
# ZetaChain Contracts Template
# Hello Example

## Getting Started
```
yarn deploy
```

## EVM

Successful call:

```
npx hardhat echo-call --contract 0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E --receiver 0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690 --network localhost --types '["string"]' hello
```

Failed call:

```
npx hardhat echo-call --contract 0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E --receiver 0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690 --network localhost --types '["uint256"]' 42
```

Install dependencies:
Failed call with handled revert:

```
yarn
npx hardhat echo-call --contract 0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E --receiver 0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690 --network localhost --revert-address 0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E --revert-message 0x --call-on-revert --types '["uint256"]' 42
```

## Next Steps
## ZetaChain

Ready to dive in? Follow our [**🚀 smart contract
tutorials**](https://www.zetachain.com/docs/developers/tutorials/intro/) to
start building universal app contracts.
Successful call:

```
npx hardhat hell-call --contract 0x67d269191c92Caf3cD7723F116c85e6E9bf55933 --receiver 0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690 --zrc20 0x2ca7d64A7EFE2D62A725E2B35Cf7230D6677FfEe --function "hello(string)" --network localhost --types '["string"]' hello
```

Failed call:

```
npx hardhat hell-call --contract 0x67d269191c92Caf3cD7723F116c85e6E9bf55933 --receiver 0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690 --zrc20 0x2ca7d64A7EFE2D62A725E2B35Cf7230D6677FfEe --function "hello(string)" --network localhost --types '["uint256"]' 42
```

Failed call with handled revert:

```
npx hardhat hell-call --contract 0x67d269191c92Caf3cD7723F116c85e6E9bf55933 --receiver 0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690 --zrc20 0x2ca7d64A7EFE2D62A725E2B35Cf7230D6677FfEe --function "hello(string)" --network localhost --revert-address 0x67d269191c92Caf3cD7723F116c85e6E9bf55933 --revert-message 0x --call-on-revert --types '["uint256"]' 42
```
36 changes: 36 additions & 0 deletions examples/hello/contracts/Echo.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import {RevertContext} from "@zetachain/protocol-contracts/contracts/Revert.sol";
import "@zetachain/protocol-contracts/contracts/evm/GatewayEVM.sol";

contract Echo {
GatewayEVM public immutable gateway;

event RevertEvent(string, RevertContext);
event HelloEvent(string, string);

constructor(address payable gatewayAddress) {
gateway = GatewayEVM(gatewayAddress);
}

function hello(string memory message) external payable {
emit HelloEvent("Hello on EVM", message);
}

function onRevert(RevertContext calldata revertContext) external {
emit RevertEvent("Revert on EVM", revertContext);
}

function call(
address receiver,
bytes calldata message,
RevertOptions memory revertOptions
) external {
gateway.call(receiver, message, revertOptions);
}

receive() external payable {}

fallback() external payable {}
}
Comment on lines +7 to +36

Check warning

Code scanning / Slither

Contracts that lock Ether

Contract locking ether found: Contract Echo (contracts/Echo.sol#7-36) has payable functions: - Echo.hello(string) (contracts/Echo.sol#17-19) - Echo.receive() (contracts/Echo.sol#33) - Echo.fallback() (contracts/Echo.sol#35) But does not have a function to withdraw the ether
30 changes: 28 additions & 2 deletions examples/hello/contracts/Hello.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import "@zetachain/protocol-contracts/contracts/zevm/interfaces/IGatewayZEVM.sol
import "@zetachain/protocol-contracts/contracts/zevm/GatewayZEVM.sol";

contract Hello is UniversalContract {
GatewayZEVM public gateway;
GatewayZEVM public immutable gateway;

event HelloEvent(string, string);
event RevertEvent(string, RevertContext);
Expand All @@ -30,7 +30,7 @@ contract Hello is UniversalContract {
emit RevertEvent("Revert on ZetaChain", revertContext);
}

function gatewayCall(
function call(
bytes memory receiver,
address zrc20,
bytes calldata message,
Expand All @@ -41,4 +41,30 @@ contract Hello is UniversalContract {
IZRC20(zrc20).approve(address(gateway), gasFee);
gateway.call(receiver, zrc20, message, gasLimit, revertOptions);
}

function withdrawAndCall(
bytes memory receiver,
uint256 amount,
address zrc20,
bytes calldata message,
uint256 gasLimit,
RevertOptions memory revertOptions
) external {
(address gasZRC20, uint256 gasFee) = IZRC20(zrc20)
.withdrawGasFeeWithGasLimit(gasLimit);
if (zrc20 == gasZRC20) {
IZRC20(zrc20).approve(address(gateway), amount + gasFee);
} else {
IZRC20(zrc20).approve(address(gateway), amount);
IZRC20(gasZRC20).approve(address(gateway), gasFee);
}
gateway.withdrawAndCall(
receiver,
amount,
zrc20,
message,
gasLimit,
revertOptions
);
}
Comment on lines +45 to +69

Check warning

Code scanning / Slither

Unused return

Hello.withdrawAndCall(bytes,uint256,address,bytes,uint256,RevertOptions) (contracts/Hello.sol#45-69) ignores return value by IZRC20(gasZRC20).approve(address(gateway),gasFee) (contracts/Hello.sol#59)
Comment on lines +45 to +69

Check warning

Code scanning / Slither

Unused return

Hello.withdrawAndCall(bytes,uint256,address,bytes,uint256,RevertOptions) (contracts/Hello.sol#45-69) ignores return value by IZRC20(zrc20).approve(address(gateway),amount + gasFee) (contracts/Hello.sol#56)
Comment on lines +45 to +69

Check warning

Code scanning / Slither

Unused return

Hello.withdrawAndCall(bytes,uint256,address,bytes,uint256,RevertOptions) (contracts/Hello.sol#45-69) ignores return value by IZRC20(zrc20).approve(address(gateway),amount) (contracts/Hello.sol#58)
}
21 changes: 0 additions & 21 deletions examples/hello/contracts/Revert.sol

This file was deleted.

5 changes: 3 additions & 2 deletions examples/hello/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import "./tasks/deploy";
import "./tasks/deployRevert";
import "./tasks/gatewayCall";
import "./tasks/helloCall";
import "./tasks/echoCall";
import "./tasks/helloWithdrawAndCall";
import "@zetachain/localnet/tasks";
import "@nomicfoundation/hardhat-toolbox";
import "@zetachain/toolkit/tasks";
Expand Down
6 changes: 3 additions & 3 deletions examples/hello/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"test": "echo \"Error: no test specified\" && exit 1",
"lint:fix": "npx eslint . --ext .js,.ts --fix",
"lint": "npx eslint . --ext .js,.ts",
"deploy": "npx hardhat compile --force && npx hardhat deploy --network localhost && npx hardhat deploy-revert --network localhost"
"deploy": "npx hardhat compile --force && npx hardhat deploy --network localhost && npx hardhat deploy --name Echo --network localhost --gateway 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0"
},
"keywords": [],
"author": "",
Expand All @@ -28,8 +28,8 @@
"@types/node": ">=12.0.0",
"@typescript-eslint/eslint-plugin": "^5.59.9",
"@typescript-eslint/parser": "^5.59.9",
"@zetachain/localnet": "^3.0.4",
"@zetachain/toolkit": "13.0.0-rc2",
"@zetachain/localnet": "^3.2.0",
"@zetachain/toolkit": "13.0.0-rc4",
"axios": "^1.3.6",
"chai": "^4.2.0",
"dotenv": "^16.0.3",
Expand Down
6 changes: 3 additions & 3 deletions examples/hello/tasks/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const main = async (args: any, hre: HardhatRuntimeEnvironment) => {
}

const factory = await hre.ethers.getContractFactory(args.name);
const contract = await (factory as any).deploy(args.gatewayZetaChain);
const contract = await (factory as any).deploy(args.gateway);
await contract.deployed();

if (args.json) {
Expand All @@ -30,7 +30,7 @@ task("deploy", "Deploy the contract", main)
.addFlag("json", "Output in JSON")
.addOptionalParam("name", "Contract to deploy", "Hello")
.addOptionalParam(
"gatewayZetaChain",
"Gateway address",
"gateway",
"Gateway address (default: ZetaChain Gateway)",
"0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0"
);
31 changes: 0 additions & 31 deletions examples/hello/tasks/deployRevert.ts

This file was deleted.

99 changes: 99 additions & 0 deletions examples/hello/tasks/echoCall.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { task, types } from "hardhat/config";
import type { HardhatRuntimeEnvironment } from "hardhat/types";

const main = async (args: any, hre: HardhatRuntimeEnvironment) => {
const { ethers } = hre;
const [signer] = await ethers.getSigners();

const txOptions = {
gasPrice: args.txOptionsGasPrice,
gasLimit: args.txOptionsGasLimit,
};

const revertOptions = {
abortAddress: "0x0000000000000000000000000000000000000000", // not used
callOnRevert: args.callOnRevert,
onRevertGasLimit: args.onRevertGasLimit,
revertAddress: args.revertAddress,
revertMessage: ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(args.revertMessage)
),
};

const types = JSON.parse(args.types);

if (types.length !== args.values.length) {
throw new Error(
`The number of types (${types.length}) does not match the number of values (${args.values.length}).`
);
}

const valuesArray = args.values.map((value: any, index: number) => {
const type = types[index];

if (type === "bool") {
try {
return JSON.parse(value.toLowerCase());
} catch (e) {
throw new Error(`Invalid boolean value: ${value}`);
}
} else if (type.startsWith("uint") || type.startsWith("int")) {
return ethers.BigNumber.from(value);
} else {
return value;
}
});
const encodedParameters = ethers.utils.defaultAbiCoder.encode(
types,
valuesArray
);

const factory = (await hre.ethers.getContractFactory(args.name)) as any;
const contract = factory.attach(args.contract).connect(signer);

const tx = await contract.call(
args.receiver,
encodedParameters,
revertOptions,
txOptions
);

console.log(`Transaction hash: ${tx.hash}`);
await tx.wait();
console.log("gatewayCall executed successfully");
};

task("echo-call", "Calls the gateway on a contract on EVM", main)
.addParam("contract", "The address of the deployed contract")
.addOptionalParam(
"txOptionsGasPrice",
"The gas price for the transaction",
10000000000,
types.int
)
.addOptionalParam(
"txOptionsGasLimit",
"The gas limit for the transaction",
7000000,
types.int
)
.addFlag("callOnRevert", "Whether to call on revert")
.addOptionalParam(
"revertAddress",
"Revert address",
"0x0000000000000000000000000000000000000000"
)
.addOptionalParam("revertMessage", "Revert message", "0x")
.addParam(
"receiver",
"The address of the receiver contract on a connected chain"
)
.addOptionalParam(
"onRevertGasLimit",
"The gas limit for the revert transaction",
7000000,
types.int
)
.addParam("name", "The name of the contract", "Echo")
.addParam("types", `The types of the parameters (example: '["string"]')`)
.addVariadicPositionalParam("values", "The values of the parameters");
Loading