Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: add gas portal to l1 contract addresses #5265

Merged
merged 1 commit into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ setup_env: &setup_env
command: ./build-system/scripts/setup_env "$CIRCLE_SHA1" "$CIRCLE_TAG" "$CIRCLE_JOB" "$CIRCLE_REPOSITORY_URL" "$CIRCLE_BRANCH" "$CIRCLE_PULL_REQUEST"

defaults_e2e_test: &defaults_e2e_test
docker:
- image: aztecprotocol/alpine-build-image
resource_class: small
docker:
- image: aztecprotocol/alpine-build-image
resource_class: small

jobs:
# Dynamically filter our code, quickly figuring out which jobs we can skip.
Expand Down Expand Up @@ -868,7 +868,6 @@ jobs:
aztec_manifest_key: end-to-end
<<: *defaults_e2e_test


e2e-outbox:
docker:
- image: aztecprotocol/alpine-build-image
Expand Down Expand Up @@ -958,7 +957,7 @@ jobs:
- *setup_env
- run:
name: "Test"
command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=e2e_fees.test.ts
command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=e2e_fees.test.ts ENABLE_GAS=1
aztec_manifest_key: end-to-end
<<: *defaults_e2e_test

Expand All @@ -968,7 +967,7 @@ jobs:
- *setup_env
- run:
name: "Test"
command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=e2e_dapp_subscription.test.ts
command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=e2e_dapp_subscription.test.ts ENABLE_GAS=1
aztec_manifest_key: end-to-end
<<: *defaults_e2e_test

Expand Down Expand Up @@ -1221,7 +1220,7 @@ defaults: &defaults
- slack/notify:
event: fail
branch_pattern: "master"

bb_acir_tests: &bb_acir_tests
requires:
- barretenberg-x86_64-linux-clang-assert
Expand Down
6 changes: 6 additions & 0 deletions yarn-project/archiver/src/archiver/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ export function getConfigEnvVars(): ArchiverConfig {
INBOX_CONTRACT_ADDRESS,
OUTBOX_CONTRACT_ADDRESS,
REGISTRY_CONTRACT_ADDRESS,
GAS_TOKEN_CONTRACT_ADDRESS,
GAS_PORTAL_CONTRACT_ADDRESS,
DATA_DIRECTORY,
} = process.env;
// Populate the relevant addresses for use by the archiver.
Expand All @@ -73,6 +75,10 @@ export function getConfigEnvVars(): ArchiverConfig {
registryAddress: REGISTRY_CONTRACT_ADDRESS ? EthAddress.fromString(REGISTRY_CONTRACT_ADDRESS) : EthAddress.ZERO,
inboxAddress: INBOX_CONTRACT_ADDRESS ? EthAddress.fromString(INBOX_CONTRACT_ADDRESS) : EthAddress.ZERO,
outboxAddress: OUTBOX_CONTRACT_ADDRESS ? EthAddress.fromString(OUTBOX_CONTRACT_ADDRESS) : EthAddress.ZERO,
gasTokenAddress: GAS_TOKEN_CONTRACT_ADDRESS ? EthAddress.fromString(GAS_TOKEN_CONTRACT_ADDRESS) : EthAddress.ZERO,
gasPortalAddress: GAS_PORTAL_CONTRACT_ADDRESS
? EthAddress.fromString(GAS_PORTAL_CONTRACT_ADDRESS)
: EthAddress.ZERO,
};
return {
rpcUrl: ETHEREUM_HOST || 'http://127.0.0.1:8545/',
Expand Down
2 changes: 2 additions & 0 deletions yarn-project/aztec.js/src/contract/contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ describe('Contract Class', () => {
registryAddress: EthAddress.random(),
inboxAddress: EthAddress.random(),
outboxAddress: EthAddress.random(),
gasTokenAddress: EthAddress.random(),
gasPortalAddress: EthAddress.random(),
};
const mockNodeInfo: NodeInfo = {
nodeVersion: 'vx.x.x',
Expand Down
24 changes: 16 additions & 8 deletions yarn-project/aztec.js/src/fee/native_fee_payment_method.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,41 @@
import { FunctionCall } from '@aztec/circuit-types';
import { FunctionData } from '@aztec/circuits.js';
import { AztecAddress, FunctionData } from '@aztec/circuits.js';
import { FunctionSelector } from '@aztec/foundation/abi';
import { Fr } from '@aztec/foundation/fields';
import { GasTokenAddress } from '@aztec/protocol-contracts/gas-token';
import { getCanonicalGasTokenAddress } from '@aztec/protocol-contracts/gas-token';

import { Wallet } from '../account/wallet.js';
import { FeePaymentMethod } from './fee_payment_method.js';

/**
* Pay fee directly in the native gas token.
*/
export class NativeFeePaymentMethod implements FeePaymentMethod {
static #GAS_TOKEN = GasTokenAddress;
#gasTokenAddress: AztecAddress;

constructor() {}
private constructor(canonicalGasTokenAddress: AztecAddress) {
this.#gasTokenAddress = canonicalGasTokenAddress;
}

static async create(wallet: Wallet): Promise<NativeFeePaymentMethod> {
const nodeInfo = await wallet.getNodeInfo();
return new NativeFeePaymentMethod(getCanonicalGasTokenAddress(nodeInfo.l1ContractAddresses.gasPortalAddress));
}

/**
* Gets the native gas asset used to pay the fee.
* @returns The asset used to pay the fee.
*/
getAsset() {
return NativeFeePaymentMethod.#GAS_TOKEN;
return this.#gasTokenAddress;
}

/**
* The contract responsible for fee payment. This will be the same as the asset.
* @returns The contract address responsible for holding the fee payment.
*/
getPaymentContract() {
return NativeFeePaymentMethod.#GAS_TOKEN;
return this.#gasTokenAddress;
}

/**
Expand All @@ -46,12 +54,12 @@ export class NativeFeePaymentMethod implements FeePaymentMethod {
getFunctionCalls(feeLimit: Fr): Promise<FunctionCall[]> {
return Promise.resolve([
{
to: NativeFeePaymentMethod.#GAS_TOKEN,
to: this.#gasTokenAddress,
functionData: new FunctionData(FunctionSelector.fromSignature('check_balance(Field)'), false),
args: [feeLimit],
},
{
to: NativeFeePaymentMethod.#GAS_TOKEN,
to: this.#gasTokenAddress,
functionData: new FunctionData(FunctionSelector.fromSignature('pay_fee(Field)'), false),
args: [feeLimit],
},
Expand Down
1 change: 1 addition & 0 deletions yarn-project/aztec/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"@aztec/noir-compiler": "workspace:^",
"@aztec/noir-contracts.js": "workspace:^",
"@aztec/p2p": "workspace:^",
"@aztec/protocol-contracts": "workspace:^",
"@aztec/pxe": "workspace:^",
"abitype": "^0.8.11",
"commander": "^11.1.0",
Expand Down
6 changes: 4 additions & 2 deletions yarn-project/aztec/src/bin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const debugLogger = createDebugLogger('aztec:cli');
const packageJsonPath = resolve(dirname(fileURLToPath(import.meta.url)), '../../package.json');
const cliVersion: string = JSON.parse(readFileSync(packageJsonPath).toString()).version;

const { TEST_ACCOUNTS = 'true', PORT = '8080' } = process.env;
const { TEST_ACCOUNTS = 'true', PORT = '8080', ENABLE_GAS = '' } = process.env;

/** CLI & full node main entrypoint */
async function main() {
Expand All @@ -32,7 +32,9 @@ async function main() {
// If no CLI arguments were provided, run aztec full node for sandbox usage.
userLog(`${splash}\n${github}\n\n`);
userLog(`Setting up Aztec Sandbox v${cliVersion}, please stand by...`);
const { aztecNodeConfig, node, pxe, stop } = await createSandbox();
const { aztecNodeConfig, node, pxe, stop } = await createSandbox({
enableGas: ['true', '1'].includes(ENABLE_GAS),
});
installSignalHandlers(userLog, [stop]);

// Deploy test accounts by default
Expand Down
81 changes: 75 additions & 6 deletions yarn-project/aztec/src/sandbox.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#!/usr/bin/env -S node --no-warnings
import { AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec/aztec-node';
import { AztecAddress, SignerlessWallet, Wallet } from '@aztec/aztec.js';
import { deployInstance, registerContractClass } from '@aztec/aztec.js/deployment';
import { AztecNode } from '@aztec/circuit-types';
import {
DeployL1Contracts,
L1ContractAddresses,
L1ContractArtifactsForDeployment,
NULL_KEY,
createEthereumChain,
Expand All @@ -13,18 +16,23 @@ import { retryUntil } from '@aztec/foundation/retry';
import {
AvailabilityOracleAbi,
AvailabilityOracleBytecode,
GasPortalAbi,
GasPortalBytecode,
InboxAbi,
InboxBytecode,
OutboxAbi,
OutboxBytecode,
PortalERC20Abi,
PortalERC20Bytecode,
RegistryAbi,
RegistryBytecode,
RollupAbi,
RollupBytecode,
} from '@aztec/l1-artifacts';
import { getCanonicalGasToken } from '@aztec/protocol-contracts/gas-token';
import { PXEServiceConfig, createPXEService, getPXEServiceConfig } from '@aztec/pxe';

import { HDAccount, PrivateKeyAccount, createPublicClient, http as httpViemTransport } from 'viem';
import { HDAccount, PrivateKeyAccount, createPublicClient, getContract, http as httpViemTransport } from 'viem';
import { mnemonicToAccount } from 'viem/accounts';
import { foundry } from 'viem/chains';

Expand Down Expand Up @@ -98,21 +106,77 @@ export async function deployContractsToL1(
contractAbi: RollupAbi,
contractBytecode: RollupBytecode,
},
gasToken: {
contractAbi: PortalERC20Abi,
contractBytecode: PortalERC20Bytecode,
},
gasPortal: {
contractAbi: GasPortalAbi,
contractBytecode: GasPortalBytecode,
},
};

aztecNodeConfig.l1Contracts = (
await waitThenDeploy(aztecNodeConfig, () =>
deployL1Contracts(aztecNodeConfig.rpcUrl, hdAccount, localAnvil, contractDeployLogger, l1Artifacts),
)
).l1ContractAddresses;
const l1Contracts = await waitThenDeploy(aztecNodeConfig, () =>
deployL1Contracts(aztecNodeConfig.rpcUrl, hdAccount, localAnvil, contractDeployLogger, l1Artifacts),
);
await initL1GasPortal(l1Contracts, getCanonicalGasToken(l1Contracts.l1ContractAddresses.gasPortalAddress).address);

aztecNodeConfig.l1Contracts = l1Contracts.l1ContractAddresses;

return aztecNodeConfig.l1Contracts;
}

/**
* Initializes the portal between L1 and L2 used to pay for gas.
* @param l1Data - The deployed L1 data.
*/
async function initL1GasPortal(
{ walletClient, l1ContractAddresses }: DeployL1Contracts,
l2GasTokenAddress: AztecAddress,
) {
const gasPortal = getContract({
address: l1ContractAddresses.gasPortalAddress.toString(),
abi: GasPortalAbi,
client: walletClient,
});

await gasPortal.write.initialize(
[
l1ContractAddresses.registryAddress.toString(),
l1ContractAddresses.gasTokenAddress.toString(),
l2GasTokenAddress.toString(),
],
{} as any,
);

logger(
`Initialized Gas Portal at ${l1ContractAddresses.gasPortalAddress} to bridge between L1 ${l1ContractAddresses.gasTokenAddress} to L2 ${l2GasTokenAddress}`,
);
}

/**
* Deploys the contract to pay for gas on L2.
*/
async function deployCanonicalL2GasToken(deployer: Wallet, l1ContractAddresses: L1ContractAddresses) {
const gasPortalAddress = l1ContractAddresses.gasPortalAddress;
const canonicalGasToken = getCanonicalGasToken(gasPortalAddress);

if (await deployer.isContractClassPubliclyRegistered(canonicalGasToken.contractClass.id)) {
return;
}

await (await registerContractClass(deployer, canonicalGasToken.artifact)).send().wait();
await deployInstance(deployer, canonicalGasToken.instance).send().wait();

logger(`Deployed Gas Token on L2 at ${canonicalGasToken.address}`);
}

/** Sandbox settings. */
export type SandboxConfig = AztecNodeConfig & {
/** Mnemonic used to derive the L1 deployer private key.*/
l1Mnemonic: string;
/** Enable the contracts to track and pay for gas */
enableGas: boolean;
};

/**
Expand All @@ -135,6 +199,11 @@ export async function createSandbox(config: Partial<SandboxConfig> = {}) {
const node = await createAztecNode(aztecNodeConfig);
const pxe = await createAztecPXE(node);

if (config.enableGas) {
const deployer = new SignerlessWallet(pxe);
await deployCanonicalL2GasToken(deployer, aztecNodeConfig.l1Contracts);
}

const stop = async () => {
await pxe.stop();
await node.stop();
Expand Down
3 changes: 3 additions & 0 deletions yarn-project/aztec/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@
{
"path": "../p2p"
},
{
"path": "../protocol-contracts"
},
{
"path": "../pxe"
}
Expand Down
17 changes: 16 additions & 1 deletion yarn-project/cli/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ import { type L1ContractArtifactsForDeployment } from '@aztec/aztec.js/ethereum'
import { type PXE } from '@aztec/aztec.js/interfaces/pxe';
import { DebugLogger, LogFn } from '@aztec/foundation/log';
import { NoirPackageConfig } from '@aztec/foundation/noir';
import { AvailabilityOracleAbi, AvailabilityOracleBytecode } from '@aztec/l1-artifacts';
import {
AvailabilityOracleAbi,
AvailabilityOracleBytecode,
GasPortalAbi,
GasPortalBytecode,
PortalERC20Abi,
PortalERC20Bytecode,
} from '@aztec/l1-artifacts';

import TOML from '@iarna/toml';
import { CommanderError, InvalidArgumentError } from 'commander';
Expand Down Expand Up @@ -85,6 +92,14 @@ export async function deployAztecContracts(
contractAbi: RollupAbi,
contractBytecode: RollupBytecode,
},
gasToken: {
contractAbi: PortalERC20Abi,
contractBytecode: PortalERC20Bytecode,
},
gasPortal: {
contractAbi: GasPortalAbi,
contractBytecode: GasPortalBytecode,
},
};
return await deployL1Contracts(chain.rpcUrl, account, chain.chainInfo, debugLogger, l1Artifacts);
}
Expand Down
2 changes: 2 additions & 0 deletions yarn-project/end-to-end/Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,11 @@ e2e-avm-simulator:
DO +E2E_TEST --test=e2e_avm_simulator.test.ts

e2e-fees:
ENV ENABLE_GAS=1
DO +E2E_TEST --test=e2e_fees.test.ts

e2e-dapp-subscription:
ENV ENABLE_GAS=1
DO +E2E_TEST --test=e2e_dapp_subscription.test.ts

pxe:
Expand Down
1 change: 1 addition & 0 deletions yarn-project/end-to-end/scripts/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ services:
PXE_BLOCK_POLLING_INTERVAL_MS: 50
ARCHIVER_VIEM_POLLING_INTERVAL_MS: 500
AVM_ENABLED: ${AVM_ENABLED:-}
ENABLE_GAS: ${ENABLE_GAS:-}
ports:
- '8080:8080'

Expand Down
11 changes: 7 additions & 4 deletions yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
FPCContract,
GasTokenContract,
} from '@aztec/noir-contracts.js';
import { GasTokenAddress } from '@aztec/protocol-contracts/gas-token';
import { getCanonicalGasTokenAddress } from '@aztec/protocol-contracts/gas-token';

import { jest } from '@jest/globals';

Expand Down Expand Up @@ -62,13 +62,16 @@ describe('e2e_dapp_subscription', () => {

beforeAll(async () => {
process.env.PXE_URL = '';
e2eContext = await setup(3, { deployProtocolContracts: true });
e2eContext = await setup(3);
await publicDeployAccounts(e2eContext.wallet, e2eContext.accounts);

const { wallets, accounts, aztecNode } = e2eContext;
const { wallets, accounts, aztecNode, deployL1ContractsValues } = e2eContext;

// this should be a SignerlessWallet but that can't call public functions directly
gasTokenContract = await GasTokenContract.at(GasTokenAddress, wallets[0]);
gasTokenContract = await GasTokenContract.at(
getCanonicalGasTokenAddress(deployL1ContractsValues.l1ContractAddresses.gasPortalAddress),
wallets[0],
);

aliceAddress = accounts.at(0)!.address;
bobAddress = accounts.at(1)!.address;
Expand Down
1 change: 0 additions & 1 deletion yarn-project/end-to-end/src/e2e_fees.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ describe('e2e_fees', () => {
let bananaPrivateBalances: BalancesFn;

beforeAll(async () => {
process.env.PXE_URL = '';
e2eContext = await setup(3);

const { accounts, logger, aztecNode, pxe, deployL1ContractsValues, wallets } = e2eContext;
Expand Down
Loading
Loading