Sfoglia il codice sorgente

evm: add token and nft bridge interface (#1710)

* Add token and nft bridge interface

* Add wormhole method to nft and bridge interface

* ethereum: add test to ensure interface match

* Add all public methods to interfaces

Co-authored-by: gator-boi <gator-boi@users.noreply.github.com>
Co-authored-by: Evan Gray <battledingo@gmail.com>
Reptile 3 anni fa
parent
commit
bac99e912f

+ 3 - 0
ethereum/Makefile

@@ -48,6 +48,9 @@ test-upgrade: build .env node_modules
 
 .PHONY:
 test-forge: dependencies
+	./compare-method-identifiers.sh contracts/Implementation.sol:Implementation contracts/interfaces/IWormhole.sol:IWormhole
+	./compare-method-identifiers.sh contracts/bridge/BridgeImplementation.sol:BridgeImplementation contracts/bridge/interfaces/ITokenBridge.sol:ITokenBridge
+	./compare-method-identifiers.sh contracts/nft/NFTBridgeImplementation.sol:NFTBridgeImplementation contracts/nft/interfaces/INFTBridge.sol:INFTBridge
 	forge test
 
 clean:

+ 15 - 0
ethereum/compare-method-identifiers.sh

@@ -0,0 +1,15 @@
+#!/bin/bash
+TMP=$(mktemp -d)
+f1="$TMP/$1.interface"
+f2="$TMP/$2.interface"
+mkdir -p $(dirname "$f1")
+mkdir -p $(dirname "$f2")
+function clean_up () {
+    ARG=$?
+    rm -rf "$TMP"
+    exit $ARG
+}
+trap clean_up SIGINT SIGTERM EXIT
+forge inspect $1 mi > "$f1"
+forge inspect $2 mi > "$f2"
+git diff --no-index "$f1" "$f2" --exit-code && echo "✅ Method interfaces are identical" || (echo "❌ Method interfaces are different" >&2 && exit 1)

+ 1 - 6
ethereum/contracts/bridge/BridgeGetters.sol

@@ -6,6 +6,7 @@ pragma solidity ^0.8.0;
 import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
 
 import "../interfaces/IWormhole.sol";
+import "./interfaces/IWETH.sol";
 
 import "./BridgeState.sol";
 
@@ -74,9 +75,3 @@ contract BridgeGetters is BridgeState {
         return _state.provider.finality;
     }
 }
-
-interface IWETH is IERC20 {
-    function deposit() external payable;
-
-    function withdraw(uint amount) external;
-}

+ 152 - 0
ethereum/contracts/bridge/interfaces/ITokenBridge.sol

@@ -0,0 +1,152 @@
+// contracts/Bridge.sol
+// SPDX-License-Identifier: Apache 2
+
+pragma solidity ^0.8.0;
+
+import "./IWETH.sol";
+import "../../interfaces/IWormhole.sol";
+
+interface ITokenBridge {
+    struct Transfer {
+        uint8 payloadID;
+        uint256 amount;
+        bytes32 tokenAddress;
+        uint16 tokenChain;
+        bytes32 to;
+        uint16 toChain;
+        uint256 fee;
+    }
+
+    struct TransferWithPayload {
+        uint8 payloadID;
+        uint256 amount;
+        bytes32 tokenAddress;
+        uint16 tokenChain;
+        bytes32 to;
+        uint16 toChain;
+        bytes32 fromAddress;
+        bytes payload;
+    }
+
+    struct AssetMeta {
+        uint8 payloadID;
+        bytes32 tokenAddress;
+        uint16 tokenChain;
+        uint8 decimals;
+        bytes32 symbol;
+        bytes32 name;
+    }
+
+    struct RegisterChain {
+        bytes32 module;
+        uint8 action;
+        uint16 chainId;
+
+        uint16 emitterChainID;
+        bytes32 emitterAddress;
+    }
+
+     struct UpgradeContract {
+        bytes32 module;
+        uint8 action;
+        uint16 chainId;
+
+        bytes32 newContract;
+    }
+
+    struct RecoverChainId {
+        bytes32 module;
+        uint8 action;
+
+        uint256 evmChainId;
+        uint16 newChainId;
+    }
+
+    event ContractUpgraded(address indexed oldContract, address indexed newContract);
+
+    function _parseTransferCommon(bytes memory encoded) external pure returns (Transfer memory transfer);
+
+    function attestToken(address tokenAddress, uint32 nonce) external payable returns (uint64 sequence);
+
+    function wrapAndTransferETH(uint16 recipientChain, bytes32 recipient, uint256 arbiterFee, uint32 nonce) external payable returns (uint64 sequence);
+
+    function wrapAndTransferETHWithPayload(uint16 recipientChain, bytes32 recipient, uint32 nonce, bytes memory payload) external payable returns (uint64 sequence);
+
+    function transferTokens(address token, uint256 amount, uint16 recipientChain, bytes32 recipient, uint256 arbiterFee, uint32 nonce) external payable returns (uint64 sequence);
+
+    function transferTokensWithPayload(address token, uint256 amount, uint16 recipientChain, bytes32 recipient, uint32 nonce, bytes memory payload) external payable returns (uint64 sequence);
+
+    function updateWrapped(bytes memory encodedVm) external returns (address token);
+
+    function createWrapped(bytes memory encodedVm) external returns (address token);
+
+    function completeTransferWithPayload(bytes memory encodedVm) external returns (bytes memory);
+
+    function completeTransferAndUnwrapETHWithPayload(bytes memory encodedVm) external returns (bytes memory);
+
+    function completeTransfer(bytes memory encodedVm) external;
+
+    function completeTransferAndUnwrapETH(bytes memory encodedVm) external;
+
+    function encodeAssetMeta(AssetMeta memory meta) external pure returns (bytes memory encoded);
+
+    function encodeTransfer(Transfer memory transfer) external pure returns (bytes memory encoded);
+
+    function encodeTransferWithPayload(TransferWithPayload memory transfer) external pure returns (bytes memory encoded);
+
+    function parsePayloadID(bytes memory encoded) external pure returns (uint8 payloadID);
+
+    function parseAssetMeta(bytes memory encoded) external pure returns (AssetMeta memory meta);
+
+    function parseTransfer(bytes memory encoded) external pure returns (Transfer memory transfer);
+
+    function parseTransferWithPayload(bytes memory encoded) external pure returns (TransferWithPayload memory transfer);
+
+    function governanceActionIsConsumed(bytes32 hash) external view returns (bool);
+
+    function isInitialized(address impl) external view returns (bool);
+
+    function isTransferCompleted(bytes32 hash) external view returns (bool);
+
+    function wormhole() external view returns (IWormhole);
+
+    function chainId() external view returns (uint16);
+
+    function evmChainId() external view returns (uint256);
+
+    function isFork() external view returns (bool);
+
+    function governanceChainId() external view returns (uint16);
+
+    function governanceContract() external view returns (bytes32);
+
+    function wrappedAsset(uint16 tokenChainId, bytes32 tokenAddress) external view returns (address);
+
+    function bridgeContracts(uint16 chainId_) external view returns (bytes32);
+
+    function tokenImplementation() external view returns (address);
+
+    function WETH() external view returns (IWETH);
+
+    function outstandingBridged(address token) external view returns (uint256);
+
+    function isWrappedAsset(address token) external view returns (bool);
+
+    function finality() external view returns (uint8);
+
+    function implementation() external view returns (address);
+
+    function initialize() external;
+
+    function registerChain(bytes memory encodedVM) external;
+
+    function upgrade(bytes memory encodedVM) external;
+
+    function submitRecoverChainId(bytes memory encodedVM) external;
+
+    function parseRegisterChain(bytes memory encoded) external pure returns (RegisterChain memory chain);
+
+    function parseUpgrade(bytes memory encoded) external pure returns (UpgradeContract memory chain);
+
+    function parseRecoverChainId(bytes memory encodedRecoverChainId) external pure returns (RecoverChainId memory rci);
+}

+ 11 - 0
ethereum/contracts/bridge/interfaces/IWETH.sol

@@ -0,0 +1,11 @@
+// contracts/Bridge.sol
+// SPDX-License-Identifier: Apache 2
+
+pragma solidity ^0.8.0;
+
+import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
+
+interface IWETH is IERC20 {
+    function deposit() external payable;
+    function withdraw(uint amount) external;
+}

+ 1 - 5
ethereum/contracts/bridge/mock/MockTokenBridgeIntegration.sol

@@ -9,11 +9,7 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
 
 import "../../libraries/external/BytesLib.sol";
 import "../../interfaces/IWormhole.sol";
-
-interface ITokenBridge {
-    function completeTransferWithPayload(bytes memory encodedVm) external returns (bytes memory);
-    function wrappedAsset(uint16 tokenChainId, bytes32 tokenAddress) external view returns (address);
-}
+import "../interfaces/ITokenBridge.sol";
 
 contract MockTokenBridgeIntegration {
     using BytesLib for bytes;

+ 113 - 13
ethereum/contracts/interfaces/IWormhole.sol

@@ -3,10 +3,80 @@
 
 pragma solidity ^0.8.0;
 
-import "../Structs.sol";
+interface IWormhole {
+    struct GuardianSet {
+        address[] keys;
+        uint32 expirationTime;
+    }
+
+    struct Signature {
+        bytes32 r;
+        bytes32 s;
+        uint8 v;
+        uint8 guardianIndex;
+    }
+
+    struct VM {
+        uint8 version;
+        uint32 timestamp;
+        uint32 nonce;
+        uint16 emitterChainId;
+        bytes32 emitterAddress;
+        uint64 sequence;
+        uint8 consistencyLevel;
+        bytes payload;
+
+        uint32 guardianSetIndex;
+        Signature[] signatures;
+
+        bytes32 hash;
+    }
+
+    struct ContractUpgrade {
+        bytes32 module;
+        uint8 action;
+        uint16 chain;
+
+        address newContract;
+    }
+
+    struct GuardianSetUpgrade {
+        bytes32 module;
+        uint8 action;
+        uint16 chain;
+
+        GuardianSet newGuardianSet;
+        uint32 newGuardianSetIndex;
+    }
+
+    struct SetMessageFee {
+        bytes32 module;
+        uint8 action;
+        uint16 chain;
+
+        uint256 messageFee;
+    }
+
+    struct TransferFees {
+        bytes32 module;
+        uint8 action;
+        uint16 chain;
+
+        uint256 amount;
+        bytes32 recipient;
+    }
+
+    struct RecoverChainId {
+        bytes32 module;
+        uint8 action;
+
+        uint256 evmChainId;
+        uint16 newChainId;
+    }
 
-interface IWormhole is Structs {
     event LogMessagePublished(address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel);
+    event ContractUpgraded(address indexed oldContract, address indexed newContract);
+    event GuardianSetAdded(uint32 indexed index);
 
     function publishMessage(
         uint32 nonce,
@@ -14,29 +84,59 @@ interface IWormhole is Structs {
         uint8 consistencyLevel
     ) external payable returns (uint64 sequence);
 
-    function parseAndVerifyVM(bytes calldata encodedVM) external view returns (Structs.VM memory vm, bool valid, string memory reason);
+    function initialize() external;
 
-    function verifyVM(Structs.VM memory vm) external view returns (bool valid, string memory reason);
+    function parseAndVerifyVM(bytes calldata encodedVM) external view returns (VM memory vm, bool valid, string memory reason);
 
-    function verifySignatures(bytes32 hash, Structs.Signature[] memory signatures, Structs.GuardianSet memory guardianSet) external pure returns (bool valid, string memory reason) ;
+    function verifyVM(VM memory vm) external view returns (bool valid, string memory reason);
 
-    function parseVM(bytes memory encodedVM) external pure returns (Structs.VM memory vm);
+    function verifySignatures(bytes32 hash, Signature[] memory signatures, GuardianSet memory guardianSet) external pure returns (bool valid, string memory reason);
 
-    function getGuardianSet(uint32 index) external view returns (Structs.GuardianSet memory) ;
+    function parseVM(bytes memory encodedVM) external pure returns (VM memory vm);
 
-    function getCurrentGuardianSetIndex() external view returns (uint32) ;
+    function quorum(uint numGuardians) external pure returns (uint numSignaturesRequiredForQuorum);
 
-    function getGuardianSetExpiry() external view returns (uint32) ;
+    function getGuardianSet(uint32 index) external view returns (GuardianSet memory);
 
-    function governanceActionIsConsumed(bytes32 hash) external view returns (bool) ;
+    function getCurrentGuardianSetIndex() external view returns (uint32);
 
-    function isInitialized(address impl) external view returns (bool) ;
+    function getGuardianSetExpiry() external view returns (uint32);
 
-    function chainId() external view returns (uint16) ;
+    function governanceActionIsConsumed(bytes32 hash) external view returns (bool);
+
+    function isInitialized(address impl) external view returns (bool);
+
+    function chainId() external view returns (uint16);
+
+    function isFork() external view returns (bool);
 
     function governanceChainId() external view returns (uint16);
 
     function governanceContract() external view returns (bytes32);
 
-    function messageFee() external view returns (uint256) ;
+    function messageFee() external view returns (uint256);
+
+    function evmChainId() external view returns (uint256);
+
+    function nextSequence(address emitter) external view returns (uint64);
+
+    function parseContractUpgrade(bytes memory encodedUpgrade) external pure returns (ContractUpgrade memory cu);
+
+    function parseGuardianSetUpgrade(bytes memory encodedUpgrade) external pure returns (GuardianSetUpgrade memory gsu);
+
+    function parseSetMessageFee(bytes memory encodedSetMessageFee) external pure returns (SetMessageFee memory smf);
+
+    function parseTransferFees(bytes memory encodedTransferFees) external pure returns (TransferFees memory tf);
+
+    function parseRecoverChainId(bytes memory encodedRecoverChainId) external pure returns (RecoverChainId memory rci);
+
+    function submitContractUpgrade(bytes memory _vm) external;
+
+    function submitSetMessageFee(bytes memory _vm) external;
+
+    function submitNewGuardianSet(bytes memory _vm) external;
+
+    function submitTransferFees(bytes memory _vm) external;
+
+    function submitRecoverChainId(bytes memory _vm) external;
 }

+ 107 - 0
ethereum/contracts/nft/interfaces/INFTBridge.sol

@@ -0,0 +1,107 @@
+// contracts/NFTBridge.sol
+// SPDX-License-Identifier: Apache 2
+
+pragma solidity ^0.8.0;
+
+import "../../interfaces/IWormhole.sol";
+
+interface INFTBridge {
+    struct Transfer {
+        bytes32 tokenAddress;
+        uint16 tokenChain;
+        bytes32 symbol;
+        bytes32 name;
+        uint256 tokenID;
+        string uri;
+        bytes32 to;
+        uint16 toChain;
+    }
+
+    struct SPLCache {
+        bytes32 name;
+        bytes32 symbol;
+    }
+
+     struct RegisterChain {
+        bytes32 module;
+        uint8 action;
+        uint16 chainId;
+
+        uint16 emitterChainID;
+        bytes32 emitterAddress;
+    }
+
+    struct UpgradeContract {
+        bytes32 module;
+        uint8 action;
+        uint16 chainId;
+
+        bytes32 newContract;
+    }
+
+    struct RecoverChainId {
+        bytes32 module;
+        uint8 action;
+
+        uint256 evmChainId;
+        uint16 newChainId;
+    }
+
+    event ContractUpgraded(address indexed oldContract, address indexed newContract);
+
+    function transferNFT(address token, uint256 tokenID, uint16 recipientChain, bytes32 recipient, uint32 nonce) external payable returns (uint64 sequence);
+
+    function completeTransfer(bytes memory encodeVm) external;
+
+    function encodeTransfer(Transfer memory transfer) external pure returns (bytes memory encoded);
+
+    function parseTransfer(bytes memory encoded) external pure returns (Transfer memory transfer);
+
+    function onERC721Received(address operator, address, uint256, bytes calldata) external view returns (bytes4);
+
+    function governanceActionIsConsumed(bytes32 hash) external view returns (bool);
+
+    function isInitialized(address impl) external view returns (bool);
+
+    function isTransferCompleted(bytes32 hash) external view returns (bool);
+
+    function wormhole() external view returns (IWormhole);
+
+    function chainId() external view returns (uint16);
+
+    function evmChainId() external view returns (uint256);
+
+    function isFork() external view returns (bool);
+
+    function governanceChainId() external view returns (uint16);
+
+    function governanceContract() external view returns (bytes32);
+
+    function wrappedAsset(uint16 tokenChainId, bytes32 tokenAddress) external view returns (address);
+
+    function bridgeContracts(uint16 chainId_) external view returns (bytes32);
+
+    function tokenImplementation() external view returns (address);
+
+    function isWrappedAsset(address token) external view returns (bool);
+
+    function splCache(uint256 tokenId) external view returns (SPLCache memory);
+
+    function finality() external view returns (uint8);
+
+    function initialize() external;
+
+    function implementation() external view returns (address);
+
+    function registerChain(bytes memory encodedVM) external;
+
+    function upgrade(bytes memory encodedVM) external;
+
+    function submitRecoverChainId(bytes memory encodedVM) external;
+
+    function parseRegisterChain(bytes memory encoded) external pure returns(RegisterChain memory chain);
+
+    function parseUpgrade(bytes memory encoded) external pure returns(UpgradeContract memory chain);
+
+    function parseRecoverChainId(bytes memory encodedRecoverChainId) external pure returns (RecoverChainId memory rci);
+}