From f2bddcb38d06051afd5f1a4c70746ebdd29842bf Mon Sep 17 00:00:00 2001 From: Henry <11198460+godzillaba@users.noreply.github.com> Date: Thu, 7 Mar 2024 15:04:04 -0500 Subject: [PATCH 1/9] fix bash scripts (#24) --- test/e2e/test-e2e.bash | 9 ++++++++- test/fork/test-fork.bash | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/test/e2e/test-e2e.bash b/test/e2e/test-e2e.bash index 0f0f104b..699c92b6 100755 --- a/test/e2e/test-e2e.bash +++ b/test/e2e/test-e2e.bash @@ -20,6 +20,13 @@ if [ $? -ne 0 ]; then exit 1 fi -yarn hardhat compile +yarn hardhat compile + +if [ $? -ne 0 ]; then + echo "Failed to compile" + exit 1 +fi yarn mocha test/e2e/ --timeout 30000000 --bail + +exit $? diff --git a/test/fork/test-fork.bash b/test/fork/test-fork.bash index 52b54c99..b28fab00 100755 --- a/test/fork/test-fork.bash +++ b/test/fork/test-fork.bash @@ -30,7 +30,7 @@ for dir in $chains; do else echo "Running hardhat tests against \$$forkUrlName ..." FORK_URL=$forkUrl yarn run hardhat test $hardhatFiles --network fork - CODE=$? + code=$? fi [ "$code" -ne 0 ] && exit $code From dc0ac29f3f1062e35cacb54e2131f074cb4e9eb3 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 25 Jul 2024 18:50:57 +0200 Subject: [PATCH 2/9] Unused errors checker (#26) * Add action which checks if there are unused errors * Rename step * main * Use main branch --------- Co-authored-by: Henry <11198460+godzillaba@users.noreply.github.com> --- .github/workflows/test.yml | 13 +++++++++++++ test/unused-errors/exceptions.txt | 0 2 files changed, 13 insertions(+) create mode 100644 test/unused-errors/exceptions.txt diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cb1cf56e..2600f09b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -84,3 +84,16 @@ jobs: - run: yarn minimal-install - run: yarn test:storage + + test-unused-errors: + name: Test Unused Errors + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Execute check + uses: OffchainLabs/actions/check-unused-errors@main + with: + directory: './contracts' + exceptions_file: './test/unused-errors/exceptions.txt' diff --git a/test/unused-errors/exceptions.txt b/test/unused-errors/exceptions.txt new file mode 100644 index 00000000..e69de29b From d6a159f90f4f805c98245eb4e26bb8f8ba333d4b Mon Sep 17 00:00:00 2001 From: Henry <11198460+godzillaba@users.noreply.github.com> Date: Fri, 26 Jul 2024 11:51:05 -0400 Subject: [PATCH 3/9] use hardhat-sizer (#29) --- hardhat.config.ts | 24 +++++++++++++++++++----- package.json | 3 ++- yarn.lock | 24 ++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 5d661820..c7dbc8e7 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,15 +1,27 @@ import { HardhatUserConfig } from 'hardhat/config' import '@nomicfoundation/hardhat-toolbox' import '@nomicfoundation/hardhat-foundry' +import 'hardhat-contract-sizer' -import { SolidityUserConfig } from 'hardhat/types' +import { SolcUserConfig } from 'hardhat/types' import toml from 'toml' import fs from 'fs' const config: HardhatUserConfig = { - solidity: getSolidityConfigFromFoundryToml( - process.env.FOUNDRY_PROFILE || 'default' - ), + solidity: { + ...getSolidityConfigFromFoundryToml(process.env.FOUNDRY_PROFILE), + // overrides here + // overrides: { + // 'contracts/MyContract.sol': { + // version: '0.8.0', + // settings: { + // optimizer: { + // enabled: false, + // }, + // }, + // }, + // }, + }, networks: { fork: { url: process.env.FORK_URL || 'http://localhost:8545', @@ -17,7 +29,9 @@ const config: HardhatUserConfig = { }, } -function getSolidityConfigFromFoundryToml(profile: string): SolidityUserConfig { +function getSolidityConfigFromFoundryToml( + profile: string | undefined +): SolcUserConfig { const data = toml.parse(fs.readFileSync('foundry.toml', 'utf-8')) const defaultConfig = data.profile['default'] diff --git a/package.json b/package.json index db673447..e9cd4f29 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "test:unit": "./test/unit/test-unit.bash", "test:fork": "./test/fork/test-fork.bash", "test:e2e": "./test/e2e/test-e2e.bash", - "test:sizes": "forge build --sizes", + "test:sizes": "STRICT=true yarn hardhat size-contracts", "test:gas-check": "forge snapshot --check --tolerance 1 --match-path \"test/unit/**/*.t.sol\"", "test:sigs": "./test/signatures/test-sigs.bash", "test:storage": "./test/storage/test-storage.bash", @@ -44,6 +44,7 @@ "ethers": "^6.4.0", "ethers-v5": "npm:ethers@^5.7.2", "hardhat": "^2.19.5", + "hardhat-contract-sizer": "^2.10.0", "hardhat-gas-reporter": "^1.0.8", "prettier": "^3.2.5", "solidity-coverage": "^0.8.0", diff --git a/yarn.lock b/yarn.lock index bd6bef75..46f7a594 100644 --- a/yarn.lock +++ b/yarn.lock @@ -48,6 +48,11 @@ "@chainsafe/persistent-merkle-tree" "^0.4.2" case "^1.6.3" +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -1757,6 +1762,15 @@ cli-table3@^0.5.0: optionalDependencies: colors "^1.1.2" +cli-table3@^0.6.0: + version "0.6.5" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.5.tgz#013b91351762739c16a9567c21a04632e449bf2f" + integrity sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -2291,6 +2305,7 @@ ethereumjs-util@^7.1.4: rlp "^2.2.4" "ethers-v5@npm:ethers@^5.7.2", ethers@^5.7.1, ethers@^5.7.2: + name ethers-v5 version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -2755,6 +2770,15 @@ handlebars@^4.0.1: optionalDependencies: uglify-js "^3.1.4" +hardhat-contract-sizer@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/hardhat-contract-sizer/-/hardhat-contract-sizer-2.10.0.tgz#72646f43bfe50e9a5702c9720c9bc3e77d93a2c9" + integrity sha512-QiinUgBD5MqJZJh1hl1jc9dNnpJg7eE/w4/4GEnrcmZJJTDbVFNe3+/3Ep24XqISSkYxRz36czcPHKHd/a0dwA== + dependencies: + chalk "^4.0.0" + cli-table3 "^0.6.0" + strip-ansi "^6.0.0" + hardhat-gas-reporter@^1.0.8: version "1.0.10" resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.10.tgz#ebe5bda5334b5def312747580cd923c2b09aef1b" From 8f9ee568a099b74f466a7ecbaa351758a01fff14 Mon Sep 17 00:00:00 2001 From: Henry <11198460+godzillaba@users.noreply.github.com> Date: Fri, 26 Jul 2024 11:51:28 -0400 Subject: [PATCH 4/9] move template scripts to their own dir (#28) * move template scripts to their own dir * fix --- .gas-snapshot | 2 +- README.md | 6 +++--- package.json | 2 +- scripts/{ => template}/delete-samples.bash | 2 +- scripts/{ => template}/prepublish.ts | 2 +- scripts/{ => template}/print-contracts.bash | 0 scripts/{ => template}/publish.bash | 2 +- test/util/forge-inspect.bash | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) rename scripts/{ => template}/delete-samples.bash (91%) rename scripts/{ => template}/prepublish.ts (96%) rename scripts/{ => template}/print-contracts.bash (100%) rename scripts/{ => template}/publish.bash (94%) diff --git a/.gas-snapshot b/.gas-snapshot index d40dfc21..fae4d8da 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,2 +1,2 @@ -CounterTest:testFuzz_SetNumber(uint256) (runs: 256, μ: 27314, ~: 28403) +CounterTest:testFuzz_SetNumber(uint256) (runs: 256, μ: 28092, ~: 28403) CounterTest:test_Increment() (gas: 28379) \ No newline at end of file diff --git a/README.md b/README.md index 7c8b7271..82e73bcb 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ - E2E testing with Hardhat + Arbitrum SDK + testnode ## Removing Sample Files -Run `scripts/delete-samples.bash` to remove `Counter.sol` and sample test files. +Run `scripts/template/delete-samples.bash` to remove `Counter.sol` and sample test files. ## Compiler Settings Solc version and optimizer runs are defined in `foundry.toml` and copied by `hardhat.config.ts`. @@ -79,7 +79,7 @@ To add the end to end setup to an existing hardhat+foundry project: ## Signatures and Storage Tests These will fail if signatures or storage of any contract defined in `contracts/` changes. -Abstract contracts and interfaces are not checked. `scripts/print-contracts.bash` produces the list of contracts that are checked in these tests. +Abstract contracts and interfaces are not checked. `scripts/template/print-contracts.bash` produces the list of contracts that are checked in these tests. Use `yarn test:signatures` and `yarn test:storage`. @@ -107,7 +107,7 @@ A helper script, `minimal-publish` is included to generate a minimal `package.js - Restore original files - Commit and tag if published successfully -Note that `yarn publish --non-interactive` is used, so there will be no prompt for package version. See `scripts/publish.bash` +Note that `yarn publish --non-interactive` is used, so there will be no prompt for package version. See `scripts/template/publish.bash` ## TODO / Wishlist - license? diff --git a/package.json b/package.json index e9cd4f29..436f9503 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "scripts": { "prepare": "forge install && cd lib/arbitrum-sdk && yarn", "minimal-install": "yarn --ignore-scripts && forge install", - "minimal-publish": "./scripts/publish.bash", + "minimal-publish": "./scripts/template/publish.bash", "audit:ci": "audit-ci --config ./audit-ci.jsonc", "upload-all-selectors": "forge build && find ./out -name \"*.json\" -exec cast upload-signature {} +", "format": "cat .prettierignore .gitignore > .pignore && prettier --ignore-path .pignore \"**/*.{js,ts,json}\" --write && rm .pignore && forge fmt", diff --git a/scripts/delete-samples.bash b/scripts/template/delete-samples.bash similarity index 91% rename from scripts/delete-samples.bash rename to scripts/template/delete-samples.bash index a12345fd..8a2b84eb 100755 --- a/scripts/delete-samples.bash +++ b/scripts/template/delete-samples.bash @@ -16,4 +16,4 @@ rm test/fork/eth/Sample.t.sol test/fork/eth/Sample.test.ts rm test/e2e/Counter.test.ts # delete this script as it is no longer needed -rm scripts/delete-samples.bash +rm scripts/template/delete-samples.bash diff --git a/scripts/prepublish.ts b/scripts/template/prepublish.ts similarity index 96% rename from scripts/prepublish.ts rename to scripts/template/prepublish.ts index 9e66c887..0f61f981 100644 --- a/scripts/prepublish.ts +++ b/scripts/template/prepublish.ts @@ -1,5 +1,5 @@ import * as fs from 'fs' -import hardhatConfig from '../hardhat.config' +import hardhatConfig from '../../hardhat.config' /* Generates a minimal package.json and hardhat.config.js for publishing to npm diff --git a/scripts/print-contracts.bash b/scripts/template/print-contracts.bash similarity index 100% rename from scripts/print-contracts.bash rename to scripts/template/print-contracts.bash diff --git a/scripts/publish.bash b/scripts/template/publish.bash similarity index 94% rename from scripts/publish.bash rename to scripts/template/publish.bash index b33a4f52..b684d616 100755 --- a/scripts/publish.bash +++ b/scripts/template/publish.bash @@ -8,7 +8,7 @@ # prepublish # must run with hardhat to generate hardhat.config.js -yarn hardhat run scripts/prepublish.ts +yarn hardhat run scripts/template/prepublish.ts if [ $? -ne 0 ]; then echo "Prepublish failed" diff --git a/test/util/forge-inspect.bash b/test/util/forge-inspect.bash index a4640ead..0237e195 100755 --- a/test/util/forge-inspect.bash +++ b/test/util/forge-inspect.bash @@ -2,7 +2,7 @@ # usage: ./test/util/forge-inspect.bash -contracts=$(./scripts/print-contracts.bash) +contracts=$(./scripts/template/print-contracts.bash) if [[ $? != "0" ]]; then echo "Failed to get contracts" exit 1 From 3d6c1cb5363f30f4c1240ea87327515baa1bd35d Mon Sep 17 00:00:00 2001 From: Henry <11198460+godzillaba@users.noreply.github.com> Date: Fri, 26 Jul 2024 11:54:30 -0400 Subject: [PATCH 5/9] simplify test scripts (#25) * simplify test scripts * update readme --- README.md | 5 +-- scripts/template/delete-samples.bash | 3 +- test/fork/{eth => }/Sample.t.sol | 5 +++ test/fork/{eth => }/Sample.test.ts | 5 +++ test/fork/arb/Sample.t.sol | 11 ------ test/fork/arb/Sample.test.ts | 14 -------- test/fork/test-fork.bash | 50 ++++------------------------ test/unit/test-unit.bash | 23 ++++--------- 8 files changed, 24 insertions(+), 92 deletions(-) rename test/fork/{eth => }/Sample.t.sol (65%) rename test/fork/{eth => }/Sample.test.ts (69%) delete mode 100644 test/fork/arb/Sample.t.sol delete mode 100644 test/fork/arb/Sample.test.ts diff --git a/README.md b/README.md index 82e73bcb..cafd4516 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,9 @@ Run `scripts/template/delete-samples.bash` to remove `Counter.sol` and sample te Solc version and optimizer runs are defined in `foundry.toml` and copied by `hardhat.config.ts`. ## Fork Tests -Fork tests are located in `test/fork//` and will run against the latest block of `$_FORK_URL`. +Fork tests are located in `test/fork/`. Use `$_FORK_URL=*** $_FORK_URL=*** yarn test:fork`. -Test files should only be placed in `test/fork//` (subdrectories are allowed). -Test files placed directly in `test/fork/` will not run. - `yarn test:fork` will pass if there are no test files. ### Disabling / Removing diff --git a/scripts/template/delete-samples.bash b/scripts/template/delete-samples.bash index 8a2b84eb..f0862795 100755 --- a/scripts/template/delete-samples.bash +++ b/scripts/template/delete-samples.bash @@ -9,8 +9,7 @@ rm contracts/Counter.sol rm test/unit/Counter.test.ts test/unit/Counter.t.sol # remove sample fork tests -rm test/fork/arb/Sample.t.sol test/fork/arb/Sample.test.ts -rm test/fork/eth/Sample.t.sol test/fork/eth/Sample.test.ts +rm test/fork/Sample.t.sol test/fork/Sample.test.ts # remove sample e2e tests rm test/e2e/Counter.test.ts diff --git a/test/fork/eth/Sample.t.sol b/test/fork/Sample.t.sol similarity index 65% rename from test/fork/eth/Sample.t.sol rename to test/fork/Sample.t.sol index d5192cd9..dd5626dd 100644 --- a/test/fork/eth/Sample.t.sol +++ b/test/fork/Sample.t.sol @@ -4,7 +4,12 @@ pragma solidity ^0.8.13; import {Test, console} from "forge-std/Test.sol"; contract SampleForkTest is Test { + function setUp() public { + vm.selectFork(vm.createFork(vm.envString("ETH_FORK_URL"))); + } + function testCode() public { + vm.createFork(vm.envString("ETH_FORK_URL")); // Arb1 Sequencer Inbox assertGt(0x1c479675ad559DC151F6Ec7ed3FbF8ceE79582B6.code.length, 0); } diff --git a/test/fork/eth/Sample.test.ts b/test/fork/Sample.test.ts similarity index 69% rename from test/fork/eth/Sample.test.ts rename to test/fork/Sample.test.ts index 93a3193a..53aeb583 100644 --- a/test/fork/eth/Sample.test.ts +++ b/test/fork/Sample.test.ts @@ -1,7 +1,12 @@ import { expect } from 'chai' import { ethers } from 'hardhat' +import { reset } from '@nomicfoundation/hardhat-network-helpers' describe('Sample', () => { + before(async () => { + await reset(process.env.ETH_FORK_URL) + }) + it('should have code at sequencer inbox', async () => { expect( ( diff --git a/test/fork/arb/Sample.t.sol b/test/fork/arb/Sample.t.sol deleted file mode 100644 index 21b961e2..00000000 --- a/test/fork/arb/Sample.t.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Test, console} from "forge-std/Test.sol"; - -contract SampleForkTest is Test { - function testCode() public { - // L2GatewayRouter - assertGt(0x5288c571Fd7aD117beA99bF60FE0846C4E84F933.code.length, 0); - } -} diff --git a/test/fork/arb/Sample.test.ts b/test/fork/arb/Sample.test.ts deleted file mode 100644 index 620231ac..00000000 --- a/test/fork/arb/Sample.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { expect } from 'chai' -import { ethers } from 'hardhat' - -describe('Sample', () => { - it('should have code at L2 Gateway Router', async () => { - expect( - ( - await ethers.provider.getCode( - '0x5288c571Fd7aD117beA99bF60FE0846C4E84F933' - ) - ).length - ).to.be.gt(2) - }) -}) diff --git a/test/fork/test-fork.bash b/test/fork/test-fork.bash index b28fab00..33981619 100755 --- a/test/fork/test-fork.bash +++ b/test/fork/test-fork.bash @@ -1,48 +1,10 @@ #!/bin/bash -# run fork tests, tests in fork// will be run against _FORK_URL -# if there is a chain dir without a corresponding env var, the script will fail +# early exit on failure +set -e -shopt -s globstar +# run hardhat tests if there are any +test $(find test/fork -name '*.test.ts' | wc -l) -eq 0 || yarn hardhat test $(find test/fork -name '*.test.ts') -chains=$(ls -d ./test/fork/*/ 2>/dev/null) - -if [ -z "$chains" ]; then - echo "No directories found in ./test/fork/" - exit 0 -fi - -for dir in $chains; do - dirName=$(basename "$dir") - forkUrlName="${dirName^^}_FORK_URL" - forkUrl="${!forkUrlName}" - - if [ -z "$forkUrl" ]; then - echo "No value found for $forkUrlName" - exit 1 - fi - - code=0 - - hardhatFiles=$(find "$dir" -name "*.test.ts") - if [ -z "$hardhatFiles" ]; then - echo "No .test.ts files found in $dir" - else - echo "Running hardhat tests against \$$forkUrlName ..." - FORK_URL=$forkUrl yarn run hardhat test $hardhatFiles --network fork - code=$? - fi - [ "$code" -ne 0 ] && exit $code - - foundryFiles=$(find "$dir" -name "*.t.sol") - if [ -z "$foundryFiles" ]; then - echo "No .t.sol files found in $dir" - else - echo "Running foundry tests against \$$forkUrlName ..." - forge test --fork-url $forkUrl --match-path "$dir**/*.t.sol" - code=$? - fi - [ "$code" -ne 0 ] && exit $code -done - -exit 0 \ No newline at end of file +# run foundry tests if there are any +test $(find test/fork -name '*.t.sol' | wc -l) -eq 0 || forge test --match-path 'test/fork/**/*.t.sol' \ No newline at end of file diff --git a/test/unit/test-unit.bash b/test/unit/test-unit.bash index 03887ba6..8e138609 100755 --- a/test/unit/test-unit.bash +++ b/test/unit/test-unit.bash @@ -1,21 +1,10 @@ #!/bin/bash -shopt -s globstar +# early exit on failure +set -e -code=0 +# run hardhat tests if there are any +test $(find test/unit -name '*.test.ts' | wc -l) -eq 0 || yarn hardhat test $(find test/unit -name '*.test.ts') -hardhatFiles=$(ls ./test/unit/**/*.test.ts 2>/dev/null) -if [ -n "$hardhatFiles" ]; then - yarn run hardhat test $hardhatFiles - code=$? -fi - -[ "$code" -ne 0 ] && exit $code - -foundryFiles=$(ls ./test/unit/**/*.t.sol 2>/dev/null) -if [ -n "$foundryFiles" ]; then - forge test --match-path "test/unit/*.t.sol" - code=$? -fi - -exit $code +# run foundry tests if there are any +test $(find test/unit -name '*.t.sol' | wc -l) -eq 0 || forge test --match-path 'test/unit/**/*.t.sol' \ No newline at end of file From fe7dabadf1c5739cebf576d87a194d2ff09329c6 Mon Sep 17 00:00:00 2001 From: Henry <11198460+godzillaba@users.noreply.github.com> Date: Tue, 30 Jul 2024 13:20:47 -0400 Subject: [PATCH 6/9] fix audit:ci --- audit-ci.jsonc | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/audit-ci.jsonc b/audit-ci.jsonc index 0967ef42..ea00c84c 100644 --- a/audit-ci.jsonc +++ b/audit-ci.jsonc @@ -1 +1,16 @@ -{} +{ + "$schema": "https://github.com/IBM/audit-ci/raw/main/docs/schema.json", + "low": true, + "allowlist": [ + // ws affected by a DoS when handling a request with many HTTP headers + "GHSA-3h5v-q93c-6h6q", + // follow-redirects' Proxy-Authorization header kept across hosts + "GHSA-cxjh-pqwp-8mfp", + // Undici's Proxy-Authorization header not cleared on cross-origin redirect for dispatch, request, stream, pipeline + "GHSA-m4v8-wqvr-p9f7", + // Undici's fetch with integrity option is too lax when algorithm is specified but hash value is in incorrect + "GHSA-9qxr-qj54-h672", + // Uncontrolled resource consumption in braces + "GHSA-grv7-fg5c-xmjg" + ] +} From 6cff3757f43d2887b161283286a37bce2a1c5fc1 Mon Sep 17 00:00:00 2001 From: Henry <11198460+godzillaba@users.noreply.github.com> Date: Wed, 7 Aug 2024 11:48:37 -0400 Subject: [PATCH 7/9] Mocks + DoubleProvider (#30) * simplify test-e2e.bash * add v5 to v6 conversion functions and add a note * return both versions of wallets and providers * mocks * move util to scripts/template * ... * getEnv fix * Revert "getEnv fix" This reverts commit f985a44684a070be3cc2b197ead5cfdde63a259c. * double provider (#33) * double provider * inheritance * better types * ... * update readme --- README.md | 12 ++++++++- scripts/template/delete-samples.bash | 3 +++ scripts/template/util.ts | 38 ++++++++++++++++++++++++++++ test/e2e/Counter.test.ts | 2 ++ test/e2e/test-e2e.bash | 15 +++-------- test/e2e/testSetup.ts | 31 +++++++++++++---------- test/mocks/SampleMock.sol | 8 ++++++ test/util/util.ts | 9 ------- 8 files changed, 82 insertions(+), 36 deletions(-) create mode 100644 scripts/template/util.ts create mode 100644 test/mocks/SampleMock.sol delete mode 100644 test/util/util.ts diff --git a/README.md b/README.md index cafd4516..7ba1f89a 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ To add the fork test setup to an existing hardhat+foundry project: - Copy `test/fork/` directory - Copy `test:fork` package script -## E2E Tests and the Arbitrum SDK +## E2E Tests, the Arbitrum SDK, and `DoubleWallet` / `DoubleProvider` End to end tests are located in `test/e2e/`, and ran by `yarn test:e2e`. The GitHub workflow defined in `.github/workflows/test-e2e.yml` will run test files against an L1+L2 nitro testnode setup by default. There are commented out jobs that add an L3 with ETH or custom fees. @@ -57,6 +57,16 @@ A separate ethers v5 dev dependency is included and can be imported for use with import { ethers as ethersv5 } from 'ethers-v5' ``` +Instead of using providers and wallets directly, use `DoubleProvider` and `DoubleWallet` defined in `scripts/template/util.ts`. Using these classes / types makes dealing with the two ethers version much easier. + +## Using Mock Contracts +Mock contracts like test tokens should live in `test/mocks`. Hardhat does not generate artifacts or types for contracts in `test/`, so to deploy and use them you should use foundry artifacts. For example: + +```typescript +import ArbSysMockArtifact from 'out/ArbSysMock.sol/ArbSysMock.json' +new ContractFactory(ArbSysMockArtifact.abi, ArbSysMockArtifact.bytecode, signer).deploy() +``` + ### Disabling / Removing To disable the end to end testing CI jobs, remove `on: pull_request:` from `.github/workflows/test-e2e.yml` diff --git a/scripts/template/delete-samples.bash b/scripts/template/delete-samples.bash index f0862795..e66ee345 100755 --- a/scripts/template/delete-samples.bash +++ b/scripts/template/delete-samples.bash @@ -14,5 +14,8 @@ rm test/fork/Sample.t.sol test/fork/Sample.test.ts # remove sample e2e tests rm test/e2e/Counter.test.ts +# remove sample mock +rm test/mocks/SampleMock.sol + # delete this script as it is no longer needed rm scripts/template/delete-samples.bash diff --git a/scripts/template/util.ts b/scripts/template/util.ts new file mode 100644 index 00000000..aa7d8828 --- /dev/null +++ b/scripts/template/util.ts @@ -0,0 +1,38 @@ +import { JsonRpcProvider, Provider, Wallet } from 'ethers' +import { ethers as ethersv5 } from 'ethers-v5' + +export type Unwrap = T extends Promise ? U : T + +export function getEnv(name: string): string { + const value = process.env[name] || '' + if (value === '') { + throw new Error(`Environment variable ${name} is not defined`) + } + return value +} + +export class DoubleProvider extends JsonRpcProvider { + public readonly v5: ethersv5.providers.JsonRpcProvider + constructor(public readonly url: string) { + super(url) + this.v5 = new ethersv5.providers.JsonRpcProvider(url) + } +} + +export class DoubleWallet extends Wallet { + public readonly provider!: Provider + public readonly v5: ethersv5.Wallet & { + provider: ethersv5.providers.JsonRpcProvider + } + + constructor( + privateKey: string, + public readonly doubleProvider: DoubleProvider + ) { + super(privateKey, doubleProvider) + this.v5 = new ethersv5.Wallet( + privateKey, + doubleProvider.v5 + ) as ethersv5.Wallet & { provider: ethersv5.providers.JsonRpcProvider } + } +} diff --git a/test/e2e/Counter.test.ts b/test/e2e/Counter.test.ts index bd170ead..3ab2e27a 100644 --- a/test/e2e/Counter.test.ts +++ b/test/e2e/Counter.test.ts @@ -7,6 +7,8 @@ This repository uses ethers v6, but the arbitrum sdk uses ethers v5. Using the sdk might be a bit tricky, but you can import v5 like this: import { ethers as ethersv5 } from 'ethers-v5' + +testSetup will return both v5 and v6 versions of signers and providers. */ describe('E2E Sample', () => { diff --git a/test/e2e/test-e2e.bash b/test/e2e/test-e2e.bash index 699c92b6..c7187b71 100755 --- a/test/e2e/test-e2e.bash +++ b/test/e2e/test-e2e.bash @@ -12,20 +12,11 @@ else export ORBIT_TEST=1 fi -cd lib/arbitrum-sdk && yarn gen:network && cd - - -# if the above command fails, exit -if [ $? -ne 0 ]; then - echo "Failed to generate network" - exit 1 -fi +set -e -yarn hardhat compile +cd lib/arbitrum-sdk && yarn gen:network && cd - -if [ $? -ne 0 ]; then - echo "Failed to compile" - exit 1 -fi +yarn build yarn mocha test/e2e/ --timeout 30000000 --bail diff --git a/test/e2e/testSetup.ts b/test/e2e/testSetup.ts index a97ef9f8..7b81c7b4 100644 --- a/test/e2e/testSetup.ts +++ b/test/e2e/testSetup.ts @@ -1,24 +1,27 @@ -import { JsonRpcProvider, Wallet } from 'ethers' import { testSetup as sdkTestSetup } from '../../lib/arbitrum-sdk/scripts/testSetup' import { L1Network, L2Network, getL1Network } from '../../lib/arbitrum-sdk/src' -import { getEnv } from '../util/util' +import { + DoubleProvider, + DoubleWallet, + getEnv, +} from '../../scripts/template/util' export const isTestingOrbit = process.env.ORBIT_TEST === '1' type BaseTestSetup = { l1Network: L1Network l2Network: L2Network - l1Signer: Wallet - l2Signer: Wallet - l1Provider: JsonRpcProvider - l2Provider: JsonRpcProvider + l1Signer: DoubleWallet + l2Signer: DoubleWallet + l1Provider: DoubleProvider + l2Provider: DoubleProvider } export type OrbitTestSetup = BaseTestSetup & { isTestingOrbit: true l3Network: L2Network - l3Provider: JsonRpcProvider - l3Signer: Wallet + l3Provider: DoubleProvider + l3Signer: DoubleWallet } export type NonOrbitTestSetup = BaseTestSetup & { @@ -28,16 +31,16 @@ export type NonOrbitTestSetup = BaseTestSetup & { export type TestSetup = OrbitTestSetup | NonOrbitTestSetup export async function testSetup(): Promise { - const l1Provider = new JsonRpcProvider(getEnv('LOCAL_L1_URL')) - const l2Provider = new JsonRpcProvider(getEnv('LOCAL_L2_URL')) - const l1Signer = new Wallet(getEnv('LOCAL_L1_KEY'), l1Provider) - const l2Signer = new Wallet(getEnv('LOCAL_L2_KEY'), l2Provider) + const l1Provider = new DoubleProvider(getEnv('LOCAL_L1_URL')) + const l2Provider = new DoubleProvider(getEnv('LOCAL_L2_URL')) + const l1Signer = new DoubleWallet(getEnv('LOCAL_L1_KEY'), l1Provider) + const l2Signer = new DoubleWallet(getEnv('LOCAL_L2_KEY'), l2Provider) const setup = await sdkTestSetup() if (isTestingOrbit) { - const l3Provider = new JsonRpcProvider(getEnv('LOCAL_L3_URL')) - const l3Signer = new Wallet(getEnv('LOCAL_L3_KEY'), l3Provider) + const l3Provider = new DoubleProvider(getEnv('LOCAL_L3_URL')) + const l3Signer = new DoubleWallet(getEnv('LOCAL_L3_KEY'), l3Provider) const l1Network = await getL1Network( (setup.l1Network as L2Network).partnerChainID diff --git a/test/mocks/SampleMock.sol b/test/mocks/SampleMock.sol new file mode 100644 index 00000000..afc67685 --- /dev/null +++ b/test/mocks/SampleMock.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.16; + +contract SampleMock { + function arbOSVersion() external pure returns (uint256) { + return 1; + } +} diff --git a/test/util/util.ts b/test/util/util.ts deleted file mode 100644 index a7898fcd..00000000 --- a/test/util/util.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type Unwrap = T extends Promise ? U : T - -export function getEnv(name: string): string { - const value = process.env[name] || '' - if (value === '') { - throw new Error(`Environment variable ${name} is not defined`) - } - return value -} From 3b432ae4b183ae62cceee80a5a47e6313d4e7453 Mon Sep 17 00:00:00 2001 From: Henry <11198460+godzillaba@users.noreply.github.com> Date: Mon, 7 Oct 2024 10:15:28 -0400 Subject: [PATCH 8/9] explicit formatter config (#34) --- foundry.toml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/foundry.toml b/foundry.toml index c6400450..741bc142 100644 --- a/foundry.toml +++ b/foundry.toml @@ -7,3 +7,19 @@ cache_path = 'cache_forge' solc_version = '0.8.20' optimizer_runs = 2000 script = 'scripts' + +[fmt] +line_length = 120 +tab_width = 4 +bracket_spacing = false +int_types = "long" +multiline_func_header = "attributes_first" +quote_style = "double" +number_underscore = "preserve" +hex_underscore = "remove" +single_line_statement_blocks = "preserve" +override_spacing = false +wrap_comments = false +ignore = [] +contract_new_lines = false +sort_imports = false From 1f2ae2dbf79afd6d54f603d5937a0f63541860b9 Mon Sep 17 00:00:00 2001 From: Henry <11198460+godzillaba@users.noreply.github.com> Date: Tue, 14 Jan 2025 16:53:48 -0500 Subject: [PATCH 9/9] fix --- .gas-snapshot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gas-snapshot b/.gas-snapshot index ab16f3c7..a2d0eb71 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1 +1 @@ -UpgradeArbOSVersionAtTimestampActionTest:test_1() (gas: 165) +UpgradeArbOSVersionAtTimestampActionTest:test_1() (gas: 189) \ No newline at end of file