Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: revert specs #217

Merged
merged 115 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
115 commits
Select commit Hold shift + click to select a range
1f2625e
initialize gateway
lumtis Jun 18, 2024
bd71007
add receiver example
lumtis Jun 18, 2024
3553a8f
add test examples
lumtis Jun 18, 2024
791834b
add entry for test prototype
lumtis Jun 18, 2024
c1bd47d
typechain
lumtis Jun 18, 2024
6aed43c
change B to non-payable
lumtis Jun 18, 2024
8a973c1
generate
lumtis Jun 18, 2024
d562400
initialize custody contract
lumtis Jun 19, 2024
555ff9d
add execute with erc20 in gateway
lumtis Jun 19, 2024
21b8ace
add test
lumtis Jun 19, 2024
484096a
add some more tests
lumtis Jun 19, 2024
a0c8e5a
initalize uniswap test
lumtis Jun 19, 2024
5b893d2
finish test for uniswap
lumtis Jun 19, 2024
776caef
generate
lumtis Jun 19, 2024
704382b
use custom error
lumtis Jun 19, 2024
5e4766c
add some more comment
lumtis Jun 19, 2024
ce87491
a bit more comments
lumtis Jun 19, 2024
049f956
Merge branch 'main' into init-prototypes
skosito Jun 20, 2024
278c327
chore: change Gateway contract to be upgradable (#175)
skosito Jun 26, 2024
9303311
conflicts
lumtis Jun 27, 2024
cb0ca6c
fix yarn.lock
lumtis Jun 27, 2024
b9e5bfd
feat: inbound evm prototype (#178)
skosito Jun 27, 2024
9a785bc
feat: prototype inbound zevm (#183)
skosito Jul 1, 2024
430992a
feat: prototype outbound zevm (#191)
skosito Jul 1, 2024
a09cc0c
start worker script to deploy evm and zevm contracts on local hardhat…
skosito Jul 1, 2024
b39bc57
add simple script to deposit to gateway evm and listen to event in wo…
skosito Jul 1, 2024
4ee9023
Merge branch 'main' into init-prototypes
skosito Jul 1, 2024
d784b8e
Merge branch 'init-prototypes' into prototype-localnet
skosito Jul 1, 2024
7e3ad3e
fix coderabbit comments
skosito Jul 2, 2024
0b1f894
fix coderabbit comments
skosito Jul 2, 2024
7db93dd
fix yarn generate
skosito Jul 2, 2024
69d5763
Merge branch 'main' into init-prototypes
skosito Jul 2, 2024
022fee2
Merge branch 'init-prototypes' into prototype-localnet
skosito Jul 2, 2024
1e8af88
generate
skosito Jul 2, 2024
d94d8ff
renamings
skosito Jul 2, 2024
290a84e
add simple task to call receiver
skosito Jul 2, 2024
5817d9a
use receiver from call event in worker script
skosito Jul 2, 2024
f7d18fd
add zcontract localnet task
skosito Jul 2, 2024
51ff6a2
cleanup
skosito Jul 2, 2024
b857b9c
rename localnet script to worker
skosito Jul 2, 2024
cbd7dcf
run localnode and worker concurrently
skosito Jul 3, 2024
da9c0cd
different colors and prefix for node and worker
skosito Jul 3, 2024
6bd8c16
Merge branch 'main' into prototype-localnet
skosito Jul 3, 2024
f2a3371
fixes after merge
skosito Jul 3, 2024
cc93e3e
fixes after merge
skosito Jul 3, 2024
5a5f76b
fix tests
skosito Jul 3, 2024
941949e
fix worker after merge
skosito Jul 3, 2024
6275282
add more tasks
skosito Jul 3, 2024
8c33743
wait on hardhat node before starting worker
skosito Jul 3, 2024
fa96e30
remove redundant hardhat config
skosito Jul 3, 2024
b5a665a
generate
skosito Jul 3, 2024
badd4f8
add tasks to coderabbit
skosito Jul 3, 2024
d158c71
improve instructions
skosito Jul 3, 2024
49223b2
exclude in coderabbit
skosito Jul 3, 2024
4275805
test config changes
skosito Jul 3, 2024
caae687
revert
skosito Jul 3, 2024
0c1b370
add try catch
skosito Jul 3, 2024
76f284d
Merge branch 'main' into prototype-localnet
skosito Jul 3, 2024
e62b051
cleanup
skosito Jul 3, 2024
b69926f
add basic property based invariants for gateway evm
skosito Jul 3, 2024
bb27a54
PR comments
skosito Jul 4, 2024
d80596e
yarn generate
skosito Jul 4, 2024
e559c31
Merge branch 'prototype-localnet' into fuzz-tests-poc
skosito Jul 4, 2024
d0ad2f5
add simple assertion tests
skosito Jul 4, 2024
354e45a
move to test folder
skosito Jul 4, 2024
3190026
Merge branch 'main' into fuzz-tests-poc
skosito Jul 4, 2024
5524b59
add hardhat foundry and simple test
skosito Jul 8, 2024
4f1b2c2
bump hardhat
skosito Jul 8, 2024
86b4d77
yarn gen
skosito Jul 8, 2024
e881d7c
more foundry tests
skosito Jul 8, 2024
c4f89f8
generate
skosito Jul 8, 2024
4613a15
cleanup
skosito Jul 8, 2024
a9ff420
bump node version in ci
skosito Jul 9, 2024
c845f68
add foundry to ci test
skosito Jul 9, 2024
065c096
remappings
skosito Jul 9, 2024
4e3c0c3
submodules in ci test
skosito Jul 9, 2024
00a835b
fix workflows
skosito Jul 9, 2024
1925dd0
lint fix
skosito Jul 9, 2024
8e63c45
generate and readme
skosito Jul 9, 2024
01648d1
cleanup and improve test ci
skosito Jul 9, 2024
b8cc11b
add simple connector
skosito Jul 9, 2024
0e03d10
zeta withdraw zevm
skosito Jul 9, 2024
f3c9a0b
deposit and call gateway zevm
skosito Jul 10, 2024
f642a9e
on revert zevm
skosito Jul 10, 2024
18819f9
on revert evm
skosito Jul 11, 2024
f558def
generate
skosito Jul 11, 2024
8036d17
Merge branch 'main' into zeta-connector
skosito Jul 12, 2024
caaf04b
Merge branch 'zeta-connector' into revert-specs
skosito Jul 12, 2024
0df0624
Merge branch 'main' into zeta-connector
skosito Jul 13, 2024
0eb9f34
Merge branch 'zeta-connector' into revert-specs
skosito Jul 13, 2024
8457ec3
cleanup
skosito Jul 16, 2024
4875824
generate
skosito Jul 16, 2024
b3b2878
Merge branch 'zeta-connector' into revert-specs
skosito Jul 16, 2024
824e4b0
cleanup
skosito Jul 16, 2024
87a94ed
yarn generate
skosito Jul 16, 2024
399f318
fix
skosito Jul 16, 2024
fe552bb
Merge branch 'zeta-connector' into revert-specs
skosito Jul 16, 2024
6592586
Merge branch 'main' into zeta-connector
skosito Jul 17, 2024
65b25d3
fix after merge
skosito Jul 17, 2024
718787f
generate
skosito Jul 17, 2024
09e5d90
fix tests
skosito Jul 17, 2024
deee4d3
generate
skosito Jul 17, 2024
2346bcb
Merge branch 'zeta-connector' into revert-specs
skosito Jul 17, 2024
78b292d
generate
skosito Jul 17, 2024
f489d9e
PR comments
skosito Jul 18, 2024
abc83eb
fix reentrancy guard import
skosito Jul 18, 2024
a4ea328
generate
skosito Jul 18, 2024
04b40f9
PR comment
skosito Jul 18, 2024
fda1131
generate
skosito Jul 18, 2024
30580ab
PR comments
skosito Jul 19, 2024
2e21657
Merge branch 'main' into revert-specs
skosito Jul 19, 2024
563c07d
fixes after merge
skosito Jul 19, 2024
55ddae8
fixes
skosito Jul 19, 2024
2ed3763
generate
skosito Jul 19, 2024
9d035a2
Merge branch 'main' into revert-specs
skosito Jul 19, 2024
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
15 changes: 15 additions & 0 deletions contracts/prototypes/evm/ERC20CustodyNew.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ contract ERC20CustodyNew is ReentrancyGuard{

event Withdraw(address indexed token, address indexed to, uint256 amount);
event WithdrawAndCall(address indexed token, address indexed to, uint256 amount, bytes data);
event WithdrawAndRevert(address indexed token, address indexed to, uint256 amount, bytes data);

constructor(address _gateway) {
if (_gateway == address(0)) {
Expand Down Expand Up @@ -47,4 +48,18 @@ contract ERC20CustodyNew is ReentrancyGuard{

emit WithdrawAndCall(token, to, amount, data);
}

// WithdrawAndRevert is called by TSS address, it transfers the tokens and call a contract
// For this, it passes through the Gateway contract, it transfers the tokens to the Gateway contract and then calls the contract
// TODO: Finalize access control
skosito marked this conversation as resolved.
Show resolved Hide resolved
// https://github.com/zeta-chain/protocol-contracts/issues/204
function withdrawAndRevert(address token, address to, uint256 amount, bytes calldata data) public nonReentrant {
// Transfer the tokens to the Gateway contract
IERC20(token).safeTransfer(address(gateway), amount);
skosito marked this conversation as resolved.
Show resolved Hide resolved
skosito marked this conversation as resolved.
Show resolved Hide resolved

// Forward the call to the Gateway contract
gateway.revertWithERC20(token, to, amount, data);
skosito marked this conversation as resolved.
Show resolved Hide resolved

emit WithdrawAndRevert(token, to, amount, data);
}
}
40 changes: 33 additions & 7 deletions contracts/prototypes/evm/GatewayEVM.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,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 "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "./IGatewayEVM.sol";
import "./ZetaConnectorNewBase.sol";

Expand All @@ -14,47 +15,56 @@
* @notice The GatewayEVM contract is the endpoint to call smart contracts on external chains.
* @dev The contract doesn't hold any funds and should never have active allowances.
*/
contract GatewayEVM is Initializable, OwnableUpgradeable, UUPSUpgradeable, IGatewayEVMErrors, IGatewayEVMEvents {
contract GatewayEVM is Initializable, OwnableUpgradeable, UUPSUpgradeable, IGatewayEVMErrors, IGatewayEVMEvents, ReentrancyGuardUpgradeable {
using SafeERC20 for IERC20;

/// @notice The address of the custody contract.
address public custody;

/// @notice The address of the TSS (Threshold Signature Scheme) contract.
address public tssAddress;

/// @notice The address of the ZetaConnector contract.
address public zetaConnector;

/// @notice The address of the Zeta token contract.
address public zetaToken;

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

function initialize(address _tssAddress, address _zetaToken) public initializer {
__Ownable_init();
__UUPSUpgradeable_init();

if (_tssAddress == address(0) || _zetaToken == address(0)) {
revert ZeroAddress();
}

__Ownable_init();
__UUPSUpgradeable_init();
__ReentrancyGuard_init();

tssAddress = _tssAddress;
zetaToken = _zetaToken;
}

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

function _execute(address destination, bytes calldata data) internal returns (bytes memory) {
(bool success, bytes memory result) = destination.call{value: msg.value}(data);
if (!success) revert ExecutionFailed();

return result;
}

// Called by the TSS
// Calling onRevert directly
function executeRevert(address destination, bytes calldata data) public payable {

Check notice

Code scanning / Slither

Missing zero address validation Low

(bool success, bytes memory result) = destination.call{value: msg.value}("");
if (!success) revert ExecutionFailed();
Revertable(destination).onRevert(data);

emit Reverted(destination, msg.value, data);
}
Comment on lines +60 to +66

Check notice

Code scanning / Slither

Reentrancy vulnerabilities Low

Comment on lines +60 to +66

Check warning

Code scanning / Slither

Low-level calls Warning


// Called by the TSS
// Execution without ERC20 tokens, it is payable and can be used in the case of WithdrawAndCall for Gas ZRC20
// It can be also used for contract call without asset movement
Expand All @@ -75,7 +85,7 @@
address to,
uint256 amount,
bytes calldata data
) public {
) public nonReentrant {
if (amount == 0) revert InsufficientETHAmount();
// Approve the target contract to spend the tokens
if(!resetApproval(token, to)) revert ApprovalFailed();
Expand All @@ -96,6 +106,22 @@
emit ExecutedWithERC20(token, to, amount, data);
}

// Called by the ERC20Custody contract
skosito marked this conversation as resolved.
Show resolved Hide resolved
// Directly transfers ERC20 and calls onRevert
function revertWithERC20(
address token,
address to,
uint256 amount,
bytes calldata data
) external nonReentrant {
if (amount == 0) revert InsufficientERC20Amount();

IERC20(token).safeTransfer(address(to), amount);
skosito marked this conversation as resolved.
Show resolved Hide resolved
skosito marked this conversation as resolved.
Show resolved Hide resolved
Revertable(to).onRevert(data);

emit RevertedWithERC20(token, to, amount, data);
}

// Deposit ETH to tss
function deposit(address receiver) external payable {
if (msg.value == 0) revert InsufficientETHAmount();
Expand Down
97 changes: 73 additions & 24 deletions contracts/prototypes/evm/GatewayEVMUpgradeTest.sol
Original file line number Diff line number Diff line change
@@ -1,49 +1,68 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "./IGatewayEVM.sol";
import "./ZetaConnectorNewBase.sol";

// NOTE: Purpose of this contract is to test upgrade process, the only difference should be name of Executed event
// The Gateway contract is the endpoint to call smart contracts on external chains
// The contract doesn't hold any funds and should never have active allowances
/// @custom:oz-upgrades-from GatewayEVM
contract GatewayEVMUpgradeTest is Initializable, OwnableUpgradeable, UUPSUpgradeable, IGatewayEVMErrors, IGatewayEVMEvents {
contract GatewayEVMUpgradeTest is Initializable, OwnableUpgradeable, UUPSUpgradeable, IGatewayEVMErrors, IGatewayEVMEvents, ReentrancyGuardUpgradeable {
using SafeERC20 for IERC20;

/// @notice The address of the custody contract.
address public custody;

/// @notice The address of the TSS (Threshold Signature Scheme) contract.
address public tssAddress;
/// @notice The address of the ZetaConnector contract.
address public zetaConnector;
/// @notice The address of the Zeta token contract.
address public zetaToken;

event ExecutedV2(address indexed destination, uint256 value, bytes data);

constructor() {}

function initialize(address _tssAddress, address _zetaToken) public initializer {
if (_tssAddress == address(0) || _zetaToken == address(0)) {
revert ZeroAddress();
}

__Ownable_init();
__UUPSUpgradeable_init();

if (_tssAddress == address(0)) revert ZeroAddress();
__ReentrancyGuard_init();

tssAddress = _tssAddress;
zetaToken = _zetaToken;
}

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

function _execute(address destination, bytes calldata data) internal returns (bytes memory) {
(bool success, bytes memory result) = destination.call{value: msg.value}(data);

if (!success) revert ExecutionFailed();

return result;
}

// Called by the TSS
// Calling onRevert directly
function executeRevert(address destination, bytes calldata data) public payable {

Check notice

Code scanning / Slither

Missing zero address validation Low

(bool success, bytes memory result) = destination.call{value: msg.value}("");
if (!success) revert ExecutionFailed();
Revertable(destination).onRevert(data);

emit Reverted(destination, msg.value, data);
}
Comment on lines +58 to +64

Check notice

Code scanning / Slither

Reentrancy vulnerabilities Low

Comment on lines +58 to +64

Check warning

Code scanning / Slither

Low-level calls Warning


// Called by the TSS
// Execution without ERC20 tokens, it is payable and can be used in the case of WithdrawAndCall for Gas ZRC20
// It can be also used for contract call without asset movement
Expand All @@ -64,7 +83,7 @@
address to,
uint256 amount,
bytes calldata data
) public returns (bytes memory) {
) public nonReentrant {
if (amount == 0) revert InsufficientETHAmount();
// Approve the target contract to spend the tokens
if(!resetApproval(token, to)) revert ApprovalFailed();
Expand All @@ -79,16 +98,26 @@
// Transfer any remaining tokens back to the custody/connector contract
uint256 remainingBalance = IERC20(token).balanceOf(address(this));
if (remainingBalance > 0) {
address destination = address(custody);
if (token == zetaToken) {
destination = address(zetaConnector);
}
IERC20(token).safeTransfer(address(destination), remainingBalance);
transferToAssetHandler(token, amount);
}

emit ExecutedWithERC20(token, to, amount, data);
}

return result;
// Called by the ERC20Custody contract
// Directly transfers ERC20 and calls onRevert
function revertWithERC20(
address token,
address to,
uint256 amount,
bytes calldata data
) external nonReentrant {
if (amount == 0) revert InsufficientERC20Amount();

IERC20(token).safeTransfer(address(to), amount);
Revertable(to).onRevert(data);

emit RevertedWithERC20(token, to, amount, data);
}

// Deposit ETH to tss
Expand All @@ -101,15 +130,11 @@
emit Deposit(msg.sender, receiver, msg.value, address(0), "");
}

// Deposit ERC20 tokens to custody
// Deposit ERC20 tokens to custody/connector
function deposit(address receiver, uint256 amount, address asset) external {
if (amount == 0) revert InsufficientERC20Amount();

address destination = address(custody);
if (asset == zetaToken) {
destination = address(zetaConnector);
}
IERC20(asset).safeTransferFrom(msg.sender, address(destination), amount);
transferFromToAssetHandler(msg.sender, asset, amount);

emit Deposit(msg.sender, receiver, amount, asset, "");
}
Expand All @@ -124,15 +149,11 @@
emit Deposit(msg.sender, receiver, msg.value, address(0), payload);
}

// Deposit ERC20 tokens to custody and call an omnichain smart contract
// Deposit ERC20 tokens to custody/connector and call an omnichain smart contract
function depositAndCall(address receiver, uint256 amount, address asset, bytes calldata payload) external {
if (amount == 0) revert InsufficientERC20Amount();

address destination = address(custody);
if (asset == zetaToken) {
destination = address(zetaConnector);
}
IERC20(asset).safeTransferFrom(msg.sender, address(destination), amount);
transferFromToAssetHandler(msg.sender, asset, amount);

emit Deposit(msg.sender, receiver, amount, asset, payload);
}
Expand All @@ -144,15 +165,43 @@

function setCustody(address _custody) external {
if (custody != address(0)) revert CustodyInitialized();
if (_custody == address(0)) revert ZeroAddress();

custody = _custody;
}

function setConnector(address _zetaConnector) external {
if (zetaConnector != address(0)) revert CustodyInitialized();
if (_zetaConnector == address(0)) revert ZeroAddress();

zetaConnector = _zetaConnector;
}

function resetApproval(address token, address to) private returns (bool) {
return IERC20(token).approve(to, 0);
}

function transferFromToAssetHandler(address from, address token, uint256 amount) private {
if (token == zetaToken) { // transfer to connector
// transfer amount to gateway
IERC20(token).safeTransferFrom(from, address(this), amount);
// approve connector to handle tokens depending on connector version (eg. lock or burn)
IERC20(token).approve(zetaConnector, amount);
// send tokens to connector
ZetaConnectorNewBase(zetaConnector).receiveTokens(amount);
} else { // transfer to custody
IERC20(token).safeTransferFrom(from, custody, amount);
}
}
Comment on lines +184 to +195

Check warning

Code scanning / Slither

Unused return Medium


function transferToAssetHandler(address token, uint256 amount) private {
if (token == zetaToken) { // transfer to connector
// approve connector to handle tokens depending on connector version (eg. lock or burn)
IERC20(token).approve(zetaConnector, amount);
// send tokens to connector
ZetaConnectorNewBase(zetaConnector).receiveTokens(amount);
} else { // transfer to custody
IERC20(token).safeTransfer(custody, amount);
}
}
Comment on lines +197 to +206

Check warning

Code scanning / Slither

Unused return Medium

}

Check warning

Code scanning / Slither

Missing inheritance Warning

GatewayEVMUpgradeTest should inherit from IGatewayEVM
15 changes: 14 additions & 1 deletion contracts/prototypes/evm/IGatewayEVM.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ pragma solidity ^0.8.0;

interface IGatewayEVMEvents {
event Executed(address indexed destination, uint256 value, bytes data);
event Reverted(address indexed destination, uint256 value, bytes data);
event ExecutedWithERC20(address indexed token, address indexed to, uint256 amount, bytes data);
event RevertedWithERC20(address indexed token, address indexed to, uint256 amount, bytes data);
event Deposit(address indexed sender, address indexed receiver, uint256 amount, address asset, bytes payload);
event Call(address indexed sender, address indexed receiver, bytes payload);
}
Expand All @@ -27,4 +29,15 @@ interface IGatewayEVM {
) external;

function execute(address destination, bytes calldata data) external payable returns (bytes memory);
}

function revertWithERC20(
address token,
address to,
uint256 amount,
bytes calldata data
) external;
}

interface Revertable {
function onRevert(bytes calldata data) external;
}
Loading
Loading