diff --git a/scripts/fetch-event-blocknumber.ts b/scripts/fetch-event-blocknumber.ts index 728ee77c0..42ea19e44 100644 --- a/scripts/fetch-event-blocknumber.ts +++ b/scripts/fetch-event-blocknumber.ts @@ -7,11 +7,11 @@ import { Network } from '../src/constants'; import { Address } from '../src/types'; import { generateConfig } from '../src/config'; // TODO: Import correct ABI -import ABI from '../src/abi/angle-transmuter/Transmuter.json'; +import ABI from '../src/abi/angle-transmuter/ChainlinkEACAggregatorProxy.json'; // This is a helper script to fetch blockNumbers where a certain // event was released by a certain contract -async function getBlockNumbersForEvents( +export async function getBlockNumbersForEvents( contractAddress: Address, contractABI: any, eventNames: string[], @@ -41,11 +41,11 @@ async function getBlockNumbersForEvents( // TODO: Set your values here const network = Network.MAINNET; -const eventNames = ['WhitelistStatusToggled']; -const address = '0x00253582b2a3FE112feEC532221d9708c64cEFAb'; +const eventNames = ['AnswerUpdated']; +const address = '0x475855DAe09af1e3f2d380d766b9E630926ad3CE'; const provider = new StaticJsonRpcProvider( generateConfig(network).privateHttpProvider, network, ); -getBlockNumbersForEvents(address, ABI, eventNames, 0, 200000, provider); +getBlockNumbersForEvents(address, ABI, eventNames, 0, 110000, provider); diff --git a/src/abi/angle-transmuter/Transmuter.json b/src/abi/angle-transmuter/Transmuter.json index fffed6243..ce78f89cd 100644 --- a/src/abi/angle-transmuter/Transmuter.json +++ b/src/abi/angle-transmuter/Transmuter.json @@ -1,4 +1,360 @@ [ + { + "type": "event", + "name": "Swap", + "inputs": [ + { + "name": "tokenIn", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "tokenOut", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "amountIn", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "amountOut", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Redeemed", + "inputs": [ + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "tokens", + "type": "address[]", + "indexed": false, + "internalType": "address[]" + }, + { + "name": "amounts", + "type": "uint256[]", + "indexed": false, + "internalType": "uint256[]" + }, + { + "name": "forfeitTokens", + "type": "address[]", + "indexed": false, + "internalType": "address[]" + }, + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "CollateralAdded", + "inputs": [ + { + "name": "collateral", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "CollateralManagerSet", + "inputs": [ + { + "name": "collateral", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "managerData", + "type": "tuple", + "indexed": false, + "internalType": "struct ManagerStorage", + "components": [ + { + "name": "subCollaterals", + "type": "address[]", + "internalType": "contract IERC20[]" + }, + { + "name": "config", + "type": "bytes", + "internalType": "bytes" + } + ] + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "CollateralRevoked", + "inputs": [ + { + "name": "collateral", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "CollateralWhitelistStatusUpdated", + "inputs": [ + { + "name": "collateral", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "whitelistData", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + }, + { + "name": "whitelistStatus", + "type": "uint8", + "indexed": false, + "internalType": "uint8" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "FeesSet", + "inputs": [ + { + "name": "collateral", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "xFee", + "type": "uint64[]", + "indexed": false, + "internalType": "uint64[]" + }, + { + "name": "yFee", + "type": "int64[]", + "indexed": false, + "internalType": "int64[]" + }, + { + "name": "mint", + "type": "bool", + "indexed": false, + "internalType": "bool" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OracleSet", + "inputs": [ + { + "name": "collateral", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "oracleConfig", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OwnershipTransferred", + "inputs": [ + { + "name": "previousOwner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newOwner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "PauseToggled", + "inputs": [ + { + "name": "collateral", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "pausedType", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "isPaused", + "type": "bool", + "indexed": false, + "internalType": "bool" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RedemptionCurveParamsSet", + "inputs": [ + { + "name": "xFee", + "type": "uint64[]", + "indexed": false, + "internalType": "uint64[]" + }, + { + "name": "yFee", + "type": "int64[]", + "indexed": false, + "internalType": "int64[]" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ReservesAdjusted", + "inputs": [ + { + "name": "collateral", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "increase", + "type": "bool", + "indexed": false, + "internalType": "bool" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "TrustedToggled", + "inputs": [ + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "isTrusted", + "type": "bool", + "indexed": false, + "internalType": "bool" + }, + { + "name": "trustedType", + "type": "uint8", + "indexed": false, + "internalType": "enum TrustedType" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "WhitelistStatusToggled", + "inputs": [ + { + "name": "whitelistType", + "type": "uint8", + "indexed": false, + "internalType": "enum WhitelistType" + }, + { + "name": "who", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "whitelistStatus", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, { "inputs": [], "name": "accessControlManager", diff --git a/src/dex/angle-transmuter/angle-transmuter-e2e.test.ts b/src/dex/angle-transmuter/angle-transmuter-e2e.test.ts index 6ba31b07f..0723b8c54 100644 --- a/src/dex/angle-transmuter/angle-transmuter-e2e.test.ts +++ b/src/dex/angle-transmuter/angle-transmuter-e2e.test.ts @@ -80,7 +80,7 @@ describe('AngleTransmuter E2E', () => { describe('EUROC', () => { const tokenASymbol: string = 'EUROC'; - const tokenBSymbol: string = 'agEUR'; + const tokenBSymbol: string = 'EURA'; const tokenAAmount: string = '1000000'; const tokenBAmount: string = '1000000000000000000'; @@ -98,12 +98,30 @@ describe('AngleTransmuter E2E', () => { }); describe('BC3M', () => { const tokenASymbol: string = 'bC3M'; - const tokenBSymbol: string = 'agEUR'; + const tokenBSymbol: string = 'EURA'; const tokenAAmount: string = '100000000000000000'; const tokenBAmount: string = '1000000000000000000'; const nativeTokenAmount = '1000000000000000000'; + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); + describe('BERNX', () => { + const tokenASymbol: string = 'bERNX'; + const tokenBSymbol: string = 'EURA'; + + const tokenAAmount: string = '500000000000000000'; + const tokenBAmount: string = '1000000000000000000'; + const nativeTokenAmount = '1000000000000000000'; + testForNetwork( network, dexKey, diff --git a/src/dex/angle-transmuter/angle-transmuter-events.test.ts b/src/dex/angle-transmuter/angle-transmuter-events.test.ts index ee85fe45c..9cc5518fc 100644 --- a/src/dex/angle-transmuter/angle-transmuter-events.test.ts +++ b/src/dex/angle-transmuter/angle-transmuter-events.test.ts @@ -34,36 +34,45 @@ describe('AngleTransmuter EventPool Mainnet', () => { const eventsToTest: Record = { //Transmuter Events '0x00253582b2a3FE112feEC532221d9708c64cEFAb': { - FeesSet: [], + // FeesSet: [19567142], RedemptionCurveParamsSet: [], - OracleSet: [], - Swap: [18012837], + // OracleSet: [19567142], + // Swap: [ + // 19582703, 19583592, 19584048, 19589408, 19602964, 19607526, 19611131, 19614332, 19616567, 19623965, 19625332, + // 19631246, 19631653, 19633515, 19638468, 19648373, 19653214, 19656178, 19657413, 19667310, 19667763, + // ], Redeemed: [], ReservesAdjusted: [], - CollateralAdded: [], + // CollateralAdded: [19567142], CollateralRevoked: [], - CollateralWhitelistStatusUpdated: [], + // CollateralWhitelistStatusUpdated: [19567142], WhitelistStatusToggled: [], }, // Pyth Events - '0x4305FB66699C3B2702D4d05CF36551390A4c69C6': { - PriceFeedUpdate: [ - 17921792, 17922079, 17943228, 17943513, 17960561, 17960561, 17960561, - 17960561, 17960561, 17983718, 17983718, 17984600, 17984600, 17984622, - 17984622, 17984709, 17984709, 17984717, 17984717, 17984778, 17984778, - 17988349, 17988349, 17990018, 17990018, 17990245, 17990245, 18027681, - 18027681, 18027717, 18027717, 18027739, 18027739, 18027751, 18027751, - 18027923, 18027923, 18031029, 18031029, 18081028, 18081028, - ], - }, + // "0x4305FB66699C3B2702D4d05CF36551390A4c69C6": { + // PriceFeedUpdate: [ + // 19611413, 19611413, 19611413, 19611413, 19611413, 19611413, 19611413, 19611413, 19611413, 19611413, 19611413, + // 19611413, 19618548, 19618548, 19618548, 19618548, 19618548, 19618548, 19618548, 19618548, 19618548, 19618548, + // 19618548, 19618548, 19625698, 19625698, 19625698, 19625698, 19625698, 19625698, 19625698, 19625698, 19625698, + // 19625698, 19625698, 19625698, 19625698, 19625698, 19625698, 19632847, 19632847, 19632847, 19632847, 19632847, + // 19632847, 19632847, 19632847, 19632847, 19632847, 19632847, 19632847, 19632847, 19632847, 19632847, 19633586, + // 19633586, 19639991, 19639991, 19639991, 19639991, 19639991, 19639991, 19639991, 19639991, 19639991, 19639991, + // 19639991, 19639991, 19647112, 19647112, 19647112, 19647112, 19647112, 19647112, 19647112, 19647112, 19647112, + // 19647112, 19647112, 19647112, 19649850, 19649850, 19654237, 19654237, 19654237, 19654237, 19654237, 19654237, + // 19654237, 19654237, 19654237, 19654237, 19654237, 19654237, + // ], + // }, //Backed Events - '0x83Ec02059F686E747392A22ddfED7833bA0d7cE3': { - AnswerUpdated: [ - 17926504, 17933436, 17940612, 17962015, 17969174, 17976303, 17983422, - 17990612, 18012042, 18019176, 18026755, 18033471, 18040608, 18062016, - 18069196, 18076364, 18083462, 18090713, 18112016, 18119149, - ], - }, + // "0x83Ec02059F686E747392A22ddfED7833bA0d7cE3": { + // AnswerUpdated: [ + // 19574099, 19574442, 19581598, 19588736, 19610148, 19617280, 19624427, 19638723, 19667243, 19674385, + // ], + // }, + // "0x475855DAe09af1e3f2d380d766b9E630926ad3CE": { + // AnswerUpdated: [ + // 19574095, 19574443, 19581596, 19588737, 19610145, 19617284, 19624426, 19631578, 19638720, 19667241, 19674386, + // ], + // }, //Redstone Events '0x6E27A25999B3C665E44D903B2139F5a4Be2B6C26': { AnswerUpdated: [], @@ -83,6 +92,7 @@ describe('AngleTransmuter EventPool Mainnet', () => { }, transmuter: '0x00253582b2a3FE112feEC532221d9708c64cEFAb', collaterals: [ + '0x3f95AA88dDbB7D9D484aa3D482bf0a80009c52c9', '0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c', '0x2F123cF3F37CE3328CC9B5b8415f9EC5109b45e7', ], @@ -94,6 +104,11 @@ describe('AngleTransmuter EventPool Mainnet', () => { aggregator: '0x83Ec02059F686E747392A22ddfED7833bA0d7cE3', decimals: 8, }, + '0x475855DAe09af1e3f2d380d766b9E630926ad3CE': { + proxy: '0x475855DAe09af1e3f2d380d766b9E630926ad3CE', + aggregator: '0x475855DAe09af1e3f2d380d766b9E630926ad3CE', + decimals: 8, + }, }, redstone: { '0x6E27A25999B3C665E44D903B2139F5a4Be2B6C26': { @@ -105,7 +120,7 @@ describe('AngleTransmuter EventPool Mainnet', () => { pyth: { proxy: '0x4305FB66699C3B2702D4d05CF36551390A4c69C6', ids: [ - '0xd052e6f54fe29355d6a3c06592fdefe49fae7840df6d8655bf6d6bfb789b56e4', + '0x76fa85158bf14ede77087fe3ae472f66213f6ea2f5b411cb2de472794990fa5c', '0xa995d00bb36a63cef7fd2c287dc105fc8f3d93779f062f09551b0af3e81ec30b', ], }, diff --git a/src/dex/angle-transmuter/angle-transmuter-integration.test.ts b/src/dex/angle-transmuter/angle-transmuter-integration.test.ts index 91b217280..72742ab61 100644 --- a/src/dex/angle-transmuter/angle-transmuter-integration.test.ts +++ b/src/dex/angle-transmuter/angle-transmuter-integration.test.ts @@ -170,35 +170,37 @@ describe('AngleTransmuter', () => { const tokens = Tokens[network]; - const srcTokenSymbol = 'EUROC'; - const destTokenSymbol = 'agEUR'; + const eurocSymbol = 'EUROC'; + const bC3MSymbol = 'bC3M'; + const bERNXSymbol = 'bERNX'; + const euraSymbol = 'EURA'; - const amountsForSell = [ + const amountsEUROC = [ 0n, - 1n * BI_POWS[tokens[srcTokenSymbol].decimals], - 2n * BI_POWS[tokens[srcTokenSymbol].decimals], - 3n * BI_POWS[tokens[srcTokenSymbol].decimals], - 4n * BI_POWS[tokens[srcTokenSymbol].decimals], - 5n * BI_POWS[tokens[srcTokenSymbol].decimals], - 6n * BI_POWS[tokens[srcTokenSymbol].decimals], - 7n * BI_POWS[tokens[srcTokenSymbol].decimals], - 8n * BI_POWS[tokens[srcTokenSymbol].decimals], - 9n * BI_POWS[tokens[srcTokenSymbol].decimals], - 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + 1n * BI_POWS[tokens[eurocSymbol].decimals], + 2n * BI_POWS[tokens[eurocSymbol].decimals], + 3n * BI_POWS[tokens[eurocSymbol].decimals], + 4n * BI_POWS[tokens[eurocSymbol].decimals], + 5n * BI_POWS[tokens[eurocSymbol].decimals], + 6n * BI_POWS[tokens[eurocSymbol].decimals], + 7n * BI_POWS[tokens[eurocSymbol].decimals], + 8n * BI_POWS[tokens[eurocSymbol].decimals], + 9n * BI_POWS[tokens[eurocSymbol].decimals], + 10n * BI_POWS[tokens[eurocSymbol].decimals], ]; - const amountsForBuy = [ + const amountsEURA = [ 0n, - 1n * BI_POWS[tokens[destTokenSymbol].decimals], - 2n * BI_POWS[tokens[destTokenSymbol].decimals], - 3n * BI_POWS[tokens[destTokenSymbol].decimals], - 4n * BI_POWS[tokens[destTokenSymbol].decimals], - 5n * BI_POWS[tokens[destTokenSymbol].decimals], - 6n * BI_POWS[tokens[destTokenSymbol].decimals], - 7n * BI_POWS[tokens[destTokenSymbol].decimals], - 8n * BI_POWS[tokens[destTokenSymbol].decimals], - 9n * BI_POWS[tokens[destTokenSymbol].decimals], - 10n * BI_POWS[tokens[destTokenSymbol].decimals], + 1n * BI_POWS[tokens[euraSymbol].decimals], + 2n * BI_POWS[tokens[euraSymbol].decimals], + 3n * BI_POWS[tokens[euraSymbol].decimals], + 4n * BI_POWS[tokens[euraSymbol].decimals], + 5n * BI_POWS[tokens[euraSymbol].decimals], + 6n * BI_POWS[tokens[euraSymbol].decimals], + 7n * BI_POWS[tokens[euraSymbol].decimals], + 8n * BI_POWS[tokens[euraSymbol].decimals], + 9n * BI_POWS[tokens[euraSymbol].decimals], + 10n * BI_POWS[tokens[euraSymbol].decimals], ]; beforeAll(async () => { @@ -209,35 +211,89 @@ describe('AngleTransmuter', () => { } }); - it('getPoolIdentifiers and getPricesVolume SELL', async () => { + it('getPoolIdentifiers and getPricesVolume SELL - EUROC', async () => { await testPricingOnNetwork( angleTransmuter, network, dexKey, blockNumber, - srcTokenSymbol, - destTokenSymbol, + eurocSymbol, + euraSymbol, SwapSide.SELL, - amountsForSell, + amountsEUROC, 'quoteIn', ); }); - it('getPoolIdentifiers and getPricesVolume BUY', async () => { + it('getPoolIdentifiers and getPricesVolume SELL - EURA', async () => { await testPricingOnNetwork( angleTransmuter, network, dexKey, blockNumber, - srcTokenSymbol, - destTokenSymbol, + euraSymbol, + eurocSymbol, + SwapSide.SELL, + amountsEURA, + 'quoteIn', + ); + }); + + it('getPoolIdentifiers and getPricesVolume BUY - EUROC', async () => { + await testPricingOnNetwork( + angleTransmuter, + network, + dexKey, + blockNumber, + eurocSymbol, + euraSymbol, SwapSide.BUY, - amountsForBuy, + amountsEURA, 'quoteOut', ); }); - it('getTopPoolsForToken', async () => { + it('getPoolIdentifiers and getPricesVolume BUY - EURA', async () => { + await testPricingOnNetwork( + angleTransmuter, + network, + dexKey, + blockNumber, + euraSymbol, + eurocSymbol, + SwapSide.BUY, + amountsEUROC, + 'quoteOut', + ); + }); + + it('getTopPoolsForToken - EUROC', async () => { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newAngleTransmuter = new AngleTransmuter( + network, + dexKey, + dexHelper, + ); + if (newAngleTransmuter.updatePoolState) { + await newAngleTransmuter.updatePoolState(); + } + const poolLiquidity = await newAngleTransmuter.getTopPoolsForToken( + tokens[eurocSymbol].address, + 10, + ); + console.log(`${eurocSymbol} Top Pools:`, poolLiquidity); + + if (!newAngleTransmuter.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][eurocSymbol].address, + dexKey, + ); + } + }); + + it('getTopPoolsForToken - EURA', async () => { // We have to check without calling initializePricing, because // pool-tracker is not calling that function const newAngleTransmuter = new AngleTransmuter( @@ -249,15 +305,15 @@ describe('AngleTransmuter', () => { await newAngleTransmuter.updatePoolState(); } const poolLiquidity = await newAngleTransmuter.getTopPoolsForToken( - tokens[srcTokenSymbol].address, + tokens[euraSymbol].address, 10, ); - console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + console.log(`${euraSymbol} Top Pools:`, poolLiquidity); if (!newAngleTransmuter.hasConstantPriceLargeAmounts) { checkPoolsLiquidity( poolLiquidity, - Tokens[network][srcTokenSymbol].address, + Tokens[network][euraSymbol].address, dexKey, ); } diff --git a/src/dex/angle-transmuter/angle-transmuter-pool.ts b/src/dex/angle-transmuter/angle-transmuter-pool.ts index f75f65bf5..3acff260d 100644 --- a/src/dex/angle-transmuter/angle-transmuter-pool.ts +++ b/src/dex/angle-transmuter/angle-transmuter-pool.ts @@ -34,6 +34,8 @@ import { formatEther, formatUnits } from 'ethers/lib/utils'; import { BackedSubscriber } from './backedOracle'; import { SwapSide } from '../../constants'; import { ethers } from 'ethers'; +import { BLOCK_UPGRADE_ORACLE } from './constants'; +import { log } from 'console'; export class AngleTransmuterEventPool extends ComposedEventSubscriber { public transmuter: Contract; @@ -102,7 +104,7 @@ export class AngleTransmuterEventPool extends ComposedEventSubscriber ); const transmuterListener = new TransmuterSubscriber( - config.agEUR.address, + config.EURA.address, config.transmuter, config.collaterals, lens>().transmuter, @@ -122,7 +124,7 @@ export class AngleTransmuterEventPool extends ComposedEventSubscriber pythListener, ], { - stablecoin: config.agEUR, + stablecoin: config.EURA, transmuter: {} as TransmuterState, oracles: { chainlink: {}, pyth: {} }, }, @@ -159,13 +161,19 @@ export class AngleTransmuterEventPool extends ComposedEventSubscriber let minRatio = 0; let collateral = _tokenIn; if (isMint) - oracleValue = await this._readMint(this.config, state, _tokenIn); + oracleValue = await this._readMint( + this.config, + state, + _tokenIn, + blockNumber, + ); else { collateral = _tokenOut; ({ oracleValue, minRatio } = await this._getBurnOracle( this.config, state, _tokenOut, + blockNumber, )); } @@ -431,7 +439,7 @@ export class AngleTransmuterEventPool extends ComposedEventSubscriber ); return { - agEUR: dexParams.EURA, + EURA: dexParams.EURA, transmuter: dexParams.transmuter, collaterals: collaterals, oracles: oracles, @@ -442,14 +450,25 @@ export class AngleTransmuterEventPool extends ComposedEventSubscriber UTILS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ - _readMint(config: PoolConfig, state: PoolState, collateral: Address): number { + _readMint( + config: PoolConfig, + state: PoolState, + collateral: Address, + blockNumber: number, + ): number { const configOracle = state.transmuter.collaterals[collateral].config; if (configOracle.oracleType === OracleReadType.EXTERNAL) { return 1; } let target: number; let spot: number; - ({ spot, target } = this._readSpotAndTarget(config, state, collateral)); + ({ spot, target } = this._readSpotAndTarget( + config, + state, + collateral, + blockNumber, + )); + if (target < spot) spot = target; return spot; } @@ -458,6 +477,7 @@ export class AngleTransmuterEventPool extends ComposedEventSubscriber config: PoolConfig, state: PoolState, collateral: Address, + blockNumber: number, ): { oracleValue: number; minRatio: number } { return config.collaterals.reduce( ( @@ -472,9 +492,16 @@ export class AngleTransmuterEventPool extends ComposedEventSubscriber config, state, comparedCollat, + blockNumber, )); acc.oracleValue = oracleValue; - } else ({ ratio } = this._readBurn(config, state, comparedCollat)); + } else + ({ ratio } = this._readBurn( + config, + state, + comparedCollat, + blockNumber, + )); if (ratio < acc.minRatio) acc.minRatio = ratio; return acc; }, @@ -486,6 +513,7 @@ export class AngleTransmuterEventPool extends ComposedEventSubscriber config: PoolConfig, state: PoolState, collateral: Address, + blockNumber: number, ): { oracleValue: number; ratio: number } { const configOracle = state.transmuter.collaterals[collateral].config; if (configOracle.oracleType === OracleReadType.EXTERNAL) { @@ -498,6 +526,7 @@ export class AngleTransmuterEventPool extends ComposedEventSubscriber config, state, collateral, + blockNumber, )); let ratio = 1; @@ -510,6 +539,7 @@ export class AngleTransmuterEventPool extends ComposedEventSubscriber config: PoolConfig, state: PoolState, collateral: Address, + blockNumber: number, ): { spot: number; target: number; @@ -517,12 +547,22 @@ export class AngleTransmuterEventPool extends ComposedEventSubscriber burnRatioDeviation: number; } { const configOracle = state.transmuter.collaterals[collateral].config; - const hyperparameters = filterDictionaryOnly( - ethers.utils.defaultAbiCoder.decode( - ['uint128 userDeviation', 'uint128 burnRatioDeviation'], - configOracle.hyperparameters, - ), - ) as unknown as OracleHyperparameter; + let userDeviation = 0; + let burnRatioDeviation = 0; + if (BLOCK_UPGRADE_ORACLE <= blockNumber) { + const hyperparameters = filterDictionaryOnly( + ethers.utils.defaultAbiCoder.decode( + ['uint128 userDeviation', 'uint128 burnRatioDeviation'], + configOracle.hyperparameters, + ), + ) as unknown as OracleHyperparameter; + userDeviation = Number.parseFloat( + formatEther(hyperparameters.userDeviation.toString()), + ); + burnRatioDeviation = Number.parseFloat( + formatEther(hyperparameters.burnRatioDeviation.toString()), + ); + } const targetPrice = this._read( config, state, @@ -537,14 +577,9 @@ export class AngleTransmuterEventPool extends ComposedEventSubscriber configOracle.oracleFeed, targetPrice, ); - const userDeviation = Number.parseFloat( - formatEther(hyperparameters.userDeviation.toString()), - ); - const burnRatioDeviation = Number.parseFloat( - formatEther(hyperparameters.burnRatioDeviation.toString()), - ); + if ( - targetPrice * (1 - userDeviation) < oracleValue || + targetPrice * (1 - userDeviation) < oracleValue && oracleValue < targetPrice * (1 + userDeviation) ) oracleValue = targetPrice; diff --git a/src/dex/angle-transmuter/angle-transmuter.ts b/src/dex/angle-transmuter/angle-transmuter.ts index 7b5c40b3b..818a42de8 100644 --- a/src/dex/angle-transmuter/angle-transmuter.ts +++ b/src/dex/angle-transmuter/angle-transmuter.ts @@ -346,7 +346,7 @@ export class AngleTransmuter srcAddress !== destAddress && this.supportedTokensMap[srcAddress] && this.supportedTokensMap[destAddress] && - // check that at least one of the tokens is agEUR + // check that at least one of the tokens is EURA (srcAddress === this.params.EURA.address.toLowerCase() || destAddress === this.params.EURA.address.toLowerCase()) ) { diff --git a/src/dex/angle-transmuter/constants.ts b/src/dex/angle-transmuter/constants.ts index c36be3c4a..c876156b9 100644 --- a/src/dex/angle-transmuter/constants.ts +++ b/src/dex/angle-transmuter/constants.ts @@ -2,3 +2,4 @@ export const CBETH = '0xBe9895146f7AF43049ca1c1AE358B0541Ea49704'; export const RETH = '0xae78736Cd615f374D3085123A210448E74Fc6393'; export const STETH = '0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84'; export const SFRXETH = '0xac3E018457B222d93114458476f3E3416Abbe38F'; +export const BLOCK_UPGRADE_ORACLE = 19567142; diff --git a/src/dex/angle-transmuter/transmuter.ts b/src/dex/angle-transmuter/transmuter.ts index 451c181c9..7d3ca5200 100644 --- a/src/dex/angle-transmuter/transmuter.ts +++ b/src/dex/angle-transmuter/transmuter.ts @@ -8,7 +8,7 @@ import { MultiCallInput, MultiCallOutput, } from '../../types'; -import { CBETH, RETH, SFRXETH, STETH } from './constants'; +import { BLOCK_UPGRADE_ORACLE, CBETH, RETH, SFRXETH, STETH } from './constants'; import { Lens } from '../../lens'; import { Interface } from '@ethersproject/abi'; import TransmuterABI from '../../abi/angle-transmuter/Transmuter.json'; @@ -35,7 +35,7 @@ export class TransmuterSubscriber extends PartialEventSubscriber< static readonly interface = new Interface(TransmuterABI); constructor( - private agEUR: Address, + private EURA: Address, private transmuter: Address, private collaterals: Address[], lens: Lens, DeepReadonly>, @@ -58,7 +58,7 @@ export class TransmuterSubscriber extends PartialEventSubscriber< case 'RedemptionCurveParamsSet': return this._handleRedemptionCurveSet(parsed, _state); case 'OracleSet': - return this._handleOracleSet(parsed, _state); + return this._handleOracleSet(parsed, _state, blockHeader.number); case 'Swap': return this._handleSwap(parsed, _state); case 'Redeemed': @@ -206,6 +206,9 @@ export class TransmuterSubscriber extends PartialEventSubscriber< ), config: this._setOracleConfig( multicallOutputs[indexOracleFees * nbrCollaterals + i], + blockNumber === undefined || blockNumber === 'latest' + ? BLOCK_UPGRADE_ORACLE + 1 + : blockNumber, ), whitelist: { status: TransmuterSubscriber.interface.decodeFunctionResult( @@ -299,8 +302,9 @@ export class TransmuterSubscriber extends PartialEventSubscriber< ): Readonly | null { const tokenIn: string = event.args.tokenIn; const tokenOut: string = event.args.tokenOut; + console.log(state); // in case of a burn - if (tokenIn.toLowerCase() === this.agEUR.toLowerCase()) { + if (tokenIn.toLowerCase() === this.EURA.toLowerCase()) { const amount: number = Number.parseFloat( formatUnits(event.args.amountIn, 18), ); @@ -407,21 +411,27 @@ export class TransmuterSubscriber extends PartialEventSubscriber< _handleOracleSet( event: ethers.utils.LogDescription, state: TransmuterState, + blockNumber: number, ): Readonly | null { const collateral: string = event.args.collateral; const oracleConfig: string = event.args.oracleConfig; - state.collaterals[collateral].config = this._setOracleConfig(oracleConfig); + state.collaterals[collateral].config = this._setOracleConfig( + oracleConfig, + blockNumber, + ); return state; } /** * Keep track of used oracles for each collaterals */ - _setOracleConfig(oracleConfig: string): Oracle { + _setOracleConfig(oracleConfig: string, blockNumber: number): Oracle { const configOracle = {} as Oracle; - const oracleConfigDecoded = - TransmuterSubscriber._decodeOracleConfig(oracleConfig); + const oracleConfigDecoded = TransmuterSubscriber._decodeOracleConfig( + oracleConfig, + blockNumber, + ); configOracle.oracleType = oracleConfigDecoded.oracleType; configOracle.targetType = oracleConfigDecoded.targetType; @@ -445,7 +455,25 @@ export class TransmuterSubscriber extends PartialEventSubscriber< return configOracle; } - static _decodeOracleConfig(oracleConfig: string): DecodedOracleConfig { + static _decodeOracleConfig( + oracleConfig: string, + blockNumber: number, + ): DecodedOracleConfig { + if (BLOCK_UPGRADE_ORACLE > blockNumber) { + const oracleConfigDecoded = filterDictionaryOnly( + ethers.utils.defaultAbiCoder.decode( + [ + 'uint8 oracleType', + 'uint8 targetType', + 'bytes oracleData', + 'bytes targetData', + ], + oracleConfig, + ), + ) as unknown as DecodedOracleConfig; + oracleConfigDecoded.hyperparameters = ''; + return oracleConfigDecoded; + } const oracleConfigDecoded = filterDictionaryOnly( ethers.utils.defaultAbiCoder.decode( [ diff --git a/src/dex/angle-transmuter/types.ts b/src/dex/angle-transmuter/types.ts index e5f0afd95..3f1ca0b6b 100644 --- a/src/dex/angle-transmuter/types.ts +++ b/src/dex/angle-transmuter/types.ts @@ -37,7 +37,7 @@ export type ChainlinkConfig = { export type PythConfig = { proxy: Address; ids: string[] }; export type PoolConfig = { - agEUR: Token; + EURA: Token; transmuter: Address; collaterals: Address[]; oracles: { diff --git a/tests/utils-e2e.ts b/tests/utils-e2e.ts index 82e0b8e00..8d2b8bc15 100644 --- a/tests/utils-e2e.ts +++ b/tests/utils-e2e.ts @@ -394,6 +394,7 @@ export async function testE2E( ); const swapTx = await ts.simulate(swapParams); + if (!swapTx.success) console.log('url swap: ', swapTx.url); // Only log gas estimate if testing against API if (useAPI) { const gasUsed = swapTx.gasUsed || '0';