diff --git a/abis/forwarderUpdated.json b/abis/forwarderUpdated.json new file mode 100644 index 0000000..08ed6d8 --- /dev/null +++ b/abis/forwarderUpdated.json @@ -0,0 +1,45 @@ +[ + { + "inputs": [], + "name": "getLastSeenPotData", + "outputs": [ + { + "components": [ + { + "internalType": "uint96", + "name": "dsr", + "type": "uint96" + }, + { + "internalType": "uint120", + "name": "chi", + "type": "uint120" + }, + { + "internalType": "uint40", + "name": "rho", + "type": "uint40" + } + ], + "internalType": "struct IForwarderBase.PotData", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "refresh", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/abis/index.ts b/abis/index.ts index 5dabd74..ea5e465 100644 --- a/abis/index.ts +++ b/abis/index.ts @@ -4,6 +4,7 @@ export { default as dsNoteAbi } from './dsNote.json' export { default as erc20Abi } from './erc20.json' export { default as forwarderAbi } from './forwarder.json' export { default as forwarderArbitrumAbi } from './forwarderArbitrum.json' +export { default as forwarderUpdatedAbi } from './forwarderUpdated.json' export { default as gnosisGovernanceExecutorAbi } from './gnosisGovernanceExecutor.json' export { default as killSwitchOracleAbi } from './killSwitchOracle.json' export { default as metaMorphoAbi } from './metaMorpho.json' diff --git a/hardhat.config.ts b/hardhat.config.ts index c3de74f..3e4f541 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -31,7 +31,7 @@ const ETHERSCAN_KEY = process.env.ETHERSCAN_KEY let forking = { url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`, - blockNumber: 20126359, // 2024-06-19 02:23:47 + blockNumber: 20627610, // 2024-08-28 02:13:35 } as HardhatNetworkForkingUserConfig if (TEST_NETWORK == 'mainnet') { diff --git a/test/web3-functions/mainnet/cap-automator.test.ts b/test/web3-functions/mainnet/cap-automator.test.ts index 2d5ca8d..26ad27b 100644 --- a/test/web3-functions/mainnet/cap-automator.test.ts +++ b/test/web3-functions/mainnet/cap-automator.test.ts @@ -33,10 +33,10 @@ describe('CapAutomator', function () { sendSlackMessages: false, } - const { wbtc, weth, wsteth } = addresses.mainnet + const { reth, weth, wsteth } = addresses.mainnet - const wbtcWhale = '0xb20Fb60E27a1Be799b5e04159eC2024CC3734eD7' as const - const wstethWhale = '0x5fEC2f34D80ED82370F733043B6A536d7e9D7f8d' as const + const rethWhale = '0x7C5aaA2a20b01df027aD032f7A768aC015E77b86' as const + const wstethWhale = '0x3c22ec75ea5D745c78fc84762F7F1E6D82a2c5BF' as const const supply = async (signerAddress: string, tokenAddress: string, amount: BigInt) => { await impersonateAccount(signerAddress) @@ -134,15 +134,15 @@ describe('CapAutomator', function () { describe(`${threshold / 100}% threshold`, () => { it(`actual gap is smaller than optimal but the threshold is not met`, async () => { - const { gap } = await capAutomator.supplyCapConfigs(wbtc) + const { gap } = await capAutomator.supplyCapConfigs(reth) const percentageOfTheGapTooSmallToTrigger = (10000 - threshold) / 100 - // full tokens * WBTC decimals * percentage of the gap + // full tokens * reth decimals * percentage of the gap const amountInFullTokens = (BigInt(gap) * BigInt(percentageOfTheGapTooSmallToTrigger)) / BigInt(100) // supplying only 1/4 of the full amount - await supply(wbtcWhale, wbtc, amountInFullTokens * BigInt(10 ** 8)) + await supply(rethWhale, reth, amountInFullTokens * BigInt(10 ** 18)) const { result } = await capAutomatorW3F.run('onRun', { userArgs: { ...userArgs, threshold } }) @@ -151,15 +151,15 @@ describe('CapAutomator', function () { }) it(`one supply cap increase is required`, async () => { - const { gap } = await capAutomator.supplyCapConfigs(wbtc) + const { gap } = await capAutomator.supplyCapConfigs(reth) const percentageOfTheGapNeededForTrigger = (10000 - threshold) / 100 + 1 - // full tokens * WBTC decimals * percentage of the gap + // full tokens * reth decimals * percentage of the gap const amountInFullTokens = (BigInt(gap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) // supplying only 1/4 of the full supply amount - await supply(wbtcWhale, wbtc, (amountInFullTokens * BigInt(10 ** 8)) / BigInt(4)) + await supply(rethWhale, reth, (amountInFullTokens * BigInt(10 ** 18)) / BigInt(4)) const { result: negativeResult } = await capAutomatorW3F.run('onRun', { userArgs: { ...userArgs, threshold }, @@ -168,7 +168,7 @@ describe('CapAutomator', function () { expect(negativeResult.canExec).to.equal(false) // supplying remaining of the full supply amount - await supply(wbtcWhale, wbtc, (amountInFullTokens * BigInt(10 ** 8) * BigInt(3)) / BigInt(4)) + await supply(rethWhale, reth, (amountInFullTokens * BigInt(10 ** 18) * BigInt(3)) / BigInt(4)) const { result: positiveResult } = await capAutomatorW3F.run('onRun', { userArgs: { ...userArgs, threshold }, @@ -184,9 +184,9 @@ describe('CapAutomator', function () { expect(callData.length).to.equal(1) expect(callData[0].to).to.equal(addresses.mainnet.capAutomator) - expect(callData[0].data).to.equal(formatExecSupplyCallData(wbtc)) + expect(callData[0].data).to.equal(formatExecSupplyCallData(reth)) - const supplyCapBefore = BigInt((await protocolDataProvider.getReserveCaps(wbtc)).supplyCap) + const supplyCapBefore = BigInt((await protocolDataProvider.getReserveCaps(reth)).supplyCap) await insistOnExecution(() => keeper.sendTransaction({ @@ -195,25 +195,25 @@ describe('CapAutomator', function () { }), ) - const supplyCapAfter = BigInt((await protocolDataProvider.getReserveCaps(wbtc)).supplyCap) + const supplyCapAfter = BigInt((await protocolDataProvider.getReserveCaps(reth)).supplyCap) expect(supplyCapAfter).to.equal(supplyCapBefore + amountInFullTokens) }) it(`one supply cap decrease is required`, async () => { - const { gap } = await capAutomator.supplyCapConfigs(wbtc) + const { gap } = await capAutomator.supplyCapConfigs(reth) const percentageOfTheGapNeededForTrigger = (10000 - threshold) / 100 + 1 - // full tokens * WBTC decimals * percentage of the gap + // full tokens * reth decimals * percentage of the gap const amountInFullTokens = (BigInt(gap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) // supplying only 1/4 of the full supply amount - await supply(wbtcWhale, wbtc, amountInFullTokens * BigInt(10 ** 8)) + await supply(rethWhale, reth, amountInFullTokens * BigInt(10 ** 18)) - await insistOnExecution(() => capAutomator.exec(wbtc)) + await insistOnExecution(() => capAutomator.exec(reth)) - await withdraw(wbtcWhale, wbtc, amountInFullTokens * BigInt(10 ** 8)) + await withdraw(rethWhale, reth, amountInFullTokens * BigInt(10 ** 18)) const { result: positiveResult } = await capAutomatorW3F.run('onRun', { userArgs: { ...userArgs, threshold }, @@ -229,9 +229,9 @@ describe('CapAutomator', function () { expect(callData.length).to.equal(1) expect(callData[0].to).to.equal(addresses.mainnet.capAutomator) - expect(callData[0].data).to.equal(formatExecSupplyCallData(wbtc)) + expect(callData[0].data).to.equal(formatExecSupplyCallData(reth)) - const supplyCapBefore = BigInt((await protocolDataProvider.getReserveCaps(wbtc)).supplyCap) + const supplyCapBefore = BigInt((await protocolDataProvider.getReserveCaps(reth)).supplyCap) await insistOnExecution(() => keeper.sendTransaction({ @@ -240,27 +240,27 @@ describe('CapAutomator', function () { }), ) - const supplyCapAfter = BigInt((await protocolDataProvider.getReserveCaps(wbtc)).supplyCap) + const supplyCapAfter = BigInt((await protocolDataProvider.getReserveCaps(reth)).supplyCap) expect(supplyCapAfter).to.equal(supplyCapBefore - amountInFullTokens) }) it('two supply cap updates are required', async () => { const { gap: wstethGap } = await capAutomator.supplyCapConfigs(wsteth) - const { gap: wbtcGap } = await capAutomator.supplyCapConfigs(wbtc) + const { gap: rethGap } = await capAutomator.supplyCapConfigs(reth) const percentageOfTheGapNeededForTrigger = (10000 - threshold) / 100 + 1 const wstethAmountInFullTokens = (BigInt(wstethGap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) - const wbtcAmountInFullTokens = - (BigInt(wbtcGap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) + const rethAmountInFullTokens = + (BigInt(rethGap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) await supply(wstethWhale, wsteth, wstethAmountInFullTokens * BigInt(10 ** 18)) await insistOnExecution(() => capAutomator.exec(wsteth)) await withdraw(wstethWhale, wsteth, wstethAmountInFullTokens * BigInt(10 ** 18)) - await supply(wbtcWhale, wbtc, wbtcAmountInFullTokens * BigInt(10 ** 8)) + await supply(rethWhale, reth, rethAmountInFullTokens * BigInt(10 ** 18)) const { result } = await capAutomatorW3F.run('onRun', { userArgs: { ...userArgs, threshold } }) @@ -277,10 +277,10 @@ describe('CapAutomator', function () { expect(callData[0].data).to.equal(formatExecSupplyCallData(wsteth)) expect(callData[1].to).to.equal(addresses.mainnet.capAutomator) - expect(callData[1].data).to.equal(formatExecSupplyCallData(wbtc)) + expect(callData[1].data).to.equal(formatExecSupplyCallData(reth)) const wstethSupplyCapBefore = BigInt((await protocolDataProvider.getReserveCaps(wsteth)).supplyCap) - const wbtcSupplyCapBefore = BigInt((await protocolDataProvider.getReserveCaps(wbtc)).supplyCap) + const rethSupplyCapBefore = BigInt((await protocolDataProvider.getReserveCaps(reth)).supplyCap) await Promise.all( callData.map(async (txData) => { @@ -294,10 +294,10 @@ describe('CapAutomator', function () { ) const wstethSupplyCapAfter = BigInt((await protocolDataProvider.getReserveCaps(wsteth)).supplyCap) - const wbtcSupplyCapAfter = BigInt((await protocolDataProvider.getReserveCaps(wbtc)).supplyCap) + const rethSupplyCapAfter = BigInt((await protocolDataProvider.getReserveCaps(reth)).supplyCap) expect(wstethSupplyCapAfter).to.equal(wstethSupplyCapBefore - wstethAmountInFullTokens) - expect(wbtcSupplyCapAfter).to.equal(wbtcSupplyCapBefore + wbtcAmountInFullTokens) + expect(rethSupplyCapAfter).to.equal(rethSupplyCapBefore + rethAmountInFullTokens) }) }) }) @@ -306,9 +306,9 @@ describe('CapAutomator', function () { describe('execBorrow', () => { beforeEach(async () => { await supply(wstethWhale, wsteth, BigInt(40000) * BigInt(10 ** 18)) - await supply(wbtcWhale, wbtc, BigInt(400) * BigInt(10 ** 8)) + await supply(rethWhale, reth, BigInt(400) * BigInt(10 ** 18)) await insistOnExecution(() => capAutomator.execSupply(wsteth)) - await insistOnExecution(() => capAutomator.execSupply(wbtc)) + await insistOnExecution(() => capAutomator.execSupply(reth)) await mine(2, { interval: 24 * 60 * 60 }) }) @@ -326,7 +326,7 @@ describe('CapAutomator', function () { const amountInFullTokens = (BigInt(gap) * BigInt(percentageOfTheGapTooSmallToTrigger)) / BigInt(100) // borrowing only 1/4 of the full amount - await borrow(wbtcWhale, wsteth, (amountInFullTokens * BigInt(10 ** 8)) / BigInt(4)) + await borrow(rethWhale, wsteth, (amountInFullTokens * BigInt(10 ** 18)) / BigInt(4)) const { result } = await capAutomatorW3F.run('onRun', { userArgs: { ...userArgs, threshold } }) @@ -342,7 +342,7 @@ describe('CapAutomator', function () { const amountInFullTokens = (BigInt(gap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) // borrowing only 1/4 of the full borrow amount - await borrow(wbtcWhale, wsteth, (amountInFullTokens * BigInt(10 ** 18)) / BigInt(4)) + await borrow(rethWhale, wsteth, (amountInFullTokens * BigInt(10 ** 18)) / BigInt(4)) const { result: negativeResult } = await capAutomatorW3F.run('onRun', { userArgs: { ...userArgs, threshold }, @@ -351,7 +351,7 @@ describe('CapAutomator', function () { expect(negativeResult.canExec).to.equal(false) // borrowing remaining of the full supply amount - await borrow(wbtcWhale, wsteth, (amountInFullTokens * BigInt(10 ** 18) * BigInt(3)) / BigInt(4)) + await borrow(rethWhale, wsteth, (amountInFullTokens * BigInt(10 ** 18) * BigInt(3)) / BigInt(4)) const { result: positiveResult } = await capAutomatorW3F.run('onRun', { userArgs: { ...userArgs, threshold }, @@ -391,11 +391,11 @@ describe('CapAutomator', function () { const amountInFullTokens = (BigInt(gap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) // borrowing only 1/4 of the full borrow amount - await borrow(wbtcWhale, wsteth, amountInFullTokens * BigInt(10 ** 18)) + await borrow(rethWhale, wsteth, amountInFullTokens * BigInt(10 ** 18)) await insistOnExecution(() => capAutomator.exec(wsteth)) - await repay(wbtcWhale, wsteth, amountInFullTokens * BigInt(10 ** 18)) + await repay(rethWhale, wsteth, amountInFullTokens * BigInt(10 ** 18)) const { result: positiveResult } = await capAutomatorW3F.run('onRun', { userArgs: { ...userArgs, threshold }, @@ -442,7 +442,7 @@ describe('CapAutomator', function () { await insistOnExecution(() => capAutomator.exec(weth)) await repay(wstethWhale, weth, wethAmountInFullTokens * BigInt(10 ** 18)) - await borrow(wbtcWhale, wsteth, wstethAmountInFullTokens * BigInt(10 ** 18)) + await borrow(rethWhale, wsteth, wstethAmountInFullTokens * BigInt(10 ** 18)) const { result } = await capAutomatorW3F.run('onRun', { userArgs: { ...userArgs, threshold } }) @@ -509,11 +509,11 @@ describe('CapAutomator', function () { const borrowAmountInFullTokens = (BigInt(borrowGap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) - await supply(wbtcWhale, wbtc, BigInt(400) * BigInt(10 ** 8)) - await insistOnExecution(() => capAutomator.execSupply(wbtc)) + await supply(rethWhale, reth, BigInt(400) * BigInt(10 ** 18)) + await insistOnExecution(() => capAutomator.execSupply(reth)) await supply(wstethWhale, wsteth, supplyAmountInFullTokens * BigInt(10 ** 18)) - await borrow(wbtcWhale, wsteth, borrowAmountInFullTokens * BigInt(10 ** 18)) + await borrow(rethWhale, wsteth, borrowAmountInFullTokens * BigInt(10 ** 18)) const { result: positiveResult } = await capAutomatorW3F.run('onRun', { userArgs: { ...userArgs, threshold }, @@ -559,15 +559,15 @@ describe('CapAutomator', function () { const borrowAmountInFullTokens = (BigInt(borrowGap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) - await supply(wbtcWhale, wbtc, BigInt(400) * BigInt(10 ** 8)) - await insistOnExecution(() => capAutomator.execSupply(wbtc)) + await supply(rethWhale, reth, BigInt(400) * BigInt(10 ** 18)) + await insistOnExecution(() => capAutomator.execSupply(reth)) await supply(wstethWhale, wsteth, supplyAmountInFullTokens * BigInt(10 ** 18)) - await borrow(wbtcWhale, wsteth, borrowAmountInFullTokens * BigInt(10 ** 18)) + await borrow(rethWhale, wsteth, borrowAmountInFullTokens * BigInt(10 ** 18)) await insistOnExecution(() => capAutomator.exec(wsteth)) await withdraw(wstethWhale, wsteth, supplyAmountInFullTokens * BigInt(10 ** 18)) - await repay(wbtcWhale, wsteth, borrowAmountInFullTokens * BigInt(10 ** 18)) + await repay(rethWhale, wsteth, borrowAmountInFullTokens * BigInt(10 ** 18)) const { result: positiveResult } = await capAutomatorW3F.run('onRun', { userArgs: { ...userArgs, threshold }, @@ -613,19 +613,19 @@ describe('CapAutomator', function () { const wstethBorrowAmountInFullTokens = (BigInt(wstethBorrowGap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) - const { gap: wbtcSupplyGap } = await capAutomator.supplyCapConfigs(wbtc) - const { gap: wbtcBorrowGap } = await capAutomator.borrowCapConfigs(wbtc) + const { gap: rethSupplyGap } = await capAutomator.supplyCapConfigs(reth) + const { gap: rethBorrowGap } = await capAutomator.borrowCapConfigs(reth) - const wbtcSupplyAmountInFullTokens = - (BigInt(wbtcSupplyGap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) - const wbtcBorrowAmountInFullTokens = - (BigInt(wbtcBorrowGap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) + const rethSupplyAmountInFullTokens = + (BigInt(rethSupplyGap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) + const rethBorrowAmountInFullTokens = + (BigInt(rethBorrowGap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) await supply(wstethWhale, wsteth, wstethSupplyAmountInFullTokens * BigInt(10 ** 18)) - await supply(wbtcWhale, wbtc, wbtcSupplyAmountInFullTokens * BigInt(10 ** 8)) + await supply(rethWhale, reth, rethSupplyAmountInFullTokens * BigInt(10 ** 18)) - await borrow(wbtcWhale, wsteth, wstethBorrowAmountInFullTokens * BigInt(10 ** 18)) - await borrow(wstethWhale, wbtc, wbtcBorrowAmountInFullTokens * BigInt(10 ** 8)) + await borrow(rethWhale, wsteth, wstethBorrowAmountInFullTokens * BigInt(10 ** 18)) + await borrow(wstethWhale, reth, rethBorrowAmountInFullTokens * BigInt(10 ** 18)) const { result: positiveResult } = await capAutomatorW3F.run('onRun', { userArgs: { ...userArgs, threshold }, @@ -643,13 +643,13 @@ describe('CapAutomator', function () { expect(callData[0].to).to.equal(addresses.mainnet.capAutomator) expect(callData[0].data).to.equal(formatExecCallData(wsteth)) expect(callData[1].to).to.equal(addresses.mainnet.capAutomator) - expect(callData[1].data).to.equal(formatExecCallData(wbtc)) + expect(callData[1].data).to.equal(formatExecCallData(reth)) const wstethSupplyCapBefore = BigInt((await protocolDataProvider.getReserveCaps(wsteth)).supplyCap) const wstethBorrowCapBefore = BigInt((await protocolDataProvider.getReserveCaps(wsteth)).borrowCap) - const wbtcSupplyCapBefore = BigInt((await protocolDataProvider.getReserveCaps(wbtc)).supplyCap) - const wbtcBorrowCapBefore = BigInt((await protocolDataProvider.getReserveCaps(wbtc)).borrowCap) + const rethSupplyCapBefore = BigInt((await protocolDataProvider.getReserveCaps(reth)).supplyCap) + const rethBorrowCapBefore = BigInt((await protocolDataProvider.getReserveCaps(reth)).borrowCap) await Promise.all( callData.map(async (txData) => { @@ -665,14 +665,14 @@ describe('CapAutomator', function () { const wstethSupplyCapAfter = BigInt((await protocolDataProvider.getReserveCaps(wsteth)).supplyCap) const wstethBorrowCapAfter = BigInt((await protocolDataProvider.getReserveCaps(wsteth)).borrowCap) - const wbtcSupplyCapAfter = BigInt((await protocolDataProvider.getReserveCaps(wbtc)).supplyCap) - const wbtcBorrowCapAfter = BigInt((await protocolDataProvider.getReserveCaps(wbtc)).borrowCap) + const rethSupplyCapAfter = BigInt((await protocolDataProvider.getReserveCaps(reth)).supplyCap) + const rethBorrowCapAfter = BigInt((await protocolDataProvider.getReserveCaps(reth)).borrowCap) expect(wstethSupplyCapAfter).to.equal(wstethSupplyCapBefore + wstethSupplyAmountInFullTokens) expect(wstethBorrowCapAfter).to.equal(wstethBorrowCapBefore + wstethBorrowAmountInFullTokens) - expect(wbtcSupplyCapAfter).to.equal(wbtcSupplyCapBefore + wbtcSupplyAmountInFullTokens) - expect(wbtcBorrowCapAfter).to.equal(wbtcBorrowCapBefore + wbtcBorrowAmountInFullTokens) + expect(rethSupplyCapAfter).to.equal(rethSupplyCapBefore + rethSupplyAmountInFullTokens) + expect(rethBorrowCapAfter).to.equal(rethBorrowCapBefore + rethBorrowAmountInFullTokens) }) it('all types of operations are required', async () => { @@ -686,20 +686,20 @@ describe('CapAutomator', function () { const wstethBorrowAmountInFullTokens = (BigInt(wstethBorrowGap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) - const { gap: wbtcSupplyGap } = await capAutomator.supplyCapConfigs(wbtc) + const { gap: rethSupplyGap } = await capAutomator.supplyCapConfigs(reth) - const wbtcSupplyAmountInFullTokens = - (BigInt(wbtcSupplyGap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) + const rethSupplyAmountInFullTokens = + (BigInt(rethSupplyGap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) const { gap: wethBorrowGap } = await capAutomator.borrowCapConfigs(weth) const wethBorrowAmountInFullTokens = (BigInt(wethBorrowGap) * BigInt(percentageOfTheGapNeededForTrigger)) / BigInt(100) - await supply(wbtcWhale, wbtc, wbtcSupplyAmountInFullTokens * BigInt(10 ** 8)) + await supply(rethWhale, reth, rethSupplyAmountInFullTokens * BigInt(10 ** 18)) await supply(wstethWhale, wsteth, wstethSupplyAmountInFullTokens * BigInt(10 ** 18)) - await borrow(wbtcWhale, wsteth, wstethBorrowAmountInFullTokens * BigInt(10 ** 18)) + await borrow(rethWhale, wsteth, wstethBorrowAmountInFullTokens * BigInt(10 ** 18)) await borrow(wstethWhale, weth, wethBorrowAmountInFullTokens * BigInt(10 ** 18)) const { result: positiveResult } = await capAutomatorW3F.run('onRun', { @@ -720,12 +720,12 @@ describe('CapAutomator', function () { expect(callData[1].to).to.equal(addresses.mainnet.capAutomator) expect(callData[1].data).to.equal(formatExecCallData(wsteth)) expect(callData[2].to).to.equal(addresses.mainnet.capAutomator) - expect(callData[2].data).to.equal(formatExecSupplyCallData(wbtc)) + expect(callData[2].data).to.equal(formatExecSupplyCallData(reth)) const wstethSupplyCapBefore = BigInt((await protocolDataProvider.getReserveCaps(wsteth)).supplyCap) const wstethBorrowCapBefore = BigInt((await protocolDataProvider.getReserveCaps(wsteth)).borrowCap) - const wbtcSupplyCapBefore = BigInt((await protocolDataProvider.getReserveCaps(wbtc)).supplyCap) + const rethSupplyCapBefore = BigInt((await protocolDataProvider.getReserveCaps(reth)).supplyCap) const wethBorrowCapBefore = BigInt((await protocolDataProvider.getReserveCaps(weth)).borrowCap) @@ -743,14 +743,14 @@ describe('CapAutomator', function () { const wstethSupplyCapAfter = BigInt((await protocolDataProvider.getReserveCaps(wsteth)).supplyCap) const wstethBorrowCapAfter = BigInt((await protocolDataProvider.getReserveCaps(wsteth)).borrowCap) - const wbtcSupplyCapAfter = BigInt((await protocolDataProvider.getReserveCaps(wbtc)).supplyCap) + const rethSupplyCapAfter = BigInt((await protocolDataProvider.getReserveCaps(reth)).supplyCap) const wethBorrowCapAfter = BigInt((await protocolDataProvider.getReserveCaps(weth)).borrowCap) expect(wstethSupplyCapAfter).to.equal(wstethSupplyCapBefore + wstethSupplyAmountInFullTokens) expect(wstethBorrowCapAfter).to.equal(wstethBorrowCapBefore + wstethBorrowAmountInFullTokens) - expect(wbtcSupplyCapAfter).to.equal(wbtcSupplyCapBefore + wbtcSupplyAmountInFullTokens) + expect(rethSupplyCapAfter).to.equal(rethSupplyCapBefore + rethSupplyAmountInFullTokens) // After initial cap setting, when fast forwarding time, some interest is accrued and added to capAfter expect(Number(wethBorrowCapAfter)).to.be.greaterThanOrEqual( diff --git a/test/web3-functions/mainnet/d3m-ticker.test.ts b/test/web3-functions/mainnet/d3m-ticker.test.ts index b832aa0..f43d3ac 100644 --- a/test/web3-functions/mainnet/d3m-ticker.test.ts +++ b/test/web3-functions/mainnet/d3m-ticker.test.ts @@ -6,7 +6,7 @@ import { Web3FunctionResultCallData } from '@gelatonetwork/web3-functions-sdk/*' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' import { SnapshotRestorer, takeSnapshot } from '@nomicfoundation/hardhat-network-helpers' -import { d3mHubAbi, multicallAbi, vatAbi } from '../../../abis' +import { d3mHubAbi, vatAbi } from '../../../abis' import { addresses, ilk } from '../../../utils' const { w3f, ethers } = hre @@ -27,7 +27,7 @@ describe('d3mTicker', function () { let threshold: string const userArgs = { threshold: 0, performGasCheck: false, sendSlackMessages: false } - const artDifferenceOnTheFork = BigInt('43108457969557943776482696') + const artDifferenceOnTheFork = BigInt('8446563830271303300236973') before(async () => { cleanStateRestorer = await takeSnapshot() diff --git a/test/web3-functions/mainnet/xchain-oracle-ticker.test.ts b/test/web3-functions/mainnet/xchain-oracle-ticker.test.ts index 72f590c..6af0e11 100644 --- a/test/web3-functions/mainnet/xchain-oracle-ticker.test.ts +++ b/test/web3-functions/mainnet/xchain-oracle-ticker.test.ts @@ -29,6 +29,7 @@ describe('xchainOracleTicker', function () { let pot: Contract let optimismStyleForwarderAddresses: string[] + let updatedOptimismStyleForwarderAddresses: string[] let arbitrumStyleForwarderAddresses: string[] let allForwarderAddresses: string[] @@ -48,8 +49,13 @@ describe('xchainOracleTicker', function () { pauseProxy = await ethers.getSigner(addresses.mainnet.pauseProxy) optimismStyleForwarderAddresses = Object.values(addresses.mainnet.dsrForwarders.optimismStyle) + updatedOptimismStyleForwarderAddresses = Object.values(addresses.mainnet.dsrForwarders.updatedOptimismStyle) arbitrumStyleForwarderAddresses = Object.values(addresses.mainnet.dsrForwarders.arbitrumStyle) - allForwarderAddresses = [...optimismStyleForwarderAddresses, ...arbitrumStyleForwarderAddresses] + allForwarderAddresses = [ + ...optimismStyleForwarderAddresses, + ...updatedOptimismStyleForwarderAddresses, + ...arbitrumStyleForwarderAddresses, + ] pot = new Contract(addresses.mainnet.pot, potAbi, pauseProxy) forwarderInterface = new utils.Interface(forwarderAbi) @@ -76,7 +82,7 @@ describe('xchainOracleTicker', function () { !result.canExec && expect(result.message).to.equal('Pot data refresh not needed') }) - it('one refresh is needed (stale rho)', async () => { + it('some refreshes are needed (stale rho)', async () => { const rhoDeltas = await Promise.all( allForwarderAddresses.map(async (forwarderAddress) => { const forwarder = new Contract(forwarderAddress, forwarderInterface, reader) @@ -101,25 +107,26 @@ describe('xchainOracleTicker', function () { } const callData = result.callData as Web3FunctionResultCallData[] - expect(callData).to.have.length(1) + expect(callData).to.have.length(3) - expect(callData[0].to).to.equal(allForwarderAddresses[rhoDeltas.indexOf(largestRhoDelta)]) - - const forwarder = new Contract(callData[0].to, forwarderInterface, reader) const potRho = (await pot.rho()).toNumber() - const rhoBefore = (await forwarder.getLastSeenPotData()).rho - await insistOnExecution(() => - keeper.sendTransaction({ - to: callData[0].to, - data: callData[0].data, - }), - ) + for (const data of callData) { + const forwarder = new Contract(data.to, forwarderInterface, reader) + const rhoBefore = (await forwarder.getLastSeenPotData()).rho + + await insistOnExecution(() => + keeper.sendTransaction({ + to: data.to, + data: data.data, + }), + ) - const rhoAfter = (await forwarder.getLastSeenPotData()).rho + const rhoAfter = (await forwarder.getLastSeenPotData()).rho - expect(rhoBefore).to.be.lessThan(potRho) - expect(rhoAfter).to.equal(potRho) + expect(rhoBefore).to.be.lessThan(potRho) + expect(rhoAfter).to.equal(potRho) + } }) it('all refreshes are needed (stale rho)', async () => { diff --git a/utils/addresses.ts b/utils/addresses.ts index 5ba0437..30a7571 100644 --- a/utils/addresses.ts +++ b/utils/addresses.ts @@ -11,6 +11,7 @@ export const addresses = { pool: '0xC13e21B648A5Ee794902342038FF3aDAB66BE987', pot: '0x197E90f9FAD81970bA7976f33CbD77088E5D7cf7', protocolDataProvider: '0xFc21d6d146E6086B8359705C8b28512a983db0cb', + reth: '0xae78736Cd615f374D3085123A210448E74Fc6393', vat: '0x35D1b3F3D7966A1DFe207aa4514C12a259A0492B', wbtc: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', weth: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', @@ -23,6 +24,9 @@ export const addresses = { base: '0x8Ed551D485701fe489c215E13E42F6fc59563e0e', optimism: '0x4042127DecC0cF7cc0966791abebf7F76294DeF3', }, + updatedOptimismStyle: { + worldChain: '0xA34437dAAE56A7CC6DC757048933D7777b3e547B', + }, }, priceSources: { wbtcBtc: '0xfdFD9C85aD200c506Cf9e21F1FD8dd01932FBB23', diff --git a/web3-functions/xchain-oracle-ticker/index.ts b/web3-functions/xchain-oracle-ticker/index.ts index 7225ac6..bf7d990 100644 --- a/web3-functions/xchain-oracle-ticker/index.ts +++ b/web3-functions/xchain-oracle-ticker/index.ts @@ -3,7 +3,7 @@ import { Web3Function, Web3FunctionContext } from '@gelatonetwork/web3-functions import axios from 'axios' import { providers, utils } from 'ethers' -import { forwarderAbi, forwarderArbitrumAbi, multicallAbi, potAbi } from '../../abis' +import { forwarderAbi, forwarderArbitrumAbi, forwarderUpdatedAbi, multicallAbi, potAbi } from '../../abis' import { addresses, formatChi, formatDsr, formatTimestamp, sendMessageToSlack } from '../../utils' const arbitrumDomainUrls: Record = { @@ -36,6 +36,7 @@ Feed refresh to be sent to:${messageBits.join('')}\`\`\`` const optimismStyleForwarderAddresses = addresses.mainnet.dsrForwarders.optimismStyle const arbitrumStyleForwarderAddresses = addresses.mainnet.dsrForwarders.arbitrumStyle + const updatedOptimismStyleForwarderAddresses = addresses.mainnet.dsrForwarders.updatedOptimismStyle const multicall = new Contract(addresses.mainnet.multicall, multicallAbi, provider) const pot = new Contract(addresses.mainnet.pot, potAbi, provider) @@ -53,6 +54,7 @@ Feed refresh to be sent to:${messageBits.join('')}\`\`\`` for (const forwarderAddress of [ ...Object.values(optimismStyleForwarderAddresses), ...Object.values(arbitrumStyleForwarderAddresses), + ...Object.values(updatedOptimismStyleForwarderAddresses), ]) { multicallCalls.push({ target: forwarderAddress, @@ -86,6 +88,33 @@ Feed refresh to be sent to:${messageBits.join('')}\`\`\`` } } + const updatedForwarderInterface = new utils.Interface(forwarderUpdatedAbi) + + for (const [domain, forwarderAddress] of Object.entries(updatedOptimismStyleForwarderAddresses)) { + const lastForwardedPotData = updatedForwarderInterface.decodeFunctionResult( + 'getLastSeenPotData', + multicallResults[0], + )[0] + + multicallResults = multicallResults.slice(1) + + const outdatedDsr = BigInt(lastForwardedPotData.dsr) != BigInt(currentDsr) + const staleRho = BigInt(latestTimestamp) > BigInt(lastForwardedPotData.rho) + maxDelta + + if (outdatedDsr || staleRho) { + callsToExecute.push({ + to: forwarderAddress, + data: updatedForwarderInterface.encodeFunctionData('refresh', [gasLimit]), + }) + + const refreshReason = outdatedDsr + ? `outdated dsr: ${formatDsr(lastForwardedPotData.dsr.toString())}` + : `stale rho: ${formatTimestamp(Number(lastForwardedPotData.rho))}` + + slackMessageBits.push(generateSlackMessageBit(domain, refreshReason)) + } + } + const arbitrumForwarderInterface = new utils.Interface(forwarderArbitrumAbi) for (const [domain, forwarderAddress] of Object.entries(arbitrumStyleForwarderAddresses)) {