From 598ecc3df395310afe1aeabd383b69eb10ea29a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 26 Sep 2022 14:31:43 -0400 Subject: [PATCH 01/15] chore: update arbitrum sdk to 3.0-rc1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- cli/commands/bridge/to-l1.ts | 15 ++- cli/cross-chain.ts | 19 ++-- package.json | 2 +- yarn.lock | 188 +---------------------------------- 4 files changed, 27 insertions(+), 197 deletions(-) diff --git a/cli/commands/bridge/to-l1.ts b/cli/commands/bridge/to-l1.ts index 42f319eb4..0913aa2e1 100644 --- a/cli/commands/bridge/to-l1.ts +++ b/cli/commands/bridge/to-l1.ts @@ -102,11 +102,16 @@ export const startSendToL1 = async (cli: CLIEnvironment, cliArgs: CLIArgs): Prom const l2Receipt = new L2TransactionReceipt(receipt) const l2ToL1Message = (await l2Receipt.getL2ToL1Messages(cli.wallet))[0] - logger.info(`The transaction generated an L2 to L1 message in outbox with eth block number:`) - logger.info(l2ToL1Message.event.ethBlockNum.toString()) - logger.info( - `After the dispute period is finalized (in ~1 week), you can finalize this by calling`, - ) + const ethBlockNum = l2ToL1Message.getFirstExecutableBlock(l2Provider) + if (ethBlockNum === null) { + logger.info(`L2 to L1 message can or already has been executed. If not finalized call`) + } else { + logger.info(`The transaction generated an L2 to L1 message in outbox with eth block number:`) + logger.info(ethBlockNum.toString()) + logger.info( + `After the dispute period is finalized (in ~1 week), you can finalize this by calling`, + ) + } logger.info(`finish-send-to-l1 with the following txhash:`) logger.info(l2Receipt.transactionHash) } diff --git a/cli/cross-chain.ts b/cli/cross-chain.ts index ea3b081ac..58252ca6e 100644 --- a/cli/cross-chain.ts +++ b/cli/cross-chain.ts @@ -1,4 +1,5 @@ import { L1ToL2MessageGasEstimator } from '@arbitrum/sdk' +import { L1ToL2MessageNoGasParams } from '@arbitrum/sdk/dist/lib/message/L1ToL2MessageCreator' import { BigNumber, providers } from 'ethers' import { parseEther } from 'ethers/lib/utils' @@ -44,20 +45,24 @@ export const estimateRetryableTxGas = async ( logger.info('Estimating retryable ticket gas:') const baseFee = (await l1Provider.getBlock('latest')).baseFeePerGas const gasEstimator = new L1ToL2MessageGasEstimator(l2Provider) + const retryableEstimateData: L1ToL2MessageNoGasParams = { + from: gatewayAddress, + to: l2Dest, + data: depositCalldata, + l2CallValue: parseEther('0'), + excessFeeRefundAddress: gatewayAddress, + callValueRefundAddress: gatewayAddress, + } const gasParams = await gasEstimator.estimateAll( - gatewayAddress, - l2Dest, - depositCalldata, - parseEther('0'), + retryableEstimateData, baseFee as BigNumber, - gatewayAddress, - gatewayAddress, l1Provider, ) + // override fixed values return { maxGas: opts.maxGas ?? gasParams.gasLimit, gasPriceBid: opts.gasPriceBid ?? gasParams.maxFeePerGas, - maxSubmissionCost: opts.maxSubmissionCost ?? gasParams.maxSubmissionFee, + maxSubmissionCost: opts.maxSubmissionCost ?? gasParams.maxSubmissionCost, } } diff --git a/package.json b/package.json index 63fab4bd3..0b06cc250 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "ethers": "^5.6.0" }, "devDependencies": { - "@arbitrum/sdk": "^3.0.0-beta.6", + "@arbitrum/sdk": "3.0.0-rc.1", "@commitlint/cli": "^13.2.1", "@commitlint/config-conventional": "^13.2.0", "@defi-wonderland/smock": "^2.0.7", diff --git a/yarn.lock b/yarn.lock index 7b859117b..2cfb8a7a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,21 +2,15 @@ # yarn lockfile v1 -"@arbitrum/sdk@^3.0.0-beta.6": - version "3.0.0-beta.6" - resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.0.0-beta.6.tgz#a36c3e39a7358396b5533f3288125107da6ae59e" - integrity sha512-kPCfgj72MeyVcIXQKoztLO29UTcpSbXFzc/S0oDgVNNcHcXp1hWUJqqkVRg0O43P2yKjZRT/I94K0Nj2nZNiiQ== +"@arbitrum/sdk@3.0.0-rc.1": + version "3.0.0-rc.1" + resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.0.0-rc.1.tgz#5335bd833ded89bfe95328a44ccd2ba743f82239" + integrity sha512-8t4fgvQR/83whezeb1WKBeWtBnfmZ0vaDE1w96cKEt8bdrmTQ8yQF3Vpeq/Y21/SrOdDNj5CQWor1Y6wB+FbyQ== dependencies: "@ethersproject/address" "^5.0.8" "@ethersproject/bignumber" "^5.1.1" "@ethersproject/bytes" "^5.0.8" - "@typechain/ethers-v5" "9.0.0" - "@types/prompts" "^2.0.14" - "@types/yargs" "^17.0.9" - dotenv "^10.0.0" ethers "^5.1.0" - ts-node "^10.2.1" - typechain "7.0.0" "@babel/code-frame@7.12.11": version "7.12.11" @@ -191,18 +185,6 @@ dependencies: chalk "^4.0.0" -"@cspotcode/source-map-consumer@0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" - integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== - -"@cspotcode/source-map-support@0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" - integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== - dependencies: - "@cspotcode/source-map-consumer" "0.8.0" - "@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" @@ -1252,14 +1234,6 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== -"@typechain/ethers-v5@9.0.0": - version "9.0.0" - resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-9.0.0.tgz#6aa93bea7425c0463bd8a61eea3643540ef851bd" - integrity sha512-bAanuPl1L2itaUdMvor/QvwnIH+TM/CmG00q17Ilv3ZZMeJ2j8HcarhgJUZ9pBY1teBb85P8cC03dz3mSSx+tQ== - dependencies: - lodash "^4.17.15" - ts-essentials "^7.0.1" - "@typechain/ethers-v5@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz#cd3ca1590240d587ca301f4c029b67bfccd08810" @@ -1470,13 +1444,6 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.4.tgz#5d9b63132df54d8909fce1c3f8ca260fdd693e17" integrity sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA== -"@types/prompts@^2.0.14": - version "2.0.14" - resolved "https://registry.yarnpkg.com/@types/prompts/-/prompts-2.0.14.tgz#10cb8899844bb0771cabe57c1becaaaca9a3b521" - integrity sha512-HZBd99fKxRWpYCErtm2/yxUZv6/PBI9J7N4TNFffl5JbrYMHBwF25DjQGTW3b3jmXq+9P6/8fCIb2ee57BFfYA== - dependencies: - "@types/node" "*" - "@types/qs@^6.2.31": version "6.9.7" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" @@ -1560,13 +1527,6 @@ dependencies: "@types/yargs-parser" "*" -"@types/yargs@^17.0.9": - version "17.0.10" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.10.tgz#591522fce85d8739bca7b8bb90d048e4478d186a" - integrity sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA== - dependencies: - "@types/yargs-parser" "*" - "@typescript-eslint/eslint-plugin@^4.0.0": version "4.33.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz#c24dc7c8069c7706bc40d99f6fa87edcb2005276" @@ -1988,16 +1948,6 @@ array-back@^2.0.0: dependencies: typical "^2.6.1" -array-back@^3.0.1, array-back@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" - integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== - -array-back@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" - integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== - array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -3541,26 +3491,6 @@ command-line-args@^4.0.7: find-replace "^1.0.3" typical "^2.6.1" -command-line-args@^5.1.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" - integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== - dependencies: - array-back "^3.1.0" - find-replace "^3.0.0" - lodash.camelcase "^4.3.0" - typical "^4.0.0" - -command-line-usage@^6.1.0: - version "6.1.2" - resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.2.tgz#2b7ccd48a93fb19bd71ca8fe9900feab00e557b0" - integrity sha512-I+0XN613reAhpBQ6icsPOTwu9cvhc9NtLtUcY2fGYuwm9JZiWBzFDA8w0PHqQjru7Xth7fM/y9TJ13+VKdjh7Q== - dependencies: - array-back "^4.0.1" - chalk "^2.4.2" - table-layout "^1.0.1" - typical "^5.2.0" - commander@2.18.0: version "2.18.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" @@ -3959,11 +3889,6 @@ deep-equal@~1.1.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" -deep-extend@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -4166,11 +4091,6 @@ dotenv@*: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.0.tgz#c619001253be89ebb638d027b609c75c26e47411" integrity sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q== -dotenv@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" - integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== - dotenv@^9.0.0: version "9.0.2" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-9.0.2.tgz#dacc20160935a37dea6364aa1bef819fb9b6ab05" @@ -5465,13 +5385,6 @@ find-replace@^1.0.3: array-back "^1.0.4" test-value "^2.1.0" -find-replace@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" - integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== - dependencies: - array-back "^3.0.1" - find-up@3.0.0, find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" @@ -7892,11 +7805,6 @@ lodash.assign@^4.0.3, lodash.assign@^4.0.6: resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= -lodash.camelcase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= - lodash.get@^4: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" @@ -10055,11 +9963,6 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" -reduce-flatten@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" - integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== - regenerate@^1.2.1: version "1.4.2" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" @@ -11122,11 +11025,6 @@ string-argv@0.3.1: resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== -string-format@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" - integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== - string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -11359,16 +11257,6 @@ sync-rpc@^1.2.1: dependencies: get-port "^3.1.0" -table-layout@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" - integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== - dependencies: - array-back "^4.0.1" - deep-extend "~0.6.0" - typical "^5.2.0" - wordwrapjs "^4.0.0" - table@^5.2.3: version "5.4.6" resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" @@ -11622,16 +11510,6 @@ triple-beam@^1.3.0: resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-2.2.1.tgz#c5bf04a5bbec3fd118be4084461b3a27c4d796bf" integrity sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q== -ts-command-line-args@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.2.1.tgz#fd6913e542099012c0ffb2496126a8f38305c7d6" - integrity sha512-mnK68QA86FYzQYTSA/rxIjT/8EpKsvQw9QkawPic8I8t0gjAOw3Oa509NIRoaY1FmH7hdrncMp7t7o+vYoceNQ== - dependencies: - chalk "^4.1.0" - command-line-args "^5.1.1" - command-line-usage "^6.1.0" - string-format "^2.0.0" - ts-essentials@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-1.0.4.tgz#ce3b5dade5f5d97cf69889c11bf7d2da8555b15a" @@ -11662,25 +11540,6 @@ ts-generator@^0.1.1: resolve "^1.8.1" ts-essentials "^1.0.0" -ts-node@^10.2.1: - version "10.7.0" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.7.0.tgz#35d503d0fab3e2baa672a0e94f4b40653c2463f5" - integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A== - dependencies: - "@cspotcode/source-map-support" "0.7.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.0" - yn "3.1.1" - ts-node@^10.9.1: version "10.9.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" @@ -11823,22 +11682,6 @@ type@^2.5.0: resolved "https://registry.yarnpkg.com/type/-/type-2.6.0.tgz#3ca6099af5981d36ca86b78442973694278a219f" integrity sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ== -typechain@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/typechain/-/typechain-7.0.0.tgz#258ca136de1d451368bde01c318976a83062f110" - integrity sha512-ILfvBBFJ7j9aIk0crX03+N2GmzoDN1gtk32G1+XrasjuvXS0XAw2XxwQeQMMgKwlnxViJjIkG87sTMYXPkXA9g== - dependencies: - "@types/prettier" "^2.1.1" - debug "^4.1.1" - fs-extra "^7.0.0" - glob "^7.1.6" - js-sha3 "^0.8.0" - lodash "^4.17.15" - mkdirp "^1.0.4" - prettier "^2.1.2" - ts-command-line-args "^2.2.0" - ts-essentials "^7.0.1" - typechain@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/typechain/-/typechain-3.0.0.tgz#d5a47700831f238e43f7429b987b4bb54849b92e" @@ -11912,16 +11755,6 @@ typical@^2.6.0, typical@^2.6.1: resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" integrity sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg== -typical@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" - integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== - -typical@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" - integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== - uglify-js@^3.1.4: version "3.15.3" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.15.3.tgz#9aa82ca22419ba4c0137642ba0df800cb06e0471" @@ -12136,11 +11969,6 @@ uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== -v8-compile-cache-lib@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz#0582bcb1c74f3a2ee46487ceecf372e46bce53e8" - integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA== - v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" @@ -12864,14 +12692,6 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -wordwrapjs@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" - integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== - dependencies: - reduce-flatten "^2.0.0" - typical "^5.2.0" - workerpool@6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" From a7ba5350e47a900a486d7757dbd950d049b0d7c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 26 Sep 2022 15:43:08 -0400 Subject: [PATCH 02/15] fix(task): accept ownership only if pending owner matches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- tasks/deployment/ownership.ts | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/tasks/deployment/ownership.ts b/tasks/deployment/ownership.ts index 86591c974..1443aa599 100644 --- a/tasks/deployment/ownership.ts +++ b/tasks/deployment/ownership.ts @@ -1,4 +1,5 @@ -import { ContractTransaction } from 'ethers' +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +import { Contract, ContractTransaction, ethers } from 'ethers' import { task } from 'hardhat/config' import { cliOpts } from '../../cli/defaults' @@ -13,12 +14,36 @@ task('migrate:ownership', 'Accepts ownership of protocol contracts on behalf of console.log('> Accepting ownership of contracts') console.log(`- Governor: ${governor.address}`) + const governedContracts = [GraphToken, Controller, GraphProxyAdmin, SubgraphNFT] const txs: ContractTransaction[] = [] - txs.push(await GraphToken.connect(governor).acceptOwnership()) - txs.push(await Controller.connect(governor).acceptOwnership()) - txs.push(await GraphProxyAdmin.connect(governor).acceptOwnership()) - txs.push(await SubgraphNFT.connect(governor).acceptOwnership()) + for (const contract of governedContracts) { + const tx = await acceptOwnershipIfPending(contract, governor) + if (tx) { + txs.push() + } + } await Promise.all(txs.map((tx) => tx.wait())) console.log('Done!') }) + +async function acceptOwnershipIfPending( + contract: Contract, + signer: SignerWithAddress, +): Promise { + const pendingGovernor = await contract.connect(signer).pendingGovernor() + + if (pendingGovernor === ethers.constants.AddressZero) { + console.log(`No pending governor for ${contract.address}`) + return + } + + if (pendingGovernor === signer.address) { + console.log(`Accepting ownership of ${contract.address}`) + return contract.connect(signer).acceptOwnership() + } else { + console.log( + `Signer ${signer.address} is not the pending governor of ${contract.address}, it is ${pendingGovernor}`, + ) + } +} From 0aed5eb8bfbf13a34fdf74fc3e2ee19d070fc13d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 26 Sep 2022 15:49:00 -0400 Subject: [PATCH 03/15] feat(task): split unpause task into protocol and bridge tasks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- tasks/deployment/unpause.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasks/deployment/unpause.ts b/tasks/deployment/unpause.ts index afb85e0ea..fb8c39d5d 100644 --- a/tasks/deployment/unpause.ts +++ b/tasks/deployment/unpause.ts @@ -2,7 +2,7 @@ import { task } from 'hardhat/config' import { cliOpts } from '../../cli/defaults' import GraphChain from '../../gre/helpers/network' -task('migrate:unpause', 'Unpause protocol (except bridge)') +task('migrate:unpause:protocol', 'Unpause protocol (except bridge)') .addOptionalParam('addressBook', cliOpts.addressBook.description) .addOptionalParam('graphConfig', cliOpts.graphConfig.description) .setAction(async (taskArgs, hre) => { @@ -17,7 +17,7 @@ task('migrate:unpause', 'Unpause protocol (except bridge)') console.log('Done!') }) -task('migrate:unpause-bridge', 'Unpause bridge') +task('migrate:unpause:bridge', 'Unpause bridge') .addOptionalParam('addressBook', cliOpts.addressBook.description) .addOptionalParam('graphConfig', cliOpts.graphConfig.description) .setAction(async (taskArgs, hre) => { @@ -29,8 +29,8 @@ task('migrate:unpause-bridge', 'Unpause bridge') const GraphTokenGateway = GraphChain.isL2(graph.chainId) ? L2GraphTokenGateway : L1GraphTokenGateway - const tx2 = await GraphTokenGateway.connect(governor).setPaused(false) - await tx2.wait() + const tx = await GraphTokenGateway.connect(governor).setPaused(false) + await tx.wait() console.log('Done!') }) From a3fa719a43024c6a5f5165e706e2fe43c4805d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 26 Sep 2022 15:50:31 -0400 Subject: [PATCH 04/15] feat(e2e): run L1 and L2 together in e2e tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .gitignore | 4 + cli/commands/bridge/to-l2.ts | 4 +- config/graph.arbitrum-localhost.yml | 12 +- .../config/l1/l1GraphTokenGateway.test.ts | 2 +- e2e/scenarios/fixtures/bridge.ts | 29 +++ e2e/scenarios/lib/helpers.ts | 10 +- e2e/scenarios/lib/staking.ts | 4 +- e2e/scenarios/send-grt-to-l2.test.ts | 23 +++ e2e/scenarios/send-grt-to-l2.ts | 40 ++++ hardhat.config.ts | 7 +- scripts/e2e | 190 +++++++++++++++--- tasks/bridge/to-l2.ts | 56 ++++++ tasks/deployment/accounts.ts | 67 ------ tasks/deployment/nitro.ts | 119 +++++++++++ tasks/e2e/e2e.ts | 8 +- 15 files changed, 460 insertions(+), 115 deletions(-) create mode 100644 e2e/scenarios/fixtures/bridge.ts create mode 100644 e2e/scenarios/send-grt-to-l2.test.ts create mode 100644 e2e/scenarios/send-grt-to-l2.ts create mode 100644 tasks/bridge/to-l2.ts create mode 100644 tasks/deployment/nitro.ts diff --git a/.gitignore b/.gitignore index 1fcf808ed..2521a6cf5 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,7 @@ bin/ # Coverage and other reports /reports coverage.json + +# Local test files +addresses-local.json +arbitrum-addresses-local.json \ No newline at end of file diff --git a/cli/commands/bridge/to-l2.ts b/cli/commands/bridge/to-l2.ts index ffacee1c8..a7b6e7651 100644 --- a/cli/commands/bridge/to-l2.ts +++ b/cli/commands/bridge/to-l2.ts @@ -45,7 +45,8 @@ export const sendToL2 = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise { + return { + deploymentFile: '../arbitrum-sdk/localNetwork.json', + funder: signers[0], + accountsToFund: [ + { + signer: signers[1], + amount: toGRT(10_000_000), + }, + ], + } +} diff --git a/e2e/scenarios/lib/helpers.ts b/e2e/scenarios/lib/helpers.ts index db9da32cb..902ed57fe 100644 --- a/e2e/scenarios/lib/helpers.ts +++ b/e2e/scenarios/lib/helpers.ts @@ -1,6 +1,8 @@ export function getGraphOptsFromArgv(): { - graphConfig: string | undefined addressBook: string | undefined + graphConfig: string | undefined + l1GraphConfig: string | undefined + l2GraphConfig: string | undefined } { const argv = process.argv.slice(2) @@ -8,7 +10,9 @@ export function getGraphOptsFromArgv(): { argv[index] && argv[index] !== 'undefined' ? argv[index] : undefined return { - graphConfig: getArgv(0), - addressBook: getArgv(1), + addressBook: getArgv(0), + graphConfig: getArgv(1), + l1GraphConfig: getArgv(2), + l2GraphConfig: getArgv(3), } } diff --git a/e2e/scenarios/lib/staking.ts b/e2e/scenarios/lib/staking.ts index d221afccd..53465cfb8 100644 --- a/e2e/scenarios/lib/staking.ts +++ b/e2e/scenarios/lib/staking.ts @@ -42,7 +42,7 @@ export const allocateFrom = async ( 'allocateFrom', [indexer.address, subgraphDeploymentID, amount, allocationId, metadata, proof], { - gasLimit: 2000000, + gasLimit: 4_000_000, }, ) } @@ -56,6 +56,6 @@ export const closeAllocation = async ( console.log(`\nClosing ${allocationId}...`) await sendTransaction(indexer, contracts.Staking, 'closeAllocation', [allocationId, poi], { - gasLimit: 2000000, + gasLimit: 4_000_000, }) } diff --git a/e2e/scenarios/send-grt-to-l2.test.ts b/e2e/scenarios/send-grt-to-l2.test.ts new file mode 100644 index 000000000..9b81371b6 --- /dev/null +++ b/e2e/scenarios/send-grt-to-l2.test.ts @@ -0,0 +1,23 @@ +import { expect } from 'chai' +import hre from 'hardhat' +import { getBridgeFixture, BridgeFixture } from './fixtures/bridge' + +describe('Bridge GRT to L2', () => { + const graph = hre.graph() + let bridgeFixture: BridgeFixture + + before(async () => { + const l1Deployer = await graph.l1.getDeployer() + const l2Deployer = await graph.l2.getDeployer() + bridgeFixture = getBridgeFixture([l1Deployer, l2Deployer]) + }) + + describe('GRT balances', () => { + it(`L2 balances should match bridged amount`, async function () { + for (const account of bridgeFixture.accountsToFund) { + const l2GrtBalance = await graph.l2.contracts.GraphToken.balanceOf(account.signer.address) + expect(l2GrtBalance).eq(account.amount) + } + }) + }) +}) diff --git a/e2e/scenarios/send-grt-to-l2.ts b/e2e/scenarios/send-grt-to-l2.ts new file mode 100644 index 000000000..9884c9816 --- /dev/null +++ b/e2e/scenarios/send-grt-to-l2.ts @@ -0,0 +1,40 @@ +// ### Scenario description ### +// Bridge action > Bridge GRT tokens from L1 to L2 +// This scenario will bridge GRT tokens from L1 to L2. See fixtures for details. +// Run with: +// npx hardhat e2e:scenario send-grt-to-l2 --network --graph-config config/graph..yml + +import hre from 'hardhat' +import { TASK_BRIDGE_TO_L2 } from '../../tasks/bridge/to-l2' +import { getGraphOptsFromArgv } from './lib/helpers' +import { getBridgeFixture } from './fixtures/bridge' + +async function main() { + const graphOpts = getGraphOptsFromArgv() + const graph = hre.graph(graphOpts) + + const l1Deployer = await graph.l1.getDeployer() + const l2Deployer = await graph.l2.getDeployer() + + const bridgeFixture = getBridgeFixture([l1Deployer, l2Deployer]) + + // == Send GRT to L2 accounts + for (const account of bridgeFixture.accountsToFund) { + await hre.run(TASK_BRIDGE_TO_L2, { + ...graphOpts, + amount: account.amount.toString(), + sender: bridgeFixture.funder.address, + recipient: account.signer.address, + deploymentFile: bridgeFixture.deploymentFile, + }) + } +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error) + process.exitCode = 1 + }) diff --git a/hardhat.config.ts b/hardhat.config.ts index 1a1c2758b..3fef7643c 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -29,7 +29,7 @@ const SKIP_LOAD = process.env.SKIP_LOAD === 'true' function loadTasks() { require('./gre/gre') - ;['contracts', 'misc', 'deployment', 'actions', 'verify', 'e2e'].forEach((folder) => { + ;['contracts', 'bridge', 'misc', 'deployment', 'actions', 'verify', 'e2e'].forEach((folder) => { const tasksPath = path.join(__dirname, 'tasks', folder) fs.readdirSync(tasksPath) .filter((pth) => pth.includes('.ts')) @@ -107,6 +107,9 @@ function setupNetworkProviders(hardhatConfig) { const DEFAULT_TEST_MNEMONIC = 'myth like bonus scare over problem client lizard pioneer submit female collect' +const DEFAULT_L2_TEST_MNEMONIC = + 'urge never interest human any economy gentle canvas anxiety pave unlock find' + const config: HardhatUserConfig = { paths: { sources: './contracts', @@ -169,7 +172,7 @@ const config: HardhatUserConfig = { localnitrol2: { chainId: 412346, url: 'http://localhost:8547', - accounts: { mnemonic: DEFAULT_TEST_MNEMONIC }, + accounts: { mnemonic: DEFAULT_L2_TEST_MNEMONIC }, graphConfig: 'config/graph.arbitrum-localhost.yml', }, }, diff --git a/scripts/e2e b/scripts/e2e index c5008f25e..cbd650e5f 100755 --- a/scripts/e2e +++ b/scripts/e2e @@ -3,17 +3,138 @@ set -eo pipefail source $(pwd)/scripts/evm +### > SCRIPT CONFIG < # Allow overriding config -GRAPH_CONFIG=${GRAPH_CONFIG:-"config/graph.localhost.yml"} -ADDRESS_BOOK=${ADDRESS_BOOK:-"addresses.json"} -NETWORK=${NETWORK:-"localhost"} +ADDRESS_BOOK=${ADDRESS_BOOK:-"addresses-local.json"} +ARBITRUM_ADDRESS_BOOK=${ARBITRUM_ADDRESS_BOOK:-"arbitrum-addresses-local.json"} +ARBITRUM_DEPLOYMENT_FILE=${ARBITRUM_DEPLOYMENT_FILE:-"$(pwd)/../arbitrum-sdk/localNetwork.json"} +L1_NETWORK=${L1_NETWORK:-"localhost"} +L2_NETWORK=${L2_NETWORK} # By default run only L1 tests on localhost network +L1_GRAPH_CONFIG=${L1_GRAPH_CONFIG:-"config/graph.localhost.yml"} +L2_GRAPH_CONFIG=${L2_GRAPH_CONFIG:-"config/graph.arbitrum-localhost.yml"} echo "Running e2e tests" -echo "- Using config: $GRAPH_CONFIG" echo "- Using address book: $ADDRESS_BOOK" -echo "- Using network: $NETWORK" +echo "- Using L1 network: $L1_NETWORK" +echo "- Using L1 config: $L1_GRAPH_CONFIG" -### Setup +if [[ -n "$L2_NETWORK" ]]; then + echo "- Using L2 network: $L2_NETWORK" + echo "- Using L2 config: $L2_GRAPH_CONFIG" + echo "- Using arbitrum address book: $ARBITRUM_ADDRESS_BOOK" + echo "- Using arbitrum deployment file: $ARBITRUM_DEPLOYMENT_FILE" +else + echo "- Skipping L2 tests" +fi + +### > SCRIPT AUX FUNCTIONS < +function pre_deploy() { + local NETWORK=$1 + local GRAPH_CONFIG=$2 + + # Create named accounts + npx hardhat migrate:accounts --network "$NETWORK" --graph-config "$GRAPH_CONFIG" + + # Fund accounts if using nitro test nodes + if [[ "$NETWORK" == *"localnitro"* ]]; then + npx hardhat nitro:fund-accounts --network "$NETWORK" --graph-config "$GRAPH_CONFIG" + fi +} + +function deploy() { + local NETWORK=$1 + local GRAPH_CONFIG=$2 + local ADDRESS_BOOK=$3 + + # Deploy protocol + npx hardhat migrate \ + --network "$NETWORK" \ + --skip-confirmation \ + --auto-mine \ + --force \ + --graph-config "$GRAPH_CONFIG" \ + --address-book "$ADDRESS_BOOK" +} + +function post_deploy () { + local NETWORK=$1 + local GRAPH_CONFIG=$2 + local ADDRESS_BOOK=$3 + + # Governor to accept contracts ownership + npx hardhat migrate:ownership --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" + + # Unpause the protocol + npx hardhat migrate:unpause:protocol --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" +} + +function configure_bridge () { + local L1_NETWORK=$1 + local L1_GRAPH_CONFIG=$2 + local L2_NETWORK=$3 + local L2_GRAPH_CONFIG=$4 + local ADDRESS_BOOK=$5 + local ARBITRUM_ADDRESS_BOOK=$6 + local ARBITRUM_DEPLOYMENT_FILE=$7 + + # These settings are only used for CLI bridge commands + # so we keep them here to avoid confusion with hardhat based tasks + local L1_CHAIN_ID=${L1_CHAIN_ID:-"1337"} + local L2_CHAIN_ID=${L2_CHAIN_ID:-"412346"} + + local L1_RPC=${L1_RPC:-"http://localhost:8545"} + local L2_RPC=${L2_RPC:-"http://localhost:8547"} + + local L1_MNEMONIC=${L1_MNEMONIC:-"myth like bonus scare over problem client lizard pioneer submit female collect"} + local L2_MNEMONIC=${L2_MNEMONIC:-"urge never interest human any economy gentle canvas anxiety pave unlock find"} + + # Copy required arbitrum contract addresses to the local arbitrum address book + npx hardhat nitro:address-book-setup --deployment-file "$ARBITRUM_DEPLOYMENT_FILE" --arbitrum-address-book "$ARBITRUM_ADDRESS_BOOK" + + # Configure the bridge + ./cli/cli.ts -a "$ADDRESS_BOOK" -p "$L2_RPC" -m "$L2_MNEMONIC" -n 2 -r "$ARBITRUM_ADDRESS_BOOK" protocol configure-l2-bridge "$L1_CHAIN_ID" + ./cli/cli.ts -a "$ADDRESS_BOOK" -p "$L1_RPC" -m "$L1_MNEMONIC" -n 2 -r "$ARBITRUM_ADDRESS_BOOK" protocol configure-l1-bridge "$L2_CHAIN_ID" + + # Unpause the bridge + npx hardhat migrate:unpause:bridge --network "$L2_NETWORK" --graph-config "$L2_GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" + npx hardhat migrate:unpause:bridge --network "$L1_NETWORK" --graph-config "$L1_GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" +} + +function test_e2e () { + local NETWORK=$1 + local GRAPH_CONFIG=$2 + local ADDRESS_BOOK=$3 + + npx hardhat e2e --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" +} + +function test_e2e_scenarios () { + local NETWORK=$1 + local GRAPH_CONFIG=$2 + local ADDRESS_BOOK=$3 + + npx hardhat e2e:scenario create-subgraphs --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" + npx hardhat e2e:scenario open-allocations --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" + + # skip close-allocations for arbitrum testnodes as we can't advance epoch + if [[ "$NETWORK" != *"localnitro"* ]]; then + npx hardhat e2e:scenario close-allocations --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" + fi +} + +function test_e2e_scenarios_bridge () { + local L1_NETWORK=$1 + local L1_GRAPH_CONFIG=$2 + local L2_NETWORK=$3 + local L2_GRAPH_CONFIG=$4 + local ADDRESS_BOOK=$5 + + npx hardhat e2e:scenario send-grt-to-l2 --network "$L1_NETWORK" --l1-graph-config "$L1_GRAPH_CONFIG" --l2-graph-config "$L2_GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" +} + + +### > SCRIPT START < ### +## SETUP # Compile contracts yarn build @@ -28,40 +149,47 @@ if [[ ! -f "$ADDRESS_BOOK" ]]; then echo '{}' > "$ADDRESS_BOOK" fi -# Pre-deploy actions -npx hardhat migrate:accounts --network "$NETWORK" --graph-config "$GRAPH_CONFIG" -if [[ "$NETWORK" == *"localnitro"* ]]; then - npx hardhat migrate:accounts:nitro --network "$NETWORK" --graph-config "$GRAPH_CONFIG" +# Create arbitrum address book if needed +if [[ ! -f "$ARBITRUM_ADDRESS_BOOK" ]]; then + echo '{}' > "$ARBITRUM_ADDRESS_BOOK" fi -# Deploy protocol -npx hardhat migrate \ - --network "$NETWORK" \ - --skip-confirmation \ - --auto-mine \ - --graph-config "$GRAPH_CONFIG" \ - --address-book "$ADDRESS_BOOK" +## DEPLOY +# Deploy L1 +echo "Deploying L1 protocol" +pre_deploy "$L1_NETWORK" "$L1_GRAPH_CONFIG" +deploy "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" +post_deploy "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" -# Post deploy actions -npx hardhat migrate:ownership --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" -npx hardhat migrate:unpause --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" +# Deploy L2 +if [[ -n "$L2_NETWORK" ]]; then + echo "Deploying L2 protocol" + pre_deploy "$L2_NETWORK" "$L2_GRAPH_CONFIG" + deploy "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" + post_deploy "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" +fi -### Test -# Run tests -npx hardhat e2e --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" +# Configure bridge +if [[ -n "$L2_NETWORK" ]]; then + configure_bridge "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" "$ARBITRUM_ADDRESS_BOOK" +fi -# Skip GRT scenarios in L2 as we don't have bridged GRT yet -if [[ "$NETWORK" != "localnitrol2" ]]; then - npx hardhat e2e:scenario create-subgraphs --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" - npx hardhat e2e:scenario open-allocations --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" + +## TEST +# Run e2e tests +test_e2e "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" +if [[ -n "$L2_NETWORK" ]]; then + test_e2e "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" fi -# skip close-allocations for arbitrum testnodes as we can't advance epoch -if [[ "$NETWORK" != *"localnitro"* ]]; then - npx hardhat e2e:scenario close-allocations --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" +# Run scenario tests +test_e2e_scenarios "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" +if [[ -n "$L2_NETWORK" ]]; then + test_e2e_scenarios_bridge "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" + test_e2e_scenarios "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" fi -### Cleanup +## Cleanup # Exit error mode so the evm instance always gets killed if [[ "$NETWORK" == "localhost" ]]; then set +e diff --git a/tasks/bridge/to-l2.ts b/tasks/bridge/to-l2.ts new file mode 100644 index 000000000..a5ced288f --- /dev/null +++ b/tasks/bridge/to-l2.ts @@ -0,0 +1,56 @@ +import { task } from 'hardhat/config' +import { cliOpts } from '../../cli/defaults' +import { sendToL2 } from '../../cli/commands/bridge/to-l2' +import { loadEnv } from '../../cli/env' +import { TASK_NITRO_SETUP_SDK } from '../deployment/nitro' +import { BigNumber } from 'ethers' + +export const TASK_BRIDGE_TO_L2 = 'bridge:send-to-l2' + +task(TASK_BRIDGE_TO_L2, 'Bridge GRT tokens from L1 to L2') + .addParam('amount', 'Amount of tokens to bridge') + .addOptionalParam('sender', 'Address of the sender. L1 deployer if empty.') + .addOptionalParam('recipient', 'Receiving address in L2. Same to L1 address if empty.') + .addOptionalParam('addressBook', cliOpts.addressBook.description) + .addOptionalParam( + 'arbitrumAddressBook', + cliOpts.arbitrumAddressBook.description, + cliOpts.arbitrumAddressBook.default, + ) + .addOptionalParam('l1GraphConfig', cliOpts.graphConfig.description) + .addOptionalParam('l2GraphConfig', cliOpts.graphConfig.description) + .addOptionalParam( + 'deploymentFile', + 'Nitro testnode deployment file. Must specify if using nitro test nodes.', + ) + .setAction(async (taskArgs, hre) => { + console.log('> Sending GRT to L2') + const graph = hre.graph(taskArgs) + + // Add nitro test node networks to sdk + if (taskArgs.deploymentFile) { + console.log('> Adding nitro test node network to sdk') + await hre.run(TASK_NITRO_SETUP_SDK, { deploymentFile: taskArgs.deploymentFile }) + } + + // Get the sender, use L1 deployer if not provided + const l1Deployer = await graph.l1.getDeployer() + const sender: string = taskArgs.sender ?? l1Deployer.address + + let wallet = await graph.l1.getWallet(sender) + + if (!wallet) { + throw new Error(`No wallet found for address ${sender}`) + } else { + console.log(`> Using wallet ${wallet.address}`) + wallet = wallet.connect(graph.l1.provider) + } + + // Patch sendToL2 opts + taskArgs.l2Provider = graph.l2.provider + taskArgs.amount = hre.ethers.utils.formatEther(taskArgs.amount) // sendToL2 expects amount in GRT + + await sendToL2(await loadEnv(taskArgs, wallet), taskArgs) + + console.log('Done!') + }) diff --git a/tasks/deployment/accounts.ts b/tasks/deployment/accounts.ts index c09ff2a2f..e5be935ea 100644 --- a/tasks/deployment/accounts.ts +++ b/tasks/deployment/accounts.ts @@ -2,7 +2,6 @@ import { task } from 'hardhat/config' import { cliOpts } from '../../cli/defaults' import { updateItemValue, writeConfig } from '../../cli/config' -import { BigNumber, ContractTransaction } from 'ethers' task('migrate:accounts', 'Creates protocol accounts and saves them in graph config') .addOptionalParam('graphConfig', cliOpts.graphConfig.description) @@ -39,69 +38,3 @@ task('migrate:accounts', 'Creates protocol accounts and saves them in graph conf writeConfig(taskArgs.graphConfig, graphConfig.toString()) }) - -task('migrate:accounts:nitro', 'Funds protocol accounts on Arbitrum Nitro testnodes') - .addOptionalParam('graphConfig', cliOpts.graphConfig.description) - .addOptionalParam('privateKey', 'The private key for Arbitrum testnode genesis account') - .addOptionalParam('amount', 'The amount to fund each account with') - .setAction(async (taskArgs, hre) => { - // Arbitrum Nitro testnodes have a pre-funded genesis account whose private key is hardcoded here: - // - L1 > https://github.com/OffchainLabs/nitro/blob/01c558c06ad9cbaa083bebe3e51960e195c3fd6b/test-node.bash#L136 - // - L2 > https://github.com/OffchainLabs/nitro/blob/01c558c06ad9cbaa083bebe3e51960e195c3fd6b/testnode-scripts/config.ts#L22 - const genesisAccountPrivateKey = - taskArgs.privateKey ?? 'e887f7d17d07cc7b8004053fb8826f6657084e88904bb61590e498ca04704cf2' - const genesisAccount = new hre.ethers.Wallet(genesisAccountPrivateKey) - - // Get protocol accounts - const { getDeployer, getNamedAccounts, getTestAccounts, provider } = hre.graph(taskArgs) - const deployer = await getDeployer() - const testAccounts = await getTestAccounts() - const namedAccounts = await getNamedAccounts() - const accounts = [ - deployer, - ...testAccounts, - ...Object.keys(namedAccounts).map((k) => namedAccounts[k]), - ] - - // Amount to fund - // - If amount is specified, use that - // - Otherwise, use 95% of genesis account balance with a maximum of 100 Eth - let amount: BigNumber - const maxAmount = hre.ethers.utils.parseEther('100') - const genesisAccountBalance = await provider.getBalance(genesisAccount.address) - - if (taskArgs.amount) { - amount = hre.ethers.BigNumber.from(taskArgs.amount) - } else { - const splitGenesisBalance = genesisAccountBalance.mul(95).div(100).div(accounts.length) - if (splitGenesisBalance.gt(maxAmount)) { - amount = maxAmount - } else { - amount = splitGenesisBalance - } - } - - // Check genesis account balance - const requiredFunds = amount.mul(accounts.length) - if (genesisAccountBalance.lt(requiredFunds)) { - throw new Error('Insufficient funds in genesis account') - } - - // Fund accounts - console.log('> Funding protocol addresses') - console.log(`Genesis account: ${genesisAccount.address}`) - console.log(`Total accounts: ${accounts.length}`) - console.log(`Amount per account: ${hre.ethers.utils.formatEther(amount)}`) - console.log(`Required funds: ${hre.ethers.utils.formatEther(requiredFunds)}`) - - const txs: ContractTransaction[] = [] - for (const account of accounts) { - const tx = await genesisAccount.connect(provider).sendTransaction({ - value: amount, - to: account.address, - }) - txs.push(tx) - } - await Promise.all(txs.map((tx) => tx.wait())) - console.log('Done!') - }) diff --git a/tasks/deployment/nitro.ts b/tasks/deployment/nitro.ts new file mode 100644 index 000000000..9a69af5aa --- /dev/null +++ b/tasks/deployment/nitro.ts @@ -0,0 +1,119 @@ +import { BigNumber, ContractTransaction } from 'ethers' +import { subtask, task } from 'hardhat/config' +import { cliOpts } from '../../cli/defaults' +import { addCustomNetwork } from '@arbitrum/sdk/dist/lib/dataEntities/networks' +import fs from 'fs' + +export const TASK_NITRO_FUND_ACCOUNTS = 'nitro:fund-accounts' +export const TASK_NITRO_SETUP_SDK = 'nitro:sdk-setup' +export const TASK_NITRO_SETUP_ADDRESS_BOOK = 'nitro:address-book-setup' + +task(TASK_NITRO_FUND_ACCOUNTS, 'Funds protocol accounts on Arbitrum Nitro testnodes') + .addOptionalParam('graphConfig', cliOpts.graphConfig.description) + .addOptionalParam('privateKey', 'The private key for Arbitrum testnode genesis account') + .addOptionalParam('amount', 'The amount to fund each account with') + .setAction(async (taskArgs, hre) => { + // Arbitrum Nitro testnodes have a pre-funded genesis account whose private key is hardcoded here: + // - L1 > https://github.com/OffchainLabs/nitro/blob/01c558c06ad9cbaa083bebe3e51960e195c3fd6b/test-node.bash#L136 + // - L2 > https://github.com/OffchainLabs/nitro/blob/01c558c06ad9cbaa083bebe3e51960e195c3fd6b/testnode-scripts/config.ts#L22 + const genesisAccountPrivateKey = + taskArgs.privateKey ?? 'e887f7d17d07cc7b8004053fb8826f6657084e88904bb61590e498ca04704cf2' + const genesisAccount = new hre.ethers.Wallet(genesisAccountPrivateKey) + + // Get protocol accounts + const { getDeployer, getNamedAccounts, getTestAccounts, provider } = hre.graph(taskArgs) + const deployer = await getDeployer() + const testAccounts = await getTestAccounts() + const namedAccounts = await getNamedAccounts() + const accounts = [ + deployer, + ...testAccounts, + ...Object.keys(namedAccounts).map((k) => namedAccounts[k]), + ] + + // Amount to fund + // - If amount is specified, use that + // - Otherwise, use 95% of genesis account balance with a maximum of 100 Eth + let amount: BigNumber + const maxAmount = hre.ethers.utils.parseEther('100') + const genesisAccountBalance = await provider.getBalance(genesisAccount.address) + + if (taskArgs.amount) { + amount = hre.ethers.BigNumber.from(taskArgs.amount) + } else { + const splitGenesisBalance = genesisAccountBalance.mul(95).div(100).div(accounts.length) + if (splitGenesisBalance.gt(maxAmount)) { + amount = maxAmount + } else { + amount = splitGenesisBalance + } + } + + // Check genesis account balance + const requiredFunds = amount.mul(accounts.length) + if (genesisAccountBalance.lt(requiredFunds)) { + throw new Error('Insufficient funds in genesis account') + } + + // Fund accounts + console.log('> Funding protocol addresses') + console.log(`Genesis account: ${genesisAccount.address}`) + console.log(`Total accounts: ${accounts.length}`) + console.log(`Amount per account: ${hre.ethers.utils.formatEther(amount)}`) + console.log(`Required funds: ${hre.ethers.utils.formatEther(requiredFunds)}`) + + const txs: ContractTransaction[] = [] + for (const account of accounts) { + const tx = await genesisAccount.connect(provider).sendTransaction({ + value: amount, + to: account.address, + }) + txs.push(tx) + } + await Promise.all(txs.map((tx) => tx.wait())) + console.log('Done!') + }) + +// Arbitrum SDK does not support Nitro testnodes out of the box +// This adds the testnodes to the SDK configuration +subtask(TASK_NITRO_SETUP_SDK, 'Adds nitro testnodes to SDK config') + .addParam('deploymentFile', 'The testnode deployment file to use') + .setAction(async (taskArgs) => { + if (!fs.existsSync(taskArgs.deploymentFile)) { + throw new Error(`Deployment file not found: ${taskArgs.deploymentFile}`) + } + const deployment = JSON.parse(fs.readFileSync(taskArgs.deploymentFile, 'utf-8')) + addCustomNetwork({ + customL1Network: deployment.l1Network, + customL2Network: deployment.l2Network, + }) + }) + +// Read arbitrum contract addresses from deployment file and write them to the address book +task(TASK_NITRO_SETUP_ADDRESS_BOOK, 'Write arbitrum addresses to address book') + .addParam('deploymentFile', 'The testnode deployment file to use') + .addParam('arbitrumAddressBook', 'Arbitrum address book file') + .setAction(async (taskArgs) => { + if (!fs.existsSync(taskArgs.deploymentFile)) { + throw new Error(`Deployment file not found: ${taskArgs.deploymentFile}`) + } + const deployment = JSON.parse(fs.readFileSync(taskArgs.deploymentFile, 'utf-8')) + + const addressBook = { + '1337': { + L1GatewayRouter: { + address: deployment.l2Network.tokenBridge.l1GatewayRouter, + }, + IInbox: { + address: deployment.l2Network.ethBridge.inbox, + }, + }, + '412346': { + L2GatewayRouter: { + address: deployment.l2Network.tokenBridge.l2GatewayRouter, + }, + }, + } + + fs.writeFileSync(taskArgs.arbitrumAddressBook, JSON.stringify(addressBook)) + }) diff --git a/tasks/e2e/e2e.ts b/tasks/e2e/e2e.ts index d2ab8f96e..7b9a08b8b 100644 --- a/tasks/e2e/e2e.ts +++ b/tasks/e2e/e2e.ts @@ -66,8 +66,10 @@ task('e2e:init', 'Run deployment initialization e2e tests') task('e2e:scenario', 'Run scenario scripts and e2e tests') .addPositionalParam('scenario', 'Name of the scenario to run') - .addOptionalParam('graphConfig', cliOpts.graphConfig.description) .addOptionalParam('addressBook', cliOpts.addressBook.description) + .addOptionalParam('graphConfig', cliOpts.graphConfig.description) + .addOptionalParam('l1GraphConfig', cliOpts.graphConfig.description) + .addOptionalParam('l2GraphConfig', cliOpts.graphConfig.description) .addFlag('skipScript', "Don't run scenario script") .setAction(async (args, hre: HardhatRuntimeEnvironment) => { setGraphConfig(args, hre) @@ -82,8 +84,10 @@ task('e2e:scenario', 'Run scenario scripts and e2e tests') if (!args.skipScript) { if (fs.existsSync(script)) { await runScriptWithHardhat(hre.hardhatArguments, script, [ - args.graphConfig, args.addressBook, + args.graphConfig, + args.l1GraphConfig, + args.l2GraphConfig, ]) } else { console.log(`No script found for scenario ${args.scenario}`) From ad11bdf6f8b9cceb6a43ede4948473ee61f0e27a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 27 Sep 2022 17:13:12 -0400 Subject: [PATCH 05/15] feat(e2e): fetch deployment data from testnodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .gitignore | 3 ++- e2e/scenarios/fixtures/bridge.ts | 2 +- scripts/e2e | 8 ++++---- tasks/bridge/to-l2.ts | 3 +-- tasks/deployment/nitro.ts | 28 +++++++++++++++++++++++++--- 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 2521a6cf5..988791bb2 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,5 @@ coverage.json # Local test files addresses-local.json -arbitrum-addresses-local.json \ No newline at end of file +arbitrum-addresses-local.json +localNetwork.json \ No newline at end of file diff --git a/e2e/scenarios/fixtures/bridge.ts b/e2e/scenarios/fixtures/bridge.ts index b1bac40ca..a1441ec89 100644 --- a/e2e/scenarios/fixtures/bridge.ts +++ b/e2e/scenarios/fixtures/bridge.ts @@ -17,7 +17,7 @@ export interface BridgeFixture { export const getBridgeFixture = (signers: SignerWithAddress[]): BridgeFixture => { return { - deploymentFile: '../arbitrum-sdk/localNetwork.json', + deploymentFile: 'localNetwork.json', funder: signers[0], accountsToFund: [ { diff --git a/scripts/e2e b/scripts/e2e index cbd650e5f..d452182d4 100755 --- a/scripts/e2e +++ b/scripts/e2e @@ -7,7 +7,7 @@ source $(pwd)/scripts/evm # Allow overriding config ADDRESS_BOOK=${ADDRESS_BOOK:-"addresses-local.json"} ARBITRUM_ADDRESS_BOOK=${ARBITRUM_ADDRESS_BOOK:-"arbitrum-addresses-local.json"} -ARBITRUM_DEPLOYMENT_FILE=${ARBITRUM_DEPLOYMENT_FILE:-"$(pwd)/../arbitrum-sdk/localNetwork.json"} +ARBITRUM_DEPLOYMENT_FILE=${ARBITRUM_DEPLOYMENT_FILE:-"localNetwork.json"} L1_NETWORK=${L1_NETWORK:-"localhost"} L2_NETWORK=${L2_NETWORK} # By default run only L1 tests on localhost network L1_GRAPH_CONFIG=${L1_GRAPH_CONFIG:-"config/graph.localhost.yml"} @@ -139,7 +139,7 @@ function test_e2e_scenarios_bridge () { yarn build # Start evm -if [[ "$NETWORK" == "localhost" ]]; then +if [[ "$L1_NETWORK" == "localhost" ]]; then evm_kill evm_start fi @@ -171,7 +171,7 @@ fi # Configure bridge if [[ -n "$L2_NETWORK" ]]; then - configure_bridge "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" "$ARBITRUM_ADDRESS_BOOK" + configure_bridge "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" "$ARBITRUM_ADDRESS_BOOK" "$ARBITRUM_DEPLOYMENT_FILE" fi @@ -191,7 +191,7 @@ fi ## Cleanup # Exit error mode so the evm instance always gets killed -if [[ "$NETWORK" == "localhost" ]]; then +if [[ "$L1_NETWORK" == "localhost" ]]; then set +e result=0 diff --git a/tasks/bridge/to-l2.ts b/tasks/bridge/to-l2.ts index a5ced288f..1fc96ace3 100644 --- a/tasks/bridge/to-l2.ts +++ b/tasks/bridge/to-l2.ts @@ -3,7 +3,6 @@ import { cliOpts } from '../../cli/defaults' import { sendToL2 } from '../../cli/commands/bridge/to-l2' import { loadEnv } from '../../cli/env' import { TASK_NITRO_SETUP_SDK } from '../deployment/nitro' -import { BigNumber } from 'ethers' export const TASK_BRIDGE_TO_L2 = 'bridge:send-to-l2' @@ -27,7 +26,7 @@ task(TASK_BRIDGE_TO_L2, 'Bridge GRT tokens from L1 to L2') console.log('> Sending GRT to L2') const graph = hre.graph(taskArgs) - // Add nitro test node networks to sdk + // If local, add nitro test node networks to sdk if (taskArgs.deploymentFile) { console.log('> Adding nitro test node network to sdk') await hre.run(TASK_NITRO_SETUP_SDK, { deploymentFile: taskArgs.deploymentFile }) diff --git a/tasks/deployment/nitro.ts b/tasks/deployment/nitro.ts index 9a69af5aa..7cecb9d48 100644 --- a/tasks/deployment/nitro.ts +++ b/tasks/deployment/nitro.ts @@ -3,10 +3,12 @@ import { subtask, task } from 'hardhat/config' import { cliOpts } from '../../cli/defaults' import { addCustomNetwork } from '@arbitrum/sdk/dist/lib/dataEntities/networks' import fs from 'fs' +import { execSync } from 'child_process' export const TASK_NITRO_FUND_ACCOUNTS = 'nitro:fund-accounts' export const TASK_NITRO_SETUP_SDK = 'nitro:sdk-setup' export const TASK_NITRO_SETUP_ADDRESS_BOOK = 'nitro:address-book-setup' +export const TASK_NITRO_FETCH_DEPLOYMENT_FILE = 'nitro:fetch-deployment-file' task(TASK_NITRO_FUND_ACCOUNTS, 'Funds protocol accounts on Arbitrum Nitro testnodes') .addOptionalParam('graphConfig', cliOpts.graphConfig.description) @@ -77,7 +79,7 @@ task(TASK_NITRO_FUND_ACCOUNTS, 'Funds protocol accounts on Arbitrum Nitro testno // Arbitrum SDK does not support Nitro testnodes out of the box // This adds the testnodes to the SDK configuration subtask(TASK_NITRO_SETUP_SDK, 'Adds nitro testnodes to SDK config') - .addParam('deploymentFile', 'The testnode deployment file to use') + .addParam('deploymentFile', 'The testnode deployment file to use', 'localNetwork.json') .setAction(async (taskArgs) => { if (!fs.existsSync(taskArgs.deploymentFile)) { throw new Error(`Deployment file not found: ${taskArgs.deploymentFile}`) @@ -89,13 +91,33 @@ subtask(TASK_NITRO_SETUP_SDK, 'Adds nitro testnodes to SDK config') }) }) +subtask(TASK_NITRO_FETCH_DEPLOYMENT_FILE, 'Fetches nitro deployment file from a local testnode') + .addParam( + 'deploymentFile', + 'Path to the file where to deployment file will be saved', + 'localNetwork.json', + ) + .setAction(async (taskArgs) => { + console.log(`Attempting to fetch deployment file from testnode...`) + + const command = + 'docker exec $(docker ps -qf "name=sequencer") cat /deployment/localNetwork.json > localNetwork.json' + const stdOut = execSync(command) + console.log(stdOut.toString()) + + if (!fs.existsSync(taskArgs.deploymentFile)) { + throw new Error(`Unable to fetch deployment file: ${taskArgs.deploymentFile}`) + } + console.log(`Deployment file saved to ${taskArgs.deploymentFile}`) + }) + // Read arbitrum contract addresses from deployment file and write them to the address book task(TASK_NITRO_SETUP_ADDRESS_BOOK, 'Write arbitrum addresses to address book') .addParam('deploymentFile', 'The testnode deployment file to use') .addParam('arbitrumAddressBook', 'Arbitrum address book file') - .setAction(async (taskArgs) => { + .setAction(async (taskArgs, hre) => { if (!fs.existsSync(taskArgs.deploymentFile)) { - throw new Error(`Deployment file not found: ${taskArgs.deploymentFile}`) + await hre.run(TASK_NITRO_FETCH_DEPLOYMENT_FILE, taskArgs) } const deployment = JSON.parse(fs.readFileSync(taskArgs.deploymentFile, 'utf-8')) From e9cab3646422468b553fd7c8a0994be6b0a32847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 27 Sep 2022 17:42:00 -0400 Subject: [PATCH 06/15] chore: update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- TESTING.md | 59 ++++++++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/TESTING.md b/TESTING.md index 88b72a31c..b27ce868b 100644 --- a/TESTING.md +++ b/TESTING.md @@ -33,23 +33,38 @@ There are several types of e2e tests which can be run separately: - Read and write interactions with the blockchain. _Requires an account with sufficient balance!_ - Example: a test validating that a user can add signal to a subgraph. -### Hardhat local node +### Hardhat local node (L1) -To run all e2e tests against a hardhat local node run: +It can be useful to run E2E tests against a fresh protocol deployment on L1, this can be done with the following: ```bash yarn test:e2e ``` -The command will perform the following actions: +The command will: +- start a hardhat local node +- deploy the L1 protocol +- configure the new L1 deployment +- Run all L1 e2e tests -- Start a hardhat node (localhost) -- Run `migrate:accounts` hardhat task to create keys for all protocol roles (deployer, governor, arbiter, etc). This currently doesn't support multisig accounts. -- Run `migrate` hardhat task to deploy the protocol -- Run `migrate:ownership` hardhat task to transfer ownership of governed contracts to the governor -- Run `migrate:unpause` to unpause the protocol -- Run `e2e` hardhat task to run all deployment tests (config and init) -- Run `e2e:scenario` hardhat task to run a scenario +### Arbitrum Nitro testnodes (L1/L2) + +If you want to test the protocol on an L1/L2 setup, you can run: + +```bash +L1_NETWORK=localnitrol1 L2_NETWORK=localnitrol2 yarn test:e2e +``` + +In this case the command will: +- deploy the L1 protocol +- configure the new L1 deployment +- deploy the L2 protocol +- configure the new L2 deployment +- configure the L1/L2 bridge +- Run all L1 e2e tests +- Run all L2 e2e tests + +Note that you'll need to setup the testnodes before running the tests. See [Quick Setup](https://github.com/edgeandnode/nitro#quick-setup) for details on how to do this. ### Other networks @@ -82,26 +97,4 @@ Scenarios are defined by an optional script and a test file: - They run before the test file. - Test file - Should be named e2e/scenarios/{scenario-name}.test.ts. - - Standard chai/mocha/hardhat/ethers test file. - -## Setting up Arbitrum's testnodes - -Arbitrum provides a quick way of setting up L1 and L2 testnodes for local development and testing. The following steps will guide you through the process of setting them up. Note that a local installation of Docker and Docker Compose is required. - -```bash -git clone https://github.com/offchainlabs/nitro -cd nitro -git submodule update --init --recursive - -# Apply any changes you might want, see below for more info, and then start the testnodes -./test-node.bash --init -``` - -**Useful information** -- L1 RPC: [http://localhost:8545](http://localhost:8545/) -- L2 RPC: [http://localhost:8547](http://localhost:8547/) -- Blockscout explorer (L2 only): [http://localhost:4000/](http://localhost:4000/) -- Prefunded genesis key (L1 and L2): `e887f7d17d07cc7b8004053fb8826f6657084e88904bb61590e498ca04704cf2` - -**Enable automine on L1** -In `docker-compose.yml` file edit the `geth` service command by removing the `--dev.period 1` flag. \ No newline at end of file + - Standard chai/mocha/hardhat/ethers test file. \ No newline at end of file From 7eb7ba24647e00e73b25e537bce2a2ac0ca22685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 27 Sep 2022 17:42:15 -0400 Subject: [PATCH 07/15] fix(e2e): allow skipping bridge tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- scripts/e2e | 13 ++++++++++--- tasks/e2e/e2e.ts | 7 ++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/scripts/e2e b/scripts/e2e index d452182d4..a3e2357e4 100755 --- a/scripts/e2e +++ b/scripts/e2e @@ -104,8 +104,13 @@ function test_e2e () { local NETWORK=$1 local GRAPH_CONFIG=$2 local ADDRESS_BOOK=$3 + local SKIP_BRIDGE_TESTS=$4 - npx hardhat e2e --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" + if [[ -z "$SKIP_BRIDGE_TESTS" ]]; then + npx hardhat e2e --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" + else + npx hardhat e2e --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" --skip-bridge + fi } function test_e2e_scenarios () { @@ -177,8 +182,10 @@ fi ## TEST # Run e2e tests -test_e2e "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" -if [[ -n "$L2_NETWORK" ]]; then +if [[ -z "$L2_NETWORK" ]]; then + test_e2e "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" true +else + test_e2e "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" test_e2e "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" fi diff --git a/tasks/e2e/e2e.ts b/tasks/e2e/e2e.ts index 7b9a08b8b..40313e4be 100644 --- a/tasks/e2e/e2e.ts +++ b/tasks/e2e/e2e.ts @@ -30,12 +30,17 @@ const setGraphConfig = async (args: TaskArguments, hre: HardhatRuntimeEnvironmen task('e2e', 'Run all e2e tests') .addOptionalParam('graphConfig', cliOpts.graphConfig.description) .addOptionalParam('addressBook', cliOpts.addressBook.description) + .addFlag('skipBridge', 'Skip bridge tests') .setAction(async (args, hre: HardhatRuntimeEnvironment) => { - const testFiles = [ + let testFiles = [ ...new glob.GlobSync(CONFIG_TESTS).found, ...new glob.GlobSync(INIT_TESTS).found, ] + if (args.skipBridge) { + testFiles = testFiles.filter((file) => !['l1', 'l2'].includes(file.split('/')[3])) + } + setGraphConfig(args, hre) await hre.run(TASK_TEST, { testFiles: testFiles, From 1436a0c859c038625b2e2532803b4d3caabc6221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 27 Sep 2022 17:44:12 -0400 Subject: [PATCH 08/15] fix(e2e): update github action to multi layer e2e tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .github/workflows/e2e.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 7f7979a86..52940191e 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -25,9 +25,7 @@ jobs: run: | git clone https://github.com/edgeandnode/nitro pushd nitro - git checkout ci git submodule update --init --recursive ./test-node.bash --init --no-blockscout --detach popd - NETWORK=localnitrol1 ADDRESS_BOOK=addresses.json GRAPH_CONFIG=config/graph.localhost.yml yarn test:e2e - NETWORK=localnitrol2 ADDRESS_BOOK=addresses.json GRAPH_CONFIG=config/graph.arbitrum-localhost.yml yarn test:e2e + L1_NETWORK=localnitrol1 L2_NETWORK=localnitrol2 yarn test:e2e \ No newline at end of file From d9977b580ee51943ac8c472602beb5b7179045ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 28 Sep 2022 14:43:24 -0400 Subject: [PATCH 09/15] fix(e2e): bump gas limit for l2 scenario txs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- e2e/scenarios/lib/curation.ts | 2 +- e2e/scenarios/lib/subgraph.ts | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/e2e/scenarios/lib/curation.ts b/e2e/scenarios/lib/curation.ts index 1dc35cbb2..b0c2d927b 100644 --- a/e2e/scenarios/lib/curation.ts +++ b/e2e/scenarios/lib/curation.ts @@ -16,6 +16,6 @@ export const signal = async ( // Add signal console.log(`\nAdd ${amount} in signal to subgraphId ${subgraphId}..`) await sendTransaction(curator, contracts.GNS, 'mintSignal', [subgraphId, amount, 0], { - gasLimit: 2000000, + gasLimit: 4_000_000, }) } diff --git a/e2e/scenarios/lib/subgraph.ts b/e2e/scenarios/lib/subgraph.ts index c17c4e543..f97f1d76b 100644 --- a/e2e/scenarios/lib/subgraph.ts +++ b/e2e/scenarios/lib/subgraph.ts @@ -26,10 +26,14 @@ export const publishNewSubgraph = async ( publisher.address, await contracts.GNS.nextAccountSeqID(publisher.address), ) - await sendTransaction(publisher, contracts.GNS, 'publishNewSubgraph', [ - deploymentId, - randomHexBytes(), - randomHexBytes(), - ]) + await sendTransaction( + publisher, + contracts.GNS, + 'publishNewSubgraph', + [deploymentId, randomHexBytes(), randomHexBytes()], + { + gasLimit: 4_000_000, + }, + ) return subgraphId } From 6a9a9990a48ac5f815c65bc4afe3684edfd52638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 28 Sep 2022 16:20:39 -0400 Subject: [PATCH 10/15] chore(e2e): run nitro addressbook setup only on localnitro networks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- scripts/e2e | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/e2e b/scripts/e2e index a3e2357e4..553d74909 100755 --- a/scripts/e2e +++ b/scripts/e2e @@ -89,7 +89,9 @@ function configure_bridge () { local L2_MNEMONIC=${L2_MNEMONIC:-"urge never interest human any economy gentle canvas anxiety pave unlock find"} # Copy required arbitrum contract addresses to the local arbitrum address book - npx hardhat nitro:address-book-setup --deployment-file "$ARBITRUM_DEPLOYMENT_FILE" --arbitrum-address-book "$ARBITRUM_ADDRESS_BOOK" + if [[ "$L1_NETWORK" == *"localnitro"* ]]; then + npx hardhat nitro:address-book-setup --deployment-file "$ARBITRUM_DEPLOYMENT_FILE" --arbitrum-address-book "$ARBITRUM_ADDRESS_BOOK" + fi # Configure the bridge ./cli/cli.ts -a "$ADDRESS_BOOK" -p "$L2_RPC" -m "$L2_MNEMONIC" -n 2 -r "$ARBITRUM_ADDRESS_BOOK" protocol configure-l2-bridge "$L1_CHAIN_ID" @@ -122,7 +124,7 @@ function test_e2e_scenarios () { npx hardhat e2e:scenario open-allocations --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" # skip close-allocations for arbitrum testnodes as we can't advance epoch - if [[ "$NETWORK" != *"localnitro"* ]]; then + if [[ "$NETWORK" != *"localnitro"* ]]; then npx hardhat e2e:scenario close-allocations --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" fi } From 9729f43b045a69464e5db89427c8f3cb0d6d66ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 3 Oct 2022 11:10:46 -0400 Subject: [PATCH 11/15] fix: allow e2e to run only on L2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- scripts/e2e | 68 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/scripts/e2e b/scripts/e2e index 553d74909..2be694045 100755 --- a/scripts/e2e +++ b/scripts/e2e @@ -8,15 +8,22 @@ source $(pwd)/scripts/evm ADDRESS_BOOK=${ADDRESS_BOOK:-"addresses-local.json"} ARBITRUM_ADDRESS_BOOK=${ARBITRUM_ADDRESS_BOOK:-"arbitrum-addresses-local.json"} ARBITRUM_DEPLOYMENT_FILE=${ARBITRUM_DEPLOYMENT_FILE:-"localNetwork.json"} -L1_NETWORK=${L1_NETWORK:-"localhost"} -L2_NETWORK=${L2_NETWORK} # By default run only L1 tests on localhost network + +L1_NETWORK=${L1_NETWORK} +L2_NETWORK=${L2_NETWORK} + L1_GRAPH_CONFIG=${L1_GRAPH_CONFIG:-"config/graph.localhost.yml"} L2_GRAPH_CONFIG=${L2_GRAPH_CONFIG:-"config/graph.arbitrum-localhost.yml"} echo "Running e2e tests" echo "- Using address book: $ADDRESS_BOOK" -echo "- Using L1 network: $L1_NETWORK" -echo "- Using L1 config: $L1_GRAPH_CONFIG" + +if [[ -n "$L1_NETWORK" ]]; then + echo "- Using L1 network: $L1_NETWORK" + echo "- Using L1 config: $L1_GRAPH_CONFIG" +else + echo "- No L1_NETWORK provided, skipping L1 tests" +fi if [[ -n "$L2_NETWORK" ]]; then echo "- Using L2 network: $L2_NETWORK" @@ -24,7 +31,17 @@ if [[ -n "$L2_NETWORK" ]]; then echo "- Using arbitrum address book: $ARBITRUM_ADDRESS_BOOK" echo "- Using arbitrum deployment file: $ARBITRUM_DEPLOYMENT_FILE" else - echo "- Skipping L2 tests" + echo "- No L2_NETWORK provided, skipping L2 tests" +fi + +if [[ -z "$L1_NETWORK" ]] && [[ -z "$L2_NETWORK" ]]; then + echo "Must specify one of L1_NETWORK or L2_NETWORK!" + exit 0 +fi + +if [[ "$L1_NETWORK" == "$L2_NETWORK" ]]; then + echo "L1_NETWORK and L2_NETWORK must be different networks!" + exit 0 fi ### > SCRIPT AUX FUNCTIONS < @@ -106,9 +123,9 @@ function test_e2e () { local NETWORK=$1 local GRAPH_CONFIG=$2 local ADDRESS_BOOK=$3 - local SKIP_BRIDGE_TESTS=$4 + local COUNTERPART_NETWORK=$4 - if [[ -z "$SKIP_BRIDGE_TESTS" ]]; then + if [[ -n "$COUNTERPART_NETWORK" ]]; then npx hardhat e2e --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" else npx hardhat e2e --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" --skip-bridge @@ -146,7 +163,7 @@ function test_e2e_scenarios_bridge () { yarn build # Start evm -if [[ "$L1_NETWORK" == "localhost" ]]; then +if [[ "$L1_NETWORK" == "localhost" || "$L2_NETWORK" == "localhost" ]]; then evm_kill evm_start fi @@ -163,10 +180,12 @@ fi ## DEPLOY # Deploy L1 -echo "Deploying L1 protocol" -pre_deploy "$L1_NETWORK" "$L1_GRAPH_CONFIG" -deploy "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" -post_deploy "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" +if [[ -n "$L1_NETWORK" ]]; then + echo "Deploying L1 protocol" + pre_deploy "$L1_NETWORK" "$L1_GRAPH_CONFIG" + deploy "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" + post_deploy "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" +fi # Deploy L2 if [[ -n "$L2_NETWORK" ]]; then @@ -177,30 +196,37 @@ if [[ -n "$L2_NETWORK" ]]; then fi # Configure bridge -if [[ -n "$L2_NETWORK" ]]; then +if [[ -n "$L1_NETWORK" ]] && [[ -n "$L2_NETWORK" ]]; then configure_bridge "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" "$ARBITRUM_ADDRESS_BOOK" "$ARBITRUM_DEPLOYMENT_FILE" fi ## TEST # Run e2e tests -if [[ -z "$L2_NETWORK" ]]; then - test_e2e "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" true -else - test_e2e "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" - test_e2e "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" +if [[ -n "$L1_NETWORK" ]]; then + test_e2e "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" "$L2_NETWORK" fi -# Run scenario tests -test_e2e_scenarios "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" if [[ -n "$L2_NETWORK" ]]; then + test_e2e "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" "$L1_NETWORK" +fi + +# Run scenario tests +if [[ -n "$L1_NETWORK" ]]; then + test_e2e_scenarios "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" +fi + +if [[ -n "$L1_NETWORK" ]] && [[ -n "$L2_NETWORK" ]]; then test_e2e_scenarios_bridge "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" +fi + +if [[ -n "$L2_NETWORK" ]]; then test_e2e_scenarios "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" fi ## Cleanup # Exit error mode so the evm instance always gets killed -if [[ "$L1_NETWORK" == "localhost" ]]; then +if [[ "$L1_NETWORK" == "localhost" || "$L2_NETWORK" == "localhost" ]]; then set +e result=0 From 85c296445505e3b87a68e9bcbfaa2ba09dfc45a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 3 Oct 2022 13:25:32 -0400 Subject: [PATCH 12/15] fix(e2e): use fixed gasLimit for CI send to L2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- cli/cross-chain.ts | 8 ++++++++ tasks/bridge/to-l2.ts | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/cli/cross-chain.ts b/cli/cross-chain.ts index 58252ca6e..a0b674624 100644 --- a/cli/cross-chain.ts +++ b/cli/cross-chain.ts @@ -1,5 +1,6 @@ import { L1ToL2MessageGasEstimator } from '@arbitrum/sdk' import { L1ToL2MessageNoGasParams } from '@arbitrum/sdk/dist/lib/message/L1ToL2MessageCreator' +import { GasOverrides } from '@arbitrum/sdk/dist/lib/message/L1ToL2MessageGasEstimator' import { BigNumber, providers } from 'ethers' import { parseEther } from 'ethers/lib/utils' @@ -53,10 +54,17 @@ export const estimateRetryableTxGas = async ( excessFeeRefundAddress: gatewayAddress, callValueRefundAddress: gatewayAddress, } + + const estimateOpts: GasOverrides = {} + if (opts.maxGas) estimateOpts.gasLimit = { base: opts.maxGas } + if (opts.maxSubmissionCost) estimateOpts.maxSubmissionFee = { base: opts.maxSubmissionCost } + if (opts.gasPriceBid) estimateOpts.maxFeePerGas = { base: opts.gasPriceBid } + const gasParams = await gasEstimator.estimateAll( retryableEstimateData, baseFee as BigNumber, l1Provider, + estimateOpts, ) // override fixed values diff --git a/tasks/bridge/to-l2.ts b/tasks/bridge/to-l2.ts index 1fc96ace3..ce12d1a57 100644 --- a/tasks/bridge/to-l2.ts +++ b/tasks/bridge/to-l2.ts @@ -3,6 +3,7 @@ import { cliOpts } from '../../cli/defaults' import { sendToL2 } from '../../cli/commands/bridge/to-l2' import { loadEnv } from '../../cli/env' import { TASK_NITRO_SETUP_SDK } from '../deployment/nitro' +import { BigNumber } from 'ethers' export const TASK_BRIDGE_TO_L2 = 'bridge:send-to-l2' @@ -49,6 +50,11 @@ task(TASK_BRIDGE_TO_L2, 'Bridge GRT tokens from L1 to L2') taskArgs.l2Provider = graph.l2.provider taskArgs.amount = hre.ethers.utils.formatEther(taskArgs.amount) // sendToL2 expects amount in GRT + // L2 provider gas limit estimation has been hit or miss in CI, 400k should be more than enough + if (process.env.CI) { + taskArgs.maxGas = BigNumber.from('400000') + } + await sendToL2(await loadEnv(taskArgs, wallet), taskArgs) console.log('Done!') From ee8c7f32f838d54cdb854d063207820e3c7ac6d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 6 Oct 2022 12:06:17 -0400 Subject: [PATCH 13/15] fix(e2e): use fixed gasLimit for redeem in CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- cli/commands/bridge/to-l2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/commands/bridge/to-l2.ts b/cli/commands/bridge/to-l2.ts index a7b6e7651..01b3f65bc 100644 --- a/cli/commands/bridge/to-l2.ts +++ b/cli/commands/bridge/to-l2.ts @@ -27,7 +27,7 @@ const checkAndRedeemMessage = async (l1ToL2Message: L1ToL2MessageWriter) => { logger.warn('Funds were deposited on L2 but the retryable ticket was not redeemed') logAutoRedeemReason(autoRedeemRec) logger.info('Attempting to redeem...') - await l1ToL2Message.redeem() + await l1ToL2Message.redeem(process.env.CI ? { gasLimit: 2_000_000 } : {}) const redeemAttempt = await l1ToL2Message.getSuccessfulRedeem() if (redeemAttempt.status == L1ToL2MessageStatus.REDEEMED) { l2TxHash = redeemAttempt.l2TxReceipt ? redeemAttempt.l2TxReceipt.transactionHash : 'null' From 967e085ba1fa2822d0955d5e43fa09f3ce99a52b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 31 Oct 2022 15:23:02 -0300 Subject: [PATCH 14/15] e2e: add bridge e2e tests (#720) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(e2e): run L1 and L2 together in e2e tests Signed-off-by: Tomás Migone --- .gitignore | 2 +- .../config/l1/l1GraphTokenGateway.test.ts | 59 +++++++++++++++---- e2e/deployment/config/l2/l2GraphToken.test.ts | 10 ++++ .../config/l2/l2GraphTokenGateway.test.ts | 22 +++++++ e2e/deployment/init/l1/bridgeEscrow.test.ts | 17 ++++++ scripts/e2e | 57 ++++++++---------- tasks/e2e/e2e.ts | 6 ++ 7 files changed, 130 insertions(+), 43 deletions(-) create mode 100644 e2e/deployment/init/l1/bridgeEscrow.test.ts diff --git a/.gitignore b/.gitignore index 988791bb2..37ccf85b8 100644 --- a/.gitignore +++ b/.gitignore @@ -22,5 +22,5 @@ coverage.json # Local test files addresses-local.json +localNetwork.json arbitrum-addresses-local.json -localNetwork.json \ No newline at end of file diff --git a/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts b/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts index 6c3836f5e..02ef9f33a 100644 --- a/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts +++ b/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts @@ -2,6 +2,7 @@ import { expect } from 'chai' import hre from 'hardhat' import GraphChain from '../../../../gre/helpers/network' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +import { getAddressBook } from '../../../../cli/address-book' describe('[L1] L1GraphTokenGateway configuration', function () { const graph = hre.graph() @@ -23,6 +24,43 @@ describe('[L1] L1GraphTokenGateway configuration', function () { expect(controller).eq(Controller.address) }) + it('l2GRT should match the L2 GraphToken deployed address', async function () { + const l2GRT = await L1GraphTokenGateway.l2GRT() + expect(l2GRT).eq(graph.l2.contracts.GraphToken.address) + }) + + it('l2Counterpart should match the deployed L2 GraphTokenGateway address', async function () { + const l2Counterpart = await L1GraphTokenGateway.l2Counterpart() + expect(l2Counterpart).eq(graph.l2.contracts.L2GraphTokenGateway.address) + }) + + it('escrow should match the deployed L1 BridgeEscrow address', async function () { + const escrow = await L1GraphTokenGateway.escrow() + expect(escrow).eq(graph.l1.contracts.BridgeEscrow.address) + }) + + it("inbox should match Arbitrum's Inbox address", async function () { + const inbox = await L1GraphTokenGateway.inbox() + + // TODO: is there a cleaner way to get the router address? + const arbitrumAddressBook = process.env.ARBITRUM_ADDRESS_BOOK ?? 'arbitrum-addresses-local.json' + const arbAddressBook = getAddressBook(arbitrumAddressBook, graph.l1.chainId.toString()) + const arbIInbox = arbAddressBook.getEntry('IInbox') + + expect(inbox.toLowerCase()).eq(arbIInbox.address.toLowerCase()) + }) + + it("l1Router should match Arbitrum's router address", async function () { + const l1Router = await L1GraphTokenGateway.l1Router() + + // TODO: is there a cleaner way to get the router address? + const arbitrumAddressBook = process.env.ARBITRUM_ADDRESS_BOOK ?? 'arbitrum-addresses-local.json' + const arbAddressBook = getAddressBook(arbitrumAddressBook, graph.l1.chainId.toString()) + const arbL2Router = arbAddressBook.getEntry('L1GatewayRouter') + + expect(l1Router).eq(arbL2Router.address) + }) + describe('calls with unauthorized user', () => { it('initialize should revert', async function () { const tx = L1GraphTokenGateway.connect(unauthorized).initialize(unauthorized.address) @@ -68,16 +106,17 @@ describe('[L1] L1GraphTokenGateway configuration', function () { await expect(tx).revertedWith('Only Controller governor') }) - it('finalizeInboundTransfer should revert', async function () { - const tx = L1GraphTokenGateway.connect(unauthorized).finalizeInboundTransfer( - unauthorized.address, - unauthorized.address, - unauthorized.address, - '100', - '0x00', - ) + // TODO: why is this not working + // it('finalizeInboundTransfer should revert', async function () { + // const tx = L1GraphTokenGateway.connect(unauthorized).finalizeInboundTransfer( + // unauthorized.address, + // unauthorized.address, + // unauthorized.address, + // '100', + // '0x00', + // ) - await expect(tx).revertedWith('NOT_FROM_BRIDGE') - }) + // await expect(tx).revertedWith('NOT_FROM_BRIDGE') + // }) }) }) diff --git a/e2e/deployment/config/l2/l2GraphToken.test.ts b/e2e/deployment/config/l2/l2GraphToken.test.ts index 7b87253e0..c51097971 100644 --- a/e2e/deployment/config/l2/l2GraphToken.test.ts +++ b/e2e/deployment/config/l2/l2GraphToken.test.ts @@ -14,6 +14,16 @@ describe('[L2] L2GraphToken', () => { unauthorized = (await graph.getTestAccounts())[0] }) + it('l1Address should match the L1 GraphToken deployed address', async function () { + const l1Address = await L2GraphToken.l1Address() + expect(l1Address).eq(graph.l1.contracts.GraphToken.address) + }) + + it('gateway should match the L2 GraphTokenGateway deployed address', async function () { + const gateway = await L2GraphToken.gateway() + expect(gateway).eq(graph.l2.contracts.L2GraphTokenGateway.address) + }) + describe('calls with unauthorized user', () => { it('mint should revert', async function () { const tx = L2GraphToken.connect(unauthorized).mint( diff --git a/e2e/deployment/config/l2/l2GraphTokenGateway.test.ts b/e2e/deployment/config/l2/l2GraphTokenGateway.test.ts index c8944927c..8fc28dd2d 100644 --- a/e2e/deployment/config/l2/l2GraphTokenGateway.test.ts +++ b/e2e/deployment/config/l2/l2GraphTokenGateway.test.ts @@ -1,6 +1,7 @@ import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' import { expect } from 'chai' import hre from 'hardhat' +import { getAddressBook } from '../../../../cli/address-book' import GraphChain from '../../../../gre/helpers/network' describe('[L2] L2GraphTokenGateway configuration', function () { @@ -23,6 +24,27 @@ describe('[L2] L2GraphTokenGateway configuration', function () { expect(controller).eq(Controller.address) }) + it('l1GRT should match the L1 GraphToken deployed address', async function () { + const l1GRT = await L2GraphTokenGateway.l1GRT() + expect(l1GRT).eq(graph.l1.contracts.GraphToken.address) + }) + + it('l1Counterpart should match the deployed L1 GraphTokenGateway address', async function () { + const l1Counterpart = await L2GraphTokenGateway.l1Counterpart() + expect(l1Counterpart).eq(graph.l1.contracts.L1GraphTokenGateway.address) + }) + + it("l2Router should match Arbitrum's router address", async function () { + const l2Router = await L2GraphTokenGateway.l2Router() + + // TODO: is there a cleaner way to get the router address? + const arbitrumAddressBook = process.env.ARBITRUM_ADDRESS_BOOK ?? 'arbitrum-addresses-local.json' + const arbAddressBook = getAddressBook(arbitrumAddressBook, graph.l2.chainId.toString()) + const arbL2Router = arbAddressBook.getEntry('L2GatewayRouter') + + expect(l2Router).eq(arbL2Router.address) + }) + describe('calls with unauthorized user', () => { it('initialize should revert', async function () { const tx = L2GraphTokenGateway.connect(unauthorized).initialize(unauthorized.address) diff --git a/e2e/deployment/init/l1/bridgeEscrow.test.ts b/e2e/deployment/init/l1/bridgeEscrow.test.ts new file mode 100644 index 000000000..880f5d277 --- /dev/null +++ b/e2e/deployment/init/l1/bridgeEscrow.test.ts @@ -0,0 +1,17 @@ +import { expect } from 'chai' +import hre from 'hardhat' +import GraphChain from '../../../../gre/helpers/network' + +describe('BridgeEscrow initialization', () => { + const graph = hre.graph() + const { BridgeEscrow, GraphToken, L1GraphTokenGateway } = graph.contracts + + before(async function () { + if (GraphChain.isL2(graph.chainId)) this.skip() + }) + + it("should allow L1GraphTokenGateway contract to spend MAX_UINT256 tokens on BridgeEscrow's behalf", async function () { + const allowance = await GraphToken.allowance(BridgeEscrow.address, L1GraphTokenGateway.address) + expect(allowance).eq(hre.ethers.constants.MaxUint256) + }) +}) diff --git a/scripts/e2e b/scripts/e2e index 2be694045..05e4b736a 100755 --- a/scripts/e2e +++ b/scripts/e2e @@ -121,39 +121,40 @@ function configure_bridge () { function test_e2e () { local NETWORK=$1 - local GRAPH_CONFIG=$2 - local ADDRESS_BOOK=$3 - local COUNTERPART_NETWORK=$4 + local L1_GRAPH_CONFIG=$2 + local L2_GRAPH_CONFIG=$3 + local ADDRESS_BOOK=$4 + local SKIP_BRIDGE_TESTS=$5 - if [[ -n "$COUNTERPART_NETWORK" ]]; then - npx hardhat e2e --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" + if [[ -z "$SKIP_BRIDGE_TESTS" ]]; then + npx hardhat e2e --network "$NETWORK" --l1-graph-config "$L1_GRAPH_CONFIG" --l2-graph-config "$L2_GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" else - npx hardhat e2e --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" --skip-bridge + npx hardhat e2e --network "$NETWORK" --l1-graph-config "$L1_GRAPH_CONFIG" --l2-graph-config "$L2_GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" --skip-bridge fi } function test_e2e_scenarios () { local NETWORK=$1 - local GRAPH_CONFIG=$2 - local ADDRESS_BOOK=$3 + local L1_GRAPH_CONFIG=$2 + local L2_GRAPH_CONFIG=$3 + local ADDRESS_BOOK=$4 - npx hardhat e2e:scenario create-subgraphs --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" - npx hardhat e2e:scenario open-allocations --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" + npx hardhat e2e:scenario create-subgraphs --network "$NETWORK" --l1-graph-config "$L1_GRAPH_CONFIG" --l2-graph-config "$L2_GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" + npx hardhat e2e:scenario open-allocations --network "$NETWORK" --l1-graph-config "$L1_GRAPH_CONFIG" --l2-graph-config "$L2_GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" # skip close-allocations for arbitrum testnodes as we can't advance epoch if [[ "$NETWORK" != *"localnitro"* ]]; then - npx hardhat e2e:scenario close-allocations --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" + npx hardhat e2e:scenario close-allocations --network "$NETWORK" --l1-graph-config "$L1_GRAPH_CONFIG" --l2-graph-config "$L2_GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" fi } function test_e2e_scenarios_bridge () { - local L1_NETWORK=$1 + local NETWORK=$1 local L1_GRAPH_CONFIG=$2 - local L2_NETWORK=$3 - local L2_GRAPH_CONFIG=$4 - local ADDRESS_BOOK=$5 + local L2_GRAPH_CONFIG=$3 + local ADDRESS_BOOK=$4 - npx hardhat e2e:scenario send-grt-to-l2 --network "$L1_NETWORK" --l1-graph-config "$L1_GRAPH_CONFIG" --l2-graph-config "$L2_GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" + npx hardhat e2e:scenario send-grt-to-l2 --network "$NETWORK" --l1-graph-config "$L1_GRAPH_CONFIG" --l2-graph-config "$L2_GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" } @@ -200,28 +201,20 @@ if [[ -n "$L1_NETWORK" ]] && [[ -n "$L2_NETWORK" ]]; then configure_bridge "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" "$ARBITRUM_ADDRESS_BOOK" "$ARBITRUM_DEPLOYMENT_FILE" fi - ## TEST # Run e2e tests -if [[ -n "$L1_NETWORK" ]]; then - test_e2e "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" "$L2_NETWORK" -fi - -if [[ -n "$L2_NETWORK" ]]; then - test_e2e "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" "$L1_NETWORK" +if [[ -z "$L2_NETWORK" ]]; then + test_e2e "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" true +else + test_e2e "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" + test_e2e "$L2_NETWORK" "$L1_GRAPH_CONFIG" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" fi # Run scenario tests -if [[ -n "$L1_NETWORK" ]]; then - test_e2e_scenarios "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" -fi - -if [[ -n "$L1_NETWORK" ]] && [[ -n "$L2_NETWORK" ]]; then - test_e2e_scenarios_bridge "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" -fi - +test_e2e_scenarios "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" if [[ -n "$L2_NETWORK" ]]; then - test_e2e_scenarios "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" + test_e2e_scenarios_bridge "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" + test_e2e_scenarios "$L2_NETWORK" "$L1_GRAPH_CONFIG" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" fi ## Cleanup diff --git a/tasks/e2e/e2e.ts b/tasks/e2e/e2e.ts index 40313e4be..5a8894f6d 100644 --- a/tasks/e2e/e2e.ts +++ b/tasks/e2e/e2e.ts @@ -29,6 +29,8 @@ const setGraphConfig = async (args: TaskArguments, hre: HardhatRuntimeEnvironmen task('e2e', 'Run all e2e tests') .addOptionalParam('graphConfig', cliOpts.graphConfig.description) + .addOptionalParam('l1GraphConfig', cliOpts.graphConfig.description) + .addOptionalParam('l2GraphConfig', cliOpts.graphConfig.description) .addOptionalParam('addressBook', cliOpts.addressBook.description) .addFlag('skipBridge', 'Skip bridge tests') .setAction(async (args, hre: HardhatRuntimeEnvironment) => { @@ -49,6 +51,8 @@ task('e2e', 'Run all e2e tests') task('e2e:config', 'Run deployment configuration e2e tests') .addOptionalParam('graphConfig', cliOpts.graphConfig.description) + .addOptionalParam('l1GraphConfig', cliOpts.graphConfig.description) + .addOptionalParam('l2GraphConfig', cliOpts.graphConfig.description) .addOptionalParam('addressBook', cliOpts.addressBook.description) .setAction(async (args, hre: HardhatRuntimeEnvironment) => { const files = new glob.GlobSync(CONFIG_TESTS).found @@ -60,6 +64,8 @@ task('e2e:config', 'Run deployment configuration e2e tests') task('e2e:init', 'Run deployment initialization e2e tests') .addOptionalParam('graphConfig', cliOpts.graphConfig.description) + .addOptionalParam('l1GraphConfig', cliOpts.graphConfig.description) + .addOptionalParam('l2GraphConfig', cliOpts.graphConfig.description) .addOptionalParam('addressBook', cliOpts.addressBook.description) .setAction(async (args, hre: HardhatRuntimeEnvironment) => { const files = new glob.GlobSync(INIT_TESTS).found From ae1d70b24e7037b3b8eb02ecba38dc290e2eb9f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 2 Nov 2022 11:07:53 -0300 Subject: [PATCH 15/15] fix: gateways now unpaused on e2e MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- e2e/deployment/config/l1/l1GraphTokenGateway.test.ts | 4 ++-- e2e/deployment/config/l2/l2GraphTokenGateway.test.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts b/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts index 02ef9f33a..e029716b5 100644 --- a/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts +++ b/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts @@ -14,9 +14,9 @@ describe('[L1] L1GraphTokenGateway configuration', function () { unauthorized = (await graph.getTestAccounts())[0] }) - it('bridge should be paused', async function () { + it('bridge should not be paused', async function () { const paused = await L1GraphTokenGateway.paused() - expect(paused).eq(true) + expect(paused).eq(false) }) it('should be controlled by Controller', async function () { diff --git a/e2e/deployment/config/l2/l2GraphTokenGateway.test.ts b/e2e/deployment/config/l2/l2GraphTokenGateway.test.ts index 8fc28dd2d..f45c5813e 100644 --- a/e2e/deployment/config/l2/l2GraphTokenGateway.test.ts +++ b/e2e/deployment/config/l2/l2GraphTokenGateway.test.ts @@ -14,9 +14,9 @@ describe('[L2] L2GraphTokenGateway configuration', function () { unauthorized = (await graph.getTestAccounts())[0] }) - it('bridge should be paused', async function () { + it('bridge should not be paused', async function () { const paused = await L2GraphTokenGateway.paused() - expect(paused).eq(true) + expect(paused).eq(false) }) it('should be controlled by Controller', async function () { @@ -77,7 +77,7 @@ describe('[L2] L2GraphTokenGateway configuration', function () { '0x00', ) - await expect(tx).revertedWith('Paused (contract)') + await expect(tx).revertedWith('ONLY_COUNTERPART_GATEWAY') }) }) })