-
Notifications
You must be signed in to change notification settings - Fork 75
initial version of gas analysis script #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…art-contracts-v2 into npai/gas-analysis
…art-contracts-v2 into npai/gas-analysis
| } | ||
|
|
||
| // Construct tree with REFUND_CHAIN_COUNT leaves, each containing REFUND_TOKEN_COUNT sends | ||
| async function constructSimpleTree() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before adding more code to this script and more test cases, I'm curious what you guys think about this being on the right track for gas analysis? Currently it only allows you create REFUND_CHAIN_COUNT count of leaves, each with REFUND_TOKEN_COUNT rebalances triggered by the HubPool.executeRelayerRefund method
| import { | ||
| toBNWei, | ||
| toBN, | ||
| SignerWithAddress, | ||
| seedWallet, | ||
| Contract, | ||
| ethers, | ||
| getContractFactory, | ||
| BigNumber, | ||
| randomAddress, | ||
| expect, | ||
| } from "../utils"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's cleaner to do two imports for this kind of thing, rather than taking 12 lines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you do import * as utils from "../utils" then you need to call utils.expect and utils.Contract for types, which seems annoying. Were you thinking of something different?
|
|
||
| describe("Gas Analytics: HubPool Relayer Refund Execution", function () { | ||
| before(async function () { | ||
| if (!process.env.GAS_TEST_ENABLED) this.skip(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
janky but works well! good
|
|
||
| // Now that we've verified that the transaction succeeded, let's compute average gas costs. | ||
| const receipt = await txn.wait(); | ||
| console.log(receipt.cumulativeGasUsed); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps add some additional strings to this? something like cumlativeGasUsed: or something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah just starting from here, I'll log it
mrice32
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is awesome! Love the way you're approaching the package.json scripts.
Have we figured out a strategy for estimating gas costs in different environments (arbitrum, optimism, etc)? Note: this would only be relevant for SpokePool tests, but was just curious if you had thought about that.
package.json
Outdated
| "lint-fix": "yarn prettier --write", | ||
| "prettier": "prettier .", | ||
| "test": "REPORT_GAS=true yarn hardhat test" | ||
| "test": "REPORT_GAS=true yarn hardhat test", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does REPORT_GAS=true do? If it's the hardhat module, should we turn this off for normal test runs (to reduce runtime) and have a separate call for hardhat gas reporting when you want it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah good call
|
|
||
| // Deploy test tokens for each chain ID | ||
| for (let i = 0; i < REFUND_CHAIN_COUNT; i++) { | ||
| destinationChainIds.push(i); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For multiple tests, I don't think this array ever gets reset, so you would end up with [1 ... n, 1 ... n, 1 ...n, etc] after a few runs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahh great catch
| const leafIndexToExecute = 0; | ||
|
|
||
| await hubPool.connect(dataWorker).initiateRelayerRefund( | ||
| [3117], // bundleEvaluationBlockNumbers used by bots to construct bundles. Length must equal the number of leafs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's 3117?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a random block number, I'll set this to something in consts to be more clear
| expect(await l1Tokens[leafIndexToExecute][i].balanceOf(mockAdapter.address)).to.equal(SEND_AMOUNT); | ||
| } | ||
|
|
||
| // Now that we've verified that the transaction succeeded, let's compute average gas costs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: is this supposed to be an average?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this ones. not an avrerage, the next test case will execute all leaves i'll fix the comment
| const { leafs, tree } = await constructSimpleTree(); | ||
| const leafIndexToExecute = 0; | ||
|
|
||
| await hubPool.connect(dataWorker).initiateRelayerRefund( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be measuring the gas cost of this call as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure
|
Here's the latest run of |
mrice32
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! One minor comment
|
|
||
| // Now that we've verified that the transaction succeeded, let's compute average gas costs. | ||
| const receipts = await Promise.all(txns.map((_txn) => _txn.wait())); | ||
| const cumulativeGasUsed = receipts.map((_receipt) => _receipt.cumulativeGasUsed).reduce((x, y) => x.add(y)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wherever we're computing gas, I think we should use gasUsed, not cumulativeGasUsed. The latter is the gas used in this transaction and all preceding transactions in the same block. Not sure this will be a problem in hardhat since it usually maps each transaction to its own block, but since that's not guaranteed we probably just want to use gasUsed to be safe.
Authored by Matt & Nick. Signed-off-by: Matt Rice <matthewcrice32@gmail.com> Co-authored-by: nicholaspai <9457025+nicholaspai@users.noreply.github.com> Co-authored-by: Matt Rice <matthewcrice32@gmail.com>
can be run via
yarn test:gas