From 92dbc20c8b1ef026cec3ae78a87185e6cbb2aabe Mon Sep 17 00:00:00 2001 From: derpy-duck <115193320+derpy-duck@users.noreply.github.com> Date: Fri, 10 Mar 2023 10:41:12 -0500 Subject: [PATCH] Forge tests faster (#117) * fast tests * forge fmt * add --via-ir to build * remove forge test-fast; just run forge test for the same effect * remove outdated and unused folder --- ethereum/Makefile | 16 +- .../contracts/coreRelayer/CoreRelayer.sol | 2 +- .../coreRelayer/CoreRelayerDelivery.sol | 76 ++++--- .../coreRelayer/CoreRelayerStructs.sol | 8 +- ethereum/forge-scripts/deploy_contracts.sol | 211 ------------------ .../forge-scripts/deploy_dependencies.sol | 72 ------ ethereum/foundry.toml | 2 +- ethereum/package.json | 6 +- .../shell-scripts/run_integration_tests.sh | 33 --- 9 files changed, 66 insertions(+), 360 deletions(-) delete mode 100644 ethereum/forge-scripts/deploy_contracts.sol delete mode 100644 ethereum/forge-scripts/deploy_dependencies.sol diff --git a/ethereum/Makefile b/ethereum/Makefile index 7c63182..7cb49ba 100644 --- a/ethereum/Makefile +++ b/ethereum/Makefile @@ -1,6 +1,6 @@ SOURCE_FILES:=$(shell find contracts -name "*.sol") -.PHONY: dependencies forge_dependencies wormhole_dependencies unit-test integration-test clean all +.PHONY: dependencies forge_dependencies unit-test integration-test clean all all: build @@ -25,13 +25,7 @@ lib/forge-std: lib/openzeppelin-contracts: forge install openzeppelin/openzeppelin-contracts@0457042d93d9dfd760dbaa06a4d2f1216fdbe297 --no-git --no-commit -.PHONY: wormhole_dependencies -wormhole_dependencies: wormhole - -wormhole: - git clone --depth 1 --branch feat/batch_vaa_alternative --single-branch https://github.com/wormhole-foundation/wormhole.git - -dependencies: node_modules forge_dependencies wormhole_dependencies +dependencies: node_modules forge_dependencies build: dependencies npm run build @@ -41,11 +35,11 @@ build: dependencies cp $< $@ .PHONY: test -test: unit-test integration-test +test: unit-test .PHONY: unit-test unit-test: dependencies build - npm run unit-test + npm run forge-test .PHONY: integration-test integration-test: dependencies build @@ -53,4 +47,4 @@ integration-test: dependencies build .PHONY: clean clean: - rm -rf anvil.log .env node_modules build lib wormhole + rm -rf anvil.log .env node_modules build lib diff --git a/ethereum/contracts/coreRelayer/CoreRelayer.sol b/ethereum/contracts/coreRelayer/CoreRelayer.sol index eaa7c61..d98d945 100644 --- a/ethereum/contracts/coreRelayer/CoreRelayer.sol +++ b/ethereum/contracts/coreRelayer/CoreRelayer.sol @@ -277,7 +277,7 @@ contract CoreRelayer is CoreRelayerDelivery { // because we will then know how much of the 'maxTransactionFee' of the current delivery is still available for use in this forward setForwardInstruction( ForwardInstruction({ - container: instructionsContainer, + container: encodeDeliveryInstructionsContainer(instructionsContainer), nonce: nonce, msgValue: msg.value, totalFee: totalFee, diff --git a/ethereum/contracts/coreRelayer/CoreRelayerDelivery.sol b/ethereum/contracts/coreRelayer/CoreRelayerDelivery.sol index 4a64566..5c04a59 100644 --- a/ethereum/contracts/coreRelayer/CoreRelayerDelivery.sol +++ b/ethereum/contracts/coreRelayer/CoreRelayerDelivery.sol @@ -41,7 +41,8 @@ contract CoreRelayerDelivery is CoreRelayerGovernance { internal returns (bool forwardIsFunded) { - DeliveryInstructionsContainer memory container = forwardInstruction.container; + DeliveryInstructionsContainer memory container = + decodeDeliveryInstructionsContainer(forwardInstruction.container); // Add any additional funds which were passed in to the forward as msg.value transactionFeeRefundAmount = transactionFeeRefundAmount + forwardInstruction.msgValue; @@ -103,18 +104,17 @@ contract CoreRelayerDelivery is CoreRelayerGovernance { * * @param internalInstruction instruction to execute * @param encodedVMs list of signed wormhole messages (VAAs) - * @param deliveryVaaHash hash of delivery VAA - * @param relayerRefund address to send the relayer's refund to - * @param sourceChain chain id that the delivery originated from - * @param sourceSequence sequence number of the delivery VAA on the source chain + * @param relayerRefundAddress address to send the relayer's refund to + * @param vaaInfo struct specifying: + * - sourceChain chain id that the delivery originated from + * - sourceSequence sequence number of the delivery VAA on the source chain + * - deliveryVaaHash hash of delivery VAA */ function _executeDelivery( DeliveryInstruction memory internalInstruction, bytes[] memory encodedVMs, - bytes32 deliveryVaaHash, - address payable relayerRefund, - uint16 sourceChain, - uint64 sourceSequence + address payable relayerRefundAddress, + DeliveryVAAInfo memory vaaInfo ) internal { // lock the contract to prevent reentrancy if (isContractLocked()) { @@ -161,26 +161,44 @@ contract CoreRelayerDelivery is CoreRelayerGovernance { status = callToTargetContractSucceeded ? DeliveryStatus.SUCCESS : DeliveryStatus.RECEIVER_FAILURE; } + // Emit a status update that can be read by a SDK + emit Delivery({ + recipientContract: fromWormholeFormat(internalInstruction.targetAddress), + sourceChain: vaaInfo.sourceChain, + sequence: vaaInfo.sourceSequence, + deliveryVaaHash: vaaInfo.deliveryVaaHash, + status: status + }); + + payRefunds( + internalInstruction, + relayerRefundAddress, + transactionFeeRefundAmount, + callToTargetContractSucceeded, + forwardingRequest.isValid, + forwardIsFunded + ); + } + + function payRefunds( + DeliveryInstruction memory internalInstruction, + address payable relayerRefundAddress, + uint256 transactionFeeRefundAmount, + bool callToTargetContractSucceeded, + bool forwardingRequestExists, + bool forwardWasFunded + ) internal { // Amount of receiverValue that is refunded to the user (0 if the call to 'receiveWormholeMessages' did not revert, or the full receiverValue otherwise) uint256 receiverValueRefundAmount = (callToTargetContractSucceeded ? 0 : internalInstruction.receiverValueTarget); // Total refund to the user - uint256 refundToRefundAddress = receiverValueRefundAmount + (forwardIsFunded ? 0 : transactionFeeRefundAmount); + uint256 refundToRefundAddress = receiverValueRefundAmount + (forwardWasFunded ? 0 : transactionFeeRefundAmount); // Whether or not the refund succeeded bool refundPaidToRefundAddress = pay(payable(fromWormholeFormat(internalInstruction.refundAddress)), refundToRefundAddress); - // Emit a status update that can be read by a SDK - emit Delivery({ - recipientContract: fromWormholeFormat(internalInstruction.targetAddress), - sourceChain: sourceChain, - sequence: sourceSequence, - deliveryVaaHash: deliveryVaaHash, - status: status - }); - uint256 wormholeMessageFee = wormhole().messageFee(); // Funds that the relayer passed as msg.value over what they needed uint256 extraRelayerFunds = ( @@ -192,8 +210,8 @@ contract CoreRelayerDelivery is CoreRelayerGovernance { // + (the users refund if that refund didn't succeed) uint256 relayerRefundAmount = extraRelayerFunds + (internalInstruction.maximumRefundTarget - transactionFeeRefundAmount) - + (forwardingRequest.isValid ? 0 : wormholeMessageFee) + (refundPaidToRefundAddress ? 0 : refundToRefundAddress); - pay(relayerRefund, relayerRefundAmount); + + (forwardingRequestExists ? 0 : wormholeMessageFee) + (refundPaidToRefundAddress ? 0 : refundToRefundAddress); + pay(relayerRefundAddress, relayerRefundAmount); } function verifyRelayerVM(IWormhole.VM memory vm) internal view returns (bool) { @@ -300,10 +318,12 @@ contract CoreRelayerDelivery is CoreRelayerGovernance { _executeDelivery( originalInstruction, targetParams.sourceEncodedVMs, - originalDeliveryVM.hash, targetParams.relayerRefundAddress, - originalDeliveryVM.emitterChainId, - originalDeliveryVM.sequence + DeliveryVAAInfo({ + sourceChain: originalDeliveryVM.emitterChainId, + sourceSequence: originalDeliveryVM.sequence, + deliveryVaaHash: originalDeliveryVM.hash + }) ); } @@ -427,10 +447,12 @@ contract CoreRelayerDelivery is CoreRelayerGovernance { _executeDelivery( deliveryInstruction, targetParams.encodedVMs, - deliveryVM.hash, targetParams.relayerRefundAddress, - deliveryVM.emitterChainId, - deliveryVM.sequence + DeliveryVAAInfo({ + sourceChain: deliveryVM.emitterChainId, + sourceSequence: deliveryVM.sequence, + deliveryVaaHash: deliveryVM.hash + }) ); } diff --git a/ethereum/contracts/coreRelayer/CoreRelayerStructs.sol b/ethereum/contracts/coreRelayer/CoreRelayerStructs.sol index 76f6052..f6d95b2 100644 --- a/ethereum/contracts/coreRelayer/CoreRelayerStructs.sol +++ b/ethereum/contracts/coreRelayer/CoreRelayerStructs.sol @@ -41,7 +41,7 @@ abstract contract CoreRelayerStructs { } struct ForwardInstruction { - DeliveryInstructionsContainer container; + bytes container; uint32 nonce; address sender; uint256 msgValue; @@ -49,4 +49,10 @@ abstract contract CoreRelayerStructs { address relayProvider; bool isValid; } + + struct DeliveryVAAInfo { + uint16 sourceChain; + uint64 sourceSequence; + bytes32 deliveryVaaHash; + } } diff --git a/ethereum/forge-scripts/deploy_contracts.sol b/ethereum/forge-scripts/deploy_contracts.sol deleted file mode 100644 index 1396083..0000000 --- a/ethereum/forge-scripts/deploy_contracts.sol +++ /dev/null @@ -1,211 +0,0 @@ -// SPDX-License-Identifier: Apache 2 - -pragma solidity ^0.8.0; - -import "forge-std/Script.sol"; - -import {Migrations} from "wormhole/ethereum/contracts/Migrations.sol"; -import {IWormhole} from "contracts/interfaces/IWormhole.sol"; -import {RelayProvider} from "contracts/relayProvider/RelayProvider.sol"; -import {RelayProviderSetup} from "contracts/relayProvider/RelayProviderSetup.sol"; -import {RelayProviderImplementation} from "contracts/relayProvider/RelayProviderImplementation.sol"; -import {RelayProviderProxy} from "contracts/relayProvider/RelayProviderProxy.sol"; -import {CoreRelayer} from "contracts/coreRelayer/CoreRelayer.sol"; -import {CoreRelayerSetup} from "contracts/coreRelayer/CoreRelayerSetup.sol"; -import {CoreRelayerImplementation} from "contracts/coreRelayer/CoreRelayerImplementation.sol"; -import {CoreRelayerProxy} from "contracts/coreRelayer/CoreRelayerProxy.sol"; -import {MockRelayerIntegration} from "contracts/mock/MockRelayerIntegration.sol"; - -import "forge-std/console.sol"; - -//Goal deploy all necessary contracts to one chain - -//Initialize our wallet & RPC provider -//Initialize our Wormhole object - -//Step 1: Deploy RelayProvider -// Deploy Contracts -// Call setup -// Set Reward Address, set delivery address, set delivergasoverhead, set price table, set maximum budget - -//Step 2: Deploy CoreRelayer -// Deploy Contracts -// Call setup -// later: register all core relayers with eachother - -//Step 3: Deploy xMint -// Deploy Hub if hubchain, deploy spoke if spoke chain -// call setup - -contract ContractScript is Script { - Migrations migrations; - IWormhole wormhole; - - // GasOracle - RelayProviderSetup relayProviderSetup; - RelayProviderImplementation relayProviderImplementation; - RelayProviderProxy relayProviderProxy; - - // CoreRelayer - CoreRelayerSetup coreRelayerSetup; - CoreRelayerImplementation coreRelayerImplementation; - CoreRelayerProxy coreRelayerProxy; - CoreRelayer coreRelayer; - - // MockRelayerIntegration - MockRelayerIntegration mockRelayerIntegration; - - address TILT_WORMHOLE_ADDRESS = 0xC89Ce4735882C9F0f0FE26686c53074E09B0D550; - address TILT_MIGRATION_ADDRESS = 0xe78A0F7E598Cc8b0Bb87894B0F60dD2a88d6a8Ab; - bool isTilt = false; - uint16 chainId; - address wormholeAddress; - - function setUp() public {} - - function deployRelayProvider() public { - // first Setup - relayProviderSetup = new RelayProviderSetup(); - - // next Implementation - relayProviderImplementation = new RelayProviderImplementation(); - - // setup Proxy using Implementation - relayProviderProxy = new RelayProviderProxy( - address(relayProviderSetup), - abi.encodeWithSelector( - bytes4(keccak256("setup(address,uint16)")), - address(relayProviderImplementation), - wormhole.chainId() - ) - ); - - // following is used just to roll to the next block - if (isTilt) { - migrations.setCompleted(69); - } - } - - function deployCoreRelayer() public { - // first Setup - coreRelayerSetup = new CoreRelayerSetup(); - - // next Implementation - coreRelayerImplementation = new CoreRelayerImplementation(); - - // setup Proxy using Implementation - coreRelayerProxy = new CoreRelayerProxy( - address(coreRelayerSetup), - abi.encodeWithSelector( - bytes4(keccak256("setup(address,uint16,address,address)")), - address(coreRelayerImplementation), - wormhole.chainId(), - address(wormhole), - address(relayProviderProxy) - ) - ); - - // following is used just to roll to the next block - if (isTilt) { - migrations.setCompleted(69); - } - - coreRelayer = CoreRelayer(address(coreRelayerProxy)); - } - - function configureRelayProvider() public { - address currentAddress = address(this); - RelayProvider provider = RelayProvider(address(relayProviderProxy)); - CoreRelayer core_relayer = CoreRelayer(address(coreRelayerProxy)); - - //Set Reward Address, - provider.updateRewardAddress(currentAddress); - - uint16[] memory chains; - - //set delivery address, - if (isTilt) { - chains = new uint16[](2); - chains[0] = 2; - chains[1] = 4; - } else { - chains = new uint16[](2); - chains[0] = 6; - chains[1] = 14; - } - - bytes32 thing = core_relayer.toWormholeFormat(currentAddress); - console.log("got current address wh"); - - for (uint16 i = 0; i < chains.length; i++) { - console.log("about to set delivery address"); - provider.updateDeliveryAddress(chains[i], core_relayer.toWormholeFormat(currentAddress)); - provider.updateAssetConversionBuffer(chains[i], 5, 100); - provider.updateDeliverGasOverhead(chains[i], 350000); - provider.updatePrice(chains[i], uint128(300000000000), uint128(100000)); - provider.updateMaximumBudget(chains[i], uint256(1000000000000000000)); - - console.log("max budget for chain %s", i); - console.log(provider.quoteMaximumBudget(i)); - } - } - - function configureCoreRelayer() public { - //Only thing to do here is register all the chains together - // contract already registers itself in the setup - // CoreRelayer core_relayer = CoreRelayer(address(coreRelayerProxy)); - // core_relayer.registerCoreRelayerContract(chainId, core_relayer.toWormholeFormat(address(core_relayer))); - } - - // function deployMockRelayerIntegration() public { - // // deploy the mock integration contract - // mockRelayerIntegration = new MockRelayerIntegration( - // address(wormhole), - // address(coreRelayerProxy) - // ); - // } - - function deployRelayerIntegrationContract() public { - // if(chainId == 2 || chainId == 6) { - // //deploy hub - // } else { - // //deploy spoke - // } - - mockRelayerIntegration = new MockRelayerIntegration(address(wormhole), - address(coreRelayerProxy)); - } - - function run(address _wormholeAddress) public { - //actual setup - wormhole = IWormhole(_wormholeAddress); - wormholeAddress = _wormholeAddress; - chainId = wormhole.chainId(); - isTilt = (wormholeAddress == TILT_WORMHOLE_ADDRESS); - if (isTilt) { - console.log("running in tilt"); - migrations = Migrations(TILT_MIGRATION_ADDRESS); - } - - // begin sending transactions - vm.startBroadcast(); - - deployRelayProvider(); - deployCoreRelayer(); - - configureRelayProvider(); - configureCoreRelayer(); - - vm.roll(block.number + 1); - - deployRelayerIntegrationContract(); - - mockRelayerIntegration.sendMessage{ - gas: 1000000, - value: coreRelayer.quoteGas(chainId, 1000000, coreRelayer.getDefaultRelayProvider()) + 10000000000 - }(abi.encode("Hello World"), chainId, address(mockRelayerIntegration)); - - // finished - vm.stopBroadcast(); - } -} diff --git a/ethereum/forge-scripts/deploy_dependencies.sol b/ethereum/forge-scripts/deploy_dependencies.sol deleted file mode 100644 index 79f19e5..0000000 --- a/ethereum/forge-scripts/deploy_dependencies.sol +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: Apache 2 - -pragma solidity ^0.8.0; - -import "forge-std/Script.sol"; - -import {Migrations} from "wormhole/ethereum/contracts/Migrations.sol"; -import {Setup} from "wormhole/ethereum/contracts/Setup.sol"; -import {Implementation} from "wormhole/ethereum/contracts/Implementation.sol"; -import {Wormhole} from "wormhole/ethereum/contracts/Wormhole.sol"; - -import "forge-std/console.sol"; - -contract ContractScript is Script { - Migrations migrations; - Setup setup; - Implementation implementation; - Wormhole wormhole; - - function setUp() public {} - - function deployMigrations() public { - migrations = new Migrations(); - - // following is used just to roll to the next block - migrations.setCompleted(1); - } - - function deployWormhole() public { - // deploy Setup - setup = new Setup(); - - // deploy Implementation - implementation = new Implementation(); - - address[] memory guardians = new address[](1); - guardians[0] = 0xbeFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe; - - // deploy Wormhole - wormhole = new Wormhole( - address(setup), - abi.encodeWithSelector( - bytes4(keccak256("setup(address,address[],uint16,uint16,bytes32,uint256)")), - address(implementation), - guardians, - uint16(2), // wormhole chain id - uint16(1), // governance chain id - 0x0000000000000000000000000000000000000000000000000000000000000004, // governance contract - block.chainid // evm chain id - ) - ); - - // following is used just to roll to the next block - migrations.setCompleted(2); - } - - function run() public { - // begin sending transactions - vm.startBroadcast(); - - // Migrations.sol - deployMigrations(); - - // Setup.sol, Implementation.sol, Wormhole.sol - deployWormhole(); - - // TODO: Token Bridge, NFT Bridge - - // finish - vm.stopBroadcast(); - } -} diff --git a/ethereum/foundry.toml b/ethereum/foundry.toml index c91048c..70cb444 100644 --- a/ethereum/foundry.toml +++ b/ethereum/foundry.toml @@ -2,7 +2,7 @@ solc_version = "0.8.17" optimizer = true optimizer_runs = 200 -via_ir = true +via_ir = false extra_output = ["metadata", "storageLayout", "evm.deployedBytecode.immutableReferences"] src = "contracts" diff --git a/ethereum/package.json b/ethereum/package.json index 318b49b..2f3fc9c 100644 --- a/ethereum/package.json +++ b/ethereum/package.json @@ -16,14 +16,14 @@ "ts-node": "^10.9.1" }, "scripts": { - "build": "forge build -o build", - "unit-test": "forge test -vvvvv", + "build": "forge build -o build --via-ir", + "forge-test": "forge test -vvv --via-ir", "integration-test": "bash shell-scripts/run_integration_tests.sh", "typechain": "bash ../sdk/scripts/make_ethers_types.sh", "flatten": "mkdir -p node_modules/@poanet/solidity-flattener/contracts && cp -r contracts/* node_modules/@poanet/solidity-flattener/contracts/ && poa-solidity-flattener", "deployAndConfigureTilt": "ENV=tilt bash ./ts-scripts/shell/deployConfigureTest.sh", "readContractsTestnet": "ENV=testnet bash ./ts-scripts/shell/readContractStatus.sh", - "size": "forge build --sizes --force" + "size": "forge build --sizes --force --via-ir" }, "author": "", "license": "ISC", diff --git a/ethereum/shell-scripts/run_integration_tests.sh b/ethereum/shell-scripts/run_integration_tests.sh index e52e914..75b75e5 100644 --- a/ethereum/shell-scripts/run_integration_tests.sh +++ b/ethereum/shell-scripts/run_integration_tests.sh @@ -1,38 +1,5 @@ #/bin/bash -pgrep anvil > /dev/null -if [ $? -eq 0 ]; then - echo "anvil already running" - exit 1; -fi - -anvil \ - -m "myth like bonus scare over problem client lizard pioneer submit female collect" \ - --timestamp 0 \ - --chain-id 1 > anvil.log & - -sleep 2 - -## anvil's rpc -RPC="http://localhost:8545" - -## first key from mnemonic above -PRIVATE_KEY="0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d" - -echo "deploy dependencies" -forge script forge-scripts/deploy_dependencies.sol \ - --rpc-url $RPC \ - --private-key $PRIVATE_KEY \ - --broadcast --slow > deploy.out 2>&1 - -echo "deploy contracts" -forge script forge-scripts/deploy_contracts.sol \ - --rpc-url $RPC \ - --private-key $PRIVATE_KEY \ - --broadcast --slow >> deploy.out 2>&1 - ## run tests here npx ts-mocha -t 1000000 ts-test/*.ts -# nuke -pkill anvil \ No newline at end of file