Skip to content

Commit

Permalink
connectors upgradable
Browse files Browse the repository at this point in the history
  • Loading branch information
skosito committed Oct 10, 2024
1 parent 579a1ac commit 758ea1c
Show file tree
Hide file tree
Showing 12 changed files with 108 additions and 41 deletions.
29 changes: 21 additions & 8 deletions v2/contracts/evm/ZetaConnectorBase.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

import { RevertContext } from "../../contracts/Revert.sol";
import { IGatewayEVM, IGatewayEVMErrors, IGatewayEVMEvents } from "../../contracts/evm/interfaces/IGatewayEVM.sol";
Expand All @@ -14,16 +16,23 @@ import "../../contracts/evm/interfaces/IZetaConnector.sol";
/// @title ZetaConnectorBase
/// @notice Abstract base contract for ZetaConnector.
/// @dev This contract implements basic functionality for handling tokens and interacting with the Gateway contract.
abstract contract ZetaConnectorBase is IZetaConnectorEvents, ReentrancyGuard, Pausable, AccessControl {
abstract contract ZetaConnectorBase is
Initializable,
UUPSUpgradeable,
IZetaConnectorEvents,
ReentrancyGuardUpgradeable,
PausableUpgradeable,
AccessControlUpgradeable
{
using SafeERC20 for IERC20;

/// @notice Error indicating that a zero address was provided.
error ZeroAddress();

/// @notice The Gateway contract used for executing cross-chain calls.
IGatewayEVM public immutable gateway;
IGatewayEVM public gateway;
/// @notice The address of the Zeta token.
address public immutable zetaToken;
address public zetaToken;
/// @notice The address of the TSS (Threshold Signature Scheme) contract.
address public tssAddress;

Expand All @@ -34,9 +43,9 @@ abstract contract ZetaConnectorBase is IZetaConnectorEvents, ReentrancyGuard, Pa
/// @notice New role identifier for tss role.
bytes32 public constant TSS_ROLE = keccak256("TSS_ROLE");

/// @notice Constructor for ZetaConnectors.
/// @notice Initializer for ZetaConnectors.
/// @dev Set admin as default admin and pauser, and tssAddress as tss role.
constructor(address gateway_, address zetaToken_, address tssAddress_, address admin_) {
function initialize(address gateway_, address zetaToken_, address tssAddress_, address admin_) public virtual initializer {
if (gateway_ == address(0) || zetaToken_ == address(0) || tssAddress_ == address(0) || admin_ == address(0)) {
revert ZeroAddress();
}
Expand All @@ -50,6 +59,10 @@ abstract contract ZetaConnectorBase is IZetaConnectorEvents, ReentrancyGuard, Pa
_grantRole(PAUSER_ROLE, admin_);
}

/// @dev Authorizes the upgrade of the contract, sender must be owner.
/// @param newImplementation Address of the new implementation.
function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) { }

/// @notice Update tss address
/// @param newTSSAddress new tss address
function updateTSSAddress(address newTSSAddress) external onlyRole(DEFAULT_ADMIN_ROLE) {
Expand Down
11 changes: 3 additions & 8 deletions v2/contracts/evm/ZetaConnectorNative.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,9 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
contract ZetaConnectorNative is ZetaConnectorBase {
using SafeERC20 for IERC20;

constructor(
address gateway_,
address zetaToken_,
address tssAddress_,
address admin_
)
ZetaConnectorBase(gateway_, zetaToken_, tssAddress_, admin_)
{ }
function initialize(address gateway_, address zetaToken_, address tssAddress_, address admin_) public override initializer {
super.initialize(gateway_, zetaToken_, tssAddress_, admin_);
}

/// @notice Withdraw tokens to a specified address.
/// @param to The address to withdraw tokens to.
Expand Down
19 changes: 8 additions & 11 deletions v2/contracts/evm/ZetaConnectorNonNative.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,20 @@ import "./interfaces/IZetaNonEthNew.sol";
/// @notice Implementation of ZetaConnectorBase for non-native token handling.
/// @dev This contract mints and burns Zeta tokens and interacts with the Gateway contract.
contract ZetaConnectorNonNative is ZetaConnectorBase {
/// @notice Max supply for minting.
uint256 public maxSupply = type(uint256).max;

/// @notice Event triggered when max supply is updated.
/// @param maxSupply New max supply.
event MaxSupplyUpdated(uint256 maxSupply);

error ExceedsMaxSupply();

constructor(
address gateway_,
address zetaToken_,
address tssAddress_,
address admin_
)
ZetaConnectorBase(gateway_, zetaToken_, tssAddress_, admin_)
{ }
/// @notice Max supply for minting.
uint256 public maxSupply;

function initialize(address gateway_, address zetaToken_, address tssAddress_, address admin_) public override initializer {
super.initialize(gateway_, zetaToken_, tssAddress_, admin_);

maxSupply = type(uint256).max;
}

/// @notice Set max supply for minting.
/// @param maxSupply_ New max supply.
Expand Down
43 changes: 36 additions & 7 deletions v2/scripts/deploy/deterministic/DeployZetaConnectorNonNative.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity 0.8.26;

import "forge-std/Script.sol";
import "contracts/evm/ZetaConnectorNonNative.sol";
import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

contract DeployZetaConnectorNonNative is Script {
function run() external {
Expand All @@ -11,19 +12,47 @@ contract DeployZetaConnectorNonNative is Script {
address gateway = vm.envAddress("GATEWAY_PROXY_EVM");
address zeta = vm.envAddress("ZETA_ERC20_EVM");

bytes32 salt = keccak256("ZetaConnectorNonNative");
address expectedImplAddress;
address expectedProxyAddress;

bytes32 implSalt = keccak256("ZetaConnectorNonNative");
bytes32 proxySalt = keccak256("ZetaConnectorNonNativeProxy");

vm.startBroadcast();

ZetaConnectorNonNative connector = new ZetaConnectorNonNative{salt: salt}(gateway, zeta, tss, admin);
require(address(connector) != address(0), "deployment failed");
expectedImplAddress = vm.computeCreate2Address(
implSalt,
hashInitCode(type(ZetaConnectorNonNative).creationCode)
);

ZetaConnectorNonNative connectorImpl = new ZetaConnectorNonNative{salt: implSalt}();
require(address(connectorImpl) != address(0), "connectorImpl deployment failed");

require(expectedImplAddress == address(connectorImpl), "impl address doesn't match expected address");

address expectedAddr = vm.computeCreate2Address(
salt,
hashInitCode(type(ZetaConnectorNonNative).creationCode, abi.encode(gateway, zeta, tss, admin))
expectedProxyAddress = vm.computeCreate2Address(
proxySalt,
hashInitCode(
type(ERC1967Proxy).creationCode,
abi.encode(
address(connectorImpl),
abi.encodeWithSelector(ZetaConnectorNonNative.initialize.selector, gateway, zeta, tss, admin)
)
)
);

require(expectedAddr == address(connector), "zeta connector non native address doesn't match expected address");
ERC1967Proxy connectorProxy = new ERC1967Proxy{salt: proxySalt}(
address(connectorImpl),
abi.encodeWithSelector(ZetaConnectorNonNative.initialize.selector, gateway, zeta, tss, admin)
);
require(address(connectorProxy) != address(0), "connectorProxy deployment failed");

require(expectedProxyAddress == address(connectorProxy), "proxy address doesn't match expected address");

ZetaConnectorNonNative connector = ZetaConnectorNonNative(address(connectorProxy));
require(connector.tssAddress() == tss, "tss not set");
require(address(connector.gateway()) == gateway, "gateway not set");
require(address(connector.zetaToken()) == zeta, "zeta not set");

vm.stopBroadcast();
}
Expand Down
6 changes: 5 additions & 1 deletion v2/test/ERC20Custody.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,11 @@ contract ERC20CustodyTest is Test, IGatewayEVMErrors, IGatewayEVMEvents, IReceiv
"ERC20Custody.sol", abi.encodeCall(ERC20Custody.initialize, (address(gateway), tssAddress, owner))
);
custody = ERC20Custody(proxy);
zetaConnector = new ZetaConnectorNonNative(address(gateway), address(zeta), tssAddress, owner);
proxy = Upgrades.deployUUPSProxy(
"ZetaConnectorNonNative.sol",
abi.encodeCall(ZetaConnectorNonNative.initialize, (address(gateway), address(zeta), tssAddress, owner))
);
zetaConnector = ZetaConnectorNonNative(proxy);
receiver = new ReceiverEVM();

vm.deal(tssAddress, 1 ether);
Expand Down
14 changes: 12 additions & 2 deletions v2/test/GatewayEVM.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,12 @@ contract GatewayEVMTest is Test, IGatewayEVMErrors, IGatewayEVMEvents, IReceiver
"ERC20Custody.sol", abi.encodeCall(ERC20Custody.initialize, (address(gateway), tssAddress, owner))
);
custody = ERC20Custody(proxy);
zetaConnector = new ZetaConnectorNonNative(address(gateway), address(zeta), tssAddress, owner);
proxy = Upgrades.deployUUPSProxy(
"ZetaConnectorNonNative.sol",
abi.encodeCall(ZetaConnectorNonNative.initialize, (address(gateway), address(zeta), tssAddress, owner))
);
zetaConnector = ZetaConnectorNonNative(proxy);

vm.prank(tssAddress);
zeta.updateTssAndConnectorAddresses(tssAddress, address(zetaConnector));
receiver = new ReceiverEVM();
Expand Down Expand Up @@ -394,7 +399,12 @@ contract GatewayEVMInboundTest is Test, IGatewayEVMErrors, IGatewayEVMEvents, IR
"ERC20Custody.sol", abi.encodeCall(ERC20Custody.initialize, (address(gateway), tssAddress, owner))
);
custody = ERC20Custody(proxy);
zetaConnector = new ZetaConnectorNonNative(address(gateway), address(zeta), tssAddress, owner);
proxy = Upgrades.deployUUPSProxy(
"ZetaConnectorNonNative.sol",
abi.encodeCall(ZetaConnectorBase.initialize, (address(gateway), address(zeta), tssAddress, owner))
);
zetaConnector = ZetaConnectorNonNative(proxy);

vm.prank(tssAddress);
zeta.updateTssAndConnectorAddresses(tssAddress, address(zetaConnector));
vm.deal(tssAddress, 1 ether);
Expand Down
7 changes: 6 additions & 1 deletion v2/test/GatewayEVMUpgrade.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,12 @@ contract GatewayEVMUUPSUpgradeTest is Test, IGatewayEVMErrors, IGatewayEVMEvents
"ERC20Custody.sol", abi.encodeCall(ERC20Custody.initialize, (address(gateway), tssAddress, owner))
);
custody = ERC20Custody(erc20CustodyProxy);
zetaConnector = new ZetaConnectorNonNative(address(gateway), address(zeta), tssAddress, owner);
address connectorProxy = Upgrades.deployUUPSProxy(
"ZetaConnectorNonNative.sol",
abi.encodeCall(ZetaConnectorNonNative.initialize, (address(gateway), address(zeta), tssAddress, owner))
);
zetaConnector = ZetaConnectorNonNative(connectorProxy);

receiver = new ReceiverEVM();

vm.deal(tssAddress, 1 ether);
Expand Down
6 changes: 5 additions & 1 deletion v2/test/GatewayEVMZEVM.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,11 @@ contract GatewayEVMZEVMTest is
"ERC20Custody.sol", abi.encodeCall(ERC20Custody.initialize, (address(gatewayEVM), tssAddress, ownerEVM))
);
custody = ERC20Custody(proxy);
zetaConnector = new ZetaConnectorNonNative(address(gatewayEVM), address(zeta), tssAddress, ownerEVM);
proxy = Upgrades.deployUUPSProxy(
"ZetaConnectorNonNative.sol",
abi.encodeCall(ZetaConnectorNonNative.initialize, (address(gatewayEVM), address(zeta), tssAddress, ownerEVM))
);
zetaConnector = ZetaConnectorNonNative(proxy);

vm.deal(tssAddress, 1 ether);

Expand Down
6 changes: 5 additions & 1 deletion v2/test/ZetaConnectorNative.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ contract ZetaConnectorNativeTest is
"ERC20Custody.sol", abi.encodeCall(ERC20Custody.initialize, (address(gateway), tssAddress, owner))
);
custody = ERC20Custody(proxy);
zetaConnector = new ZetaConnectorNative(address(gateway), address(zetaToken), tssAddress, owner);
proxy = Upgrades.deployUUPSProxy(
"ZetaConnectorNative.sol",
abi.encodeCall(ZetaConnectorNative.initialize, (address(gateway), address(zetaToken), tssAddress, owner))
);
zetaConnector = ZetaConnectorNative(proxy);

receiver = new ReceiverEVM();

Expand Down
6 changes: 5 additions & 1 deletion v2/test/ZetaConnectorNonNative.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ contract ZetaConnectorNonNativeTest is
"ERC20Custody.sol", abi.encodeCall(ERC20Custody.initialize, (address(gateway), tssAddress, owner))
);
custody = ERC20Custody(proxy);
zetaConnector = new ZetaConnectorNonNative(address(gateway), address(zetaToken), tssAddress, owner);
proxy = Upgrades.deployUUPSProxy(
"ZetaConnectorNonNative.sol",
abi.encodeCall(ZetaConnectorNonNative.initialize, (address(gateway), address(zetaToken), tssAddress, owner))
);
zetaConnector = ZetaConnectorNonNative(proxy);

vm.prank(tssAddress);
zetaToken.updateTssAndConnectorAddresses(tssAddress, address(zetaConnector));
Expand Down
1 change: 1 addition & 0 deletions v2/test/fuzz/ERC20CustodyEchidnaTest.sol
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// TODO: https://github.com/zeta-chain/protocol-contracts/issues/384
// // SPDX-License-Identifier: MIT
// pragma solidity 0.8.26;

Expand Down
1 change: 1 addition & 0 deletions v2/test/fuzz/GatewayEVMEchidnaTest.sol
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// TODO: https://github.com/zeta-chain/protocol-contracts/issues/384
// // SPDX-License-Identifier: MIT
// pragma solidity 0.8.26;

Expand Down

0 comments on commit 758ea1c

Please sign in to comment.