Skip to content

Commit

Permalink
feat: pay fees in native gas
Browse files Browse the repository at this point in the history
  • Loading branch information
alexghr committed Feb 12, 2024
1 parent ecc25e3 commit 80cc1cb
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { PXE, Tx, TxExecutionRequest } from '@aztec/circuit-types';

import { FeeOptions } from '../account/interface.js';
import { SentTx } from './sent_tx.js';

/**
Expand All @@ -11,6 +12,11 @@ export type SendMethodOptions = {
* Wether to skip the simulation of the public part of the transaction.
*/
skipPublicSimulation?: boolean;

/**
* The fee options for the transaction.
*/
fee?: FeeOptions;
};

/**
Expand Down
7 changes: 4 additions & 3 deletions yarn-project/aztec.js/src/contract/batch_call.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FunctionCall, TxExecutionRequest } from '@aztec/circuit-types';

import { Wallet } from '../account/index.js';
import { BaseContractInteraction } from './base_contract_interaction.js';
import { BaseContractInteraction, SendMethodOptions } from './base_contract_interaction.js';

/** A batch of function calls to be sent as a single transaction through a wallet. */
export class BatchCall extends BaseContractInteraction {
Expand All @@ -12,11 +12,12 @@ export class BatchCall extends BaseContractInteraction {
/**
* Create a transaction execution request that represents this batch, encoded and authenticated by the
* user's wallet, ready to be simulated.
* @param opts - An optional object containing additional configuration for the transaction.
* @returns A Promise that resolves to a transaction instance.
*/
public async create(): Promise<TxExecutionRequest> {
public async create(opts?: SendMethodOptions): Promise<TxExecutionRequest> {
if (!this.txRequest) {
this.txRequest = await this.wallet.createTxExecutionRequest(this.calls);
this.txRequest = await this.wallet.createTxExecutionRequest(this.calls, opts?.fee);
}
return this.txRequest;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,15 @@ export class ContractFunctionInteraction extends BaseContractInteraction {
/**
* Create a transaction execution request that represents this call, encoded and authenticated by the
* user's wallet, ready to be simulated.
* @param opts - An optional object containing additional configuration for the transaction.
* @returns A Promise that resolves to a transaction instance.
*/
public async create(): Promise<TxExecutionRequest> {
public async create(opts?: SendMethodOptions): Promise<TxExecutionRequest> {
if (this.functionDao.functionType === FunctionType.UNCONSTRAINED) {
throw new Error("Can't call `create` on an unconstrained function.");
}
if (!this.txRequest) {
this.txRequest = await this.wallet.createTxExecutionRequest([this.request()]);
this.txRequest = await this.wallet.createTxExecutionRequest([this.request()], opts?.fee);
}
return this.txRequest;
}
Expand Down
1 change: 1 addition & 0 deletions yarn-project/end-to-end/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@aztec/merkle-tree": "workspace:^",
"@aztec/noir-contracts": "workspace:^",
"@aztec/p2p": "workspace:^",
"@aztec/protocol-contracts": "workspace:^",
"@aztec/pxe": "workspace:^",
"@aztec/sequencer-client": "workspace:^",
"@aztec/types": "workspace:^",
Expand Down
62 changes: 62 additions & 0 deletions yarn-project/end-to-end/src/e2e_native_fee_payments.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { AztecAddress, ContractDeployer, NativeFeePaymentMethod } from '@aztec/aztec.js';
import { GasTokenContract, TokenContract } from '@aztec/noir-contracts';
import { getCanonicalGasToken } from '@aztec/protocol-contracts/gas-token';

import { setup } from './fixtures/utils.js';

describe('e2e_native_fee_payments', () => {
let aliceAddress: AztecAddress;
let _bobAddress: AztecAddress;
let sequencerAddress: AztecAddress;
let gasTokenContract: GasTokenContract;
let testContract: TokenContract;

beforeAll(async () => {
const { accounts, sequencer, wallet } = await setup(3);
sequencer?.updateSequencerConfig({
feeRecipient: accounts.at(-1)!.address,
});
const canonicalGasToken = getCanonicalGasToken();
const deployer = new ContractDeployer(canonicalGasToken.artifact, wallet);
const { contract } = await deployer
.deploy()
.send({
contractAddressSalt: canonicalGasToken.instance.salt,
})
.wait();

gasTokenContract = contract as GasTokenContract;
aliceAddress = accounts.at(0)!.address;
_bobAddress = accounts.at(1)!.address;
sequencerAddress = sequencer!.feeRecipient;

testContract = await TokenContract.deploy(wallet, aliceAddress, 'Test', 'TEST', 1).send().deployed();

// Alice gets a balance of 1000 gas token
await gasTokenContract.methods.redeem_bridged_balance(1000).send().wait();
}, 100_000);

it('deploys gas token contract at canonical address', () => {
expect(gasTokenContract.address).toEqual(getCanonicalGasToken().address);
});

it('pays out the expected fee to the sequencer', async () => {
await testContract.methods
.mint_public(aliceAddress, 1000)
.send({
fee: {
maxFee: 1,
paymentMethod: new NativeFeePaymentMethod(),
},
})
.wait();

const [sequencerBalance, aliceBalance] = await Promise.all([
gasTokenContract.methods.balance_of(sequencerAddress).view(),
gasTokenContract.methods.balance_of(aliceAddress).view(),
]);

expect(sequencerBalance).toEqual(1n);
expect(aliceBalance).toEqual(999n);
});
});
1 change: 1 addition & 0 deletions yarn-project/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ __metadata:
"@aztec/merkle-tree": "workspace:^"
"@aztec/noir-contracts": "workspace:^"
"@aztec/p2p": "workspace:^"
"@aztec/protocol-contracts": "workspace:^"
"@aztec/pxe": "workspace:^"
"@aztec/sequencer-client": "workspace:^"
"@aztec/types": "workspace:^"
Expand Down

0 comments on commit 80cc1cb

Please sign in to comment.