From 1762bb84c06e37d3d2349bd60d1a937f34f9e0d5 Mon Sep 17 00:00:00 2001 From: Michal Rzeszutko Date: Thu, 5 Mar 2026 10:44:03 +0000 Subject: [PATCH 1/6] feat: Remove non-protocol contracts from public setup allowlist --- .../operators/reference/changelog/v4.md | 28 ++++++++++- .../contracts/fees/fpc_contract/src/main.nr | 4 ++ .../src/fee/private_fee_payment_method.ts | 1 + .../src/fee/public_fee_payment_method.ts | 1 + .../aztec/src/local-network/local-network.ts | 43 +++++++++++++++- .../cli-wallet/src/utils/options/fees.ts | 6 +++ .../client_flows/client_flows_benchmark.ts | 38 +++++++++++++- .../end-to-end/src/e2e_fees/fees_test.ts | 49 ++++++++++++++++++- yarn-project/p2p/src/config.test.ts | 34 +++++++++++++ yarn-project/p2p/src/config.ts | 42 ++++++++++++++-- .../tx_validator/allowed_public_setup.ts | 19 ------- 11 files changed, 239 insertions(+), 26 deletions(-) diff --git a/docs/docs-operate/operators/reference/changelog/v4.md b/docs/docs-operate/operators/reference/changelog/v4.md index 83b29d4758a6..acafa85b92f1 100644 --- a/docs/docs-operate/operators/reference/changelog/v4.md +++ b/docs/docs-operate/operators/reference/changelog/v4.md @@ -125,10 +125,36 @@ The variable fully **replaced** the hardcoded defaults. Format allowed entries w --txPublicSetupAllowListExtend ($TX_PUBLIC_SETUP_ALLOWLIST) ``` -The variable now **extends** the hardcoded defaults (which are always present). Selectors are now mandatory. Format: `I:address:selector,C:classId:selector`. +The variable now **extends** the hardcoded defaults (which are always present). Selectors are now mandatory. An optional flags segment can be appended for additional validation: + +``` +I:address:selector[:flags] +C:classId:selector[:flags] +``` + +Where `flags` is a `+`-separated list of: +- `os` — `onlySelf`: only allow calls where msg_sender == contract address +- `rn` — `rejectNullMsgSender`: reject calls with a null msg_sender +- `cl=N` — `calldataLength`: enforce exact calldata length of N fields + +Example: `C:0xabc:0x1234:os+cl=4` **Migration**: If you were using `TX_PUBLIC_SETUP_ALLOWLIST`, ensure all entries include function selectors. Note the variable now adds to defaults rather than replacing them. If you were not setting this variable, no action is needed — the hardcoded defaults now include the correct selectors automatically. +### Token removed from default setup allowlist + +Token class-based entries (`_increase_public_balance` and `transfer_in_public`) have been removed from the default public setup allowlist. FPC-based fee payments using custom tokens no longer work out of the box. + +This change was made because Token class IDs change with aztec-nr releases, making the allowlist hard to maintain. FPC-based fee payment with custom tokens won't work on mainnet alpha. + +**Migration**: Node operators who need FPC support must manually add Token entries via `TX_PUBLIC_SETUP_ALLOWLIST`. Example: + +```bash +TX_PUBLIC_SETUP_ALLOWLIST="C:::os+cl=3,C:::cl=5" +``` + +Replace `` with the deployed Token contract class ID and ``/`` with the respective function selectors. + ## Removed features ## New features diff --git a/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr b/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr index 62014342f741..fdd9b02f8e81 100644 --- a/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr @@ -6,6 +6,10 @@ use aztec::macros::aztec; /// Fee Payment Contract (FPC) allows users to pay for the transaction fee with an arbitrary asset. Supports private /// and public fee payment flows. /// +/// **WARNING**: This is an example/reference implementation. FPC-based fee payment with custom tokens will NOT work +/// on mainnet alpha because Token class IDs change with aztec-nr releases and are not included in the default public +/// setup allowlist. Node operators would need to manually extend the allowlist to support this contract. +/// /// ***Note:*** /// Accepted asset funds sent by the users to this contract stay in this contract and later on can /// be pulled by the admin using the `pull_funds` function. diff --git a/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts b/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts index 891c52f79a64..c1e95fdaeb7c 100644 --- a/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts +++ b/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts @@ -10,6 +10,7 @@ import type { FeePaymentMethod } from './fee_payment_method.js'; /** * Holds information about how the fee for a transaction is to be paid. + * @deprecated Will not work on mainnet alpha. Use {@link FeeJuicePaymentMethodWithClaim} or `SponsoredFeePaymentMethod` instead. */ export class PrivateFeePaymentMethod implements FeePaymentMethod { private assetPromise: Promise | null = null; diff --git a/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts b/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts index 2847a40f1dea..c35e32fde396 100644 --- a/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts +++ b/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts @@ -11,6 +11,7 @@ import type { FeePaymentMethod } from './fee_payment_method.js'; /** * Holds information about how the fee for a transaction is to be paid. + * @deprecated Will not work on mainnet alpha. Use {@link FeeJuicePaymentMethodWithClaim} or `SponsoredFeePaymentMethod` instead. */ export class PublicFeePaymentMethod implements FeePaymentMethod { private assetPromise: Promise | null = null; diff --git a/yarn-project/aztec/src/local-network/local-network.ts b/yarn-project/aztec/src/local-network/local-network.ts index a2d04e8b22ab..4f62ea214738 100644 --- a/yarn-project/aztec/src/local-network/local-network.ts +++ b/yarn-project/aztec/src/local-network/local-network.ts @@ -16,11 +16,15 @@ import { SecretValue } from '@aztec/foundation/config'; import { EthAddress } from '@aztec/foundation/eth-address'; import type { LogFn } from '@aztec/foundation/log'; import { DateProvider, TestDateProvider } from '@aztec/foundation/timer'; +import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token'; import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree'; import { protocolContractsHash } from '@aztec/protocol-contracts'; import { SequencerState } from '@aztec/sequencer-client'; +import { FunctionSelector, countArgumentsSize } from '@aztec/stdlib/abi'; +import type { FunctionAbi } from '@aztec/stdlib/abi'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; -import type { ProvingJobBroker } from '@aztec/stdlib/interfaces/server'; +import { getContractClassFromArtifact } from '@aztec/stdlib/contract'; +import type { AllowedElement, ProvingJobBroker } from '@aztec/stdlib/interfaces/server'; import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees'; import { type TelemetryClient, @@ -44,6 +48,38 @@ import { getSponsoredFPCAddress } from './sponsored_fpc.js'; const logger = createLogger('local-network'); +/** + * Returns Token-specific allowlist entries for FPC-based fee payments. + * The local network deploys a banana FPC and Token contracts, so the node must allow Token setup functions. + */ +async function getTokenAllowedSetupFunctions(): Promise { + const tokenClassId = (await getContractClassFromArtifact(TokenContractArtifact)).id; + const allFunctions: FunctionAbi[] = (TokenContractArtifact.functions as FunctionAbi[]).concat( + TokenContractArtifact.nonDispatchPublicFunctions || [], + ); + const getCalldataLength = (name: string) => { + const fn = allFunctions.find(f => f.name === name)!; + return 1 + countArgumentsSize(fn); + }; + const increaseBalanceSelector = await FunctionSelector.fromSignature('_increase_public_balance((Field),u128)'); + const transferInPublicSelector = await FunctionSelector.fromSignature( + 'transfer_in_public((Field),(Field),u128,Field)', + ); + return [ + { + classId: tokenClassId, + selector: increaseBalanceSelector, + calldataLength: getCalldataLength('_increase_public_balance'), + onlySelf: true, + }, + { + classId: tokenClassId, + selector: transferInPublicSelector, + calldataLength: getCalldataLength('transfer_in_public'), + }, + ]; +} + const localAnvil = foundry; /** @@ -102,9 +138,14 @@ export async function createLocalNetwork(config: Partial = { logger.warn(`Multiple L1 RPC URLs provided. Local networks will only use the first one: ${l1RpcUrl}`); } + // The local network deploys a banana FPC with Token contracts, so include Token entries + // in the setup allowlist so FPC-based fee payments work out of the box. + const tokenAllowList = await getTokenAllowedSetupFunctions(); + const aztecNodeConfig: AztecNodeConfig = { ...getConfigEnvVars(), ...config, + txPublicSetupAllowListExtend: [...tokenAllowList, ...(config.txPublicSetupAllowListExtend ?? [])], }; const hdAccount = mnemonicToAccount(config.l1Mnemonic || DefaultMnemonic); if ( diff --git a/yarn-project/cli-wallet/src/utils/options/fees.ts b/yarn-project/cli-wallet/src/utils/options/fees.ts index 79e89ff8e60c..908de366f549 100644 --- a/yarn-project/cli-wallet/src/utils/options/fees.ts +++ b/yarn-project/cli-wallet/src/utils/options/fees.ts @@ -171,6 +171,9 @@ export function parsePaymentMethod( case 'fpc-public': { const fpc = getFpc(); const asset = getAsset(); + log( + `WARNING: fpc-public is deprecated and will not work on mainnet alpha. Use fee_juice or fpc-sponsored instead.`, + ); log(`Using public fee payment with asset ${asset} via paymaster ${fpc}`); const { PublicFeePaymentMethod } = await import('@aztec/aztec.js/fee'); return new PublicFeePaymentMethod(fpc, from, wallet, gasSettings); @@ -178,6 +181,9 @@ export function parsePaymentMethod( case 'fpc-private': { const fpc = getFpc(); const asset = getAsset(); + log( + `WARNING: fpc-private is deprecated and will not work on mainnet alpha. Use fee_juice or fpc-sponsored instead.`, + ); log(`Using private fee payment with asset ${asset} via paymaster ${fpc}`); const { PrivateFeePaymentMethod } = await import('@aztec/aztec.js/fee'); return new PrivateFeePaymentMethod(fpc, from, wallet, gasSettings); diff --git a/yarn-project/end-to-end/src/bench/client_flows/client_flows_benchmark.ts b/yarn-project/end-to-end/src/bench/client_flows/client_flows_benchmark.ts index 689cfc2dcfef..26e6e78f3dc1 100644 --- a/yarn-project/end-to-end/src/bench/client_flows/client_flows_benchmark.ts +++ b/yarn-project/end-to-end/src/bench/client_flows/client_flows_benchmark.ts @@ -19,12 +19,16 @@ import { AMMContract } from '@aztec/noir-contracts.js/AMM'; import { FPCContract } from '@aztec/noir-contracts.js/FPC'; import { FeeJuiceContract } from '@aztec/noir-contracts.js/FeeJuice'; import { SponsoredFPCContract } from '@aztec/noir-contracts.js/SponsoredFPC'; -import { TokenContract as BananaCoin, TokenContract } from '@aztec/noir-contracts.js/Token'; +import { TokenContract as BananaCoin, TokenContract, TokenContractArtifact } from '@aztec/noir-contracts.js/Token'; import { ProtocolContractAddress } from '@aztec/protocol-contracts'; import { getCanonicalFeeJuice } from '@aztec/protocol-contracts/fee-juice'; import { type PXEConfig, getPXEConfig } from '@aztec/pxe/server'; +import { FunctionSelector, countArgumentsSize } from '@aztec/stdlib/abi'; +import type { FunctionAbi } from '@aztec/stdlib/abi'; +import { getContractClassFromArtifact } from '@aztec/stdlib/contract'; import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract'; import { GasSettings } from '@aztec/stdlib/gas'; +import type { AllowedElement } from '@aztec/stdlib/interfaces/server'; import { deriveSigningKey } from '@aztec/stdlib/keys'; import { MNEMONIC } from '../../fixtures/fixtures.js'; @@ -42,6 +46,35 @@ import { type ClientFlowsConfig, FULL_FLOWS_CONFIG, KEY_FLOWS_CONFIG } from './c const { BENCHMARK_CONFIG } = process.env; +/** Returns Token-specific allowlist entries for FPC-based fee payments (test-only). */ +async function getTokenAllowedSetupFunctions(): Promise { + const tokenClassId = (await getContractClassFromArtifact(TokenContractArtifact)).id; + const allFunctions: FunctionAbi[] = (TokenContractArtifact.functions as FunctionAbi[]).concat( + TokenContractArtifact.nonDispatchPublicFunctions || [], + ); + const getCalldataLength = (name: string) => { + const fn = allFunctions.find(f => f.name === name)!; + return 1 + countArgumentsSize(fn); + }; + const increaseBalanceSelector = await FunctionSelector.fromSignature('_increase_public_balance((Field),u128)'); + const transferInPublicSelector = await FunctionSelector.fromSignature( + 'transfer_in_public((Field),(Field),u128,Field)', + ); + return [ + { + classId: tokenClassId, + selector: increaseBalanceSelector, + calldataLength: getCalldataLength('_increase_public_balance'), + onlySelf: true, + }, + { + classId: tokenClassId, + selector: transferInPublicSelector, + calldataLength: getCalldataLength('transfer_in_public'), + }, + ]; +} + export type AccountType = 'ecdsar1' | 'schnorr'; export type FeePaymentMethodGetter = (wallet: Wallet, sender: AztecAddress) => Promise; export type BenchmarkingFeePaymentMethod = 'bridged_fee_juice' | 'private_fpc' | 'sponsored_fpc' | 'fee_juice'; @@ -130,11 +163,14 @@ export class ClientFlowsBenchmark { async setup() { this.logger.info('Setting up subsystems from fresh'); + // Token allowlist entries are test-only: FPC-based fee payment with custom tokens won't work on mainnet alpha. + const tokenAllowList = await getTokenAllowedSetupFunctions(); this.context = await setup(0, { ...this.setupOptions, fundSponsoredFPC: true, skipAccountDeployment: true, l1ContractsArgs: this.setupOptions, + txPublicSetupAllowListExtend: [...(this.setupOptions.txPublicSetupAllowListExtend ?? []), ...tokenAllowList], }); await this.applyBaseSetup(); diff --git a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts index d810c896ffc1..f163d566681d 100644 --- a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts @@ -14,12 +14,16 @@ import { AppSubscriptionContract } from '@aztec/noir-contracts.js/AppSubscriptio import { FPCContract } from '@aztec/noir-contracts.js/FPC'; import { FeeJuiceContract } from '@aztec/noir-contracts.js/FeeJuice'; import { SponsoredFPCContract } from '@aztec/noir-contracts.js/SponsoredFPC'; -import { TokenContract as BananaCoin } from '@aztec/noir-contracts.js/Token'; +import { TokenContract as BananaCoin, TokenContractArtifact } from '@aztec/noir-contracts.js/Token'; import { CounterContract } from '@aztec/noir-test-contracts.js/Counter'; import { ProtocolContractAddress } from '@aztec/protocol-contracts'; import { getCanonicalFeeJuice } from '@aztec/protocol-contracts/fee-juice'; +import { FunctionSelector, countArgumentsSize } from '@aztec/stdlib/abi'; +import type { FunctionAbi } from '@aztec/stdlib/abi'; +import { getContractClassFromArtifact } from '@aztec/stdlib/contract'; import { GasSettings } from '@aztec/stdlib/gas'; import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client'; +import type { AllowedElement } from '@aztec/stdlib/interfaces/server'; import { getContract } from 'viem'; @@ -37,6 +41,46 @@ import { type BalancesFn, getBalancesFn, setupSponsoredFPC } from '../fixtures/u import { FeeJuicePortalTestingHarnessFactory, type GasBridgingTestHarness } from '../shared/gas_portal_test_harness.js'; import { TestWallet } from '../test-wallet/test_wallet.js'; +/** Returns the calldata length for a function: 1 (selector) + arguments size. */ +function getCalldataLength(functionName: string): number { + const allFunctions: FunctionAbi[] = (TokenContractArtifact.functions as FunctionAbi[]).concat( + TokenContractArtifact.nonDispatchPublicFunctions || [], + ); + const fn = allFunctions.find(f => f.name === functionName); + if (!fn) { + throw new Error(`Unknown function ${functionName} in Token artifact`); + } + return 1 + countArgumentsSize(fn); +} + +/** + * Returns Token-specific allowlist entries needed for FPC-based fee payments. + * These are test-only — FPC-based fee payment with custom tokens won't work on mainnet alpha. + */ +async function getTokenAllowedSetupFunctions(): Promise { + const tokenClassId = (await getContractClassFromArtifact(TokenContractArtifact)).id; + const increaseBalanceSelector = await FunctionSelector.fromSignature('_increase_public_balance((Field),u128)'); + const transferInPublicSelector = await FunctionSelector.fromSignature( + 'transfer_in_public((Field),(Field),u128,Field)', + ); + + return [ + // Token: needed for private transfers via FPC (transfer_to_public enqueues this) + { + classId: tokenClassId, + selector: increaseBalanceSelector, + calldataLength: getCalldataLength('_increase_public_balance'), + onlySelf: true, + }, + // Token: needed for public transfers via FPC (fee_entrypoint_public enqueues this) + { + classId: tokenClassId, + selector: transferInPublicSelector, + calldataLength: getCalldataLength('transfer_in_public'), + }, + ]; +} + /** * Test fixture for testing fees. Provides the following setup steps: * InitialAccounts: Initializes 3 Schnorr account contracts. @@ -104,12 +148,15 @@ export class FeesTest { async setup() { this.logger.verbose('Setting up fresh context...'); + // Token allowlist entries are test-only: FPC-based fee payment with custom tokens won't work on mainnet alpha. + const tokenAllowList = await getTokenAllowedSetupFunctions(); this.context = await setup(0, { startProverNode: true, ...this.setupOptions, fundSponsoredFPC: true, skipAccountDeployment: true, l1ContractsArgs: { ...this.setupOptions }, + txPublicSetupAllowListExtend: [...(this.setupOptions.txPublicSetupAllowListExtend ?? []), ...tokenAllowList], }); this.rollupContract = RollupContract.getFromConfig(this.context.config); diff --git a/yarn-project/p2p/src/config.test.ts b/yarn-project/p2p/src/config.test.ts index 7c80cedbf670..02185e3322c2 100644 --- a/yarn-project/p2p/src/config.test.ts +++ b/yarn-project/p2p/src/config.test.ts @@ -21,6 +21,40 @@ describe('config', () => { expect(allowList).toEqual(config); }); + it('parses entries with flags', async () => { + const address = await AztecAddress.random(); + const selector = FunctionSelector.random(); + const classId = Fr.random(); + const classSelector = FunctionSelector.random(); + + const allowList = parseAllowList(`I:${address}:${selector}:os+cl=4,C:${classId}:${classSelector}:rn+os+cl=10`); + + expect(allowList).toEqual([ + { address, selector, onlySelf: true, calldataLength: 4 }, + { classId, selector: classSelector, rejectNullMsgSender: true, onlySelf: true, calldataLength: 10 }, + ]); + }); + + it('parses entries without flags (backward compat)', async () => { + const address = await AztecAddress.random(); + const selector = FunctionSelector.random(); + + const allowList = parseAllowList(`I:${address}:${selector}`); + expect(allowList).toEqual([{ address, selector }]); + }); + + it('rejects entry with unknown flag', async () => { + const address = await AztecAddress.random(); + const selector = FunctionSelector.random(); + expect(() => parseAllowList(`I:${address}:${selector}:unknown`)).toThrow('unknown flag'); + }); + + it('rejects entry with invalid calldataLength', async () => { + const address = await AztecAddress.random(); + const selector = FunctionSelector.random(); + expect(() => parseAllowList(`I:${address}:${selector}:cl=abc`)).toThrow('invalid calldataLength'); + }); + it('rejects instance entry without selector', async () => { const address = await AztecAddress.random(); expect(() => parseAllowList(`I:${address}`)).toThrow('selector is required'); diff --git a/yarn-project/p2p/src/config.ts b/yarn-project/p2p/src/config.ts index fc27123df79c..0ca77b29be50 100644 --- a/yarn-project/p2p/src/config.ts +++ b/yarn-project/p2p/src/config.ts @@ -410,9 +410,9 @@ export const p2pConfigMappings: ConfigMappingsType = { env: 'TX_PUBLIC_SETUP_ALLOWLIST', parseEnv: (val: string) => parseAllowList(val), description: - 'Additional entries to extend the default setup allow list. Format: I:address:selector,C:classId:selector', + 'Additional entries to extend the default setup allow list. Format: I:address:selector[:flags],C:classId:selector[:flags]. Flags: os (onlySelf), rn (rejectNullMsgSender), cl=N (calldataLength), joined with +.', printDefault: () => - 'Default: AuthRegistry._set_authorized, FeeJuice._increase_public_balance, Token._increase_public_balance, Token.transfer_in_public', + 'Default: AuthRegistry._set_authorized, AuthRegistry.set_authorized, FeeJuice._increase_public_balance', }, maxPendingTxCount: { env: 'P2P_MAX_PENDING_TX_COUNT', @@ -541,12 +541,45 @@ export const bootnodeConfigMappings = pickConfigMappings( bootnodeConfigKeys, ); +/** + * Parses a `+`-separated flags string into validation properties for an allow list entry. + * Supported flags: `os` (onlySelf), `rn` (rejectNullMsgSender), `cl=N` (calldataLength). + */ +function parseFlags( + flags: string, + entry: string, +): { onlySelf?: boolean; rejectNullMsgSender?: boolean; calldataLength?: number } { + const result: { onlySelf?: boolean; rejectNullMsgSender?: boolean; calldataLength?: number } = {}; + for (const flag of flags.split('+')) { + if (flag === 'os') { + result.onlySelf = true; + } else if (flag === 'rn') { + result.rejectNullMsgSender = true; + } else if (flag.startsWith('cl=')) { + const n = parseInt(flag.slice(3), 10); + if (isNaN(n) || n < 0) { + throw new Error( + `Invalid allow list entry "${entry}": invalid calldataLength in flag "${flag}". Expected a non-negative integer.`, + ); + } + result.calldataLength = n; + } else { + throw new Error(`Invalid allow list entry "${entry}": unknown flag "${flag}". Supported flags: os, rn, cl=N.`); + } + } + return result; +} + /** * Parses a string to a list of allowed elements. * Each entry is expected to be of one of the following formats: * `I:${address}:${selector}` — instance (contract address) with function selector * `C:${classId}:${selector}` — class with function selector * + * An optional flags segment can be appended after the selector: + * `I:${address}:${selector}:${flags}` or `C:${classId}:${selector}:${flags}` + * where flags is a `+`-separated list of: `os` (onlySelf), `rn` (rejectNullMsgSender), `cl=N` (calldataLength). + * * @param value The string to parse * @returns A list of allowed elements */ @@ -562,7 +595,7 @@ export function parseAllowList(value: string): AllowedElement[] { if (!trimmed) { continue; } - const [typeString, identifierString, selectorString] = trimmed.split(':'); + const [typeString, identifierString, selectorString, flagsString] = trimmed.split(':'); if (!selectorString) { throw new Error( @@ -571,16 +604,19 @@ export function parseAllowList(value: string): AllowedElement[] { } const selector = FunctionSelector.fromString(selectorString); + const flags = flagsString ? parseFlags(flagsString, trimmed) : {}; if (typeString === 'I') { entries.push({ address: AztecAddress.fromString(identifierString), selector, + ...flags, }); } else if (typeString === 'C') { entries.push({ classId: Fr.fromHexString(identifierString), selector, + ...flags, }); } else { throw new Error( diff --git a/yarn-project/p2p/src/msg_validators/tx_validator/allowed_public_setup.ts b/yarn-project/p2p/src/msg_validators/tx_validator/allowed_public_setup.ts index 6e78567c039c..b8709732a192 100644 --- a/yarn-project/p2p/src/msg_validators/tx_validator/allowed_public_setup.ts +++ b/yarn-project/p2p/src/msg_validators/tx_validator/allowed_public_setup.ts @@ -1,10 +1,8 @@ -import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token'; import { ProtocolContractAddress } from '@aztec/protocol-contracts'; import { AuthRegistryArtifact } from '@aztec/protocol-contracts/auth-registry'; import { FeeJuiceArtifact } from '@aztec/protocol-contracts/fee-juice'; import { FunctionSelector, countArgumentsSize } from '@aztec/stdlib/abi'; import type { ContractArtifact, FunctionAbi } from '@aztec/stdlib/abi'; -import { getContractClassFromArtifact } from '@aztec/stdlib/contract'; import type { AllowedElement } from '@aztec/stdlib/interfaces/server'; /** Returns the expected calldata length for a function: 1 (selector) + arguments size. */ @@ -24,13 +22,9 @@ let defaultAllowedSetupFunctions: AllowedElement[] | undefined; /** Returns the default list of functions allowed to run in the setup phase of a transaction. */ export async function getDefaultAllowedSetupFunctions(): Promise { if (defaultAllowedSetupFunctions === undefined) { - const tokenClassId = (await getContractClassFromArtifact(TokenContractArtifact)).id; const setAuthorizedInternalSelector = await FunctionSelector.fromSignature('_set_authorized((Field),Field,bool)'); const setAuthorizedSelector = await FunctionSelector.fromSignature('set_authorized(Field,bool)'); const increaseBalanceSelector = await FunctionSelector.fromSignature('_increase_public_balance((Field),u128)'); - const transferInPublicSelector = await FunctionSelector.fromSignature( - 'transfer_in_public((Field),(Field),u128,Field)', - ); defaultAllowedSetupFunctions = [ // AuthRegistry: needed for authwit support via private path (set_authorized_private enqueues _set_authorized) @@ -55,19 +49,6 @@ export async function getDefaultAllowedSetupFunctions(): Promise Date: Thu, 5 Mar 2026 13:09:05 +0100 Subject: [PATCH 2/6] Update docs/docs-operate/operators/reference/changelog/v4.md Co-authored-by: Santiago Palladino --- docs/docs-operate/operators/reference/changelog/v4.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs-operate/operators/reference/changelog/v4.md b/docs/docs-operate/operators/reference/changelog/v4.md index acafa85b92f1..0aae0ad9f392 100644 --- a/docs/docs-operate/operators/reference/changelog/v4.md +++ b/docs/docs-operate/operators/reference/changelog/v4.md @@ -145,7 +145,7 @@ Example: `C:0xabc:0x1234:os+cl=4` Token class-based entries (`_increase_public_balance` and `transfer_in_public`) have been removed from the default public setup allowlist. FPC-based fee payments using custom tokens no longer work out of the box. -This change was made because Token class IDs change with aztec-nr releases, making the allowlist hard to maintain. FPC-based fee payment with custom tokens won't work on mainnet alpha. +This change was made because Token class IDs change with aztec-nr releases, making the allowlist impossible to keep up to date with new library releases. In addition, `transfer_in_public` requires complex additional logic to be built into the node to prevent mass transaction invalidation attacks. **FPC-based fee payment with custom tokens won't work on mainnet alpha**. **Migration**: Node operators who need FPC support must manually add Token entries via `TX_PUBLIC_SETUP_ALLOWLIST`. Example: From 57c5a625513f20db7f9fea5afdb4256fef5bd80e Mon Sep 17 00:00:00 2001 From: Michal Rzeszutko Date: Thu, 5 Mar 2026 13:09:24 +0100 Subject: [PATCH 3/6] Update docs/docs-operate/operators/reference/changelog/v4.md Co-authored-by: Santiago Palladino --- docs/docs-operate/operators/reference/changelog/v4.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs-operate/operators/reference/changelog/v4.md b/docs/docs-operate/operators/reference/changelog/v4.md index 0aae0ad9f392..0e30180c1abc 100644 --- a/docs/docs-operate/operators/reference/changelog/v4.md +++ b/docs/docs-operate/operators/reference/changelog/v4.md @@ -153,7 +153,7 @@ This change was made because Token class IDs change with aztec-nr releases, maki TX_PUBLIC_SETUP_ALLOWLIST="C:::os+cl=3,C:::cl=5" ``` -Replace `` with the deployed Token contract class ID and ``/`` with the respective function selectors. +Replace `` with the deployed Token contract class ID and ``/`` with the respective function selectors. Keep in mind that this will only work on local network setups, since even if you as an operator add these entries, other nodes will not have them and will not pick up these transactions. ## Removed features From eb4143e3587d4300d25429aaeedf77040eb3f9ad Mon Sep 17 00:00:00 2001 From: Michal Rzeszutko Date: Thu, 5 Mar 2026 13:09:40 +0100 Subject: [PATCH 4/6] Update noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr Co-authored-by: Santiago Palladino --- .../noir-contracts/contracts/fees/fpc_contract/src/main.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr b/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr index fdd9b02f8e81..c0b209eb6451 100644 --- a/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/fees/fpc_contract/src/main.nr @@ -8,7 +8,7 @@ use aztec::macros::aztec; /// /// **WARNING**: This is an example/reference implementation. FPC-based fee payment with custom tokens will NOT work /// on mainnet alpha because Token class IDs change with aztec-nr releases and are not included in the default public -/// setup allowlist. Node operators would need to manually extend the allowlist to support this contract. +/// setup allowlist. /// /// ***Note:*** /// Accepted asset funds sent by the users to this contract stay in this contract and later on can From 922b33e385b3b1cadfed63e8072670d8d19b00e9 Mon Sep 17 00:00:00 2001 From: Michal Rzeszutko Date: Thu, 5 Mar 2026 13:09:54 +0100 Subject: [PATCH 5/6] Update yarn-project/aztec.js/src/fee/private_fee_payment_method.ts Co-authored-by: Santiago Palladino --- yarn-project/aztec.js/src/fee/private_fee_payment_method.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts b/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts index c1e95fdaeb7c..61277579681c 100644 --- a/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts +++ b/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts @@ -10,7 +10,7 @@ import type { FeePaymentMethod } from './fee_payment_method.js'; /** * Holds information about how the fee for a transaction is to be paid. - * @deprecated Will not work on mainnet alpha. Use {@link FeeJuicePaymentMethodWithClaim} or `SponsoredFeePaymentMethod` instead. + * @deprecated Is not supported on mainnet. Use {@link FeeJuicePaymentMethodWithClaim} or `SponsoredFeePaymentMethod` instead. */ export class PrivateFeePaymentMethod implements FeePaymentMethod { private assetPromise: Promise | null = null; From 2a06d98ebb345eb751fd7ff5b63c6527cbbccb4d Mon Sep 17 00:00:00 2001 From: Michal Rzeszutko Date: Thu, 5 Mar 2026 13:10:46 +0100 Subject: [PATCH 6/6] Update yarn-project/aztec.js/src/fee/public_fee_payment_method.ts Co-authored-by: Santiago Palladino --- yarn-project/aztec.js/src/fee/public_fee_payment_method.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts b/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts index c35e32fde396..98f20c961241 100644 --- a/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts +++ b/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts @@ -11,7 +11,7 @@ import type { FeePaymentMethod } from './fee_payment_method.js'; /** * Holds information about how the fee for a transaction is to be paid. - * @deprecated Will not work on mainnet alpha. Use {@link FeeJuicePaymentMethodWithClaim} or `SponsoredFeePaymentMethod` instead. + * @deprecated Is not supported on mainnet. Use {@link FeeJuicePaymentMethodWithClaim} or `SponsoredFeePaymentMethod` instead. */ export class PublicFeePaymentMethod implements FeePaymentMethod { private assetPromise: Promise | null = null;