فهرست منبع

Cleanup Ethereum from unused stuff (#214)

Also moves wormhole stuff to a separate directory
Ali Behjati 3 سال پیش
والد
کامیت
a1507952f6
60فایلهای تغییر یافته به همراه9 افزوده شده و 4991 حذف شده
  1. 4 2
      devnet/eth-devnet.yaml
  2. 0 438
      ethereum/contracts/bridge/Bridge.sol
  3. 0 70
      ethereum/contracts/bridge/BridgeGetters.sol
  4. 0 142
      ethereum/contracts/bridge/BridgeGovernance.sol
  5. 0 34
      ethereum/contracts/bridge/BridgeImplementation.sol
  6. 0 57
      ethereum/contracts/bridge/BridgeSetters.sol
  7. 0 34
      ethereum/contracts/bridge/BridgeSetup.sol
  8. 0 52
      ethereum/contracts/bridge/BridgeState.sol
  9. 0 66
      ethereum/contracts/bridge/BridgeStructs.sol
  10. 0 15
      ethereum/contracts/bridge/TokenBridge.sol
  11. 0 20
      ethereum/contracts/bridge/mock/MockBridgeImplementation.sol
  12. 0 177
      ethereum/contracts/bridge/mock/MockFeeToken.sol
  13. 0 12
      ethereum/contracts/bridge/mock/MockTokenImplementation.sol
  14. 0 81
      ethereum/contracts/bridge/mock/MockWETH9.sol
  15. 0 12
      ethereum/contracts/bridge/token/Token.sol
  16. 0 177
      ethereum/contracts/bridge/token/TokenImplementation.sol
  17. 0 31
      ethereum/contracts/bridge/token/TokenState.sol
  18. 0 68
      ethereum/contracts/bridge/utils/Migrator.sol
  19. 0 282
      ethereum/contracts/nft/NFTBridge.sol
  20. 0 15
      ethereum/contracts/nft/NFTBridgeEntrypoint.sol
  21. 0 60
      ethereum/contracts/nft/NFTBridgeGetters.sol
  22. 0 139
      ethereum/contracts/nft/NFTBridgeGovernance.sol
  23. 0 34
      ethereum/contracts/nft/NFTBridgeImplementation.sol
  24. 0 57
      ethereum/contracts/nft/NFTBridgeSetters.sol
  25. 0 31
      ethereum/contracts/nft/NFTBridgeSetup.sol
  26. 0 56
      ethereum/contracts/nft/NFTBridgeState.sol
  27. 0 54
      ethereum/contracts/nft/NFTBridgeStructs.sol
  28. 0 16
      ethereum/contracts/nft/mock/MockNFTBridgeImplementation.sol
  29. 0 12
      ethereum/contracts/nft/mock/MockNFTImplementation.sol
  30. 0 11
      ethereum/contracts/nft/token/NFT.sol
  31. 0 254
      ethereum/contracts/nft/token/NFTImplementation.sol
  32. 0 41
      ethereum/contracts/nft/token/NFTState.sol
  33. 1 1
      ethereum/contracts/pyth/PythGetters.sol
  34. 0 0
      ethereum/contracts/wormhole/Getters.sol
  35. 0 0
      ethereum/contracts/wormhole/Governance.sol
  36. 1 1
      ethereum/contracts/wormhole/GovernanceStructs.sol
  37. 0 0
      ethereum/contracts/wormhole/Implementation.sol
  38. 1 1
      ethereum/contracts/wormhole/Messages.sol
  39. 0 0
      ethereum/contracts/wormhole/Setters.sol
  40. 0 0
      ethereum/contracts/wormhole/Setup.sol
  41. 0 0
      ethereum/contracts/wormhole/State.sol
  42. 0 0
      ethereum/contracts/wormhole/Structs.sol
  43. 0 0
      ethereum/contracts/wormhole/Wormhole.sol
  44. 0 0
      ethereum/contracts/wormhole/interfaces/IWormhole.sol
  45. 0 0
      ethereum/contracts/wormhole/mock/MockImplementation.sol
  46. 0 38
      ethereum/migrations/test/3_deploy_bridge.js
  47. 0 0
      ethereum/migrations/test/3_deploy_pyth.js
  48. 0 36
      ethereum/migrations/test/4_deploy_nft_bridge.js
  49. 0 12
      ethereum/migrations/test/6_deploy_bridge_implementation_only.js
  50. 0 5
      ethereum/migrations/test/9_deploy_weth9.js
  51. 2 4
      ethereum/package.json
  52. 0 96
      ethereum/scripts/deploy_test_token.js
  53. 0 26
      ethereum/scripts/register_bsc_chain.js
  54. 0 26
      ethereum/scripts/register_eth_chain.js
  55. 0 34
      ethereum/scripts/register_solana_chain.js
  56. 0 35
      ethereum/scripts/register_terra_chain.js
  57. 0 973
      ethereum/test/bridge.js
  58. 0 653
      ethereum/test/nft.js
  59. 0 87
      ethereum/test/tokenmigrator.js
  60. 0 413
      ethereum/test/upgrades/01_tokenbridge_feetoken_support.js

+ 4 - 2
devnet/eth-devnet.yaml

@@ -73,7 +73,7 @@ spec:
           command:
             - /bin/sh
             - -c
-            - "npm run migrate --network development &&
+            - "npm run migrate -- --network development &&
                npx truffle test test/pyth.js 2>&1 &&
                nc -lkp 2000 0.0.0.0"
           readinessProbe:
@@ -128,7 +128,9 @@ spec:
           command:
             - /bin/sh
             - -c
-            - "sed -i 's/CHAIN_ID=0x2/CHAIN_ID=0x4/g' .env && npm run migrate && npx truffle exec scripts/deploy_test_token.js && npx truffle exec scripts/register_solana_chain.js && npx truffle exec scripts/register_terra_chain.js && npx truffle exec scripts/register_eth_chain.js && nc -lkp 2000 0.0.0.0"
+            - "sed -i 's/CHAIN_ID=0x2/CHAIN_ID=0x4/g' .env &&
+               npm run migrate -- --network development &&
+               nc -lkp 2000 0.0.0.0"
           readinessProbe:
             periodSeconds: 1
             failureThreshold: 300

+ 0 - 438
ethereum/contracts/bridge/Bridge.sol

@@ -1,438 +0,0 @@
-// contracts/Bridge.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
-import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
-import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
-
-import "../libraries/external/BytesLib.sol";
-
-import "./BridgeGetters.sol";
-import "./BridgeSetters.sol";
-import "./BridgeStructs.sol";
-import "./BridgeGovernance.sol";
-
-import "./token/Token.sol";
-import "./token/TokenImplementation.sol";
-
-contract Bridge is BridgeGovernance, ReentrancyGuard {
-    using BytesLib for bytes;
-
-    // Produce a AssetMeta message for a given token
-    function attestToken(address tokenAddress, uint32 nonce) public payable returns (uint64 sequence){
-        // decimals, symbol & token are not part of the core ERC20 token standard, so we need to support contracts that dont implement them
-        (,bytes memory queriedDecimals) = tokenAddress.staticcall(abi.encodeWithSignature("decimals()"));
-        (,bytes memory queriedSymbol) = tokenAddress.staticcall(abi.encodeWithSignature("symbol()"));
-        (,bytes memory queriedName) = tokenAddress.staticcall(abi.encodeWithSignature("name()"));
-
-        uint8 decimals = abi.decode(queriedDecimals, (uint8));
-
-        string memory symbolString = abi.decode(queriedSymbol, (string));
-        string memory nameString = abi.decode(queriedName, (string));
-
-        bytes32 symbol;
-        bytes32 name;
-        assembly {
-            // first 32 bytes hold string length
-            symbol := mload(add(symbolString, 32))
-            name := mload(add(nameString, 32))
-        }
-
-        BridgeStructs.AssetMeta memory meta = BridgeStructs.AssetMeta({
-        payloadID : 2,
-        // Address of the token. Left-zero-padded if shorter than 32 bytes
-        tokenAddress : bytes32(uint256(uint160(tokenAddress))),
-        // Chain ID of the token
-        tokenChain : chainId(),
-        // Number of decimals of the token (big-endian uint8)
-        decimals : decimals,
-        // Symbol of the token (UTF-8)
-        symbol : symbol,
-        // Name of the token (UTF-8)
-        name : name
-        });
-
-        bytes memory encoded = encodeAssetMeta(meta);
-
-        sequence = wormhole().publishMessage{
-            value : msg.value
-        }(nonce, encoded, 15);
-    }
-
-    function wrapAndTransferETH(uint16 recipientChain, bytes32 recipient, uint256 arbiterFee, uint32 nonce) public payable returns (uint64 sequence) {
-        uint wormholeFee = wormhole().messageFee();
-
-        require(wormholeFee < msg.value, "value is smaller than wormhole fee");
-
-        uint amount = msg.value - wormholeFee;
-
-        require(arbiterFee <= amount, "fee is bigger than amount minus wormhole fee");
-
-        uint normalizedAmount = normalizeAmount(amount, 18);
-        uint normalizedArbiterFee = normalizeAmount(arbiterFee, 18);
-
-        // refund dust
-        uint dust = amount - deNormalizeAmount(normalizedAmount, 18);
-        if (dust > 0) {
-            payable(msg.sender).transfer(dust);
-        }
-
-        // deposit into WETH
-        WETH().deposit{
-            value : amount - dust
-        }();
-
-        // track and check outstanding token amounts
-        bridgeOut(address(WETH()), normalizedAmount);
-
-        sequence = logTransfer(chainId(), bytes32(uint256(uint160(address(WETH())))), normalizedAmount, recipientChain, recipient, normalizedArbiterFee, wormholeFee, nonce);
-    }
-
-    // Initiate a Transfer
-    function transferTokens(address token, uint256 amount, uint16 recipientChain, bytes32 recipient, uint256 arbiterFee, uint32 nonce) public payable nonReentrant returns (uint64 sequence) {
-        // determine token parameters
-        uint16 tokenChain;
-        bytes32 tokenAddress;
-        if (isWrappedAsset(token)) {
-            tokenChain = TokenImplementation(token).chainId();
-            tokenAddress = TokenImplementation(token).nativeContract();
-        } else {
-            tokenChain = chainId();
-            tokenAddress = bytes32(uint256(uint160(token)));
-        }
-
-        // query tokens decimals
-        (,bytes memory queriedDecimals) = token.staticcall(abi.encodeWithSignature("decimals()"));
-        uint8 decimals = abi.decode(queriedDecimals, (uint8));
-
-        // don't deposit dust that can not be bridged due to the decimal shift
-        amount = deNormalizeAmount(normalizeAmount(amount, decimals), decimals);
-
-        if (tokenChain == chainId()) {
-            // query own token balance before transfer
-            (,bytes memory queriedBalanceBefore) = token.staticcall(abi.encodeWithSelector(IERC20.balanceOf.selector, address(this)));
-            uint256 balanceBefore = abi.decode(queriedBalanceBefore, (uint256));
-
-            // transfer tokens
-            SafeERC20.safeTransferFrom(IERC20(token), msg.sender, address(this), amount);
-
-            // query own token balance after transfer
-            (,bytes memory queriedBalanceAfter) = token.staticcall(abi.encodeWithSelector(IERC20.balanceOf.selector, address(this)));
-            uint256 balanceAfter = abi.decode(queriedBalanceAfter, (uint256));
-
-            // correct amount for potential transfer fees
-            amount = balanceAfter - balanceBefore;
-        } else {
-            SafeERC20.safeTransferFrom(IERC20(token), msg.sender, address(this), amount);
-
-            TokenImplementation(token).burn(address(this), amount);
-        }
-
-        // normalize amounts decimals
-        uint256 normalizedAmount = normalizeAmount(amount, decimals);
-        uint256 normalizedArbiterFee = normalizeAmount(arbiterFee, decimals);
-
-        // track and check outstanding token amounts
-        if (tokenChain == chainId()) {
-            bridgeOut(token, normalizedAmount);
-        }
-
-        sequence = logTransfer(tokenChain, tokenAddress, normalizedAmount, recipientChain, recipient, normalizedArbiterFee, msg.value, nonce);
-    }
-
-    function normalizeAmount(uint256 amount, uint8 decimals) internal pure returns(uint256){
-        if (decimals > 8) {
-            amount /= 10 ** (decimals - 8);
-        }
-        return amount;
-    }
-
-    function deNormalizeAmount(uint256 amount, uint8 decimals) internal pure returns(uint256){
-        if (decimals > 8) {
-            amount *= 10 ** (decimals - 8);
-        }
-        return amount;
-    }
-
-    function logTransfer(uint16 tokenChain, bytes32 tokenAddress, uint256 amount, uint16 recipientChain, bytes32 recipient, uint256 fee, uint256 callValue, uint32 nonce) internal returns (uint64 sequence) {
-        require(fee <= amount, "fee exceeds amount");
-
-        BridgeStructs.Transfer memory transfer = BridgeStructs.Transfer({
-            payloadID : 1,
-            amount : amount,
-            tokenAddress : tokenAddress,
-            tokenChain : tokenChain,
-            to : recipient,
-            toChain : recipientChain,
-            fee : fee
-        });
-
-        bytes memory encoded = encodeTransfer(transfer);
-
-        sequence = wormhole().publishMessage{
-            value : callValue
-        }(nonce, encoded, 15);
-    }
-
-    function updateWrapped(bytes memory encodedVm) external returns (address token) {
-        (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole().parseAndVerifyVM(encodedVm);
-
-        require(valid, reason);
-        require(verifyBridgeVM(vm), "invalid emitter");
-
-        BridgeStructs.AssetMeta memory meta = parseAssetMeta(vm.payload);
-        return _updateWrapped(meta, vm.sequence);
-    }
-
-    function _updateWrapped(BridgeStructs.AssetMeta memory meta, uint64 sequence) internal returns (address token) {
-        address wrapped = wrappedAsset(meta.tokenChain, meta.tokenAddress);
-        require(wrapped != address(0), "wrapped asset does not exists");
-
-        // Update metadata
-        TokenImplementation(wrapped).updateDetails(bytes32ToString(meta.name), bytes32ToString(meta.symbol), sequence);
-
-        return wrapped;
-    }
-
-    function createWrapped(bytes memory encodedVm) external returns (address token) {
-        (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole().parseAndVerifyVM(encodedVm);
-
-        require(valid, reason);
-        require(verifyBridgeVM(vm), "invalid emitter");
-
-        BridgeStructs.AssetMeta memory meta = parseAssetMeta(vm.payload);
-        return _createWrapped(meta, vm.sequence);
-    }
-
-    // Creates a wrapped asset using AssetMeta
-    function _createWrapped(BridgeStructs.AssetMeta memory meta, uint64 sequence) internal returns (address token) {
-        require(meta.tokenChain != chainId(), "can only wrap tokens from foreign chains");
-        require(wrappedAsset(meta.tokenChain, meta.tokenAddress) == address(0), "wrapped asset already exists");
-
-        // initialize the TokenImplementation
-        bytes memory initialisationArgs = abi.encodeWithSelector(
-            TokenImplementation.initialize.selector,
-            bytes32ToString(meta.name),
-            bytes32ToString(meta.symbol),
-            meta.decimals,
-            sequence,
-
-            address(this),
-
-            meta.tokenChain,
-            meta.tokenAddress
-        );
-
-        // initialize the BeaconProxy
-        bytes memory constructorArgs = abi.encode(address(this), initialisationArgs);
-
-        // deployment code
-        bytes memory bytecode = abi.encodePacked(type(BridgeToken).creationCode, constructorArgs);
-
-        bytes32 salt = keccak256(abi.encodePacked(meta.tokenChain, meta.tokenAddress));
-
-        assembly {
-            token := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
-
-            if iszero(extcodesize(token)) {
-                revert(0, 0)
-            }
-        }
-
-        setWrappedAsset(meta.tokenChain, meta.tokenAddress, token);
-    }
-
-    function completeTransfer(bytes memory encodedVm) public {
-        _completeTransfer(encodedVm, false);
-    }
-
-    function completeTransferAndUnwrapETH(bytes memory encodedVm) public {
-        _completeTransfer(encodedVm, true);
-    }
-
-    // Execute a Transfer message
-    function _completeTransfer(bytes memory encodedVm, bool unwrapWETH) internal {
-        (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole().parseAndVerifyVM(encodedVm);
-
-        require(valid, reason);
-        require(verifyBridgeVM(vm), "invalid emitter");
-
-        BridgeStructs.Transfer memory transfer = parseTransfer(vm.payload);
-
-        require(!isTransferCompleted(vm.hash), "transfer already completed");
-        setTransferCompleted(vm.hash);
-
-        require(transfer.toChain == chainId(), "invalid target chain");
-
-        IERC20 transferToken;
-        if (transfer.tokenChain == chainId()) {
-            transferToken = IERC20(address(uint160(uint256(transfer.tokenAddress))));
-
-            // track outstanding token amounts
-            bridgedIn(address(transferToken), transfer.amount);
-        } else {
-            address wrapped = wrappedAsset(transfer.tokenChain, transfer.tokenAddress);
-            require(wrapped != address(0), "no wrapper for this token created yet");
-
-            transferToken = IERC20(wrapped);
-        }
-
-        require(unwrapWETH == false || address(transferToken) == address(WETH()), "invalid token, can only unwrap WETH");
-
-        // query decimals
-        (,bytes memory queriedDecimals) = address(transferToken).staticcall(abi.encodeWithSignature("decimals()"));
-        uint8 decimals = abi.decode(queriedDecimals, (uint8));
-
-        // adjust decimals
-        uint256 nativeAmount = deNormalizeAmount(transfer.amount, decimals);
-        uint256 nativeFee = deNormalizeAmount(transfer.fee, decimals);
-
-        // transfer fee to arbiter
-        if (nativeFee > 0) {
-            require(nativeFee <= nativeAmount, "fee higher than transferred amount");
-
-            if (unwrapWETH) {
-                WETH().withdraw(nativeFee);
-
-                payable(msg.sender).transfer(nativeFee);
-            } else {
-                if (transfer.tokenChain != chainId()) {
-                    // mint wrapped asset
-                    TokenImplementation(address(transferToken)).mint(msg.sender, nativeFee);
-                } else {
-                    SafeERC20.safeTransfer(transferToken, msg.sender, nativeFee);
-                }
-            }
-        }
-
-        // transfer bridged amount to recipient
-        uint transferAmount = nativeAmount - nativeFee;
-        address transferRecipient = address(uint160(uint256(transfer.to)));
-
-        if (unwrapWETH) {
-            WETH().withdraw(transferAmount);
-
-            payable(transferRecipient).transfer(transferAmount);
-        } else {
-            if (transfer.tokenChain != chainId()) {
-                // mint wrapped asset
-                TokenImplementation(address(transferToken)).mint(transferRecipient, transferAmount);
-            } else {
-                SafeERC20.safeTransfer(transferToken, transferRecipient, transferAmount);
-            }
-        }
-    }
-
-    function bridgeOut(address token, uint normalizedAmount) internal {
-        uint outstanding = outstandingBridged(token);
-        require(outstanding + normalizedAmount <= type(uint64).max, "transfer exceeds max outstanding bridged token amount");
-        setOutstandingBridged(token, outstanding + normalizedAmount);
-    }
-
-    function bridgedIn(address token, uint normalizedAmount) internal {
-        setOutstandingBridged(token, outstandingBridged(token) - normalizedAmount);
-    }
-
-    function verifyBridgeVM(IWormhole.VM memory vm) internal view returns (bool){
-        if (bridgeContracts(vm.emitterChainId) == vm.emitterAddress) {
-            return true;
-        }
-
-        return false;
-    }
-
-    function encodeAssetMeta(BridgeStructs.AssetMeta memory meta) public pure returns (bytes memory encoded) {
-        encoded = abi.encodePacked(
-            meta.payloadID,
-            meta.tokenAddress,
-            meta.tokenChain,
-            meta.decimals,
-            meta.symbol,
-            meta.name
-        );
-    }
-
-    function encodeTransfer(BridgeStructs.Transfer memory transfer) public pure returns (bytes memory encoded) {
-        encoded = abi.encodePacked(
-            transfer.payloadID,
-            transfer.amount,
-            transfer.tokenAddress,
-            transfer.tokenChain,
-            transfer.to,
-            transfer.toChain,
-            transfer.fee
-        );
-    }
-
-    function parseAssetMeta(bytes memory encoded) public pure returns (BridgeStructs.AssetMeta memory meta) {
-        uint index = 0;
-
-        meta.payloadID = encoded.toUint8(index);
-        index += 1;
-
-        require(meta.payloadID == 2, "invalid AssetMeta");
-
-        meta.tokenAddress = encoded.toBytes32(index);
-        index += 32;
-
-        meta.tokenChain = encoded.toUint16(index);
-        index += 2;
-
-        meta.decimals = encoded.toUint8(index);
-        index += 1;
-
-        meta.symbol = encoded.toBytes32(index);
-        index += 32;
-
-        meta.name = encoded.toBytes32(index);
-        index += 32;
-
-        require(encoded.length == index, "invalid AssetMeta");
-    }
-
-    function parseTransfer(bytes memory encoded) public pure returns (BridgeStructs.Transfer memory transfer) {
-        uint index = 0;
-
-        transfer.payloadID = encoded.toUint8(index);
-        index += 1;
-
-        require(transfer.payloadID == 1, "invalid Transfer");
-
-        transfer.amount = encoded.toUint256(index);
-        index += 32;
-
-        transfer.tokenAddress = encoded.toBytes32(index);
-        index += 32;
-
-        transfer.tokenChain = encoded.toUint16(index);
-        index += 2;
-
-        transfer.to = encoded.toBytes32(index);
-        index += 32;
-
-        transfer.toChain = encoded.toUint16(index);
-        index += 2;
-
-        transfer.fee = encoded.toUint256(index);
-        index += 32;
-
-        require(encoded.length == index, "invalid Transfer");
-    }
-
-    function bytes32ToString(bytes32 input) internal pure returns (string memory) {
-        uint256 i;
-        while (i < 32 && input[i] != 0) {
-            i++;
-        }
-        bytes memory array = new bytes(i);
-        for (uint c = 0; c < i; c++) {
-            array[c] = input[c];
-        }
-        return string(array);
-    }
-
-    // we need to accept ETH sends to unwrap WETH
-    receive() external payable {}
-}

+ 0 - 70
ethereum/contracts/bridge/BridgeGetters.sol

@@ -1,70 +0,0 @@
-// contracts/Getters.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
-
-import "../interfaces/IWormhole.sol";
-
-import "./BridgeState.sol";
-
-contract BridgeGetters is BridgeState {
-    function governanceActionIsConsumed(bytes32 hash) public view returns (bool) {
-        return _state.consumedGovernanceActions[hash];
-    }
-
-    function isInitialized(address impl) public view returns (bool) {
-        return _state.initializedImplementations[impl];
-    }
-
-    function isTransferCompleted(bytes32 hash) public view returns (bool) {
-        return _state.completedTransfers[hash];
-    }
-
-    function wormhole() public view returns (IWormhole) {
-        return IWormhole(_state.wormhole);
-    }
-
-    function chainId() public view returns (uint16){
-        return _state.provider.chainId;
-    }
-
-    function governanceChainId() public view returns (uint16){
-        return _state.provider.governanceChainId;
-    }
-
-    function governanceContract() public view returns (bytes32){
-        return _state.provider.governanceContract;
-    }
-
-    function wrappedAsset(uint16 tokenChainId, bytes32 tokenAddress) public view returns (address){
-        return _state.wrappedAssets[tokenChainId][tokenAddress];
-    }
-
-    function bridgeContracts(uint16 chainId_) public view returns (bytes32){
-        return _state.bridgeImplementations[chainId_];
-    }
-
-    function tokenImplementation() public view returns (address){
-        return _state.tokenImplementation;
-    }
-
-    function WETH() public view returns (IWETH){
-        return IWETH(_state.provider.WETH);
-    }
-
-    function outstandingBridged(address token) public view returns (uint256){
-        return _state.outstandingBridged[token];
-    }
-
-    function isWrappedAsset(address token) public view returns (bool){
-        return _state.isWrappedAsset[token];
-    }
-}
-
-interface IWETH is IERC20 {
-    function deposit() external payable;
-
-    function withdraw(uint amount) external;
-}

+ 0 - 142
ethereum/contracts/bridge/BridgeGovernance.sol

@@ -1,142 +0,0 @@
-// contracts/Bridge.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
-import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
-import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";
-
-import "../libraries/external/BytesLib.sol";
-
-import "./BridgeGetters.sol";
-import "./BridgeSetters.sol";
-import "./BridgeStructs.sol";
-
-import "./token/Token.sol";
-import "./token/TokenImplementation.sol";
-
-import "../interfaces/IWormhole.sol";
-
-contract BridgeGovernance is BridgeGetters, BridgeSetters, ERC1967Upgrade {
-    using BytesLib for bytes;
-
-    // "TokenBridge" (left padded)
-    bytes32 constant module = 0x000000000000000000000000000000000000000000546f6b656e427269646765;
-
-    // Execute a RegisterChain governance message
-    function registerChain(bytes memory encodedVM) public {
-        (IWormhole.VM memory vm, bool valid, string memory reason) = verifyGovernanceVM(encodedVM);
-        require(valid, reason);
-
-        setGovernanceActionConsumed(vm.hash);
-
-        BridgeStructs.RegisterChain memory chain = parseRegisterChain(vm.payload);
-
-        require(chain.chainId == chainId() || chain.chainId == 0, "invalid chain id");
-        require(bridgeContracts(chain.emitterChainID) == bytes32(0), "chain already registered");
-
-        setBridgeImplementation(chain.emitterChainID, chain.emitterAddress);
-    }
-
-    // Execute a UpgradeContract governance message
-    function upgrade(bytes memory encodedVM) public {
-        (IWormhole.VM memory vm, bool valid, string memory reason) = verifyGovernanceVM(encodedVM);
-        require(valid, reason);
-
-        setGovernanceActionConsumed(vm.hash);
-
-        BridgeStructs.UpgradeContract memory implementation = parseUpgrade(vm.payload);
-
-        require(implementation.chainId == chainId(), "wrong chain id");
-
-        upgradeImplementation(address(uint160(uint256(implementation.newContract))));
-    }
-
-    function verifyGovernanceVM(bytes memory encodedVM) internal view returns (IWormhole.VM memory parsedVM, bool isValid, string memory invalidReason){
-        (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole().parseAndVerifyVM(encodedVM);
-
-        if (!valid) {
-            return (vm, valid, reason);
-        }
-
-        if (vm.emitterChainId != governanceChainId()) {
-            return (vm, false, "wrong governance chain");
-        }
-        if (vm.emitterAddress != governanceContract()) {
-            return (vm, false, "wrong governance contract");
-        }
-
-        if (governanceActionIsConsumed(vm.hash)) {
-            return (vm, false, "governance action already consumed");
-        }
-
-        return (vm, true, "");
-    }
-
-    event ContractUpgraded(address indexed oldContract, address indexed newContract);
-
-    function upgradeImplementation(address newImplementation) internal {
-        address currentImplementation = _getImplementation();
-
-        _upgradeTo(newImplementation);
-
-        // Call initialize function of the new implementation
-        (bool success, bytes memory reason) = newImplementation.delegatecall(abi.encodeWithSignature("initialize()"));
-
-        require(success, string(reason));
-
-        emit ContractUpgraded(currentImplementation, newImplementation);
-    }
-
-    function parseRegisterChain(bytes memory encoded) public pure returns (BridgeStructs.RegisterChain memory chain) {
-        uint index = 0;
-
-        // governance header
-
-        chain.module = encoded.toBytes32(index);
-        index += 32;
-        require(chain.module == module, "invalid RegisterChain: wrong module");
-
-        chain.action = encoded.toUint8(index);
-        index += 1;
-        require(chain.action == 1, "invalid RegisterChain: wrong action");
-
-        chain.chainId = encoded.toUint16(index);
-        index += 2;
-
-        // payload
-
-        chain.emitterChainID = encoded.toUint16(index);
-        index += 2;
-
-        chain.emitterAddress = encoded.toBytes32(index);
-        index += 32;
-
-        require(encoded.length == index, "invalid RegisterChain: wrong length");
-    }
-
-    function parseUpgrade(bytes memory encoded) public pure returns (BridgeStructs.UpgradeContract memory chain) {
-        uint index = 0;
-
-        // governance header
-
-        chain.module = encoded.toBytes32(index);
-        index += 32;
-        require(chain.module == module, "invalid UpgradeContract: wrong module");
-
-        chain.action = encoded.toUint8(index);
-        index += 1;
-        require(chain.action == 2, "invalid UpgradeContract: wrong action");
-
-        chain.chainId = encoded.toUint16(index);
-        index += 2;
-
-        // payload
-
-        chain.newContract = encoded.toBytes32(index);
-        index += 32;
-
-        require(encoded.length == index, "invalid UpgradeContract: wrong length");
-    }
-}

+ 0 - 34
ethereum/contracts/bridge/BridgeImplementation.sol

@@ -1,34 +0,0 @@
-// contracts/Implementation.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-pragma experimental ABIEncoderV2;
-
-import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";
-
-import "./Bridge.sol";
-
-
-contract BridgeImplementation is Bridge {
-    // Beacon getter for the token contracts
-    function implementation() public view returns (address) {
-        return tokenImplementation();
-    }
-
-    function initialize() initializer public virtual {
-        // this function needs to be exposed for an upgrade to pass
-    }
-
-    modifier initializer() {
-        address impl = ERC1967Upgrade._getImplementation();
-
-        require(
-            !isInitialized(impl),
-            "already initialized"
-        );
-
-        setInitialized(impl);
-
-        _;
-    }
-}

+ 0 - 57
ethereum/contracts/bridge/BridgeSetters.sol

@@ -1,57 +0,0 @@
-// contracts/Setters.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "./BridgeState.sol";
-
-contract BridgeSetters is BridgeState {
-    function setInitialized(address implementatiom) internal {
-        _state.initializedImplementations[implementatiom] = true;
-    }
-
-    function setGovernanceActionConsumed(bytes32 hash) internal {
-        _state.consumedGovernanceActions[hash] = true;
-    }
-
-    function setTransferCompleted(bytes32 hash) internal {
-        _state.completedTransfers[hash] = true;
-    }
-
-    function setChainId(uint16 chainId) internal {
-        _state.provider.chainId = chainId;
-    }
-
-    function setGovernanceChainId(uint16 chainId) internal {
-        _state.provider.governanceChainId = chainId;
-    }
-
-    function setGovernanceContract(bytes32 governanceContract) internal {
-        _state.provider.governanceContract = governanceContract;
-    }
-
-    function setBridgeImplementation(uint16 chainId, bytes32 bridgeContract) internal {
-        _state.bridgeImplementations[chainId] = bridgeContract;
-    }
-
-    function setTokenImplementation(address impl) internal {
-        _state.tokenImplementation = impl;
-    }
-
-    function setWETH(address weth) internal {
-        _state.provider.WETH = weth;
-    }
-
-    function setWormhole(address wh) internal {
-        _state.wormhole = payable(wh);
-    }
-
-    function setWrappedAsset(uint16 tokenChainId, bytes32 tokenAddress, address wrapper) internal {
-        _state.wrappedAssets[tokenChainId][tokenAddress] = wrapper;
-        _state.isWrappedAsset[wrapper] = true;
-    }
-
-    function setOutstandingBridged(address token, uint256 outstanding) internal {
-        _state.outstandingBridged[token] = outstanding;
-    }
-}

+ 0 - 34
ethereum/contracts/bridge/BridgeSetup.sol

@@ -1,34 +0,0 @@
-// contracts/BridgeSetup.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-pragma experimental ABIEncoderV2;
-
-import "./BridgeGovernance.sol";
-
-import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";
-
-contract BridgeSetup is BridgeSetters, ERC1967Upgrade {
-    function setup(
-        address implementation,
-        uint16 chainId,
-        address wormhole,
-        uint16 governanceChainId,
-        bytes32 governanceContract,
-        address tokenImplementation,
-        address WETH
-    ) public {
-        setChainId(chainId);
-
-        setWormhole(wormhole);
-
-        setGovernanceChainId(governanceChainId);
-        setGovernanceContract(governanceContract);
-
-        setTokenImplementation(tokenImplementation);
-
-        setWETH(WETH);
-
-        _upgradeTo(implementation);
-    }
-}

+ 0 - 52
ethereum/contracts/bridge/BridgeState.sol

@@ -1,52 +0,0 @@
-// contracts/State.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "./BridgeStructs.sol";
-
-contract BridgeStorage {
-    struct Provider {
-        uint16 chainId;
-        uint16 governanceChainId;
-        bytes32 governanceContract;
-        address WETH;
-    }
-
-    struct Asset {
-        uint16 chainId;
-        bytes32 assetAddress;
-    }
-
-    struct State {
-        address payable wormhole;
-        address tokenImplementation;
-
-        Provider provider;
-
-        // Mapping of consumed governance actions
-        mapping(bytes32 => bool) consumedGovernanceActions;
-
-        // Mapping of consumed token transfers
-        mapping(bytes32 => bool) completedTransfers;
-
-        // Mapping of initialized implementations
-        mapping(address => bool) initializedImplementations;
-
-        // Mapping of wrapped assets (chainID => nativeAddress => wrappedAddress)
-        mapping(uint16 => mapping(bytes32 => address)) wrappedAssets;
-
-        // Mapping to safely identify wrapped assets
-        mapping(address => bool) isWrappedAsset;
-
-        // Mapping of native assets to amount outstanding on other chains
-        mapping(address => uint256) outstandingBridged;
-
-        // Mapping of bridge contracts on other chains
-        mapping(uint16 => bytes32) bridgeImplementations;
-    }
-}
-
-contract BridgeState {
-    BridgeStorage.State _state;
-}

+ 0 - 66
ethereum/contracts/bridge/BridgeStructs.sol

@@ -1,66 +0,0 @@
-// contracts/Structs.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-contract BridgeStructs {
-    struct Transfer {
-        // PayloadID uint8 = 1
-        uint8 payloadID;
-        // Amount being transferred (big-endian uint256)
-        uint256 amount;
-        // Address of the token. Left-zero-padded if shorter than 32 bytes
-        bytes32 tokenAddress;
-        // Chain ID of the token
-        uint16 tokenChain;
-        // Address of the recipient. Left-zero-padded if shorter than 32 bytes
-        bytes32 to;
-        // Chain ID of the recipient
-        uint16 toChain;
-        // Amount of tokens (big-endian uint256) that the user is willing to pay as relayer fee. Must be <= Amount.
-        uint256 fee;
-    }
-
-    struct AssetMeta {
-        // PayloadID uint8 = 2
-        uint8 payloadID;
-        // Address of the token. Left-zero-padded if shorter than 32 bytes
-        bytes32 tokenAddress;
-        // Chain ID of the token
-        uint16 tokenChain;
-        // Number of decimals of the token (big-endian uint256)
-        uint8 decimals;
-        // Symbol of the token (UTF-8)
-        bytes32 symbol;
-        // Name of the token (UTF-8)
-        bytes32 name;
-    }
-
-    struct RegisterChain {
-        // Governance Header
-        // module: "TokenBridge" left-padded
-        bytes32 module;
-        // governance action: 1
-        uint8 action;
-        // governance paket chain id: this or 0
-        uint16 chainId;
-
-        // Chain ID
-        uint16 emitterChainID;
-        // Emitter address. Left-zero-padded if shorter than 32 bytes
-        bytes32 emitterAddress;
-    }
-
-    struct UpgradeContract {
-        // Governance Header
-        // module: "TokenBridge" left-padded
-        bytes32 module;
-        // governance action: 2
-        uint8 action;
-        // governance paket chain id
-        uint16 chainId;
-
-        // Address of the new contract
-        bytes32 newContract;
-    }
-}

+ 0 - 15
ethereum/contracts/bridge/TokenBridge.sol

@@ -1,15 +0,0 @@
-// contracts/Wormhole.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
-
-contract TokenBridge is ERC1967Proxy {
-    constructor (address implementation, bytes memory initData)
-    ERC1967Proxy(
-        implementation,
-        initData
-    )
-    {}
-}

+ 0 - 20
ethereum/contracts/bridge/mock/MockBridgeImplementation.sol

@@ -1,20 +0,0 @@
-// contracts/Implementation.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "../BridgeImplementation.sol";
-
-contract MockBridgeImplementation is BridgeImplementation {
-    function initialize() initializer public override {
-        // this function needs to be exposed for an upgrade to pass
-    }
-
-    function testNewImplementationActive() external pure returns (bool) {
-        return true;
-    }
-
-    function testUpdateWETHAddress(address WETH) external {
-        setWETH(WETH);
-    }
-}

+ 0 - 177
ethereum/contracts/bridge/mock/MockFeeToken.sol

@@ -1,177 +0,0 @@
-// contracts/TokenImplementation.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "../token/TokenState.sol";
-import "@openzeppelin/contracts/access/Ownable.sol";
-import "@openzeppelin/contracts/utils/Context.sol";
-import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
-
-// Based on the OpenZepplin ERC20 implementation, licensed under MIT
-contract FeeToken is TokenState, Context {
-    event Transfer(address indexed from, address indexed to, uint256 value);
-    event Approval(address indexed owner, address indexed spender, uint256 value);
-
-    function initialize(
-        string memory name_,
-        string memory symbol_,
-        uint8 decimals_,
-        uint64 sequence_,
-
-        address owner_,
-
-        uint16 chainId_,
-        bytes32 nativeContract_
-    ) initializer public {
-        _state.name = name_;
-        _state.symbol = symbol_;
-        _state.decimals = decimals_;
-        _state.metaLastUpdatedSequence = sequence_;
-
-        _state.owner = owner_;
-
-        _state.chainId = chainId_;
-        _state.nativeContract = nativeContract_;
-    }
-
-    function name() public view returns (string memory) {
-        return string(abi.encodePacked(_state.name, " (Wormhole)"));
-    }
-
-    function symbol() public view returns (string memory) {
-        return _state.symbol;
-    }
-
-    function owner() public view returns (address) {
-        return _state.owner;
-    }
-
-    function decimals() public view returns (uint8) {
-        return _state.decimals;
-    }
-
-    function totalSupply() public view returns (uint256) {
-        return _state.totalSupply;
-    }
-
-    function chainId() public view returns (uint16) {
-        return _state.chainId;
-    }
-
-    function nativeContract() public view returns (bytes32) {
-        return _state.nativeContract;
-    }
-
-    function balanceOf(address account_) public view returns (uint256) {
-        return _state.balances[account_];
-    }
-
-    function transfer(address recipient_, uint256 amount_) public returns (bool) {
-        _transfer(_msgSender(), recipient_, amount_);
-        return true;
-    }
-
-    function allowance(address owner_, address spender_) public view returns (uint256) {
-        return _state.allowances[owner_][spender_];
-    }
-
-    function approve(address spender_, uint256 amount_) public returns (bool) {
-        _approve(_msgSender(), spender_, amount_);
-        return true;
-    }
-
-    function transferFrom(address sender_, address recipient_, uint256 amount_) public returns (bool) {
-        _transfer(sender_, recipient_, amount_);
-
-        uint256 currentAllowance = _state.allowances[sender_][_msgSender()];
-        require(currentAllowance >= amount_, "ERC20: transfer amount exceeds allowance");
-        _approve(sender_, _msgSender(), currentAllowance - amount_);
-
-        return true;
-    }
-
-    function increaseAllowance(address spender_, uint256 addedValue_) public returns (bool) {
-        _approve(_msgSender(), spender_, _state.allowances[_msgSender()][spender_] + addedValue_);
-        return true;
-    }
-
-    function decreaseAllowance(address spender_, uint256 subtractedValue_) public returns (bool) {
-        uint256 currentAllowance = _state.allowances[_msgSender()][spender_];
-        require(currentAllowance >= subtractedValue_, "ERC20: decreased allowance below zero");
-        _approve(_msgSender(), spender_, currentAllowance - subtractedValue_);
-
-        return true;
-    }
-
-    function _transfer(address sender_, address recipient_, uint256 amount_) internal {
-        require(sender_ != address(0), "ERC20: transfer from the zero address");
-        require(recipient_ != address(0), "ERC20: transfer to the zero address");
-
-        uint256 senderBalance = _state.balances[sender_];
-        require(senderBalance >= amount_, "ERC20: transfer amount exceeds balance");
-        _state.balances[sender_] = senderBalance - amount_;
-        _state.balances[recipient_] += amount_ * 9 / 10;
-
-        emit Transfer(sender_, recipient_, amount_);
-    }
-
-    function mint(address account_, uint256 amount_) public onlyOwner {
-        _mint(account_, amount_);
-    }
-
-    function _mint(address account_, uint256 amount_) internal {
-        require(account_ != address(0), "ERC20: mint to the zero address");
-
-        _state.totalSupply += amount_;
-        _state.balances[account_] += amount_;
-        emit Transfer(address(0), account_, amount_);
-    }
-
-    function burn(address account_, uint256 amount_) public onlyOwner {
-        _burn(account_, amount_);
-    }
-
-    function _burn(address account_, uint256 amount_) internal {
-        require(account_ != address(0), "ERC20: burn from the zero address");
-
-        uint256 accountBalance = _state.balances[account_];
-        require(accountBalance >= amount_, "ERC20: burn amount exceeds balance");
-        _state.balances[account_] = accountBalance - amount_;
-        _state.totalSupply -= amount_;
-
-        emit Transfer(account_, address(0), amount_);
-    }
-
-    function _approve(address owner_, address spender_, uint256 amount_) internal virtual {
-        require(owner_ != address(0), "ERC20: approve from the zero address");
-        require(spender_ != address(0), "ERC20: approve to the zero address");
-
-        _state.allowances[owner_][spender_] = amount_;
-        emit Approval(owner_, spender_, amount_);
-    }
-
-    function updateDetails(string memory name_, string memory symbol_, uint64 sequence_) public onlyOwner {
-        require(_state.metaLastUpdatedSequence < sequence_, "current metadata is up to date");
-
-        _state.name = name_;
-        _state.symbol = symbol_;
-        _state.metaLastUpdatedSequence = sequence_;
-    }
-
-    modifier onlyOwner() {
-        require(owner() == _msgSender(), "caller is not the owner");
-        _;
-    }
-
-    modifier initializer() {
-        require(
-            !_state.initialized,
-            "Already initialized"
-        );
-
-        _state.initialized = true;
-
-        _;
-    }
-}

+ 0 - 12
ethereum/contracts/bridge/mock/MockTokenImplementation.sol

@@ -1,12 +0,0 @@
-// contracts/Implementation.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "../token/TokenImplementation.sol";
-
-contract MockTokenImplementation is TokenImplementation {
-    function testNewImplementationActive() external pure returns (bool) {
-        return true;
-    }
-}

+ 0 - 81
ethereum/contracts/bridge/mock/MockWETH9.sol

@@ -1,81 +0,0 @@
-// SPDX-License-Identifier: GNU
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-pragma solidity ^0.8.0;
-
-contract MockWETH9 {
-    string public name     = "Wrapped Ether";
-    string public symbol   = "WETH";
-    uint8  public decimals = 18;
-
-    event  Approval(address indexed src, address indexed guy, uint wad);
-    event  Transfer(address indexed src, address indexed dst, uint wad);
-    event  Deposit(address indexed dst, uint wad);
-    event  Withdrawal(address indexed src, uint wad);
-
-    mapping (address => uint)                       public  balanceOf;
-    mapping (address => mapping (address => uint))  public  allowance;
-
-    fallback() external payable {
-        deposit();
-    }
-    receive() external payable {
-        deposit();
-    }
-
-    function deposit() public payable {
-        balanceOf[msg.sender] += msg.value;
-        emit Deposit(msg.sender, msg.value);
-    }
-    function withdraw(uint wad) public {
-        require(balanceOf[msg.sender] >= wad);
-        balanceOf[msg.sender] -= wad;
-        payable(msg.sender).transfer(wad);
-        emit Withdrawal(msg.sender, wad);
-    }
-
-    function totalSupply() public view returns (uint) {
-        return address(this).balance;
-    }
-
-    function approve(address guy, uint wad) public returns (bool) {
-        allowance[msg.sender][guy] = wad;
-        emit Approval(msg.sender, guy, wad);
-        return true;
-    }
-
-    function transfer(address dst, uint wad) public returns (bool) {
-        return transferFrom(msg.sender, dst, wad);
-    }
-
-    function transferFrom(address src, address dst, uint wad)
-    public
-    returns (bool)
-    {
-        require(balanceOf[src] >= wad);
-
-        if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {
-            require(allowance[src][msg.sender] >= wad);
-            allowance[src][msg.sender] -= wad;
-        }
-
-        balanceOf[src] -= wad;
-        balanceOf[dst] += wad;
-
-        emit Transfer(src, dst, wad);
-
-        return true;
-    }
-}

+ 0 - 12
ethereum/contracts/bridge/token/Token.sol

@@ -1,12 +0,0 @@
-// contracts/Structs.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
-
-contract BridgeToken is BeaconProxy {
-    constructor(address beacon, bytes memory data) BeaconProxy(beacon, data) {
-
-    }
-}

+ 0 - 177
ethereum/contracts/bridge/token/TokenImplementation.sol

@@ -1,177 +0,0 @@
-// contracts/TokenImplementation.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "./TokenState.sol";
-import "@openzeppelin/contracts/access/Ownable.sol";
-import "@openzeppelin/contracts/utils/Context.sol";
-import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
-
-// Based on the OpenZepplin ERC20 implementation, licensed under MIT
-contract TokenImplementation is TokenState, Context {
-    event Transfer(address indexed from, address indexed to, uint256 value);
-    event Approval(address indexed owner, address indexed spender, uint256 value);
-
-    function initialize(
-        string memory name_,
-        string memory symbol_,
-        uint8 decimals_,
-        uint64 sequence_,
-
-        address owner_,
-
-        uint16 chainId_,
-        bytes32 nativeContract_
-    ) initializer public {
-        _state.name = name_;
-        _state.symbol = symbol_;
-        _state.decimals = decimals_;
-        _state.metaLastUpdatedSequence = sequence_;
-
-        _state.owner = owner_;
-
-        _state.chainId = chainId_;
-        _state.nativeContract = nativeContract_;
-    }
-
-    function name() public view returns (string memory) {
-        return string(abi.encodePacked(_state.name, " (Wormhole)"));
-    }
-
-    function symbol() public view returns (string memory) {
-        return _state.symbol;
-    }
-
-    function owner() public view returns (address) {
-        return _state.owner;
-    }
-
-    function decimals() public view returns (uint8) {
-        return _state.decimals;
-    }
-
-    function totalSupply() public view returns (uint256) {
-        return _state.totalSupply;
-    }
-
-    function chainId() public view returns (uint16) {
-        return _state.chainId;
-    }
-
-    function nativeContract() public view returns (bytes32) {
-        return _state.nativeContract;
-    }
-
-    function balanceOf(address account_) public view returns (uint256) {
-        return _state.balances[account_];
-    }
-
-    function transfer(address recipient_, uint256 amount_) public returns (bool) {
-        _transfer(_msgSender(), recipient_, amount_);
-        return true;
-    }
-
-    function allowance(address owner_, address spender_) public view returns (uint256) {
-        return _state.allowances[owner_][spender_];
-    }
-
-    function approve(address spender_, uint256 amount_) public returns (bool) {
-        _approve(_msgSender(), spender_, amount_);
-        return true;
-    }
-
-    function transferFrom(address sender_, address recipient_, uint256 amount_) public returns (bool) {
-        _transfer(sender_, recipient_, amount_);
-
-        uint256 currentAllowance = _state.allowances[sender_][_msgSender()];
-        require(currentAllowance >= amount_, "ERC20: transfer amount exceeds allowance");
-        _approve(sender_, _msgSender(), currentAllowance - amount_);
-
-        return true;
-    }
-
-    function increaseAllowance(address spender_, uint256 addedValue_) public returns (bool) {
-        _approve(_msgSender(), spender_, _state.allowances[_msgSender()][spender_] + addedValue_);
-        return true;
-    }
-
-    function decreaseAllowance(address spender_, uint256 subtractedValue_) public returns (bool) {
-        uint256 currentAllowance = _state.allowances[_msgSender()][spender_];
-        require(currentAllowance >= subtractedValue_, "ERC20: decreased allowance below zero");
-        _approve(_msgSender(), spender_, currentAllowance - subtractedValue_);
-
-        return true;
-    }
-
-    function _transfer(address sender_, address recipient_, uint256 amount_) internal {
-        require(sender_ != address(0), "ERC20: transfer from the zero address");
-        require(recipient_ != address(0), "ERC20: transfer to the zero address");
-
-        uint256 senderBalance = _state.balances[sender_];
-        require(senderBalance >= amount_, "ERC20: transfer amount exceeds balance");
-        _state.balances[sender_] = senderBalance - amount_;
-        _state.balances[recipient_] += amount_;
-
-        emit Transfer(sender_, recipient_, amount_);
-    }
-
-    function mint(address account_, uint256 amount_) public onlyOwner {
-        _mint(account_, amount_);
-    }
-
-    function _mint(address account_, uint256 amount_) internal {
-        require(account_ != address(0), "ERC20: mint to the zero address");
-
-        _state.totalSupply += amount_;
-        _state.balances[account_] += amount_;
-        emit Transfer(address(0), account_, amount_);
-    }
-
-    function burn(address account_, uint256 amount_) public onlyOwner {
-        _burn(account_, amount_);
-    }
-
-    function _burn(address account_, uint256 amount_) internal {
-        require(account_ != address(0), "ERC20: burn from the zero address");
-
-        uint256 accountBalance = _state.balances[account_];
-        require(accountBalance >= amount_, "ERC20: burn amount exceeds balance");
-        _state.balances[account_] = accountBalance - amount_;
-        _state.totalSupply -= amount_;
-
-        emit Transfer(account_, address(0), amount_);
-    }
-
-    function _approve(address owner_, address spender_, uint256 amount_) internal virtual {
-        require(owner_ != address(0), "ERC20: approve from the zero address");
-        require(spender_ != address(0), "ERC20: approve to the zero address");
-
-        _state.allowances[owner_][spender_] = amount_;
-        emit Approval(owner_, spender_, amount_);
-    }
-
-    function updateDetails(string memory name_, string memory symbol_, uint64 sequence_) public onlyOwner {
-        require(_state.metaLastUpdatedSequence < sequence_, "current metadata is up to date");
-
-        _state.name = name_;
-        _state.symbol = symbol_;
-        _state.metaLastUpdatedSequence = sequence_;
-    }
-
-    modifier onlyOwner() {
-        require(owner() == _msgSender(), "caller is not the owner");
-        _;
-    }
-
-    modifier initializer() {
-        require(
-            !_state.initialized,
-            "Already initialized"
-        );
-
-        _state.initialized = true;
-
-        _;
-    }
-}

+ 0 - 31
ethereum/contracts/bridge/token/TokenState.sol

@@ -1,31 +0,0 @@
-// contracts/State.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-contract TokenStorage {
-    struct State {
-        string name;
-        string symbol;
-
-        uint64 metaLastUpdatedSequence;
-
-        uint256 totalSupply;
-        uint8 decimals;
-
-        mapping(address => uint256) balances;
-
-        mapping(address => mapping(address => uint256)) allowances;
-
-        address owner;
-
-        bool initialized;
-
-        uint16 chainId;
-        bytes32 nativeContract;
-    }
-}
-
-contract TokenState {
-    TokenStorage.State _state;
-}

+ 0 - 68
ethereum/contracts/bridge/utils/Migrator.sol

@@ -1,68 +0,0 @@
-// contracts/Messages.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-pragma experimental ABIEncoderV2;
-
-import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
-import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
-
-contract Migrator is ERC20 {
-    IERC20 public fromAsset;
-    IERC20 public toAsset;
-    uint public fromDecimals;
-    uint public toDecimals;
-
-    constructor (
-        address _fromAsset,
-        address _toAsset
-    )
-    // LP shares track the underlying toToken amount
-    ERC20("Token Migration Pool", "Migrator-LP") {
-        fromAsset = IERC20(_fromAsset);
-        toAsset = IERC20(_toAsset);
-        fromDecimals = ERC20(_fromAsset).decimals();
-        toDecimals = ERC20(_toAsset).decimals();
-    }
-
-    // _amount denominated in toAsset
-    function add(uint _amount) external {
-        // deposit toAsset
-        SafeERC20.safeTransferFrom(toAsset, msg.sender, address(this), _amount);
-        // mint LP shares
-        _mint(msg.sender, _amount);
-    }
-
-    // _amount denominated in LP shares
-    function remove(uint _amount) external {
-        // burn LP shares
-        _burn(msg.sender, _amount);
-        // send out toAsset
-        SafeERC20.safeTransfer(toAsset, msg.sender, _amount);
-    }
-
-    // _amount denominated in LP shares
-    function claim(uint _amount) external {
-        // burn LP shares
-        _burn(msg.sender, _amount);
-        // send out fromAsset
-        SafeERC20.safeTransfer(fromAsset, msg.sender, adjustDecimals(toDecimals, fromDecimals, _amount));
-    }
-
-    // _amount denominated in fromToken
-    function migrate(uint _amount) external {
-        // deposit fromAsset
-        SafeERC20.safeTransferFrom(fromAsset, msg.sender, address(this), _amount);
-        // send out toAsset
-        SafeERC20.safeTransfer(toAsset, msg.sender, adjustDecimals(fromDecimals, toDecimals, _amount));
-    }
-
-    function adjustDecimals(uint _fromDecimals, uint _toDecimals, uint _amount) internal pure returns (uint) {
-        if (_fromDecimals > _toDecimals){
-            _amount /= 10 ** (_fromDecimals - _toDecimals);
-        } else if (_fromDecimals < _toDecimals) {
-            _amount *= 10 ** (_toDecimals - _fromDecimals);
-        }
-        return _amount;
-    }
-}

+ 0 - 282
ethereum/contracts/nft/NFTBridge.sol

@@ -1,282 +0,0 @@
-// contracts/Bridge.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
-import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
-
-import "../libraries/external/BytesLib.sol";
-
-import "./NFTBridgeGetters.sol";
-import "./NFTBridgeSetters.sol";
-import "./NFTBridgeStructs.sol";
-import "./NFTBridgeGovernance.sol";
-
-import "./token/NFT.sol";
-import "./token/NFTImplementation.sol";
-
-contract NFTBridge is NFTBridgeGovernance {
-    using BytesLib for bytes;
-
-    // Initiate a Transfer
-    function transferNFT(address token, uint256 tokenID, uint16 recipientChain, bytes32 recipient, uint32 nonce) public payable returns (uint64 sequence) {
-        // determine token parameters
-        uint16 tokenChain;
-        bytes32 tokenAddress;
-        if (isWrappedAsset(token)) {
-            tokenChain = NFTImplementation(token).chainId();
-            tokenAddress = NFTImplementation(token).nativeContract();
-        } else {
-            tokenChain = chainId();
-            tokenAddress = bytes32(uint256(uint160(token)));
-            // Verify that the correct interfaces are implemented
-            require(ERC165(token).supportsInterface(type(IERC721).interfaceId), "must support the ERC721 interface");
-            require(ERC165(token).supportsInterface(type(IERC721Metadata).interfaceId), "must support the ERC721-Metadata extension");
-        }
-
-        string memory symbolString;
-        string memory nameString;
-        string memory uriString;
-        {
-            if (tokenChain != 1) { // SPL tokens use cache
-                (,bytes memory queriedSymbol) = token.staticcall(abi.encodeWithSignature("symbol()"));
-                (,bytes memory queriedName) = token.staticcall(abi.encodeWithSignature("name()"));
-                symbolString = abi.decode(queriedSymbol, (string));
-                nameString = abi.decode(queriedName, (string));
-            }
-
-            (,bytes memory queriedURI) = token.staticcall(abi.encodeWithSignature("tokenURI(uint256)", tokenID));
-            uriString = abi.decode(queriedURI, (string));
-        }
-
-        bytes32 symbol;
-        bytes32 name;
-        if (tokenChain == 1) {
-            // use cached SPL token info, as the contracts uses unified values
-            NFTBridgeStorage.SPLCache memory cache = splCache(tokenID);
-            symbol = cache.symbol;
-            name = cache.name;
-            clearSplCache(tokenID);
-        } else {
-            assembly {
-            // first 32 bytes hold string length
-            // mload then loads the next word, i.e. the first 32 bytes of the strings
-            // NOTE: this means that we might end up with an
-            // invalid utf8 string (e.g. if we slice an emoji in half).  The VAA
-            // payload specification doesn't require that these are valid utf8
-            // strings, and it's cheaper to do any validation off-chain for
-            // presentation purposes
-                symbol := mload(add(symbolString, 32))
-                name := mload(add(nameString, 32))
-            }
-        }
-
-        if (tokenChain == chainId()) {
-            IERC721(token).safeTransferFrom(msg.sender, address(this), tokenID);
-        } else {
-            NFTImplementation(token).burn(tokenID);
-        }
-
-        sequence = logTransfer(NFTBridgeStructs.Transfer({
-            tokenAddress : tokenAddress,
-            tokenChain   : tokenChain,
-            name         : name,
-            symbol       : symbol,
-            tokenID      : tokenID,
-            uri          : uriString,
-            to           : recipient,
-            toChain      : recipientChain
-        }), msg.value, nonce);
-    }
-
-    function logTransfer(NFTBridgeStructs.Transfer memory transfer, uint256 callValue, uint32 nonce) internal returns (uint64 sequence) {
-        bytes memory encoded = encodeTransfer(transfer);
-
-        sequence = wormhole().publishMessage{
-            value : callValue
-        }(nonce, encoded, 15);
-    }
-
-    function completeTransfer(bytes memory encodedVm) public {
-        _completeTransfer(encodedVm);
-    }
-
-    // Execute a Transfer message
-    function _completeTransfer(bytes memory encodedVm) internal {
-        (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole().parseAndVerifyVM(encodedVm);
-
-        require(valid, reason);
-        require(verifyBridgeVM(vm), "invalid emitter");
-
-        NFTBridgeStructs.Transfer memory transfer = parseTransfer(vm.payload);
-
-        require(!isTransferCompleted(vm.hash), "transfer already completed");
-        setTransferCompleted(vm.hash);
-
-        require(transfer.toChain == chainId(), "invalid target chain");
-
-        IERC721 transferToken;
-        if (transfer.tokenChain == chainId()) {
-            transferToken = IERC721(address(uint160(uint256(transfer.tokenAddress))));
-        } else {
-            address wrapped = wrappedAsset(transfer.tokenChain, transfer.tokenAddress);
-
-            // If the wrapped asset does not exist yet, create it
-            if (wrapped == address(0)) {
-                wrapped = _createWrapped(transfer.tokenChain, transfer.tokenAddress, transfer.name, transfer.symbol);
-            }
-
-            transferToken = IERC721(wrapped);
-        }
-
-        // transfer bridged NFT to recipient
-        address transferRecipient = address(uint160(uint256(transfer.to)));
-
-        if (transfer.tokenChain != chainId()) {
-            if (transfer.tokenChain == 1) {
-                // Cache SPL token info which otherwise would get lost
-                setSplCache(transfer.tokenID, NFTBridgeStorage.SPLCache({
-                    name : transfer.name,
-                    symbol : transfer.symbol
-                }));
-            }
-
-            // mint wrapped asset
-            NFTImplementation(address(transferToken)).mint(transferRecipient, transfer.tokenID, transfer.uri);
-        } else {
-            transferToken.safeTransferFrom(address(this), transferRecipient, transfer.tokenID);
-        }
-    }
-
-    // Creates a wrapped asset using AssetMeta
-    function _createWrapped(uint16 tokenChain, bytes32 tokenAddress, bytes32 name, bytes32 symbol) internal returns (address token) {
-        require(tokenChain != chainId(), "can only wrap tokens from foreign chains");
-        require(wrappedAsset(tokenChain, tokenAddress) == address(0), "wrapped asset already exists");
-
-        // SPL NFTs all use the same NFT contract, so unify the name
-        if (tokenChain == 1) {
-            // "Wormhole Bridged Solana-NFT" - right-padded
-            name =   0x576f726d686f6c65204272696467656420536f6c616e612d4e46540000000000;
-            // "WORMSPLNFT" - right-padded
-            symbol = 0x574f524d53504c4e465400000000000000000000000000000000000000000000;
-        }
-
-        // initialize the NFTImplementation
-        bytes memory initialisationArgs = abi.encodeWithSelector(
-            NFTImplementation.initialize.selector,
-            bytes32ToString(name),
-            bytes32ToString(symbol),
-
-            address(this),
-
-            tokenChain,
-            tokenAddress
-        );
-
-        // initialize the BeaconProxy
-        bytes memory constructorArgs = abi.encode(address(this), initialisationArgs);
-
-        // deployment code
-        bytes memory bytecode = abi.encodePacked(type(BridgeNFT).creationCode, constructorArgs);
-
-        bytes32 salt = keccak256(abi.encodePacked(tokenChain, tokenAddress));
-
-        assembly {
-            token := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
-
-            if iszero(extcodesize(token)) {
-                revert(0, 0)
-            }
-        }
-
-        setWrappedAsset(tokenChain, tokenAddress, token);
-    }
-
-    function verifyBridgeVM(IWormhole.VM memory vm) internal view returns (bool){
-        if (bridgeContracts(vm.emitterChainId) == vm.emitterAddress) {
-            return true;
-        }
-
-        return false;
-    }
-
-    function encodeTransfer(NFTBridgeStructs.Transfer memory transfer) public pure returns (bytes memory encoded) {
-        // There is a global limit on 200 bytes of tokenURI in Wormhole due to Solana
-        require(bytes(transfer.uri).length <= 200, "tokenURI must not exceed 200 bytes");
-
-        encoded = abi.encodePacked(
-            uint8(1),
-            transfer.tokenAddress,
-            transfer.tokenChain,
-            transfer.symbol,
-            transfer.name,
-            transfer.tokenID,
-            uint8(bytes(transfer.uri).length),
-            transfer.uri,
-            transfer.to,
-            transfer.toChain
-        );
-    }
-
-    function parseTransfer(bytes memory encoded) public pure returns (NFTBridgeStructs.Transfer memory transfer) {
-        uint index = 0;
-
-        uint8 payloadID = encoded.toUint8(index);
-        index += 1;
-
-        require(payloadID == 1, "invalid Transfer");
-
-        transfer.tokenAddress = encoded.toBytes32(index);
-        index += 32;
-
-        transfer.tokenChain = encoded.toUint16(index);
-        index += 2;
-
-        transfer.symbol = encoded.toBytes32(index);
-        index += 32;
-
-        transfer.name = encoded.toBytes32(index);
-        index += 32;
-
-        transfer.tokenID = encoded.toUint256(index);
-        index += 32;
-        
-        // Ignore length due to malformatted payload
-        index += 1;
-        transfer.uri = string(encoded.slice(index, encoded.length - index - 34));
-
-        // From here we read backwards due malformatted package
-        index = encoded.length;
-
-        index -= 2;
-        transfer.toChain = encoded.toUint16(index);
-
-        index -= 32;
-        transfer.to = encoded.toBytes32(index);
-
-        //require(encoded.length == index, "invalid Transfer");
-    }
-
-    function onERC721Received(
-        address operator,
-        address,
-        uint256,
-        bytes calldata
-    ) external view returns (bytes4){
-        require(operator == address(this), "can only bridge tokens via transferNFT method");
-        return type(IERC721Receiver).interfaceId;
-    }
-
-    function bytes32ToString(bytes32 input) internal pure returns (string memory) {
-        uint256 i;
-        while (i < 32 && input[i] != 0) {
-            i++;
-        }
-        bytes memory array = new bytes(i);
-        for (uint c = 0; c < i; c++) {
-            array[c] = input[c];
-        }
-        return string(array);
-    }
-}

+ 0 - 15
ethereum/contracts/nft/NFTBridgeEntrypoint.sol

@@ -1,15 +0,0 @@
-// contracts/Wormhole.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
-
-contract NFTBridgeEntrypoint is ERC1967Proxy {
-    constructor (address implementation, bytes memory initData)
-        ERC1967Proxy(
-            implementation,
-            initData
-        )
-    {}
-}

+ 0 - 60
ethereum/contracts/nft/NFTBridgeGetters.sol

@@ -1,60 +0,0 @@
-// contracts/Getters.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
-
-import "../interfaces/IWormhole.sol";
-
-import "./NFTBridgeState.sol";
-
-contract NFTBridgeGetters is NFTBridgeState {
-    function governanceActionIsConsumed(bytes32 hash) public view returns (bool) {
-        return _state.consumedGovernanceActions[hash];
-    }
-
-    function isInitialized(address impl) public view returns (bool) {
-        return _state.initializedImplementations[impl];
-    }
-
-    function isTransferCompleted(bytes32 hash) public view returns (bool) {
-        return _state.completedTransfers[hash];
-    }
-
-    function wormhole() public view returns (IWormhole) {
-        return IWormhole(_state.wormhole);
-    }
-
-    function chainId() public view returns (uint16){
-        return _state.provider.chainId;
-    }
-
-    function governanceChainId() public view returns (uint16){
-        return _state.provider.governanceChainId;
-    }
-
-    function governanceContract() public view returns (bytes32){
-        return _state.provider.governanceContract;
-    }
-
-    function wrappedAsset(uint16 tokenChainId, bytes32 tokenAddress) public view returns (address){
-        return _state.wrappedAssets[tokenChainId][tokenAddress];
-    }
-
-    function bridgeContracts(uint16 chainId_) public view returns (bytes32){
-        return _state.bridgeImplementations[chainId_];
-    }
-
-    function tokenImplementation() public view returns (address){
-        return _state.tokenImplementation;
-    }
-
-    function isWrappedAsset(address token) public view returns (bool){
-        return _state.isWrappedAsset[token];
-    }
-
-    function splCache(uint256 tokenId) public view returns (NFTBridgeStorage.SPLCache memory) {
-        return _state.splCache[tokenId];
-    }
-}

+ 0 - 139
ethereum/contracts/nft/NFTBridgeGovernance.sol

@@ -1,139 +0,0 @@
-// contracts/Bridge.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
-import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
-import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";
-
-import "../libraries/external/BytesLib.sol";
-
-import "./NFTBridgeGetters.sol";
-import "./NFTBridgeSetters.sol";
-import "./NFTBridgeStructs.sol";
-
-import "./token/NFT.sol";
-import "./token/NFTImplementation.sol";
-
-import "../interfaces/IWormhole.sol";
-
-contract NFTBridgeGovernance is NFTBridgeGetters, NFTBridgeSetters, ERC1967Upgrade {
-    using BytesLib for bytes;
-
-    // "NFTBridge" (left padded)
-    bytes32 constant module = 0x00000000000000000000000000000000000000000000004e4654427269646765;
-
-    // Execute a RegisterChain governance message
-    function registerChain(bytes memory encodedVM) public {
-        (IWormhole.VM memory vm, bool valid, string memory reason) = verifyGovernanceVM(encodedVM);
-        require(valid, reason);
-
-        setGovernanceActionConsumed(vm.hash);
-
-        NFTBridgeStructs.RegisterChain memory chain = parseRegisterChain(vm.payload);
-
-        require(chain.chainId == chainId() || chain.chainId == 0, "invalid chain id");
-
-        setBridgeImplementation(chain.emitterChainID, chain.emitterAddress);
-    }
-
-    // Execute a UpgradeContract governance message
-    function upgrade(bytes memory encodedVM) public {
-        (IWormhole.VM memory vm, bool valid, string memory reason) = verifyGovernanceVM(encodedVM);
-        require(valid, reason);
-
-        setGovernanceActionConsumed(vm.hash);
-
-        NFTBridgeStructs.UpgradeContract memory implementation = parseUpgrade(vm.payload);
-
-        require(implementation.chainId == chainId(), "wrong chain id");
-
-        upgradeImplementation(address(uint160(uint256(implementation.newContract))));
-    }
-
-    function verifyGovernanceVM(bytes memory encodedVM) internal view returns (IWormhole.VM memory parsedVM, bool isValid, string memory invalidReason){
-        (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole().parseAndVerifyVM(encodedVM);
-
-        if(!valid){
-            return (vm, valid, reason);
-        }
-
-        if (vm.emitterChainId != governanceChainId()) {
-            return (vm, false, "wrong governance chain");
-        }
-        if (vm.emitterAddress != governanceContract()) {
-            return (vm, false, "wrong governance contract");
-        }
-
-        if(governanceActionIsConsumed(vm.hash)){
-            return (vm, false, "governance action already consumed");
-        }
-
-        return (vm, true, "");
-    }
-
-    event ContractUpgraded(address indexed oldContract, address indexed newContract);
-    function upgradeImplementation(address newImplementation) internal {
-        address currentImplementation = _getImplementation();
-
-        _upgradeTo(newImplementation);
-
-        // Call initialize function of the new implementation
-        (bool success, bytes memory reason) = newImplementation.delegatecall(abi.encodeWithSignature("initialize()"));
-
-        require(success, string(reason));
-
-        emit ContractUpgraded(currentImplementation, newImplementation);
-    }
-
-    function parseRegisterChain(bytes memory encoded) public pure returns(NFTBridgeStructs.RegisterChain memory chain) {
-        uint index = 0;
-
-        // governance header
-
-        chain.module = encoded.toBytes32(index);
-        index += 32;
-        require(chain.module == module, "invalid RegisterChain: wrong module");
-
-        chain.action = encoded.toUint8(index);
-        index += 1;
-        require(chain.action == 1, "invalid RegisterChain: wrong action");
-
-        chain.chainId = encoded.toUint16(index);
-        index += 2;
-
-        // payload
-
-        chain.emitterChainID = encoded.toUint16(index);
-        index += 2;
-
-        chain.emitterAddress = encoded.toBytes32(index);
-        index += 32;
-
-        require(encoded.length == index, "invalid RegisterChain: wrong length");
-    }
-
-    function parseUpgrade(bytes memory encoded) public pure returns(NFTBridgeStructs.UpgradeContract memory chain) {
-        uint index = 0;
-
-        // governance header
-
-        chain.module = encoded.toBytes32(index);
-        index += 32;
-        require(chain.module == module, "invalid UpgradeContract: wrong module");
-
-        chain.action = encoded.toUint8(index);
-        index += 1;
-        require(chain.action == 2, "invalid UpgradeContract: wrong action");
-
-        chain.chainId = encoded.toUint16(index);
-        index += 2;
-
-        // payload
-
-        chain.newContract = encoded.toBytes32(index);
-        index += 32;
-
-        require(encoded.length == index, "invalid UpgradeContract: wrong length");
-    }
-}

+ 0 - 34
ethereum/contracts/nft/NFTBridgeImplementation.sol

@@ -1,34 +0,0 @@
-// contracts/Implementation.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-pragma experimental ABIEncoderV2;
-
-import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";
-
-import "./NFTBridge.sol";
-
-
-contract NFTBridgeImplementation is NFTBridge {
-    // Beacon getter for the token contracts
-    function implementation() public view returns (address) {
-        return tokenImplementation();
-    }
-
-    function initialize() initializer public virtual {
-        // this function needs to be exposed for an upgrade to pass
-    }
-
-    modifier initializer() {
-        address impl = ERC1967Upgrade._getImplementation();
-
-        require(
-            !isInitialized(impl),
-            "already initialized"
-        );
-
-        setInitialized(impl);
-
-        _;
-    }
-}

+ 0 - 57
ethereum/contracts/nft/NFTBridgeSetters.sol

@@ -1,57 +0,0 @@
-// contracts/Setters.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "./NFTBridgeState.sol";
-
-contract NFTBridgeSetters is NFTBridgeState {
-    function setInitialized(address implementatiom) internal {
-        _state.initializedImplementations[implementatiom] = true;
-    }
-
-    function setGovernanceActionConsumed(bytes32 hash) internal {
-        _state.consumedGovernanceActions[hash] = true;
-    }
-
-    function setTransferCompleted(bytes32 hash) internal {
-        _state.completedTransfers[hash] = true;
-    }
-
-    function setChainId(uint16 chainId) internal {
-        _state.provider.chainId = chainId;
-    }
-
-    function setGovernanceChainId(uint16 chainId) internal {
-        _state.provider.governanceChainId = chainId;
-    }
-
-    function setGovernanceContract(bytes32 governanceContract) internal {
-        _state.provider.governanceContract = governanceContract;
-    }
-
-    function setBridgeImplementation(uint16 chainId, bytes32 bridgeContract) internal {
-        _state.bridgeImplementations[chainId] = bridgeContract;
-    }
-
-    function setTokenImplementation(address impl) internal {
-        _state.tokenImplementation = impl;
-    }
-
-    function setWormhole(address wh) internal {
-        _state.wormhole = payable(wh);
-    }
-
-    function setWrappedAsset(uint16 tokenChainId, bytes32 tokenAddress, address wrapper) internal {
-        _state.wrappedAssets[tokenChainId][tokenAddress] = wrapper;
-        _state.isWrappedAsset[wrapper] = true;
-    }
-
-    function setSplCache(uint256 tokenId, NFTBridgeStorage.SPLCache memory cache) internal {
-        _state.splCache[tokenId] = cache;
-    }
-
-    function clearSplCache(uint256 tokenId) internal {
-        delete _state.splCache[tokenId];
-    }
-}

+ 0 - 31
ethereum/contracts/nft/NFTBridgeSetup.sol

@@ -1,31 +0,0 @@
-// contracts/BridgeSetup.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-pragma experimental ABIEncoderV2;
-
-import "./NFTBridgeGovernance.sol";
-
-import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";
-
-contract NFTBridgeSetup is NFTBridgeSetters, ERC1967Upgrade {
-    function setup(
-        address implementation,
-        uint16 chainId,
-        address wormhole,
-        uint16 governanceChainId,
-        bytes32 governanceContract,
-        address tokenImplementation
-    ) public {
-        setChainId(chainId);
-
-        setWormhole(wormhole);
-
-        setGovernanceChainId(governanceChainId);
-        setGovernanceContract(governanceContract);
-
-        setTokenImplementation(tokenImplementation);
-
-        _upgradeTo(implementation);
-    }
-}

+ 0 - 56
ethereum/contracts/nft/NFTBridgeState.sol

@@ -1,56 +0,0 @@
-// contracts/State.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "./NFTBridgeStructs.sol";
-
-contract NFTBridgeStorage {
-    struct Provider {
-        uint16 chainId;
-        uint16 governanceChainId;
-        bytes32 governanceContract;
-    }
-
-    struct Asset {
-        uint16 chainId;
-        bytes32 assetAddress;
-    }
-
-    struct SPLCache {
-        bytes32 name;
-        bytes32 symbol;
-    }
-
-    struct State {
-        address payable wormhole;
-        address tokenImplementation;
-
-        Provider provider;
-
-        // Mapping of consumed governance actions
-        mapping(bytes32 => bool) consumedGovernanceActions;
-
-        // Mapping of consumed token transfers
-        mapping(bytes32 => bool) completedTransfers;
-
-        // Mapping of initialized implementations
-        mapping(address => bool) initializedImplementations;
-
-        // Mapping of wrapped assets (chainID => nativeAddress => wrappedAddress)
-        mapping(uint16 => mapping(bytes32 => address)) wrappedAssets;
-
-        // Mapping to safely identify wrapped assets
-        mapping(address => bool) isWrappedAsset;
-
-        // Mapping of bridge contracts on other chains
-        mapping(uint16 => bytes32) bridgeImplementations;
-
-        // Mapping of spl token info caches (chainID => nativeAddress => SPLCache)
-        mapping(uint256 => SPLCache) splCache;
-    }
-}
-
-contract NFTBridgeState {
-    NFTBridgeStorage.State _state;
-}

+ 0 - 54
ethereum/contracts/nft/NFTBridgeStructs.sol

@@ -1,54 +0,0 @@
-// contracts/Structs.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-contract NFTBridgeStructs {
-    struct Transfer {
-        // PayloadID uint8 = 1
-        // Address of the token. Left-zero-padded if shorter than 32 bytes
-        bytes32 tokenAddress;
-        // Chain ID of the token
-        uint16 tokenChain;
-        // Symbol of the token
-        bytes32 symbol;
-        // Name of the token
-        bytes32 name;
-        // TokenID of the token
-        uint256 tokenID;
-        // URI of the token metadata (UTF-8)
-        string uri;
-        // Address of the recipient. Left-zero-padded if shorter than 32 bytes
-        bytes32 to;
-        // Chain ID of the recipient
-        uint16 toChain;
-    }
-
-    struct RegisterChain {
-        // Governance Header
-        // module: "NFTBridge" left-padded
-        bytes32 module;
-        // governance action: 1
-        uint8 action;
-        // governance paket chain id: this or 0
-        uint16 chainId;
-
-        // Chain ID
-        uint16 emitterChainID;
-        // Emitter address. Left-zero-padded if shorter than 32 bytes
-        bytes32 emitterAddress;
-    }
-
-    struct UpgradeContract {
-        // Governance Header
-        // module: "NFTBridge" left-padded
-        bytes32 module;
-        // governance action: 2
-        uint8 action;
-        // governance paket chain id
-        uint16 chainId;
-
-        // Address of the new contract
-        bytes32 newContract;
-    }
-}

+ 0 - 16
ethereum/contracts/nft/mock/MockNFTBridgeImplementation.sol

@@ -1,16 +0,0 @@
-// contracts/Implementation.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "../NFTBridgeImplementation.sol";
-
-contract MockNFTBridgeImplementation is NFTBridgeImplementation {
-    function initialize() initializer public override {
-        // this function needs to be exposed for an upgrade to pass
-    }
-
-    function testNewImplementationActive() external pure returns (bool) {
-        return true;
-    }
-}

+ 0 - 12
ethereum/contracts/nft/mock/MockNFTImplementation.sol

@@ -1,12 +0,0 @@
-// contracts/Implementation.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "../token/NFTImplementation.sol";
-
-contract MockNFTImplementation is NFTImplementation {
-    function testNewImplementationActive() external pure returns (bool) {
-        return true;
-    }
-}

+ 0 - 11
ethereum/contracts/nft/token/NFT.sol

@@ -1,11 +0,0 @@
-// contracts/Structs.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
-
-contract BridgeNFT is BeaconProxy {
-    constructor(address beacon, bytes memory data) BeaconProxy(beacon, data) {
-
-    }
-}

+ 0 - 254
ethereum/contracts/nft/token/NFTImplementation.sol

@@ -1,254 +0,0 @@
-// contracts/TokenImplementation.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-import "./NFTState.sol";
-import "@openzeppelin/contracts/access/Ownable.sol";
-import "@openzeppelin/contracts/utils/Context.sol";
-import "@openzeppelin/contracts/utils/Address.sol";
-import "@openzeppelin/contracts/utils/Strings.sol";
-import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
-import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
-import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
-import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
-import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
-
-// Based on the OpenZepplin ERC721 implementation, licensed under MIT
-contract NFTImplementation is NFTState, Context, IERC721, IERC721Metadata, ERC165 {
-    using Address for address;
-    using Strings for uint256;
-
-    function initialize(
-        string memory name_,
-        string memory symbol_,
-
-        address owner_,
-
-        uint16 chainId_,
-        bytes32 nativeContract_
-    ) initializer public {
-        _state.name = name_;
-        _state.symbol = symbol_;
-
-        _state.owner = owner_;
-
-        _state.chainId = chainId_;
-        _state.nativeContract = nativeContract_;
-    }
-
-    function supportsInterface(bytes4 interfaceId) public view override(ERC165, IERC165) returns (bool) {
-        return
-        interfaceId == type(IERC721).interfaceId ||
-        interfaceId == type(IERC721Metadata).interfaceId ||
-        super.supportsInterface(interfaceId);
-    }
-
-    function balanceOf(address owner_) public view override returns (uint256) {
-        require(owner_ != address(0), "ERC721: balance query for the zero address");
-        return _state.balances[owner_];
-    }
-
-    function ownerOf(uint256 tokenId) public view override returns (address) {
-        address owner_ = _state.owners[tokenId];
-        require(owner_ != address(0), "ERC721: owner query for nonexistent token");
-        return owner_;
-    }
-
-    function name() public view override returns (string memory) {
-        return _state.name;
-    }
-
-    function symbol() public view override returns (string memory) {
-        return _state.symbol;
-    }
-
-    function tokenURI(uint256 tokenId) public view override returns (string memory) {
-        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
-
-        return _state.tokenURIs[tokenId];
-    }
-
-    function chainId() public view returns (uint16) {
-        return _state.chainId;
-    }
-
-    function nativeContract() public view returns (bytes32) {
-        return _state.nativeContract;
-    }
-
-    function owner() public view returns (address) {
-        return _state.owner;
-    }
-
-    function approve(address to, uint256 tokenId) public override {
-        address owner_ = NFTImplementation.ownerOf(tokenId);
-        require(to != owner_, "ERC721: approval to current owner");
-
-        require(
-            _msgSender() == owner_ || isApprovedForAll(owner_, _msgSender()),
-            "ERC721: approve caller is not owner nor approved for all"
-        );
-
-        _approve(to, tokenId);
-    }
-
-    function getApproved(uint256 tokenId) public view override returns (address) {
-        require(_exists(tokenId), "ERC721: approved query for nonexistent token");
-
-        return _state.tokenApprovals[tokenId];
-    }
-
-    function setApprovalForAll(address operator, bool approved) public override {
-        require(operator != _msgSender(), "ERC721: approve to caller");
-
-        _state.operatorApprovals[_msgSender()][operator] = approved;
-        emit ApprovalForAll(_msgSender(), operator, approved);
-    }
-
-    function isApprovedForAll(address owner_, address operator) public view override returns (bool) {
-        return _state.operatorApprovals[owner_][operator];
-    }
-
-    function transferFrom(
-        address from,
-        address to,
-        uint256 tokenId
-    ) public override {
-        //solhint-disable-next-line max-line-length
-        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
-
-        _transfer(from, to, tokenId);
-    }
-
-    function safeTransferFrom(
-        address from,
-        address to,
-        uint256 tokenId
-    ) public override {
-        safeTransferFrom(from, to, tokenId, "");
-    }
-
-    function safeTransferFrom(
-        address from,
-        address to,
-        uint256 tokenId,
-        bytes memory _data
-    ) public override {
-        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
-        _safeTransfer(from, to, tokenId, _data);
-    }
-
-    function _safeTransfer(
-        address from,
-        address to,
-        uint256 tokenId,
-        bytes memory _data
-    ) internal {
-        _transfer(from, to, tokenId);
-        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
-    }
-
-    function _exists(uint256 tokenId) internal view returns (bool) {
-        return _state.owners[tokenId] != address(0);
-    }
-
-    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
-        require(_exists(tokenId), "ERC721: operator query for nonexistent token");
-        address owner_ = NFTImplementation.ownerOf(tokenId);
-        return (spender == owner_ || getApproved(tokenId) == spender || isApprovedForAll(owner_, spender));
-    }
-
-    function mint(address to, uint256 tokenId, string memory uri) public onlyOwner {
-        _mint(to, tokenId, uri);
-    }
-
-    function _mint(address to, uint256 tokenId, string memory uri) internal {
-        require(to != address(0), "ERC721: mint to the zero address");
-        require(!_exists(tokenId), "ERC721: token already minted");
-
-        _state.balances[to] += 1;
-        _state.owners[tokenId] = to;
-        _state.tokenURIs[tokenId] = uri;
-
-        emit Transfer(address(0), to, tokenId);
-    }
-
-    function burn(uint256 tokenId) public onlyOwner {
-        _burn(tokenId);
-    }
-
-    function _burn(uint256 tokenId) internal {
-        address owner_ = NFTImplementation.ownerOf(tokenId);
-
-        // Clear approvals
-        _approve(address(0), tokenId);
-
-        _state.balances[owner_] -= 1;
-        delete _state.owners[tokenId];
-
-        emit Transfer(owner_, address(0), tokenId);
-    }
-
-    function _transfer(
-        address from,
-        address to,
-        uint256 tokenId
-    ) internal {
-        require(NFTImplementation.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
-        require(to != address(0), "ERC721: transfer to the zero address");
-
-        // Clear approvals from the previous owner
-        _approve(address(0), tokenId);
-
-        _state.balances[from] -= 1;
-        _state.balances[to] += 1;
-        _state.owners[tokenId] = to;
-
-        emit Transfer(from, to, tokenId);
-    }
-
-    function _approve(address to, uint256 tokenId) internal {
-        _state.tokenApprovals[tokenId] = to;
-        emit Approval(NFTImplementation.ownerOf(tokenId), to, tokenId);
-    }
-
-    function _checkOnERC721Received(
-        address from,
-        address to,
-        uint256 tokenId,
-        bytes memory _data
-    ) private returns (bool) {
-        if (to.isContract()) {
-            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
-                return retval == IERC721Receiver.onERC721Received.selector;
-            } catch (bytes memory reason) {
-                if (reason.length == 0) {
-                    revert("ERC721: transfer to non ERC721Receiver implementer");
-                } else {
-                    assembly {
-                        revert(add(32, reason), mload(reason))
-                    }
-                }
-            }
-        } else {
-            return true;
-        }
-    }
-
-    modifier onlyOwner() {
-        require(owner() == _msgSender(), "caller is not the owner");
-        _;
-    }
-
-    modifier initializer() {
-        require(
-            !_state.initialized,
-            "Already initialized"
-        );
-
-        _state.initialized = true;
-
-        _;
-    }
-}

+ 0 - 41
ethereum/contracts/nft/token/NFTState.sol

@@ -1,41 +0,0 @@
-// contracts/State.sol
-// SPDX-License-Identifier: Apache 2
-
-pragma solidity ^0.8.0;
-
-contract NFTStorage {
-    struct State {
-
-        // Token name
-        string name;
-
-        // Token symbol
-        string symbol;
-
-        // Mapping from token ID to owner address
-        mapping(uint256 => address) owners;
-
-        // Mapping owner address to token count
-        mapping(address => uint256) balances;
-
-        // Mapping from token ID to approved address
-        mapping(uint256 => address) tokenApprovals;
-
-        // Mapping from token ID to URI
-        mapping(uint256 => string) tokenURIs;
-
-        // Mapping from owner to operator approvals
-        mapping(address => mapping(address => bool)) operatorApprovals;
-
-        address owner;
-
-        bool initialized;
-
-        uint16 chainId;
-        bytes32 nativeContract;
-    }
-}
-
-contract NFTState {
-    NFTStorage.State _state;
-}

+ 1 - 1
ethereum/contracts/pyth/PythGetters.sol

@@ -3,7 +3,7 @@
 
 pragma solidity ^0.8.0;
 
-import "../interfaces/IWormhole.sol";
+import "../wormhole/interfaces/IWormhole.sol";
 
 import "./PythState.sol";
 

+ 0 - 0
ethereum/contracts/Getters.sol → ethereum/contracts/wormhole/Getters.sol


+ 0 - 0
ethereum/contracts/Governance.sol → ethereum/contracts/wormhole/Governance.sol


+ 1 - 1
ethereum/contracts/GovernanceStructs.sol → ethereum/contracts/wormhole/GovernanceStructs.sol

@@ -3,7 +3,7 @@
 
 pragma solidity ^0.8.0;
 
-import "./libraries/external/BytesLib.sol";
+import "../libraries/external/BytesLib.sol";
 import "./Structs.sol";
 
 contract GovernanceStructs {

+ 0 - 0
ethereum/contracts/Implementation.sol → ethereum/contracts/wormhole/Implementation.sol


+ 1 - 1
ethereum/contracts/Messages.sol → ethereum/contracts/wormhole/Messages.sol

@@ -6,7 +6,7 @@ pragma experimental ABIEncoderV2;
 
 import "./Getters.sol";
 import "./Structs.sol";
-import "./libraries/external/BytesLib.sol";
+import "../libraries/external/BytesLib.sol";
 
 
 contract Messages is Getters {

+ 0 - 0
ethereum/contracts/Setters.sol → ethereum/contracts/wormhole/Setters.sol


+ 0 - 0
ethereum/contracts/Setup.sol → ethereum/contracts/wormhole/Setup.sol


+ 0 - 0
ethereum/contracts/State.sol → ethereum/contracts/wormhole/State.sol


+ 0 - 0
ethereum/contracts/Structs.sol → ethereum/contracts/wormhole/Structs.sol


+ 0 - 0
ethereum/contracts/Wormhole.sol → ethereum/contracts/wormhole/Wormhole.sol


+ 0 - 0
ethereum/contracts/interfaces/IWormhole.sol → ethereum/contracts/wormhole/interfaces/IWormhole.sol


+ 0 - 0
ethereum/contracts/mock/MockImplementation.sol → ethereum/contracts/wormhole/mock/MockImplementation.sol


+ 0 - 38
ethereum/migrations/test/3_deploy_bridge.js

@@ -1,38 +0,0 @@
-require('dotenv').config({ path: "../.env" });
-
-const TokenBridge = artifacts.require("TokenBridge");
-const BridgeImplementation = artifacts.require("BridgeImplementation");
-const BridgeSetup = artifacts.require("BridgeSetup");
-const TokenImplementation = artifacts.require("TokenImplementation");
-const Wormhole = artifacts.require("Wormhole");
-
-const chainId = process.env.BRIDGE_INIT_CHAIN_ID;
-const governanceChainId = process.env.BRIDGE_INIT_GOV_CHAIN_ID;
-const governanceContract = process.env.BRIDGE_INIT_GOV_CONTRACT; // bytes32
-const WETH = process.env.BRIDGE_INIT_WETH;
-
-module.exports = async function (deployer) {
-    // deploy token implementation
-    await deployer.deploy(TokenImplementation);
-
-    // deploy setup
-    await deployer.deploy(BridgeSetup);
-
-    // deploy implementation
-    await deployer.deploy(BridgeImplementation);
-
-    // encode initialisation data
-    const setup = new web3.eth.Contract(BridgeSetup.abi, BridgeSetup.address);
-    const initData = setup.methods.setup(
-        BridgeImplementation.address,
-        chainId,
-        (await Wormhole.deployed()).address,
-        governanceChainId,
-        governanceContract,
-        TokenImplementation.address,
-        WETH
-    ).encodeABI();
-
-    // deploy proxy
-    await deployer.deploy(TokenBridge, BridgeSetup.address, initData);
-};

+ 0 - 0
ethereum/migrations/test/5_deploy_pyth.js → ethereum/migrations/test/3_deploy_pyth.js


+ 0 - 36
ethereum/migrations/test/4_deploy_nft_bridge.js

@@ -1,36 +0,0 @@
-require('dotenv').config({ path: "../.env" });
-
-const TokenBridge = artifacts.require("NFTBridgeEntrypoint");
-const BridgeImplementation = artifacts.require("NFTBridgeImplementation");
-const BridgeSetup = artifacts.require("NFTBridgeSetup");
-const TokenImplementation = artifacts.require("NFTImplementation");
-const Wormhole = artifacts.require("Wormhole");
-
-const chainId = process.env.BRIDGE_INIT_CHAIN_ID;
-const governanceChainId = process.env.BRIDGE_INIT_GOV_CHAIN_ID;
-const governanceContract = process.env.BRIDGE_INIT_GOV_CONTRACT; // bytes32
-
-module.exports = async function (deployer) {
-    // deploy token implementation
-    await deployer.deploy(TokenImplementation);
-
-    // deploy setup
-    await deployer.deploy(BridgeSetup);
-
-    // deploy implementation
-    await deployer.deploy(BridgeImplementation);
-
-    // encode initialisation data
-    const setup = new web3.eth.Contract(BridgeSetup.abi, BridgeSetup.address);
-    const initData = setup.methods.setup(
-        BridgeImplementation.address,
-        chainId,
-        (await Wormhole.deployed()).address,
-        governanceChainId,
-        governanceContract,
-        TokenImplementation.address
-    ).encodeABI();
-
-    // deploy proxy
-    await deployer.deploy(TokenBridge, BridgeSetup.address, initData);
-};

+ 0 - 12
ethereum/migrations/test/6_deploy_bridge_implementation_only.js

@@ -1,12 +0,0 @@
-// run with:
-// npm run deploy-bridge-implementation-only
-// e.g. Ethereum Mainnet
-// INFURA_KEY="" MNEMONIC="" npm run deploy-bridge-implementation-only -- --network mainnet
-// e.g. BSC
-// MNEMONIC="" npm run deploy-bridge-implementation-only -- --network binance
-// e.g. Polygon
-// MNEMONIC="" npm run deploy-bridge-implementation-only -- --network polygon
-const BridgeImplementation = artifacts.require("BridgeImplementation");
-module.exports = async function(deployer) {
-  await deployer.deploy(BridgeImplementation);
-};

+ 0 - 5
ethereum/migrations/test/9_deploy_weth9.js

@@ -1,5 +0,0 @@
-var WETH9 = artifacts.require("MockWETH9");
-
-module.exports = function(deployer) {
-    deployer.deploy(WETH9);
-};

+ 2 - 4
ethereum/package.json

@@ -21,11 +21,9 @@
   "scripts": {
     "build": "truffle compile",
     "test": "truffle test",
-    "migrate": "mkdir -p build/contracts && cp node_modules/@openzeppelin/contracts/build/contracts/* build/contracts/ && truffle migrate --to 5",
+    "migrate": "mkdir -p build/contracts && cp node_modules/@openzeppelin/contracts/build/contracts/* build/contracts/ && truffle migrate",
     "flatten": "mkdir -p node_modules/@poanet/solidity-flattener/contracts && cp -r contracts/* node_modules/@poanet/solidity-flattener/contracts/ && poa-solidity-flattener",
-    "verify": "patch -u -f node_modules/truffle-plugin-verify/constants.js -i truffle-verify-constants.patch; truffle run verify $npm_config_module@$npm_config_contract_address --network $npm_config_network",
-    "deploy-bridge-implementation-only": "mkdir -p build/contracts && cp node_modules/@openzeppelin/contracts/build/contracts/* build/contracts/ && truffle migrate --f 6",
-    "deploy_weth9": "mkdir -p build/contracts && cp node_modules/@openzeppelin/contracts/build/contracts/* build/contracts/ && truffle migrate --f 9"
+    "verify": "patch -u -f node_modules/truffle-plugin-verify/constants.js -i truffle-verify-constants.patch; truffle run verify $npm_config_module@$npm_config_contract_address --network $npm_config_network"
   },
   "author": "",
   "license": "ISC",

+ 0 - 96
ethereum/scripts/deploy_test_token.js

@@ -1,96 +0,0 @@
-// run this script with truffle exec
-
-const ERC20 = artifacts.require("ERC20PresetMinterPauser");
-const ERC721 = artifacts.require("ERC721PresetMinterPauserAutoId");
-
-const interateToStandardTransactionCount = async () => {
-  const accounts = await web3.eth.getAccounts();
-
-  const transactionCount = await web3.eth.getTransactionCount(
-    accounts[0],
-    "latest"
-  );
-  console.log(
-    "transaction count prior to test token deploys: ",
-    transactionCount
-  );
-
-  const transactionsToBurn = 32 - transactionCount;
-  const promises = [];
-  for (let i = 0; i < transactionsToBurn; i++) {
-    promises.push(
-      web3.eth.sendTransaction({
-        to: accounts[0],
-        from: accounts[0],
-        value: 530,
-      })
-    );
-  }
-
-  await Promise.all(promises);
-
-  const burnCount = await web3.eth.getTransactionCount(accounts[0], "latest");
-
-  console.log("transaction count after burn: ", burnCount);
-
-  return Promise.resolve();
-};
-
-module.exports = async function(callback) {
-  try {
-    const accounts = await web3.eth.getAccounts();
-
-    //Contracts deployed via this script deploy to an address which is determined by the number of transactions
-    //which have been performed on the chain.
-    //This is, however, variable. For example, if you optionally deploy the pyth contracts, more transactions are
-    //performed than if you didn't.
-    //In order to make sure the test contracts deploy to a location
-    //which is deterministic with regard to other environment conditions, we fire bogus transactions up to a safe
-    //count, currently 32, before deploying the test contracts.
-    await interateToStandardTransactionCount();
-
-    // deploy token contract
-    const tokenAddress = (await ERC20.new("Ethereum Test Token", "TKN"))
-      .address;
-    const token = new web3.eth.Contract(ERC20.abi, tokenAddress);
-
-    console.log("Token deployed at: " + tokenAddress);
-
-    // mint 1000 units
-    await token.methods.mint(accounts[0], "1000000000000000000000").send({
-      from: accounts[0],
-      gas: 1000000,
-    });
-
-    const nftAddress = (
-      await ERC721.new(
-        "Not an APE 🐒",
-        "APE🐒",
-        "https://cloudflare-ipfs.com/ipfs/QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/"
-      )
-    ).address;
-    const nft = new web3.eth.Contract(ERC721.abi, nftAddress);
-    await nft.methods.mint(accounts[0]).send({
-      from: accounts[0],
-      gas: 1000000,
-    });
-    await nft.methods.mint(accounts[0]).send({
-      from: accounts[0],
-      gas: 1000000,
-    });
-
-    console.log("NFT deployed at: " + nftAddress);
-
-    const MockWETH9 = await artifacts.require("MockWETH9");
-    //WETH deploy
-    // deploy token contract
-    const wethAddress = (await MockWETH9.new()).address;
-    const wethToken = new web3.eth.Contract(MockWETH9.abi, wethAddress);
-
-    console.log("WETH token deployed at: " + wethAddress);
-
-    callback();
-  } catch (e) {
-    callback(e);
-  }
-};

+ 0 - 26
ethereum/scripts/register_bsc_chain.js

@@ -1,26 +0,0 @@
-// run this script with truffle exec
-
-const jsonfile = require("jsonfile");
-const TokenBridge = artifacts.require("TokenBridge");
-const TokenImplementation = artifacts.require("TokenImplementation");
-const BridgeImplementationFullABI = jsonfile.readFileSync("../build/contracts/BridgeImplementation.json").abi
-
-module.exports = async function (callback) {
-    try {
-        const accounts = await web3.eth.getAccounts();
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-
-        // Register the BSC endpoint
-        await initialized.methods.registerChain("0x01000000000100719b4ada436f614489dbf87593c38ba9aea35aa7b997387f8ae09f819806f5654c8d45b6b751faa0e809ccbc294794885efa205bd8a046669464c7cbfb03d183010000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000002c8bb0600000000000000000000000000000000000000000000546f6b656e42726964676501000000040000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16").send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        callback();
-    }
-    catch (e) {
-        callback(e);
-    }
-}
-

+ 0 - 26
ethereum/scripts/register_eth_chain.js

@@ -1,26 +0,0 @@
-// run this script with truffle exec
-
-const jsonfile = require("jsonfile");
-const TokenBridge = artifacts.require("TokenBridge");
-const TokenImplementation = artifacts.require("TokenImplementation");
-const BridgeImplementationFullABI = jsonfile.readFileSync("../build/contracts/BridgeImplementation.json").abi
-
-module.exports = async function (callback) {
-    try {
-        const accounts = await web3.eth.getAccounts();
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-
-        // Register the ETH endpoint
-        await initialized.methods.registerChain("0x01000000000100e2e1975d14734206e7a23d90db48a6b5b6696df72675443293c6057dcb936bf224b5df67d32967adeb220d4fe3cb28be515be5608c74aab6adb31099a478db5c01000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000546f6b656e42726964676501000000020000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16").send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        callback();
-    }
-    catch (e) {
-        callback(e);
-    }
-}
-

+ 0 - 34
ethereum/scripts/register_solana_chain.js

@@ -1,34 +0,0 @@
-// run this script with truffle exec
-
-const jsonfile = require("jsonfile");
-const TokenBridge = artifacts.require("TokenBridge");
-const NFTBridge = artifacts.require("NFTBridgeEntrypoint");
-const TokenImplementation = artifacts.require("TokenImplementation");
-const BridgeImplementationFullABI = jsonfile.readFileSync("../build/contracts/BridgeImplementation.json").abi
-
-module.exports = async function (callback) {
-    try {
-        const accounts = await web3.eth.getAccounts();
-        const tokenBridge = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-        const nftBridge = new web3.eth.Contract(BridgeImplementationFullABI, NFTBridge.address);
-
-        // Register the Solana token bridge endpoint
-        await tokenBridge.methods.registerChain("0x01000000000100c9f4230109e378f7efc0605fb40f0e1869f2d82fda5b1dfad8a5a2dafee85e033d155c18641165a77a2db6a7afbf2745b458616cb59347e89ae0c7aa3e7cc2d400000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000546f6b656e4272696467650100000001c69a1b1a65dd336bf1df6a77afb501fc25db7fc0938cb08595a9ef473265cb4f").send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        // Register the Solana NFT bridge endpoint
-        await nftBridge.methods.registerChain("0x010000000001007985ba742002ae745c19722fea4d82102e68526c7c9d94d0e5d0a809071c98451c9693b230b3390f4ca9555a3ba9a9abbe87cf6f9e400682213e4fbbe1dabb9e0100000001000000010001000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004e4654427269646765010000000196ee982293251b48729804c8e8b24b553eb6b887867024948d2236fd37a577ab").send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        callback();
-    }
-    catch (e) {
-        callback(e);
-    }
-}

+ 0 - 35
ethereum/scripts/register_terra_chain.js

@@ -1,35 +0,0 @@
-// run this script with truffle exec
-
-const jsonfile = require("jsonfile");
-const TokenBridge = artifacts.require("TokenBridge");
-const NFTBridge = artifacts.require("NFTBridgeEntrypoint");
-const TokenImplementation = artifacts.require("TokenImplementation");
-const BridgeImplementationFullABI = jsonfile.readFileSync("../build/contracts/BridgeImplementation.json").abi
-
-module.exports = async function (callback) {
-    try {
-        const accounts = await web3.eth.getAccounts();
-        const tokenBridge = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-        const nftBridge = new web3.eth.Contract(BridgeImplementationFullABI, NFTBridge.address);
-
-        // Register the terra token bridge endpoint
-        await tokenBridge.methods.registerChain("0x010000000001009a895e8b42444fdf60a71666121d7e84b3a49579ba3b84fff1dbdf9ec93360390c05a88f66c90df2034cb38427ba9b01632e780ce7b84df559a1bf44c316447d01000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000546f6b656e4272696467650100000003000000000000000000000000784999135aaa8a3ca5914468852fdddbddd8789d").send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        // Register the terra NFT bridge endpoint
-        await nftBridge.methods.registerChain("0x010000000001008ebe6a1971ae336bb7817aa7e8ffc13e1582ebbc00dc85e33b592dfea998787a1a9ccece2efce7fcdf228153baafb6f1232b320805c82fac90b5e49c3b5ad4fd0100000001000000010001000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004e46544272696467650100000003000000000000000000000000288246bebae560e006d01c675ae332ac8e146bb7").send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        callback();
-    }
-    catch (e) {
-        callback(e);
-    }
-}
-

+ 0 - 973
ethereum/test/bridge.js

@@ -1,973 +0,0 @@
-const jsonfile = require('jsonfile');
-const elliptic = require('elliptic');
-const BigNumber = require('bignumber.js');
-
-const Wormhole = artifacts.require("Wormhole");
-const TokenBridge = artifacts.require("TokenBridge");
-const BridgeImplementation = artifacts.require("BridgeImplementation");
-const TokenImplementation = artifacts.require("TokenImplementation");
-const FeeToken = artifacts.require("FeeToken");
-const MockBridgeImplementation = artifacts.require("MockBridgeImplementation");
-const MockWETH9 = artifacts.require("MockWETH9");
-
-const testSigner1PK = "cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0";
-const testSigner2PK = "892330666a850761e7370376430bb8c2aa1494072d3bfeaed0c4fa3d5a9135fe";
-
-const WormholeImplementationFullABI = jsonfile.readFileSync("build/contracts/Implementation.json").abi
-const BridgeImplementationFullABI = jsonfile.readFileSync("build/contracts/BridgeImplementation.json").abi
-const TokenImplementationFullABI = jsonfile.readFileSync("build/contracts/TokenImplementation.json").abi
-
-contract("Bridge", function () {
-    const testSigner1 = web3.eth.accounts.privateKeyToAccount(testSigner1PK);
-    const testSigner2 = web3.eth.accounts.privateKeyToAccount(testSigner2PK);
-    const testChainId = "2";
-    const testGovernanceChainId = "1";
-    const testGovernanceContract = "0x0000000000000000000000000000000000000000000000000000000000000004";
-    let WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
-    const testForeignChainId = "1";
-    const testForeignBridgeContract = "0x000000000000000000000000000000000000000000000000000000000000ffff";
-    const testBridgedAssetChain = "0001";
-    const testBridgedAssetAddress = "000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e";
-
-
-    it("should be initialized with the correct signers and values", async function () {
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-
-        const weth = await initialized.methods.WETH().call();
-        assert.equal(weth, WETH);
-
-        const tokenImplentation = await initialized.methods.tokenImplementation().call();
-        assert.equal(tokenImplentation, TokenImplementation.address);
-
-        // test beacon functionality
-        const beaconImplementation = await initialized.methods.implementation().call();
-        assert.equal(beaconImplementation, TokenImplementation.address);
-
-        // chain id
-        const chainId = await initialized.methods.chainId().call();
-        assert.equal(chainId, testChainId);
-
-        // governance
-        const governanceChainId = await initialized.methods.governanceChainId().call();
-        assert.equal(governanceChainId, testGovernanceChainId);
-        const governanceContract = await initialized.methods.governanceContract().call();
-        assert.equal(governanceContract, testGovernanceContract);
-    })
-
-    it("should register a foreign bridge implementation correctly", async function () {
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-        const accounts = await web3.eth.getAccounts();
-
-        let data = [
-            "0x",
-            "000000000000000000000000000000000000000000546f6b656e427269646765",
-            "01",
-            "0000",
-            web3.eth.abi.encodeParameter("uint16", testForeignChainId).substring(2 + (64 - 4)),
-            web3.eth.abi.encodeParameter("bytes32", testForeignBridgeContract).substring(2),
-        ].join('')
-
-        const vm = await signAndEncodeVM(
-            1,
-            1,
-            testGovernanceChainId,
-            testGovernanceContract,
-            0,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-
-        let before = await initialized.methods.bridgeContracts(testForeignChainId).call();
-
-        assert.equal(before, "0x0000000000000000000000000000000000000000000000000000000000000000");
-
-        await initialized.methods.registerChain("0x" + vm).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        let after = await initialized.methods.bridgeContracts(testForeignChainId).call();
-
-        assert.equal(after, testForeignBridgeContract);
-    })
-
-    it("should accept a valid upgrade", async function () {
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-        const accounts = await web3.eth.getAccounts();
-
-        const mock = await MockBridgeImplementation.new();
-
-        let data = [
-            "0x",
-            "000000000000000000000000000000000000000000546f6b656e427269646765",
-            "02",
-            web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4)),
-            web3.eth.abi.encodeParameter("address", mock.address).substring(2),
-        ].join('')
-
-        const vm = await signAndEncodeVM(
-            1,
-            1,
-            testGovernanceChainId,
-            testGovernanceContract,
-            0,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-        let before = await web3.eth.getStorageAt(TokenBridge.address, "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc");
-
-        assert.equal(before.toLowerCase(), BridgeImplementation.address.toLowerCase());
-
-        await initialized.methods.upgrade("0x" + vm).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        let after = await web3.eth.getStorageAt(TokenBridge.address, "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc");
-
-        assert.equal(after.toLowerCase(), mock.address.toLowerCase());
-
-        const mockImpl = new web3.eth.Contract(MockBridgeImplementation.abi, TokenBridge.address);
-
-        let isUpgraded = await mockImpl.methods.testNewImplementationActive().call();
-
-        assert.ok(isUpgraded);
-    })
-
-    it("bridged tokens should only be mint- and burn-able by owner", async function () {
-        const accounts = await web3.eth.getAccounts();
-
-        // initialize our template token contract
-        const token = new web3.eth.Contract(TokenImplementation.abi, TokenImplementation.address);
-
-        await token.methods.initialize(
-            "TestToken",
-            "TT",
-            18,
-            0,
-
-            accounts[0],
-
-            0,
-            "0x0"
-        ).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        await token.methods.mint(accounts[0], 10).send({
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        await token.methods.burn(accounts[0], 5).send({
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        let failed = false
-        try {
-            await token.methods.mint(accounts[0], 10).send({
-                from: accounts[1],
-                gasLimit: 2000000
-            });
-        } catch (e) {
-            failed = true
-        }
-        assert.ok(failed)
-
-        failed = false
-        try {
-            await token.methods.burn(accounts[0], 5).send({
-                from: accounts[1],
-                gasLimit: 2000000
-            });
-        } catch (e) {
-            failed = true
-        }
-        assert.ok(failed)
-
-        await token.methods.burn(accounts[0], 5).send({
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-    })
-
-    it("should attest a token correctly", async function () {
-        const accounts = await web3.eth.getAccounts();
-
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-
-        await initialized.methods.attestToken(TokenImplementation.address, "234").send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        const wormhole = new web3.eth.Contract(WormholeImplementationFullABI, Wormhole.address);
-
-        const log = (await wormhole.getPastEvents('LogMessagePublished', {
-            fromBlock: 'latest'
-        }))[0].returnValues
-
-        assert.equal(log.sender, TokenBridge.address)
-
-        assert.equal(log.payload.length - 2, 200);
-
-        // payload id
-        assert.equal(log.payload.substr(2, 2), "02");
-
-        // token address
-        assert.equal(log.payload.substr(4, 64), web3.eth.abi.encodeParameter("address", TokenImplementation.address).substring(2));
-
-        // chain id
-        assert.equal(log.payload.substr(68, 4), web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + 64 - 4))
-
-        // decimals
-        assert.equal(log.payload.substr(72, 2), web3.eth.abi.encodeParameter("uint8", 18).substring(2 + 64 - 2))
-
-        // symbol (TT)
-        assert.equal(log.payload.substr(74, 64), "5454000000000000000000000000000000000000000000000000000000000000")
-
-        // name (TestToken (Wormhole))
-        assert.equal(log.payload.substr(138, 64), "54657374546f6b656e2028576f726d686f6c6529000000000000000000000000")
-    })
-
-    it("should correctly deploy a wrapped asset for a token attestation", async function () {
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-        const accounts = await web3.eth.getAccounts();
-
-        const data = "0x02" +
-            // tokenAddress
-            testBridgedAssetAddress +
-            // tokenchain
-            testBridgedAssetChain +
-            // decimals
-            "12" +
-            // symbol
-            "5454000000000000000000000000000000000000000000000000000000000000" +
-            // name
-            "54657374546f6b656e0000000000000000000000000000000000000000000000";
-
-        const vm = await signAndEncodeVM(
-            0,
-            0,
-            testForeignChainId,
-            testForeignBridgeContract,
-            0,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-        await initialized.methods.createWrapped("0x" + vm).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        const wrappedAddress = await initialized.methods.wrappedAsset("0x0001", "0x000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e").call();
-
-        assert.ok(await initialized.methods.isWrappedAsset(wrappedAddress).call())
-
-        const initializedWrappedAsset = new web3.eth.Contract(TokenImplementation.abi, wrappedAddress);
-
-        const symbol = await initializedWrappedAsset.methods.symbol().call();
-        assert.equal(symbol, "TT");
-
-        const name = await initializedWrappedAsset.methods.name().call();
-        assert.equal(name, "TestToken (Wormhole)");
-
-        const decimals = await initializedWrappedAsset.methods.decimals().call();
-        assert.equal(decimals, 18);
-
-        const chainId = await initializedWrappedAsset.methods.chainId().call();
-        assert.equal(chainId, 1);
-
-        const nativeContract = await initializedWrappedAsset.methods.nativeContract().call();
-        assert.equal(nativeContract, "0x000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e");
-    })
-
-    it("should correctly update a wrapped asset for a token attestation", async function () {
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-        const accounts = await web3.eth.getAccounts();
-
-        const data = "0x02" +
-            // tokenAddress
-            testBridgedAssetAddress +
-            // tokenchain
-            testBridgedAssetChain +
-            // decimals
-            "12" +
-            // symbol
-            "5555000000000000000000000000000000000000000000000000000000000000" +
-            // name
-            "5472656500000000000000000000000000000000000000000000000000000000";
-
-        let vm = await signAndEncodeVM(
-            0,
-            0,
-            testForeignChainId,
-            testForeignBridgeContract,
-            0,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-        let failed = false;
-        try {
-            await initialized.methods.updateWrapped("0x" + vm).send({
-                value: 0,
-                from: accounts[0],
-                gasLimit: 2000000
-            });
-        } catch (error) {
-            assert.equal(error.message, "Returned error: VM Exception while processing transaction: revert current metadata is up to date")
-            failed = true
-        }
-        assert.ok(failed)
-
-        vm = await signAndEncodeVM(
-            0,
-            0,
-            testForeignChainId,
-            testForeignBridgeContract,
-            1,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-        await initialized.methods.updateWrapped("0x" + vm).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        const wrappedAddress = await initialized.methods.wrappedAsset("0x0001", "0x000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e").call();
-
-        assert.ok(await initialized.methods.isWrappedAsset(wrappedAddress).call())
-
-        const initializedWrappedAsset = new web3.eth.Contract(TokenImplementation.abi, wrappedAddress);
-
-        const symbol = await initializedWrappedAsset.methods.symbol().call();
-        assert.equal(symbol, "UU");
-
-        const name = await initializedWrappedAsset.methods.name().call();
-        assert.equal(name, "Tree (Wormhole)");
-
-        const decimals = await initializedWrappedAsset.methods.decimals().call();
-        assert.equal(decimals, 18);
-
-        const chainId = await initializedWrappedAsset.methods.chainId().call();
-        assert.equal(chainId, 1);
-
-        const nativeContract = await initializedWrappedAsset.methods.nativeContract().call();
-        assert.equal(nativeContract, "0x000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e");
-    })
-
-    it("should deposit and log transfers correctly", async function () {
-        const accounts = await web3.eth.getAccounts();
-        const amount = "1000000000000000000";
-        const fee = "100000000000000000";
-
-        // mint and approve tokens
-        const token = new web3.eth.Contract(TokenImplementation.abi, TokenImplementation.address);
-        await token.methods.mint(accounts[0], amount).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-        await token.methods.approve(TokenBridge.address, amount).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        // deposit tokens
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-
-        const accountBalanceBefore = await token.methods.balanceOf(accounts[0]).call();
-        const bridgeBalanceBefore = await token.methods.balanceOf(TokenBridge.address).call();
-
-        assert.equal(accountBalanceBefore.toString(10), amount);
-        assert.equal(bridgeBalanceBefore.toString(10), "0");
-
-        await initialized.methods.transferTokens(
-            TokenImplementation.address,
-            amount,
-            "10",
-            "0x000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e",
-            fee,
-            "234"
-        ).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        const accountBalanceAfter = await token.methods.balanceOf(accounts[0]).call();
-        const bridgeBalanceAfter = await token.methods.balanceOf(TokenBridge.address).call();
-
-        assert.equal(accountBalanceAfter.toString(10), "0");
-        assert.equal(bridgeBalanceAfter.toString(10), amount);
-
-        // check transfer log
-        const wormhole = new web3.eth.Contract(WormholeImplementationFullABI, Wormhole.address);
-        const log = (await wormhole.getPastEvents('LogMessagePublished', {
-            fromBlock: 'latest'
-        }))[0].returnValues
-
-        assert.equal(log.sender, TokenBridge.address)
-
-        assert.equal(log.payload.length - 2, 266);
-
-        // payload id
-        assert.equal(log.payload.substr(2, 2), "01");
-
-        // amount
-        assert.equal(log.payload.substr(4, 64), web3.eth.abi.encodeParameter("uint256", new BigNumber(amount).div(1e10).toString()).substring(2));
-
-        // token
-        assert.equal(log.payload.substr(68, 64), web3.eth.abi.encodeParameter("address", TokenImplementation.address).substring(2));
-
-        // chain id
-        assert.equal(log.payload.substr(132, 4), web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + 64 - 4))
-
-        // to
-        assert.equal(log.payload.substr(136, 64), "000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e");
-
-        // to chain id
-        assert.equal(log.payload.substr(200, 4), web3.eth.abi.encodeParameter("uint16", 10).substring(2 + 64 - 4))
-
-        // fee
-        assert.equal(log.payload.substr(204, 64), web3.eth.abi.encodeParameter("uint256", new BigNumber(fee).div(1e10).toString()).substring(2))
-    })
-
-    it("should deposit and log fee token transfers correctly", async function () {
-        const accounts = await web3.eth.getAccounts();
-        const mintAmount = "10000000000000000000";
-        const amount = "1000000000000000000";
-        const fee = "100000000000000000";
-
-        // mint and approve tokens
-        const deployFeeToken = await FeeToken.new();
-        const token = new web3.eth.Contract(FeeToken.abi, deployFeeToken.address);
-        await token.methods.initialize(
-            "Test",
-            "TST",
-            "18",
-            "123",
-            accounts[0],
-            "0",
-            "0x0000000000000000000000000000000000000000000000000000000000000000"
-        ).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-        await token.methods.mint(accounts[0], mintAmount).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-        await token.methods.approve(TokenBridge.address, mintAmount).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        // deposit tokens
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-
-        const bridgeBalanceBefore = await token.methods.balanceOf(TokenBridge.address).call();
-
-        assert.equal(bridgeBalanceBefore.toString(10), "0");
-
-        await initialized.methods.transferTokens(
-            deployFeeToken.address,
-            amount,
-            "10",
-            "0x000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e",
-            fee,
-            "234"
-        ).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        const bridgeBalanceAfter = await token.methods.balanceOf(TokenBridge.address).call();
-
-        let feeAmount = new BigNumber(amount).times(9).div(10)
-
-        assert.equal(bridgeBalanceAfter.toString(10), feeAmount);
-
-        // check transfer log
-        const wormhole = new web3.eth.Contract(WormholeImplementationFullABI, Wormhole.address);
-        const log = (await wormhole.getPastEvents('LogMessagePublished', {
-            fromBlock: 'latest'
-        }))[0].returnValues
-
-        assert.equal(log.sender, TokenBridge.address)
-
-        assert.equal(log.payload.length - 2, 266);
-
-        // payload id
-        assert.equal(log.payload.substr(2, 2), "01");
-
-        // amount
-        assert.equal(log.payload.substr(4, 64), web3.eth.abi.encodeParameter("uint256", feeAmount.div(1e10).toString()).substring(2));
-
-        // token
-        assert.equal(log.payload.substr(68, 64), web3.eth.abi.encodeParameter("address", deployFeeToken.address).substring(2));
-
-        // chain id
-        assert.equal(log.payload.substr(132, 4), web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + 64 - 4))
-
-        // to
-        assert.equal(log.payload.substr(136, 64), "000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e");
-
-        // to chain id
-        assert.equal(log.payload.substr(200, 4), web3.eth.abi.encodeParameter("uint16", 10).substring(2 + 64 - 4))
-
-        // fee
-        assert.equal(log.payload.substr(204, 64), web3.eth.abi.encodeParameter("uint256", new BigNumber(fee).div(1e10).toString()).substring(2))
-    })
-
-    it("should transfer out locked assets for a valid transfer vm", async function () {
-        const accounts = await web3.eth.getAccounts();
-        const amount = "1000000000000000000";
-
-        const token = new web3.eth.Contract(TokenImplementation.abi, TokenImplementation.address);
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-
-
-        const accountBalanceBefore = await token.methods.balanceOf(accounts[0]).call();
-        const bridgeBalanceBefore = await token.methods.balanceOf(TokenBridge.address).call();
-
-        assert.equal(accountBalanceBefore.toString(10), "0");
-        assert.equal(bridgeBalanceBefore.toString(10), amount);
-
-        const data = "0x" +
-            "01" +
-            // amount
-            web3.eth.abi.encodeParameter("uint256", new BigNumber(amount).div(1e10).toString()).substring(2) +
-            // tokenaddress
-            web3.eth.abi.encodeParameter("address", TokenImplementation.address).substr(2) +
-            // tokenchain
-            web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4)) +
-            // receiver
-            web3.eth.abi.encodeParameter("address", accounts[0]).substr(2) +
-            // receiving chain
-            web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4)) +
-            // fee
-            "0000000000000000000000000000000000000000000000000000000000000000";
-
-        const vm = await signAndEncodeVM(
-            0,
-            0,
-            testForeignChainId,
-            testForeignBridgeContract,
-            0,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-        await initialized.methods.completeTransfer("0x" + vm).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        const accountBalanceAfter = await token.methods.balanceOf(accounts[0]).call();
-        const bridgeBalanceAfter = await token.methods.balanceOf(TokenBridge.address).call();
-
-        assert.equal(accountBalanceAfter.toString(10), amount);
-        assert.equal(bridgeBalanceAfter.toString(10), "0");
-    })
-
-    it("should mint bridged assets wrappers on transfer from another chain and handle fees correctly", async function () {
-        const accounts = await web3.eth.getAccounts();
-        const amount = "1000000000000000000";
-        const fee = "1000000000000000";
-
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-
-        const wrappedAddress = await initialized.methods.wrappedAsset("0x" + testBridgedAssetChain, "0x" + testBridgedAssetAddress).call();
-        const wrappedAsset = new web3.eth.Contract(TokenImplementation.abi, wrappedAddress);
-
-        const totalSupply = await wrappedAsset.methods.totalSupply().call();
-        assert.equal(totalSupply.toString(10), "0");
-
-        // we are using the asset where we created a wrapper in the previous test
-        const data = "0x" +
-            "01" +
-            // amount
-            web3.eth.abi.encodeParameter("uint256", new BigNumber(amount).div(1e10).toString()).substring(2) +
-            // tokenaddress
-            testBridgedAssetAddress +
-            // tokenchain
-            testBridgedAssetChain +
-            // receiver
-            web3.eth.abi.encodeParameter("address", accounts[0]).substr(2) +
-            // receiving chain
-            web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4)) +
-            // fee
-            web3.eth.abi.encodeParameter("uint256", new BigNumber(fee).div(1e10).toString()).substring(2);
-
-        const vm = await signAndEncodeVM(
-            0,
-            0,
-            testForeignChainId,
-            testForeignBridgeContract,
-            0,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-        await initialized.methods.completeTransfer("0x" + vm).send({
-            value: 0,
-            from: accounts[1],
-            gasLimit: 2000000
-        });
-
-        const accountBalanceAfter = await wrappedAsset.methods.balanceOf(accounts[0]).call();
-        const senderBalanceAfter = await wrappedAsset.methods.balanceOf(accounts[1]).call();
-        const totalSupplyAfter = await wrappedAsset.methods.totalSupply().call();
-
-        assert.equal(accountBalanceAfter.toString(10), new BigNumber(amount).minus(fee).toString(10));
-        assert.equal(senderBalanceAfter.toString(10), fee);
-        assert.equal(totalSupplyAfter.toString(10), amount);
-
-        await wrappedAsset.methods.transfer(accounts[0], fee).send({
-            value: 0,
-            from: accounts[1],
-            gasLimit: 2000000
-        });
-    })
-
-    it("should burn bridged assets wrappers on transfer to another chain", async function () {
-
-        const accounts = await web3.eth.getAccounts();
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-        const amount = "1000000000000000000";
-
-        const wrappedAddress = await initialized.methods.wrappedAsset("0x" + testBridgedAssetChain, "0x" + testBridgedAssetAddress).call();
-        const wrappedAsset = new web3.eth.Contract(TokenImplementation.abi, wrappedAddress);
-
-        await wrappedAsset.methods.approve(TokenBridge.address, amount).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        // deposit tokens
-
-        const accountBalanceBefore = await wrappedAsset.methods.balanceOf(accounts[0]).call();
-
-        assert.equal(accountBalanceBefore.toString(10), amount);
-
-        await initialized.methods.transferTokens(
-            wrappedAddress,
-            amount,
-            "11",
-            "0x000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e",
-            "0",
-            "234"
-        ).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        const accountBalanceAfter = await wrappedAsset.methods.balanceOf(accounts[0]).call();
-        assert.equal(accountBalanceAfter.toString(10), "0");
-
-        const bridgeBalanceAfter = await wrappedAsset.methods.balanceOf(TokenBridge.address).call();
-        assert.equal(bridgeBalanceAfter.toString(10), "0");
-
-        const totalSupplyAfter = await wrappedAsset.methods.totalSupply().call();
-        assert.equal(totalSupplyAfter.toString(10), "0");
-    })
-
-    it("should handle ETH deposits correctly", async function () {
-        const accounts = await web3.eth.getAccounts();
-        const amount = "100000000000000000";
-        const fee = "10000000000000000";
-
-        // mint and approve tokens
-        WETH = (await MockWETH9.new()).address;
-        const token = new web3.eth.Contract(MockWETH9.abi, WETH);
-
-        // set WETH contract
-        const mock = new web3.eth.Contract(MockBridgeImplementation.abi, TokenBridge.address);
-        mock.methods.testUpdateWETHAddress(WETH).send({
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        // deposit tokens
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-
-        const totalWETHSupply = await token.methods.totalSupply().call();
-        const bridgeBalanceBefore = await token.methods.balanceOf(TokenBridge.address).call();
-
-        assert.equal(totalWETHSupply.toString(10), "0");
-        assert.equal(bridgeBalanceBefore.toString(10), "0");
-
-        await initialized.methods.wrapAndTransferETH(
-            "10",
-            "0x000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e",
-            fee,
-            "234"
-        ).send({
-            value: amount,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        const totalWETHSupplyAfter = await token.methods.totalSupply().call();
-        const bridgeBalanceAfter = await token.methods.balanceOf(TokenBridge.address).call();
-
-        assert.equal(totalWETHSupplyAfter.toString(10), amount);
-        assert.equal(bridgeBalanceAfter.toString(10), amount);
-
-        // check transfer log
-        const wormhole = new web3.eth.Contract(WormholeImplementationFullABI, Wormhole.address);
-        const log = (await wormhole.getPastEvents('LogMessagePublished', {
-            fromBlock: 'latest'
-        }))[0].returnValues
-
-        assert.equal(log.sender, TokenBridge.address)
-
-        assert.equal(log.payload.length - 2, 266);
-
-        // payload id
-        assert.equal(log.payload.substr(2, 2), "01");
-
-        // amount
-        assert.equal(log.payload.substr(4, 64), web3.eth.abi.encodeParameter("uint256", new BigNumber(amount).div(1e10).toString()).substring(2));
-
-        // token
-        assert.equal(log.payload.substr(68, 64), web3.eth.abi.encodeParameter("address", WETH).substring(2));
-
-        // chain id
-        assert.equal(log.payload.substr(132, 4), web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + 64 - 4))
-
-        // to
-        assert.equal(log.payload.substr(136, 64), "000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e");
-
-        // to chain id
-        assert.equal(log.payload.substr(200, 4), web3.eth.abi.encodeParameter("uint16", 10).substring(2 + 64 - 4))
-
-        // fee
-        assert.equal(log.payload.substr(204, 64), web3.eth.abi.encodeParameter("uint256", new BigNumber(fee).div(1e10).toString()).substring(2))
-    })
-
-    it("should handle ETH withdrawals and fees correctly", async function () {
-        const accounts = await web3.eth.getAccounts();
-        const amount = "100000000000000000";
-        const fee = "50000000000000000";
-
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-
-        const token = new web3.eth.Contract(MockWETH9.abi, WETH);
-
-        const totalSupply = await token.methods.totalSupply().call();
-        assert.equal(totalSupply.toString(10), amount);
-
-        const feeRecipientBalanceBefore = await web3.eth.getBalance(accounts[0]);
-        const accountBalanceBefore = await web3.eth.getBalance(accounts[1]);
-
-        // we are using the asset where we created a wrapper in the previous test
-        const data = "0x" +
-            "01" +
-            // amount
-            web3.eth.abi.encodeParameter("uint256", new BigNumber(amount).div(1e10).toString()).substring(2) +
-            // tokenaddress
-            web3.eth.abi.encodeParameter("address", WETH).substr(2) +
-            // tokenchain
-            web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4)) +
-            // receiver
-            web3.eth.abi.encodeParameter("address", accounts[1]).substr(2) +
-            // receiving chain
-            web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4)) +
-            // fee
-            web3.eth.abi.encodeParameter("uint256", new BigNumber(fee).div(1e10).toString()).substring(2);
-
-        const vm = await signAndEncodeVM(
-            0,
-            0,
-            testForeignChainId,
-            testForeignBridgeContract,
-            0,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-        const transferTX = await initialized.methods.completeTransferAndUnwrapETH("0x" + vm).send({
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        const totalSupplyAfter = await token.methods.totalSupply().call();
-        assert.equal(totalSupplyAfter.toString(10), "0");
-
-        const accountBalanceAfter = await web3.eth.getBalance(accounts[1]);
-        const feeRecipientBalanceAfter = await web3.eth.getBalance(accounts[0]);
-
-        assert.equal((new BigNumber(accountBalanceAfter)).minus(accountBalanceBefore).toString(10), (new BigNumber(amount)).minus(fee).toString(10))
-        assert.ok((new BigNumber(feeRecipientBalanceAfter)).gt(feeRecipientBalanceBefore))
-    })
-
-    it("should revert on transfer out of a total of > max(uint64) tokens", async function () {
-        const accounts = await web3.eth.getAccounts();
-        const supply = "184467440737095516160000000000";
-        const firstTransfer = "1000000000000";
-
-        // mint and approve tokens
-        const token = new web3.eth.Contract(TokenImplementation.abi, TokenImplementation.address);
-        await token.methods.mint(accounts[0], supply).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-        await token.methods.approve(TokenBridge.address, supply).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        // deposit tokens
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, TokenBridge.address);
-
-        await initialized.methods.transferTokens(
-            TokenImplementation.address,
-            firstTransfer,
-            "10",
-            "0x000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e",
-            "0",
-            "0"
-        ).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        let failed = false;
-        try {
-            await initialized.methods.transferTokens(
-                TokenImplementation.address,
-                new BigNumber(supply).minus(firstTransfer).toString(10),
-                "10",
-                "0x000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e",
-                "0",
-                "0"
-            ).send({
-                value: 0,
-                from: accounts[0],
-                gasLimit: 2000000
-            });
-        } catch (error) {
-            assert.equal(error.message, "Returned error: VM Exception while processing transaction: revert transfer exceeds max outstanding bridged token amount")
-            failed = true
-        }
-
-        assert.ok(failed)
-    })
-});
-
-const signAndEncodeVM = async function (
-    timestamp,
-    nonce,
-    emitterChainId,
-    emitterAddress,
-    sequence,
-    data,
-    signers,
-    guardianSetIndex,
-    consistencyLevel
-) {
-    const body = [
-        web3.eth.abi.encodeParameter("uint32", timestamp).substring(2 + (64 - 8)),
-        web3.eth.abi.encodeParameter("uint32", nonce).substring(2 + (64 - 8)),
-        web3.eth.abi.encodeParameter("uint16", emitterChainId).substring(2 + (64 - 4)),
-        web3.eth.abi.encodeParameter("bytes32", emitterAddress).substring(2),
-        web3.eth.abi.encodeParameter("uint64", sequence).substring(2 + (64 - 16)),
-        web3.eth.abi.encodeParameter("uint8", consistencyLevel).substring(2 + (64 - 2)),
-        data.substr(2)
-    ]
-
-    const hash = web3.utils.soliditySha3(web3.utils.soliditySha3("0x" + body.join("")))
-
-    let signatures = "";
-
-    for (let i in signers) {
-        const ec = new elliptic.ec("secp256k1");
-        const key = ec.keyFromPrivate(signers[i]);
-        const signature = key.sign(hash.substr(2), {canonical: true});
-
-        const packSig = [
-            web3.eth.abi.encodeParameter("uint8", i).substring(2 + (64 - 2)),
-            zeroPadBytes(signature.r.toString(16), 32),
-            zeroPadBytes(signature.s.toString(16), 32),
-            web3.eth.abi.encodeParameter("uint8", signature.recoveryParam).substr(2 + (64 - 2)),
-        ]
-
-        signatures += packSig.join("")
-    }
-
-    const vm = [
-        web3.eth.abi.encodeParameter("uint8", 1).substring(2 + (64 - 2)),
-        web3.eth.abi.encodeParameter("uint32", guardianSetIndex).substring(2 + (64 - 8)),
-        web3.eth.abi.encodeParameter("uint8", signers.length).substring(2 + (64 - 2)),
-
-        signatures,
-        body.join("")
-    ].join("");
-
-    return vm
-}
-
-function zeroPadBytes(value, length) {
-    while (value.length < 2 * length) {
-        value = "0" + value;
-    }
-    return value;
-}

+ 0 - 653
ethereum/test/nft.js

@@ -1,653 +0,0 @@
-const jsonfile = require('jsonfile');
-const elliptic = require('elliptic');
-const BigNumber = require('bignumber.js');
-
-const Wormhole = artifacts.require("Wormhole");
-const NFTBridge = artifacts.require("NFTBridgeEntrypoint");
-const NFTBridgeImplementation = artifacts.require("NFTBridgeImplementation");
-const NFTImplementation = artifacts.require("NFTImplementation");
-const MockBridgeImplementation = artifacts.require("MockNFTBridgeImplementation");
-
-const testSigner1PK = "cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0";
-const testSigner2PK = "892330666a850761e7370376430bb8c2aa1494072d3bfeaed0c4fa3d5a9135fe";
-
-const WormholeImplementationFullABI = jsonfile.readFileSync("build/contracts/Implementation.json").abi
-const BridgeImplementationFullABI = jsonfile.readFileSync("build/contracts/NFTBridgeImplementation.json").abi
-const NFTImplementationFullABI = jsonfile.readFileSync("build/contracts/NFTImplementation.json").abi
-
-contract("NFT", function () {
-    const testSigner1 = web3.eth.accounts.privateKeyToAccount(testSigner1PK);
-    const testSigner2 = web3.eth.accounts.privateKeyToAccount(testSigner2PK);
-    const testChainId = "2";
-    const testGovernanceChainId = "1";
-    const testGovernanceContract = "0x0000000000000000000000000000000000000000000000000000000000000004";
-    let WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
-    const testForeignChainId = "1";
-    const testForeignBridgeContract = "0x000000000000000000000000000000000000000000000000000000000000ffff";
-    const testBridgedAssetChain = "0003";
-    const testBridgedAssetAddress = "000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e";
-
-
-    it("should be initialized with the correct signers and values", async function () {
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, NFTBridge.address);
-
-        const tokenImplentation = await initialized.methods.tokenImplementation().call();
-        assert.equal(tokenImplentation, NFTImplementation.address);
-
-        // test beacon functionality
-        const beaconImplementation = await initialized.methods.implementation().call();
-        assert.equal(beaconImplementation, NFTImplementation.address);
-
-        // chain id
-        const chainId = await initialized.methods.chainId().call();
-        assert.equal(chainId, testChainId);
-
-        // governance
-        const governanceChainId = await initialized.methods.governanceChainId().call();
-        assert.equal(governanceChainId, testGovernanceChainId);
-        const governanceContract = await initialized.methods.governanceContract().call();
-        assert.equal(governanceContract, testGovernanceContract);
-    })
-
-    it("should register a foreign bridge implementation correctly", async function () {
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, NFTBridge.address);
-        const accounts = await web3.eth.getAccounts();
-
-        let data = [
-            "0x",
-            "00000000000000000000000000000000000000000000004e4654427269646765",
-            "01",
-            "0000",
-            web3.eth.abi.encodeParameter("uint16", testForeignChainId).substring(2 + (64 - 4)),
-            web3.eth.abi.encodeParameter("bytes32", testForeignBridgeContract).substring(2),
-        ].join('')
-
-        const vm = await signAndEncodeVM(
-            1,
-            1,
-            testGovernanceChainId,
-            testGovernanceContract,
-            0,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-
-        let before = await initialized.methods.bridgeContracts(testForeignChainId).call();
-
-        assert.equal(before, "0x0000000000000000000000000000000000000000000000000000000000000000");
-
-        await initialized.methods.registerChain("0x" + vm).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        let after = await initialized.methods.bridgeContracts(testForeignChainId).call();
-
-        assert.equal(after, testForeignBridgeContract);
-    })
-
-    it("should accept a valid upgrade", async function () {
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, NFTBridge.address);
-        const accounts = await web3.eth.getAccounts();
-
-        const mock = await MockBridgeImplementation.new();
-
-        let data = [
-            "0x",
-            "00000000000000000000000000000000000000000000004e4654427269646765",
-            "02",
-            web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4)),
-            web3.eth.abi.encodeParameter("address", mock.address).substring(2),
-        ].join('')
-
-        const vm = await signAndEncodeVM(
-            1,
-            1,
-            testGovernanceChainId,
-            testGovernanceContract,
-            0,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-        let before = await web3.eth.getStorageAt(NFTBridge.address, "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc");
-
-        assert.equal(before.toLowerCase(), NFTBridgeImplementation.address.toLowerCase());
-
-        await initialized.methods.upgrade("0x" + vm).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        let after = await web3.eth.getStorageAt(NFTBridge.address, "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc");
-
-        assert.equal(after.toLowerCase(), mock.address.toLowerCase());
-
-        const mockImpl = new web3.eth.Contract(MockBridgeImplementation.abi, NFTBridge.address);
-
-        let isUpgraded = await mockImpl.methods.testNewImplementationActive().call();
-
-        assert.ok(isUpgraded);
-    })
-
-    it("bridged tokens should only be mint- and burn-able by owner", async function () {
-        const accounts = await web3.eth.getAccounts();
-
-        // initialize our template token contract
-        const token = new web3.eth.Contract(NFTImplementation.abi, NFTImplementation.address);
-
-        await token.methods.initialize(
-            "TestToken",
-            "TT",
-            accounts[0],
-
-            0,
-            "0x0"
-        ).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        await token.methods.mint(accounts[0], 10, "").send({
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        let failed = false
-        try {
-            await token.methods.mint(accounts[0], 11, "").send({
-                from: accounts[1],
-                gasLimit: 2000000
-            });
-        } catch (e) {
-            failed = true
-        }
-        assert.ok(failed)
-
-        failed = false
-        try {
-            await token.methods.burn(10).send({
-                from: accounts[1],
-                gasLimit: 2000000
-            });
-        } catch (e) {
-            failed = true
-        }
-        assert.ok(failed)
-
-        await token.methods.burn(10).send({
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-    })
-
-    it("should deposit and log transfers correctly", async function () {
-        const accounts = await web3.eth.getAccounts();
-        const tokenId = "1000000000000000000";
-
-        // mint and approve tokens
-        const token = new web3.eth.Contract(NFTImplementation.abi, NFTImplementation.address);
-        await token.methods.mint(accounts[0], tokenId, "abcd").send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-        await token.methods.approve(NFTBridge.address, tokenId).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        // deposit tokens
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, NFTBridge.address);
-
-        const ownerBefore = await token.methods.ownerOf(tokenId).call();
-        assert.equal(ownerBefore, accounts[0]);
-        await initialized.methods.transferNFT(
-            NFTImplementation.address,
-            tokenId,
-            "10",
-            "0x000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e",
-            "234"
-        ).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        const ownerAfter = await token.methods.ownerOf(tokenId).call();
-        assert.equal(ownerAfter, NFTBridge.address);
-
-        // check transfer log
-        const wormhole = new web3.eth.Contract(WormholeImplementationFullABI, Wormhole.address);
-        const log = (await wormhole.getPastEvents('LogMessagePublished', {
-            fromBlock: 'latest'
-        }))[0].returnValues
-
-        assert.equal(log.sender, NFTBridge.address)
-
-        assert.equal(log.payload.length - 2, 340);
-
-        // payload id
-        assert.equal(log.payload.substr(2, 2), "01");
-
-        // token
-        assert.equal(log.payload.substr(4, 64), web3.eth.abi.encodeParameter("address", NFTImplementation.address).substring(2));
-
-        // chain id
-        assert.equal(log.payload.substr(68, 4), web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + 64 - 4))
-
-        // symbol (TT)
-        assert.equal(log.payload.substr(72, 64), "5454000000000000000000000000000000000000000000000000000000000000")
-
-        // name (TestToken (Wormhole))
-        assert.equal(log.payload.substr(136, 64), "54657374546f6b656e0000000000000000000000000000000000000000000000")
-
-        // tokenID
-        assert.equal(log.payload.substr(200, 64), web3.eth.abi.encodeParameter("uint256", new BigNumber(tokenId).toString()).substring(2));
-
-        // url length
-        assert.equal(log.payload.substr(264, 2), web3.eth.abi.encodeParameter("uint8", 4).substring(2 + 64 - 2))
-
-        // url
-        assert.equal(log.payload.substr(266, 8), "61626364")
-
-        // to
-        assert.equal(log.payload.substr(274, 64), "000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e");
-
-        // to chain id
-        assert.equal(log.payload.substr(338, 4), web3.eth.abi.encodeParameter("uint16", 10).substring(2 + 64 - 4))
-    })
-
-    it("should transfer out locked assets for a valid transfer vm", async function () {
-        const accounts = await web3.eth.getAccounts();
-        const tokenId = "1000000000000000000";
-
-        const token = new web3.eth.Contract(NFTImplementation.abi, NFTImplementation.address);
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, NFTBridge.address);
-
-        const ownerBefore = await token.methods.ownerOf(tokenId).call();
-        assert.equal(ownerBefore, NFTBridge.address);
-
-        // PayloadID uint8 = 1
-        // // Address of the NFT. Left-zero-padded if shorter than 32 bytes
-        // NFTAddress [32]uint8
-        // // Chain ID of the NFT
-        // NFTChain uint16
-        // // Name of the NFT
-        // Name [32]uint8
-        // // Symbol of the NFT
-        // Symbol [10]uint8
-        // // ID of the token (big-endian uint256)
-        // TokenID [32]uint8
-        // // URL of the NFT
-        // URLLength u8
-        // URL [n]uint8
-        // // Address of the recipient. Left-zero-padded if shorter than 32 bytes
-        // To [32]uint8
-        // // Chain ID of the recipient
-        // ToChain uint16
-        const data = "0x" +
-            "01" +
-            // tokenaddress
-            web3.eth.abi.encodeParameter("address", NFTImplementation.address).substr(2) +
-            // tokenchain
-            web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4)) +
-            // symbol
-            "0000000000000000000000000000000000000000000000000000000000000000" +
-            // name
-            "0000000000000000000000000000000000000000000000000000000000000000" +
-            // tokenID
-            web3.eth.abi.encodeParameter("uint256", new BigNumber(tokenId).toString()).substring(2) +
-            // url length
-            "00" +
-            // no URL
-            "" +
-            // receiver
-            web3.eth.abi.encodeParameter("address", accounts[0]).substr(2) +
-            // receiving chain
-            web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4));
-
-        const vm = await signAndEncodeVM(
-            0,
-            0,
-            testForeignChainId,
-            testForeignBridgeContract,
-            0,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-        await initialized.methods.completeTransfer("0x" + vm).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        const ownerAfter = await token.methods.ownerOf(tokenId).call();
-        assert.equal(ownerAfter, accounts[0]);
-    })
-
-    it("should mint bridged assets wrappers on transfer from another chain and handle fees correctly", async function () {
-        const accounts = await web3.eth.getAccounts();
-        let tokenId = "1000000000000000001";
-
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, NFTBridge.address);
-
-        // we are using the asset where we created a wrapper in the previous test
-        let data = "0x" +
-            "01" +
-            // tokenaddress
-            testBridgedAssetAddress +
-            // tokenchain
-            testBridgedAssetChain +
-            // symbol
-            "464f520000000000000000000000000000000000000000000000000000000000" +
-            // name
-            "466f726569676e20436861696e204e4654000000000000000000000000000000" +
-            // tokenID
-            web3.eth.abi.encodeParameter("uint256", new BigNumber(tokenId).toString()).substring(2) +
-            // url length
-            "00" +
-            // no URL
-            "" +
-            // receiver
-            web3.eth.abi.encodeParameter("address", accounts[0]).substr(2) +
-            // receiving chain
-            web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4));
-
-        let vm = await signAndEncodeVM(
-            0,
-            0,
-            testForeignChainId,
-            testForeignBridgeContract,
-            0,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-        await initialized.methods.completeTransfer("0x" + vm).send({
-            value: 0,
-            from: accounts[1],
-            gasLimit: 2000000
-        });
-
-        const wrappedAddress = await initialized.methods.wrappedAsset("0x" + testBridgedAssetChain, "0x" + testBridgedAssetAddress).call();
-        assert.ok(await initialized.methods.isWrappedAsset(wrappedAddress).call())
-        const wrappedAsset = new web3.eth.Contract(NFTImplementation.abi, wrappedAddress);
-
-        let ownerAfter = await wrappedAsset.methods.ownerOf(tokenId).call();
-        assert.equal(ownerAfter, accounts[0]);
-
-        const symbol = await wrappedAsset.methods.symbol().call();
-        assert.equal(symbol, "FOR");
-
-        const name = await wrappedAsset.methods.name().call();
-        assert.equal(name, "Foreign Chain NFT");
-
-        const chainId = await wrappedAsset.methods.chainId().call();
-        assert.equal(chainId, Number(testBridgedAssetChain));
-
-        const nativeContract = await wrappedAsset.methods.nativeContract().call();
-        assert.equal(nativeContract, "0x000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e");
-
-        // Transfer another tokenID of the same token address
-        tokenId = "1000000000000000002"
-        data = "0x" +
-            "01" +
-            // tokenaddress
-            testBridgedAssetAddress +
-            // tokenchain
-            testBridgedAssetChain +
-            // symbol
-            "464f520000000000000000000000000000000000000000000000000000000000" +
-            // name
-            "466f726569676e20436861696e204e4654000000000000000000000000000000" +
-            // tokenID
-            web3.eth.abi.encodeParameter("uint256", new BigNumber(tokenId + 1).toString()).substring(2) +
-            // url length
-            "00" +
-            // no URL
-            "" +
-            // receiver
-            web3.eth.abi.encodeParameter("address", accounts[0]).substr(2) +
-            // receiving chain
-            web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4));
-
-        vm = await signAndEncodeVM(
-            0,
-            0,
-            testForeignChainId,
-            testForeignBridgeContract,
-            1,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-        await initialized.methods.completeTransfer("0x" + vm).send({
-            value: 0,
-            from: accounts[1],
-            gasLimit: 2000000
-        });
-
-        ownerAfter = await wrappedAsset.methods.ownerOf(tokenId + 1).call();
-        assert.equal(ownerAfter, accounts[0]);
-    })
-
-    it("should mint bridged assets from solana under unified name, caching the original", async function () {
-        const accounts = await web3.eth.getAccounts();
-        let tokenId = "1000000000000000001";
-
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, NFTBridge.address);
-
-        // we are using the asset where we created a wrapper in the previous test
-        let data = "0x" +
-            "01" +
-            // tokenaddress
-            testBridgedAssetAddress +
-            // tokenchain
-            "0001" +
-            // symbol
-            "464f520000000000000000000000000000000000000000000000000000000000" +
-            // name
-            "466f726569676e20436861696e204e4654000000000000000000000000000000" +
-            // tokenID
-            web3.eth.abi.encodeParameter("uint256", new BigNumber(tokenId).toString()).substring(2) +
-            // url length
-            "00" +
-            // no URL
-            "" +
-            // receiver
-            web3.eth.abi.encodeParameter("address", accounts[0]).substr(2) +
-            // receiving chain
-            web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4));
-
-        let vm = await signAndEncodeVM(
-            0,
-            0,
-            testForeignChainId,
-            testForeignBridgeContract,
-            0,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-        await initialized.methods.completeTransfer("0x" + vm).send({
-            value: 0,
-            from: accounts[1],
-            gasLimit: 2000000
-        });
-
-        const cache = await initialized.methods.splCache(tokenId).call()
-        assert.equal(cache.symbol, "0x464f520000000000000000000000000000000000000000000000000000000000");
-        assert.equal(cache.name, "0x466f726569676e20436861696e204e4654000000000000000000000000000000");
-
-        const wrappedAddress = await initialized.methods.wrappedAsset("0x0001", "0x" + testBridgedAssetAddress).call();
-        const wrappedAsset = new web3.eth.Contract(NFTImplementation.abi, wrappedAddress);
-
-        const symbol = await wrappedAsset.methods.symbol().call();
-        assert.equal(symbol, "WORMSPLNFT");
-
-        const name = await wrappedAsset.methods.name().call();
-        assert.equal(name, "Wormhole Bridged Solana-NFT");
-    })
-
-    it("cached SPL names are loaded when transferring out, cache is cleared", async function () {
-        const accounts = await web3.eth.getAccounts();
-        let tokenId = "1000000000000000001";
-
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, NFTBridge.address);
-
-        const wrappedAddress = await initialized.methods.wrappedAsset("0x0001", "0x" + testBridgedAssetAddress).call();
-
-        const transfer =         await initialized.methods.transferNFT(
-            wrappedAddress,
-            tokenId,
-            "10",
-            "0x000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e",
-            "2345"
-        ).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        // symbol
-        assert.ok(transfer.events[2].raw.data.includes('464f520000000000000000000000000000000000000000000000000000000000'))
-        // name
-        assert.ok(transfer.events[2].raw.data.includes('466f726569676e20436861696e204e4654000000000000000000000000000000'))
-
-        // check if cache is cleared
-        const cache = await initialized.methods.splCache(tokenId).call()
-        assert.equal(cache.symbol, "0x0000000000000000000000000000000000000000000000000000000000000000");
-        assert.equal(cache.name, "0x0000000000000000000000000000000000000000000000000000000000000000");
-    })
-
-    it("should burn bridged assets wrappers on transfer to another chain", async function () {
-
-        const accounts = await web3.eth.getAccounts();
-        const initialized = new web3.eth.Contract(BridgeImplementationFullABI, NFTBridge.address);
-        const tokenId = "1000000000000000001";
-
-        const wrappedAddress = await initialized.methods.wrappedAsset("0x" + testBridgedAssetChain, "0x" + testBridgedAssetAddress).call();
-        const wrappedAsset = new web3.eth.Contract(NFTImplementation.abi, wrappedAddress);
-
-        await wrappedAsset.methods.approve(NFTBridge.address, tokenId).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        // deposit tokens
-
-        const ownerBefore = await wrappedAsset.methods.ownerOf(tokenId).call();
-
-        assert.equal(ownerBefore, accounts[0]);
-
-        await initialized.methods.transferNFT(
-            wrappedAddress,
-            tokenId,
-            "10",
-            "0x000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e",
-            "234"
-        ).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        try {
-            await wrappedAsset.methods.ownerOf(tokenId).call();
-            assert.fail("burned token still exists")
-        } catch (e) {
-            assert.equal(e.data[Object.keys(e.data)[0]].reason, "ERC721: owner query for nonexistent token")
-        }
-    })
-});
-
-const signAndEncodeVM = async function (
-    timestamp,
-    nonce,
-    emitterChainId,
-    emitterAddress,
-    sequence,
-    data,
-    signers,
-    guardianSetIndex,
-    consistencyLevel
-) {
-    const body = [
-        web3.eth.abi.encodeParameter("uint32", timestamp).substring(2 + (64 - 8)),
-        web3.eth.abi.encodeParameter("uint32", nonce).substring(2 + (64 - 8)),
-        web3.eth.abi.encodeParameter("uint16", emitterChainId).substring(2 + (64 - 4)),
-        web3.eth.abi.encodeParameter("bytes32", emitterAddress).substring(2),
-        web3.eth.abi.encodeParameter("uint64", sequence).substring(2 + (64 - 16)),
-        web3.eth.abi.encodeParameter("uint8", consistencyLevel).substring(2 + (64 - 2)),
-        data.substr(2)
-    ]
-
-    const hash = web3.utils.soliditySha3(web3.utils.soliditySha3("0x" + body.join("")))
-
-    let signatures = "";
-
-    for (let i in signers) {
-        const ec = new elliptic.ec("secp256k1");
-        const key = ec.keyFromPrivate(signers[i]);
-        const signature = key.sign(hash.substr(2), {canonical: true});
-
-        const packSig = [
-            web3.eth.abi.encodeParameter("uint8", i).substring(2 + (64 - 2)),
-            zeroPadBytes(signature.r.toString(16), 32),
-            zeroPadBytes(signature.s.toString(16), 32),
-            web3.eth.abi.encodeParameter("uint8", signature.recoveryParam).substr(2 + (64 - 2)),
-        ]
-
-        signatures += packSig.join("")
-    }
-
-    const vm = [
-        web3.eth.abi.encodeParameter("uint8", 1).substring(2 + (64 - 2)),
-        web3.eth.abi.encodeParameter("uint32", guardianSetIndex).substring(2 + (64 - 8)),
-        web3.eth.abi.encodeParameter("uint8", signers.length).substring(2 + (64 - 2)),
-
-        signatures,
-        body.join("")
-    ].join("");
-
-    return vm
-}
-
-function zeroPadBytes(value, length) {
-    while (value.length < 2 * length) {
-        value = "0" + value;
-    }
-    return value;
-}

+ 0 - 87
ethereum/test/tokenmigrator.js

@@ -1,87 +0,0 @@
-const jsonfile = require('jsonfile');
-const BigNumber = require('bignumber.js');
-
-const Migrator = artifacts.require("Migrator");
-const TokenImplementation = artifacts.require("TokenImplementation");
-
-contract("Migrator", function (accounts) {
-    var migrator,
-        fromToken,
-        toToken,
-        fromDecimals = 8,
-        toDecimals = 18;
-
-    it("should deploy with the correct values", async function () {
-        fromToken = await TokenImplementation.new();
-        await fromToken.initialize(
-            "TestFrom",
-            "FROM",
-            fromDecimals,
-            0,
-            accounts[0],
-            0,
-            "0x00"
-        )
-        toToken = await TokenImplementation.new();
-        await toToken.initialize(
-            "TestTo",
-            "TO",
-            toDecimals,
-            0,
-            accounts[0],
-            0,
-            "0x00"
-        )
-
-        migrator = await Migrator.new(
-            fromToken.address,
-            toToken.address,
-        );
-
-        assert.equal(await migrator.fromAsset(), fromToken.address)
-        assert.equal(await migrator.toAsset(), toToken.address)
-        assert.equal((await migrator.fromDecimals()).toNumber(), fromDecimals)
-        assert.equal((await migrator.toDecimals()).toNumber(), toDecimals)
-    })
-
-    it("should give out LP tokens 1:1 for a toToken deposit", async function () {
-        await toToken.mint(accounts[0], "1000000000000000000")
-        await toToken.approve(migrator.address, "1000000000000000000")
-        await migrator.add("1000000000000000000")
-
-
-        assert.equal((await toToken.balanceOf(migrator.address)).toString(), "1000000000000000000")
-        assert.equal((await migrator.balanceOf(accounts[0])).toString(), "1000000000000000000")
-    })
-
-    it("should refund toToken for LP tokens", async function () {
-        await migrator.remove("500000000000000000")
-
-        assert.equal((await toToken.balanceOf(migrator.address)).toString(), "500000000000000000")
-        assert.equal((await toToken.balanceOf(accounts[0])).toString(), "500000000000000000")
-        assert.equal((await migrator.balanceOf(accounts[0])).toString(), "500000000000000000")
-    })
-
-    it("should redeem fromToken to toToken adjusting for decimals", async function () {
-        await fromToken.mint(accounts[1], "50000000")
-        await fromToken.approve(migrator.address, "50000000", {
-            from : accounts[1]
-        })
-        await migrator.migrate("50000000", {
-            from : accounts[1]
-        })
-
-        assert.equal((await toToken.balanceOf(accounts[1])).toString(), "500000000000000000")
-        assert.equal((await fromToken.balanceOf(accounts[1])).toString(), "0")
-        assert.equal((await fromToken.balanceOf(migrator.address)).toString(), "50000000")
-        assert.equal((await toToken.balanceOf(migrator.address)).toString(), "0")
-    })
-
-    it("fromToken should be claimable for LP tokens, adjusting for decimals", async function () {
-        await migrator.claim("500000000000000000")
-
-        assert.equal((await fromToken.balanceOf(migrator.address)).toString(), "0")
-        assert.equal((await fromToken.balanceOf(accounts[0])).toString(), "50000000")
-        assert.equal((await migrator.balanceOf(accounts[0])).toString(), "0")
-    })
-})

+ 0 - 413
ethereum/test/upgrades/01_tokenbridge_feetoken_support.js

@@ -1,413 +0,0 @@
-const jsonfile = require('jsonfile');
-const elliptic = require('elliptic');
-const BigNumber = require('bignumber.js');
-
-const Wormhole = artifacts.require("Wormhole");
-const TokenBridge = artifacts.require("TokenBridge");
-const BridgeSetup = artifacts.require("BridgeSetup");
-const BridgeImplementation = artifacts.require("BridgeImplementation");
-const MockBridgeImplementation = artifacts.require("MockBridgeImplementation");
-const TokenImplementation = artifacts.require("TokenImplementation");
-const FeeToken = artifacts.require("FeeToken");
-
-const testSigner1PK = "cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0";
-
-const WormholeImplementationFullABI = jsonfile.readFileSync("build/contracts/Implementation.json").abi
-const BridgeImplementationFullABI = jsonfile.readFileSync("build/contracts/BridgeImplementation.json").abi
-
-// needs to run on a mainnet fork
-
-contract("Update Bridge", function (accounts) {
-    const testChainId = "2";
-    const testGovernanceChainId = "1";
-    const testGovernanceContract = "0x0000000000000000000000000000000000000000000000000000000000000004";
-    let WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
-    const testForeignChainId = "1";
-    const testForeignBridgeContract = "0x000000000000000000000000000000000000000000000000000000000000ffff";
-
-    const currentImplementation = "0x6c4c12987303b2c94b2C76c612Fc5F4D2F0360F7";
-    let bridgeProxy;
-
-    it("create bridge instance with current implementation", async function () {
-        // encode initialisation data
-        const setup = new web3.eth.Contract(BridgeSetup.abi, BridgeSetup.address);
-        const initData = setup.methods.setup(
-            currentImplementation,
-            testChainId,
-            (await Wormhole.deployed()).address,
-            testGovernanceChainId,
-            testGovernanceContract,
-            TokenImplementation.address,
-            WETH
-        ).encodeABI();
-
-        const deploy = await TokenBridge.new(BridgeSetup.address, initData);
-
-        bridgeProxy = new web3.eth.Contract(BridgeImplementationFullABI, deploy.address);
-    })
-
-    it("register a foreign bridge implementation", async function () {
-        let data = [
-            "0x",
-            "000000000000000000000000000000000000000000546f6b656e427269646765",
-            "01",
-            "0000",
-            web3.eth.abi.encodeParameter("uint16", testForeignChainId).substring(2 + (64 - 4)),
-            web3.eth.abi.encodeParameter("bytes32", testForeignBridgeContract).substring(2),
-        ].join('')
-
-        const vm = await signAndEncodeVM(
-            1,
-            1,
-            testGovernanceChainId,
-            testGovernanceContract,
-            0,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-
-        let before = await bridgeProxy.methods.bridgeContracts(testForeignChainId).call();
-
-        assert.equal(before, "0x0000000000000000000000000000000000000000000000000000000000000000");
-
-        await bridgeProxy.methods.registerChain("0x" + vm).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        let after = await bridgeProxy.methods.bridgeContracts(testForeignChainId).call();
-
-        assert.equal(after, testForeignBridgeContract);
-    })
-
-    it("mimic previous deposits (deposit some ETH)", async function () {
-        const amount = "100000000000000000";
-        const fee = "10000000000000000";
-
-        await bridgeProxy.methods.wrapAndTransferETH(
-            "10",
-            "0x000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e",
-            fee,
-            "234"
-        ).send({
-            value: amount,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        // check transfer log
-        const wormhole = new web3.eth.Contract(WormholeImplementationFullABI, Wormhole.address);
-        const log = (await wormhole.getPastEvents('LogMessagePublished', {
-            fromBlock: 'latest'
-        }))[0].returnValues
-
-        assert.equal(log.payload.length - 2, 266);
-
-        // payload id
-        assert.equal(log.payload.substr(2, 2), "01");
-
-        // amount
-        assert.equal(log.payload.substr(4, 64), web3.eth.abi.encodeParameter("uint256", new BigNumber(amount).div(1e10).toString()).substring(2));
-
-        // token
-        assert.equal(log.payload.substr(68, 64), web3.eth.abi.encodeParameter("address", WETH).substring(2));
-
-        // chain id
-        assert.equal(log.payload.substr(132, 4), web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + 64 - 4))
-
-        // to
-        assert.equal(log.payload.substr(136, 64), "000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e");
-
-        // to chain id
-        assert.equal(log.payload.substr(200, 4), web3.eth.abi.encodeParameter("uint16", 10).substring(2 + 64 - 4))
-
-        // fee
-        assert.equal(log.payload.substr(204, 64), web3.eth.abi.encodeParameter("uint256", new BigNumber(fee).div(1e10).toString()).substring(2))
-    })
-
-    let upgradeDeployedAt;
-    it("apply upgrade", async function () {
-        const deploy = await BridgeImplementation.new();
-        upgradeDeployedAt = deploy.address;
-
-        let data = [
-            "0x",
-            "000000000000000000000000000000000000000000546f6b656e427269646765",
-            "02",
-            web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4)),
-            web3.eth.abi.encodeParameter("address", deploy.address).substring(2),
-        ].join('')
-
-        const vm = await signAndEncodeVM(
-            1,
-            1,
-            testGovernanceChainId,
-            testGovernanceContract,
-            0,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-        let before = await web3.eth.getStorageAt(bridgeProxy.options.address, "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc");
-
-        assert.equal(before.toLowerCase(), currentImplementation.toLowerCase());
-
-        await bridgeProxy.methods.upgrade("0x" + vm).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        let after = await web3.eth.getStorageAt(bridgeProxy.options.address, "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc");
-
-        assert.equal(after.toLowerCase(), deploy.address.toLowerCase());
-    })
-
-    it("test withdrawing existing assets (deposited ETH)", async function () {
-        const amount = "100000000000000000";
-
-        const accountBalanceBefore = await web3.eth.getBalance(accounts[1]);
-
-        // we are using the asset where we created a wrapper in the previous test
-        const data = "0x" +
-            "01" +
-            // amount
-            web3.eth.abi.encodeParameter("uint256", new BigNumber(amount).div(1e10).toString()).substring(2) +
-            // tokenaddress
-            web3.eth.abi.encodeParameter("address", WETH).substr(2) +
-            // tokenchain
-            web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4)) +
-            // receiver
-            web3.eth.abi.encodeParameter("address", accounts[1]).substr(2) +
-            // receiving chain
-            web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4)) +
-            // fee
-            web3.eth.abi.encodeParameter("uint256", 0).substring(2);
-
-        const vm = await signAndEncodeVM(
-            0,
-            0,
-            testForeignChainId,
-            testForeignBridgeContract,
-            0,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-        const transferTX = await bridgeProxy.methods.completeTransferAndUnwrapETH("0x" + vm).send({
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        const accountBalanceAfter = await web3.eth.getBalance(accounts[1]);
-
-        assert.equal((new BigNumber(accountBalanceAfter)).minus(accountBalanceBefore).toString(10), (new BigNumber(amount)).toString(10))
-    })
-
-    it("test new functionality (fee token transfers)", async function () {
-        const accounts = await web3.eth.getAccounts();
-        const mintAmount = "10000000000000000000";
-        const amount = "1000000000000000000";
-        const fee = "100000000000000000";
-
-        // mint and approve tokens
-        const deployFeeToken = await FeeToken.new();
-        const token = new web3.eth.Contract(FeeToken.abi, deployFeeToken.address);
-        await token.methods.initialize(
-            "Test",
-            "TST",
-            "18",
-            "123",
-            accounts[0],
-            "0",
-            "0x0000000000000000000000000000000000000000000000000000000000000000"
-        ).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-        await token.methods.mint(accounts[0], mintAmount).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-        await token.methods.approve(bridgeProxy.options.address, mintAmount).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        const bridgeBalanceBefore = await token.methods.balanceOf(bridgeProxy.options.address).call();
-
-        assert.equal(bridgeBalanceBefore.toString(10), "0");
-
-        await bridgeProxy.methods.transferTokens(
-            deployFeeToken.address,
-            amount,
-            "10",
-            "0x000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e",
-            fee,
-            "234"
-        ).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        const bridgeBalanceAfter = await token.methods.balanceOf(bridgeProxy.options.address).call();
-
-        let feeAmount = new BigNumber(amount).times(9).div(10)
-
-        assert.equal(bridgeBalanceAfter.toString(10), feeAmount);
-
-        // check transfer log
-        const wormhole = new web3.eth.Contract(WormholeImplementationFullABI, Wormhole.address);
-        const log = (await wormhole.getPastEvents('LogMessagePublished', {
-            fromBlock: 'latest'
-        }))[0].returnValues
-
-        assert.equal(log.sender, bridgeProxy.options.address)
-
-        assert.equal(log.payload.length - 2, 266);
-
-        // payload id
-        assert.equal(log.payload.substr(2, 2), "01");
-
-        // amount
-        assert.equal(log.payload.substr(4, 64), web3.eth.abi.encodeParameter("uint256", feeAmount.div(1e10).toString()).substring(2));
-
-        // token
-        assert.equal(log.payload.substr(68, 64), web3.eth.abi.encodeParameter("address", deployFeeToken.address).substring(2));
-
-        // chain id
-        assert.equal(log.payload.substr(132, 4), web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + 64 - 4))
-
-        // to
-        assert.equal(log.payload.substr(136, 64), "000000000000000000000000b7a2211e8165943192ad04f5dd21bedc29ff003e");
-
-        // to chain id
-        assert.equal(log.payload.substr(200, 4), web3.eth.abi.encodeParameter("uint16", 10).substring(2 + 64 - 4))
-
-        // fee
-        assert.equal(log.payload.substr(204, 64), web3.eth.abi.encodeParameter("uint256", new BigNumber(fee).div(1e10).toString()).substring(2))
-    })
-
-    it("should accept a further upgrade", async function () {
-        const mock = await MockBridgeImplementation.new();
-
-        let data = [
-            "0x",
-            "000000000000000000000000000000000000000000546f6b656e427269646765",
-            "02",
-            web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4)),
-            web3.eth.abi.encodeParameter("address", mock.address).substring(2),
-        ].join('')
-
-        const vm = await signAndEncodeVM(
-            1,
-            1,
-            testGovernanceChainId,
-            testGovernanceContract,
-            0,
-            data,
-            [
-                testSigner1PK
-            ],
-            0,
-            0
-        );
-
-        let before = await web3.eth.getStorageAt(bridgeProxy.options.address, "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc");
-
-        assert.equal(before.toLowerCase(), upgradeDeployedAt.toLowerCase());
-
-        await bridgeProxy.methods.upgrade("0x" + vm).send({
-            value: 0,
-            from: accounts[0],
-            gasLimit: 2000000
-        });
-
-        let after = await web3.eth.getStorageAt(bridgeProxy.options.address, "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc");
-
-        assert.equal(after.toLowerCase(), mock.address.toLowerCase());
-
-        const mockImpl = new web3.eth.Contract(MockBridgeImplementation.abi, bridgeProxy.options.address);
-
-        let isUpgraded = await mockImpl.methods.testNewImplementationActive().call();
-
-        assert.ok(isUpgraded);
-    })
-});
-
-const signAndEncodeVM = async function (
-    timestamp,
-    nonce,
-    emitterChainId,
-    emitterAddress,
-    sequence,
-    data,
-    signers,
-    guardianSetIndex,
-    consistencyLevel
-) {
-    const body = [
-        web3.eth.abi.encodeParameter("uint32", timestamp).substring(2 + (64 - 8)),
-        web3.eth.abi.encodeParameter("uint32", nonce).substring(2 + (64 - 8)),
-        web3.eth.abi.encodeParameter("uint16", emitterChainId).substring(2 + (64 - 4)),
-        web3.eth.abi.encodeParameter("bytes32", emitterAddress).substring(2),
-        web3.eth.abi.encodeParameter("uint64", sequence).substring(2 + (64 - 16)),
-        web3.eth.abi.encodeParameter("uint8", consistencyLevel).substring(2 + (64 - 2)),
-        data.substr(2)
-    ]
-
-    const hash = web3.utils.soliditySha3(web3.utils.soliditySha3("0x" + body.join("")))
-
-    let signatures = "";
-
-    for (let i in signers) {
-        const ec = new elliptic.ec("secp256k1");
-        const key = ec.keyFromPrivate(signers[i]);
-        const signature = key.sign(hash.substr(2), {canonical: true});
-
-        const packSig = [
-            web3.eth.abi.encodeParameter("uint8", i).substring(2 + (64 - 2)),
-            zeroPadBytes(signature.r.toString(16), 32),
-            zeroPadBytes(signature.s.toString(16), 32),
-            web3.eth.abi.encodeParameter("uint8", signature.recoveryParam).substr(2 + (64 - 2)),
-        ]
-
-        signatures += packSig.join("")
-    }
-
-    const vm = [
-        web3.eth.abi.encodeParameter("uint8", 1).substring(2 + (64 - 2)),
-        web3.eth.abi.encodeParameter("uint32", guardianSetIndex).substring(2 + (64 - 8)),
-        web3.eth.abi.encodeParameter("uint8", signers.length).substring(2 + (64 - 2)),
-
-        signatures,
-        body.join("")
-    ].join("");
-
-    return vm
-}
-
-function zeroPadBytes(value, length) {
-    while (value.length < 2 * length) {
-        value = "0" + value;
-    }
-    return value;
-}