Skip to content

Commit

Permalink
Merge branch 'master' into aa/chore/fuel-core-0.39.0
Browse files Browse the repository at this point in the history
  • Loading branch information
arboleya authored Oct 14, 2024
2 parents 33db93b + b78d032 commit b8b5dc5
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 22 deletions.
5 changes: 5 additions & 0 deletions .changeset/ten-dryers-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fuel-ts/address": patch
---

chore: use `FuelError` instead of JS `Error`
5 changes: 5 additions & 0 deletions .changeset/unlucky-buses-cheer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fuel-ts/account": patch
---

chore: validate tx max number of inputs
25 changes: 25 additions & 0 deletions packages/account/src/account.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,31 @@ describe('Account', () => {
vi.restoreAllMocks();
});

it('should validate max number of inputs when funding the TX', async () => {
using launched = await setupTestProviderAndWallets({
walletsConfig: {
amountPerCoin: 100,
coinsPerAsset: 400,
},
});
const {
wallets: [wallet],
provider,
} = launched;

const request = new ScriptTransactionRequest();
request.addCoinOutput(wallet.address, 30_000, provider.getBaseAssetId());

const txCost = await wallet.getTransactionCost(request);

request.gasLimit = txCost.gasUsed;
request.maxFee = txCost.maxFee;

await expectToThrowFuelError(() => wallet.fund(request, txCost), {
code: ErrorCode.MAX_INPUTS_EXCEEDED,
});
});

test('can properly use getBalances', async () => {
const fundAmount = 10_000;

Expand Down
2 changes: 2 additions & 0 deletions packages/account/src/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,8 @@ export class Account extends AbstractAccount {
);
}

this.provider.validateTransaction(request);

request.updatePredicateGasUsed(estimatedPredicates);

const requestToReestimate = clone(request);
Expand Down
50 changes: 36 additions & 14 deletions packages/account/src/providers/provider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,7 @@ describe('Provider', () => {
});
});

it('should throws if max of inputs was exceeded', async () => {
it('should validate max number of inputs at sendTransaction method', async () => {
const maxInputs = 2;
using launched = await setupTestProviderAndWallets({
nodeOptions: {
Expand Down Expand Up @@ -851,31 +851,53 @@ describe('Provider', () => {
provider,
} = launched;

const request = new ScriptTransactionRequest();
const request = new ScriptTransactionRequest({
gasLimit: 1000,
maxFee: 1000,
});

const quantities = [coinQuantityfy([1000, ASSET_A]), coinQuantityfy([500, ASSET_B])];
const resources = await sender.getResourcesToSpend(quantities);
const quantities = [
coinQuantityfy([1000, ASSET_A]),
coinQuantityfy([500, ASSET_B]),
coinQuantityfy([5000, provider.getBaseAssetId()]),
];

const resources = await sender.getResourcesToSpend(quantities);
request.addCoinOutput(receiver.address, 500, provider.getBaseAssetId());

const txCost = await sender.getTransactionCost(request);

request.gasLimit = txCost.gasUsed;
request.maxFee = txCost.maxFee;

request.addResources(resources);

await sender.fund(request, txCost);

await expectToThrowFuelError(
() => sender.sendTransaction(request),
new FuelError(
ErrorCode.MAX_INPUTS_EXCEEDED,
'The transaction exceeds the maximum allowed number of inputs.'
`The transaction exceeds the maximum allowed number of inputs. Tx inputs: ${quantities.length}, max inputs: ${maxInputs}`
)
);
});

it('should validate max number of inputs when estimating TX', async () => {
using launched = await setupTestProviderAndWallets({
walletsConfig: {
amountPerCoin: 100,
coinsPerAsset: 400,
},
});
const {
wallets: [wallet],
provider,
} = launched;

const request = new ScriptTransactionRequest();
request.addCoinOutput(wallet.address, 40_000, provider.getBaseAssetId());

const { coins } = await wallet.getCoins(provider.getBaseAssetId());
request.addResources(coins);

await expectToThrowFuelError(() => wallet.getTransactionCost(request), {
code: ErrorCode.MAX_INPUTS_EXCEEDED,
});
});

it('should throws if max of ouputs was exceeded', async () => {
const maxOutputs = 2;
using launched = await setupTestProviderAndWallets({
Expand Down Expand Up @@ -917,7 +939,7 @@ describe('Provider', () => {
() => sender.sendTransaction(request),
new FuelError(
ErrorCode.MAX_OUTPUTS_EXCEEDED,
'The transaction exceeds the maximum allowed number of outputs.'
`The transaction exceeds the maximum allowed number of outputs. Tx outputs: ${request.outputs.length}, max outputs: ${maxOutputs}`
)
);
});
Expand Down
21 changes: 14 additions & 7 deletions packages/account/src/providers/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -829,19 +829,26 @@ Supported fuel-core version: ${supportedVersion}.`
this.cache.set(transactionId, inputsToCache);
}

private validateTransaction(tx: TransactionRequest, consensusParameters: ConsensusParameters) {
const { maxOutputs, maxInputs } = consensusParameters.txParameters;
/**
* @hidden
*/
validateTransaction(tx: TransactionRequest) {
const {
consensusParameters: {
txParameters: { maxInputs, maxOutputs },
},
} = this.getChain();
if (bn(tx.inputs.length).gt(maxInputs)) {
throw new FuelError(
ErrorCode.MAX_INPUTS_EXCEEDED,
'The transaction exceeds the maximum allowed number of inputs.'
`The transaction exceeds the maximum allowed number of inputs. Tx inputs: ${tx.inputs.length}, max inputs: ${maxInputs}`
);
}

if (bn(tx.outputs.length).gt(maxOutputs)) {
throw new FuelError(
ErrorCode.MAX_OUTPUTS_EXCEEDED,
'The transaction exceeds the maximum allowed number of outputs.'
`The transaction exceeds the maximum allowed number of outputs. Tx outputs: ${tx.outputs.length}, max outputs: ${maxOutputs}`
);
}
}
Expand All @@ -867,9 +874,7 @@ Supported fuel-core version: ${supportedVersion}.`
}
// #endregion Provider-sendTransaction

const { consensusParameters } = this.getChain();

this.validateTransaction(transactionRequest, consensusParameters);
this.validateTransaction(transactionRequest);

const encodedTransaction = hexlify(transactionRequest.toTransactionBytes());

Expand Down Expand Up @@ -985,6 +990,8 @@ Supported fuel-core version: ${supportedVersion}.`
let outputVariables = 0;
let dryRunStatus: DryRunStatus | undefined;

this.validateTransaction(transactionRequest);

for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
const {
dryRun: [{ receipts: rawReceipts, status }],
Expand Down
5 changes: 4 additions & 1 deletion packages/address/src/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,10 @@ export default class Address extends AbstractAddress {
/** @hidden */
private static toChecksum(address: string) {
if (!isB256(address)) {
throw new Error('Invalid B256 Address');
throw new FuelError(
FuelError.CODES.INVALID_B256_ADDRESS,
`Invalid B256 Address: ${address}.`
);
}

const addressHex = hexlify(address).toLowerCase().slice(2);
Expand Down

0 comments on commit b8b5dc5

Please sign in to comment.