diff --git a/docs/components/snippet.js b/docs/components/snippet.js deleted file mode 100644 index 7496220cac5..00000000000 --- a/docs/components/snippet.js +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; - -const Spec_Placeholder = () => ( -

The design and implementation have largely changed since the original specification, and these docs will soon be updated to reflect the latest implementation. -

-); - -export default Spec_Placeholder; \ No newline at end of file diff --git a/docs/components/snippets.js b/docs/components/snippets.js new file mode 100644 index 00000000000..0c25f82db95 --- /dev/null +++ b/docs/components/snippets.js @@ -0,0 +1,31 @@ +import React from "react"; + +export const CLI_Fees = () => ( +

+ The CLI tool aztec-wallet takes the fee payment method via the + param: --payment method=fee_juice. See help for sending txs, eg{" "} + aztec-wallet help deploy +

+); + +export const Gas_Settings = () => ( +

+ Gas Settings used in transactions specify gas limits and + maximum fee rates (fees-per-gas) +

+); + +export const Gas_Components = () => ( +

+ The Gas and GasFees types each specify Data + availability and L2 cost components. +

+); + +export const Spec_Placeholder = () => ( +

+ The design and implementation have largely changed since the original + specification, and these docs will soon be updated to reflect the latest + implementation. +

+); diff --git a/docs/docs/aztec/concepts/accounts/_category_.json b/docs/docs/aztec/concepts/accounts/_category_.json index 2aae1b60db1..f55eaf4200d 100644 --- a/docs/docs/aztec/concepts/accounts/_category_.json +++ b/docs/docs/aztec/concepts/accounts/_category_.json @@ -1,6 +1,6 @@ { "label": "Accounts", - "position": 2, + "position": 4, "collapsible": true, "collapsed": true } diff --git a/docs/docs/aztec/concepts/fees.md b/docs/docs/aztec/concepts/fees.md new file mode 100644 index 00000000000..87d2ba0e3c7 --- /dev/null +++ b/docs/docs/aztec/concepts/fees.md @@ -0,0 +1,9 @@ +--- +title: Fees +sidebar_position: 0 +tags: [fees] +--- + +This section is currently being updated and will supplemented by information in the corresponding section of the protocol specifications. + +For a guide on how to pay fees programmatically, see [Paying fees in TypeScript](../../developers/guides/js_apps/pay_fees). diff --git a/docs/docs/aztec/concepts/storage/_category_.json b/docs/docs/aztec/concepts/storage/_category_.json index 18fc6d50b8c..0c73c07e563 100644 --- a/docs/docs/aztec/concepts/storage/_category_.json +++ b/docs/docs/aztec/concepts/storage/_category_.json @@ -1,6 +1,6 @@ { "label": "Storage", - "position": 0, + "position": 1, "collapsible": true, "collapsed": true } diff --git a/docs/docs/aztec/smart_contracts/contract_creation.md b/docs/docs/aztec/smart_contracts/contract_creation.md index 7947c8cad92..4106e0dd25e 100644 --- a/docs/docs/aztec/smart_contracts/contract_creation.md +++ b/docs/docs/aztec/smart_contracts/contract_creation.md @@ -3,7 +3,7 @@ title: Contract Deployment tags: [contracts, protocol] --- -import Spec_Placeholder from '/components/snippet'; +import { Spec_Placeholder } from '/components/snippets'; diff --git a/docs/docs/aztec/smart_contracts/functions/function_transforms.md b/docs/docs/aztec/smart_contracts/functions/function_transforms.md index 8ceedea172f..e7399d2b152 100644 --- a/docs/docs/aztec/smart_contracts/functions/function_transforms.md +++ b/docs/docs/aztec/smart_contracts/functions/function_transforms.md @@ -14,7 +14,6 @@ When you define a function in an Aztec contract, it undergoes several transforma - [Creating a context for the function](#context-creation) - [Handling function inputs](#private-and-public-input-injection) - [Processing return values](#return-value-handling) -- [Computing note hashes and nullifiers](#computing-note-hash-and-nullifier) - [Generating function signatures](#function-signature-generation) - [Generating contract artifacts](#contract-artifacts) @@ -155,7 +154,7 @@ fn compute_fn_signature_hash(fn_name: &str, parameters: &[Type]) -> u32 { - A string representation of the function is created, including the function name and parameter types - This signature string is then hashed using Keccak-256 -- The first 4 bytes of the resulting hash are coverted to a u32 integer +- The first 4 bytes of the resulting hash are converted to a u32 integer ### Integration into contract interface diff --git a/docs/docs/developers/guides/js_apps/pay_fees.md b/docs/docs/developers/guides/js_apps/pay_fees.md new file mode 100644 index 00000000000..60197b57532 --- /dev/null +++ b/docs/docs/developers/guides/js_apps/pay_fees.md @@ -0,0 +1,96 @@ +--- +title: How to Pay Fees +tags: [fees, transactions, developers] +--- + +There a several ways to pay for transaction fees, thanks to fee abstraction implemented in the Aztec protocol. + +This guide shows the various ways this can be done. For more of a background see [Fees on Aztec](../../../aztec/concepts/fees). + +## Methods to pay a tx fee + +### Natively via an existing balance of fee juice + +Either your own account or someone else's address has a balance of fee juice, and the transaction is paid for from this balance. + +### Natively via a balance of fee juice to be claimed + +Processing this transaction first claims bridged fee juice then is paid for from the balance, all in the same public/private tx. + +### Privately or publicly via a Fee Paying Contract + +A fee paying contract (FPC) is created and nominates a token that it accepts to then pay for txs in fee juice. So a user doesn't need to hold fee juice, they only need the token that the FPC accepts. + +## Fee Options + +Functions pertaining to sending a transaction, such as `deploy` and `send`, each include a `fee` variable defined with the following (optional) parameters: + +#include_code user_fee_options yarn-project/aztec.js/src/entrypoint/payload.ts javascript + + +### Fee Payment Method + +The `paymentMethod` is an object for the type of payment. Each of the implementations can be found [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/yarn-project/aztec.js/src/fee). For example: + +#include_code fee_juice_method yarn-project/aztec.js/src/fee/fee_juice_payment_method.ts javascript + +### Gas Settings + +#include_code gas_settings_vars yarn-project/stdlib/src/gas/gas_settings.ts javascript + +import { Gas_Components, Gas_Settings } from '/components/snippets'; + + + + + +### Other params + +Fee and gas padding params can be left to their default values, and the estimateGas boolean can be used when simulating a tx to calculate gas. + +With the fee options explained, lets do a paid transaction. + +## Examples + +### Pay with FeeJuice + +An account can be deployed directly via fee-juice payment if the address has been pre-funded. +This is done using the AccountManager as follows: + +#include_code pay_fee_juice_deploy yarn-project/end-to-end/src/e2e_fees/account_init.test.ts javascript + +Or to send a transaction from an account holding fee juice: +(Note: this example is a public token transfer call, but can equally be a private function call) + +#include_code pay_fee_juice_send yarn-project/end-to-end/src/e2e_fees/fee_juice_payments.test.ts javascript + +**The equivalent to specify fees via CLI...** + +import { CLI_Fees } from '/components/snippets'; + + + +See here to [Bridge Fee Juice](../../../developers/reference/environment_reference/cli_wallet_reference#bridge-fee-juice) via the CLI wallet. + +### Claim and pay + +After a user has sent fee juice from L1 to be bridged to L2, a transaction can be made that claims this to pay for itself, and make the transaction, in one. + +The claim object: + +#include_code claim_type_amount yarn-project/aztec.js/src/api/ethereum/portal_manager.ts javascript + +Calling a function on an object (in this case checking the balance of the fee juice contract) + +#include_code claim_and_pay yarn-project/end-to-end/src/e2e_fees/fee_juice_payments.test.ts javascript + + +### Fee Paying Contract + +Similarly with a fee paying contract, the fee payment method is created and used as follows: + +#include_code fpc yarn-project/end-to-end/src/e2e_fees/public_payments.test.ts javascript + +In this example, thanks to the FPC's `accepted_asset` being banana tokens, Alice only needs to hold this token and not fee juice. The function being called happens to also be a transfer of banana tokens to Bob. + +More on FPCs [here](https://github.com/AztecProtocol/aztec-packages/tree/#include_aztec_version/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr) diff --git a/docs/docs/developers/tutorials/codealong/contract_tutorials/token_contract.md b/docs/docs/developers/tutorials/codealong/contract_tutorials/token_contract.md index b3308fa477c..5aa6053ce90 100644 --- a/docs/docs/developers/tutorials/codealong/contract_tutorials/token_contract.md +++ b/docs/docs/developers/tutorials/codealong/contract_tutorials/token_contract.md @@ -410,7 +410,7 @@ aztec codegen target -o src/artifacts ### Token Bridge Contract -The [token bridge tutorial](./token_bridge/index.md) is a great follow up to this one. +The [token bridge tutorial](./token_bridge) is a great follow up to this one. It builds on the Token contract described here and goes into more detail about Aztec contract composability and Ethereum (L1) and Aztec (L2) cross-chain messaging. diff --git a/yarn-project/aztec.js/src/api/ethereum/portal_manager.ts b/yarn-project/aztec.js/src/api/ethereum/portal_manager.ts index 91bef9da838..1f516525f28 100644 --- a/yarn-project/aztec.js/src/api/ethereum/portal_manager.ts +++ b/yarn-project/aztec.js/src/api/ethereum/portal_manager.ts @@ -21,6 +21,8 @@ import { toFunctionSelector, } from 'viem'; +// docs:start:claim_type +// docs:start:claim_type_amount /** L1 to L2 message info to claim it on L2. */ export type L2Claim = { /** Secret for claiming. */ @@ -32,9 +34,11 @@ export type L2Claim = { /** Leaf index in the L1 to L2 message tree. */ messageLeafIndex: bigint; }; +// docs:end:claim_type /** L1 to L2 message info that corresponds to an amount to claim. */ export type L2AmountClaim = L2Claim & { /** Amount to claim */ claimAmount: bigint }; +// docs:end:claim_type_amount /** L1 to L2 message info that corresponds to an amount to claim with associated recipient. */ export type L2AmountClaimWithRecipient = L2AmountClaim & { diff --git a/yarn-project/aztec.js/src/entrypoint/payload.ts b/yarn-project/aztec.js/src/entrypoint/payload.ts index 9a29e3e503c..8e75d7e7aa9 100644 --- a/yarn-project/aztec.js/src/entrypoint/payload.ts +++ b/yarn-project/aztec.js/src/entrypoint/payload.ts @@ -21,6 +21,7 @@ export type FeeOptions = { gasSettings: GasSettings; }; +// docs:start:user_fee_options /** Fee options as set by a user. */ export type UserFeeOptions = { /** The fee payment method to use */ @@ -34,6 +35,7 @@ export type UserFeeOptions = { /** Percentage to pad the estimated gas limits by, if empty, defaults to 0.1. Only relevant if estimateGas is set. */ estimatedGasPadding?: number; }; +// docs:end:user_fee_options // These must match the values defined in: // - noir-projects/aztec-nr/aztec/src/entrypoint/app.nr diff --git a/yarn-project/aztec.js/src/fee/fee_juice_payment_method.ts b/yarn-project/aztec.js/src/fee/fee_juice_payment_method.ts index 1697be16811..1dc32d1bda5 100644 --- a/yarn-project/aztec.js/src/fee/fee_juice_payment_method.ts +++ b/yarn-project/aztec.js/src/fee/fee_juice_payment_method.ts @@ -4,10 +4,12 @@ import type { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { FeePaymentMethod } from './fee_payment_method.js'; +// docs:start:fee_juice_method /** * Pay fee directly in the Fee Juice. */ export class FeeJuicePaymentMethod implements FeePaymentMethod { + // docs:end:fee_juice_method constructor(protected sender: AztecAddress) {} getAsset() { diff --git a/yarn-project/end-to-end/src/e2e_fees/account_init.test.ts b/yarn-project/end-to-end/src/e2e_fees/account_init.test.ts index 067067877be..e3a7857ca45 100644 --- a/yarn-project/end-to-end/src/e2e_fees/account_init.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/account_init.test.ts @@ -88,8 +88,10 @@ describe('e2e_fees account_init', () => { const [bobsInitialGas] = await t.getGasBalanceFn(bobsAddress); expect(bobsInitialGas).toEqual(FEE_FUNDING_FOR_TESTER_ACCOUNT); + // docs:start:pay_fee_juice_deploy const paymentMethod = new FeeJuicePaymentMethod(bobsAddress); const tx = await bobsAccountManager.deploy({ fee: { paymentMethod } }).wait(); + // docs:end:pay_fee_juice_deploy expect(tx.transactionFee!).toBeGreaterThan(0n); await expect(t.getGasBalanceFn(bobsAddress)).resolves.toEqual([bobsInitialGas - tx.transactionFee!]); diff --git a/yarn-project/end-to-end/src/e2e_fees/fee_juice_payments.test.ts b/yarn-project/end-to-end/src/e2e_fees/fee_juice_payments.test.ts index d63b193293a..c934f4ed8d7 100644 --- a/yarn-project/end-to-end/src/e2e_fees/fee_juice_payments.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/fee_juice_payments.test.ts @@ -67,12 +67,14 @@ describe('e2e_fees Fee Juice payments', () => { it('claims bridged funds and pays with them on the same tx', async () => { const claim = await t.feeJuiceBridgeTestHarness.prepareTokensOnL1(FEE_FUNDING_FOR_TESTER_ACCOUNT, bobAddress); + // docs:start:claim_and_pay const paymentMethod = new FeeJuicePaymentMethodWithClaim(bobAddress, claim); const receipt = await feeJuiceContract .withWallet(bobWallet) .methods.check_balance(0n) .send({ fee: { gasSettings, paymentMethod } }) .wait(); + // docs:end:claim_and_pay const endBalance = await feeJuiceContract.methods.balance_of_public(bobAddress).simulate(); expect(endBalance).toBeGreaterThan(0n); @@ -84,11 +86,13 @@ describe('e2e_fees Fee Juice payments', () => { describe('with initial funds', () => { it('sends tx with payment in Fee Juice with public calls', async () => { const initialBalance = await feeJuiceContract.methods.balance_of_public(aliceAddress).simulate(); + // docs:start:pay_fee_juice_send const paymentMethod = new FeeJuicePaymentMethod(aliceAddress); const { transactionFee } = await bananaCoin.methods .transfer_in_public(aliceAddress, bobAddress, 1n, 0n) .send({ fee: { gasSettings, paymentMethod } }) .wait(); + // docs:end:pay_fee_juice_send expect(transactionFee).toBeGreaterThan(0n); const endBalance = await feeJuiceContract.methods.balance_of_public(aliceAddress).simulate(); expect(endBalance).toBeLessThan(initialBalance); diff --git a/yarn-project/end-to-end/src/e2e_fees/public_payments.test.ts b/yarn-project/end-to-end/src/e2e_fees/public_payments.test.ts index e4eb53e46d7..8f68e5a2c2e 100644 --- a/yarn-project/end-to-end/src/e2e_fees/public_payments.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/public_payments.test.ts @@ -59,6 +59,7 @@ describe('e2e_fees public_payment', () => { it('pays fees for tx that make public transfer', async () => { const bananasToSendToBob = 10n; + // docs:start:fpc const tx = await bananaCoin.methods .transfer_in_public(aliceAddress, bobAddress, bananasToSendToBob, 0) .send({ @@ -68,6 +69,7 @@ describe('e2e_fees public_payment', () => { }, }) .wait(); + // docs:end:fpc const feeAmount = tx.transactionFee!; diff --git a/yarn-project/stdlib/src/gas/gas_settings.ts b/yarn-project/stdlib/src/gas/gas_settings.ts index e0851c28411..767b682781d 100644 --- a/yarn-project/stdlib/src/gas/gas_settings.ts +++ b/yarn-project/stdlib/src/gas/gas_settings.ts @@ -8,6 +8,7 @@ import { z } from 'zod'; import { Gas, GasDimensions } from './gas.js'; import { GasFees } from './gas_fees.js'; +// docs:start:gas_settings_vars /** Gas usage and fees limits set by the transaction sender for different dimensions and phases. */ export class GasSettings { constructor( @@ -16,6 +17,7 @@ export class GasSettings { public readonly maxFeesPerGas: GasFees, public readonly maxPriorityFeesPerGas: GasFees, ) {} + // docs:end:gas_settings_vars static get schema() { return z