Skip to content

Commit

Permalink
update cross chain tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rahul-kothari committed Sep 17, 2023
1 parent fb1b08f commit 3f962f9
Show file tree
Hide file tree
Showing 6 changed files with 335 additions and 200 deletions.
84 changes: 40 additions & 44 deletions yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts
Original file line number Diff line number Diff line change
@@ -1,58 +1,56 @@
import { AztecNodeService } from '@aztec/aztec-node';
import { AztecRPCServer } from '@aztec/aztec-rpc';
import { AztecAddress } from '@aztec/aztec.js';
import { AccountWallet, AztecAddress } from '@aztec/aztec.js';
import { Fr, FunctionSelector } from '@aztec/circuits.js';
import { EthAddress } from '@aztec/foundation/eth-address';
import { DebugLogger } from '@aztec/foundation/log';
import { NonNativeTokenContract } from '@aztec/noir-contracts/types';
import { AztecRPC, TxStatus } from '@aztec/types';
import { TokenBridgeContract, TokenContract } from '@aztec/noir-contracts/types';
import { AztecRPC } from '@aztec/types';

import { CrossChainTestHarness } from './fixtures/cross_chain_test_harness.js';
import { delay, setup } from './fixtures/utils.js';
import { delay, hashPayload, setup } from './fixtures/utils.js';

describe('e2e_cross_chain_messaging', () => {
let aztecNode: AztecNodeService;
let aztecRpcServer: AztecRPC;
let logger: DebugLogger;

let l2Contract: NonNativeTokenContract;
let wallet: AccountWallet;
let ethAccount: EthAddress;

let underlyingERC20: any;
let outbox: any;

const initialBalance = 10n;
let ownerAddress: AztecAddress;

let crossChainTestHarness: CrossChainTestHarness;
let l2Token: TokenContract;
let l2Bridge: TokenBridgeContract;
let outbox: any;

beforeEach(async () => {
const {
aztecNode,
aztecRpcServer: aztecRpcServer_,
deployL1ContractsValues,
accounts,
wallet,
wallet: wallet_,
logger: logger_,
cheatCodes,
} = await setup(2);
crossChainTestHarness = await CrossChainTestHarness.new(
initialBalance,
aztecNode,
aztecRpcServer_,
deployL1ContractsValues,
accounts,
wallet,
wallet_,
logger_,
cheatCodes,
);

l2Contract = crossChainTestHarness.l2Contract;
l2Token = crossChainTestHarness.l2Token;
l2Bridge = crossChainTestHarness.l2Bridge;
ethAccount = crossChainTestHarness.ethAccount;
ownerAddress = crossChainTestHarness.ownerAddress;
underlyingERC20 = crossChainTestHarness.underlyingERC20;
outbox = crossChainTestHarness.outbox;
aztecRpcServer = crossChainTestHarness.aztecRpcServer;

wallet = wallet_;
logger = logger_;
logger('Successfully deployed contracts and initialized portal');
}, 100_000);
Expand All @@ -65,58 +63,56 @@ describe('e2e_cross_chain_messaging', () => {
await crossChainTestHarness?.stop();
});

const expectBalance = async (owner: AztecAddress, expectedBalance: bigint) => {
const balance = await l2Contract.methods.getBalance(owner).view({ from: owner });
logger(`Account ${owner} balance: ${balance}`);
expect(balance).toBe(expectedBalance);
};

const withdrawFundsFromAztec = async (withdrawAmount: bigint) => {
logger('Send L2 tx to withdraw funds');
const withdrawTx = l2Contract.methods
.withdraw(withdrawAmount, ownerAddress, ethAccount, EthAddress.ZERO.toField())
.send();

await withdrawTx.isMined({ interval: 0.1 });
const withdrawReceipt = await withdrawTx.getReceipt();

expect(withdrawReceipt.status).toBe(TxStatus.MINED);
};

it('Milestone 2: Deposit funds from L1 -> L2 and withdraw back to L1', async () => {
// Generate a claim secret using pedersen
const l1TokenBalance = 1000000n;
const bridgeAmount = 100n;

const [secret, secretHash] = await crossChainTestHarness.generateClaimSecret();

// 1. Mint tokens on L1
await crossChainTestHarness.mintTokensOnL1(l1TokenBalance);
const messageKey = await crossChainTestHarness.sendTokensToPortal(bridgeAmount, secretHash);
expect(await underlyingERC20.read.balanceOf([ethAccount.toString()])).toBe(l1TokenBalance - bridgeAmount);
expect(await crossChainTestHarness.getL1BalanceOf(ethAccount)).toBe(l1TokenBalance - bridgeAmount);

// Wait for the archiver to process the message
await delay(5000); /// waiting 5 seconds.

// Perform another unrelated transaction on L2 to progress the rollup.
const transferAmount = 1n;
await crossChainTestHarness.performL2Transfer(transferAmount);
const unrelatedMintAmount = 99n;
await crossChainTestHarness.mintTokensPublicOnL2(unrelatedMintAmount);
await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, unrelatedMintAmount);

// 3. Consume L1-> L2 message and mint private tokens on L2
await crossChainTestHarness.consumeMessageOnAztecAndMintSecretly(bridgeAmount, messageKey, secret);
await expectBalance(ownerAddress, bridgeAmount + initialBalance - transferAmount);
await crossChainTestHarness.redeemShieldPrivatelyOnL2(bridgeAmount, secret);
await crossChainTestHarness.expectPrivateBalanceOnL2(ownerAddress, bridgeAmount);

// time to withdraw the funds again!
logger('Withdrawing funds from L2');

// 4. Give approval to bridge to burn owner's funds:
const withdrawAmount = 9n;
const nonce = Fr.random();
const burnMessageHash = await hashPayload([
l2Bridge.address.toField(),
l2Token.address.toField(),
FunctionSelector.fromSignature('burn((Field),Field,Field)').toField(),
ownerAddress.toField(),
new Fr(withdrawAmount),
nonce,
]);
await wallet.createAuthWitness(burnMessageHash);

// 5. Withdraw owner's funds from L2 to L1
const entryKey = await crossChainTestHarness.checkEntryIsNotInOutbox(withdrawAmount);
await withdrawFundsFromAztec(withdrawAmount);
await expectBalance(ownerAddress, bridgeAmount + initialBalance - transferAmount - withdrawAmount);
await crossChainTestHarness.withdrawPrivateFromAztecToL1(withdrawAmount, nonce);
await crossChainTestHarness.expectPrivateBalanceOnL2(ownerAddress, bridgeAmount - withdrawAmount);

// Check balance before and after exit.
expect(await underlyingERC20.read.balanceOf([ethAccount.toString()])).toBe(l1TokenBalance - bridgeAmount);
expect(await crossChainTestHarness.getL1BalanceOf(ethAccount)).toBe(l1TokenBalance - bridgeAmount);
await crossChainTestHarness.withdrawFundsFromBridgeOnL1(withdrawAmount, entryKey);
expect(await underlyingERC20.read.balanceOf([ethAccount.toString()])).toBe(
l1TokenBalance - bridgeAmount + withdrawAmount,
);
expect(await crossChainTestHarness.getL1BalanceOf(ethAccount)).toBe(l1TokenBalance - bridgeAmount + withdrawAmount);

expect(await outbox.read.contains([entryKey.toString(true)])).toBeFalsy();
}, 120_000);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,58 +1,57 @@
import { AztecNodeService } from '@aztec/aztec-node';
import { AztecRPCServer } from '@aztec/aztec-rpc';
import { AztecAddress } from '@aztec/aztec.js';
import { AccountWallet, AztecAddress } from '@aztec/aztec.js';
import { Fr, FunctionSelector } from '@aztec/circuits.js';
import { EthAddress } from '@aztec/foundation/eth-address';
import { DebugLogger } from '@aztec/foundation/log';
import { NonNativeTokenContract } from '@aztec/noir-contracts/types';
import { AztecRPC, TxStatus } from '@aztec/types';
import { TokenBridgeContract, TokenContract } from '@aztec/noir-contracts/types';
import { AztecRPC } from '@aztec/types';

import { CrossChainTestHarness } from './fixtures/cross_chain_test_harness.js';
import { delay, setup } from './fixtures/utils.js';
import { delay, hashPayload, setup } from './fixtures/utils.js';

describe('e2e_public_cross_chain_messaging', () => {
let aztecNode: AztecNodeService | undefined;
let aztecRpcServer: AztecRPC;
let logger: DebugLogger;

let l2Contract: NonNativeTokenContract;
let wallet: AccountWallet;
let ethAccount: EthAddress;

let underlyingERC20: any;
let outbox: any;

const initialBalance = 10n;
let ownerAddress: AztecAddress;

let crossChainTestHarness: CrossChainTestHarness;
let l2Token: TokenContract;
let l2Bridge: TokenBridgeContract;
let outbox: any;

beforeEach(async () => {
const {
aztecNode: aztecNode_,
aztecRpcServer: aztecRpcServer_,
deployL1ContractsValues,
accounts,
wallet,
wallet: wallet_,
logger: logger_,
cheatCodes,
} = await setup(2);
crossChainTestHarness = await CrossChainTestHarness.new(
initialBalance,
aztecNode_,
aztecRpcServer_,
deployL1ContractsValues,
accounts,
wallet,
wallet_,
logger_,
cheatCodes,
);

l2Contract = crossChainTestHarness.l2Contract;
l2Token = crossChainTestHarness.l2Token;
l2Bridge = crossChainTestHarness.l2Bridge;
ethAccount = crossChainTestHarness.ethAccount;
ownerAddress = crossChainTestHarness.ownerAddress;
underlyingERC20 = crossChainTestHarness.underlyingERC20;
outbox = crossChainTestHarness.outbox;
aztecRpcServer = crossChainTestHarness.aztecRpcServer;
aztecNode = aztecNode_;
wallet = wallet_;

logger = logger_;
logger('Successfully deployed contracts and initialized portal');
Expand All @@ -66,53 +65,62 @@ describe('e2e_public_cross_chain_messaging', () => {
await crossChainTestHarness?.stop();
});

const withdrawFundsFromAztec = async (withdrawAmount: bigint) => {
logger('Send L2 tx to withdraw funds');
const withdrawTx = l2Contract.methods
.withdrawPublic(withdrawAmount, ethAccount.toField(), EthAddress.ZERO.toField())
.send();

await withdrawTx.isMined({ interval: 0.1 });
const withdrawReceipt = await withdrawTx.getReceipt();

expect(withdrawReceipt.status).toBe(TxStatus.MINED);
};

it('Milestone 2: Deposit funds from L1 -> L2 and withdraw back to L1', async () => {
// Generate a claim secret using pedersen
const l1TokenBalance = 1000000n;
const bridgeAmount = 100n;

const [secret, secretHash] = await crossChainTestHarness.generateClaimSecret();

// 1. Mint tokens on L1
await crossChainTestHarness.mintTokensOnL1(l1TokenBalance);

// 2. Deposit tokens to the TokenPortal
const messageKey = await crossChainTestHarness.sendTokensToPortal(bridgeAmount, secretHash);
expect(await underlyingERC20.read.balanceOf([ethAccount.toString()])).toBe(l1TokenBalance - bridgeAmount);
expect(await crossChainTestHarness.getL1BalanceOf(ethAccount)).toBe(l1TokenBalance - bridgeAmount);

// Wait for the archiver to process the message
await delay(5000); /// waiting 5 seconds.

// Perform another unrelated transaction on L2 to progress the rollup.
const transferAmount = 1n;
await crossChainTestHarness.performL2Transfer(transferAmount);
// Perform an unrelated transaction on L2 to progress the rollup. Here we mint tokens to owner
const unrelatedMintAmount = 99n;
await crossChainTestHarness.mintTokensPublicOnL2(unrelatedMintAmount);
await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, unrelatedMintAmount);
const balanceBefore = unrelatedMintAmount;

// 3. Consume L1-> L2 message and mint public tokens on L2
await crossChainTestHarness.consumeMessageOnAztecAndMintPublicly(bridgeAmount, messageKey, secret);
await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, bridgeAmount);
await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, balanceBefore + bridgeAmount);
const afterBalance = balanceBefore + bridgeAmount;

// time to withdraw the funds again!
// // time to withdraw the funds again!
logger('Withdrawing funds from L2');

// 4. Give approval to bridge to burn owner's funds:
const withdrawAmount = 9n;
const nonce = Fr.random();
const burnMessageHash = await hashPayload([
l2Bridge.address.toField(),
l2Token.address.toField(),
FunctionSelector.fromSignature('burn_public((Field),Field,Field)').toField(),
ownerAddress.toField(),
new Fr(withdrawAmount),
nonce,
]);
await wallet.setPublicAuth(burnMessageHash, true).send().wait();

// 5. Withdraw owner's funds from L2 to L1
const entryKey = await crossChainTestHarness.checkEntryIsNotInOutbox(withdrawAmount);
await withdrawFundsFromAztec(withdrawAmount);
await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, bridgeAmount - withdrawAmount);
await crossChainTestHarness.withdrawPublicFromAztecToL1(withdrawAmount, nonce);
await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, afterBalance - withdrawAmount);

// Check balance before and after exit.
expect(await underlyingERC20.read.balanceOf([ethAccount.toString()])).toBe(l1TokenBalance - bridgeAmount);
expect(await crossChainTestHarness.getL1BalanceOf(ethAccount)).toBe(l1TokenBalance - bridgeAmount);
await crossChainTestHarness.withdrawFundsFromBridgeOnL1(withdrawAmount, entryKey);
expect(await underlyingERC20.read.balanceOf([ethAccount.toString()])).toBe(
l1TokenBalance - bridgeAmount + withdrawAmount,
);
expect(await crossChainTestHarness.getL1BalanceOf(ethAccount)).toBe(l1TokenBalance - bridgeAmount + withdrawAmount);

expect(await outbox.read.contains([entryKey.toString(true)])).toBeFalsy();
}, 120_000);

// TODO: Fialure cases!
});
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ describe('e2e_public_to_private_messaging', () => {

let underlyingERC20: any;

const initialBalance = 10n;
let ownerAddress: AztecAddress;

let crossChainTestHarness: CrossChainTestHarness;
Expand All @@ -32,7 +31,6 @@ describe('e2e_public_to_private_messaging', () => {
cheatCodes,
} = await setup(2);
crossChainTestHarness = await CrossChainTestHarness.new(
initialBalance,
aztecNode_,
aztecRpcServer_,
deployL1ContractsValues,
Expand Down Expand Up @@ -76,25 +74,24 @@ describe('e2e_public_to_private_messaging', () => {
await delay(5000); /// waiting 5 seconds.

// Perform another unrelated transaction on L2 to progress the rollup.
await crossChainTestHarness.expectBalanceOnL2(ownerAddress, initialBalance);
const transferAmount = 1n;
await crossChainTestHarness.performL2Transfer(transferAmount);
await crossChainTestHarness.expectBalanceOnL2(ownerAddress, initialBalance - transferAmount);
const initialBalance = 1n;
await crossChainTestHarness.mintTokensPublicOnL2(initialBalance);
await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, initialBalance);

await crossChainTestHarness.consumeMessageOnAztecAndMintPublicly(bridgeAmount, messageKey, secret);
await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, bridgeAmount);
await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, initialBalance + bridgeAmount);

// Create the commitment to be spent in the private domain
await crossChainTestHarness.shieldFundsOnL2(shieldAmount, secretHash);

// Create the transaction spending the commitment
await crossChainTestHarness.redeemShieldPrivatelyOnL2(shieldAmount, secret);
await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, bridgeAmount - shieldAmount);
await crossChainTestHarness.expectBalanceOnL2(ownerAddress, initialBalance + shieldAmount - transferAmount);
await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, initialBalance + bridgeAmount - shieldAmount);
await crossChainTestHarness.expectPrivateBalanceOnL2(ownerAddress, shieldAmount);

// Unshield the tokens again, sending them to the same account, however this can be any account.
await crossChainTestHarness.unshieldTokensOnL2(shieldAmount);
await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, bridgeAmount);
await crossChainTestHarness.expectBalanceOnL2(ownerAddress, initialBalance - transferAmount);
await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, initialBalance + bridgeAmount);
await crossChainTestHarness.expectPrivateBalanceOnL2(ownerAddress, 0n);
}, 200_000);
});
Loading

0 comments on commit 3f962f9

Please sign in to comment.