Skip to content

Commit

Permalink
fix: add predicateData to predicate resources and inputs (#2380)
Browse files Browse the repository at this point in the history
  • Loading branch information
Torres-ssf committed May 24, 2024
1 parent 66a1375 commit 3b27bac
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 35 deletions.
5 changes: 5 additions & 0 deletions .changeset/giant-jobs-buy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fuel-ts/account": patch
---

fix: add `predicateData` to predicate resources and inputs
1 change: 1 addition & 0 deletions packages/account/src/predicate/predicate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ export class Predicate<TInputData extends InputValue[]> extends Account {
return resources.map((resource) => ({
...resource,
predicate: hexlify(this.bytes),
predicateData: hexlify(this.getPredicateData()),
}));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ import { normalizeJSON } from '../utils';
import { getMaxGas, getMinGas } from '../utils/gas';

import { NoWitnessAtIndexError } from './errors';
import { isRequestInputResource } from './helpers';
import {
getRequestInputResourceOwner,
isRequestInputResource,
isRequestInputResourceFromOwner,
} from './helpers';
import type {
TransactionRequestInput,
CoinTransactionRequestInput,
Expand Down Expand Up @@ -348,7 +352,7 @@ export abstract class BaseTransactionRequest implements BaseTransactionRequestLi
* @param coin - Coin resource.
*/
addCoinInput(coin: Coin) {
const { assetId, owner, amount, id, predicate } = coin;
const { assetId, owner, amount, id, predicate, predicateData } = coin;

let witnessIndex;

Expand All @@ -372,6 +376,7 @@ export abstract class BaseTransactionRequest implements BaseTransactionRequestLi
txPointer: '0x00000000000000000000000000000000',
witnessIndex,
predicate,
predicateData,
};

// Insert the Input
Expand All @@ -388,7 +393,7 @@ export abstract class BaseTransactionRequest implements BaseTransactionRequestLi
* @param message - Message resource.
*/
addMessageInput(message: MessageCoin) {
const { recipient, sender, amount, predicate, nonce, assetId } = message;
const { recipient, sender, amount, predicate, nonce, assetId, predicateData } = message;

let witnessIndex;

Expand All @@ -411,6 +416,7 @@ export abstract class BaseTransactionRequest implements BaseTransactionRequestLi
amount,
witnessIndex,
predicate,
predicateData,
};

// Insert the Input
Expand Down Expand Up @@ -660,29 +666,19 @@ export abstract class BaseTransactionRequest implements BaseTransactionRequestLi
}

updatePredicateGasUsed(inputs: TransactionRequestInput[]) {
this.inputs.forEach((i) => {
let correspondingInput: TransactionRequestInput | undefined;
switch (i.type) {
case InputType.Coin:
correspondingInput = inputs.find((x) => x.type === InputType.Coin && x.owner === i.owner);
break;
case InputType.Message:
correspondingInput = inputs.find(
(x) => x.type === InputType.Message && x.sender === i.sender
);
break;
default:
return;
}
const inputsToExtractGasUsed = inputs.filter(isRequestInputResource);

this.inputs.filter(isRequestInputResource).forEach((i) => {
const owner = getRequestInputResourceOwner(i);
const correspondingInput = inputsToExtractGasUsed.find((x) =>
isRequestInputResourceFromOwner(x, Address.fromString(String(owner)))
);

if (
correspondingInput &&
'predicateGasUsed' in correspondingInput &&
bn(correspondingInput.predicateGasUsed).gt(0)
) {
// eslint-disable-next-line no-param-reassign
i.predicate = correspondingInput.predicate;
// eslint-disable-next-line no-param-reassign
i.predicateData = correspondingInput.predicateData;
// eslint-disable-next-line no-param-reassign
i.predicateGasUsed = correspondingInput.predicateGasUsed;
}
Expand Down
25 changes: 13 additions & 12 deletions packages/fuel-gauge/src/predicate/predicate-arguments.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { seedTestWallet } from '@fuel-ts/account/test-utils';
import type { WalletLocked, WalletUnlocked, BigNumberish } from 'fuels';
import { Provider, FUEL_NETWORK_URL, toHex, Predicate } from 'fuels';

import { FuelGaugeProjectsEnum, getFuelGaugeForcProject } from '../../test/fixtures';
import type { Validation } from '../types/predicate';

import { setupWallets, assertBalances, fundPredicate } from './utils/predicate';
import { setupWallets, assertBalances } from './utils/predicate';

/**
* @group node
Expand All @@ -31,7 +32,7 @@ describe('Predicate', () => {
let provider: Provider;
let baseAssetId: string;
const amountToReceiver = 50;
const amountToPredicate = 300_000;
const amountToPredicate = 900_000;

beforeAll(async () => {
provider = await Provider.create(FUEL_NETWORK_URL);
Expand All @@ -51,7 +52,7 @@ describe('Predicate', () => {
inputData: ['0xef86afa9696cf0dc6385e2c407a6e159a1103cefb7e2ae0636fb33d3cb2a9e4a'],
});

await fundPredicate(wallet, predicate, amountToPredicate);
await seedTestWallet(predicate, [[amountToPredicate, baseAssetId]], 3);
const initialReceiverBalance = await receiver.getBalance();

const tx = await predicate.transfer(receiver.address, amountToReceiver, baseAssetId, {
Expand All @@ -70,7 +71,7 @@ describe('Predicate', () => {
provider,
inputData: ['0xbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbada'],
});
await fundPredicate(wallet, predicate, amountToPredicate);
await seedTestWallet(predicate, [[amountToPredicate, baseAssetId]], 3);
const initialReceiverBalance = await receiver.getBalance();

expect(initialReceiverBalance.toHex()).toEqual(toHex(0));
Expand All @@ -88,7 +89,7 @@ describe('Predicate', () => {
inputData: [1078],
});

await fundPredicate(wallet, predicate, amountToPredicate);
await seedTestWallet(predicate, [[amountToPredicate, baseAssetId]], 3);
const initialReceiverBalance = await receiver.getBalance();

const tx = await predicate.transfer(receiver.address, amountToReceiver, baseAssetId, {
Expand All @@ -108,7 +109,7 @@ describe('Predicate', () => {
inputData: [100],
});

await fundPredicate(wallet, predicate, amountToPredicate);
await seedTestWallet(predicate, [[amountToPredicate, baseAssetId]], 3);
const initialReceiverBalance = await receiver.getBalance();

expect(initialReceiverBalance.toHex()).toEqual(toHex(0));
Expand All @@ -127,7 +128,7 @@ describe('Predicate', () => {
provider,
inputData: [{ has_account: true, total_complete: 100 }],
});
await fundPredicate(wallet, predicateInstanceForBalance, amountToPredicate);
await seedTestWallet(predicateInstanceForBalance, [[amountToPredicate, baseAssetId]], 3);
const initialReceiverBalance = await receiver.getBalance();

// #region predicate-struct-arg
Expand Down Expand Up @@ -160,7 +161,7 @@ describe('Predicate', () => {
],
});

await fundPredicate(wallet, predicate, amountToPredicate);
await seedTestWallet(predicate, [[amountToPredicate, baseAssetId]], 3);

await expect(
predicate.transfer(receiver.address, 50, baseAssetId, { gasLimit: 1000 })
Expand All @@ -175,7 +176,7 @@ describe('Predicate', () => {
inputData: [[42]],
});

await fundPredicate(wallet, predicate, amountToPredicate);
await seedTestWallet(predicate, [[amountToPredicate, baseAssetId]], 3);
const initialReceiverBalance = await receiver.getBalance();

const tx = await predicate.transfer(receiver.address, amountToReceiver, baseAssetId, {
Expand All @@ -195,7 +196,7 @@ describe('Predicate', () => {
inputData: [20, 30],
});

await fundPredicate(wallet, predicateForBalance, amountToPredicate);
await seedTestWallet(predicateForBalance, [[amountToPredicate, baseAssetId]], 3);
const initialReceiverBalance = await receiver.getBalance();

// #region predicate-multi-args
Expand Down Expand Up @@ -223,7 +224,7 @@ describe('Predicate', () => {
inputData: [20, 30],
});

await fundPredicate(wallet, predicate, amountToPredicate);
await seedTestWallet(predicate, [[amountToPredicate, baseAssetId]], 3);
const initialReceiverBalance = await receiver.getBalance();

const tx = await predicate.transfer(receiver.address, amountToReceiver, baseAssetId, {
Expand All @@ -243,7 +244,7 @@ describe('Predicate', () => {
inputData: [20, 20],
});

await fundPredicate(wallet, predicate, amountToPredicate);
await seedTestWallet(predicate, [[amountToPredicate, baseAssetId]], 3);

await expect(
predicate.transfer(receiver.address, 50, baseAssetId, { gasLimit: 1000 })
Expand Down
54 changes: 52 additions & 2 deletions packages/fuel-gauge/src/predicate/predicate-estimations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
FUEL_NETWORK_URL,
getRandomB256,
WalletUnlocked,
isRequestInputResource,
} from 'fuels';

import { FuelGaugeProjectsEnum, getFuelGaugeForcProject } from '../../test/fixtures';
Expand All @@ -35,8 +36,9 @@ describe('Predicate', () => {
let predicateTrue: Predicate<[]>;
let predicateStruct: Predicate<[Validation]>;
let baseAssetId: string;
const fundingAmount = 10_000;

beforeEach(async () => {
beforeAll(async () => {
provider = await Provider.create(FUEL_NETWORK_URL);
baseAssetId = provider.getBaseAssetId();
predicateTrue = new Predicate({
Expand All @@ -48,10 +50,13 @@ describe('Predicate', () => {
abi: predicateAbiMainArgsStruct,
provider,
});
});

beforeEach(async () => {
await seedTestWallet(predicateStruct, [
{
assetId: baseAssetId,
amount: bn(10_000),
amount: bn(fundingAmount),
},
]);
});
Expand Down Expand Up @@ -204,5 +209,50 @@ describe('Predicate', () => {
expect(estimatePredicatesSpy).toHaveBeenCalledTimes(1);
expect(dryRunSpy).toHaveBeenCalledOnce();
});

describe('predicate resource fetching and predicateData population', () => {
test('getting predicate resources via the predicate automatically populates predicateData', async () => {
const transactionRequest = new ScriptTransactionRequest();

const resources = await predicateStruct.getResourcesToSpend([[fundingAmount, baseAssetId]]);
resources.forEach((resource) => {
expect(resource.predicateData).toBeDefined();
});

transactionRequest.addResources(resources);
const inputs = transactionRequest.inputs.filter(isRequestInputResource);

expect(inputs.length).toBeGreaterThan(0);
inputs.forEach((resource) => {
expect(resource.predicateData).toBeDefined();
});
});

test('getting predicate resources via the provider requires manual predicateData population', async () => {
const transactionRequest = new ScriptTransactionRequest();

const resources = await provider.getResourcesToSpend(predicateStruct.address, [
[fundingAmount, baseAssetId],
]);

resources.forEach((resource) => {
expect(resource.predicateData).toBeUndefined();
});

transactionRequest.addResources(resources);
const inputs = transactionRequest.inputs.filter(isRequestInputResource);

expect(inputs.length).toBeGreaterThan(0);
inputs.forEach((resource) => {
expect(resource.predicateData).toBeUndefined();
});

predicateStruct.populateTransactionPredicateData(transactionRequest);

inputs.forEach((resource) => {
expect(resource.predicateData).toBeDefined();
});
});
});
});
});

0 comments on commit 3b27bac

Please sign in to comment.