@aztec/aztec.js 0.40.1 → 0.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/account/index.d.ts +2 -2
- package/dest/account/index.d.ts.map +1 -1
- package/dest/account/interface.d.ts +16 -1
- package/dest/account/interface.d.ts.map +1 -1
- package/dest/account/interface.js +1 -1
- package/dest/account/wallet.d.ts +2 -2
- package/dest/account/wallet.d.ts.map +1 -1
- package/dest/account_manager/deploy_account_method.d.ts.map +1 -1
- package/dest/account_manager/deploy_account_method.js +8 -5
- package/dest/account_manager/index.d.ts +1 -1
- package/dest/account_manager/index.d.ts.map +1 -1
- package/dest/account_manager/index.js +2 -1
- package/dest/api/abi.d.ts +2 -2
- package/dest/api/abi.d.ts.map +1 -1
- package/dest/api/abi.js +1 -1
- package/dest/api/fee.d.ts +2 -0
- package/dest/api/fee.d.ts.map +1 -1
- package/dest/api/fee.js +3 -1
- package/dest/contract/base_contract_interaction.d.ts +7 -6
- package/dest/contract/base_contract_interaction.d.ts.map +1 -1
- package/dest/contract/base_contract_interaction.js +20 -9
- package/dest/contract/batch_call.d.ts +11 -0
- package/dest/contract/batch_call.d.ts.map +1 -1
- package/dest/contract/batch_call.js +50 -2
- package/dest/contract/contract_function_interaction.d.ts +2 -7
- package/dest/contract/contract_function_interaction.d.ts.map +1 -1
- package/dest/contract/contract_function_interaction.js +22 -36
- package/dest/contract/deploy_method.d.ts +5 -1
- package/dest/contract/deploy_method.d.ts.map +1 -1
- package/dest/contract/deploy_method.js +22 -6
- package/dest/contract/get_gas_limits.d.ts +1 -1
- package/dest/contract/get_gas_limits.d.ts.map +1 -1
- package/dest/contract/get_gas_limits.js +5 -3
- package/dest/contract/sent_tx.js +2 -2
- package/dest/entrypoint/default_entrypoint.d.ts.map +1 -1
- package/dest/entrypoint/default_entrypoint.js +6 -2
- package/dest/entrypoint/default_multi_call_entrypoint.d.ts.map +1 -1
- package/dest/entrypoint/default_multi_call_entrypoint.js +7 -5
- package/dest/entrypoint/payload.d.ts +26 -9
- package/dest/entrypoint/payload.d.ts.map +1 -1
- package/dest/entrypoint/payload.js +51 -28
- package/dest/fee/fee_payment_method.d.ts +6 -7
- package/dest/fee/fee_payment_method.d.ts.map +1 -1
- package/dest/fee/native_fee_payment_method.d.ts +5 -25
- package/dest/fee/native_fee_payment_method.d.ts.map +1 -1
- package/dest/fee/native_fee_payment_method.js +9 -45
- package/dest/fee/native_fee_payment_method_with_claim.d.ts +17 -0
- package/dest/fee/native_fee_payment_method_with_claim.d.ts.map +1 -0
- package/dest/fee/native_fee_payment_method_with_claim.js +32 -0
- package/dest/fee/no_fee_payment_method.d.ts +13 -0
- package/dest/fee/no_fee_payment_method.d.ts.map +1 -0
- package/dest/fee/no_fee_payment_method.js +17 -0
- package/dest/fee/private_fee_payment_method.d.ts +1 -5
- package/dest/fee/private_fee_payment_method.d.ts.map +1 -1
- package/dest/fee/private_fee_payment_method.js +15 -12
- package/dest/fee/public_fee_payment_method.d.ts +1 -5
- package/dest/fee/public_fee_payment_method.d.ts.map +1 -1
- package/dest/fee/public_fee_payment_method.js +15 -12
- package/dest/index.d.ts +11 -12
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +10 -11
- package/dest/rpc_clients/pxe_client.js +3 -3
- package/dest/utils/authwit.d.ts.map +1 -1
- package/dest/utils/authwit.js +2 -6
- package/dest/utils/cheat_codes.js +3 -3
- package/dest/wallet/account_wallet.d.ts +12 -1
- package/dest/wallet/account_wallet.d.ts.map +1 -1
- package/dest/wallet/account_wallet.js +58 -4
- package/dest/wallet/base_wallet.d.ts +10 -3
- package/dest/wallet/base_wallet.d.ts.map +1 -1
- package/dest/wallet/base_wallet.js +12 -3
- package/dest/wallet/create_recipient.d.ts.map +1 -1
- package/dest/wallet/create_recipient.js +3 -1
- package/dest/wallet/signerless_wallet.d.ts +2 -1
- package/dest/wallet/signerless_wallet.d.ts.map +1 -1
- package/dest/wallet/signerless_wallet.js +9 -6
- package/package.json +7 -7
- package/src/account/index.ts +2 -2
- package/src/account/interface.ts +17 -1
- package/src/account/wallet.ts +2 -2
- package/src/account_manager/deploy_account_method.ts +11 -3
- package/src/account_manager/index.ts +5 -1
- package/src/api/abi.ts +2 -2
- package/src/api/fee.ts +2 -0
- package/src/contract/base_contract_interaction.ts +32 -8
- package/src/contract/batch_call.ts +77 -1
- package/src/contract/contract_function_interaction.ts +31 -34
- package/src/contract/deploy_method.ts +23 -6
- package/src/contract/get_gas_limits.ts +4 -3
- package/src/contract/sent_tx.ts +1 -1
- package/src/entrypoint/default_entrypoint.ts +7 -1
- package/src/entrypoint/default_multi_call_entrypoint.ts +6 -4
- package/src/entrypoint/payload.ts +61 -25
- package/src/fee/fee_payment_method.ts +6 -8
- package/src/fee/native_fee_payment_method.ts +8 -46
- package/src/fee/native_fee_payment_method_with_claim.ts +33 -0
- package/src/fee/no_fee_payment_method.ts +23 -0
- package/src/fee/private_fee_payment_method.ts +15 -14
- package/src/fee/public_fee_payment_method.ts +15 -18
- package/src/index.ts +34 -32
- package/src/rpc_clients/pxe_client.ts +2 -2
- package/src/utils/authwit.ts +1 -5
- package/src/utils/cheat_codes.ts +3 -3
- package/src/wallet/account_wallet.ts +65 -3
- package/src/wallet/base_wallet.ts +21 -3
- package/src/wallet/create_recipient.ts +2 -0
- package/src/wallet/signerless_wallet.ts +10 -6
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { type FunctionCall, type TxExecutionRequest } from '@aztec/circuit-types';
|
|
2
|
+
import { FunctionType, decodeReturnValues } from '@aztec/foundation/abi';
|
|
2
3
|
|
|
3
4
|
import { type Wallet } from '../account/index.js';
|
|
4
5
|
import { BaseContractInteraction, type SendMethodOptions } from './base_contract_interaction.js';
|
|
6
|
+
import type { SimulateMethodOptions } from './contract_function_interaction.js';
|
|
5
7
|
|
|
6
8
|
/** A batch of function calls to be sent as a single transaction through a wallet. */
|
|
7
9
|
export class BatchCall extends BaseContractInteraction {
|
|
@@ -18,9 +20,83 @@ export class BatchCall extends BaseContractInteraction {
|
|
|
18
20
|
public async create(opts?: SendMethodOptions): Promise<TxExecutionRequest> {
|
|
19
21
|
if (!this.txRequest) {
|
|
20
22
|
const calls = this.calls;
|
|
21
|
-
const fee = opts?.estimateGas ? await this.
|
|
23
|
+
const fee = opts?.estimateGas ? await this.getFeeOptionsFromEstimatedGas({ calls, fee: opts?.fee }) : opts?.fee;
|
|
22
24
|
this.txRequest = await this.wallet.createTxExecutionRequest({ calls, fee });
|
|
23
25
|
}
|
|
24
26
|
return this.txRequest;
|
|
25
27
|
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Simulate a transaction and get its return values
|
|
31
|
+
* Differs from prove in a few important ways:
|
|
32
|
+
* 1. It returns the values of the function execution
|
|
33
|
+
* 2. It supports `unconstrained`, `private` and `public` functions
|
|
34
|
+
*
|
|
35
|
+
* @param options - An optional object containing additional configuration for the transaction.
|
|
36
|
+
* @returns The result of the transaction as returned by the contract function.
|
|
37
|
+
*/
|
|
38
|
+
public async simulate(options: SimulateMethodOptions = {}): Promise<any> {
|
|
39
|
+
const { calls, unconstrained } = this.calls.reduce<{
|
|
40
|
+
/**
|
|
41
|
+
* Keep track of the number of private calls to retrieve the return values
|
|
42
|
+
*/
|
|
43
|
+
privateIndex: 0;
|
|
44
|
+
/**
|
|
45
|
+
* Keep track of the number of private calls to retrieve the return values
|
|
46
|
+
*/
|
|
47
|
+
publicIndex: 0;
|
|
48
|
+
/**
|
|
49
|
+
* The public and private function calls in the batch
|
|
50
|
+
*/
|
|
51
|
+
calls: [FunctionCall, number, number][];
|
|
52
|
+
/**
|
|
53
|
+
* The unconstrained function calls in the batch.
|
|
54
|
+
*/
|
|
55
|
+
unconstrained: [FunctionCall, number][];
|
|
56
|
+
}>(
|
|
57
|
+
(acc, current, index) => {
|
|
58
|
+
if (current.type === FunctionType.UNCONSTRAINED) {
|
|
59
|
+
acc.unconstrained.push([current, index]);
|
|
60
|
+
} else {
|
|
61
|
+
acc.calls.push([
|
|
62
|
+
current,
|
|
63
|
+
index,
|
|
64
|
+
current.type === FunctionType.PRIVATE ? acc.privateIndex++ : acc.publicIndex++,
|
|
65
|
+
]);
|
|
66
|
+
}
|
|
67
|
+
return acc;
|
|
68
|
+
},
|
|
69
|
+
{ calls: [], unconstrained: [], publicIndex: 0, privateIndex: 0 },
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const txRequest = await this.wallet.createTxExecutionRequest({ calls: calls.map(indexedCall => indexedCall[0]) });
|
|
73
|
+
|
|
74
|
+
const unconstrainedCalls = unconstrained.map(async indexedCall => {
|
|
75
|
+
const call = indexedCall[0];
|
|
76
|
+
return [await this.wallet.simulateUnconstrained(call.name, call.args, call.to, options?.from), indexedCall[1]];
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const [unconstrainedResults, simulatedTx] = await Promise.all([
|
|
80
|
+
Promise.all(unconstrainedCalls),
|
|
81
|
+
this.wallet.simulateTx(txRequest, true, options?.from),
|
|
82
|
+
]);
|
|
83
|
+
|
|
84
|
+
const results: any[] = [];
|
|
85
|
+
|
|
86
|
+
unconstrainedResults.forEach(([result, index]) => {
|
|
87
|
+
results[index] = result;
|
|
88
|
+
});
|
|
89
|
+
calls.forEach(([call, callIndex, resultIndex]) => {
|
|
90
|
+
// As account entrypoints are private, for private functions we retrieve the return values from the first nested call
|
|
91
|
+
// since we're interested in the first set of values AFTER the account entrypoint
|
|
92
|
+
// For public functions we retrieve the first values directly from the public output.
|
|
93
|
+
const rawReturnValues =
|
|
94
|
+
call.type == FunctionType.PRIVATE
|
|
95
|
+
? simulatedTx.privateReturnValues?.nested?.[resultIndex].values
|
|
96
|
+
: simulatedTx.publicOutput?.publicReturnValues?.[resultIndex].values;
|
|
97
|
+
|
|
98
|
+
results[callIndex] = rawReturnValues ? decodeReturnValues(call.returnTypes, rawReturnValues) : [];
|
|
99
|
+
});
|
|
100
|
+
return results;
|
|
101
|
+
}
|
|
26
102
|
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type AztecAddress,
|
|
3
|
-
import {
|
|
1
|
+
import type { FunctionCall, TxExecutionRequest } from '@aztec/circuit-types';
|
|
2
|
+
import { type AztecAddress, type GasSettings } from '@aztec/circuits.js';
|
|
3
|
+
import {
|
|
4
|
+
type FunctionAbi,
|
|
5
|
+
FunctionSelector,
|
|
6
|
+
FunctionType,
|
|
7
|
+
decodeReturnValues,
|
|
8
|
+
encodeArguments,
|
|
9
|
+
} from '@aztec/foundation/abi';
|
|
4
10
|
|
|
5
11
|
import { type Wallet } from '../account/wallet.js';
|
|
6
12
|
import { BaseContractInteraction, type SendMethodOptions } from './base_contract_interaction.js';
|
|
@@ -48,7 +54,7 @@ export class ContractFunctionInteraction extends BaseContractInteraction {
|
|
|
48
54
|
}
|
|
49
55
|
if (!this.txRequest) {
|
|
50
56
|
const calls = [this.request()];
|
|
51
|
-
const fee = opts?.estimateGas ? await this.
|
|
57
|
+
const fee = opts?.estimateGas ? await this.getFeeOptionsFromEstimatedGas({ calls, fee: opts?.fee }) : opts?.fee;
|
|
52
58
|
this.txRequest = await this.wallet.createTxExecutionRequest({ calls, fee });
|
|
53
59
|
}
|
|
54
60
|
return this.txRequest;
|
|
@@ -61,8 +67,15 @@ export class ContractFunctionInteraction extends BaseContractInteraction {
|
|
|
61
67
|
*/
|
|
62
68
|
public request(): FunctionCall {
|
|
63
69
|
const args = encodeArguments(this.functionDao, this.args);
|
|
64
|
-
|
|
65
|
-
|
|
70
|
+
return {
|
|
71
|
+
name: this.functionDao.name,
|
|
72
|
+
args,
|
|
73
|
+
selector: FunctionSelector.fromNameAndParameters(this.functionDao.name, this.functionDao.parameters),
|
|
74
|
+
type: this.functionDao.functionType,
|
|
75
|
+
to: this.contractAddress,
|
|
76
|
+
isStatic: this.functionDao.isStatic,
|
|
77
|
+
returnTypes: this.functionDao.returnTypes,
|
|
78
|
+
};
|
|
66
79
|
}
|
|
67
80
|
|
|
68
81
|
/**
|
|
@@ -70,42 +83,26 @@ export class ContractFunctionInteraction extends BaseContractInteraction {
|
|
|
70
83
|
* Differs from prove in a few important ways:
|
|
71
84
|
* 1. It returns the values of the function execution
|
|
72
85
|
* 2. It supports `unconstrained`, `private` and `public` functions
|
|
73
|
-
* 3. For `private` execution it:
|
|
74
|
-
* 3.a SKIPS the entrypoint and starts directly at the function
|
|
75
|
-
* 4. For `public` execution it:
|
|
76
|
-
* 4.a Removes the `txRequest` value after ended simulation
|
|
77
|
-
* 4.b Ignores the `from` in the options
|
|
78
86
|
*
|
|
79
87
|
* @param options - An optional object containing additional configuration for the transaction.
|
|
80
88
|
* @returns The result of the transaction as returned by the contract function.
|
|
81
89
|
*/
|
|
82
90
|
public async simulate(options: SimulateMethodOptions = {}): Promise<any> {
|
|
83
91
|
if (this.functionDao.functionType == FunctionType.UNCONSTRAINED) {
|
|
84
|
-
return this.wallet.
|
|
92
|
+
return this.wallet.simulateUnconstrained(this.functionDao.name, this.args, this.contractAddress, options?.from);
|
|
85
93
|
}
|
|
86
94
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const packedArgs = PackedValues.fromValues(encodeArguments(this.functionDao, this.args));
|
|
90
|
-
const gasSettings = options.gasSettings ?? GasSettings.simulation();
|
|
95
|
+
const txRequest = await this.create();
|
|
96
|
+
const simulatedTx = await this.wallet.simulateTx(txRequest, true, options?.from);
|
|
91
97
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const flattened = simulatedTx.privateReturnValues;
|
|
102
|
-
return flattened ? decodeReturnValues(this.functionDao, flattened) : [];
|
|
103
|
-
} else {
|
|
104
|
-
const txRequest = await this.create();
|
|
105
|
-
const simulatedTx = await this.wallet.simulateTx(txRequest, true);
|
|
106
|
-
this.txRequest = undefined;
|
|
107
|
-
const flattened = simulatedTx.publicOutput?.publicReturnValues;
|
|
108
|
-
return flattened ? decodeReturnValues(this.functionDao, flattened) : [];
|
|
109
|
-
}
|
|
98
|
+
// As account entrypoints are private, for private functions we retrieve the return values from the first nested call
|
|
99
|
+
// since we're interested in the first set of values AFTER the account entrypoint
|
|
100
|
+
// For public functions we retrieve the first values directly from the public output.
|
|
101
|
+
const rawReturnValues =
|
|
102
|
+
this.functionDao.functionType == FunctionType.PRIVATE
|
|
103
|
+
? simulatedTx.privateReturnValues?.nested?.[0].values
|
|
104
|
+
: simulatedTx.publicOutput?.publicReturnValues?.[0].values;
|
|
105
|
+
|
|
106
|
+
return rawReturnValues ? decodeReturnValues(this.functionDao.returnTypes, rawReturnValues) : [];
|
|
110
107
|
}
|
|
111
108
|
}
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
} from '@aztec/circuits.js';
|
|
8
8
|
import { type ContractArtifact, type FunctionArtifact, getInitializer } from '@aztec/foundation/abi';
|
|
9
9
|
import { type Fr } from '@aztec/foundation/fields';
|
|
10
|
-
import { createDebugLogger } from '@aztec/foundation/log';
|
|
11
10
|
import { type ContractInstanceWithAddress } from '@aztec/types/contracts';
|
|
12
11
|
|
|
13
12
|
import { type Wallet } from '../account/index.js';
|
|
@@ -53,8 +52,6 @@ export class DeployMethod<TContract extends ContractBase = Contract> extends Bas
|
|
|
53
52
|
/** Cached call to request() */
|
|
54
53
|
private functionCalls?: ExecutionRequestInit;
|
|
55
54
|
|
|
56
|
-
private log = createDebugLogger('aztec:js:deploy_method');
|
|
57
|
-
|
|
58
55
|
constructor(
|
|
59
56
|
private publicKeysHash: Fr,
|
|
60
57
|
wallet: Wallet,
|
|
@@ -79,8 +76,6 @@ export class DeployMethod<TContract extends ContractBase = Contract> extends Bas
|
|
|
79
76
|
public async create(options: DeployOptions = {}): Promise<TxExecutionRequest> {
|
|
80
77
|
if (!this.txRequest) {
|
|
81
78
|
this.txRequest = await this.wallet.createTxExecutionRequest(await this.request(options));
|
|
82
|
-
// TODO: Should we add the contracts to the DB here, or once the tx has been sent or mined?
|
|
83
|
-
await this.wallet.registerContract({ artifact: this.artifact, instance: this.instance! });
|
|
84
79
|
}
|
|
85
80
|
return this.txRequest;
|
|
86
81
|
}
|
|
@@ -98,6 +93,14 @@ export class DeployMethod<TContract extends ContractBase = Contract> extends Bas
|
|
|
98
93
|
*/
|
|
99
94
|
public async request(options: DeployOptions = {}): Promise<ExecutionRequestInit> {
|
|
100
95
|
if (!this.functionCalls) {
|
|
96
|
+
// TODO: Should we add the contracts to the DB here, or once the tx has been sent or mined?
|
|
97
|
+
// Note that we need to run this registerContract here so it's available when computeFeeOptionsFromEstimatedGas
|
|
98
|
+
// runs, since it needs the contract to have been registered in order to estimate gas for its initialization,
|
|
99
|
+
// in case the initializer is public. This hints at the need of having "transient" contracts scoped to a
|
|
100
|
+
// simulation, so we can run the simulation with a set of contracts, but only "commit" them to the wallet
|
|
101
|
+
// once this tx has gone through.
|
|
102
|
+
await this.wallet.registerContract({ artifact: this.artifact, instance: this.getInstance(options) });
|
|
103
|
+
|
|
101
104
|
const deployment = await this.getDeploymentFunctionCalls(options);
|
|
102
105
|
const bootstrap = await this.getInitializeFunctionCalls(options);
|
|
103
106
|
|
|
@@ -113,7 +116,13 @@ export class DeployMethod<TContract extends ContractBase = Contract> extends Bas
|
|
|
113
116
|
};
|
|
114
117
|
|
|
115
118
|
if (options.estimateGas) {
|
|
116
|
-
|
|
119
|
+
// Why do we call this seemingly idempotent getter method here, without using its return value?
|
|
120
|
+
// This call pushes a capsule required for contract class registration under the hood. And since
|
|
121
|
+
// capsules are a stack, when we run the simulation for estimating gas, we consume the capsule
|
|
122
|
+
// that was meant for the actual call. So we need to push it again here. Hopefully this design
|
|
123
|
+
// will go away soon.
|
|
124
|
+
await this.getDeploymentFunctionCalls(options);
|
|
125
|
+
request.fee = await this.getFeeOptionsFromEstimatedGas(request);
|
|
117
126
|
}
|
|
118
127
|
|
|
119
128
|
this.functionCalls = request;
|
|
@@ -233,6 +242,14 @@ export class DeployMethod<TContract extends ContractBase = Contract> extends Bas
|
|
|
233
242
|
return super.prove(options);
|
|
234
243
|
}
|
|
235
244
|
|
|
245
|
+
/**
|
|
246
|
+
* Estimates gas cost for this deployment operation.
|
|
247
|
+
* @param options - Options.
|
|
248
|
+
*/
|
|
249
|
+
public override estimateGas(options?: Omit<DeployOptions, 'estimateGas' | 'skipPublicSimulation'>) {
|
|
250
|
+
return super.estimateGas(options);
|
|
251
|
+
}
|
|
252
|
+
|
|
236
253
|
/** Return this deployment address. */
|
|
237
254
|
public get address() {
|
|
238
255
|
return this.instance?.address;
|
|
@@ -6,8 +6,10 @@ import { Gas } from '@aztec/circuits.js';
|
|
|
6
6
|
* Note that public gas usage is only accounted for if the publicOutput is present.
|
|
7
7
|
* @param pad - Percentage to pad the suggested gas limits by, defaults to 10%.
|
|
8
8
|
*/
|
|
9
|
-
export function getGasLimits(simulatedTx: SimulatedTx, pad = 0.1) {
|
|
10
|
-
const privateGasUsed = simulatedTx.tx.data.publicInputs.end.gasUsed
|
|
9
|
+
export function getGasLimits(simulatedTx: SimulatedTx, simulationTeardownGasLimits: Gas, pad = 0.1) {
|
|
10
|
+
const privateGasUsed = simulatedTx.tx.data.publicInputs.end.gasUsed
|
|
11
|
+
.sub(simulationTeardownGasLimits)
|
|
12
|
+
.add(simulatedTx.tx.data.forPublic?.endNonRevertibleData.gasUsed ?? Gas.empty());
|
|
11
13
|
if (simulatedTx.publicOutput) {
|
|
12
14
|
const publicGasUsed = Object.values(simulatedTx.publicOutput.gasUsed)
|
|
13
15
|
.filter(Boolean)
|
|
@@ -19,6 +21,5 @@ export function getGasLimits(simulatedTx: SimulatedTx, pad = 0.1) {
|
|
|
19
21
|
teardownGas: teardownGas.mul(1 + pad),
|
|
20
22
|
};
|
|
21
23
|
}
|
|
22
|
-
|
|
23
24
|
return { totalGas: privateGasUsed.mul(1 + pad), teardownGas: Gas.empty() };
|
|
24
25
|
}
|
package/src/contract/sent_tx.ts
CHANGED
|
@@ -72,7 +72,7 @@ export class SentTx {
|
|
|
72
72
|
throw new Error('Cannot set debug to true if waitForNotesSync is false');
|
|
73
73
|
}
|
|
74
74
|
const receipt = await this.waitForReceipt(opts);
|
|
75
|
-
if (
|
|
75
|
+
if (receipt.status !== TxStatus.SUCCESS && !opts?.dontThrowOnRevert) {
|
|
76
76
|
throw new Error(
|
|
77
77
|
`Transaction ${await this.getTxHash()} was ${receipt.status}. Reason: ${receipt.error ?? 'unknown'}`,
|
|
78
78
|
);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { PackedValues, TxExecutionRequest } from '@aztec/circuit-types';
|
|
2
2
|
import { GasSettings, TxContext } from '@aztec/circuits.js';
|
|
3
|
+
import { FunctionType } from '@aztec/foundation/abi';
|
|
3
4
|
|
|
4
5
|
import { type EntrypointInterface, type ExecutionRequestInit } from './entrypoint.js';
|
|
5
6
|
|
|
@@ -17,13 +18,18 @@ export class DefaultEntrypoint implements EntrypointInterface {
|
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
const call = calls[0];
|
|
21
|
+
|
|
22
|
+
if (call.type !== FunctionType.PRIVATE) {
|
|
23
|
+
throw new Error('Public entrypoints are not allowed');
|
|
24
|
+
}
|
|
25
|
+
|
|
20
26
|
const entrypointPackedValues = PackedValues.fromValues(call.args);
|
|
21
27
|
const gasSettings = exec.fee?.gasSettings ?? GasSettings.default();
|
|
22
28
|
const txContext = new TxContext(this.chainId, this.protocolVersion, gasSettings);
|
|
23
29
|
return Promise.resolve(
|
|
24
30
|
new TxExecutionRequest(
|
|
25
31
|
call.to,
|
|
26
|
-
call.
|
|
32
|
+
call.selector,
|
|
27
33
|
entrypointPackedValues.hash,
|
|
28
34
|
txContext,
|
|
29
35
|
[...packedArguments, entrypointPackedValues],
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type EntrypointInterface, EntrypointPayload, type ExecutionRequestInit } from '@aztec/aztec.js/entrypoint';
|
|
2
2
|
import { PackedValues, TxExecutionRequest } from '@aztec/circuit-types';
|
|
3
|
-
import { type AztecAddress,
|
|
4
|
-
import { type FunctionAbi, encodeArguments } from '@aztec/foundation/abi';
|
|
3
|
+
import { type AztecAddress, GasSettings, TxContext } from '@aztec/circuits.js';
|
|
4
|
+
import { type FunctionAbi, FunctionSelector, encodeArguments } from '@aztec/foundation/abi';
|
|
5
5
|
import { getCanonicalMultiCallEntrypointAddress } from '@aztec/protocol-contracts/multi-call-entrypoint';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -24,7 +24,7 @@ export class DefaultMultiCallEntrypoint implements EntrypointInterface {
|
|
|
24
24
|
const txRequest = TxExecutionRequest.from({
|
|
25
25
|
firstCallArgsHash: entrypointPackedArgs.hash,
|
|
26
26
|
origin: this.address,
|
|
27
|
-
|
|
27
|
+
functionSelector: FunctionSelector.fromNameAndParameters(abi.name, abi.parameters),
|
|
28
28
|
txContext: new TxContext(this.chainId, this.version, gasSettings),
|
|
29
29
|
argsOfCalls: [...payload.packedArguments, ...packedArguments, entrypointPackedArgs],
|
|
30
30
|
authWitnesses,
|
|
@@ -37,8 +37,9 @@ export class DefaultMultiCallEntrypoint implements EntrypointInterface {
|
|
|
37
37
|
return {
|
|
38
38
|
name: 'entrypoint',
|
|
39
39
|
isInitializer: false,
|
|
40
|
-
functionType: '
|
|
40
|
+
functionType: 'private',
|
|
41
41
|
isInternal: false,
|
|
42
|
+
isStatic: false,
|
|
42
43
|
parameters: [
|
|
43
44
|
{
|
|
44
45
|
name: 'app_payload',
|
|
@@ -73,6 +74,7 @@ export class DefaultMultiCallEntrypoint implements EntrypointInterface {
|
|
|
73
74
|
},
|
|
74
75
|
},
|
|
75
76
|
{ name: 'is_public', type: { kind: 'boolean' } },
|
|
77
|
+
{ name: 'is_static', type: { kind: 'boolean' } },
|
|
76
78
|
],
|
|
77
79
|
},
|
|
78
80
|
},
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Fr, type GasSettings, GeneratorIndex } from '@aztec/circuits.js';
|
|
1
|
+
import { FunctionCall, PackedValues } from '@aztec/circuit-types';
|
|
2
|
+
import { type AztecAddress, Fr, type GasSettings, GeneratorIndex } from '@aztec/circuits.js';
|
|
3
|
+
import { FunctionType } from '@aztec/foundation/abi';
|
|
3
4
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
4
5
|
import { pedersenHash } from '@aztec/foundation/crypto';
|
|
5
6
|
import { type Tuple } from '@aztec/foundation/serialize';
|
|
@@ -33,17 +34,19 @@ type EncodedFunctionCall = {
|
|
|
33
34
|
target_address: Fr;
|
|
34
35
|
/** Whether the function is public or private */
|
|
35
36
|
is_public: boolean;
|
|
37
|
+
/** Whether the function can alter state */
|
|
38
|
+
is_static: boolean;
|
|
36
39
|
};
|
|
37
40
|
/* eslint-enable camelcase */
|
|
38
41
|
|
|
39
42
|
/** Assembles an entrypoint payload */
|
|
40
|
-
export class EntrypointPayload {
|
|
43
|
+
export abstract class EntrypointPayload {
|
|
41
44
|
#packedArguments: PackedValues[] = [];
|
|
42
45
|
#functionCalls: EncodedFunctionCall[] = [];
|
|
43
46
|
#nonce = Fr.random();
|
|
44
47
|
#generatorIndex: number;
|
|
45
48
|
|
|
46
|
-
|
|
49
|
+
protected constructor(functionCalls: FunctionCall[], generatorIndex: number) {
|
|
47
50
|
for (const call of functionCalls) {
|
|
48
51
|
this.#packedArguments.push(PackedValues.fromValues(call.args));
|
|
49
52
|
}
|
|
@@ -51,9 +54,10 @@ export class EntrypointPayload {
|
|
|
51
54
|
/* eslint-disable camelcase */
|
|
52
55
|
this.#functionCalls = functionCalls.map((call, index) => ({
|
|
53
56
|
args_hash: this.#packedArguments[index].hash,
|
|
54
|
-
function_selector: call.
|
|
57
|
+
function_selector: call.selector.toField(),
|
|
55
58
|
target_address: call.to.toField(),
|
|
56
|
-
is_public:
|
|
59
|
+
is_public: call.type == FunctionType.PUBLIC,
|
|
60
|
+
is_static: call.isStatic,
|
|
57
61
|
}));
|
|
58
62
|
/* eslint-enable camelcase */
|
|
59
63
|
|
|
@@ -89,17 +93,7 @@ export class EntrypointPayload {
|
|
|
89
93
|
* Serializes the payload to an array of fields
|
|
90
94
|
* @returns The fields of the payload
|
|
91
95
|
*/
|
|
92
|
-
toFields(): Fr[]
|
|
93
|
-
return [
|
|
94
|
-
...this.#functionCalls.flatMap(call => [
|
|
95
|
-
call.args_hash,
|
|
96
|
-
call.function_selector,
|
|
97
|
-
call.target_address,
|
|
98
|
-
new Fr(call.is_public),
|
|
99
|
-
]),
|
|
100
|
-
this.#nonce,
|
|
101
|
-
];
|
|
102
|
-
}
|
|
96
|
+
abstract toFields(): Fr[];
|
|
103
97
|
|
|
104
98
|
/**
|
|
105
99
|
* Hashes the payload
|
|
@@ -109,13 +103,24 @@ export class EntrypointPayload {
|
|
|
109
103
|
return pedersenHash(this.toFields(), this.#generatorIndex);
|
|
110
104
|
}
|
|
111
105
|
|
|
106
|
+
/** Serializes the function calls to an array of fields. */
|
|
107
|
+
protected functionCallsToFields() {
|
|
108
|
+
return this.#functionCalls.flatMap(call => [
|
|
109
|
+
call.args_hash,
|
|
110
|
+
call.function_selector,
|
|
111
|
+
call.target_address,
|
|
112
|
+
new Fr(call.is_public),
|
|
113
|
+
new Fr(call.is_static),
|
|
114
|
+
]);
|
|
115
|
+
}
|
|
116
|
+
|
|
112
117
|
/**
|
|
113
|
-
* Creates an execution payload from a set of function calls
|
|
118
|
+
* Creates an execution payload for a dapp from a set of function calls
|
|
114
119
|
* @param functionCalls - The function calls to execute
|
|
115
120
|
* @returns The execution payload
|
|
116
121
|
*/
|
|
117
122
|
static fromFunctionCalls(functionCalls: FunctionCall[]) {
|
|
118
|
-
return new
|
|
123
|
+
return new AppEntrypointPayload(functionCalls, 0);
|
|
119
124
|
}
|
|
120
125
|
|
|
121
126
|
/**
|
|
@@ -127,18 +132,49 @@ export class EntrypointPayload {
|
|
|
127
132
|
if (functionCalls.length > APP_MAX_CALLS) {
|
|
128
133
|
throw new Error(`Expected at most ${APP_MAX_CALLS} function calls, got ${functionCalls.length}`);
|
|
129
134
|
}
|
|
130
|
-
const paddedCalls = padArrayEnd(functionCalls,
|
|
131
|
-
return new
|
|
135
|
+
const paddedCalls = padArrayEnd(functionCalls, FunctionCall.empty(), APP_MAX_CALLS);
|
|
136
|
+
return new AppEntrypointPayload(paddedCalls, GeneratorIndex.SIGNATURE_PAYLOAD);
|
|
132
137
|
}
|
|
133
138
|
|
|
134
139
|
/**
|
|
135
140
|
* Creates an execution payload to pay the fee for a transaction
|
|
141
|
+
* @param sender - The address sending this payload
|
|
136
142
|
* @param feeOpts - The fee payment options
|
|
137
143
|
* @returns The execution payload
|
|
138
144
|
*/
|
|
139
|
-
static async fromFeeOptions(feeOpts?: FeeOptions) {
|
|
140
|
-
const calls =
|
|
141
|
-
const
|
|
142
|
-
|
|
145
|
+
static async fromFeeOptions(sender: AztecAddress, feeOpts?: FeeOptions) {
|
|
146
|
+
const calls = (await feeOpts?.paymentMethod.getFunctionCalls(feeOpts?.gasSettings)) ?? [];
|
|
147
|
+
const feePayer = await feeOpts?.paymentMethod.getFeePayer(feeOpts?.gasSettings);
|
|
148
|
+
const isFeePayer = !!feePayer && feePayer.equals(sender);
|
|
149
|
+
const paddedCalls = padArrayEnd(calls, FunctionCall.empty(), FEE_MAX_CALLS);
|
|
150
|
+
return new FeeEntrypointPayload(paddedCalls, GeneratorIndex.FEE_PAYLOAD, isFeePayer);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Entrypoint payload for app phase execution. */
|
|
155
|
+
class AppEntrypointPayload extends EntrypointPayload {
|
|
156
|
+
override toFields(): Fr[] {
|
|
157
|
+
return [...this.functionCallsToFields(), this.nonce];
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Entrypoint payload for fee payment to be run during setup phase. */
|
|
162
|
+
class FeeEntrypointPayload extends EntrypointPayload {
|
|
163
|
+
#isFeePayer: boolean;
|
|
164
|
+
|
|
165
|
+
constructor(functionCalls: FunctionCall[], generatorIndex: number, isFeePayer: boolean) {
|
|
166
|
+
super(functionCalls, generatorIndex);
|
|
167
|
+
this.#isFeePayer = isFeePayer;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
override toFields(): Fr[] {
|
|
171
|
+
return [...this.functionCallsToFields(), this.nonce, new Fr(this.#isFeePayer)];
|
|
143
172
|
}
|
|
173
|
+
|
|
174
|
+
/* eslint-disable camelcase */
|
|
175
|
+
/** Whether the sender should be appointed as fee payer. */
|
|
176
|
+
get is_fee_payer() {
|
|
177
|
+
return this.#isFeePayer;
|
|
178
|
+
}
|
|
179
|
+
/* eslint-enable camelcase */
|
|
144
180
|
}
|
|
@@ -6,19 +6,17 @@ import { type AztecAddress } from '@aztec/foundation/aztec-address';
|
|
|
6
6
|
* Holds information about how the fee for a transaction is to be paid.
|
|
7
7
|
*/
|
|
8
8
|
export interface FeePaymentMethod {
|
|
9
|
-
/**
|
|
10
|
-
* The asset used to pay the fee.
|
|
11
|
-
*/
|
|
9
|
+
/** The asset used to pay the fee. */
|
|
12
10
|
getAsset(): AztecAddress;
|
|
13
|
-
/**
|
|
14
|
-
* Address which will hold the fee payment.
|
|
15
|
-
*/
|
|
16
|
-
getPaymentContract(): AztecAddress;
|
|
17
|
-
|
|
18
11
|
/**
|
|
19
12
|
* Creates a function call to pay the fee in the given asset.
|
|
20
13
|
* @param gasSettings - The gas limits and max fees.
|
|
21
14
|
* @returns The function call to pay the fee.
|
|
22
15
|
*/
|
|
23
16
|
getFunctionCalls(gasSettings: GasSettings): Promise<FunctionCall[]>;
|
|
17
|
+
/**
|
|
18
|
+
* The expected fee payer for this tx.
|
|
19
|
+
* @param gasSettings - The gas limits and max fees.
|
|
20
|
+
*/
|
|
21
|
+
getFeePayer(gasSettings: GasSettings): Promise<AztecAddress>;
|
|
24
22
|
}
|
|
@@ -1,62 +1,24 @@
|
|
|
1
1
|
import { type FunctionCall } from '@aztec/circuit-types';
|
|
2
|
-
import { type AztecAddress
|
|
3
|
-
import {
|
|
4
|
-
import { getCanonicalGasTokenAddress } from '@aztec/protocol-contracts/gas-token';
|
|
2
|
+
import { type AztecAddress } from '@aztec/circuits.js';
|
|
3
|
+
import { GasTokenAddress } from '@aztec/protocol-contracts/gas-token';
|
|
5
4
|
|
|
6
|
-
import { type Wallet } from '../account/wallet.js';
|
|
7
5
|
import { type FeePaymentMethod } from './fee_payment_method.js';
|
|
8
6
|
|
|
9
7
|
/**
|
|
10
8
|
* Pay fee directly in the native gas token.
|
|
11
9
|
*/
|
|
12
10
|
export class NativeFeePaymentMethod implements FeePaymentMethod {
|
|
13
|
-
|
|
11
|
+
constructor(protected sender: AztecAddress) {}
|
|
14
12
|
|
|
15
|
-
private constructor(canonicalGasTokenAddress: AztecAddress) {
|
|
16
|
-
this.#gasTokenAddress = canonicalGasTokenAddress;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
static async create(wallet: Wallet): Promise<NativeFeePaymentMethod> {
|
|
20
|
-
const nodeInfo = await wallet.getNodeInfo();
|
|
21
|
-
return new NativeFeePaymentMethod(getCanonicalGasTokenAddress(nodeInfo.l1ContractAddresses.gasPortalAddress));
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Gets the native gas asset used to pay the fee.
|
|
26
|
-
* @returns The asset used to pay the fee.
|
|
27
|
-
*/
|
|
28
13
|
getAsset() {
|
|
29
|
-
return
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* The contract responsible for fee payment. This will be the same as the asset.
|
|
34
|
-
* @returns The contract address responsible for holding the fee payment.
|
|
35
|
-
*/
|
|
36
|
-
getPaymentContract() {
|
|
37
|
-
return this.#gasTokenAddress;
|
|
14
|
+
return GasTokenAddress;
|
|
38
15
|
}
|
|
39
16
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
* @returns false
|
|
43
|
-
*/
|
|
44
|
-
isPrivateFeePayment(): boolean {
|
|
45
|
-
return false;
|
|
17
|
+
getFunctionCalls(): Promise<FunctionCall[]> {
|
|
18
|
+
return Promise.resolve([]);
|
|
46
19
|
}
|
|
47
20
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
* @param gasSettings - The gas settings.
|
|
51
|
-
* @returns A function call
|
|
52
|
-
*/
|
|
53
|
-
getFunctionCalls(gasSettings: GasSettings): Promise<FunctionCall[]> {
|
|
54
|
-
return Promise.resolve([
|
|
55
|
-
{
|
|
56
|
-
to: this.#gasTokenAddress,
|
|
57
|
-
functionData: new FunctionData(FunctionSelector.fromSignature('pay_fee(Field)'), false),
|
|
58
|
-
args: [gasSettings.getFeeLimit()],
|
|
59
|
-
},
|
|
60
|
-
]);
|
|
21
|
+
getFeePayer(): Promise<AztecAddress> {
|
|
22
|
+
return Promise.resolve(this.sender);
|
|
61
23
|
}
|
|
62
24
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type FunctionCall } from '@aztec/circuit-types';
|
|
2
|
+
import { type AztecAddress, Fr, FunctionSelector } from '@aztec/circuits.js';
|
|
3
|
+
import { FunctionType } from '@aztec/foundation/abi';
|
|
4
|
+
import { GasTokenAddress } from '@aztec/protocol-contracts/gas-token';
|
|
5
|
+
|
|
6
|
+
import { NativeFeePaymentMethod } from './native_fee_payment_method.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Pay fee directly with native gas token claimed on the same tx.
|
|
10
|
+
*/
|
|
11
|
+
export class NativeFeePaymentMethodWithClaim extends NativeFeePaymentMethod {
|
|
12
|
+
constructor(sender: AztecAddress, private claimAmount: bigint | Fr, private claimSecret: Fr) {
|
|
13
|
+
super(sender);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Creates a function call to pay the fee in gas token.
|
|
18
|
+
* @returns A function call
|
|
19
|
+
*/
|
|
20
|
+
override getFunctionCalls(): Promise<FunctionCall[]> {
|
|
21
|
+
return Promise.resolve([
|
|
22
|
+
{
|
|
23
|
+
to: GasTokenAddress,
|
|
24
|
+
name: 'claim',
|
|
25
|
+
selector: FunctionSelector.fromSignature('claim((Field),Field,Field)'),
|
|
26
|
+
isStatic: false,
|
|
27
|
+
args: [this.sender, new Fr(this.claimAmount), this.claimSecret],
|
|
28
|
+
returnTypes: [],
|
|
29
|
+
type: FunctionType.PRIVATE,
|
|
30
|
+
},
|
|
31
|
+
]);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type FunctionCall } from '@aztec/circuit-types';
|
|
2
|
+
import { AztecAddress } from '@aztec/circuits.js';
|
|
3
|
+
|
|
4
|
+
import { type FeePaymentMethod } from './fee_payment_method.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Does not pay fees. Will work until we enforce fee payment for all txs.
|
|
8
|
+
*/
|
|
9
|
+
export class NoFeePaymentMethod implements FeePaymentMethod {
|
|
10
|
+
constructor() {}
|
|
11
|
+
|
|
12
|
+
getAsset() {
|
|
13
|
+
return AztecAddress.ZERO;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getFunctionCalls(): Promise<FunctionCall[]> {
|
|
17
|
+
return Promise.resolve([]);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
getFeePayer(): Promise<AztecAddress> {
|
|
21
|
+
return Promise.resolve(AztecAddress.ZERO);
|
|
22
|
+
}
|
|
23
|
+
}
|