Skip to content

Commit

Permalink
test: add reward payout check
Browse files Browse the repository at this point in the history
  • Loading branch information
LHerskind committed Oct 24, 2024
1 parent a5e670c commit 94a9025
Show file tree
Hide file tree
Showing 9 changed files with 182 additions and 72 deletions.
8 changes: 7 additions & 1 deletion l1-contracts/src/core/Rollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -528,12 +528,18 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup {
if (blockNumber <= assumeProvenThroughBlockNumber) {
fakeBlockNumberAsProven(blockNumber);

if (header.globalVariables.coinbase != address(0) && header.totalFees > 0) {
bool isFeeCanonical = address(this) == FEE_JUICE_PORTAL.canonicalRollup();
bool isSysstiaCanonical = address(this) == SYSSTIA.canonicalRollup();

if (isFeeCanonical && header.globalVariables.coinbase != address(0) && header.totalFees > 0) {
// @note This will currently fail if there are insufficient funds in the bridge
// which WILL happen for the old version after an upgrade where the bridge follow.
// Consider allowing a failure. See #7938.
FEE_JUICE_PORTAL.distributeFees(header.globalVariables.coinbase, header.totalFees);
}
if (isSysstiaCanonical && header.globalVariables.coinbase != address(0)) {
SYSSTIA.claim(header.globalVariables.coinbase);
}

emit L2ProofVerified(blockNumber, "CHEAT");
}
Expand Down
16 changes: 12 additions & 4 deletions yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
type CompleteAddress,
type DebugLogger,
type DeployL1Contracts,
EthAddress,
ExtendedNote,
type Fq,
Fr,
Expand Down Expand Up @@ -88,14 +89,20 @@ export class FullProverTest {
private context!: SubsystemsContext;
private proverNode!: ProverNode;
private simulatedProverNode!: ProverNode;
private l1Contracts!: DeployL1Contracts;

constructor(testName: string, private minNumberOfTxsPerBlock: number, private realProofs = true) {
public l1Contracts!: DeployL1Contracts;
public proverAddress!: EthAddress;

constructor(
testName: string,
private minNumberOfTxsPerBlock: number,
coinbase: EthAddress,
private realProofs = true,
) {
this.logger = createDebugLogger(`aztec:full_prover_test:${testName}`);
this.snapshotManager = createSnapshotManager(
`full_prover_integration/${testName}`,
dataPath,
{ startProverNode: true },
{ startProverNode: true, fundSysstia: true, coinbase },
{ assumeProvenThrough: undefined },
);
}
Expand Down Expand Up @@ -261,6 +268,7 @@ export class FullProverTest {
// The simulated prover node (now shutdown) used private key index 2
const proverNodePrivateKey = getPrivateKeyFromIndex(2);
const proverNodeSenderAddress = privateKeyToAddress(new Buffer32(proverNodePrivateKey!).to0xString());
this.proverAddress = EthAddress.fromString(proverNodeSenderAddress);

this.logger.verbose(`Funding prover node at ${proverNodeSenderAddress}`);
await this.mintL1ERC20(proverNodeSenderAddress, 100_000_000n);
Expand Down
51 changes: 49 additions & 2 deletions yarn-project/end-to-end/src/e2e_prover/full.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { type AztecAddress, retryUntil } from '@aztec/aztec.js';
import { type AztecAddress, EthAddress, retryUntil } from '@aztec/aztec.js';
import { RollupAbi, SysstiaAbi, TestERC20Abi } from '@aztec/l1-artifacts';

import '@jest/globals';
import { type Chain, type GetContractReturnType, type HttpTransport, type PublicClient, getContract } from 'viem';

import { FullProverTest } from './e2e_prover_test.js';

Expand All @@ -11,12 +13,17 @@ process.env.AVM_PROVING_STRICT = '1';

describe('full_prover', () => {
const realProofs = !['true', '1'].includes(process.env.FAKE_PROOFS ?? '');
const t = new FullProverTest('full_prover', 1, realProofs);
const COINBASE_ADDRESS = EthAddress.random();
const t = new FullProverTest('full_prover', 1, COINBASE_ADDRESS, realProofs);

let { provenAssets, accounts, tokenSim, logger, cheatCodes } = t;
let sender: AztecAddress;
let recipient: AztecAddress;

let rollup: GetContractReturnType<typeof RollupAbi, PublicClient<HttpTransport, Chain>>;
let feeJuice: GetContractReturnType<typeof TestERC20Abi, PublicClient<HttpTransport, Chain>>;
let sysstia: GetContractReturnType<typeof SysstiaAbi, PublicClient<HttpTransport, Chain>>;

beforeAll(async () => {
await t.applyBaseSnapshots();
await t.applyMintSnapshot();
Expand All @@ -25,6 +32,24 @@ describe('full_prover', () => {

({ provenAssets, accounts, tokenSim, logger, cheatCodes } = t);
[sender, recipient] = accounts.map(a => a.address);

rollup = getContract({
abi: RollupAbi,
address: t.l1Contracts.l1ContractAddresses.rollupAddress.toString(),
client: t.l1Contracts.publicClient,
});

feeJuice = getContract({
abi: TestERC20Abi,
address: t.l1Contracts.l1ContractAddresses.feeJuiceAddress.toString(),
client: t.l1Contracts.publicClient,
});

sysstia = getContract({
abi: SysstiaAbi,
address: t.l1Contracts.l1ContractAddresses.sysstiaAddress.toString(),
client: t.l1Contracts.publicClient,
});
});

afterAll(async () => {
Expand Down Expand Up @@ -86,6 +111,9 @@ describe('full_prover', () => {
logger.info(`Advancing from epoch ${epoch} to next epoch`);
await cheatCodes.rollup.advanceToNextEpoch();

const balanceBeforeCoinbase = await feeJuice.read.balanceOf([COINBASE_ADDRESS.toString()]);
const balanceBeforeProver = await feeJuice.read.balanceOf([t.proverAddress.toString()]);

// Wait until the prover node submits a quote
logger.info(`Waiting for prover node to submit quote for epoch ${epoch}`);
await retryUntil(() => t.aztecNode.getEpochProofQuotes(epoch).then(qs => qs.length > 0), 'quote', 60, 1);
Expand All @@ -108,6 +136,25 @@ describe('full_prover', () => {
// And wait for the first pair of txs to be proven
logger.info(`Awaiting proof for the previous epoch`);
await Promise.all(txs.map(tx => tx.wait({ timeout: 300, interval: 10, proven: true, provenTimeout: 1500 })));

const provenBn = await rollup.read.getProvenBlockNumber();
const balanceAfterCoinbase = await feeJuice.read.balanceOf([COINBASE_ADDRESS.toString()]);
const balanceAfterProver = await feeJuice.read.balanceOf([t.proverAddress.toString()]);
const blockReward = (await sysstia.read.BLOCK_REWARD()) as bigint;
const fees = (
await Promise.all([t.aztecNode.getBlock(Number(provenBn - 1n)), t.aztecNode.getBlock(Number(provenBn))])
).map(b => b!.header.totalFees.toBigInt());

const rewards = fees.map(fee => fee + blockReward);
const toProver = rewards
.map(reward => (reward * claim!.basisPointFee) / 10_000n)
.reduce((acc, fee) => acc + fee, 0n);
const toCoinbase = rewards.reduce((acc, reward) => acc + reward, 0n) - toProver;

expect(provenBn + 1n).toBe(await rollup.read.getPendingBlockNumber());
expect(balanceAfterCoinbase).toBe(balanceBeforeCoinbase + toCoinbase);
expect(balanceAfterProver).toBe(balanceBeforeProver + toProver);
expect(claim!.bondProvider).toEqual(t.proverAddress);
},
TIMEOUT,
);
Expand Down
27 changes: 25 additions & 2 deletions yarn-project/end-to-end/src/fixtures/snapshot_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
type Wallet,
} from '@aztec/aztec.js';
import { deployInstance, registerContractClass } from '@aztec/aztec.js/deployment';
import { type DeployL1ContractsArgs, createL1Clients } from '@aztec/ethereum';
import { type DeployL1ContractsArgs, createL1Clients, l1Artifacts } from '@aztec/ethereum';
import { asyncMap } from '@aztec/foundation/async-map';
import { type Logger, createDebugLogger } from '@aztec/foundation/log';
import { resolver, reviver } from '@aztec/foundation/serialize';
Expand All @@ -31,7 +31,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
import { copySync, removeSync } from 'fs-extra/esm';
import getPort from 'get-port';
import { join } from 'path';
import { type Hex } from 'viem';
import { type Hex, getContract } from 'viem';
import { mnemonicToAccount } from 'viem/accounts';

import { MNEMONIC } from './fixtures.js';
Expand Down Expand Up @@ -336,6 +336,29 @@ async function setupFromFresh(
aztecNodeConfig.l1Contracts = deployL1ContractsValues.l1ContractAddresses;
aztecNodeConfig.l1PublishRetryIntervalMS = 100;

if (opts.fundSysstia) {
// Mints block rewards for 10000 blocks to the sysstia contract

const sysstia = getContract({
address: deployL1ContractsValues.l1ContractAddresses.sysstiaAddress.toString(),
abi: l1Artifacts.sysstia.contractAbi,
client: deployL1ContractsValues.publicClient,
});

const blockReward = await sysstia.read.BLOCK_REWARD([]);
const mintAmount = 10_000n * (blockReward as bigint);

const feeJuice = getContract({
address: deployL1ContractsValues.l1ContractAddresses.feeJuiceAddress.toString(),
abi: l1Artifacts.feeJuice.contractAbi,
client: deployL1ContractsValues.walletClient,
});

const sysstiaMintTxHash = await feeJuice.write.mint([sysstia.address, mintAmount], {} as any);
await deployL1ContractsValues.publicClient.waitForTransactionReceipt({ hash: sysstiaMintTxHash });
logger.info(`Funding sysstia in ${sysstiaMintTxHash}`);
}

const watcher = new AnvilTestWatcher(
new EthCheatCodes(aztecNodeConfig.l1RpcUrl),
deployL1ContractsValues.l1ContractAddresses.rollupAddress,
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

28 changes: 27 additions & 1 deletion yarn-project/end-to-end/src/fixtures/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { deployInstance, registerContractClass } from '@aztec/aztec.js/deploymen
import { DefaultMultiCallEntrypoint } from '@aztec/aztec.js/entrypoint';
import { type BBNativePrivateKernelProver } from '@aztec/bb-prover';
import { type EthAddress, GasSettings, getContractClassFromArtifact } from '@aztec/circuits.js';
import { NULL_KEY, isAnvilTestChain } from '@aztec/ethereum';
import { NULL_KEY, isAnvilTestChain, l1Artifacts } from '@aztec/ethereum';
import { makeBackoff, retry, retryUntil } from '@aztec/foundation/retry';
import { FeeJuiceContract } from '@aztec/noir-contracts.js/FeeJuice';
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types';
Expand All @@ -50,6 +50,7 @@ import {
type PrivateKeyAccount,
createPublicClient,
createWalletClient,
getContract,
http,
} from 'viem';
import { mnemonicToAccount, privateKeyToAccount } from 'viem/accounts';
Expand Down Expand Up @@ -247,6 +248,8 @@ export type SetupOptions = {
assumeProvenThrough?: number;
/** Whether to start a prover node */
startProverNode?: boolean;
/** Whether to fund the sysstia */
fundSysstia?: boolean;
} & Partial<AztecNodeConfig>;

/** Context for an end-to-end test as returned by the `setup` function */
Expand Down Expand Up @@ -360,6 +363,29 @@ export async function setup(

config.l1Contracts = deployL1ContractsValues.l1ContractAddresses;

if (opts.fundSysstia) {
// Mints block rewards for 10000 blocks to the sysstia contract

const sysstia = getContract({
address: deployL1ContractsValues.l1ContractAddresses.sysstiaAddress.toString(),
abi: l1Artifacts.sysstia.contractAbi,
client: deployL1ContractsValues.publicClient,
});

const blockReward = await sysstia.read.BLOCK_REWARD([]);
const mintAmount = 10_000n * (blockReward as bigint);

const feeJuice = getContract({
address: deployL1ContractsValues.l1ContractAddresses.feeJuiceAddress.toString(),
abi: l1Artifacts.feeJuice.contractAbi,
client: deployL1ContractsValues.walletClient,
});

const sysstiaMintTxHash = await feeJuice.write.mint([sysstia.address, mintAmount], {} as any);
await deployL1ContractsValues.publicClient.waitForTransactionReceipt({ hash: sysstiaMintTxHash });
logger.info(`Funding sysstia in ${sysstiaMintTxHash}`);
}

if (opts.l2StartTime) {
// This should only be used in synching test or when you need to have a stable
// timestamp for the first l2 block.
Expand Down

0 comments on commit 94a9025

Please sign in to comment.