소스 검색

remove truffle and replace with foundry

nidhi-singh02 3 달 전
부모
커밋
e65f9f4d82

+ 51 - 8
target_chains/ethereum/contracts/README.md

@@ -34,28 +34,71 @@ npm run coverage
 
 Open `coverage/index.html` in your web browser to see the results.
 
-### Governance tests
+## Deployment
 
-There is a separate test suite executed by truffle for testing governance messages and contract upgrades. You can run ganache-cli as a blockchain instance and test it manually. To do the latter, run the following commands in the `contracts` folder:
+To deploy the contracts, you'll need to set up your environment variables and use the Foundry deployment script.
 
-1. Spawn a new network on a seperate terminal (do not close it while running tests):
+1. Copy the environment template and fill in your values:
 
 ```bash
-pnpm dlx ganache-cli -e 10000 --deterministic --time="1970-01-02T00:00:00+00:00" --host=0.0.0.0
+cp deploy.env.example .env
+# Edit .env with your configuration
 ```
 
-2. deploy the contracts:
+2. Deploy to a local network (for testing):
 
 ```bash
-cp .env.test .env && pnpm exec truffle compile --all && pnpm exec truffle migrate --network development
+# Start a local node
+anvil
+
+# In another terminal, deploy the contracts
+npm run deploy-local
+```
+
+3. Deploy to a live network:
+
+```bash
+# Make sure your .env file has the correct RPC_URL and PRIVATE_KEY
+npm run deploy
 ```
 
-3. Run the test suite:
+The deployment script will:
+- Deploy the Wormhole contracts (Setup, Implementation, and Wormhole proxy)
+- Deploy the Pyth contracts (PythUpgradable with ERC1967 proxy)
+- Configure all necessary parameters from environment variables
+
+### Guardian Set Sync
+
+After deploying Wormhole contracts on mainnet, you need to sync the guardian sets to match the current mainnet state:
 
 ```bash
-npm run test-contract
+# Set WORMHOLE_ADDRESS in your .env file to the deployed Wormhole contract address
+npm run sync-guardian-sets
 ```
 
+This script submits the pre-configured mainnet guardian set upgrade VAAs to bring your contract up to date with the current mainnet guardian set.
+
+### Utility Scripts
+
+Additional utility scripts are available for testing and development:
+
+#### Create Governance VAA (for testing)
+
+```bash
+# Create a governance VAA for localnet testing
+GOVERNANCE_DATA=0x... npm run create-governance-vaa
+```
+
+This script creates a properly signed governance VAA for local testing. You can customize it with environment variables:
+- `TIMESTAMP` - VAA timestamp (defaults to current block timestamp)
+- `NONCE` - VAA nonce (defaults to 0)
+- `EMITTER_CHAIN_ID` - Chain ID of the emitter (defaults to 1)
+- `EMITTER_ADDRESS` - Address of the emitter (defaults to test address)
+- `SEQUENCE` - VAA sequence number (defaults to 0)
+- `GOVERNANCE_DATA` - The governance payload data (required)
+- `GUARDIAN_SET_INDEX` - Guardian set index (defaults to 0)
+- `CONSISTENCY_LEVEL` - Consistency level (defaults to 32)
+
 ### Gas Benchmarks
 
 You can use foundry to run gas benchmark tests (which can be found in the `forge-test` directory). To run the tests with gas report

+ 10 - 33
target_chains/ethereum/contracts/VERIFY.md

@@ -17,12 +17,12 @@ Most of the explorers accept the standard json-input format, while some only acc
 Pyth contract address refers to the proxy contract. After verifying the proxy contract, the implementation contract needs to be verified as well.
 
 Use the verification files in the release to verify the contracts on the explorer sites.
-You can find the compiler configurations in [`truffle-config.js`](./truffle-config.js) by searching for `compilers`.
+You can find the compiler configurations in [`foundry.toml`](./foundry.toml).
 The required configurations are the _solc version_ and the _optimizer runs_.
 
-## Verifying the contract via truffle or hardhat
+## Verifying the contract via Foundry or Hardhat
 
-Although, verification via explorers is the recommended way, you can also verify the contracts using truffle or hardhat.
+Although, verification via explorers is the recommended way, you can also verify the contracts using Foundry or Hardhat.
 In general, you will need an API key for the relevant explorer (this can be obtained by creating an account),
 and also know which address the contract code lives. The API key is expected to
 be set in the `ETHERSCAN_KEY` environment variable for all APIs (not just etherscan, bit of a misnomer).
@@ -31,44 +31,21 @@ be set in the `ETHERSCAN_KEY` environment variable for all APIs (not just ethers
 ETHERSCAN_KEY=... npm run verify --module=PythUpgradable --contract_address=0x0e082F06FF657D94310cB8cE8B0D9a04541d8052 --network=avalanche
 ```
 
-(Note: the network name comes from the `truffle-config.json`).
 (Note: In this case, the `ETHERSCAN_KEY` is your snowtrace API key).
 
-**You might need to add the explorer api keys in [the truffle config](./truffle-config.js) `api_keys`.** Please look at
-`truffle-plugin-verify/utils.js` to find the key names. Here is an example:
+For Foundry verification, you can use the built-in verification feature by adding `--verify` to your deployment command:
 
-```js
-{
-    compilers: [...],
-
-    api_keys: {
-        etherscan: process.env.ETHERSCAN_KEY,
-        bscscan: process.env.BSCSCAN_KEY,
-        snowtrace: process.env.SNOWTRACE_KEY,
-    },
-
-    plugins: [...]
-}
+```bash
+forge script script/Deploy.s.sol --rpc-url $RPC_URL --broadcast --verify --etherscan-api-key $ETHERSCAN_API_KEY
 ```
 
-# Note
-
-The `npm run verify` script uses the `truffle-plugin-verify` plugin under the
-hood. The version of `truffle-plugin-verify` pinned in the repo (`^0.5.11` at
-the time of writing) doesn't support the avalanche RPC. In later versions of the
-plugin, support was added, but other stuff has changed as well in the transitive
-dependencies, so it fails to parse the `HDWallet` arguments in our
-`truffle-config.json`. As a quick workaround, we backport the patch to `0.5.11`
-by applying the `truffle-verify-constants.patch` file, which the `npm run verify` script does transparently. Once the toolchain has been upgraded and the
-errors fixed, this patch can be removed.
-
-### Verifying with hardhat
+### Verifying with Hardhat
 
-Some chains might require users to verify with hardhat. Here are the additional steps :
+Some chains might require users to verify with Hardhat. Here are the additional steps:
 
-- Add the chain to `networks` in `hardhat.config.ts` (equivalent of `truffle-config.js`)
+- Add the chain to `networks` in `hardhat.config.ts`
 - Add the explorer parameters to `etherscan` in `hardhat.config.ts`
-- Run :
+- Run:
 
 ```
 MNEMONIC=... pnpm exec hardhat verify 0x354bF866A4B006C9AF9d9e06d9364217A8616E12 --network shimmer_testnet

+ 0 - 14
target_chains/ethereum/contracts/contracts/Migrations.sol

@@ -1,14 +0,0 @@
-// SPDX-License-Identifier: MIT
-pragma solidity >=0.4.22 <0.9.0;
-
-import "@openzeppelin/contracts/access/Ownable.sol";
-
-// Needed for truffle migrate to work correctly.
-// Simply stores the last completed migration.
-contract Migrations is Ownable {
-    uint public last_completed_migration;
-
-    function setCompleted(uint completed) public onlyOwner {
-        last_completed_migration = completed;
-    }
-}

+ 24 - 0
target_chains/ethereum/contracts/deploy.env.example

@@ -0,0 +1,24 @@
+# Deployment Configuration
+PRIVATE_KEY=your_private_key_here
+
+# Wormhole Configuration
+INIT_SIGNERS=["0x...","0x..."]  # JSON array of initial guardian public keys
+INIT_CHAIN_ID=1                 # Chain ID for this deployment
+INIT_GOV_CHAIN_ID=1            # Governance chain ID
+INIT_GOV_CONTRACT=0x0000000000000000000000000000000000000000000000000000000000000004
+
+# Pyth Configuration
+SOLANA_CHAIN_ID=1              # Solana chain ID for Pyth data source
+SOLANA_EMITTER=0x...           # Pyth emitter address on Solana
+GOVERNANCE_CHAIN_ID=1          # Governance chain ID
+GOVERNANCE_EMITTER=0x...       # Governance emitter address
+GOVERNANCE_INITIAL_SEQUENCE=0  # Initial governance sequence number
+VALID_TIME_PERIOD_SECONDS=60   # Valid time period for price updates in seconds
+SINGLE_UPDATE_FEE_IN_WEI=1000000000000000  # Fee for single price update in wei
+
+# RPC Configuration
+RPC_URL=https://rpc.ankr.com/eth
+ETHERSCAN_API_KEY=your_etherscan_api_key_here
+
+# Guardian Set Sync Configuration
+WORMHOLE_ADDRESS=0x...  # Address of the deployed Wormhole contract

+ 1 - 2
target_chains/ethereum/contracts/foundry.toml

@@ -4,8 +4,7 @@ evm_version = "paris"
 optimizer = true
 optimizer_runs = 200
 src = 'contracts'
-# We put the tests into the forge-test directory (instead of test) so that
-# truffle doesn't try to build them
+# Tests are in the forge-test directory
 test = 'forge-test'
 
 libs = ['lib', 'node_modules']

+ 0 - 6
target_chains/ethereum/contracts/migrations/test/1_initial_migration.js

@@ -1,6 +0,0 @@
-var Migrations = artifacts.require("Migrations");
-
-module.exports = function (deployer) {
-  // Deploy the Migrations contract as our only task
-  deployer.deploy(Migrations);
-};

+ 0 - 34
target_chains/ethereum/contracts/migrations/test/2_deploy_wormhole.js

@@ -1,34 +0,0 @@
-require("dotenv").config();
-
-const Setup = artifacts.require("Setup");
-const Implementation = artifacts.require("Implementation");
-const Wormhole = artifacts.require("Wormhole");
-
-// CONFIG
-const initialSigners = JSON.parse(process.env.INIT_SIGNERS);
-const chainId = process.env.INIT_CHAIN_ID;
-const governanceChainId = process.env.INIT_GOV_CHAIN_ID;
-const governanceContract = process.env.INIT_GOV_CONTRACT; // bytes32
-
-module.exports = async function (deployer) {
-  // deploy setup
-  await deployer.deploy(Setup);
-
-  // deploy implementation
-  await deployer.deploy(Implementation);
-
-  // encode initialisation data
-  const setup = new web3.eth.Contract(Setup.abi, Setup.address);
-  const initData = setup.methods
-    .setup(
-      Implementation.address,
-      initialSigners,
-      chainId,
-      governanceChainId,
-      governanceContract,
-    )
-    .encodeABI();
-
-  // deploy proxy
-  await deployer.deploy(Wormhole, Setup.address, initData);
-};

+ 0 - 47
target_chains/ethereum/contracts/migrations/test/3_deploy_pyth.js

@@ -1,47 +0,0 @@
-require("dotenv").config();
-
-const bs58 = require("bs58");
-
-const PythUpgradable = artifacts.require("PythUpgradable");
-const Wormhole = artifacts.require("Wormhole");
-
-const pyth2WormholeChainId = process.env.SOLANA_CHAIN_ID;
-const pyth2WormholeEmitter = process.env.SOLANA_EMITTER;
-
-const governanceChainId = process.env.GOVERNANCE_CHAIN_ID;
-const governanceEmitter = process.env.GOVERNANCE_EMITTER;
-// Default value for this field is 0
-const governanceInitialSequence = Number(
-  process.env.GOVERNANCE_INITIAL_SEQUENCE ?? "0",
-);
-
-const validTimePeriodSeconds = Number(process.env.VALID_TIME_PERIOD_SECONDS);
-const singleUpdateFeeInWei = Number(process.env.SINGLE_UPDATE_FEE_IN_WEI);
-
-const { deployProxy } = require("@openzeppelin/truffle-upgrades");
-
-console.log("pyth2WormholeChainId: " + pyth2WormholeChainId);
-console.log("pyth2WormholeEmitter: " + pyth2WormholeEmitter);
-console.log("governanceEmitter: " + governanceEmitter);
-console.log("governanceChainId: " + governanceChainId);
-console.log("governanceInitialSequence: " + governanceInitialSequence);
-console.log("validTimePeriodSeconds: " + validTimePeriodSeconds);
-console.log("singleUpdateFeeInWei: " + singleUpdateFeeInWei);
-
-module.exports = async function (deployer) {
-  // Deploy the proxy script
-  await deployProxy(
-    PythUpgradable,
-    [
-      (await Wormhole.deployed()).address,
-      [pyth2WormholeChainId],
-      [pyth2WormholeEmitter],
-      governanceChainId,
-      governanceEmitter,
-      governanceInitialSequence,
-      validTimePeriodSeconds,
-      singleUpdateFeeInWei,
-    ],
-    { deployer },
-  );
-};

+ 8 - 14
target_chains/ethereum/contracts/package.json

@@ -4,25 +4,20 @@
   "description": "",
   "private": "true",
   "devDependencies": {
-    "@openzeppelin/test-helpers": "^0.5.15",
-    "@openzeppelin/truffle-upgrades": "^1.14.0",
-    "@truffle/hdwallet-provider": "^2.1.5",
     "@types/chai": "^4.3.4",
     "chai": "^4.2.0",
     "mocha": "^8.2.1",
     "prettier": "catalog:",
-    "prettier-plugin-solidity": "catalog:",
-    "truffle": "^5.7.4",
-    "truffle-deploy-registry": "^0.5.1",
-    "truffle-plugin-stdjsonin": "github:mhrsalehi/truffle-plugin-stdjsonin",
-    "truffle-plugin-verify": "^0.6.1"
+    "prettier-plugin-solidity": "catalog:"
   },
   "scripts": {
-    "build": "rm -rf build && truffle compile --all",
-    "test-contract": "truffle test",
-    "migrate": "truffle migrate",
-    "receiver-submit-guardian-sets": "truffle exec scripts/receiverSubmitGuardianSetUpgrades.js",
-    "verify": "truffle run verify $npm_config_module@$npm_config_contract_address --network $npm_config_network",
+    "build": "forge build",
+    "test": "forge test",
+    "test-contract": "forge test",
+    "deploy": "forge script script/Deploy.s.sol --rpc-url $RPC_URL --broadcast --verify",
+    "deploy-local": "forge script script/Deploy.s.sol --rpc-url http://localhost:8545 --broadcast",
+    "sync-guardian-sets": "forge script script/SyncGuardianSets.s.sol --rpc-url $RPC_URL --broadcast",
+    "create-governance-vaa": "forge script script/CreateLocalnetGovernanceVaa.s.sol",
     "install-forge-deps": "forge install foundry-rs/forge-std@v1.7.6 --no-git",
     "coverage": "./coverage.sh",
     "test:format": "prettier --check .",
@@ -53,7 +48,6 @@
     "jsonfile": "^4.0.0",
     "lodash": "^4.17.21",
     "solc": "0.8.4",
-    "truffle-contract-size": "^2.0.1",
     "ts-node": "catalog:",
     "typescript": "catalog:",
     "web3": "^1.2.2",

+ 0 - 1
target_chains/ethereum/contracts/remappings.txt

@@ -4,4 +4,3 @@
 ds-test/=lib/forge-std/lib/ds-test/src/
 forge-std/=lib/forge-std/src/
 @nomad-xyz=./node_modules/@nomad-xyz/
-truffle/=./node_modules/truffle/

+ 70 - 0
target_chains/ethereum/contracts/script/CreateLocalnetGovernanceVaa.s.sol

@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.0;
+
+import "forge-std/Script.sol";
+import "forge-std/console.sol";
+
+contract CreateLocalnetGovernanceVaaScript is Script {
+    // Test signer private key (same as in the JS version)
+    uint256 constant TEST_SIGNER_PK = 0xcfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0;
+    
+    uint16 constant TEST_GOVERNANCE_CHAIN = 1; // ethereum
+    bytes32 constant TEST_GOVERNANCE_EMITTER = 0x0000000000000000000000000000000000000000000000000000000000001234;
+
+    function run() external view {
+        uint32 timestamp = uint32(vm.envOr("TIMESTAMP", uint256(block.timestamp)));
+        uint32 nonce = uint32(vm.envOr("NONCE", uint256(0)));
+        uint16 emitterChainId = uint16(vm.envOr("EMITTER_CHAIN_ID", uint256(TEST_GOVERNANCE_CHAIN)));
+        bytes32 emitterAddress = vm.envOr("EMITTER_ADDRESS", TEST_GOVERNANCE_EMITTER);
+        uint64 sequence = uint64(vm.envOr("SEQUENCE", uint256(0)));
+        bytes memory data = vm.envBytes("GOVERNANCE_DATA");
+        uint32 guardianSetIndex = uint32(vm.envOr("GUARDIAN_SET_INDEX", uint256(0)));
+        uint8 consistencyLevel = uint8(vm.envOr("CONSISTENCY_LEVEL", uint256(32)));
+
+        console.log("Creating localnet governance VAA with parameters:");
+        console.log("Timestamp:", timestamp);
+        console.log("Nonce:", nonce);
+        console.log("Emitter Chain ID:", emitterChainId);
+        console.log("Emitter Address:", uint256(emitterAddress));
+        console.log("Sequence:", sequence);
+        console.log("Guardian Set Index:", guardianSetIndex);
+        console.log("Consistency Level:", consistencyLevel);
+        console.log("Data length:", data.length);
+
+        // Create VAA body
+        bytes memory body = abi.encodePacked(
+            timestamp,
+            nonce,
+            emitterChainId,
+            emitterAddress,
+            sequence,
+            consistencyLevel,
+            data
+        );
+
+        // Hash the body for signing
+        bytes32 bodyHash = keccak256(abi.encodePacked(keccak256(body)));
+        
+        // Sign with test private key
+        (uint8 v, bytes32 r, bytes32 s) = vm.sign(TEST_SIGNER_PK, bodyHash);
+        
+        // Create signature structure (guardian index 0, signature)
+        bytes memory signature = abi.encodePacked(uint8(0), r, s, v);
+        
+        // Create complete VAA
+        bytes memory vaa = abi.encodePacked(
+            uint8(1),           // version
+            guardianSetIndex,   // guardian set index
+            uint8(1),           // number of signatures
+            signature,          // signatures
+            body               // body
+        );
+
+        console.log("Generated VAA (hex):");
+        console.logBytes(vaa);
+        
+        // Also log as a string for easy copying
+        string memory vaaHex = vm.toString(vaa);
+        console.log("VAA hex string:", vaaHex);
+    }
+}

+ 112 - 0
target_chains/ethereum/contracts/script/Deploy.s.sol

@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.0;
+
+import "forge-std/Script.sol";
+import "forge-std/console.sol";
+import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
+
+// Wormhole contracts
+import "../contracts/wormhole/Setup.sol";
+import "../contracts/wormhole/Implementation.sol";
+import "../contracts/wormhole/Wormhole.sol";
+
+// Pyth contracts
+import "../contracts/pyth/PythUpgradable.sol";
+
+contract DeployScript is Script {
+    function run() external {
+        uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
+        vm.startBroadcast(deployerPrivateKey);
+
+        // Deploy Wormhole first
+        address wormholeAddress = deployWormhole();
+        console.log("Wormhole deployed at:", wormholeAddress);
+
+        // Deploy Pyth
+        address pythAddress = deployPyth(wormholeAddress);
+        console.log("Pyth deployed at:", pythAddress);
+
+        vm.stopBroadcast();
+    }
+
+    function deployWormhole() internal returns (address) {
+        // Read environment variables
+        bytes32[] memory initialSigners = abi.decode(vm.parseJson(vm.envString("INIT_SIGNERS")), (bytes32[]));
+        uint16 chainId = uint16(vm.envUint("INIT_CHAIN_ID"));
+        uint16 governanceChainId = uint16(vm.envUint("INIT_GOV_CHAIN_ID"));
+        bytes32 governanceContract = vm.envBytes32("INIT_GOV_CONTRACT");
+
+        console.log("Deploying Wormhole with chainId:", chainId);
+        console.log("Governance chainId:", governanceChainId);
+
+        // Deploy Setup contract
+        Setup setup = new Setup();
+        console.log("Setup deployed at:", address(setup));
+
+        // Deploy Implementation contract
+        Implementation implementation = new Implementation();
+        console.log("Implementation deployed at:", address(implementation));
+
+        // Encode initialization data
+        bytes memory initData = abi.encodeWithSignature(
+            "setup(address,bytes32[],uint16,uint16,bytes32)",
+            address(implementation),
+            initialSigners,
+            chainId,
+            governanceChainId,
+            governanceContract
+        );
+
+        // Deploy Wormhole proxy
+        Wormhole wormhole = new Wormhole(address(setup), initData);
+        
+        return address(wormhole);
+    }
+
+    function deployPyth(address wormholeAddress) internal returns (address) {
+        // Read environment variables
+        uint16 pyth2WormholeChainId = uint16(vm.envUint("SOLANA_CHAIN_ID"));
+        bytes32 pyth2WormholeEmitter = vm.envBytes32("SOLANA_EMITTER");
+        uint16 governanceChainId = uint16(vm.envUint("GOVERNANCE_CHAIN_ID"));
+        bytes32 governanceEmitter = vm.envBytes32("GOVERNANCE_EMITTER");
+        uint64 governanceInitialSequence = uint64(vm.envOr("GOVERNANCE_INITIAL_SEQUENCE", uint256(0)));
+        uint256 validTimePeriodSeconds = vm.envUint("VALID_TIME_PERIOD_SECONDS");
+        uint256 singleUpdateFeeInWei = vm.envUint("SINGLE_UPDATE_FEE_IN_WEI");
+
+        console.log("pyth2WormholeChainId:", pyth2WormholeChainId);
+        console.log("pyth2WormholeEmitter:", uint256(pyth2WormholeEmitter));
+        console.log("governanceEmitter:", uint256(governanceEmitter));
+        console.log("governanceChainId:", governanceChainId);
+        console.log("governanceInitialSequence:", governanceInitialSequence);
+        console.log("validTimePeriodSeconds:", validTimePeriodSeconds);
+        console.log("singleUpdateFeeInWei:", singleUpdateFeeInWei);
+
+        // Deploy PythUpgradable implementation
+        PythUpgradable pythImpl = new PythUpgradable();
+        console.log("PythUpgradable implementation deployed at:", address(pythImpl));
+
+        // Prepare initialization data
+        uint16[] memory dataSourceChainIds = new uint16[](1);
+        dataSourceChainIds[0] = pyth2WormholeChainId;
+        
+        bytes32[] memory dataSourceEmitterAddresses = new bytes32[](1);
+        dataSourceEmitterAddresses[0] = pyth2WormholeEmitter;
+
+        bytes memory pythInitData = abi.encodeWithSignature(
+            "initialize(address,uint16[],bytes32[],uint16,bytes32,uint64,uint256,uint256)",
+            wormholeAddress,
+            dataSourceChainIds,
+            dataSourceEmitterAddresses,
+            governanceChainId,
+            governanceEmitter,
+            governanceInitialSequence,
+            validTimePeriodSeconds,
+            singleUpdateFeeInWei
+        );
+
+        // Deploy ERC1967 proxy
+        ERC1967Proxy pythProxy = new ERC1967Proxy(address(pythImpl), pythInitData);
+        
+        return address(pythProxy);
+    }
+}

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 14 - 0
target_chains/ethereum/contracts/script/SyncGuardianSets.s.sol


+ 65 - 0
target_chains/ethereum/contracts/script/utils/VaaUtils.sol

@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.0;
+
+import "forge-std/Test.sol";
+
+library VaaUtils {
+    /**
+     * @dev Assert that a VAA has the expected payload
+     * @param vaaBytes The VAA bytes to check
+     * @param expectedPayload The expected payload bytes
+     */
+    function assertVaaPayloadEquals(bytes memory vaaBytes, bytes memory expectedPayload) internal pure {
+        // VAA structure: version (1) + guardianSetIndex (4) + signaturesLength (1) + signatures + body
+        // Body structure: timestamp (4) + nonce (4) + emitterChainId (2) + emitterAddress (32) + sequence (8) + consistencyLevel (1) + payload
+        
+        require(vaaBytes.length >= 51, "VAA too short"); // Minimum VAA length
+        
+        uint256 offset = 6; // Skip version (1) + guardianSetIndex (4) + signaturesLength (1)
+        
+        // Skip signatures (each signature is 66 bytes: guardianIndex (1) + r (32) + s (32) + v (1))
+        uint8 signaturesLength = uint8(vaaBytes[5]);
+        offset += signaturesLength * 66;
+        
+        // Skip to payload (skip timestamp (4) + nonce (4) + emitterChainId (2) + emitterAddress (32) + sequence (8) + consistencyLevel (1))
+        offset += 51;
+        
+        require(offset < vaaBytes.length, "Invalid VAA structure");
+        
+        // Extract payload
+        bytes memory actualPayload = new bytes(vaaBytes.length - offset);
+        for (uint256 i = 0; i < actualPayload.length; i++) {
+            actualPayload[i] = vaaBytes[offset + i];
+        }
+        
+        require(
+            keccak256(actualPayload) == keccak256(expectedPayload),
+            "VAA payload does not match expected payload"
+        );
+    }
+    
+    /**
+     * @dev Extract payload from VAA bytes
+     * @param vaaBytes The VAA bytes
+     * @return payload The extracted payload
+     */
+    function extractPayload(bytes memory vaaBytes) internal pure returns (bytes memory payload) {
+        require(vaaBytes.length >= 51, "VAA too short");
+        
+        uint256 offset = 6; // Skip version (1) + guardianSetIndex (4) + signaturesLength (1)
+        
+        // Skip signatures
+        uint8 signaturesLength = uint8(vaaBytes[5]);
+        offset += signaturesLength * 66;
+        
+        // Skip to payload
+        offset += 51;
+        
+        require(offset < vaaBytes.length, "Invalid VAA structure");
+        
+        payload = new bytes(vaaBytes.length - offset);
+        for (uint256 i = 0; i < payload.length; i++) {
+            payload[i] = vaaBytes[offset + i];
+        }
+    }
+}

+ 0 - 895
target_chains/ethereum/contracts/test/pyth.js

@@ -1,895 +0,0 @@
-const elliptic = require("elliptic");
-const governance = require("@pythnetwork/xc-admin-common");
-
-const { deployProxy, upgradeProxy } = require("@openzeppelin/truffle-upgrades");
-const {
-  expectRevert,
-  expectEvent,
-  time,
-} = require("@openzeppelin/test-helpers");
-const { assert, expect } = require("chai");
-const { EvmSetWormholeAddress } = require("@pythnetwork/xc-admin-common");
-
-// Use "WormholeReceiver" if you are testing with Wormhole Receiver
-const Setup = artifacts.require("Setup");
-const Implementation = artifacts.require("Implementation");
-const Wormhole = artifacts.require("Wormhole");
-
-const ReceiverSetup = artifacts.require("ReceiverSetup");
-const ReceiverImplementation = artifacts.require("ReceiverImplementation");
-const WormholeReceiver = artifacts.require("WormholeReceiver");
-
-const wormholeGovernanceChainId = governance.CHAINS.solana;
-const wormholeGovernanceContract =
-  "0x0000000000000000000000000000000000000000000000000000000000000004";
-
-const PythUpgradable = artifacts.require("PythUpgradable");
-const MockPythUpgrade = artifacts.require("MockPythUpgrade");
-const MockUpgradeableProxy = artifacts.require("MockUpgradeableProxy");
-
-const testSigner1PK =
-  "cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0";
-const testSigner2PK =
-  "892330666a850761e7370376430bb8c2aa1494072d3bfeaed0c4fa3d5a9135fe";
-
-contract("Pyth", function () {
-  const testSigner1 = web3.eth.accounts.privateKeyToAccount(testSigner1PK);
-  const testSigner2 = web3.eth.accounts.privateKeyToAccount(testSigner2PK);
-  const testGovernanceChainId = "1";
-  const testGovernanceEmitter =
-    "0x0000000000000000000000000000000000000000000000000000000000001234";
-  const testPyth2WormholeChainId = "1";
-  const testPyth2WormholeEmitter =
-    "0x71f8dcb863d176e2c420ad6610cf687359612b6fb392e0642b0ca6b1f186aa3b";
-
-  // Place all atomic operations that are done within migrations here.
-  beforeEach(async function () {
-    this.pythProxy = await deployProxy(PythUpgradable, [
-      (await Wormhole.deployed()).address,
-      [testPyth2WormholeChainId],
-      [testPyth2WormholeEmitter],
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      0, // Initial governance sequence
-      60, // Validity time in seconds
-      0, // single update fee in wei
-    ]);
-  });
-
-  it("should be initialized with the correct signers and values", async function () {
-    await this.pythProxy.isValidDataSource(
-      testPyth2WormholeChainId,
-      testPyth2WormholeEmitter,
-    );
-  });
-
-  it("there should be no owner", async function () {
-    // Check that the ownership is renounced.
-    const owner = await this.pythProxy.owner();
-    assert.equal(owner, "0x0000000000000000000000000000000000000000");
-  });
-
-  it("deployer cannot upgrade the contract", async function () {
-    // upgrade proxy should fail
-    await expectRevert(
-      upgradeProxy(this.pythProxy.address, MockPythUpgrade),
-      "Ownable: caller is not the owner.",
-    );
-  });
-
-  async function updatePriceFeeds(
-    contract,
-    batches,
-    valueInWei,
-    chainId,
-    emitter,
-  ) {
-    let updateData = [];
-    for (let data of batches) {
-      const vm = await signAndEncodeVM(
-        1,
-        1,
-        chainId || testPyth2WormholeChainId,
-        emitter || testPyth2WormholeEmitter,
-        0,
-        data,
-        [testSigner1PK],
-        0,
-        0,
-      );
-      updateData.push("0x" + vm);
-    }
-    return await contract.updatePriceFeeds(updateData, { value: valueInWei });
-  }
-
-  /**
-   * Create a governance instruction VAA from the Instruction object. Then
-   * Submit and execute it on the contract.
-   * @param contract Pyth contract
-   * @param {governance.PythGovernanceAction} governanceInstruction
-   * @param {number} sequence
-   */
-  async function createAndThenSubmitGovernanceInstructionVaa(
-    contract,
-    governanceInstruction,
-    sequence,
-  ) {
-    await contract.executeGovernanceInstruction(
-      await createVAAFromUint8Array(
-        governanceInstruction.encode(),
-        testGovernanceChainId,
-        testGovernanceEmitter,
-        sequence,
-      ),
-    );
-  }
-
-  it("should attest price updates empty", async function () {
-    const receipt = await updatePriceFeeds(this.pythProxy, []);
-    expectEvent.notEmitted(receipt, "PriceFeedUpdate");
-  });
-
-  /**
-   * Set fee to `newFee` by creating and submitting a governance instruction for it.
-   * @param contarct Pyth contract
-   * @param {number} newFee
-   * @param {number=} governanceSequence Sequence number of the governance instruction. Defaults to 1.
-   */
-  async function setFeeTo(contract, newFee, governanceSequence) {
-    await createAndThenSubmitGovernanceInstructionVaa(
-      contract,
-      new governance.SetFee("ethereum", BigInt(newFee), BigInt(0)),
-      governanceSequence ?? 1,
-    );
-  }
-
-  it("should fail transaction if a price is not found", async function () {
-    await expectRevertCustomError(
-      this.pythProxy.queryPriceFeed(
-        "0xdeadfeeddeadfeeddeadfeeddeadfeeddeadfeeddeadfeeddeadfeeddeadfeed",
-      ),
-      "PriceFeedNotFound",
-    );
-  });
-
-  /**
-   * Set valid time period to `newValidPeriod` by creating and submitting a
-   * governance instruction for it.
-   * @param contract Pyth contract
-   * @param {number} newValidPeriod
-   * @param {number=} governanceSequence Sequence number of the governance instruction. Defaults to 1.
-   */
-  async function setValidPeriodTo(
-    contract,
-    newValidPeriod,
-    governanceSequence,
-  ) {
-    await createAndThenSubmitGovernanceInstructionVaa(
-      contract,
-      new governance.SetValidPeriod("ethereum", BigInt(newValidPeriod)),
-      governanceSequence ?? 1,
-    );
-  }
-
-  // Governance
-
-  // Logics that apply to all governance messages
-  it("Make sure invalid magic and module won't work", async function () {
-    // First 4 bytes of data are magic and the second byte after that is module
-    const data = new governance.SetValidPeriod("ethereum", BigInt(10)).encode();
-
-    const wrongMagic = Buffer.from(data);
-    wrongMagic[1] = 0;
-
-    const vaaWrongMagic = await createVAAFromUint8Array(
-      wrongMagic,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      1,
-    );
-
-    await expectRevertCustomError(
-      this.pythProxy.executeGovernanceInstruction(vaaWrongMagic),
-      "InvalidGovernanceMessage",
-    );
-
-    const wrongModule = Buffer.from(data);
-    wrongModule[4] = 0;
-
-    const vaaWrongModule = await createVAAFromUint8Array(
-      wrongModule,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      1,
-    );
-
-    await expectRevertCustomError(
-      this.pythProxy.executeGovernanceInstruction(vaaWrongModule),
-      "InvalidGovernanceTarget",
-    );
-
-    const outOfBoundModule = Buffer.from(data);
-    outOfBoundModule[4] = 20;
-
-    const vaaOutOfBoundModule = await createVAAFromUint8Array(
-      outOfBoundModule,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      1,
-    );
-
-    await expectRevert(
-      this.pythProxy.executeGovernanceInstruction(vaaOutOfBoundModule),
-      "Panic: Enum value out of bounds.",
-    );
-  });
-
-  it("Make sure governance with wrong sender won't work", async function () {
-    const data = new governance.SetValidPeriod("ethereum", BigInt(10)).encode();
-
-    const vaaWrongEmitter = await createVAAFromUint8Array(
-      data,
-      testGovernanceChainId,
-      "0x0000000000000000000000000000000000000000000000000000000000001111",
-      1,
-    );
-
-    await expectRevertCustomError(
-      this.pythProxy.executeGovernanceInstruction(vaaWrongEmitter),
-      "InvalidGovernanceDataSource",
-    );
-
-    const vaaWrongChain = await createVAAFromUint8Array(
-      data,
-      governance.CHAINS.karura,
-      testGovernanceEmitter,
-      1,
-    );
-
-    await expectRevertCustomError(
-      this.pythProxy.executeGovernanceInstruction(vaaWrongChain),
-      "InvalidGovernanceDataSource",
-    );
-  });
-
-  it("Make sure governance with only target chain id and 0 work", async function () {
-    const wrongChainData = new governance.SetValidPeriod(
-      "solana",
-      BigInt(10),
-    ).encode();
-
-    const wrongChainVaa = await createVAAFromUint8Array(
-      wrongChainData,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      1,
-    );
-
-    await expectRevertCustomError(
-      this.pythProxy.executeGovernanceInstruction(wrongChainVaa),
-      "InvalidGovernanceTarget",
-    );
-
-    const dataForAllChains = new governance.SetValidPeriod(
-      "unset",
-      BigInt(10),
-    ).encode();
-
-    const vaaForAllChains = await createVAAFromUint8Array(
-      dataForAllChains,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      1,
-    );
-
-    await this.pythProxy.executeGovernanceInstruction(vaaForAllChains);
-
-    const dataForEth = new governance.SetValidPeriod(
-      "ethereum",
-      BigInt(10),
-    ).encode();
-
-    const vaaForEth = await createVAAFromUint8Array(
-      dataForEth,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      2,
-    );
-
-    await this.pythProxy.executeGovernanceInstruction(vaaForEth);
-  });
-
-  it("Make sure that governance messages are executed in order and cannot be reused", async function () {
-    const data = new governance.SetValidPeriod("ethereum", BigInt(10)).encode();
-
-    const vaaSeq1 = await createVAAFromUint8Array(
-      data,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      1,
-    );
-
-    await this.pythProxy.executeGovernanceInstruction(vaaSeq1),
-      // Replaying shouldn't work
-      await expectRevertCustomError(
-        this.pythProxy.executeGovernanceInstruction(vaaSeq1),
-        "OldGovernanceMessage",
-      );
-
-    const vaaSeq2 = await createVAAFromUint8Array(
-      data,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      2,
-    );
-
-    await this.pythProxy.executeGovernanceInstruction(vaaSeq2),
-      // Replaying shouldn't work
-      await expectRevertCustomError(
-        this.pythProxy.executeGovernanceInstruction(vaaSeq1),
-        "OldGovernanceMessage",
-      );
-    await expectRevertCustomError(
-      this.pythProxy.executeGovernanceInstruction(vaaSeq2),
-      "OldGovernanceMessage",
-    );
-  });
-
-  // Per governance type logic
-  it("Upgrading the contract with chain id 0 is invalid", async function () {
-    const newImplementation = await PythUpgradable.new();
-
-    const data = new governance.EvmUpgradeContract(
-      "unset", // 0
-      newImplementation.address.replace("0x", ""),
-    ).encode();
-
-    const vaa = await createVAAFromUint8Array(
-      data,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      1,
-    );
-
-    await expectRevertCustomError(
-      this.pythProxy.executeGovernanceInstruction(vaa),
-      "InvalidGovernanceTarget",
-    );
-  });
-
-  it("Upgrading the contract should work", async function () {
-    const newImplementation = await PythUpgradable.new();
-
-    const data = new governance.EvmUpgradeContract(
-      "ethereum",
-      newImplementation.address.replace("0x", ""),
-    ).encode();
-
-    const vaa = await createVAAFromUint8Array(
-      data,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      1,
-    );
-
-    const receipt = await this.pythProxy.executeGovernanceInstruction(vaa);
-
-    // Couldn't get the oldImplementation address.
-    expectEvent(receipt, "ContractUpgraded", {
-      newImplementation: newImplementation.address,
-    });
-    expectEvent(receipt, "Upgraded", {
-      implementation: newImplementation.address,
-    });
-  });
-
-  it("Upgrading the contract to a non-pyth contract won't work", async function () {
-    const newImplementation = await MockUpgradeableProxy.new();
-
-    const data = new governance.EvmUpgradeContract(
-      "ethereum",
-      newImplementation.address.replace("0x", ""),
-    ).encode();
-
-    const vaa = await createVAAFromUint8Array(
-      data,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      1,
-    );
-
-    // Calling a non-existing method will cause a revert with no explanation.
-    await expectRevert(
-      this.pythProxy.executeGovernanceInstruction(vaa),
-      "revert",
-    );
-  });
-
-  it("Transferring governance data source should work", async function () {
-    const newEmitterAddress =
-      "0x0000000000000000000000000000000000000000000000000000000000001111";
-    const newEmitterChain = governance.CHAINS.acala;
-
-    const claimInstructionData =
-      new governance.RequestGovernanceDataSourceTransfer("unset", 1).encode();
-
-    const claimVaaHexString = await createVAAFromUint8Array(
-      claimInstructionData,
-      newEmitterChain,
-      newEmitterAddress,
-      1,
-    );
-
-    await expectRevertCustomError(
-      this.pythProxy.executeGovernanceInstruction(claimVaaHexString),
-      "InvalidGovernanceDataSource",
-    );
-
-    const claimVaa = Buffer.from(claimVaaHexString.substring(2), "hex");
-
-    const data = new governance.AuthorizeGovernanceDataSourceTransfer(
-      "unset",
-      claimVaa,
-    ).encode();
-
-    const vaa = await createVAAFromUint8Array(
-      data,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      1,
-    );
-
-    const oldGovernanceDataSource = await this.pythProxy.governanceDataSource();
-
-    const receipt = await this.pythProxy.executeGovernanceInstruction(vaa);
-
-    const newGovernanceDataSource = await this.pythProxy.governanceDataSource();
-
-    expectEvent(receipt, "GovernanceDataSourceSet", {
-      oldDataSource: oldGovernanceDataSource,
-      newDataSource: newGovernanceDataSource,
-    });
-
-    expect(newGovernanceDataSource.chainId).equal(newEmitterChain.toString());
-    expect(newGovernanceDataSource.emitterAddress).equal(newEmitterAddress);
-
-    // Verifies the data source has changed.
-    await expectRevertCustomError(
-      this.pythProxy.executeGovernanceInstruction(vaa),
-      "InvalidGovernanceDataSource",
-    );
-
-    // Make sure a claim vaa does not get executed
-
-    const claimLonely = new governance.RequestGovernanceDataSourceTransfer(
-      "unset",
-      2,
-    ).encode();
-
-    const claimLonelyVaa = await createVAAFromUint8Array(
-      claimLonely,
-      newEmitterChain,
-      newEmitterAddress,
-      2,
-    );
-
-    await expectRevertCustomError(
-      this.pythProxy.executeGovernanceInstruction(claimLonelyVaa),
-      "InvalidGovernanceMessage",
-    );
-
-    // Transfer back the ownership to the old governance data source without increasing
-    // the governance index should not work
-
-    // A wrong vaa that does not move the governance index
-    const transferBackClaimInstructionDataWrong =
-      new governance.RequestGovernanceDataSourceTransfer(
-        "unset",
-        1, // The same governance data source index => Should fail
-      ).encode();
-
-    const transferBackClaimVaaHexStringWrong = await createVAAFromUint8Array(
-      transferBackClaimInstructionDataWrong,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      2,
-    );
-
-    const transferBackClaimVaaWrong = Buffer.from(
-      transferBackClaimVaaHexStringWrong.substring(2),
-      "hex",
-    );
-
-    const transferBackDataWrong =
-      new governance.AuthorizeGovernanceDataSourceTransfer(
-        "unset",
-        transferBackClaimVaaWrong,
-      ).encode();
-
-    const transferBackVaaWrong = await createVAAFromUint8Array(
-      transferBackDataWrong,
-      newEmitterChain,
-      newEmitterAddress,
-      2,
-    );
-
-    await expectRevertCustomError(
-      this.pythProxy.executeGovernanceInstruction(transferBackVaaWrong),
-      "OldGovernanceMessage",
-    );
-  });
-
-  it("Setting data sources should work", async function () {
-    const data = new governance.SetDataSources("ethereum", [
-      {
-        emitterChain: governance.CHAINS.acala,
-        emitterAddress:
-          "0000000000000000000000000000000000000000000000000000000000001111",
-      },
-    ]).encode();
-
-    const vaa = await createVAAFromUint8Array(
-      data,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      1,
-    );
-
-    const oldDataSources = await this.pythProxy.validDataSources();
-
-    const receipt = await this.pythProxy.executeGovernanceInstruction(vaa);
-    expectEvent(receipt, "DataSourcesSet", {
-      oldDataSources: oldDataSources,
-      newDataSources: await this.pythProxy.validDataSources(),
-    });
-
-    assert.isTrue(
-      await this.pythProxy.isValidDataSource(
-        governance.CHAINS.acala,
-        "0x0000000000000000000000000000000000000000000000000000000000001111",
-      ),
-    );
-    assert.isFalse(
-      await this.pythProxy.isValidDataSource(
-        testPyth2WormholeChainId,
-        testPyth2WormholeEmitter,
-      ),
-    );
-
-    // TODO: try to publish prices
-  });
-
-  it("Setting fee should work", async function () {
-    const data = new governance.SetFee(
-      "ethereum",
-      BigInt(5),
-      BigInt(3), // 5*10**3 = 5000
-    ).encode();
-
-    const vaa = await createVAAFromUint8Array(
-      data,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      1,
-    );
-
-    const oldFee = await this.pythProxy.singleUpdateFeeInWei();
-
-    const receipt = await this.pythProxy.executeGovernanceInstruction(vaa);
-    expectEvent(receipt, "FeeSet", {
-      oldFee: oldFee,
-      newFee: await this.pythProxy.singleUpdateFeeInWei(),
-    });
-
-    assert.equal(await this.pythProxy.singleUpdateFeeInWei(), "5000");
-
-    // TODO: check that fee is applied
-  });
-
-  it("Setting valid period should work", async function () {
-    const data = new governance.SetValidPeriod("ethereum", BigInt(0)).encode();
-
-    const vaa = await createVAAFromUint8Array(
-      data,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      1,
-    );
-
-    const oldValidPeriod = await this.pythProxy.validTimePeriodSeconds();
-
-    const receipt = await this.pythProxy.executeGovernanceInstruction(vaa);
-    expectEvent(receipt, "ValidPeriodSet", {
-      oldValidPeriod: oldValidPeriod,
-      newValidPeriod: await this.pythProxy.validTimePeriodSeconds(),
-    });
-
-    assert.equal(await this.pythProxy.validTimePeriodSeconds(), "0");
-
-    // The behaviour of valid time period is extensively tested before,
-    // and adding it here will cause more complexity (and is not so short).
-  });
-
-  it("Setting wormhole address should work", async function () {
-    // Deploy a new wormhole contract
-    const newSetup = await Setup.new();
-    const newImpl = await Implementation.new();
-
-    // encode initialisation data
-    const initData = newSetup.contract.methods
-      .setup(
-        newImpl.address,
-        [testSigner1.address],
-        governance.CHAINS.polygon, // changing the chain id to polygon
-        wormholeGovernanceChainId,
-        wormholeGovernanceContract,
-      )
-      .encodeABI();
-
-    const newWormhole = await Wormhole.new(newSetup.address, initData);
-
-    // Creating the vaa to set the new wormhole address
-    const data = new governance.EvmSetWormholeAddress(
-      "ethereum",
-      newWormhole.address.replace("0x", ""),
-    ).encode();
-
-    const vaa = await createVAAFromUint8Array(
-      data,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      1,
-    );
-
-    assert.equal(await this.pythProxy.chainId(), governance.CHAINS.ethereum);
-
-    const oldWormholeAddress = await this.pythProxy.wormhole();
-
-    const receipt = await this.pythProxy.executeGovernanceInstruction(vaa);
-    expectEvent(receipt, "WormholeAddressSet", {
-      oldWormholeAddress: oldWormholeAddress,
-      newWormholeAddress: newWormhole.address,
-    });
-
-    assert.equal(await this.pythProxy.wormhole(), newWormhole.address);
-    assert.equal(await this.pythProxy.chainId(), governance.CHAINS.polygon);
-  });
-
-  it("Setting wormhole address to WormholeReceiver should work", async function () {
-    // Deploy a new wormhole receiver contract
-    const newReceiverSetup = await ReceiverSetup.new();
-    const newReceiverImpl = await ReceiverImplementation.new();
-
-    // encode initialisation data
-    const initData = newReceiverSetup.contract.methods
-      .setup(
-        newReceiverImpl.address,
-        [testSigner1.address],
-        governance.CHAINS.polygon, // changing the chain id to polygon
-        wormholeGovernanceChainId,
-        wormholeGovernanceContract,
-      )
-      .encodeABI();
-
-    const newWormholeReceiver = await WormholeReceiver.new(
-      newReceiverSetup.address,
-      initData,
-    );
-
-    // Creating the vaa to set the new wormhole address
-    const data = new governance.EvmSetWormholeAddress(
-      "ethereum",
-      newWormholeReceiver.address.replace("0x", ""),
-    ).encode();
-
-    const vaa = await createVAAFromUint8Array(
-      data,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      1,
-    );
-
-    assert.equal(await this.pythProxy.chainId(), governance.CHAINS.ethereum);
-
-    const oldWormholeAddress = await this.pythProxy.wormhole();
-
-    const receipt = await this.pythProxy.executeGovernanceInstruction(vaa);
-    expectEvent(receipt, "WormholeAddressSet", {
-      oldWormholeAddress: oldWormholeAddress,
-      newWormholeAddress: newWormholeReceiver.address,
-    });
-
-    assert.equal(await this.pythProxy.wormhole(), newWormholeReceiver.address);
-    assert.equal(await this.pythProxy.chainId(), governance.CHAINS.polygon);
-  });
-
-  it("Setting wormhole address to a wrong contract should reject", async function () {
-    // Deploy a new wormhole contract
-    const newSetup = await Setup.new();
-    const newImpl = await Implementation.new();
-
-    // encode initialisation data
-    const initData = newSetup.contract.methods
-      .setup(
-        newImpl.address,
-        [testSigner2.address], // A wrong signer
-        governance.CHAINS.ethereum,
-        wormholeGovernanceChainId,
-        wormholeGovernanceContract,
-      )
-      .encodeABI();
-
-    const newWormhole = await Wormhole.new(newSetup.address, initData);
-
-    // Creating the vaa to set the new wormhole address
-    const data = new governance.EvmSetWormholeAddress(
-      "ethereum",
-      newWormhole.address.replace("0x", ""),
-    ).encode();
-
-    const wrongVaa = await createVAAFromUint8Array(
-      data,
-      testGovernanceChainId,
-      testGovernanceEmitter,
-      1,
-    );
-
-    await expectRevertCustomError(
-      this.pythProxy.executeGovernanceInstruction(wrongVaa),
-      "InvalidGovernanceMessage",
-    );
-  });
-
-  // Version
-
-  it("Make sure version is the npm package version", async function () {
-    const contractVersion = await this.pythProxy.version();
-    const { version } = require("../package.json");
-
-    expect(contractVersion).equal(version);
-  });
-});
-
-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;
-}
-
-async function createVAAFromUint8Array(
-  dataBuffer,
-  emitterChainId,
-  emitterAddress,
-  sequence,
-) {
-  const dataHex = "0x" + dataBuffer.toString("hex");
-  return (
-    "0x" +
-    (await signAndEncodeVM(
-      0,
-      0,
-      emitterChainId.toString(),
-      emitterAddress,
-      sequence,
-      dataHex,
-      [testSigner1PK],
-      0,
-      0,
-    ))
-  );
-}
-
-// There is no way to check event with given args has not emitted with expectEvent
-// or how many times an event was emitted. This function is implemented to count
-// the matching events and is used for the mentioned purposes.
-function getNumMatchingEvents(receipt, eventName, args) {
-  let matchCnt = 0;
-  for (let log of receipt.logs) {
-    if (log.event === eventName) {
-      let match = true;
-      for (let argKey in args) {
-        if (log.args[argKey].toString() !== args[argKey].toString()) {
-          match = false;
-          break;
-        }
-      }
-      if (match) {
-        matchCnt++;
-      }
-    }
-  }
-  return matchCnt;
-}
-
-function expectEventNotEmittedWithArgs(receipt, eventName, args) {
-  const matches = getNumMatchingEvents(receipt, eventName, args);
-  assert(
-    matches === 0,
-    `Expected no matching emitted event. But found ${matches}.`,
-  );
-}
-
-function expectEventMultipleTimes(receipt, eventName, args, cnt) {
-  const matches = getNumMatchingEvents(receipt, eventName, args);
-  assert(matches === cnt, `Expected ${cnt} event matches, found ${matches}.`);
-}
-
-async function expectRevertCustomError(promise, reason) {
-  try {
-    await promise;
-    expect.fail("Expected promise to throw but it didn't");
-  } catch (revert) {
-    if (reason) {
-      const reasonId = web3.utils.keccak256(reason + "()").substr(0, 10);
-      expect(
-        JSON.stringify(revert),
-        `Expected custom error ${reason} (${reasonId})`,
-      ).to.include(reasonId);
-    }
-  }
-}

+ 0 - 52
target_chains/ethereum/contracts/truffle-config.js

@@ -1,52 +0,0 @@
-require("dotenv").config({ path: ".env" });
-const HDWalletProvider = require("@truffle/hdwallet-provider");
-
-/**
- *
- * @param {string} url
- * @returns {HDWalletProvider} An instance of HDWalletProvider
- */
-function payerProvider(url) {
-  return () =>
-    new HDWalletProvider({
-      mnemonic: process.env.MNEMONIC,
-      providerOrUrl: url,
-      // This option makes deployments more reliable (by avoiding rate limiting errors) at the cost of
-      // taking a little longer.
-      pollingInterval: 12000,
-    });
-}
-
-module.exports = {
-  migrations_directory: process.env.MIGRATIONS_DIR,
-  networks: {
-    development: {
-      host: "127.0.0.1",
-      port: 8545,
-      network_id: "*",
-    },
-    [process.env.MIGRATIONS_NETWORK]: {
-      provider: payerProvider(process.env.RPC_URL),
-      network_id: process.env.NETWORK_ID,
-    },
-  },
-
-  compilers: {
-    solc: {
-      version: "0.8.29",
-      evmVersion: "paris",
-      settings: {
-        optimizer: {
-          enabled: true,
-          runs: 200,
-        },
-      },
-    },
-  },
-
-  plugins: [
-    "truffle-plugin-verify",
-    "truffle-contract-size",
-    "truffle-plugin-stdjsonin",
-  ],
-};

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.