Skip to content

Commit

Permalink
perf: avoid initializing ethers contracts during construction
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielSchiavini committed Aug 30, 2024
1 parent cd36cb4 commit 346997a
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 38 deletions.
31 changes: 16 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,25 @@
},
"type": "module",
"devDependencies": {
"@types/chai": "^4.3.4",
"@types/memoizee": "^0.4.7",
"@types/mocha": "^10.0.1",
"@types/node": "^14.14.37",
"@typescript-eslint/eslint-plugin": "^4.33.0",
"@typescript-eslint/parser": "^4.20.0",
"@types/chai": "^4.3.19",
"@types/memoizee": "^0.4.11",
"@types/mocha": "^10.0.7",
"@types/node": "^22.5.1",
"@typescript-eslint/eslint-plugin": "^8.3.0",
"@typescript-eslint/parser": "^8.3.0",
"babel-eslint": "^10.1.0",
"chai": "^4.3.7",
"eslint": "^7.32.0",
"mocha": "^10.2.0",
"typescript": "^4.5.2",
"vue-eslint-parser": "^7.6.0"
"chai": "^5.1.1",
"eslint": "^9.9.1",
"mocha": "^10.7.3",
"typescript": "^5.5.4",
"vue-eslint-parser": "^9.4.3"
},
"dependencies": {
"axios": "^0.21.1",
"bignumber.js": "^9.0.1",
"@curvefi/ethcall": "6.0.7",
"ethers": "^6.11.0",
"memoizee": "^0.4.15"
"abitype": "^1.0.6",
"axios": "^0.21.1",
"bignumber.js": "^9.1.2",
"ethers": "^6.13.2",
"memoizee": "^0.4.17"
}
}
6 changes: 5 additions & 1 deletion src/curve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
JsonRpcProvider,
Signer,
} from "ethers";
import type { Abi } from "abitype";
import { Provider as MulticallProvider, Contract as MulticallContract } from "@curvefi/ethcall";
import { getFactoryPoolData } from "./factory/factory.js";
import { getFactoryPoolsDataFromApi } from "./factory/factory-api.js";
Expand Down Expand Up @@ -419,13 +420,16 @@ export const NETWORK_CONSTANTS: { [index: number]: any } = {

const OLD_CHAINS = [1, 10, 56, 100, 137, 250, 1284, 2222, 8453, 42161, 42220, 43114, 1313161554]; // these chains have non-ng pools


export type ContractItem = { contract: Contract, multicallContract: MulticallContract, abi: Abi };

class Curve implements ICurve {
provider: ethers.BrowserProvider | ethers.JsonRpcProvider;
multicallProvider: MulticallProvider;
signer: ethers.Signer | null;
signerAddress: string;
chainId: IChainId;
contracts: { [index: string]: { contract: Contract, multicallContract: MulticallContract } };
contracts: { [index: string]: ContractItem };
feeData: { gasPrice?: number, maxFeePerGas?: number, maxPriorityFeePerGas?: number };
constantOptions: { gasLimit?: number };
options: { gasPrice?: number | bigint, maxFeePerGas?: number | bigint, maxPriorityFeePerGas?: number | bigint };
Expand Down
5 changes: 2 additions & 3 deletions src/pools/PoolTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
smartNumber,
DIGas,
_getAddress,
isMethodExist,
findAbiFunction,
getVolumeApiController,
} from '../utils.js';
import {IDict, IReward, IProfit, IPoolType} from '../interfaces';
Expand Down Expand Up @@ -2323,8 +2323,7 @@ export class PoolTemplate {
}

//for crvusd and stable-ng implementations
const isUseStoredRates = isMethodExist(curve.contracts[this.address].contract, 'stored_rates') && this.isPlain;
if (isUseStoredRates) {
if (findAbiFunction(curve.contracts[this.address].abi, 'stored_rates').length > 0 && this.isPlain) {
const _stored_rates: bigint[] = await curve.contracts[this.address].contract.stored_rates();
return _stored_rates.map((_r, i) => toBN(_r, 36 - this.wrappedDecimals[i]));
}
Expand Down
12 changes: 6 additions & 6 deletions src/pools/poolConstructor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
swapWrappedMixin,
swapWrappedRequiredMixin,
} from "./mixins/swapWrappedMixins.js";
import { getCountArgsOfMethodByContract } from "../utils.js";
import { getCountArgsOfMethodByAbi, findAbiSignature } from "../utils.js";


export const getPool = (poolId: string): PoolTemplate => {
Expand Down Expand Up @@ -59,7 +59,7 @@ export const getPool = (poolId: string): PoolTemplate => {
}
} else if (poolDummy.zap && poolId !== 'susd') {
Object.assign(Pool.prototype, depositZapMixin);
} else if (getCountArgsOfMethodByContract(curve.contracts[poolDummy.address].contract, 'add_liquidity') > 2) {
} else if (getCountArgsOfMethodByAbi(curve.contracts[poolDummy.address].abi, 'add_liquidity') > 2) {
Object.assign(Pool.prototype, depositLendingOrCryptoMixin);
} else {
Object.assign(Pool.prototype, depositPlainMixin);
Expand Down Expand Up @@ -92,7 +92,7 @@ export const getPool = (poolId: string): PoolTemplate => {
}
} else if (poolDummy.zap && poolId !== 'susd') {
Object.assign(Pool.prototype, withdrawZapMixin);
} else if (getCountArgsOfMethodByContract(curve.contracts[poolDummy.address].contract, 'remove_liquidity') > 2) {
} else if (getCountArgsOfMethodByAbi(curve.contracts[poolDummy.address].abi, 'remove_liquidity') > 2) {
Object.assign(Pool.prototype, withdrawLendingOrCryptoMixin);
} else {
Object.assign(Pool.prototype, withdrawPlainMixin);
Expand Down Expand Up @@ -151,7 +151,7 @@ export const getPool = (poolId: string): PoolTemplate => {
}
} else if (poolDummy.zap) { // including susd
Object.assign(Pool.prototype, withdrawOneCoinZapMixin);
} else if (getCountArgsOfMethodByContract(curve.contracts[poolDummy.address].contract, 'remove_liquidity_one_coin') > 3) {
} else if (getCountArgsOfMethodByAbi(curve.contracts[poolDummy.address].abi, 'remove_liquidity_one_coin') > 3) {
Object.assign(Pool.prototype, withdrawOneCoinLendingOrCryptoMixin);
} else {
Object.assign(Pool.prototype, withdrawOneCoinPlainMixin);
Expand All @@ -176,7 +176,7 @@ export const getPool = (poolId: string): PoolTemplate => {
}

// swap and swapEstimateGas
if ('exchange(uint256,uint256,uint256,uint256,bool)' in curve.contracts[poolDummy.address].contract &&
if (findAbiSignature(curve.contracts[poolDummy.address].abi, 'exchange', 'uint256,uint256,uint256,uint256,bool') &&
!(curve.chainId === 100 && poolDummy.id === "tricrypto")) { // tricrypto2 (eth), tricrypto (arbitrum), avaxcrypto (avalanche); 100 is xDAI
Object.assign(Pool.prototype, swapTricrypto2Mixin);
} else if (poolDummy.isMetaFactory && (getPool(poolDummy.basePool).isLending || getPool(poolDummy.basePool).isFake || poolDummy.isCrypto)) {
Expand All @@ -193,7 +193,7 @@ export const getPool = (poolId: string): PoolTemplate => {
if (!poolDummy.isPlain && !poolDummy.isFake) {
Object.assign(Pool.prototype, swapWrappedExpectedAndApproveMixin);
Object.assign(Pool.prototype, swapWrappedRequiredMixin);
if ('exchange(uint256,uint256,uint256,uint256,bool)' in curve.contracts[poolDummy.address].contract) { // tricrypto2 (eth), tricrypto (arbitrum)
if (findAbiSignature(curve.contracts[poolDummy.address].abi, 'exchange', 'uint256,uint256,uint256,uint256,bool')) { // tricrypto2 (eth), tricrypto (arbitrum)
Object.assign(Pool.prototype, swapWrappedTricrypto2Mixin);
} else {
Object.assign(Pool.prototype, swapWrappedMixin);
Expand Down
22 changes: 9 additions & 13 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import axios from 'axios';
import {Contract} from 'ethers';
import {Contract as MulticallContract} from "@curvefi/ethcall";
import type { Abi, AbiFunction } from "abitype";
import BigNumber from 'bignumber.js';
import {
IBasePoolShortItem,
Expand Down Expand Up @@ -634,6 +635,7 @@ export const getVolume = async (network: INetworkName | IChainId = curve.chainId

export const _setContracts = (address: string, abi: any): void => {
curve.contracts[address] = {
abi,
contract: new Contract(address, abi, curve.signer || curve.provider),
multicallContract: new MulticallContract(address, abi),
}
Expand Down Expand Up @@ -709,17 +711,13 @@ export const getCoinsData = async (...coins: string[] | string[][]): Promise<{na
export const hasDepositAndStake = (): boolean => curve.constants.ALIASES.deposit_and_stake !== curve.constants.ZERO_ADDRESS;
export const hasRouter = (): boolean => curve.constants.ALIASES.router !== curve.constants.ZERO_ADDRESS;

export const getCountArgsOfMethodByContract = (contract: Contract, methodName: string): number => {
const func = contract.interface.fragments.find((item: any) => item.name === methodName);
if(func) {
return func.inputs.length;
} else {
return -1;
}
}
export const findAbiFunction = (abi: Abi, methodName: string) =>
abi.filter((item) => item.type == 'function' && item.name === methodName) as AbiFunction[]

export const isMethodExist = (contract: Contract, methodName: string): boolean =>
contract.interface.fragments.find((item: any) => item.name === methodName) !== undefined
export const getCountArgsOfMethodByAbi = (abi: Abi, methodName: string): number => findAbiFunction(abi, methodName)[0]?.inputs.length ?? -1

export const findAbiSignature = (abi: Abi, methodName: string, signature: string) =>
findAbiFunction(abi, methodName).find((func) => func.inputs.map(i => `${i.type}`).join(',') == signature)

export const getPoolName = (name: string): string => {
const separatedName = name.split(": ")
Expand All @@ -730,9 +728,7 @@ export const getPoolName = (name: string): string => {
}
}

export const isStableNgPool = (name: string): boolean => {
return name.includes('factory-stable-ng')
}
export const isStableNgPool = (name: string): boolean => name.includes('factory-stable-ng')

export const assetTypeNameHandler = (assetTypeName: string): REFERENCE_ASSET => {
if (assetTypeName.toUpperCase() === 'UNKNOWN') {
Expand Down

0 comments on commit 346997a

Please sign in to comment.