From 62aeea8a32e59aa134b9d390d378ebc6a16923b9 Mon Sep 17 00:00:00 2001 From: William Poulin Date: Fri, 10 Mar 2023 20:49:23 -0500 Subject: [PATCH] fix(convex): Add stash wrapped tokens (#2409) --- .../abis/convex-stash-token-wrapped.json | 93 ++++++ .../ethers/ConvexStashTokenWrapped.ts | 283 ++++++++++++++++++ .../ConvexStashTokenWrapped__factory.ts | 203 +++++++++++++ .../contracts/ethers/factories/index.ts | 1 + src/apps/convex/contracts/ethers/index.ts | 2 + src/apps/convex/contracts/index.ts | 5 + ...onvex.stash-token-wrapped.token-fetcher.ts | 42 +++ src/apps/convex/ethereum/index.ts | 2 + 8 files changed, 631 insertions(+) create mode 100644 src/apps/convex/contracts/abis/convex-stash-token-wrapped.json create mode 100644 src/apps/convex/contracts/ethers/ConvexStashTokenWrapped.ts create mode 100644 src/apps/convex/contracts/ethers/factories/ConvexStashTokenWrapped__factory.ts create mode 100644 src/apps/convex/ethereum/convex.stash-token-wrapped.token-fetcher.ts diff --git a/src/apps/convex/contracts/abis/convex-stash-token-wrapped.json b/src/apps/convex/contracts/abis/convex-stash-token-wrapped.json new file mode 100644 index 000000000..67a0e0f09 --- /dev/null +++ b/src/apps/convex/contracts/abis/convex-stash-token-wrapped.json @@ -0,0 +1,93 @@ +[ + { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [{ "internalType": "address", "name": "_account", "type": "address" }], + "name": "balanceOf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "booster", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "address", "name": "_rewardpool", "type": "address" } + ], + "name": "init", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isInvalid", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardPool", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "bool", "name": "_isInvalid", "type": "bool" }], + "name": "setInvalid", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_recipient", "type": "address" }, + { "internalType": "uint256", "name": "_amount", "type": "uint256" } + ], + "name": "transfer", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/apps/convex/contracts/ethers/ConvexStashTokenWrapped.ts b/src/apps/convex/contracts/ethers/ConvexStashTokenWrapped.ts new file mode 100644 index 000000000..90f916da2 --- /dev/null +++ b/src/apps/convex/contracts/ethers/ConvexStashTokenWrapped.ts @@ -0,0 +1,283 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { + BaseContract, + BigNumber, + BigNumberish, + BytesLike, + CallOverrides, + ContractTransaction, + Overrides, + PopulatedTransaction, + Signer, + utils, +} from 'ethers'; +import type { FunctionFragment, Result } from '@ethersproject/abi'; +import type { Listener, Provider } from '@ethersproject/providers'; +import type { TypedEventFilter, TypedEvent, TypedListener, OnEvent, PromiseOrValue } from './common'; + +export interface ConvexStashTokenWrappedInterface extends utils.Interface { + functions: { + 'balanceOf(address)': FunctionFragment; + 'booster()': FunctionFragment; + 'decimals()': FunctionFragment; + 'init(address,address)': FunctionFragment; + 'isInvalid()': FunctionFragment; + 'name()': FunctionFragment; + 'rewardPool()': FunctionFragment; + 'setInvalid(bool)': FunctionFragment; + 'symbol()': FunctionFragment; + 'token()': FunctionFragment; + 'totalSupply()': FunctionFragment; + 'transfer(address,uint256)': FunctionFragment; + }; + + getFunction( + nameOrSignatureOrTopic: + | 'balanceOf' + | 'booster' + | 'decimals' + | 'init' + | 'isInvalid' + | 'name' + | 'rewardPool' + | 'setInvalid' + | 'symbol' + | 'token' + | 'totalSupply' + | 'transfer', + ): FunctionFragment; + + encodeFunctionData(functionFragment: 'balanceOf', values: [PromiseOrValue]): string; + encodeFunctionData(functionFragment: 'booster', values?: undefined): string; + encodeFunctionData(functionFragment: 'decimals', values?: undefined): string; + encodeFunctionData(functionFragment: 'init', values: [PromiseOrValue, PromiseOrValue]): string; + encodeFunctionData(functionFragment: 'isInvalid', values?: undefined): string; + encodeFunctionData(functionFragment: 'name', values?: undefined): string; + encodeFunctionData(functionFragment: 'rewardPool', values?: undefined): string; + encodeFunctionData(functionFragment: 'setInvalid', values: [PromiseOrValue]): string; + encodeFunctionData(functionFragment: 'symbol', values?: undefined): string; + encodeFunctionData(functionFragment: 'token', values?: undefined): string; + encodeFunctionData(functionFragment: 'totalSupply', values?: undefined): string; + encodeFunctionData( + functionFragment: 'transfer', + values: [PromiseOrValue, PromiseOrValue], + ): string; + + decodeFunctionResult(functionFragment: 'balanceOf', data: BytesLike): Result; + decodeFunctionResult(functionFragment: 'booster', data: BytesLike): Result; + decodeFunctionResult(functionFragment: 'decimals', data: BytesLike): Result; + decodeFunctionResult(functionFragment: 'init', data: BytesLike): Result; + decodeFunctionResult(functionFragment: 'isInvalid', data: BytesLike): Result; + decodeFunctionResult(functionFragment: 'name', data: BytesLike): Result; + decodeFunctionResult(functionFragment: 'rewardPool', data: BytesLike): Result; + decodeFunctionResult(functionFragment: 'setInvalid', data: BytesLike): Result; + decodeFunctionResult(functionFragment: 'symbol', data: BytesLike): Result; + decodeFunctionResult(functionFragment: 'token', data: BytesLike): Result; + decodeFunctionResult(functionFragment: 'totalSupply', data: BytesLike): Result; + decodeFunctionResult(functionFragment: 'transfer', data: BytesLike): Result; + + events: {}; +} + +export interface ConvexStashTokenWrapped extends BaseContract { + connect(signerOrProvider: Signer | Provider | string): this; + attach(addressOrName: string): this; + deployed(): Promise; + + interface: ConvexStashTokenWrappedInterface; + + queryFilter( + event: TypedEventFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined, + ): Promise>; + + listeners(eventFilter?: TypedEventFilter): Array>; + listeners(eventName?: string): Array; + removeAllListeners(eventFilter: TypedEventFilter): this; + removeAllListeners(eventName?: string): this; + off: OnEvent; + on: OnEvent; + once: OnEvent; + removeListener: OnEvent; + + functions: { + balanceOf(_account: PromiseOrValue, overrides?: CallOverrides): Promise<[BigNumber]>; + + booster(overrides?: CallOverrides): Promise<[string]>; + + decimals(overrides?: CallOverrides): Promise<[number]>; + + init( + _token: PromiseOrValue, + _rewardpool: PromiseOrValue, + overrides?: Overrides & { from?: PromiseOrValue }, + ): Promise; + + isInvalid(overrides?: CallOverrides): Promise<[boolean]>; + + name(overrides?: CallOverrides): Promise<[string]>; + + rewardPool(overrides?: CallOverrides): Promise<[string]>; + + setInvalid( + _isInvalid: PromiseOrValue, + overrides?: Overrides & { from?: PromiseOrValue }, + ): Promise; + + symbol(overrides?: CallOverrides): Promise<[string]>; + + token(overrides?: CallOverrides): Promise<[string]>; + + totalSupply(overrides?: CallOverrides): Promise<[BigNumber]>; + + transfer( + _recipient: PromiseOrValue, + _amount: PromiseOrValue, + overrides?: Overrides & { from?: PromiseOrValue }, + ): Promise; + }; + + balanceOf(_account: PromiseOrValue, overrides?: CallOverrides): Promise; + + booster(overrides?: CallOverrides): Promise; + + decimals(overrides?: CallOverrides): Promise; + + init( + _token: PromiseOrValue, + _rewardpool: PromiseOrValue, + overrides?: Overrides & { from?: PromiseOrValue }, + ): Promise; + + isInvalid(overrides?: CallOverrides): Promise; + + name(overrides?: CallOverrides): Promise; + + rewardPool(overrides?: CallOverrides): Promise; + + setInvalid( + _isInvalid: PromiseOrValue, + overrides?: Overrides & { from?: PromiseOrValue }, + ): Promise; + + symbol(overrides?: CallOverrides): Promise; + + token(overrides?: CallOverrides): Promise; + + totalSupply(overrides?: CallOverrides): Promise; + + transfer( + _recipient: PromiseOrValue, + _amount: PromiseOrValue, + overrides?: Overrides & { from?: PromiseOrValue }, + ): Promise; + + callStatic: { + balanceOf(_account: PromiseOrValue, overrides?: CallOverrides): Promise; + + booster(overrides?: CallOverrides): Promise; + + decimals(overrides?: CallOverrides): Promise; + + init(_token: PromiseOrValue, _rewardpool: PromiseOrValue, overrides?: CallOverrides): Promise; + + isInvalid(overrides?: CallOverrides): Promise; + + name(overrides?: CallOverrides): Promise; + + rewardPool(overrides?: CallOverrides): Promise; + + setInvalid(_isInvalid: PromiseOrValue, overrides?: CallOverrides): Promise; + + symbol(overrides?: CallOverrides): Promise; + + token(overrides?: CallOverrides): Promise; + + totalSupply(overrides?: CallOverrides): Promise; + + transfer( + _recipient: PromiseOrValue, + _amount: PromiseOrValue, + overrides?: CallOverrides, + ): Promise; + }; + + filters: {}; + + estimateGas: { + balanceOf(_account: PromiseOrValue, overrides?: CallOverrides): Promise; + + booster(overrides?: CallOverrides): Promise; + + decimals(overrides?: CallOverrides): Promise; + + init( + _token: PromiseOrValue, + _rewardpool: PromiseOrValue, + overrides?: Overrides & { from?: PromiseOrValue }, + ): Promise; + + isInvalid(overrides?: CallOverrides): Promise; + + name(overrides?: CallOverrides): Promise; + + rewardPool(overrides?: CallOverrides): Promise; + + setInvalid( + _isInvalid: PromiseOrValue, + overrides?: Overrides & { from?: PromiseOrValue }, + ): Promise; + + symbol(overrides?: CallOverrides): Promise; + + token(overrides?: CallOverrides): Promise; + + totalSupply(overrides?: CallOverrides): Promise; + + transfer( + _recipient: PromiseOrValue, + _amount: PromiseOrValue, + overrides?: Overrides & { from?: PromiseOrValue }, + ): Promise; + }; + + populateTransaction: { + balanceOf(_account: PromiseOrValue, overrides?: CallOverrides): Promise; + + booster(overrides?: CallOverrides): Promise; + + decimals(overrides?: CallOverrides): Promise; + + init( + _token: PromiseOrValue, + _rewardpool: PromiseOrValue, + overrides?: Overrides & { from?: PromiseOrValue }, + ): Promise; + + isInvalid(overrides?: CallOverrides): Promise; + + name(overrides?: CallOverrides): Promise; + + rewardPool(overrides?: CallOverrides): Promise; + + setInvalid( + _isInvalid: PromiseOrValue, + overrides?: Overrides & { from?: PromiseOrValue }, + ): Promise; + + symbol(overrides?: CallOverrides): Promise; + + token(overrides?: CallOverrides): Promise; + + totalSupply(overrides?: CallOverrides): Promise; + + transfer( + _recipient: PromiseOrValue, + _amount: PromiseOrValue, + overrides?: Overrides & { from?: PromiseOrValue }, + ): Promise; + }; +} diff --git a/src/apps/convex/contracts/ethers/factories/ConvexStashTokenWrapped__factory.ts b/src/apps/convex/contracts/ethers/factories/ConvexStashTokenWrapped__factory.ts new file mode 100644 index 000000000..2c1ac2d32 --- /dev/null +++ b/src/apps/convex/contracts/ethers/factories/ConvexStashTokenWrapped__factory.ts @@ -0,0 +1,203 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ + +import { Contract, Signer, utils } from 'ethers'; +import type { Provider } from '@ethersproject/providers'; +import type { ConvexStashTokenWrapped, ConvexStashTokenWrappedInterface } from '../ConvexStashTokenWrapped'; + +const _abi = [ + { + inputs: [], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + inputs: [ + { + internalType: 'address', + name: '_account', + type: 'address', + }, + ], + name: 'balanceOf', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'booster', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'decimals', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_token', + type: 'address', + }, + { + internalType: 'address', + name: '_rewardpool', + type: 'address', + }, + ], + name: 'init', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'isInvalid', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'name', + outputs: [ + { + internalType: 'string', + name: '', + type: 'string', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'rewardPool', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bool', + name: '_isInvalid', + type: 'bool', + }, + ], + name: 'setInvalid', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'symbol', + outputs: [ + { + internalType: 'string', + name: '', + type: 'string', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'token', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalSupply', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_recipient', + type: 'address', + }, + { + internalType: 'uint256', + name: '_amount', + type: 'uint256', + }, + ], + name: 'transfer', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, +]; + +export class ConvexStashTokenWrapped__factory { + static readonly abi = _abi; + static createInterface(): ConvexStashTokenWrappedInterface { + return new utils.Interface(_abi) as ConvexStashTokenWrappedInterface; + } + static connect(address: string, signerOrProvider: Signer | Provider): ConvexStashTokenWrapped { + return new Contract(address, _abi, signerOrProvider) as ConvexStashTokenWrapped; + } +} diff --git a/src/apps/convex/contracts/ethers/factories/index.ts b/src/apps/convex/contracts/ethers/factories/index.ts index 101596b00..3952d01a2 100644 --- a/src/apps/convex/contracts/ethers/factories/index.ts +++ b/src/apps/convex/contracts/ethers/factories/index.ts @@ -11,5 +11,6 @@ export { ConvexCvxStaking__factory } from './ConvexCvxStaking__factory'; export { ConvexDepositToken__factory } from './ConvexDepositToken__factory'; export { ConvexDepositor__factory } from './ConvexDepositor__factory'; export { ConvexSingleStakingRewards__factory } from './ConvexSingleStakingRewards__factory'; +export { ConvexStashTokenWrapped__factory } from './ConvexStashTokenWrapped__factory'; export { ConvexVirtualBalanceRewardPool__factory } from './ConvexVirtualBalanceRewardPool__factory'; export { ConvexVotingEscrow__factory } from './ConvexVotingEscrow__factory'; diff --git a/src/apps/convex/contracts/ethers/index.ts b/src/apps/convex/contracts/ethers/index.ts index 0320f4159..ee732b7a0 100644 --- a/src/apps/convex/contracts/ethers/index.ts +++ b/src/apps/convex/contracts/ethers/index.ts @@ -11,6 +11,7 @@ export type { ConvexCvxStaking } from './ConvexCvxStaking'; export type { ConvexDepositToken } from './ConvexDepositToken'; export type { ConvexDepositor } from './ConvexDepositor'; export type { ConvexSingleStakingRewards } from './ConvexSingleStakingRewards'; +export type { ConvexStashTokenWrapped } from './ConvexStashTokenWrapped'; export type { ConvexVirtualBalanceRewardPool } from './ConvexVirtualBalanceRewardPool'; export type { ConvexVotingEscrow } from './ConvexVotingEscrow'; export * as factories from './factories'; @@ -24,5 +25,6 @@ export { ConvexCvxStaking__factory } from './factories/ConvexCvxStaking__factory export { ConvexDepositToken__factory } from './factories/ConvexDepositToken__factory'; export { ConvexDepositor__factory } from './factories/ConvexDepositor__factory'; export { ConvexSingleStakingRewards__factory } from './factories/ConvexSingleStakingRewards__factory'; +export { ConvexStashTokenWrapped__factory } from './factories/ConvexStashTokenWrapped__factory'; export { ConvexVirtualBalanceRewardPool__factory } from './factories/ConvexVirtualBalanceRewardPool__factory'; export { ConvexVotingEscrow__factory } from './factories/ConvexVotingEscrow__factory'; diff --git a/src/apps/convex/contracts/index.ts b/src/apps/convex/contracts/index.ts index 8ec51daa2..26c1d1ee9 100644 --- a/src/apps/convex/contracts/index.ts +++ b/src/apps/convex/contracts/index.ts @@ -15,6 +15,7 @@ import { ConvexDepositToken__factory, ConvexDepositor__factory, ConvexSingleStakingRewards__factory, + ConvexStashTokenWrapped__factory, ConvexVirtualBalanceRewardPool__factory, ConvexVotingEscrow__factory, } from './ethers'; @@ -58,6 +59,9 @@ export class ConvexContractFactory extends ContractFactory { convexSingleStakingRewards({ address, network }: ContractOpts) { return ConvexSingleStakingRewards__factory.connect(address, this.appToolkit.getNetworkProvider(network)); } + convexStashTokenWrapped({ address, network }: ContractOpts) { + return ConvexStashTokenWrapped__factory.connect(address, this.appToolkit.getNetworkProvider(network)); + } convexVirtualBalanceRewardPool({ address, network }: ContractOpts) { return ConvexVirtualBalanceRewardPool__factory.connect(address, this.appToolkit.getNetworkProvider(network)); } @@ -76,5 +80,6 @@ export type { ConvexCvxStaking } from './ethers'; export type { ConvexDepositToken } from './ethers'; export type { ConvexDepositor } from './ethers'; export type { ConvexSingleStakingRewards } from './ethers'; +export type { ConvexStashTokenWrapped } from './ethers'; export type { ConvexVirtualBalanceRewardPool } from './ethers'; export type { ConvexVotingEscrow } from './ethers'; diff --git a/src/apps/convex/ethereum/convex.stash-token-wrapped.token-fetcher.ts b/src/apps/convex/ethereum/convex.stash-token-wrapped.token-fetcher.ts new file mode 100644 index 000000000..0099e22d2 --- /dev/null +++ b/src/apps/convex/ethereum/convex.stash-token-wrapped.token-fetcher.ts @@ -0,0 +1,42 @@ +import { Inject } from '@nestjs/common'; + +import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; +import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; +import { AppTokenTemplatePositionFetcher } from '~position/template/app-token.template.position-fetcher'; +import { GetUnderlyingTokensParams } from '~position/template/app-token.template.types'; + +import { ConvexContractFactory, ConvexStashTokenWrapped } from '../contracts'; + +@PositionTemplate() +export class EthereumConvexStashTokenWrappedTokenFetcher extends AppTokenTemplatePositionFetcher { + groupLabel = 'Stash Token Wrapped'; + + constructor( + @Inject(APP_TOOLKIT) protected readonly appToolkit: IAppToolkit, + @Inject(ConvexContractFactory) protected readonly contractFactory: ConvexContractFactory, + ) { + super(appToolkit); + } + + getContract(address: string): ConvexStashTokenWrapped { + return this.contractFactory.convexStashTokenWrapped({ address, network: this.network }); + } + + async getAddresses(): Promise { + return [ + '0xf132a783d8567c11d3df3e4ef890786affc16402', + '0xe657aa15ec2eec10facbdc68d388895dd700a0d5', + '0x49b559563ab764381554feee9951e9ec899c5952', + '0xad2074172e212dcf82ec94558209c88156764a93', + '0xbb554e5e8ec27a2b8f6d5cd269fec43e9637018b', + ]; + } + + async getUnderlyingTokenDefinitions({ contract }: GetUnderlyingTokensParams) { + return [{ address: await contract.token(), network: this.network }]; + } + + async getPricePerShare() { + return [1]; + } +} diff --git a/src/apps/convex/ethereum/index.ts b/src/apps/convex/ethereum/index.ts index f15892b12..c5986786e 100644 --- a/src/apps/convex/ethereum/index.ts +++ b/src/apps/convex/ethereum/index.ts @@ -6,6 +6,7 @@ import { EthereumConvexCvxStakingContractPositionFetcher } from './convex.cvx-st import { EthereumConvexDepositTokenFetcher } from './convex.deposit.token-fetcher'; import { EthereumConvexDepositorContractPositionFetcher } from './convex.depositor.contract-position-fetcher'; import { EthereumConvexLpFarmContractPositionFetcher } from './convex.lp-farm.contract-position-fetcher'; +import { EthereumConvexStashTokenWrappedTokenFetcher } from './convex.stash-token-wrapped.token-fetcher'; import { EthereumConvexVotingEscrowContractPositionFetcher } from './convex.voting-escrow.contract-position-fetcher'; export const CONVEX_ETHEREUM_PROVIDERS = [ @@ -18,4 +19,5 @@ export const CONVEX_ETHEREUM_PROVIDERS = [ EthereumConvexLpFarmContractPositionFetcher, EthereumConvexVotingEscrowContractPositionFetcher, EthereumConvexCvxCrvStakingWrappedContractPositionFetcher, + EthereumConvexStashTokenWrappedTokenFetcher, ];