Skip to content

Commit

Permalink
Update Hello and Swap to authenticated calls (#218)
Browse files Browse the repository at this point in the history
  • Loading branch information
fadeev authored Nov 24, 2024
1 parent c394e92 commit 02373a6
Show file tree
Hide file tree
Showing 81 changed files with 2,738 additions and 1,952 deletions.
43 changes: 0 additions & 43 deletions .github/workflows/publish-npm.yml

This file was deleted.

8 changes: 6 additions & 2 deletions .github/workflows/slither.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ jobs:
include:
- project: "examples/hello"
file: "hello.sarif"
- project: "examples/call"
file: "call.sarif"
- project: "examples/swap"
file: "swap.sarif"
- project: "omnichain/swap"
file: "omnichain-swap.sarif"
- project: "examples/nft"
file: "nft.sarif"
- project: "examples/token"
file: "token.sarif"
permissions:
contents: read
security-events: write
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Set up Test Matrix
id: set-matrix
run: |
test_dirs=$(find examples/*/scripts -type f -name 'test.sh' -exec dirname {} \; | xargs dirname)
test_dirs=$(find examples/*/scripts -type f -name 'localnet.sh' -exec dirname {} \; | xargs dirname)
matrix_json=$(echo "$test_dirs" | jq -R '{"example-dir": .}' | jq -s . | jq -c .)
echo "matrix=$matrix_json" >> $GITHUB_OUTPUT
Expand All @@ -39,5 +39,5 @@ jobs:
run: |
cd "${{ matrix.example-dir }}"
yarn
chmod +x ./scripts/test.sh
./scripts/test.sh localnet
chmod +x ./scripts/localnet.sh
./scripts/localnet.sh start
File renamed without changes.
File renamed without changes.
4 changes: 3 additions & 1 deletion omnichain/swap/.gitignore → examples/call/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ artifacts
out
cache_forge

access_token
access_token

localnet.json
File renamed without changes.
3 changes: 3 additions & 0 deletions examples/call/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Hello Example

Tutorial: https://www.zetachain.com/docs/developers/tutorials/call/
98 changes: 98 additions & 0 deletions examples/call/contracts/Connected.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// 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";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

contract Connected {
using SafeERC20 for IERC20; // Use SafeERC20 for IERC20 operations

GatewayEVM public immutable gateway;

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

error Unauthorized();

modifier onlyGateway() {
if (msg.sender != address(gateway)) revert Unauthorized();
_;
}

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

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

function deposit(
address receiver,
RevertOptions memory revertOptions
) external payable {
gateway.deposit{value: msg.value}(receiver, revertOptions);
}

function deposit(
address receiver,
uint256 amount,
address asset,
RevertOptions memory revertOptions
) external {
IERC20(asset).safeTransferFrom(msg.sender, address(this), amount);
IERC20(asset).approve(address(gateway), amount);
gateway.deposit(receiver, amount, asset, revertOptions);
}

function depositAndCall(
address receiver,
uint256 amount,
address asset,
bytes calldata message,
RevertOptions memory revertOptions
) external {
IERC20(asset).safeTransferFrom(msg.sender, address(this), amount);
IERC20(asset).approve(address(gateway), amount);
gateway.depositAndCall(receiver, amount, asset, message, revertOptions);
}

function depositAndCall(
address receiver,
bytes calldata message,
RevertOptions memory revertOptions
) external payable {
gateway.depositAndCall{value: msg.value}(
receiver,
message,
revertOptions
);
}

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

function onCall(
MessageContext calldata context,
bytes calldata message
) external payable onlyGateway returns (bytes4) {
emit HelloEvent("Hello on EVM from onCall()", "hey");
return "";
}

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

receive() external payable {}

fallback() external payable {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,62 +6,78 @@ import "@zetachain/protocol-contracts/contracts/zevm/interfaces/UniversalContrac
import "@zetachain/protocol-contracts/contracts/zevm/interfaces/IGatewayZEVM.sol";
import "@zetachain/protocol-contracts/contracts/zevm/GatewayZEVM.sol";

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

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

error TransferFailed();
error Unauthorized();

modifier onlyGateway() {
require(msg.sender == address(gateway), "Caller is not the gateway");
if (msg.sender != address(gateway)) revert Unauthorized();
_;
}

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

function onCall(
MessageContext calldata context,
address zrc20,
uint256 amount,
bytes calldata message
) external override onlyGateway {
string memory name = abi.decode(message, (string));
emit HelloEvent("Hello on ZetaChain", name);
}

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

function call(
bytes memory receiver,
address zrc20,
bytes calldata message,
uint256 gasLimit,
CallOptions memory callOptions,
RevertOptions memory revertOptions
) external {
(, uint256 gasFee) = IZRC20(zrc20).withdrawGasFeeWithGasLimit(gasLimit);
if (!IZRC20(zrc20).transferFrom(msg.sender, address(this), gasFee))
(, uint256 gasFee) = IZRC20(zrc20).withdrawGasFeeWithGasLimit(
callOptions.gasLimit
);
if (!IZRC20(zrc20).transferFrom(msg.sender, address(this), gasFee)) {
revert TransferFailed();
}
IZRC20(zrc20).approve(address(gateway), gasFee);
gateway.call(receiver, zrc20, message, gasLimit, revertOptions);
gateway.call(receiver, zrc20, message, callOptions, revertOptions);
}

function withdraw(
bytes memory receiver,
uint256 amount,
address zrc20,
RevertOptions memory revertOptions
) external {
(address gasZRC20, uint256 gasFee) = IZRC20(zrc20).withdrawGasFee();
uint256 target = zrc20 == gasZRC20 ? amount + gasFee : amount;
if (!IZRC20(zrc20).transferFrom(msg.sender, address(this), target)) {
revert TransferFailed();
}
IZRC20(zrc20).approve(address(gateway), target);
if (zrc20 != gasZRC20) {
if (
!IZRC20(gasZRC20).transferFrom(
msg.sender,
address(this),
gasFee
)
) {
revert TransferFailed();
}
IZRC20(gasZRC20).approve(address(gateway), gasFee);
}
gateway.withdraw(receiver, amount, zrc20, revertOptions);
}

function withdrawAndCall(
bytes memory receiver,
uint256 amount,
address zrc20,
bytes calldata message,
uint256 gasLimit,
CallOptions memory callOptions,
RevertOptions memory revertOptions
) external {
(address gasZRC20, uint256 gasFee) = IZRC20(zrc20)
.withdrawGasFeeWithGasLimit(gasLimit);
.withdrawGasFeeWithGasLimit(callOptions.gasLimit);
uint256 target = zrc20 == gasZRC20 ? amount + gasFee : amount;
if (!IZRC20(zrc20).transferFrom(msg.sender, address(this), target))
revert TransferFailed();
Expand All @@ -73,16 +89,34 @@ contract Hello is UniversalContract {
address(this),
gasFee
)
) revert TransferFailed();
) {
revert TransferFailed();
}
IZRC20(gasZRC20).approve(address(gateway), gasFee);
}
gateway.withdrawAndCall(
receiver,
amount,
zrc20,
message,
gasLimit,
callOptions,
revertOptions
);
}

function onCall(
MessageContext calldata context,
address zrc20,
uint256 amount,
bytes calldata message
) external override onlyGateway {
string memory name = abi.decode(message, (string));
emit HelloEvent("Hello on ZetaChain", name);
}

function onRevert(
RevertContext calldata revertContext
) external onlyGateway {
emit RevertEvent("Revert on ZetaChain", revertContext);
}
}
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import "./tasks/deploy";
import "./tasks/solana/interact";
import "./tasks/interact";
import "./tasks/swap";
import "./tasks/universalCall";
import "./tasks/connectedCall";
import "./tasks/connectedDeposit";
import "./tasks/connectedDepositAndCall";
import "./tasks/universalWithdraw";
import "./tasks/universalWithdrawAndCall";
import "@zetachain/localnet/tasks";
import "@nomicfoundation/hardhat-toolbox";
import "@zetachain/toolkit/tasks";
Expand All @@ -13,15 +16,7 @@ const config: HardhatUserConfig = {
networks: {
...getHardhatConfigNetworks(),
},
solidity: {
compilers: [
{ version: "0.5.10" /** For create2 factory */ },
{ version: "0.6.6" /** For uniswap v2 router*/ },
{ version: "0.5.16" /** For uniswap v2 core*/ },
{ version: "0.4.19" /** For weth*/ },
{ version: "0.8.7" },
],
},
solidity: "0.8.26",
};

export default config;
11 changes: 5 additions & 6 deletions omnichain/swap/package.json → examples/call/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 --name Hello && npx hardhat deploy --network localhost --name ReceiverContract"
"deploy:localnet": "npx hardhat compile --force && npx hardhat deploy --network localhost --gateway 0x9A676e781A523b5d0C0e43731313A708CB607508 && npx hardhat deploy --name Echo --network localhost --gateway 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0"
},
"keywords": [],
"author": "",
Expand All @@ -28,9 +28,8 @@
"@types/node": ">=12.0.0",
"@typescript-eslint/eslint-plugin": "^5.59.9",
"@typescript-eslint/parser": "^5.59.9",
"@zetachain/localnet": "^1.0.1",
"@zetachain/protocol-contracts": "9.0.0",
"@zetachain/toolkit": "^10.0.0",
"@zetachain/localnet": "4.0.0-rc6",
"@zetachain/toolkit": "13.0.0-rc7",
"axios": "^1.3.6",
"chai": "^4.2.0",
"dotenv": "^16.0.3",
Expand All @@ -55,9 +54,9 @@
"packageManager": "yarn@1.22.21+sha1.1959a18351b811cdeedbd484a8f86c3cc3bbaf72",
"dependencies": {
"@coral-xyz/anchor": "0.30.0",
"@openzeppelin/contracts": "^4.9.6",
"@solana-developers/helpers": "^2.4.0",
"@solana/spl-memo": "^0.2.5",
"@solana/web3.js": "^1.95.2"
"@solana/web3.js": "^1.95.2",
"@zetachain/protocol-contracts": "11.0.0-rc3"
}
}
Loading

0 comments on commit 02373a6

Please sign in to comment.