Skip to content

Commit

Permalink
feat: Reenable native fee payment
Browse files Browse the repository at this point in the history
Had been disabled after #6403
  • Loading branch information
spalladino committed May 23, 2024
1 parent d387180 commit e48f63c
Show file tree
Hide file tree
Showing 20 changed files with 181 additions and 122 deletions.
2 changes: 1 addition & 1 deletion l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ library Constants {
uint256 internal constant CANONICAL_KEY_REGISTRY_ADDRESS =
0x1585e564a60e6ec974bc151b62705292ebfc75c33341986a47fd9749cedb567e;
uint256 internal constant DEPLOYER_CONTRACT_ADDRESS =
0x2e9c386f07e22a1d24e677ab70407b2dd0adbc7cafb9c822bf249685d6a2e4cc;
0x02f1337e8c79dd0247ccbde85241ad65ee991ae283a63479e095e51f0abbc7e3;
uint256 internal constant GAS_TOKEN_ADDRESS =
0x283353eafd3802181f7c1461a4b68332afc6c04e95097bc51b5458d8a8abf4f9;
uint256 internal constant AZTEC_ADDRESS_LENGTH = 1;
Expand Down
10 changes: 8 additions & 2 deletions noir-projects/aztec-nr/authwit/src/entrypoint/fee.nr
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use dep::aztec::prelude::PrivateContext;
use dep::aztec::protocol_types::{constants::GENERATOR_INDEX__FEE_PAYLOAD, hash::pedersen_hash, traits::{Hash, Serialize}};
use crate::entrypoint::function_call::FunctionCall;

// 2 * 5 (FUNCTION_CALL_SIZE) + 1
global FEE_PAYLOAD_SIZE: Field = 11;
// 2 * 5 (FUNCTION_CALL_SIZE) + 2
global FEE_PAYLOAD_SIZE: Field = 12;

// 2 * 98 (FUNCTION_CALL_SIZE_IN_BYTES) + 32
global FEE_PAYLOAD_SIZE_IN_BYTES: Field = 228;
Expand All @@ -14,6 +14,7 @@ global MAX_FEE_FUNCTION_CALLS = 2;
struct FeePayload {
function_calls: [FunctionCall; MAX_FEE_FUNCTION_CALLS],
nonce: Field,
is_fee_payer: bool,
}
// docs:end:fee-payload-struct

Expand All @@ -25,6 +26,7 @@ impl Serialize<FEE_PAYLOAD_SIZE> for FeePayload {
fields.extend_from_array(self.function_calls[i].serialize());
}
fields.push(self.nonce);
fields.push(self.is_fee_payer as Field);
fields.storage
}
}
Expand All @@ -46,6 +48,7 @@ impl FeePayload {
bytes.extend_from_array(self.function_calls[i].to_be_bytes());
}
bytes.extend_from_slice(self.nonce.to_be_bytes(32));
bytes.push(self.is_fee_payer as u8);

bytes.storage
}
Expand All @@ -72,5 +75,8 @@ impl FeePayload {
}
}
}
if self.is_fee_payer {
context.set_as_fee_payer();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ global FIXED_DA_GAS: u32 = 512;

// CANONICAL CONTRACT ADDRESSES
global CANONICAL_KEY_REGISTRY_ADDRESS = 0x1585e564a60e6ec974bc151b62705292ebfc75c33341986a47fd9749cedb567e;
global DEPLOYER_CONTRACT_ADDRESS = 0x2e9c386f07e22a1d24e677ab70407b2dd0adbc7cafb9c822bf249685d6a2e4cc;
global DEPLOYER_CONTRACT_ADDRESS = 0x02f1337e8c79dd0247ccbde85241ad65ee991ae283a63479e095e51f0abbc7e3;
global GAS_TOKEN_ADDRESS = 0x283353eafd3802181f7c1461a4b68332afc6c04e95097bc51b5458d8a8abf4f9;

// LENGTH OF STRUCTS SERIALIZED TO FIELDS
Expand Down
65 changes: 47 additions & 18 deletions yarn-project/aztec.js/src/entrypoint/payload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ type EncodedFunctionCall = {
/* eslint-enable camelcase */

/** Assembles an entrypoint payload */
export class EntrypointPayload {
export abstract class EntrypointPayload {
#packedArguments: PackedValues[] = [];
#functionCalls: EncodedFunctionCall[] = [];
#nonce = Fr.random();
#generatorIndex: number;

private constructor(functionCalls: FunctionCall[], generatorIndex: number) {
protected constructor(functionCalls: FunctionCall[], generatorIndex: number) {
for (const call of functionCalls) {
this.#packedArguments.push(PackedValues.fromValues(call.args));
}
Expand Down Expand Up @@ -93,18 +93,7 @@ export class EntrypointPayload {
* Serializes the payload to an array of fields
* @returns The fields of the payload
*/
toFields(): Fr[] {
return [
...this.#functionCalls.flatMap(call => [
call.args_hash,
call.function_selector,
call.target_address,
new Fr(call.is_public),
new Fr(call.is_static),
]),
this.#nonce,
];
}
abstract toFields(): Fr[];

/**
* Hashes the payload
Expand All @@ -114,13 +103,24 @@ export class EntrypointPayload {
return pedersenHash(this.toFields(), this.#generatorIndex);
}

/** Serializes the function calls to an array of fields. */
protected functionCallsToFields() {
return this.#functionCalls.flatMap(call => [
call.args_hash,
call.function_selector,
call.target_address,
new Fr(call.is_public),
new Fr(call.is_static),
]);
}

/**
* Creates an execution payload from a set of function calls
* Creates an execution payload for a dapp from a set of function calls
* @param functionCalls - The function calls to execute
* @returns The execution payload
*/
static fromFunctionCalls(functionCalls: FunctionCall[]) {
return new EntrypointPayload(functionCalls, 0);
return new AppEntrypointPayload(functionCalls, 0);
}

/**
Expand All @@ -133,7 +133,7 @@ export class EntrypointPayload {
throw new Error(`Expected at most ${APP_MAX_CALLS} function calls, got ${functionCalls.length}`);
}
const paddedCalls = padArrayEnd(functionCalls, FunctionCall.empty(), APP_MAX_CALLS);
return new EntrypointPayload(paddedCalls, GeneratorIndex.SIGNATURE_PAYLOAD);
return new AppEntrypointPayload(paddedCalls, GeneratorIndex.SIGNATURE_PAYLOAD);
}

/**
Expand All @@ -143,7 +143,36 @@ export class EntrypointPayload {
*/
static async fromFeeOptions(feeOpts?: FeeOptions) {
const calls = feeOpts ? await feeOpts.paymentMethod.getFunctionCalls(feeOpts?.gasSettings) : [];
const isFeePayer = feeOpts ? await feeOpts.paymentMethod.isFeePayer(feeOpts?.gasSettings) : false;
const paddedCalls = padArrayEnd(calls, FunctionCall.empty(), FEE_MAX_CALLS);
return new EntrypointPayload(paddedCalls, GeneratorIndex.FEE_PAYLOAD);
return new FeeEntrypointPayload(paddedCalls, GeneratorIndex.FEE_PAYLOAD, isFeePayer);
}
}

/** Entrypoint payload for app phase execution. */
class AppEntrypointPayload extends EntrypointPayload {
override toFields(): Fr[] {
return [...this.functionCallsToFields(), this.nonce];
}
}

/** Entrypoint payload for fee payment to be run during setup phase. */
class FeeEntrypointPayload extends EntrypointPayload {
#isFeePayer: boolean;

constructor(functionCalls: FunctionCall[], generatorIndex: number, isFeePayer: boolean) {
super(functionCalls, generatorIndex);
this.#isFeePayer = isFeePayer;
}

override toFields(): Fr[] {
return [...this.functionCallsToFields(), this.nonce, new Fr(this.#isFeePayer)];
}

/* eslint-disable camelcase */
/** Whether the sender should be appointed as fee payer. */
get is_fee_payer() {
return this.#isFeePayer;
}
/* eslint-enable camelcase */
}
14 changes: 6 additions & 8 deletions yarn-project/aztec.js/src/fee/fee_payment_method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,17 @@ import { type AztecAddress } from '@aztec/foundation/aztec-address';
* Holds information about how the fee for a transaction is to be paid.
*/
export interface FeePaymentMethod {
/**
* The asset used to pay the fee.
*/
/** The asset used to pay the fee. */
getAsset(): AztecAddress;
/**
* Address which will hold the fee payment.
*/
getPaymentContract(): AztecAddress;

/**
* Creates a function call to pay the fee in the given asset.
* @param gasSettings - The gas limits and max fees.
* @returns The function call to pay the fee.
*/
getFunctionCalls(gasSettings: GasSettings): Promise<FunctionCall[]>;
/**
* Whether the sender should be appointed as fee payer.
* @param gasSettings - The gas limits and max fees.
*/
isFeePayer(gasSettings: GasSettings): Promise<boolean>;
}
38 changes: 7 additions & 31 deletions yarn-project/aztec.js/src/fee/native_fee_payment_method.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { type FunctionCall } from '@aztec/circuit-types';
import { type AztecAddress, type GasSettings } from '@aztec/circuits.js';
import { FunctionSelector, FunctionType } from '@aztec/foundation/abi';
import { type AztecAddress } from '@aztec/circuits.js';
import { GasTokenAddress } from '@aztec/protocol-contracts/gas-token';

import { type FeePaymentMethod } from './fee_payment_method.js';
Expand All @@ -23,38 +22,15 @@ export class NativeFeePaymentMethod implements FeePaymentMethod {
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 this.#gasTokenAddress;
}

/**
* Fee payments in the native gas token are always public.
* @returns false
*/
isPrivateFeePayment(): boolean {
return false;
}

/**
* Creates a function call to pay the fee in gas token.
* @param gasSettings - The gas settings.
* @returns A function call
*/
getFunctionCalls(gasSettings: GasSettings): Promise<FunctionCall[]> {
return Promise.resolve([
{
name: 'pay_fee',
to: this.#gasTokenAddress,
selector: FunctionSelector.fromSignature('pay_fee(Field)'),
type: FunctionType.PUBLIC,
isStatic: false,
args: [gasSettings.getFeeLimit()],
returnTypes: [],
},
]);
getFunctionCalls(): Promise<FunctionCall[]> {
return Promise.resolve([]);
}

isFeePayer(): Promise<boolean> {
return Promise.resolve(true);
}
}
6 changes: 5 additions & 1 deletion yarn-project/aztec.js/src/fee/private_fee_payment_method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ export class PrivateFeePaymentMethod implements FeePaymentMethod {
return this.paymentContract;
}

isFeePayer(): Promise<boolean> {
return Promise.resolve(false);
}

/**
* Creates a function call to pay the fee in the given asset.
* @param gasSettings - The gas settings.
Expand Down Expand Up @@ -80,7 +84,7 @@ export class PrivateFeePaymentMethod implements FeePaymentMethod {
return [
{
name: 'fee_entrypoint_private',
to: this.getPaymentContract(),
to: this.paymentContract,
selector: FunctionSelector.fromSignature('fee_entrypoint_private(Field,(Field),Field,Field)'),
type: FunctionType.PRIVATE,
isStatic: false,
Expand Down
4 changes: 4 additions & 0 deletions yarn-project/aztec.js/src/fee/public_fee_payment_method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ export class PublicFeePaymentMethod implements FeePaymentMethod {
return this.paymentContract;
}

isFeePayer(): Promise<boolean> {
return Promise.resolve(false);
}

/**
* Creates a function call to pay the fee in the given asset.
* @param gasSettings - The gas settings.
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/circuits.js/src/constants.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export const DA_BYTES_PER_FIELD = 32;
export const DA_GAS_PER_BYTE = 16;
export const FIXED_DA_GAS = 512;
export const CANONICAL_KEY_REGISTRY_ADDRESS = 0x1585e564a60e6ec974bc151b62705292ebfc75c33341986a47fd9749cedb567en;
export const DEPLOYER_CONTRACT_ADDRESS = 0x2e9c386f07e22a1d24e677ab70407b2dd0adbc7cafb9c822bf249685d6a2e4ccn;
export const DEPLOYER_CONTRACT_ADDRESS = 0x02f1337e8c79dd0247ccbde85241ad65ee991ae283a63479e095e51f0abbc7e3n;
export const GAS_TOKEN_ADDRESS = 0x283353eafd3802181f7c1461a4b68332afc6c04e95097bc51b5458d8a8abf4f9n;
export const AZTEC_ADDRESS_LENGTH = 1;
export const GAS_FEES_LENGTH = 2;
Expand Down
6 changes: 6 additions & 0 deletions yarn-project/circuits.js/src/contract/artifact_hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ export function computeArtifactMetadataHash(artifact: ContractArtifact) {
return sha256Fr(Buffer.from(JSON.stringify({ name: artifact.name }), 'utf-8'));
}

// TODO(palla) Minimize impact of contract instance deployer address changing, using the same
// trick as in the contracts above.
if (artifact.name === 'ContractInstanceDeployer') {
return sha256Fr(Buffer.from(JSON.stringify({ name: artifact.name }), 'utf-8'));
}

return sha256Fr(Buffer.from(JSON.stringify(metadata), 'utf-8'));
}

Expand Down
20 changes: 10 additions & 10 deletions yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
type AccountWalletWithSecretKey,
type AztecAddress,
type FeePaymentMethod,
NativeFeePaymentMethod,
PrivateFeePaymentMethod,
PublicFeePaymentMethod,
TxStatus,
Expand Down Expand Up @@ -58,16 +59,15 @@ describe('benchmarks/tx_size_fees', () => {

it.each<[string, () => FeePaymentMethod | undefined, bigint]>([
['no', () => undefined, 200021120n],
// TODO(palla/gas): Fix and reenable
// [
// 'native fee',
// () => new NativeFeePaymentMethod(),
// // DA:
// // non-rev: 1 nullifiers, overhead; rev: 2 note hashes, 1 nullifier, 1168 B enc note logs, 0 B enc logs, 0 B unenc logs, teardown
// // L2:
// // non-rev: 0; rev: 0
// 200289690n,
// ],
[
'native fee',
() => new NativeFeePaymentMethod(),
// DA:
// non-rev: 1 nullifiers, overhead; rev: 2 note hashes, 1 nullifier, 1168 B enc note logs, 0 B enc logs, 0 B unenc logs, teardown
// L2:
// non-rev: 0; rev: 0
200289690n,
],
[
'public fee',
() => new PublicFeePaymentMethod(token.address, fpc.address, aliceWallet),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ describe('e2e_fees dapp_subscription', () => {

beforeAll(async () => {
await t.applyBaseSnapshots();
await t.applyFPCSetupSnapshot();
await t.applyFundAliceWithBananas();
await t.applySetupSubscription();

Expand Down Expand Up @@ -103,8 +104,7 @@ describe('e2e_fees dapp_subscription', () => {
we then privately transfer `SUBSCRIPTION_AMOUNT` BC from alice to bob's subscription contract
PUBLIC TEARDOWN
then the FPC calls `pay_fee`, reducing its gas balance by `FEE_AMOUNT`, and increasing the sequencer's gas balance by `FEE_AMOUNT`
the FPC also publicly sends `REFUND` BC to alice
the FPC publicly sends `REFUND` BC to alice
*/

const { transactionFee } = await subscribe(
Expand Down Expand Up @@ -133,8 +133,7 @@ describe('e2e_fees dapp_subscription', () => {
we then privately transfer `SUBSCRIPTION_AMOUNT` BC from alice to bob's subscription contract
PUBLIC TEARDOWN
then the FPC calls `pay_fee`, reducing its gas balance by `FEE_AMOUNT`, and increasing the sequencer's gas balance by `FEE_AMOUNT`
the FPC also publicly sends `REFUND` BC to alice
the FPC publicly sends `REFUND` BC to alice
*/
const { transactionFee } = await subscribe(
new PublicFeePaymentMethod(bananaCoin.address, bananaFPC.address, aliceWallet),
Expand Down
1 change: 1 addition & 0 deletions yarn-project/end-to-end/src/e2e_fees/failures.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ describe('e2e_fees failures', () => {

beforeAll(async () => {
await t.applyBaseSnapshots();
await t.applyFPCSetupSnapshot();
({ aliceWallet, aliceAddress, sequencerAddress, bananaCoin, bananaFPC, gasSettings } = await t.setup());
});

Expand Down
Loading

0 comments on commit e48f63c

Please sign in to comment.