From cca9b60e3489ab856b15f86b49ed1e4234ae94d8 Mon Sep 17 00:00:00 2001 From: Leonardo Massazza Date: Fri, 28 May 2021 23:37:29 -0300 Subject: [PATCH 1/7] ported. Some tests still failing --- .../dual/migrateEscrow.integration.test.js | 453 ++++++++---------- test/integration/utils/escrow.js | 58 +++ 2 files changed, 259 insertions(+), 252 deletions(-) create mode 100644 test/integration/utils/escrow.js diff --git a/test/integration/dual/migrateEscrow.integration.test.js b/test/integration/dual/migrateEscrow.integration.test.js index 09ca86f8ca..63b7ac6c1d 100644 --- a/test/integration/dual/migrateEscrow.integration.test.js +++ b/test/integration/dual/migrateEscrow.integration.test.js @@ -1,307 +1,256 @@ const ethers = require('ethers'); const { assert } = require('../../contracts/common'); const { bootstrapDual } = require('../utils/bootstrap'); +const { appendEscrow } = require('../utils/escrow'); +const { approveIfNeeded } = require('../utils/approve'); describe('migrateEscrow() integration tests (L1, L2)', () => { const ctx = this; bootstrapDual({ ctx }); - const SECOND = 1000; - const MINUTE = SECOND * 60; - const HOUR = MINUTE * 60; - let user; - let SynthetixL1, RewardEscrowV2L1, SynthetixBridgeToOptimism; - let SynthetixL2, RewardEscrowV2L2, SynthetixBridgeToBase; - - let initialEntriesL1; - let initialEscrowedBalanceL1; - let initialEscrowedBalanceL2; - let userNumVestingEntriesL1; - let userNumVestingEntriesL2; - let userEscrowedBalanceL1; - let userEscrowedBalanceL2; - let userVestedAccountBalanceL1; - let userVestedAccountBalanceL2; + let Synthetix, RewardEscrowV2, SynthetixBridgeToOptimism, SynthetixBridgeToBase; + + let initialParametersL1, initialParametersL2; + + const retrieveEscrowParameters = async ({ ctx, user }) => { + const RewardEscrowV2 = ctx.contracts.RewardEscrowV2.connect(user); + + const numberOfEntries = await RewardEscrowV2.nextEntryId(); + const escrowedBalance = await RewardEscrowV2.totalEscrowedBalance(); + const userNumVestingEntries = await RewardEscrowV2.numVestingEntries(user.address); + const userEscrowedBalance = await RewardEscrowV2.totalEscrowedAccountBalance(user.address); + const userVestedAccountBalance = await RewardEscrowV2.totalVestedAccountBalance(user.address); + + return { + numberOfEntries, + escrowedBalance, + userNumVestingEntries, + userEscrowedBalance, + userVestedAccountBalance, + }; + }; before('target contracts and users', () => { - ({ - Synthetix: SynthetixL1, - RewardEscrowV2: RewardEscrowV2L1, - SynthetixBridgeToOptimism, - } = ctx.l1.contracts); - ({ - Synthetix: SynthetixL2, - RewardEscrowV2: RewardEscrowV2L2, - SynthetixBridgeToBase, - } = ctx.l2.contracts); - - user = ctx.l1.users.someUser; + user = ctx.l1.user; }); before('record current escrow state', async () => { - initialEntriesL1 = await RewardEscrowV2L1.nextEntryId(); - initialEscrowedBalanceL1 = await RewardEscrowV2L1.totalEscrowedBalance(); - initialEscrowedBalanceL2 = await RewardEscrowV2L2.totalEscrowedBalance(); - userNumVestingEntriesL1 = await RewardEscrowV2L1.numVestingEntries(user.address); - userNumVestingEntriesL2 = await RewardEscrowV2L2.numVestingEntries(user.address); - userEscrowedBalanceL1 = await RewardEscrowV2L1.totalEscrowedAccountBalance(user.address); - userEscrowedBalanceL2 = await RewardEscrowV2L2.totalEscrowedAccountBalance(user.address); - userVestedAccountBalanceL1 = await RewardEscrowV2L1.totalVestedAccountBalance(user.address); - userVestedAccountBalanceL2 = await RewardEscrowV2L2.totalVestedAccountBalance(user.address); + initialParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1, user }); + initialParametersL2 = await retrieveEscrowParameters({ ctx: ctx.l2, user }); }); - describe('when a user owns enough SNX', () => { - let userBalanceL1; + describe('when the user approves the reward escrow to transfer their SNX', () => { const snxAmount = ethers.utils.parseEther('100'); - before('record current values', async () => { - userBalanceL1 = await SynthetixL1.balanceOf(user.address); + before('approve reward escrow if needed', async () => { + await approveIfNeeded({ + token: Synthetix, + user, + beneficiary: RewardEscrowV2, + amount: snxAmount, + }); }); - before('transfer SNX to the L1 user', async () => { - SynthetixL1 = SynthetixL1.connect(ctx.l1.users.owner); + const escrowNum = 26; + const escrowBatches = 2; + const numExtraEntries = 3; + const totalEntriesCreated = escrowNum * escrowBatches + numExtraEntries; + describe(`when the user creates ${totalEntriesCreated} escrow entries`, () => { + let postParametersL1 = {}; + let escrowEntriesData = {}; + + before('create and append escrow entries', async () => { + escrowEntriesData = await appendEscrow({ + ctx: ctx.l1, + user, + escrowBatches, + numExtraEntries, + escrowNum, + escrowEntryAmount: ethers.constants.One, + }); + }); - const tx = await SynthetixL1.transfer(user.address, snxAmount); - await tx.wait(); - }); + before('grab new states on L1', async () => { + postParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1, user }); + }); - it('updates user balance', async () => { - assert.bnEqual(await SynthetixL1.balanceOf(user.address), userBalanceL1.add(snxAmount)); - }); + it('should update the L1 escrow state', async () => { + assert.bnEqual( + postParametersL1.escrowedBalance, + initialParametersL1.escrowedBalance.add(escrowEntriesData.totalEscrowed) + ); + assert.bnEqual( + postParametersL1.userNumVestingEntries, + initialParametersL1.userNumVestingEntries.add(totalEntriesCreated) + ); + assert.bnEqual( + postParametersL1.userEscrowedBalance, + initialParametersL1.userEscrowedBalance.add(escrowEntriesData.totalEscrowed) + ); + assert.bnEqual( + postParametersL1.userVestedAccountBalance, + initialParametersL1.userVestedAccountBalance + ); + }); - describe('when the user approves the reward escrow to transfer their SNX', () => { - before('approve reward escrow ', async () => { - SynthetixL1 = SynthetixL1.connect(user); + describe('when the user has no outstanding debt on L1', () => { + describe('when the user migrates their escrow', () => { + let migrateEscrowReceipt, migrateEscrowReceiptExtra; + let userBalanceL2; + let totalSupplyL2; + let rewardEscrowBalanceL2; - await SynthetixL1.approve(RewardEscrowV2L1.address, snxAmount); - }); + const importedVestingEntriesEvents = []; - const escrowNum = 26; - const escrowBatches = 2; - const numExtraEntries = 3; - const totalEntriesCreated = escrowNum * escrowBatches + numExtraEntries; - - describe(`when the user creates ${totalEntriesCreated} escrow entries`, () => { - const escrowEntryAmount = ethers.utils.parseEther('1'); - const duration = HOUR; - let currentId; - const batchEscrowAmounts = []; - const userEntryBatch = []; - let totalEscrowed = ethers.constants.Zero; - const extraEntries = []; - let extraEscrowAmount = ethers.constants.Zero; - - before('create and append escrow entries', async () => { - RewardEscrowV2L1 = RewardEscrowV2L1.connect(user); - for (let i = 0; i < escrowBatches; i++) { - batchEscrowAmounts[i] = ethers.constants.Zero; - const userEntries = []; - for (let j = 0; j < escrowNum; j++) { - currentId = await RewardEscrowV2L1.nextEntryId(); - const tx = await RewardEscrowV2L1.createEscrowEntry( - user.address, - escrowEntryAmount, - duration - ); - await tx.wait(); - userEntries[j] = currentId; - batchEscrowAmounts[i] = batchEscrowAmounts[i].add(escrowEntryAmount); + const importedVestingEntriesEventListener = (account, amount, entries, event) => { + if (event && event.event === 'ImportedVestingEntries') { + importedVestingEntriesEvents.push(event); } - userEntryBatch.push(userEntries); - } - - totalEscrowed = batchEscrowAmounts.reduce((a, b) => a.add(b)); - - // this loop creates entries [1-numExtraEntries], e.g. 1,2,3 if numExtraEntries = 3 - for (let i = 0; i < numExtraEntries; i++) { - currentId = await RewardEscrowV2L1.nextEntryId(); - const tx = await RewardEscrowV2L1.createEscrowEntry( - user.address, - escrowEntryAmount, - duration + }; + + before('get L2 contracts', () => { + ({ Synthetix, RewardEscrowV2, SynthetixBridgeToBase } = ctx.l2.contracts); + }); + + before('listen to events on L2', async () => { + SynthetixBridgeToBase.on('ImportedVestingEntries', importedVestingEntriesEventListener); + }); + + before('record current values', async () => { + userBalanceL2 = await Synthetix.balanceOf(user.address); + totalSupplyL2 = await Synthetix.totalSupply(); + rewardEscrowBalanceL2 = await Synthetix.balanceOf(RewardEscrowV2.address); + }); + + before('migrateEscrow', async () => { + SynthetixBridgeToOptimism = SynthetixBridgeToOptimism.connect(user); + // first test migrating a few entries using random extra invalid Ids! + const randomEntries = [escrowEntriesData.extraEntries, [0, 100, 3, 2]]; + let tx = await SynthetixBridgeToOptimism.migrateEscrow( + escrowEntriesData.userEntryBatch ); - await tx.wait(); - extraEscrowAmount = extraEscrowAmount.add(escrowEntryAmount); - extraEntries.push(currentId); - } - totalEscrowed = totalEscrowed.add(extraEscrowAmount); - }); + migrateEscrowReceipt = await tx.wait(); + tx = await SynthetixBridgeToOptimism.migrateEscrow(randomEntries); + migrateEscrowReceiptExtra = await tx.wait(); + }); - it(`Should create ${totalEntriesCreated} new entry IDs`, async () => { - assert.bnEqual( - await RewardEscrowV2L1.nextEntryId(), - initialEntriesL1.add(totalEntriesCreated) - ); - }); + it('emitted three ExportedVestingEntries events', async () => { + let events = migrateEscrowReceipt.events.filter( + e => e.event === 'ExportedVestingEntries' + ); + assert.equal(events.length, 2); + assert.equal(events[0].args.account, user.address); + assert.bnEqual( + events[0].args.escrowedAccountBalance, + escrowEntriesData.batchEscrowAmounts[0] + ); + assert.equal(events[1].args.account, user.address); + assert.bnEqual( + events[1].args.escrowedAccountBalance, + escrowEntriesData.batchEscrowAmounts[1] + ); - it('should update the L1 escrow state', async () => { - assert.bnEqual( - await RewardEscrowV2L1.totalEscrowedBalance(), - initialEscrowedBalanceL1.add(totalEscrowed) - ); - assert.bnEqual( - await RewardEscrowV2L1.numVestingEntries(user.address), - userNumVestingEntriesL1.add(totalEntriesCreated) - ); - assert.bnEqual( - await RewardEscrowV2L1.totalEscrowedAccountBalance(user.address), - userEscrowedBalanceL1.add(totalEscrowed) - ); - assert.bnEqual( - await RewardEscrowV2L1.totalVestedAccountBalance(user.address), - userVestedAccountBalanceL1 - ); - }); + events = migrateEscrowReceiptExtra.events.filter( + e => e.event === 'ExportedVestingEntries' + ); + assert.equal(events.length, 1); + assert.equal(events[0].args.account, user.address); + assert.bnEqual( + events[0].args.escrowedAccountBalance, + escrowEntriesData.extraEscrowAmount + ); + }); + + it('should update the L1 escrow state', async () => { + postParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1, user }); - describe('when the user has no outstanding debt on L1', () => { - describe('when the user migrates their escrow', () => { - let migrateEscrowReceipt, migrateEscrowReceiptExtra; - let userBalanceL2; - let totalSupplyL2; - let rewardEscrowBalanceL2; + assert.bnEqual(postParametersL1.escrowedBalance, initialParametersL1.escrowedBalance); - const importedVestingEntriesEvents = []; + assert.bnEqual( + postParametersL1.userNumVestingEntries, + initialParametersL1.userNumVestingEntries.add(totalEntriesCreated) + ); + + assert.bnEqual( + postParametersL1.escrowedBalance, + initialParametersL1.escrowedBalance.add(escrowEntriesData.totalEscrowed) + ); + assert.bnEqual( + postParametersL1.userEscrowedBalance, + initialParametersL1.userEscrowedBalance + ); + + assert.bnEqual( + postParametersL1.userVestedAccountBalance, + initialParametersL1.userVestedAccountBalance + ); + }); - const importedVestingEntriesEventListener = (account, amount, entries, event) => { - if (event && event.event === 'ImportedVestingEntries') { - importedVestingEntriesEvents.push(event); - } - }; + // -------------------------- + // Wait... + // -------------------------- - before('listen to events on l2', async () => { - SynthetixBridgeToBase.on( + describe('when waiting for the tx to complete on L2', () => { + before('stop listening to events on L2', async () => { + SynthetixBridgeToBase.off( 'ImportedVestingEntries', importedVestingEntriesEventListener ); }); - before('record current values', async () => { - userBalanceL2 = await SynthetixL2.balanceOf(user.address); - totalSupplyL2 = await SynthetixL2.totalSupply(); - rewardEscrowBalanceL2 = await SynthetixL2.balanceOf(RewardEscrowV2L2.address); - }); - - before('migrateEscrow', async () => { - SynthetixBridgeToOptimism = SynthetixBridgeToOptimism.connect(user); - // first test migrating a few entries using random extra invalid Ids! - const randomEntries = [extraEntries, [0, 100, 3, 2]]; - let tx = await SynthetixBridgeToOptimism.migrateEscrow(userEntryBatch); - migrateEscrowReceipt = await tx.wait(); - tx = await SynthetixBridgeToOptimism.migrateEscrow(randomEntries); - migrateEscrowReceiptExtra = await tx.wait(); - }); - - it('emitted three ExportedVestingEntries events', async () => { - let events = migrateEscrowReceipt.events.filter( - e => e.event === 'ExportedVestingEntries' + it('emitted three ImportedVestingEntries events', async () => { + assert.equal(importedVestingEntriesEvents.length, 3); + assert.equal(importedVestingEntriesEvents[0].args.account, user.address); + assert.bnEqual( + importedVestingEntriesEvents[0].args.escrowedAmount, + escrowEntriesData.batchEscrowAmounts[0] + ); + assert.equal(importedVestingEntriesEvents[1].args.account, user.address); + assert.bnEqual( + importedVestingEntriesEvents[1].args.escrowedAmount, + escrowEntriesData.batchEscrowAmounts[1] ); - assert.equal(events.length, 2); - assert.equal(events[0].args.account, user.address); - assert.bnEqual(events[0].args.escrowedAccountBalance, batchEscrowAmounts[0]); - assert.equal(events[1].args.account, user.address); - assert.bnEqual(events[1].args.escrowedAccountBalance, batchEscrowAmounts[1]); - - events = migrateEscrowReceiptExtra.events.filter( - e => e.event === 'ExportedVestingEntries' + assert.equal(importedVestingEntriesEvents[2].args.account, user.address); + assert.bnEqual( + importedVestingEntriesEvents[2].args.escrowedAmount, + escrowEntriesData.extraEscrowAmount ); - assert.equal(events.length, 1); - assert.equal(events[0].args.account, user.address); - assert.bnEqual(events[0].args.escrowedAccountBalance, extraEscrowAmount); }); - it('should update the L1 escrow state', async () => { + it('should update the L2 escrow state', async () => { + const postParametersL2 = await retrieveEscrowParameters({ ctx: ctx.l2, user }); assert.bnEqual( - await RewardEscrowV2L1.totalEscrowedBalance(), - initialEscrowedBalanceL1 + postParametersL2.escrowedBalance, + initialParametersL2.escrowedBalance.add(escrowEntriesData.totalEscrowed) ); assert.bnEqual( - await RewardEscrowV2L1.numVestingEntries(user.address), - userNumVestingEntriesL1.add(totalEntriesCreated) + postParametersL2.userNumVestingEntries, + initialParametersL2.userNumVestingEntries.add(totalEntriesCreated) ); assert.bnEqual( - await RewardEscrowV2L1.totalEscrowedAccountBalance(user.address), - userEscrowedBalanceL1 + postParametersL2.userEscrowedBalance, + initialParametersL2.userEscrowedBalance.add(escrowEntriesData.totalEscrowed) ); assert.bnEqual( - await RewardEscrowV2L1.totalVestedAccountBalance(user.address), - userVestedAccountBalanceL1 + postParametersL2.userVestedAccountBalance, + initialParametersL2.userVestedAccountBalance ); }); - // -------------------------- - // Wait... - // -------------------------- - - describe('when waiting for the tx to complete on L2', () => { - before('listen for completion', async () => { - const [messageHashL2ImportEntries] = await ctx.watcher.getMessageHashesFromL1Tx( - migrateEscrowReceipt.transactionHash - ); - await ctx.watcher.getL2TransactionReceipt(messageHashL2ImportEntries); - const [ - messageHashL2ImportEntriesExtra, - ] = await ctx.watcher.getMessageHashesFromL1Tx( - migrateEscrowReceiptExtra.transactionHash - ); - await ctx.watcher.getL2TransactionReceipt(messageHashL2ImportEntriesExtra); - }); - - before('stop listening to events on L2', async () => { - SynthetixBridgeToBase.off( - 'ImportedVestingEntries', - importedVestingEntriesEventListener - ); - }); - - it('emitted three ImportedVestingEntries events', async () => { - assert.equal(importedVestingEntriesEvents.length, 3); - assert.equal(importedVestingEntriesEvents[0].args.account, user.address); - assert.bnEqual( - importedVestingEntriesEvents[0].args.escrowedAmount, - batchEscrowAmounts[0] - ); - assert.equal(importedVestingEntriesEvents[1].args.account, user.address); - assert.bnEqual( - importedVestingEntriesEvents[1].args.escrowedAmount, - batchEscrowAmounts[1] - ); - assert.equal(importedVestingEntriesEvents[2].args.account, user.address); - assert.bnEqual( - importedVestingEntriesEvents[2].args.escrowedAmount, - extraEscrowAmount - ); - }); - - it('should update the L2 escrow state', async () => { - assert.bnEqual( - await RewardEscrowV2L2.totalEscrowedBalance(), - initialEscrowedBalanceL2.add(totalEscrowed) - ); - assert.bnEqual( - await RewardEscrowV2L2.numVestingEntries(user.address), - userNumVestingEntriesL2.add(totalEntriesCreated) - ); - assert.bnEqual( - await RewardEscrowV2L2.totalEscrowedAccountBalance(user.address), - userEscrowedBalanceL2.add(totalEscrowed) - ); - assert.bnEqual( - await RewardEscrowV2L2.totalVestedAccountBalance(user.address), - userVestedAccountBalanceL2 - ); - }); - - it('should update the L2 Synthetix state', async () => { - // no change in user balance - assert.bnEqual(await SynthetixL2.balanceOf(user.address), userBalanceL2); - // - assert.bnEqual( - await SynthetixL2.balanceOf(RewardEscrowV2L2.address), - rewardEscrowBalanceL2.add(totalEscrowed) - ); - assert.bnEqual(await SynthetixL2.totalSupply(), totalSupplyL2.add(totalEscrowed)); - }); + it('should update the L2 Synthetix state', async () => { + ({ Synthetix, RewardEscrowV2 } = ctx.l2.contracts); + // no change in user balance + assert.bnEqual(await Synthetix.balanceOf(user.address), userBalanceL2); + // + assert.bnEqual( + await Synthetix.balanceOf(RewardEscrowV2.address), + rewardEscrowBalanceL2.add(escrowEntriesData.totalEscrowed) + ); + assert.bnEqual( + await Synthetix.totalSupply(), + totalSupplyL2.add(escrowEntriesData.totalEscrowed) + ); }); }); }); diff --git a/test/integration/utils/escrow.js b/test/integration/utils/escrow.js new file mode 100644 index 0000000000..f3ab25fe8b --- /dev/null +++ b/test/integration/utils/escrow.js @@ -0,0 +1,58 @@ +const ethers = require('ethers'); + +async function appendEscrow({ + ctx, + user, + escrowBatches, + numExtraEntries, + escrowNum, + escrowEntryAmount, +}) { + const batchEscrowAmounts = []; + const userEntryBatch = []; + const extraEntries = []; + const RewardEscrowV2 = ctx.contracts.RewardEscrowV2.connect(user); + + const DURATION = 60 * 60 * 1000; // 1h + + let currentId; + let totalEscrowed = ethers.constants.Zero; + let extraEscrowAmount = ethers.constants.Zero; + + for (let i = 0; i < escrowBatches; i++) { + batchEscrowAmounts[i] = ethers.constants.Zero; + const userEntries = []; + for (let j = 0; j < escrowNum; j++) { + currentId = await RewardEscrowV2.nextEntryId(); + const tx = await RewardEscrowV2.createEscrowEntry(user.address, escrowEntryAmount, DURATION); + await tx.wait(); + userEntries[j] = currentId; + batchEscrowAmounts[i] = batchEscrowAmounts[i].add(escrowEntryAmount); + } + userEntryBatch.push(userEntries); + } + + totalEscrowed = batchEscrowAmounts.reduce((a, b) => a.add(b)); + + // this loop creates entries [1-numExtraEntries], e.g. 1,2,3 if numExtraEntries = 3 + for (let i = 0; i < numExtraEntries; i++) { + currentId = await RewardEscrowV2.nextEntryId(); + const tx = await RewardEscrowV2.createEscrowEntry(user.address, escrowEntryAmount, DURATION); + await tx.wait(); + extraEscrowAmount = extraEscrowAmount.add(escrowEntryAmount); + extraEntries.push(currentId); + } + totalEscrowed = totalEscrowed.add(extraEscrowAmount); + + return { + batchEscrowAmounts, + userEntryBatch, + totalEscrowed, + extraEntries, + extraEscrowAmount, + }; +} + +module.exports = { + appendEscrow, +}; From 234470deec6bfd6fa23b4c9a1e49fabfb59bd314 Mon Sep 17 00:00:00 2001 From: Leonardo Massazza Date: Mon, 31 May 2021 19:30:47 -0300 Subject: [PATCH 2/7] wip --- .../dual/migrateEscrow.integration.test.js | 291 +++++++++--------- test/integration/utils/escrow.js | 50 ++- 2 files changed, 175 insertions(+), 166 deletions(-) diff --git a/test/integration/dual/migrateEscrow.integration.test.js b/test/integration/dual/migrateEscrow.integration.test.js index 63b7ac6c1d..feb739130b 100644 --- a/test/integration/dual/migrateEscrow.integration.test.js +++ b/test/integration/dual/migrateEscrow.integration.test.js @@ -1,7 +1,7 @@ const ethers = require('ethers'); const { assert } = require('../../contracts/common'); const { bootstrapDual } = require('../utils/bootstrap'); -const { appendEscrow } = require('../utils/escrow'); +const { appendEscrows, retrieveEscrowParameters } = require('../utils/escrow'); const { approveIfNeeded } = require('../utils/approve'); describe('migrateEscrow() integration tests (L1, L2)', () => { @@ -13,31 +13,15 @@ describe('migrateEscrow() integration tests (L1, L2)', () => { let initialParametersL1, initialParametersL2; - const retrieveEscrowParameters = async ({ ctx, user }) => { - const RewardEscrowV2 = ctx.contracts.RewardEscrowV2.connect(user); - - const numberOfEntries = await RewardEscrowV2.nextEntryId(); - const escrowedBalance = await RewardEscrowV2.totalEscrowedBalance(); - const userNumVestingEntries = await RewardEscrowV2.numVestingEntries(user.address); - const userEscrowedBalance = await RewardEscrowV2.totalEscrowedAccountBalance(user.address); - const userVestedAccountBalance = await RewardEscrowV2.totalVestedAccountBalance(user.address); - - return { - numberOfEntries, - escrowedBalance, - userNumVestingEntries, - userEscrowedBalance, - userVestedAccountBalance, - }; - }; - before('target contracts and users', () => { - user = ctx.l1.user; + ({ Synthetix, RewardEscrowV2, SynthetixBridgeToOptimism } = ctx.l1.contracts); + + user = ctx.l1.users.owner; }); before('record current escrow state', async () => { - initialParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1, user }); - initialParametersL2 = await retrieveEscrowParameters({ ctx: ctx.l2, user }); + initialParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1 }); + initialParametersL2 = await retrieveEscrowParameters({ ctx: ctx.l2 }); }); describe('when the user approves the reward escrow to transfer their SNX', () => { @@ -46,7 +30,7 @@ describe('migrateEscrow() integration tests (L1, L2)', () => { before('approve reward escrow if needed', async () => { await approveIfNeeded({ token: Synthetix, - user, + owner: user, beneficiary: RewardEscrowV2, amount: snxAmount, }); @@ -61,7 +45,7 @@ describe('migrateEscrow() integration tests (L1, L2)', () => { let escrowEntriesData = {}; before('create and append escrow entries', async () => { - escrowEntriesData = await appendEscrow({ + escrowEntriesData = await appendEscrows({ ctx: ctx.l1, user, escrowBatches, @@ -72,7 +56,7 @@ describe('migrateEscrow() integration tests (L1, L2)', () => { }); before('grab new states on L1', async () => { - postParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1, user }); + postParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1 }); }); it('should update the L1 escrow state', async () => { @@ -94,164 +78,165 @@ describe('migrateEscrow() integration tests (L1, L2)', () => { ); }); - describe('when the user has no outstanding debt on L1', () => { - describe('when the user migrates their escrow', () => { - let migrateEscrowReceipt, migrateEscrowReceiptExtra; - let userBalanceL2; - let totalSupplyL2; - let rewardEscrowBalanceL2; + describe('when the user migrates their escrow', () => { + let migrateEscrowReceipt, migrateEscrowReceiptExtra; + let userBalanceL2; + let totalSupplyL2; + let rewardEscrowBalanceL2; - const importedVestingEntriesEvents = []; + const importedVestingEntriesEvents = []; - const importedVestingEntriesEventListener = (account, amount, entries, event) => { - if (event && event.event === 'ImportedVestingEntries') { - importedVestingEntriesEvents.push(event); - } - }; + const importedVestingEntriesEventListener = (account, amount, entries, event) => { + if (event && event.event === 'ImportedVestingEntries') { + importedVestingEntriesEvents.push(event); + } + }; - before('get L2 contracts', () => { - ({ Synthetix, RewardEscrowV2, SynthetixBridgeToBase } = ctx.l2.contracts); - }); + before('target contracts and users L2 ', () => { + ({ Synthetix, RewardEscrowV2, SynthetixBridgeToBase } = ctx.l2.contracts); - before('listen to events on L2', async () => { - SynthetixBridgeToBase.on('ImportedVestingEntries', importedVestingEntriesEventListener); - }); + user = ctx.l2.users.owner; + }); - before('record current values', async () => { - userBalanceL2 = await Synthetix.balanceOf(user.address); - totalSupplyL2 = await Synthetix.totalSupply(); - rewardEscrowBalanceL2 = await Synthetix.balanceOf(RewardEscrowV2.address); - }); + before('listen to events on L2', async () => { + SynthetixBridgeToBase.on('ImportedVestingEntries', importedVestingEntriesEventListener); + }); + + before('record current values', async () => { + userBalanceL2 = await Synthetix.balanceOf(user.address); + totalSupplyL2 = await Synthetix.totalSupply(); + rewardEscrowBalanceL2 = await Synthetix.balanceOf(RewardEscrowV2.address); + }); + + before('migrateEscrow', async () => { + SynthetixBridgeToOptimism = SynthetixBridgeToOptimism.connect(ctx.l1.users.owner); + // first test migrating a few entries using random extra invalid Ids! + const randomEntries = [escrowEntriesData.extraEntries, [0, 100, 3, 2]]; + let tx = await SynthetixBridgeToOptimism.migrateEscrow(escrowEntriesData.userEntryBatch); + migrateEscrowReceipt = await tx.wait(); + tx = await SynthetixBridgeToOptimism.migrateEscrow(randomEntries); + migrateEscrowReceiptExtra = await tx.wait(); + }); + + it('emitted three ExportedVestingEntries events', async () => { + let events = migrateEscrowReceipt.events.filter( + e => e.event === 'ExportedVestingEntries' + ); + assert.equal(events.length, 2); + assert.equal(events[0].args.account, user.address); + assert.bnEqual( + events[0].args.escrowedAccountBalance, + escrowEntriesData.batchEscrowAmounts[0] + ); + assert.equal(events[1].args.account, user.address); + assert.bnEqual( + events[1].args.escrowedAccountBalance, + escrowEntriesData.batchEscrowAmounts[1] + ); + + events = migrateEscrowReceiptExtra.events.filter( + e => e.event === 'ExportedVestingEntries' + ); + assert.equal(events.length, 1); + assert.equal(events[0].args.account, user.address); + assert.bnEqual( + events[0].args.escrowedAccountBalance, + escrowEntriesData.extraEscrowAmount + ); + }); - before('migrateEscrow', async () => { - SynthetixBridgeToOptimism = SynthetixBridgeToOptimism.connect(user); - // first test migrating a few entries using random extra invalid Ids! - const randomEntries = [escrowEntriesData.extraEntries, [0, 100, 3, 2]]; - let tx = await SynthetixBridgeToOptimism.migrateEscrow( - escrowEntriesData.userEntryBatch + it('should update the L1 escrow state', async () => { + postParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1 }); + + assert.bnEqual(postParametersL1.escrowedBalance, initialParametersL1.escrowedBalance); + + assert.bnEqual( + postParametersL1.userNumVestingEntries, + initialParametersL1.userNumVestingEntries.add(totalEntriesCreated) + ); + + assert.bnEqual( + postParametersL1.escrowedBalance, + initialParametersL1.escrowedBalance.add(escrowEntriesData.totalEscrowed) + ); + assert.bnEqual( + postParametersL1.userEscrowedBalance, + initialParametersL1.userEscrowedBalance + ); + + assert.bnEqual( + postParametersL1.userVestedAccountBalance, + initialParametersL1.userVestedAccountBalance + ); + }); + + // -------------------------- + // Wait... + // -------------------------- + + describe('when waiting for the tx to complete on L2', () => { + before('stop listening to events on L2', async () => { + SynthetixBridgeToBase.off( + 'ImportedVestingEntries', + importedVestingEntriesEventListener ); - migrateEscrowReceipt = await tx.wait(); - tx = await SynthetixBridgeToOptimism.migrateEscrow(randomEntries); - migrateEscrowReceiptExtra = await tx.wait(); }); - it('emitted three ExportedVestingEntries events', async () => { - let events = migrateEscrowReceipt.events.filter( - e => e.event === 'ExportedVestingEntries' - ); - assert.equal(events.length, 2); - assert.equal(events[0].args.account, user.address); + it('emitted three ImportedVestingEntries events', async () => { + assert.equal(importedVestingEntriesEvents.length, 3); + assert.equal(importedVestingEntriesEvents[0].args.account, user.address); assert.bnEqual( - events[0].args.escrowedAccountBalance, + importedVestingEntriesEvents[0].args.escrowedAmount, escrowEntriesData.batchEscrowAmounts[0] ); - assert.equal(events[1].args.account, user.address); + assert.equal(importedVestingEntriesEvents[1].args.account, user.address); assert.bnEqual( - events[1].args.escrowedAccountBalance, + importedVestingEntriesEvents[1].args.escrowedAmount, escrowEntriesData.batchEscrowAmounts[1] ); - - events = migrateEscrowReceiptExtra.events.filter( - e => e.event === 'ExportedVestingEntries' - ); - assert.equal(events.length, 1); - assert.equal(events[0].args.account, user.address); + assert.equal(importedVestingEntriesEvents[2].args.account, user.address); assert.bnEqual( - events[0].args.escrowedAccountBalance, + importedVestingEntriesEvents[2].args.escrowedAmount, escrowEntriesData.extraEscrowAmount ); }); - it('should update the L1 escrow state', async () => { - postParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1, user }); - - assert.bnEqual(postParametersL1.escrowedBalance, initialParametersL1.escrowedBalance); - + it('should update the L2 escrow state', async () => { + const postParametersL2 = await retrieveEscrowParameters({ ctx: ctx.l2 }); assert.bnEqual( - postParametersL1.userNumVestingEntries, - initialParametersL1.userNumVestingEntries.add(totalEntriesCreated) + postParametersL2.escrowedBalance, + initialParametersL2.escrowedBalance.add(escrowEntriesData.totalEscrowed) ); - assert.bnEqual( - postParametersL1.escrowedBalance, - initialParametersL1.escrowedBalance.add(escrowEntriesData.totalEscrowed) + postParametersL2.userNumVestingEntries, + initialParametersL2.userNumVestingEntries.add(totalEntriesCreated) ); assert.bnEqual( - postParametersL1.userEscrowedBalance, - initialParametersL1.userEscrowedBalance + postParametersL2.userEscrowedBalance, + initialParametersL2.userEscrowedBalance.add(escrowEntriesData.totalEscrowed) ); - assert.bnEqual( - postParametersL1.userVestedAccountBalance, - initialParametersL1.userVestedAccountBalance + postParametersL2.userVestedAccountBalance, + initialParametersL2.userVestedAccountBalance ); }); - // -------------------------- - // Wait... - // -------------------------- - - describe('when waiting for the tx to complete on L2', () => { - before('stop listening to events on L2', async () => { - SynthetixBridgeToBase.off( - 'ImportedVestingEntries', - importedVestingEntriesEventListener - ); - }); - - it('emitted three ImportedVestingEntries events', async () => { - assert.equal(importedVestingEntriesEvents.length, 3); - assert.equal(importedVestingEntriesEvents[0].args.account, user.address); - assert.bnEqual( - importedVestingEntriesEvents[0].args.escrowedAmount, - escrowEntriesData.batchEscrowAmounts[0] - ); - assert.equal(importedVestingEntriesEvents[1].args.account, user.address); - assert.bnEqual( - importedVestingEntriesEvents[1].args.escrowedAmount, - escrowEntriesData.batchEscrowAmounts[1] - ); - assert.equal(importedVestingEntriesEvents[2].args.account, user.address); - assert.bnEqual( - importedVestingEntriesEvents[2].args.escrowedAmount, - escrowEntriesData.extraEscrowAmount - ); - }); - - it('should update the L2 escrow state', async () => { - const postParametersL2 = await retrieveEscrowParameters({ ctx: ctx.l2, user }); - assert.bnEqual( - postParametersL2.escrowedBalance, - initialParametersL2.escrowedBalance.add(escrowEntriesData.totalEscrowed) - ); - assert.bnEqual( - postParametersL2.userNumVestingEntries, - initialParametersL2.userNumVestingEntries.add(totalEntriesCreated) - ); - assert.bnEqual( - postParametersL2.userEscrowedBalance, - initialParametersL2.userEscrowedBalance.add(escrowEntriesData.totalEscrowed) - ); - assert.bnEqual( - postParametersL2.userVestedAccountBalance, - initialParametersL2.userVestedAccountBalance - ); - }); - - it('should update the L2 Synthetix state', async () => { - ({ Synthetix, RewardEscrowV2 } = ctx.l2.contracts); - // no change in user balance - assert.bnEqual(await Synthetix.balanceOf(user.address), userBalanceL2); - // - assert.bnEqual( - await Synthetix.balanceOf(RewardEscrowV2.address), - rewardEscrowBalanceL2.add(escrowEntriesData.totalEscrowed) - ); - assert.bnEqual( - await Synthetix.totalSupply(), - totalSupplyL2.add(escrowEntriesData.totalEscrowed) - ); - }); + it('should update the L2 Synthetix state', async () => { + ({ Synthetix, RewardEscrowV2 } = ctx.l2.contracts); + + user = ctx.l2.users.owner; + + // no change in user balance + assert.bnEqual(await Synthetix.balanceOf(user.address), userBalanceL2); + // + assert.bnEqual( + await Synthetix.balanceOf(RewardEscrowV2.address), + rewardEscrowBalanceL2.add(escrowEntriesData.totalEscrowed) + ); + assert.bnEqual( + await Synthetix.totalSupply(), + totalSupplyL2.add(escrowEntriesData.totalEscrowed) + ); }); }); }); diff --git a/test/integration/utils/escrow.js b/test/integration/utils/escrow.js index f3ab25fe8b..f339044d4c 100644 --- a/test/integration/utils/escrow.js +++ b/test/integration/utils/escrow.js @@ -1,6 +1,16 @@ const ethers = require('ethers'); -async function appendEscrow({ +async function appendEscrow({ ctx, user, escrowEntryAmount }) { + const DURATION = 60 * 60 * 1000; // 1h + + const RewardEscrowV2 = ctx.contracts.RewardEscrowV2.connect(user); + const currentId = await RewardEscrowV2.nextEntryId(); + const tx = await RewardEscrowV2.createEscrowEntry(user.address, escrowEntryAmount, DURATION); + await tx.wait(); + return currentId; +} + +async function appendEscrows({ ctx, user, escrowBatches, @@ -11,11 +21,7 @@ async function appendEscrow({ const batchEscrowAmounts = []; const userEntryBatch = []; const extraEntries = []; - const RewardEscrowV2 = ctx.contracts.RewardEscrowV2.connect(user); - - const DURATION = 60 * 60 * 1000; // 1h - let currentId; let totalEscrowed = ethers.constants.Zero; let extraEscrowAmount = ethers.constants.Zero; @@ -23,10 +29,7 @@ async function appendEscrow({ batchEscrowAmounts[i] = ethers.constants.Zero; const userEntries = []; for (let j = 0; j < escrowNum; j++) { - currentId = await RewardEscrowV2.nextEntryId(); - const tx = await RewardEscrowV2.createEscrowEntry(user.address, escrowEntryAmount, DURATION); - await tx.wait(); - userEntries[j] = currentId; + userEntries[j] = await appendEscrow({ ctx, user, escrowEntryAmount }); batchEscrowAmounts[i] = batchEscrowAmounts[i].add(escrowEntryAmount); } userEntryBatch.push(userEntries); @@ -36,11 +39,8 @@ async function appendEscrow({ // this loop creates entries [1-numExtraEntries], e.g. 1,2,3 if numExtraEntries = 3 for (let i = 0; i < numExtraEntries; i++) { - currentId = await RewardEscrowV2.nextEntryId(); - const tx = await RewardEscrowV2.createEscrowEntry(user.address, escrowEntryAmount, DURATION); - await tx.wait(); + extraEntries.push(await appendEscrow({ ctx, user, escrowEntryAmount })); extraEscrowAmount = extraEscrowAmount.add(escrowEntryAmount); - extraEntries.push(currentId); } totalEscrowed = totalEscrowed.add(extraEscrowAmount); @@ -53,6 +53,30 @@ async function appendEscrow({ }; } +async function retrieveEscrowParameters({ ctx }) { + const RewardEscrowV2 = ctx.contracts.RewardEscrowV2; + const user = ctx.users.owner; + + let numberOfEntries; + if (!ctx.l1) { + numberOfEntries = await RewardEscrowV2.nextEntryId(); + } + const escrowedBalance = await RewardEscrowV2.totalEscrowedBalance(); + const userNumVestingEntries = await RewardEscrowV2.numVestingEntries(user.address); + const userEscrowedBalance = await RewardEscrowV2.totalEscrowedAccountBalance(user.address); + const userVestedAccountBalance = await RewardEscrowV2.totalVestedAccountBalance(user.address); + + return { + numberOfEntries, + escrowedBalance, + userNumVestingEntries, + userEscrowedBalance, + userVestedAccountBalance, + }; +} + module.exports = { appendEscrow, + appendEscrows, + retrieveEscrowParameters, }; From 37ec2f8333925da7cd3371f0aa9436f11140c794 Mon Sep 17 00:00:00 2001 From: Leonardo Massazza Date: Tue, 1 Jun 2021 00:29:58 -0300 Subject: [PATCH 3/7] migrateEscrow test ported --- .../dual/migrateEscrow.integration.test.js | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/test/integration/dual/migrateEscrow.integration.test.js b/test/integration/dual/migrateEscrow.integration.test.js index feb739130b..c6b90cfeee 100644 --- a/test/integration/dual/migrateEscrow.integration.test.js +++ b/test/integration/dual/migrateEscrow.integration.test.js @@ -14,9 +14,8 @@ describe('migrateEscrow() integration tests (L1, L2)', () => { let initialParametersL1, initialParametersL2; before('target contracts and users', () => { - ({ Synthetix, RewardEscrowV2, SynthetixBridgeToOptimism } = ctx.l1.contracts); - - user = ctx.l1.users.owner; + ({ SynthetixBridgeToOptimism } = ctx.l1.contracts); + ({ SynthetixBridgeToBase } = ctx.l2.contracts); }); before('record current escrow state', async () => { @@ -28,6 +27,9 @@ describe('migrateEscrow() integration tests (L1, L2)', () => { const snxAmount = ethers.utils.parseEther('100'); before('approve reward escrow if needed', async () => { + ({ Synthetix, RewardEscrowV2 } = ctx.l1.contracts); + user = ctx.l1.users.owner; + await approveIfNeeded({ token: Synthetix, owner: user, @@ -45,6 +47,8 @@ describe('migrateEscrow() integration tests (L1, L2)', () => { let escrowEntriesData = {}; before('create and append escrow entries', async () => { + user = ctx.l1.users.owner; + escrowEntriesData = await appendEscrows({ ctx: ctx.l1, user, @@ -92,7 +96,7 @@ describe('migrateEscrow() integration tests (L1, L2)', () => { } }; - before('target contracts and users L2 ', () => { + before('target contracts and users', () => { ({ Synthetix, RewardEscrowV2, SynthetixBridgeToBase } = ctx.l2.contracts); user = ctx.l2.users.owner; @@ -145,7 +149,7 @@ describe('migrateEscrow() integration tests (L1, L2)', () => { ); }); - it('should update the L1 escrow state', async () => { + it('should update the L1 escrow state after migrate', async () => { postParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1 }); assert.bnEqual(postParametersL1.escrowedBalance, initialParametersL1.escrowedBalance); @@ -155,10 +159,7 @@ describe('migrateEscrow() integration tests (L1, L2)', () => { initialParametersL1.userNumVestingEntries.add(totalEntriesCreated) ); - assert.bnEqual( - postParametersL1.escrowedBalance, - initialParametersL1.escrowedBalance.add(escrowEntriesData.totalEscrowed) - ); + assert.bnEqual(postParametersL1.escrowedBalance, initialParametersL1.escrowedBalance); assert.bnEqual( postParametersL1.userEscrowedBalance, initialParametersL1.userEscrowedBalance @@ -175,6 +176,17 @@ describe('migrateEscrow() integration tests (L1, L2)', () => { // -------------------------- describe('when waiting for the tx to complete on L2', () => { + before('listen for completion', async () => { + const [messageHashL2ImportEntries] = await ctx.watcher.getMessageHashesFromL1Tx( + migrateEscrowReceipt.transactionHash + ); + await ctx.watcher.getL2TransactionReceipt(messageHashL2ImportEntries); + const [messageHashL2ImportEntriesExtra] = await ctx.watcher.getMessageHashesFromL1Tx( + migrateEscrowReceiptExtra.transactionHash + ); + await ctx.watcher.getL2TransactionReceipt(messageHashL2ImportEntriesExtra); + }); + before('stop listening to events on L2', async () => { SynthetixBridgeToBase.off( 'ImportedVestingEntries', From 47b6faebe061b53bcb8aaaa87545c5d0dca4a104 Mon Sep 17 00:00:00 2001 From: Leonardo Massazza Date: Wed, 2 Jun 2021 13:21:39 -0300 Subject: [PATCH 4/7] accept multiples hashes in watchers --- test/integration/utils/watchers.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/test/integration/utils/watchers.js b/test/integration/utils/watchers.js index 57f44b0f16..ef5c73eec5 100644 --- a/test/integration/utils/watchers.js +++ b/test/integration/utils/watchers.js @@ -1,13 +1,19 @@ async function finalizationOnL2({ ctx, transactionHash }) { - const [messageHash] = await ctx.watcher.getMessageHashesFromL1Tx(transactionHash); + const messageHashes = await ctx.watcher.getMessageHashesFromL1Tx(transactionHash); + const promises = messageHashes.map(messageHash => + ctx.watcher.getL2TransactionReceipt(messageHash) + ); - await ctx.watcher.getL2TransactionReceipt(messageHash); + await Promise.all(promises); } async function finalizationOnL1({ ctx, transactionHash }) { - const [messageHash] = await ctx.watcher.getMessageHashesFromL2Tx(transactionHash); + const messageHashes = await ctx.watcher.getMessageHashesFromL2Tx(transactionHash); + const promises = messageHashes.map(messageHash => + ctx.watcher.getL1TransactionReceipt(messageHash) + ); - await ctx.watcher.getL1TransactionReceipt(messageHash); + await Promise.all(promises); } module.exports = { From e76609fbe6650727e2aefc12c64635659865c22b Mon Sep 17 00:00:00 2001 From: Leonardo Massazza Date: Wed, 2 Jun 2021 14:10:13 -0300 Subject: [PATCH 5/7] Reduce migrateEscrow dual test to dual scope --- .../dual/migrateEscrow.integration.test.js | 309 +++++++----------- 1 file changed, 118 insertions(+), 191 deletions(-) diff --git a/test/integration/dual/migrateEscrow.integration.test.js b/test/integration/dual/migrateEscrow.integration.test.js index c6b90cfeee..bb389150bd 100644 --- a/test/integration/dual/migrateEscrow.integration.test.js +++ b/test/integration/dual/migrateEscrow.integration.test.js @@ -2,6 +2,7 @@ const ethers = require('ethers'); const { assert } = require('../../contracts/common'); const { bootstrapDual } = require('../utils/bootstrap'); const { appendEscrows, retrieveEscrowParameters } = require('../utils/escrow'); +const { finalizationOnL2 } = require('../utils/watchers'); const { approveIfNeeded } = require('../utils/approve'); describe('migrateEscrow() integration tests (L1, L2)', () => { @@ -9,248 +10,174 @@ describe('migrateEscrow() integration tests (L1, L2)', () => { bootstrapDual({ ctx }); let user; - let Synthetix, RewardEscrowV2, SynthetixBridgeToOptimism, SynthetixBridgeToBase; + let Synthetix, RewardEscrowV2; let initialParametersL1, initialParametersL2; + const snxAmount = ethers.utils.parseEther('100'); - before('target contracts and users', () => { - ({ SynthetixBridgeToOptimism } = ctx.l1.contracts); - ({ SynthetixBridgeToBase } = ctx.l2.contracts); - }); - - before('record current escrow state', async () => { + before('record initial escrow state', async () => { initialParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1 }); initialParametersL2 = await retrieveEscrowParameters({ ctx: ctx.l2 }); }); - describe('when the user approves the reward escrow to transfer their SNX', () => { - const snxAmount = ethers.utils.parseEther('100'); + before('approve reward escrow if needed', async () => { + ({ Synthetix, RewardEscrowV2 } = ctx.l1.contracts); + user = ctx.l1.users.owner; - before('approve reward escrow if needed', async () => { - ({ Synthetix, RewardEscrowV2 } = ctx.l1.contracts); + await approveIfNeeded({ + token: Synthetix, + owner: user, + beneficiary: RewardEscrowV2, + amount: snxAmount, + }); + }); + + const escrowNum = 26; + const escrowBatches = 2; + const numExtraEntries = 3; + const totalEntriesCreated = escrowNum * escrowBatches + numExtraEntries; + describe(`when the user creates ${totalEntriesCreated} escrow entries`, () => { + let postParametersL1 = {}; + let escrowEntriesData = {}; + + before('create and append escrow entries', async () => { user = ctx.l1.users.owner; - await approveIfNeeded({ - token: Synthetix, - owner: user, - beneficiary: RewardEscrowV2, - amount: snxAmount, + escrowEntriesData = await appendEscrows({ + ctx: ctx.l1, + user, + escrowBatches, + numExtraEntries, + escrowNum, + escrowEntryAmount: ethers.constants.One, }); }); - const escrowNum = 26; - const escrowBatches = 2; - const numExtraEntries = 3; - const totalEntriesCreated = escrowNum * escrowBatches + numExtraEntries; - describe(`when the user creates ${totalEntriesCreated} escrow entries`, () => { - let postParametersL1 = {}; - let escrowEntriesData = {}; + before('grab new states on L1', async () => { + postParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1 }); + }); + + it('should update the L1 escrow state', async () => { + assert.bnEqual( + postParametersL1.escrowedBalance, + initialParametersL1.escrowedBalance.add(escrowEntriesData.totalEscrowed) + ); + assert.bnEqual( + postParametersL1.userNumVestingEntries, + initialParametersL1.userNumVestingEntries.add(totalEntriesCreated) + ); + assert.bnEqual( + postParametersL1.userEscrowedBalance, + initialParametersL1.userEscrowedBalance.add(escrowEntriesData.totalEscrowed) + ); + assert.bnEqual( + postParametersL1.userVestedAccountBalance, + initialParametersL1.userVestedAccountBalance + ); + }); + + describe('when the user migrates their escrow', () => { + let migrateEscrowReceipt, migrateEscrowReceiptExtra; + let userBalanceL2; + let totalSupplyL2; + let rewardEscrowBalanceL2; - before('create and append escrow entries', async () => { - user = ctx.l1.users.owner; + before('target contracts and users', () => { + ({ Synthetix, RewardEscrowV2 } = ctx.l2.contracts); - escrowEntriesData = await appendEscrows({ - ctx: ctx.l1, - user, - escrowBatches, - numExtraEntries, - escrowNum, - escrowEntryAmount: ethers.constants.One, - }); + user = ctx.l2.users.owner; }); - before('grab new states on L1', async () => { - postParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1 }); + before('record current values', async () => { + userBalanceL2 = await Synthetix.balanceOf(user.address); + totalSupplyL2 = await Synthetix.totalSupply(); + rewardEscrowBalanceL2 = await Synthetix.balanceOf(RewardEscrowV2.address); }); - it('should update the L1 escrow state', async () => { - assert.bnEqual( - postParametersL1.escrowedBalance, - initialParametersL1.escrowedBalance.add(escrowEntriesData.totalEscrowed) - ); + before('migrateEscrow', async () => { + let { SynthetixBridgeToOptimism } = ctx.l1.contracts; + + SynthetixBridgeToOptimism = SynthetixBridgeToOptimism.connect(ctx.l1.users.owner); + // first test migrating a few entries using random extra invalid Ids! + const randomEntries = [escrowEntriesData.extraEntries, [0, 100, 3, 2]]; + let tx = await SynthetixBridgeToOptimism.migrateEscrow(escrowEntriesData.userEntryBatch); + migrateEscrowReceipt = await tx.wait(); + tx = await SynthetixBridgeToOptimism.migrateEscrow(randomEntries); + migrateEscrowReceiptExtra = await tx.wait(); + }); + + it('should update the L1 escrow state after migrate', async () => { + postParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1 }); + + assert.bnEqual(postParametersL1.escrowedBalance, initialParametersL1.escrowedBalance); + assert.bnEqual( postParametersL1.userNumVestingEntries, initialParametersL1.userNumVestingEntries.add(totalEntriesCreated) ); + + assert.bnEqual(postParametersL1.escrowedBalance, initialParametersL1.escrowedBalance); assert.bnEqual( postParametersL1.userEscrowedBalance, - initialParametersL1.userEscrowedBalance.add(escrowEntriesData.totalEscrowed) + initialParametersL1.userEscrowedBalance ); + assert.bnEqual( postParametersL1.userVestedAccountBalance, initialParametersL1.userVestedAccountBalance ); }); - describe('when the user migrates their escrow', () => { - let migrateEscrowReceipt, migrateEscrowReceiptExtra; - let userBalanceL2; - let totalSupplyL2; - let rewardEscrowBalanceL2; - - const importedVestingEntriesEvents = []; - - const importedVestingEntriesEventListener = (account, amount, entries, event) => { - if (event && event.event === 'ImportedVestingEntries') { - importedVestingEntriesEvents.push(event); - } - }; - - before('target contracts and users', () => { - ({ Synthetix, RewardEscrowV2, SynthetixBridgeToBase } = ctx.l2.contracts); - - user = ctx.l2.users.owner; - }); + // -------------------------- + // Wait... + // -------------------------- - before('listen to events on L2', async () => { - SynthetixBridgeToBase.on('ImportedVestingEntries', importedVestingEntriesEventListener); - }); - - before('record current values', async () => { - userBalanceL2 = await Synthetix.balanceOf(user.address); - totalSupplyL2 = await Synthetix.totalSupply(); - rewardEscrowBalanceL2 = await Synthetix.balanceOf(RewardEscrowV2.address); - }); - - before('migrateEscrow', async () => { - SynthetixBridgeToOptimism = SynthetixBridgeToOptimism.connect(ctx.l1.users.owner); - // first test migrating a few entries using random extra invalid Ids! - const randomEntries = [escrowEntriesData.extraEntries, [0, 100, 3, 2]]; - let tx = await SynthetixBridgeToOptimism.migrateEscrow(escrowEntriesData.userEntryBatch); - migrateEscrowReceipt = await tx.wait(); - tx = await SynthetixBridgeToOptimism.migrateEscrow(randomEntries); - migrateEscrowReceiptExtra = await tx.wait(); + describe('when the escrow gets picked up in L2', () => { + before('listen for completion', async () => { + await finalizationOnL2({ ctx, transactionHash: migrateEscrowReceipt.transactionHash }); + await finalizationOnL2({ + ctx, + transactionHash: migrateEscrowReceiptExtra.transactionHash, + }); }); - it('emitted three ExportedVestingEntries events', async () => { - let events = migrateEscrowReceipt.events.filter( - e => e.event === 'ExportedVestingEntries' - ); - assert.equal(events.length, 2); - assert.equal(events[0].args.account, user.address); + it('should update the L2 escrow state', async () => { + const postParametersL2 = await retrieveEscrowParameters({ ctx: ctx.l2 }); assert.bnEqual( - events[0].args.escrowedAccountBalance, - escrowEntriesData.batchEscrowAmounts[0] + postParametersL2.escrowedBalance, + initialParametersL2.escrowedBalance.add(escrowEntriesData.totalEscrowed) ); - assert.equal(events[1].args.account, user.address); assert.bnEqual( - events[1].args.escrowedAccountBalance, - escrowEntriesData.batchEscrowAmounts[1] + postParametersL2.userNumVestingEntries, + initialParametersL2.userNumVestingEntries.add(totalEntriesCreated) ); - - events = migrateEscrowReceiptExtra.events.filter( - e => e.event === 'ExportedVestingEntries' + assert.bnEqual( + postParametersL2.userEscrowedBalance, + initialParametersL2.userEscrowedBalance.add(escrowEntriesData.totalEscrowed) ); - assert.equal(events.length, 1); - assert.equal(events[0].args.account, user.address); assert.bnEqual( - events[0].args.escrowedAccountBalance, - escrowEntriesData.extraEscrowAmount + postParametersL2.userVestedAccountBalance, + initialParametersL2.userVestedAccountBalance ); }); - it('should update the L1 escrow state after migrate', async () => { - postParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1 }); - - assert.bnEqual(postParametersL1.escrowedBalance, initialParametersL1.escrowedBalance); + it('should update the L2 Synthetix state', async () => { + ({ Synthetix, RewardEscrowV2 } = ctx.l2.contracts); - assert.bnEqual( - postParametersL1.userNumVestingEntries, - initialParametersL1.userNumVestingEntries.add(totalEntriesCreated) - ); + user = ctx.l2.users.owner; - assert.bnEqual(postParametersL1.escrowedBalance, initialParametersL1.escrowedBalance); + // no change in user balance + assert.bnEqual(await Synthetix.balanceOf(user.address), userBalanceL2); + // assert.bnEqual( - postParametersL1.userEscrowedBalance, - initialParametersL1.userEscrowedBalance + await Synthetix.balanceOf(RewardEscrowV2.address), + rewardEscrowBalanceL2.add(escrowEntriesData.totalEscrowed) ); - assert.bnEqual( - postParametersL1.userVestedAccountBalance, - initialParametersL1.userVestedAccountBalance + await Synthetix.totalSupply(), + totalSupplyL2.add(escrowEntriesData.totalEscrowed) ); }); - - // -------------------------- - // Wait... - // -------------------------- - - describe('when waiting for the tx to complete on L2', () => { - before('listen for completion', async () => { - const [messageHashL2ImportEntries] = await ctx.watcher.getMessageHashesFromL1Tx( - migrateEscrowReceipt.transactionHash - ); - await ctx.watcher.getL2TransactionReceipt(messageHashL2ImportEntries); - const [messageHashL2ImportEntriesExtra] = await ctx.watcher.getMessageHashesFromL1Tx( - migrateEscrowReceiptExtra.transactionHash - ); - await ctx.watcher.getL2TransactionReceipt(messageHashL2ImportEntriesExtra); - }); - - before('stop listening to events on L2', async () => { - SynthetixBridgeToBase.off( - 'ImportedVestingEntries', - importedVestingEntriesEventListener - ); - }); - - it('emitted three ImportedVestingEntries events', async () => { - assert.equal(importedVestingEntriesEvents.length, 3); - assert.equal(importedVestingEntriesEvents[0].args.account, user.address); - assert.bnEqual( - importedVestingEntriesEvents[0].args.escrowedAmount, - escrowEntriesData.batchEscrowAmounts[0] - ); - assert.equal(importedVestingEntriesEvents[1].args.account, user.address); - assert.bnEqual( - importedVestingEntriesEvents[1].args.escrowedAmount, - escrowEntriesData.batchEscrowAmounts[1] - ); - assert.equal(importedVestingEntriesEvents[2].args.account, user.address); - assert.bnEqual( - importedVestingEntriesEvents[2].args.escrowedAmount, - escrowEntriesData.extraEscrowAmount - ); - }); - - it('should update the L2 escrow state', async () => { - const postParametersL2 = await retrieveEscrowParameters({ ctx: ctx.l2 }); - assert.bnEqual( - postParametersL2.escrowedBalance, - initialParametersL2.escrowedBalance.add(escrowEntriesData.totalEscrowed) - ); - assert.bnEqual( - postParametersL2.userNumVestingEntries, - initialParametersL2.userNumVestingEntries.add(totalEntriesCreated) - ); - assert.bnEqual( - postParametersL2.userEscrowedBalance, - initialParametersL2.userEscrowedBalance.add(escrowEntriesData.totalEscrowed) - ); - assert.bnEqual( - postParametersL2.userVestedAccountBalance, - initialParametersL2.userVestedAccountBalance - ); - }); - - it('should update the L2 Synthetix state', async () => { - ({ Synthetix, RewardEscrowV2 } = ctx.l2.contracts); - - user = ctx.l2.users.owner; - - // no change in user balance - assert.bnEqual(await Synthetix.balanceOf(user.address), userBalanceL2); - // - assert.bnEqual( - await Synthetix.balanceOf(RewardEscrowV2.address), - rewardEscrowBalanceL2.add(escrowEntriesData.totalEscrowed) - ); - assert.bnEqual( - await Synthetix.totalSupply(), - totalSupplyL2.add(escrowEntriesData.totalEscrowed) - ); - }); - }); }); }); }); From ddcc1f0d03d1af7c2c26007e68cf29d96e6c7091 Mon Sep 17 00:00:00 2001 From: Leonardo Massazza Date: Wed, 2 Jun 2021 16:04:48 -0300 Subject: [PATCH 6/7] ported depositAndMigrateEscrow test --- .../depositAndMigrateEscrow.integration.js | 209 ++++++++++++++++++ ...n.test.js => migrateEscrow.integration.js} | 0 2 files changed, 209 insertions(+) create mode 100644 test/integration/dual/depositAndMigrateEscrow.integration.js rename test/integration/dual/{migrateEscrow.integration.test.js => migrateEscrow.integration.js} (100%) diff --git a/test/integration/dual/depositAndMigrateEscrow.integration.js b/test/integration/dual/depositAndMigrateEscrow.integration.js new file mode 100644 index 0000000000..5cdc0a9a4a --- /dev/null +++ b/test/integration/dual/depositAndMigrateEscrow.integration.js @@ -0,0 +1,209 @@ +const ethers = require('ethers'); +const { assert } = require('../../contracts/common'); +const { bootstrapDual } = require('../utils/bootstrap'); +const { appendEscrows, retrieveEscrowParameters } = require('../utils/escrow'); +const { finalizationOnL2 } = require('../utils/watchers'); +const { approveIfNeeded } = require('../utils/approve'); + +describe('depositAndMigrateEscrow() integration tests (L1, L2)', () => { + const ctx = this; + bootstrapDual({ ctx }); + + let user; + let Synthetix, RewardEscrowV2, SynthetixBridgeToOptimism; + + let initialParametersL1, initialParametersL2, initialUserL1Balance; + const snxAmount = ethers.utils.parseEther('100'); + + before('record initial escrow state', async () => { + initialParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1 }); + initialParametersL2 = await retrieveEscrowParameters({ ctx: ctx.l2 }); + + ({ Synthetix } = ctx.l1.contracts); + user = ctx.l1.users.owner; + initialUserL1Balance = await Synthetix.balanceOf(user.address); + }); + + before('approve reward escrow if needed', async () => { + ({ Synthetix, RewardEscrowV2 } = ctx.l1.contracts); + user = ctx.l1.users.owner; + + await approveIfNeeded({ + token: Synthetix, + owner: user, + beneficiary: RewardEscrowV2, + amount: snxAmount, + }); + }); + + const escrowNum = 26; + const escrowBatches = 2; + const numExtraEntries = 0; + const totalEntriesCreated = escrowNum * escrowBatches + numExtraEntries; + describe(`when the user creates ${totalEntriesCreated} escrow entries`, () => { + let postParametersL1 = {}; + let escrowEntriesData = {}; + + before('create and append escrow entries', async () => { + user = ctx.l1.users.owner; + + escrowEntriesData = await appendEscrows({ + ctx: ctx.l1, + user, + escrowBatches, + numExtraEntries, + escrowNum, + escrowEntryAmount: ethers.constants.One, + }); + }); + + before('grab new states on L1', async () => { + postParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1 }); + }); + + it('should update the L1 escrow state', async () => { + assert.bnEqual( + postParametersL1.escrowedBalance, + initialParametersL1.escrowedBalance.add(escrowEntriesData.totalEscrowed) + ); + assert.bnEqual( + postParametersL1.userNumVestingEntries, + initialParametersL1.userNumVestingEntries.add(totalEntriesCreated) + ); + assert.bnEqual( + postParametersL1.userEscrowedBalance, + initialParametersL1.userEscrowedBalance.add(escrowEntriesData.totalEscrowed) + ); + assert.bnEqual( + postParametersL1.userVestedAccountBalance, + initialParametersL1.userVestedAccountBalance + ); + }); + + describe('when the user migrates their escrow and deposit SNX', () => { + let depositAndMigrateEscrowReceipt; + let userBalanceL2; + let totalSupplyL2; + let rewardEscrowBalanceL2; + const depositAmount = ethers.utils.parseEther('20'); + + before('approve L1 bridge if needed', async () => { + ({ Synthetix, SynthetixBridgeToOptimism } = ctx.l1.contracts); + user = ctx.l1.users.owner; + + await approveIfNeeded({ + token: Synthetix, + owner: user, + beneficiary: SynthetixBridgeToOptimism, + amount: depositAmount, + }); + }); + + before('target contracts and users', () => { + ({ Synthetix, RewardEscrowV2 } = ctx.l2.contracts); + + user = ctx.l2.users.owner; + }); + + before('record current values', async () => { + userBalanceL2 = await Synthetix.balanceOf(user.address); + totalSupplyL2 = await Synthetix.totalSupply(); + rewardEscrowBalanceL2 = await Synthetix.balanceOf(RewardEscrowV2.address); + }); + + before('depositAndMigrateEscrow', async () => { + ({ SynthetixBridgeToOptimism } = ctx.l1.contracts); + + SynthetixBridgeToOptimism = SynthetixBridgeToOptimism.connect(ctx.l1.users.owner); + // first test migrating a few entries using random extra invalid Ids! + const tx = await SynthetixBridgeToOptimism.depositAndMigrateEscrow( + depositAmount, + escrowEntriesData.userEntryBatch + ); + depositAndMigrateEscrowReceipt = await tx.wait(); + }); + + it('should update the L1 escrow state after migrate', async () => { + postParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1 }); + + assert.bnEqual(postParametersL1.escrowedBalance, initialParametersL1.escrowedBalance); + + assert.bnEqual( + postParametersL1.userNumVestingEntries, + initialParametersL1.userNumVestingEntries.add(totalEntriesCreated) + ); + + assert.bnEqual(postParametersL1.escrowedBalance, initialParametersL1.escrowedBalance); + assert.bnEqual( + postParametersL1.userEscrowedBalance, + initialParametersL1.userEscrowedBalance + ); + + assert.bnEqual( + postParametersL1.userVestedAccountBalance, + initialParametersL1.userVestedAccountBalance + ); + }); + + it('should update the L1 escrow state after migrate', async () => { + ({ Synthetix } = ctx.l1.contracts); + user = ctx.l1.users.owner; + + assert.bnEqual( + await Synthetix.balanceOf(user.address), + initialUserL1Balance.sub(depositAmount).sub(escrowEntriesData.totalEscrowed) + ); + }); + + // -------------------------- + // Wait... + // -------------------------- + + describe('when the escrow gets picked up in L2', () => { + before('listen for completion', async () => { + await finalizationOnL2({ + ctx, + transactionHash: depositAndMigrateEscrowReceipt.transactionHash, + }); + }); + + it('should update the L2 escrow state', async () => { + const postParametersL2 = await retrieveEscrowParameters({ ctx: ctx.l2 }); + assert.bnEqual( + postParametersL2.escrowedBalance, + initialParametersL2.escrowedBalance.add(escrowEntriesData.totalEscrowed) + ); + assert.bnEqual( + postParametersL2.userNumVestingEntries, + initialParametersL2.userNumVestingEntries.add(totalEntriesCreated) + ); + assert.bnEqual( + postParametersL2.userEscrowedBalance, + initialParametersL2.userEscrowedBalance.add(escrowEntriesData.totalEscrowed) + ); + assert.bnEqual( + postParametersL2.userVestedAccountBalance, + initialParametersL2.userVestedAccountBalance + ); + }); + + it('should update the L2 Synthetix state', async () => { + ({ Synthetix, RewardEscrowV2 } = ctx.l2.contracts); + + user = ctx.l2.users.owner; + + assert.bnEqual(await Synthetix.balanceOf(user.address), userBalanceL2.add(depositAmount)); + + assert.bnEqual( + await Synthetix.balanceOf(RewardEscrowV2.address), + rewardEscrowBalanceL2.add(escrowEntriesData.totalEscrowed) + ); + assert.bnEqual( + await Synthetix.totalSupply(), + totalSupplyL2.add(escrowEntriesData.totalEscrowed).add(depositAmount) + ); + }); + }); + }); + }); +}); diff --git a/test/integration/dual/migrateEscrow.integration.test.js b/test/integration/dual/migrateEscrow.integration.js similarity index 100% rename from test/integration/dual/migrateEscrow.integration.test.js rename to test/integration/dual/migrateEscrow.integration.js From bfa69a1835b80fd25dd99874c3067a479e615fad Mon Sep 17 00:00:00 2001 From: Leonardo Massazza Date: Wed, 2 Jun 2021 16:13:31 -0300 Subject: [PATCH 7/7] update test wording --- test/integration/dual/depositAndMigrateEscrow.integration.js | 4 ++-- test/integration/dual/migrateEscrow.integration.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration/dual/depositAndMigrateEscrow.integration.js b/test/integration/dual/depositAndMigrateEscrow.integration.js index 5cdc0a9a4a..966087e62f 100644 --- a/test/integration/dual/depositAndMigrateEscrow.integration.js +++ b/test/integration/dual/depositAndMigrateEscrow.integration.js @@ -123,7 +123,7 @@ describe('depositAndMigrateEscrow() integration tests (L1, L2)', () => { depositAndMigrateEscrowReceipt = await tx.wait(); }); - it('should update the L1 escrow state after migrate', async () => { + it('should update the L1 escrow state', async () => { postParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1 }); assert.bnEqual(postParametersL1.escrowedBalance, initialParametersL1.escrowedBalance); @@ -145,7 +145,7 @@ describe('depositAndMigrateEscrow() integration tests (L1, L2)', () => { ); }); - it('should update the L1 escrow state after migrate', async () => { + it('should update the L1 Synthetix state', async () => { ({ Synthetix } = ctx.l1.contracts); user = ctx.l1.users.owner; diff --git a/test/integration/dual/migrateEscrow.integration.js b/test/integration/dual/migrateEscrow.integration.js index bb389150bd..a05472d05c 100644 --- a/test/integration/dual/migrateEscrow.integration.js +++ b/test/integration/dual/migrateEscrow.integration.js @@ -106,7 +106,7 @@ describe('migrateEscrow() integration tests (L1, L2)', () => { migrateEscrowReceiptExtra = await tx.wait(); }); - it('should update the L1 escrow state after migrate', async () => { + it('should update the L1 escrow state', async () => { postParametersL1 = await retrieveEscrowParameters({ ctx: ctx.l1 }); assert.bnEqual(postParametersL1.escrowedBalance, initialParametersL1.escrowedBalance);