Skip to content
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

improve: update sdk queries to accurately estimate gas costs #64

Merged

Conversation

james-a-morris
Copy link
Contributor

This PR aims to reflect the gas cost estimation changes proposed by PR 212 at the SDK level.

During the development of this PR, I found a pattern in the call structure across all chain queries to estimate gas costs. I encapsulated it in two utility functions.

Finally, the SDK e2e test was found to have an error on production, so this PR includes a patch.

Comment on lines +5 to +6
// NODE_URL_1
// NODE_URL_137
Copy link
Contributor Author

@james-a-morris james-a-morris Aug 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two environment variables may need to be added to the e2e test on Git Actions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems easy to do

Alternatively we could use the public infura key here but I do think setting env vars in github actions is more sustainable

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to try to add these to the github actions file in ./.github/?

src/utils.ts Outdated Show resolved Hide resolved
src/utils.ts Outdated Show resolved Hide resolved
@james-a-morris james-a-morris marked this pull request as ready for review August 8, 2022 12:40
@@ -35,7 +37,8 @@ describe("Queries", function () {
]);
});
test("Ethereum", async function () {
const ethereumQueries = new EthereumQueries();
const provider = new providers.JsonRpcProvider(process.env.NODE_URL_1);
const ethereumQueries = new EthereumQueries(provider);
await Promise.all([
ethereumQueries.getGasCosts("USDC"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we test that the return values are sensible values? For example, the gas costs are a wei value, decimals are 6, etc?

@@ -19,9 +23,8 @@ export class ArbitrumQueries implements QueryInterface {
}

async getGasCosts(_tokenSymbol: string): Promise<BigNumberish> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's quite a lot of duplication across these different classes (arbitrum, polygon, etc.). Can we potentially change the QueryInterface they currently implement to be a class they can inherit all these common methods from? I think currently only Polygon has a different implementation of getTokenPrice() and all other ones look exactly the same (just different addresses which can easily be passed in the constructor)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree - I did notice code-duplication within the chain queries. In this PR I focused primarily on refactoring the duplication within getGasCosts

But, I think changing QueryInterface to a class structure (assuming there aren't any frontend/relayer dependencies) would be a great move. As you mentioned, the inheritance would help refactor the code into a more succinct format.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would actually remove all the code for all chains, if I'm not mistaken, except for Polygon, which needs to override getTokenPrice().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep! And if we pass a coinGeckoBaseCurrency variable to the base class, we can use the shared implementation of super.getTokenPrice() for the first half of the Polygon getTokenPrice custom implementation (further cutting the code reuse).

Copy link
Member

@nicholaspai nicholaspai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great refactor! I left some comments on constructor variable visibility consistency and suggestions for the e2e tests. I also want to make sure that @kevinuma reviews this to make sure its consistent with the potential changes in his relayer-v2 PR

Copy link
Contributor

@mrice32 mrice32 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all looks really great! Nice work @james-a-morris!

src/utils.ts Outdated Show resolved Hide resolved
src/utils.ts Show resolved Hide resolved
src/utils.ts Outdated Show resolved Hide resolved
src/relayFeeCalculator/chain-queries/ethereum.ts Outdated Show resolved Hide resolved
src/utils.ts Outdated
Comment on lines 242 to 243
// Verify if this provider has been L2Provider wrapped
if (isL2Provider(provider)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can we make this comment more specific that this detects whether this is an Optimism-specific provider? The way it's written now, it almost seems like all L2s get captured in this if, whereas this logic is Optimism-specific.

Alternatively, you could rename isL2Provider/L2Provider on import to something more optimism specific. Either way is cool with me!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated here. To really highlight the difference, I added both a comment & changed the function alias

Copy link
Contributor

@mrice32 mrice32 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Two minor nits/suggestions

import { SymbolMapping } from "./ethereum";
import { Coingecko } from "../../coingecko/Coingecko";
import { ArbitrumSpokePool__factory, ArbitrumSpokePool } from "@across-protocol/contracts-v2";
import { ArbitrumSpokePool__factory, SpokePool } from "@across-protocol/contracts-v2";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: shouldn't these factories all be changed to be SpokePool__factory? I'm a bit surprised that the types are working (I didn't think that on-chain inheritance implies typechain type inheritance, but that's cool!). Anyway, it's probably a good idea to use the same factory type as the contract type you're using just to avoid any type issues in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/utils.ts Outdated Show resolved Hide resolved
@james-a-morris james-a-morris merged commit a0ad4fb into master Aug 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants