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

Update SOR buffers to use unwrapRate from erc4626 tokens #1353

Merged
merged 9 commits into from
Jan 3, 2025
5 changes: 5 additions & 0 deletions .changeset/nasty-adults-applaud.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'backend': minor
---

Update SOR buffers to use unwrapRate from erc4626 tokens
10 changes: 10 additions & 0 deletions apps/worker/job-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
StakedSonicController,
} from '../../modules/controllers';
import { updateVolumeAndFees } from '../../modules/actions/pool/update-volume-and-fees';
import { TokenController } from '../../modules/controllers/token-controller';

const runningJobs: Set<string> = new Set();

Expand Down Expand Up @@ -411,6 +412,15 @@ const setupJobHandlers = async (name: string, chainId: string, res: any, next: N
case 'sync-erc4626-data':
await runIfNotAlreadyRunning(name, chainId, () => ContentController().syncErc4626Data(), res, next);
break;
case 'sync-erc4626-unwrap-rate':
await runIfNotAlreadyRunning(
name,
chainId,
() => TokenController().syncErc4626UnwrapRates(chain),
res,
next,
);
break;
default:
res.sendStatus(400);
// throw new Error(`Unhandled job type ${name}`);
Expand Down
2 changes: 1 addition & 1 deletion modules/actions/pool/v3/upsert-pools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { prisma } from '../../../../prisma/prisma-client';
import { tokensTransformer } from '../../../sources/transformers/tokens-transformer';
import { V3JoinedSubgraphPool } from '../../../sources/subgraphs';
import { enrichPoolUpsertsUsd } from '../../../sources/enrichers/pool-upserts-usd';
import type { VaultClient } from '../../../sources/contracts';
import { type VaultClient } from '../../../sources/contracts';
import { poolUpsertTransformerV3 } from '../../../sources/transformers/pool-upsert-transformer-v3';
import { applyOnchainDataUpdateV3 } from '../../../sources/enrichers/apply-onchain-data';
import { fetchErc4626AndUnderlyingTokenData } from '../../../sources/contracts/fetch-erc4626-token-data';
Expand Down
4 changes: 2 additions & 2 deletions modules/actions/token/sync-erc4626-tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ export const syncErc4626Tokens = async (viemClient: ViemClient, chain: Chain) =>
},
});

const erc4626AndUnderlying = await fetchErc4626AndUnderlyingTokenData(allTokens, viemClient);
const enrichedTokensWithErc4626Data = await fetchErc4626AndUnderlyingTokenData(allTokens, viemClient);

for (const token of erc4626AndUnderlying) {
for (const token of enrichedTokensWithErc4626Data) {
await prisma.prismaToken.upsert({
where: {
address_chain: {
Expand Down
52 changes: 52 additions & 0 deletions modules/actions/token/sync-erc4626-unwrap-rates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Chain } from '@prisma/client';
import { prisma } from '../../../prisma/prisma-client';
import { fetchUnwrapRates } from '../../sources/contracts/v3/fetch-unwrap-rates';

/**
* Sync erc4626 unwrap rates between wrapped/underlying
*/
export const syncErc4626UnwrapRates = async (chain: Chain) => {
const erc4626Tokens = await prisma.prismaToken.findMany({
where: {
chain,
address: { not: '0x0000000000000000000000000000000000000000' },
types: {
some: {
type: 'ERC4626',
},
},
},
});

const underlyingTokens = await prisma.prismaToken.findMany({
where: {
chain,
address: {
in: erc4626Tokens.map((token) => token.underlyingTokenAddress).filter((address) => address !== null),
},
},
});

const underlyingTokenMap = Object.fromEntries(underlyingTokens.map((token) => [token.address, token]));

const unwrapRates = await fetchUnwrapRates(erc4626Tokens, underlyingTokenMap);

for (const token of erc4626Tokens) {
await prisma.prismaToken.upsert({
where: {
address_chain: {
address: token.address,
chain: chain,
},
},
create: {
...token,
unwrapRate: unwrapRates[token.address],
},
update: {
...token,
unwrapRate: unwrapRates[token.address],
},
});
}
};
4 changes: 4 additions & 0 deletions modules/controllers/token-controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Chain } from '@prisma/client';
import { syncErc4626Tokens } from '../actions/token/sync-erc4626-tokens';
import { syncErc4626UnwrapRates } from '../actions/token/sync-erc4626-unwrap-rates';
import { getViemClient } from '../sources/viem-client';

export function TokenController(tracer?: any) {
Expand All @@ -10,5 +11,8 @@ export function TokenController(tracer?: any) {
const viemClient = getViemClient(chain);
await syncErc4626Tokens(viemClient, chain);
},
async syncErc4626UnwrapRates(chain: Chain) {
await syncErc4626UnwrapRates(chain);
},
};
}
4 changes: 4 additions & 0 deletions modules/network/arbitrum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,5 +144,9 @@ export const arbitrumNetworkConfig: NetworkConfig = {
name: 'update-cow-amm-volume-and-fees',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(60, 'minutes') : every(20, 'minutes'),
},
{
name: 'sync-erc4626-unwrap-rate',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(60, 'minutes') : every(20, 'minutes'),
},
],
};
4 changes: 4 additions & 0 deletions modules/network/avalanche.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,5 +128,9 @@ export const avalancheNetworkConfig: NetworkConfig = {
name: 'sync-swaps-v2',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(10, 'minutes') : every(1, 'minutes'),
},
{
name: 'sync-erc4626-unwrap-rate',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(60, 'minutes') : every(20, 'minutes'),
},
],
};
4 changes: 4 additions & 0 deletions modules/network/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,5 +144,9 @@ export const baseNetworkConfig: NetworkConfig = {
name: 'update-cow-amm-volume-and-fees',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(60, 'minutes') : every(20, 'minutes'),
},
{
name: 'sync-erc4626-unwrap-rate',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(60, 'minutes') : every(20, 'minutes'),
},
],
};
4 changes: 4 additions & 0 deletions modules/network/fraxtal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,9 @@ export const fraxtalNetworkConfig: NetworkConfig = {
name: 'sync-swaps-v2',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(10, 'minutes') : every(1, 'minutes'),
},
{
name: 'sync-erc4626-unwrap-rate',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(60, 'minutes') : every(20, 'minutes'),
},
],
};
4 changes: 4 additions & 0 deletions modules/network/gnosis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,9 @@ export const gnosisNetworkConfig: NetworkConfig = {
name: 'sync-hook-data',
interval: every(1, 'hours'),
},
{
name: 'sync-erc4626-unwrap-rate',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(60, 'minutes') : every(20, 'minutes'),
},
],
};
4 changes: 4 additions & 0 deletions modules/network/mainnet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,5 +230,9 @@ export const mainnetNetworkConfig: NetworkConfig = {
name: 'sync-hook-data',
interval: every(1, 'hours'),
},
{
name: 'sync-erc4626-unwrap-rate',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(60, 'minutes') : every(20, 'minutes'),
},
],
};
4 changes: 4 additions & 0 deletions modules/network/mode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,5 +122,9 @@ export const modeNetworkConfig: NetworkConfig = {
name: 'sync-swaps-v2',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(10, 'minutes') : every(1, 'minutes'),
},
{
name: 'sync-erc4626-unwrap-rate',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(60, 'minutes') : every(20, 'minutes'),
},
],
};
4 changes: 4 additions & 0 deletions modules/network/optimism.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,5 +127,9 @@ export const optimismNetworkConfig: NetworkConfig = {
name: 'sync-swaps-v2',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(10, 'minutes') : every(1, 'minutes'),
},
{
name: 'sync-erc4626-unwrap-rate',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(60, 'minutes') : every(20, 'minutes'),
},
],
};
4 changes: 4 additions & 0 deletions modules/network/polygon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,5 +127,9 @@ export const polygonNetworkConfig: NetworkConfig = {
name: 'sync-swaps-v2',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(10, 'minutes') : every(1, 'minutes'),
},
{
name: 'sync-erc4626-unwrap-rate',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(60, 'minutes') : every(20, 'minutes'),
},
],
};
4 changes: 4 additions & 0 deletions modules/network/sepolia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,5 +168,9 @@ export const sepoliaNetworkConfig: NetworkConfig = {
name: 'update-cow-amm-volume-and-fees',
interval: every(20, 'minutes'),
},
{
name: 'sync-erc4626-unwrap-rate',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(60, 'minutes') : every(20, 'minutes'),
},
],
};
4 changes: 4 additions & 0 deletions modules/network/sonic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,5 +137,9 @@ export const sonicNetworkConfig: NetworkConfig = {
name: 'sync-sts-staking-snapshots',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(20, 'minutes') : every(10, 'minutes'),
},
{
name: 'sync-erc4626-unwrap-rate',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(60, 'minutes') : every(20, 'minutes'),
},
],
};
4 changes: 4 additions & 0 deletions modules/network/zkevm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,9 @@ export const zkevmNetworkConfig: NetworkConfig = {
name: 'sync-swaps-v2',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(10, 'minutes') : every(1, 'minutes'),
},
{
name: 'sync-erc4626-unwrap-rate',
interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(60, 'minutes') : every(20, 'minutes'),
},
],
};
18 changes: 10 additions & 8 deletions modules/sor/sor-debug.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
import { Chain } from '@prisma/client';
import { initRequestScopedContext, setRequestScopedContextValue } from '../context/request-scoped-context';
import { chainIdToChain } from '../network/chain-id-to-chain';
import { PoolController } from '../controllers/pool-controller'; // Add this import statement
import { PoolController } from '../controllers/pool-controller';
import { TokenController } from '../controllers/token-controller';
import { sorService } from './sor.service';

describe('sor debugging', () => {
Expand Down Expand Up @@ -36,24 +37,25 @@ describe('sor debugging', () => {
expect(parseFloat(swaps.returnAmount)).toBeGreaterThan(0);
}, 5000000);

it('sor v3 mainnet wusdl -> csusdl', async () => {
const chain = Chain.MAINNET;
it.only('sor v3 mainnet wstETH -> waGnowstETH', async () => {
const chain = Chain.GNOSIS;

const chainId = Object.keys(chainIdToChain).find((key) => chainIdToChain[key] === chain) as string;
initRequestScopedContext();
setRequestScopedContextValue('chainId', chainId);
//only do once before starting to debug
await PoolController().reloadPoolsV3(chain);
await PoolController().updateLiquidityValuesForActivePools(chain);
await TokenController().syncErc4626Tokens(chain);
await TokenController().syncErc4626UnwrapRates(chain);

const swaps = await sorService.getSorSwapPaths({
chain,
tokenIn: '0x7751e2f4b8ae93ef6b79d86419d42fe3295a4559', // wusdl
tokenOut: '0xbeefc01767ed5086f35decb6c00e6c12bc7476c1', // csusdl
tokenIn: '0x773cda0cade2a3d86e6d4e30699d40bb95174ff2', // wagnowsteth
tokenOut: '0x6C76971f98945AE98dD7d4DFcA8711ebea946eA6', // wsteth
swapType: 'EXACT_IN',
swapAmount: '10',
swapAmount: '1',
useProtocolVersion: 3,
// poolIds: ['0xbeefc01767ed5086f35decb6c00e6c12bc7476c1'], // buffer
poolIds: ['0x272d6be442e30d7c87390edeb9b96f1e84cecd8d'], // boosted
});

console.log(swaps.returnAmount);
Expand Down
11 changes: 10 additions & 1 deletion modules/sor/sorV2/lib/poolsV2/erc4626PoolToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,20 @@ import { BasePoolToken } from './basePoolToken';

export class Erc4626PoolToken extends BasePoolToken {
public readonly rate: bigint;
public readonly unwrapRate: bigint;
public readonly underlyingTokenAddress: string;

public constructor(token: Token, amount: BigintIsh, index: number, rate: bigint, underlyingTokenAddress: string) {
public constructor(
token: Token,
amount: BigintIsh,
index: number,
rate: bigint,
unwrapRate: bigint,
underlyingTokenAddress: string,
) {
super(token, amount, index);
this.rate = rate;
this.unwrapRate = unwrapRate;
this.underlyingTokenAddress = underlyingTokenAddress;
}

Expand Down
2 changes: 1 addition & 1 deletion modules/sor/sorV2/lib/poolsV3/buffer/bufferPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class BufferPool implements BasePoolV3 {
erc4626Token.token.address,
erc4626Token.token.address,
erc4626Token.token.chainId,
erc4626Token.rate,
erc4626Token.unwrapRate,
mainToken,
underlyingToken,
);
Expand Down
1 change: 1 addition & 0 deletions modules/sor/sorV2/lib/poolsV3/stable/stablePool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export class StablePool implements BasePoolV3 {
tokenAmount.amount,
poolToken.index,
parseEther(poolToken.priceRate),
parseEther(poolToken.token.unwrapRate),
poolToken.token.underlyingTokenAddress,
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ export class WeightedErc4626PoolToken extends Erc4626PoolToken {
amount: BigintIsh,
index: number,
rate: bigint,
unwrapRate: bigint,
underlyingTokenAddress: string,
weight: BigintIsh,
) {
super(token, amount, index, rate, underlyingTokenAddress);
super(token, amount, index, rate, unwrapRate, underlyingTokenAddress);
this.weight = BigInt(weight);
}
}
1 change: 1 addition & 0 deletions modules/sor/sorV2/lib/poolsV3/weighted/weightedPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export class WeightedPoolV3 implements BasePoolV3 {
tokenAmount.amount,
poolToken.index,
parseEther(poolToken.priceRate),
parseEther(poolToken.token.unwrapRate),
poolToken.token.underlyingTokenAddress,
parseEther(poolToken.weight),
),
Expand Down
2 changes: 1 addition & 1 deletion modules/sources/contracts/fetch-erc4626-token-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export async function fetchErc4626AndUnderlyingTokenData(
name: token.name,
symbol: token.symbol,
chain: token.chain,
underlyingTokenAddress: underlyingTokenAddress,
underlyingTokenAddress,
};

if (underlyingTokenAddress && !tokenData[underlyingTokenAddress]) {
Expand Down
7 changes: 3 additions & 4 deletions modules/sources/contracts/v3/fetch-pool-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ type PoolTokenRates = [
AbiParameterToPrimitiveType<ExtractAbiFunction<typeof VaultV3Abi, 'getPoolTokenRates'>['outputs'][0]>, // decimalScalingFactors
AbiParameterToPrimitiveType<ExtractAbiFunction<typeof VaultV3Abi, 'getPoolTokenRates'>['outputs'][1]>, // tokenRates
];
export interface OnchainDataV3 {

export interface PoolDataV3 {
totalSupply: bigint;
swapFee: bigint;
aggregateSwapFee?: bigint;
Expand All @@ -28,7 +29,6 @@ export interface OnchainDataV3 {
balance: bigint;
rateProvider: string;
rate: bigint;
isErc4626: boolean;
scalingFactor: bigint;
}[];
}
Expand All @@ -38,7 +38,7 @@ export async function fetchPoolData(
pools: string[],
client: ViemClient,
blockNumber?: bigint,
): Promise<{ [address: string]: OnchainDataV3 }> {
): Promise<{ [address: string]: PoolDataV3 }> {
const contracts = pools
.map((pool) => [
{
Expand Down Expand Up @@ -102,7 +102,6 @@ export async function fetchPoolData(
paysYieldFees: poolTokenInfo[1][i].paysYieldFees,
rateProvider: poolTokenInfo[1][i].rateProvider,
rate: poolTokenRates ? poolTokenRates[1][i] : 1000000000000000000n,
isErc4626: false, // will be added later in the process
scalingFactor: poolTokenRates ? poolTokenRates[0][i] : 1000000000000000000n,
})),
},
Expand Down
Loading
Loading