Skip to content

Commit

Permalink
feat: prototype inbound zevm (#183)
Browse files Browse the repository at this point in the history
Co-authored-by: lumtis <lucas.bertrand.22@gmail.com>
  • Loading branch information
skosito and lumtis authored Jul 1, 2024
1 parent b9e5bfd commit 9a785bc
Show file tree
Hide file tree
Showing 34 changed files with 4,413 additions and 55 deletions.
61 changes: 61 additions & 0 deletions contracts/prototypes/zevm/GatewayZEVM.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "../../zevm/interfaces/IZRC20.sol";

// The GatewayZEVM contract is the endpoint to call smart contracts on omnichain
// The contract doesn't hold any funds and should never have active allowances
contract GatewayZEVM is Initializable, OwnableUpgradeable, UUPSUpgradeable {
address public constant FUNGIBLE_MODULE_ADDRESS = 0x735b14BB79463307AAcBED86DAf3322B1e6226aB;

error WithdrawalFailed();
error InsufficientZRC20Amount();
error GasFeeTransferFailed();

event Call(address indexed sender, bytes indexed receiver, bytes message);
event Withdrawal(address indexed from, bytes to, uint256 value, uint256 gasfee, uint256 protocolFlatFee, bytes message);

/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}

function initialize() public initializer {
__Ownable_init();
__UUPSUpgradeable_init();
}

function _authorizeUpgrade(address newImplementation) internal override onlyOwner() {}

function _withdraw(uint256 amount, address zrc20) internal returns (uint256) {
(address gasZRC20, uint256 gasFee) = IZRC20(zrc20).withdrawGasFee();
if (!IZRC20(gasZRC20).transferFrom(msg.sender, FUNGIBLE_MODULE_ADDRESS, gasFee)) {
revert GasFeeTransferFailed();
}

IZRC20(zrc20).transferFrom(msg.sender, address(this), amount);
IZRC20(zrc20).burn(amount);

return gasFee;
}

// Withdraw ZRC20 tokens to external chain
function withdraw(bytes memory receiver, uint256 amount, address zrc20) external {
uint256 gasFee = _withdraw(amount, zrc20);
emit Withdrawal(msg.sender, receiver, amount, gasFee, IZRC20(zrc20).PROTOCOL_FLAT_FEE(), "");
}

// Withdraw ZRC20 tokens and call smart contract on external chain
function withdrawAndCall(bytes memory receiver, uint256 amount, address zrc20, bytes calldata message) external {
uint256 gasFee = _withdraw(amount, zrc20);
emit Withdrawal(msg.sender, receiver, amount, gasFee, IZRC20(zrc20).PROTOCOL_FLAT_FEE(), message);
}

// Call smart contract on external chain without asset transfer
function call(bytes memory receiver, bytes calldata message) external {
emit Call(msg.sender, receiver, message);
}
}
35 changes: 35 additions & 0 deletions contracts/prototypes/zevm/Sender.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./interfaces.sol";
import "../../zevm/interfaces/IZRC20.sol";

contract Sender {
address public gateway;

constructor(address _gateway) {
gateway = _gateway;
}

// Call receiver on EVM
function callReceiver(bytes memory receiver, string memory str, uint256 num, bool flag) external {
// Encode the function call to the receiver's receiveA method
bytes memory message = abi.encodeWithSignature("receiveA(string,uint256,bool)", str, num, flag);

// Pass encoded call to gateway
IGatewayZEVM(gateway).call(receiver, message);
}

// Withdraw and call receiver on EVM
function withdrawAndCallReceiver(bytes memory receiver, uint256 amount, address zrc20, string memory str, uint256 num, bool flag) external {
// Encode the function call to the receiver's receiveA method
bytes memory message = abi.encodeWithSignature("receiveA(string,uint256,bool)", str, num, flag);

// Approve gateway to withdraw
IZRC20(zrc20).approve(gateway, amount);

// Pass encoded call to gateway
IGatewayZEVM(gateway).withdrawAndCall(receiver, amount, zrc20, message);
}
}
10 changes: 10 additions & 0 deletions contracts/prototypes/zevm/interfaces.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;

interface IGatewayZEVM {
function withdraw(bytes memory receiver, uint256 amount, address zrc20) external;

function withdrawAndCall(bytes memory receiver, uint256 amount, address zrc20, bytes calldata message) external;

function call(bytes memory receiver, bytes calldata message) external;
}
4 changes: 2 additions & 2 deletions contracts/zevm/interfaces/IZRC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ interface IZRC20 {

function deposit(address to, uint256 amount) external returns (bool);

function burn(address account, uint256 amount) external returns (bool);
function burn(uint256 amount) external returns (bool);

function withdraw(bytes memory to, uint256 amount) external returns (bool);

function withdrawGasFee() external view returns (address, uint256);

function PROTOCOL_FEE() external view returns (uint256);
function PROTOCOL_FLAT_FEE() external view returns (uint256);

event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
Expand Down
13 changes: 13 additions & 0 deletions data/addresses.testnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,19 @@
"symbol": "tBTC",
"type": "zrc20"
},
{
"address": "0x777915D031d1e8144c90D025C594b3b8Bf07a08d",
"asset": "",
"category": "omnichain",
"chain_id": 7001,
"chain_name": "zeta_testnet",
"coin_type": "gas",
"decimals": 18,
"description": "ZetaChain ZRC20 Amoy MATIC-amoy_testnet",
"foreign_chain_id": "80002",
"symbol": "MATIC.AMOY",
"type": "zrc20"
},
{
"address": "0x7c8dDa80bbBE1254a7aACf3219EBe1481c6E01d7",
"asset": "0x64544969ed7EBf5f083679233325356EbE738930",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ function withdraw(bytes memory to, uint256 amount) external returns (bool);
function withdrawGasFee() external view returns (address, uint256);
```

### PROTOCOL_FEE
### PROTOCOL_FLAT_FEE


```solidity
function PROTOCOL_FEE() external view returns (uint256);
function PROTOCOL_FLAT_FEE() external view returns (uint256);
```

## Events
Expand Down
1 change: 1 addition & 0 deletions lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export type ParamSymbol =
| "BTC.BTC"
| "ETH.ETH"
| "gETH"
| "MATIC.AMOY"
| "sETH.SEPOLIA"
| "tBNB"
| "tBTC"
Expand Down
1,477 changes: 1,477 additions & 0 deletions pkg/contracts/prototypes/zevm/gatewayzevm.sol/gatewayzevm.go

Large diffs are not rendered by default.

Loading

0 comments on commit 9a785bc

Please sign in to comment.