From a7ab401fb16e0408ed8b1078b45e9d125d91a9f8 Mon Sep 17 00:00:00 2001 From: gs8nrv <55771972+GuillaumeNervoXS@users.noreply.github.com> Date: Wed, 13 Sep 2023 18:29:04 +0200 Subject: [PATCH] add logic whietlist (but can't check) + add/remove collat + adjust reserves --- .../angle-transmuter-e2e.test.ts | 10 +- .../angle-transmuter/angle-transmuter-pool.ts | 6 +- src/dex/angle-transmuter/angle-transmuter.ts | 2 +- src/dex/angle-transmuter/transmuter.ts | 118 ++++++++++++++++-- src/dex/angle-transmuter/types.ts | 20 +-- 5 files changed, 124 insertions(+), 32 deletions(-) diff --git a/src/dex/angle-transmuter/angle-transmuter-e2e.test.ts b/src/dex/angle-transmuter/angle-transmuter-e2e.test.ts index 62c2caec1..f893c43d8 100644 --- a/src/dex/angle-transmuter/angle-transmuter-e2e.test.ts +++ b/src/dex/angle-transmuter/angle-transmuter-e2e.test.ts @@ -70,16 +70,8 @@ function testForNetwork( // TODO: Add any direct swap contractMethod name if it exists const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - ], - ], + [SwapSide.SELL, [ContractMethod.simpleSwap]], // TODO: If buy is not supported remove the buy contract methods - // [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], [SwapSide.BUY, [ContractMethod.simpleBuy]], ]); diff --git a/src/dex/angle-transmuter/angle-transmuter-pool.ts b/src/dex/angle-transmuter/angle-transmuter-pool.ts index c8ba69729..886c63e56 100644 --- a/src/dex/angle-transmuter/angle-transmuter-pool.ts +++ b/src/dex/angle-transmuter/angle-transmuter-pool.ts @@ -448,8 +448,7 @@ export class AngleTransmuterEventPool extends ComposedEventSubscriber //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ _readMint(config: PoolConfig, state: PoolState, collateral: Address): number { - const configOracle = - state.transmuter.collaterals[collateral].oracles.config; + const configOracle = state.transmuter.collaterals[collateral].config; if (configOracle.oracleType == OracleReadType.EXTERNAL) { return 1; } else { @@ -505,8 +504,7 @@ export class AngleTransmuterEventPool extends ComposedEventSubscriber state: PoolState, collateral: Address, ): { oracleValue: number; ratio: number } { - const configOracle = - state.transmuter.collaterals[collateral].oracles.config; + const configOracle = state.transmuter.collaterals[collateral].config; if (configOracle.oracleType == OracleReadType.EXTERNAL) { return { oracleValue: 1, ratio: 1 }; } else { diff --git a/src/dex/angle-transmuter/angle-transmuter.ts b/src/dex/angle-transmuter/angle-transmuter.ts index 3ce0172ac..15069d65b 100644 --- a/src/dex/angle-transmuter/angle-transmuter.ts +++ b/src/dex/angle-transmuter/angle-transmuter.ts @@ -216,7 +216,7 @@ export class AngleTransmuter // Encode here the transaction arguments const swapData = TransmuterSubscriber.interface.encodeFunctionData( - 'swapExactInput', + side == SwapSide.SELL ? 'swapExactInput' : 'swapExactOutput', [ srcAmount, destAmount, diff --git a/src/dex/angle-transmuter/transmuter.ts b/src/dex/angle-transmuter/transmuter.ts index b067c7ebe..2f8ca6c91 100644 --- a/src/dex/angle-transmuter/transmuter.ts +++ b/src/dex/angle-transmuter/transmuter.ts @@ -21,6 +21,7 @@ import { TransmuterState, Fees, Oracle, + CollateralState, } from './types'; import _ from 'lodash'; import { BigNumber, ethers } from 'ethers'; @@ -63,6 +64,16 @@ export class TransmuterSubscriber extends PartialEventSubscriber< return this._handleSwap(parsed, _state); case 'Redeemed': return this._handleRedeem(parsed, _state); + case 'ReservesAdjusted': + return this._handleAdjustStablecoins(parsed, _state); + case 'CollateralAdded': + return this._handleAddCollateral(parsed, _state); + case 'CollateralRevoked': + return this._handleRevokeCollateral(parsed, _state); + case 'CollateralWhitelistStatusUpdated': + return this._handleSetWhitelistedStatus(parsed, _state); + case 'WhitelistStatusToggled': + return this._handleIsWhitelistedForType(parsed, _state); default: return null; } @@ -102,6 +113,20 @@ export class TransmuterSubscriber extends PartialEventSubscriber< [collat], ), })), + ...this.collaterals.map(collat => ({ + target: this.transmuter, + callData: TransmuterSubscriber.interface.encodeFunctionData( + 'isWhitelistedCollateral', + [collat], + ), + })), + ...this.collaterals.map(collat => ({ + target: this.transmuter, + callData: TransmuterSubscriber.interface.encodeFunctionData( + 'getCollateralWhitelistData', + [collat], + ), + })), { target: this.transmuter, callData: @@ -122,7 +147,12 @@ export class TransmuterSubscriber extends PartialEventSubscriber< blockNumber?: number | 'latest', ): DeepReadonly { let transmuterState = { - collaterals: {}, + collaterals: {} as { + [token: string]: CollateralState; + }, + isWhitelisted: {} as { + [token: string]: Set; + }, totalStablecoinIssued: 0, xRedemptionCurve: [], yRedemptionCurve: [], @@ -133,6 +163,8 @@ export class TransmuterSubscriber extends PartialEventSubscriber< const indexOracleFees = 1; const indexMintFees = 2; const indexBurnFees = 3; + const indexWhitelistStatus = 4; + const indexWhitelistData = 5; this.collaterals.forEach( (collat: Address, i: number) => @@ -172,12 +204,18 @@ export class TransmuterSubscriber extends PartialEventSubscriber< 18, ), ), - oracles: { - collateralMintPrice: 0, - collateralBurnPrice: 0, - config: this._setOracleConfig( - multicallOutputs[indexOracleFees * nbrCollaterals + i], - ), + config: this._setOracleConfig( + multicallOutputs[indexOracleFees * nbrCollaterals + i], + ), + whitelist: { + status: TransmuterSubscriber.interface.decodeFunctionResult( + 'isWhitelistedCollateral', + multicallOutputs[indexWhitelistStatus * nbrCollaterals + i], + )[0] as boolean, + data: TransmuterSubscriber.interface.decodeFunctionResult( + 'getCollateralWhitelistData', + multicallOutputs[indexWhitelistData * nbrCollaterals + i], + )[0] as string, }, }), ); @@ -289,6 +327,69 @@ export class TransmuterSubscriber extends PartialEventSubscriber< return state; } + _handleAddCollateral( + event: ethers.utils.LogDescription, + state: TransmuterState, + ): Readonly | null { + this.collaterals.push(event.args.collateral); + state.collaterals[event.args.collateral] = {} as CollateralState; + return state; + } + + _handleRevokeCollateral( + event: ethers.utils.LogDescription, + state: TransmuterState, + ): Readonly | null { + const index = this.collaterals.indexOf(event.args.collateral); + if (index > -1) this.collaterals.splice(index, 1); + delete state.collaterals[event.args.collateral]; + + return state; + } + + _handleAdjustStablecoins( + event: ethers.utils.LogDescription, + state: TransmuterState, + ): Readonly | null { + const collateral = event.args.collateral; + const isIncrease: boolean = event.args.increase; + const amount: number = + parseFloat(formatUnits(event.args.amount, 18)) * Number(isIncrease); + state.totalStablecoinIssued += amount; + state.collaterals[collateral].stablecoinsIssued += amount; + return state; + } + + _handleSetWhitelistedStatus( + event: ethers.utils.LogDescription, + state: TransmuterState, + ): Readonly | null { + const status: number = event.args.whitelistStatus; + const collateral: string = event.args.collateral; + const data: string = event.args.whitelistData; + if (!state.collaterals[collateral]) + state.collaterals[collateral] = {} as CollateralState; + if (status == 1) state.collaterals[collateral].whitelist.data = data; + state.collaterals[collateral].whitelist.status = status > 0 ? true : false; + return state; + } + + _handleIsWhitelistedForType( + event: ethers.utils.LogDescription, + state: TransmuterState, + ): Readonly | null { + const status: number = event.args.whitelistStatus; + const who: string = event.args.who; + const whitelistType: number = event.args.whitelistType; + if (!state.isWhitelisted[whitelistType]) + state.isWhitelisted[whitelistType] = new Set(); + if (status == 0 && state.isWhitelisted[whitelistType].has(who)) + state.isWhitelisted[whitelistType].delete(who); + else if (status !== 0 && !state.isWhitelisted[whitelistType].has(who)) + state.isWhitelisted[whitelistType].add(who); + return state; + } + /** * Keep track of used oracles for each collaterals */ @@ -299,8 +400,7 @@ export class TransmuterSubscriber extends PartialEventSubscriber< const collateral: string = event.args.collateral; const oracleConfig: string = event.args.oracleConfig; - state.collaterals[collateral].oracles.config = - this._setOracleConfig(oracleConfig); + state.collaterals[collateral].config = this._setOracleConfig(oracleConfig); return state; } diff --git a/src/dex/angle-transmuter/types.ts b/src/dex/angle-transmuter/types.ts index cd2b9a1e8..40f80a162 100644 --- a/src/dex/angle-transmuter/types.ts +++ b/src/dex/angle-transmuter/types.ts @@ -15,17 +15,19 @@ export type PoolState = { }; }; +export type CollateralState = { + whitelist: { status: boolean; data: string }; + fees: Fees; + stablecoinsIssued: number; + config: Oracle; +}; + export type TransmuterState = { collaterals: { - [token: string]: { - fees: Fees; - stablecoinsIssued: number; - oracles: { - collateralMintPrice: number; // Mint oracle collat --> EUR - collateralBurnPrice: number; // Burn oracle EUR --> collat - config: Oracle; - }; - }; + [token: string]: CollateralState; + }; + isWhitelisted: { + [type: number]: Set; }; xRedemptionCurve: number[]; yRedemptionCurve: number[];