Skip to content

Commit 4cbd72c

Browse files
authored
fix!: enforce predicateData when predicate has arguments (#3886)
1 parent 842e0f3 commit 4cbd72c

File tree

10 files changed

+83
-13
lines changed

10 files changed

+83
-13
lines changed

.changeset/loud-bags-deny.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@fuel-ts/account": minor
3+
---
4+
5+
fix!: enforce `predicateData` when predicate has arguments

apps/create-fuels-counter-guide/src/components/Predicate.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ export default function Predicate() {
3131

3232
useEffect(() => {
3333
if (wallet) {
34-
const testPredicate = new TestPredicate(wallet);
34+
const testPredicate = new TestPredicate({
35+
provider: wallet.provider,
36+
data: [0],
37+
});
3538
setPredicate(testPredicate);
3639
}
3740
}, [wallet]);

apps/docs/src/guide/predicates/snippets/deploying-predicates.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const baseAssetId = await provider.getBaseAssetId();
1616
// We can deploy dynamically or via `fuels deploy`
1717
const originalPredicate = new ConfigurablePin({
1818
provider,
19+
data: [1337],
1920
});
2021

2122
const { waitForResult: waitForDeploy } = await originalPredicate.deploy(wallet);

packages/account/src/predicate/predicate.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,26 @@ import { deployScriptOrPredicate } from '../utils/deployScriptOrPredicate';
2727

2828
import { getPredicateRoot } from './utils';
2929

30+
// Helper type to check if T is a tuple with a fixed, non-zero length
31+
type IsNonEmptyTuple<T extends unknown[]> = number extends T['length']
32+
? false
33+
: T['length'] extends 0
34+
? false
35+
: true;
36+
37+
// Type for the 'data' property, required if TData is a non-empty tuple
38+
export type PredicateDataParam<TData extends InputValue[]> =
39+
IsNonEmptyTuple<TData> extends true
40+
? { data: TData } // If TData is a non-empty tuple, 'data' is required
41+
: { data?: TData }; // Otherwise (TData is []), 'data' is optional
42+
3043
export type PredicateParams<
3144
TData extends InputValue[] = InputValue[],
3245
TConfigurables extends { [name: string]: unknown } | undefined = { [name: string]: unknown },
33-
> = {
46+
> = PredicateDataParam<TData> & {
3447
bytecode: BytesLike;
3548
provider: Provider;
3649
abi: JsonAbi;
37-
data?: TData;
3850
configurableConstants?: TConfigurables;
3951
};
4052

@@ -161,7 +173,9 @@ export class Predicate<
161173
* @returns A new Predicate instance with the same bytecode, ABI and provider but with the ability to set the data and configurable constants.
162174
*/
163175
toNewInstance(
164-
overrides: Pick<PredicateParams<TData, TConfigurables>, 'data' | 'configurableConstants'> = {}
176+
overrides: Partial<
177+
Pick<PredicateParams<TData, TConfigurables>, 'data' | 'configurableConstants'>
178+
> = {}
165179
) {
166180
return new Predicate<TData, TConfigurables>({
167181
bytecode: this.initialBytecode,

packages/fuel-gauge/src/blob-deploy.test.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
describe('deploying blobs', () => {
1919
function decodeConfigurables(
2020
// eslint-disable-next-line @typescript-eslint/no-explicit-any
21-
program: Predicate | Script<any, any>
21+
program: Predicate<any, any> | Script<any, any>
2222
): Record<string, unknown> {
2323
const configurables: Record<string, unknown> = {};
2424

@@ -225,10 +225,6 @@ describe('deploying blobs', () => {
225225

226226
const receiver = Wallet.generate({ provider });
227227

228-
const loaderPredicate = await (
229-
await new PredicateWithMoreConfigurables({ provider }).deploy(wallet)
230-
).waitForResult();
231-
232228
const configurable = {
233229
FEE: 99,
234230
ADDRESS: getRandomB256(),
@@ -238,6 +234,13 @@ describe('deploying blobs', () => {
238234
BOOL: false,
239235
};
240236

237+
const loaderPredicate = await (
238+
await new PredicateWithMoreConfigurables({
239+
provider,
240+
data: [configurable.FEE, configurable.ADDRESS],
241+
}).deploy(wallet)
242+
).waitForResult();
243+
241244
const predicate = new Predicate({
242245
data: [configurable.FEE, configurable.ADDRESS],
243246
bytecode: loaderPredicate.bytes,

packages/fuel-gauge/src/predicate/predicate-configurables.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ describe('Predicate', () => {
239239

240240
const predicate = new PredicateWithConfigurable({
241241
provider,
242+
data: [99, getRandomB256()],
242243
});
243244

244245
const destination = WalletUnlocked.generate({

packages/fuel-gauge/src/predicate/predicate-estimations.test.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,27 @@ describe('Predicate', () => {
4646
bytecode: PredicateMainArgsStruct.bytecode,
4747
abi: PredicateMainArgsStruct.abi,
4848
provider,
49+
data: [
50+
{
51+
has_account: true,
52+
total_complete: 100,
53+
},
54+
],
4955
});
5056

5157
await fundAccount(wallet, predicateStruct, fundingAmount);
5258

5359
const tx = new ScriptTransactionRequest();
5460

5561
// Get resources from the predicate struct
56-
const ressources = await predicateStruct.getResourcesToSpend([
62+
const resources = await predicateStruct.getResourcesToSpend([
5763
{
5864
assetId: await provider.getBaseAssetId(),
5965
amount: bn(10_000),
6066
},
6167
]);
62-
tx.addResource(ressources[0]);
68+
69+
tx.addResource(resources[0]);
6370
// Add predicate bytecode to the input predicate
6471
(<CoinTransactionRequestInput>tx.inputs[0]).predicate = predicateStruct.bytes;
6572

@@ -167,6 +174,12 @@ describe('Predicate', () => {
167174
abi: PredicateMainArgsStruct.abi,
168175
bytecode: PredicateMainArgsStruct.bytecode,
169176
provider,
177+
data: [
178+
{
179+
has_account: true,
180+
total_complete: 100,
181+
},
182+
],
170183
});
171184

172185
await fundAccount(wallet, predicateTrue, fundingAmount);
@@ -254,6 +267,12 @@ describe('Predicate', () => {
254267
abi: PredicateMainArgsStruct.abi,
255268
bytecode: PredicateMainArgsStruct.bytecode,
256269
provider,
270+
data: [
271+
{
272+
has_account: true,
273+
total_complete: 100,
274+
},
275+
],
257276
});
258277

259278
await fundAccount(wallet, predicateStruct, fundingAmount);
@@ -288,6 +307,12 @@ describe('Predicate', () => {
288307
abi: PredicateMainArgsStruct.abi,
289308
bytecode: PredicateMainArgsStruct.bytecode,
290309
provider,
310+
data: [
311+
{
312+
has_account: true,
313+
total_complete: 100,
314+
},
315+
],
291316
});
292317

293318
await fundAccount(wallet, predicateStruct, fundingAmount);

packages/fuel-gauge/src/predicate/predicate-invalidations.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ describe('Predicate', () => {
2323
abi: PredicateMainArgsStruct.abi,
2424
bytecode: PredicateMainArgsStruct.bytecode,
2525
provider,
26+
data: [
27+
{
28+
has_account: true,
29+
total_complete: 100,
30+
},
31+
],
2632
});
2733

2834
await fundAccount(wallet, predicate, 1000);
@@ -57,6 +63,12 @@ describe('Predicate', () => {
5763
abi: PredicateMainArgsStruct.abi,
5864
bytecode: PredicateMainArgsStruct.bytecode,
5965
provider,
66+
data: [
67+
{
68+
has_account: true,
69+
total_complete: 100,
70+
},
71+
],
6072
});
6173

6274
await fundAccount(wallet, predicate, 10_000);

templates/nextjs/src/components/Predicate.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ export default function Predicate() {
3636

3737
useEffect(() => {
3838
if (wallet) {
39-
const testPredicate = new TestPredicate(wallet);
39+
const testPredicate = new TestPredicate({
40+
provider: wallet.provider,
41+
data: [0],
42+
});
4043
setPredicate(testPredicate);
4144
}
4245
}, [wallet]);

templates/vite/src/components/Predicate.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ export default function Predicate() {
3535

3636
useEffect(() => {
3737
if (wallet) {
38-
const testPredicate = new TestPredicate(wallet);
38+
const testPredicate = new TestPredicate({
39+
provider: wallet.provider,
40+
data: [0],
41+
});
3942
setPredicate(testPredicate);
4043
}
4144
}, [wallet]);

0 commit comments

Comments
 (0)