From 6d95c4355471aeb3e06ed724e3469fd5c1eda74a Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Tue, 3 Dec 2024 15:24:50 +0100 Subject: [PATCH] add transfers to upgrade tests --- contracts/deploy/base/021_upgrade_oeth.js | 2 +- contracts/deploy/mainnet/110_oeth_upgrade.js | 2 +- contracts/test/helpers.js | 45 ++++++++++++++++++ contracts/test/token/README.md | 47 ++++++++++++++++++- contracts/test/token/oeth.base.fork-test.js | 14 ++++-- .../test/token/oeth.mainnet.fork-test.js | 15 ++++-- .../test/token/ousd.mainnet.fork-test.js | 15 ++++-- 7 files changed, 127 insertions(+), 13 deletions(-) diff --git a/contracts/deploy/base/021_upgrade_oeth.js b/contracts/deploy/base/021_upgrade_oeth.js index f6a9d6751d..e1e013e635 100644 --- a/contracts/deploy/base/021_upgrade_oeth.js +++ b/contracts/deploy/base/021_upgrade_oeth.js @@ -4,7 +4,7 @@ const { deployWithConfirmation } = require("../../utils/deploy"); module.exports = deployOnBaseWithGuardian( { deployName: "021_upgrade_oeth", - forceSkip: true + forceSkip: false }, async ({ ethers }) => { const dOETHb = await deployWithConfirmation("OETHBase"); diff --git a/contracts/deploy/mainnet/110_oeth_upgrade.js b/contracts/deploy/mainnet/110_oeth_upgrade.js index 5a6d53bf12..73701417fe 100644 --- a/contracts/deploy/mainnet/110_oeth_upgrade.js +++ b/contracts/deploy/mainnet/110_oeth_upgrade.js @@ -4,7 +4,7 @@ module.exports = deploymentWithGovernanceProposal( { deployName: "110_oeth_upgrade", forceDeploy: false, - forceSkip: true, + forceSkip: false, reduceQueueTime: true, deployerIsProposer: false, proposalId: "", diff --git a/contracts/test/helpers.js b/contracts/test/helpers.js index 3d25168002..04785362dc 100644 --- a/contracts/test/helpers.js +++ b/contracts/test/helpers.js @@ -5,6 +5,7 @@ const { parseUnits, formatUnits, keccak256, toUtf8Bytes } = const { BigNumber } = require("ethers"); const addresses = require("../utils/addresses"); +const { impersonateAndFund } = require("../utils/signers"); const { decimalsFor, units } = require("../utils/units"); const fs = require('fs'); @@ -788,6 +789,49 @@ async function addActualBalancesToSquidData(squidDataCsvFile, outputFileName, to fs.writeFileSync(outputFileName, csvContent); } +async function testTransfersOnTokenContract(balancesFile, upgradedTokenContract) { + // CSV file in format account, squidBalance, onChainBalance + const data = fs.readFileSync(balancesFile, "utf8").split('\n'); + let transferBalanceMissmatches = 0; + for (let i = 1; i < data.length; i++) { + const [accountPrevious,,] = data[i-1].split(','); + const [account,,] = data[i].split(','); + + const balanceSender = await upgradedTokenContract.balanceOf(account); + const balanceReceiver = await upgradedTokenContract.balanceOf(accountPrevious); + + if (i % 50 == 0) { + console.log(`Validated transfers of ${i + 1} accounts`); + } + + if (balanceSender.lte(BigNumber.from(2))) { + // skip small balances + continue; + } + + const accountSigner = await impersonateAndFund(account); + // 1/2 balance + const balanceToTransfer = balanceSender.div(BigNumber.from("2")); + await upgradedTokenContract + .connect(accountSigner) + .transfer(accountPrevious, balanceToTransfer); + + + const balanceSenderAfter = await upgradedTokenContract.balanceOf(account); + const balanceReceiverAfter = await upgradedTokenContract.balanceOf(accountPrevious); + + if (!balanceSender.sub(balanceToTransfer).eq(balanceSenderAfter)) { + transferBalanceMissmatches += 1; + console.log(`Balance miss match ${account} expected to have ${balanceSender.sub(balanceToTransfer).toString(10)} actually has ${balanceSenderAfter.toString(10)}`) + } + if (!balanceReceiver.add(balanceToTransfer).eq(balanceReceiverAfter)) { + transferBalanceMissmatches += 1; + console.log(`Balance miss match ${accountPrevious} expected to have ${balanceReceiver.add(balanceToTransfer).toString(10)} actually has ${balanceReceiverAfter.toString(10)}`) + } + } + console.log(`Accounts with unexpected balances: ${transferBalanceMissmatches}`) +} + async function compareUpgradedContractBalances(balancesFile, upgradedTokenContract) { // CSV file in format account, squidBalance, onChainBalance const data = fs.readFileSync(balancesFile, "utf8").split('\n'); @@ -911,4 +955,5 @@ module.exports = { differenceInStrategyBalance, addActualBalancesToSquidData, compareUpgradedContractBalances, + testTransfersOnTokenContract, }; diff --git a/contracts/test/token/README.md b/contracts/test/token/README.md index 8aef492b79..99098d890f 100644 --- a/contracts/test/token/README.md +++ b/contracts/test/token/README.md @@ -4,6 +4,7 @@ The purpose of upgrade tests is to verify that the token contract upgrades will 1. fetch all accounts from Sub Squid which have positive token balance 2. run a forked node on the same block number and add actual/precise on-chain token balances to those addresses (there are errors / deviations in SubSquid) 3. run a forked node with token contracts upgraded and compare balances +4. run a forked node with token contracts upgraded and validate transfer amounts ## 1. Fetch data from SubSquid @@ -13,7 +14,7 @@ yarn run fetch-pre-upgrade ``` This will execute the `scripts/yield-delegation/fetchAllAddresses.js` which fetches the accounts with positive balances and their SubSquid balances. This script should create files: `oethBalances.csv`, `ousdBalances.csv`, `soethBalances.csv`. They are all of format `address, token_balance, block_number` -## 2. & 3. Supplement account with pre-upgrade on-chain data and verify with post upgrade balances +## 2. & 3 & 4. Supplement account with pre-upgrade on-chain data and verify with post upgrade balances Since this is a 1 off test there is less automation and more manual work required. Open the 3 token upgrade file: - contracts/deploy/mainnet/109_ousd_upgrade.js @@ -58,6 +59,20 @@ After the script executes there should be 0 accounts with not matching balances: Accounts with difference balances: 0 ``` +#### Verify post-upgrade token transfers +Keep settings in `contracts/deploy/mainnet/109_ousd_upgrade.js` to `forceSkip=false` +Open test file (`contracts/test/token/ousd.mainnet.fork-test.js`) and remove the previous `.only` modifier and set the `.only` modifier to `Execute transfer and inspect balances` test. + +run +``` +yarn run test:fork +``` + +After the script executes there should be 0 accounts with not matching balances: +``` +Accounts with difference balances: 0 +``` + ### OETH verification #### Add pre-upgrade OETH token balances run @@ -89,6 +104,20 @@ After the script executes there should be 0 accounts with not matching balances: Accounts with difference balances: 0 ``` +#### Verify post-upgrade token balances +Keep settings in `contracts/deploy/mainnet/110_oeth_upgrade.js` to `forceSkip=false` +Open test file (`contracts/test/token/oeth.mainnet.fork-test.js`) and remove the previous `.only` modifier and set the `.only` modifier to `Execute transfer and inspect balances` test. + +run +``` +yarn run test:fork +``` + +After the script executes there should be 0 accounts with not matching balances: +``` +Accounts with difference balances: 0 +``` + ### Super OETH verification #### Add pre-upgrade Super OETH token balances run @@ -118,4 +147,18 @@ yarn run test:base-fork After the script executes there should be 0 accounts with not matching balances: ``` Accounts with difference balances: 0 -``` \ No newline at end of file +``` + +#### Verify post-upgrade token balances +Keep settings in `contracts/deploy/base/021_upgrade_oeth.js` to `forceSkip=false` +Open test file (`contracts/test/token/oeth.base.fork-test.js`) and remove the previous `.only` modifier and set the `.only` modifier to `Execute transfer and inspect balances` test. + +run +``` +yarn run test:fork +``` + +After the script executes there should be 0 accounts with not matching balances: +``` +Accounts with difference balances: 0 +``` diff --git a/contracts/test/token/oeth.base.fork-test.js b/contracts/test/token/oeth.base.fork-test.js index 460dab09dd..12d00f99eb 100644 --- a/contracts/test/token/oeth.base.fork-test.js +++ b/contracts/test/token/oeth.base.fork-test.js @@ -2,7 +2,11 @@ const { createFixtureLoader } = require("../_fixture"); const { defaultBaseFixture } = require("../_fixture-base"); const { expect } = require("chai"); const addresses = require("../../utils/addresses"); -const { addActualBalancesToSquidData, compareUpgradedContractBalances } = require("./../helpers"); +const { + addActualBalancesToSquidData, + compareUpgradedContractBalances, + testTransfersOnTokenContract +} = require("./../helpers"); const baseFixture = createFixtureLoader(defaultBaseFixture); @@ -40,7 +44,6 @@ describe("ForkTest: OETHb", function () { // has the actual balances on chain before the contract upgrade it("Fetch the actual on chain data", async () => { const { oethb } = fixture; - this.timeout(1000000000); await addActualBalancesToSquidData('./soethBalances.csv', './soethBalancesCombined.csv', oethb); }); @@ -48,7 +51,12 @@ describe("ForkTest: OETHb", function () { // test can be compared to the balances after the upgrade it("Compare the data before and after the upgrade", async () => { const { oethb } = fixture; - this.timeout(1000000000); await compareUpgradedContractBalances('./soethBalancesCombined.csv', oethb); }); + + // execute transfer and compare balances + it("Execute transfer and inspect balances", async () => { + const { oethb } = fixture; + await testTransfersOnTokenContract('./soethBalancesCombined.csv', oethb); + }); }); diff --git a/contracts/test/token/oeth.mainnet.fork-test.js b/contracts/test/token/oeth.mainnet.fork-test.js index e356294cdf..268a94a912 100644 --- a/contracts/test/token/oeth.mainnet.fork-test.js +++ b/contracts/test/token/oeth.mainnet.fork-test.js @@ -1,7 +1,12 @@ const { expect } = require("chai"); const { loadDefaultFixture } = require("./../_fixture"); -const { isCI, addActualBalancesToSquidData, compareUpgradedContractBalances } = require("./../helpers"); +const { + isCI, + addActualBalancesToSquidData, + compareUpgradedContractBalances, + testTransfersOnTokenContract +} = require("./../helpers"); /** * Regarding hardcoded addresses: @@ -42,7 +47,6 @@ describe("ForkTest: OETH", function () { // has the actual balances on chain before the contract upgrade it("Fetch the actual on chain data", async () => { const { oeth } = fixture; - this.timeout(1000000000); await addActualBalancesToSquidData('./oethBalances.csv', './oethBalancesCombined.csv', oeth); }); @@ -50,8 +54,13 @@ describe("ForkTest: OETH", function () { // test can be compared to the balances after the upgrade it("Compare the data before and after the upgrade", async () => { const { oeth } = fixture; - this.timeout(1000000000); await compareUpgradedContractBalances('./oethBalancesCombined.csv', oeth); }); + + // execute transfer and compare balances + it("Execute transfer and inspect balances", async () => { + const { oeth } = fixture; + await testTransfersOnTokenContract('./oethBalancesCombined.csv', oeth); + }); }); }); diff --git a/contracts/test/token/ousd.mainnet.fork-test.js b/contracts/test/token/ousd.mainnet.fork-test.js index 39a9fb9a2d..928338ac5c 100644 --- a/contracts/test/token/ousd.mainnet.fork-test.js +++ b/contracts/test/token/ousd.mainnet.fork-test.js @@ -1,5 +1,10 @@ const { loadDefaultFixture } = require("./../_fixture"); -const { isCI, addActualBalancesToSquidData, compareUpgradedContractBalances } = require("./../helpers"); +const { + isCI, + addActualBalancesToSquidData, + compareUpgradedContractBalances, + testTransfersOnTokenContract +} = require("./../helpers"); /** * Regarding hardcoded addresses: @@ -31,7 +36,6 @@ describe("ForkTest: OUSD", function () { // has the actual balances on chain before the contract upgrade it("Fetch the actual on chain data", async () => { const { ousd } = fixture; - this.timeout(1000000000); await addActualBalancesToSquidData('./ousdBalances.csv', './ousdBalancesCombined.csv', ousd); }); @@ -39,8 +43,13 @@ describe("ForkTest: OUSD", function () { // test can be compared to the balances after the upgrade it("Compare the data before and after the upgrade", async () => { const { ousd } = fixture; - this.timeout(1000000000); await compareUpgradedContractBalances('./ousdBalancesCombined.csv', ousd); }); + + // execute transfer and compare balances + it("Execute transfer and inspect balances", async () => { + const { ousd } = fixture; + await testTransfersOnTokenContract('./ousdBalancesCombined.csv', ousd); + }); }); });