diff --git a/.changeset/thirty-dogs-sleep.md b/.changeset/thirty-dogs-sleep.md new file mode 100644 index 00000000000..1a51368148c --- /dev/null +++ b/.changeset/thirty-dogs-sleep.md @@ -0,0 +1,4 @@ +--- +--- + +Add tests for Bytes and RawSlice diff --git a/packages/fuel-gauge/fixtures/forc-projects/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/Forc.toml index 4d012ebfe2d..12e6d0f573a 100644 --- a/packages/fuel-gauge/fixtures/forc-projects/Forc.toml +++ b/packages/fuel-gauge/fixtures/forc-projects/Forc.toml @@ -15,11 +15,13 @@ members = [ "multi-token-contract", "payable-annotation", "predicate-address", + "predicate-bytes", "predicate-conditional-inputs", "predicate-false", "predicate-main-args-struct", "predicate-main-args-vector", "predicate-multi-args", + "predicate-raw-slice", "predicate-struct", "predicate-triple-sig", "predicate-true", diff --git a/packages/fuel-gauge/fixtures/forc-projects/predicate-bytes/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/predicate-bytes/Forc.toml new file mode 100644 index 00000000000..5a88bab0ec6 --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/predicate-bytes/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["FuelLabs"] +entry = "main.sw" +license = "Apache-2.0" +name = "predicate-bytes" + +[dependencies] \ No newline at end of file diff --git a/packages/fuel-gauge/fixtures/forc-projects/predicate-bytes/src/main.sw b/packages/fuel-gauge/fixtures/forc-projects/predicate-bytes/src/main.sw new file mode 100644 index 00000000000..c795f0eab5f --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/predicate-bytes/src/main.sw @@ -0,0 +1,44 @@ +predicate; + +use std::bytes::Bytes; + +#[allow(dead_code)] +enum SomeEnum { + First: bool, + Second: T, +} + +struct Wrapper { + inner: T, + inner_enum: SomeEnum, +} + +fn expected_bytes() -> Bytes { + let mut bytes = Bytes::new(); + + bytes.push(40u8); + bytes.push(41u8); + bytes.push(42u8); + + bytes +} + +fn valid_bytes(bytes: Bytes) -> bool { + bytes == expected_bytes() +} + +fn valid_vec(arg: Vec) -> bool { + if arg.len() != 2 { + return false; + } + + valid_bytes(arg.get(0).unwrap()) && valid_bytes(arg.get(1).unwrap()) +} + +fn main(wrapper: Wrapper>) -> bool { + if let SomeEnum::Second(enum_bytes) = wrapper.inner_enum { + valid_bytes(enum_bytes) && valid_vec(wrapper.inner) + } else { + false + } +} diff --git a/packages/fuel-gauge/fixtures/forc-projects/predicate-raw-slice/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/predicate-raw-slice/Forc.toml new file mode 100644 index 00000000000..979cb682cd2 --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/predicate-raw-slice/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["FuelLabs"] +entry = "main.sw" +license = "Apache-2.0" +name = "predicate-raw-slice" + +[dependencies] \ No newline at end of file diff --git a/packages/fuel-gauge/fixtures/forc-projects/predicate-raw-slice/src/main.sw b/packages/fuel-gauge/fixtures/forc-projects/predicate-raw-slice/src/main.sw new file mode 100644 index 00000000000..19ba59de2ca --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/predicate-raw-slice/src/main.sw @@ -0,0 +1,30 @@ +predicate; + +#[allow(dead_code)] +enum SomeEnum { + First: bool, + Second: T, +} + +struct Wrapper { + inner: T, + inner_enum: SomeEnum, +} + +fn valid_raw_slice(slice: raw_slice) -> bool { + let vec: Vec = Vec::from(slice); + vec.len() == 3 && vec.get(0).unwrap() == 40 && vec.get(1).unwrap() == 41 && vec.get(2).unwrap() == 42 +} + +fn valid_vec(vec: Vec) -> bool { + vec.len() == 2 && valid_raw_slice(vec.get(0).unwrap()) && valid_raw_slice(vec.get(1).unwrap()) +} + +fn main(wrapper: Wrapper>) -> bool { + if let SomeEnum::Second(enum_raw_slice) = wrapper.inner_enum + { + valid_raw_slice(enum_raw_slice) && valid_vec(wrapper.inner) + } else { + false + } +} diff --git a/packages/fuel-gauge/src/bytes.test.ts b/packages/fuel-gauge/src/bytes.test.ts index 600c50c0b6a..9a4eb695b9d 100644 --- a/packages/fuel-gauge/src/bytes.test.ts +++ b/packages/fuel-gauge/src/bytes.test.ts @@ -1,4 +1,17 @@ -import { type Contract } from 'fuels'; +import { generateTestWallet } from '@fuel-ts/wallet/test-utils'; +import { + type Contract, + bn, + Predicate, + Wallet, + Address, + BaseAssetId, + Provider, + FUEL_NETWORK_URL, +} from 'fuels'; + +import predicateBytes from '../fixtures/forc-projects/predicate-bytes'; +import predicateBytesAbi from '../fixtures/forc-projects/predicate-bytes/out/debug/predicate-bytes-abi.json'; import { getSetupContract } from './utils'; @@ -8,6 +21,16 @@ beforeAll(async () => { contractInstance = await setupContract(); }); +type SomeEnum = { + First?: boolean; + Second?: number[]; +}; + +type Wrapper = { + inner: number[][]; + inner_enum: SomeEnum; +}; + describe('Bytes Tests', () => { it('should test bytes output', async () => { const INPUT = 10; @@ -35,7 +58,8 @@ describe('Bytes Tests', () => { it('should test bytes input [nested]', async () => { const bytes = [40, 41, 42]; - const INPUT = { + + const INPUT: Wrapper = { inner: [bytes, bytes], inner_enum: { Second: bytes }, }; @@ -44,4 +68,40 @@ describe('Bytes Tests', () => { expect(true).toBeTruthy(); }); + + it('should test bytes input [predicate-bytes]', async () => { + const provider = await Provider.create(FUEL_NETWORK_URL); + + // Create wallet + const wallet = await generateTestWallet(provider, [[5_000, BaseAssetId]]); + const receiver = Wallet.fromAddress(Address.fromRandom(), wallet.provider); + const amountToPredicate = 100; + const amountToReceiver = 50; + type MainArgs = [Wrapper]; + const predicate = new Predicate(predicateBytes, wallet.provider, predicateBytesAbi); + + // setup predicate + const setupTx = await wallet.transfer(predicate.address, amountToPredicate, BaseAssetId); + await setupTx.waitForResult(); + + const initialPredicateBalance = await predicate.getBalance(); + const initialReceiverBalance = await receiver.getBalance(); + const bytes = [40, 41, 42]; + const INPUT: Wrapper = { + inner: [bytes, bytes], + inner_enum: { Second: bytes }, + }; + const tx = await predicate.setData(INPUT).transfer(receiver.address, amountToReceiver); + await tx.waitForResult(); + + // Check the balance of the receiver + const finalReceiverBalance = await receiver.getBalance(); + expect(bn(initialReceiverBalance).add(amountToReceiver).toHex()).toEqual( + finalReceiverBalance.toHex() + ); + + // Check we spent the entire predicate hash input + const finalPredicateBalance = await predicate.getBalance(); + expect(finalPredicateBalance.lte(initialPredicateBalance)).toBeTruthy(); + }); }); diff --git a/packages/fuel-gauge/src/raw-slice.test.ts b/packages/fuel-gauge/src/raw-slice.test.ts index fa9411e2135..5dd90573654 100644 --- a/packages/fuel-gauge/src/raw-slice.test.ts +++ b/packages/fuel-gauge/src/raw-slice.test.ts @@ -1,8 +1,31 @@ +import { generateTestWallet } from '@fuel-ts/wallet/test-utils'; import type { BN } from 'fuels'; -import { type Contract } from 'fuels'; +import { + type Contract, + bn, + Predicate, + Wallet, + Address, + BaseAssetId, + Provider, + FUEL_NETWORK_URL, +} from 'fuels'; + +import predicateRawSlice from '../fixtures/forc-projects/predicate-raw-slice'; +import predicateRawSliceAbi from '../fixtures/forc-projects/predicate-raw-slice/out/debug/predicate-raw-slice-abi.json'; import { getSetupContract } from './utils'; +type SomeEnum = { + First?: boolean; + Second?: number[]; +}; + +type Wrapper = { + inner: number[][]; + inner_enum: SomeEnum; +}; + const setupContract = getSetupContract('raw-slice'); let contractInstance: Contract; beforeAll(async () => { @@ -37,4 +60,44 @@ describe('Raw Slice Tests', () => { expect(true).toBeTruthy(); }); + + it('should test raw slice input [predicate-raw slice]', async () => { + const provider = await Provider.create(FUEL_NETWORK_URL); + + // Create wallet + const wallet = await generateTestWallet(provider, [[5_000, BaseAssetId]]); + const receiver = Wallet.fromAddress(Address.fromRandom(), wallet.provider); + const amountToPredicate = 100; + const amountToReceiver = 50; + type MainArgs = [Wrapper]; + const predicate = new Predicate( + predicateRawSlice, + wallet.provider, + predicateRawSliceAbi + ); + + // setup predicate + const setupTx = await wallet.transfer(predicate.address, amountToPredicate, BaseAssetId); + await setupTx.waitForResult(); + + const initialPredicateBalance = await predicate.getBalance(); + const initialReceiverBalance = await receiver.getBalance(); + const bytes = [40, 41, 42]; + const INPUT: Wrapper = { + inner: [bytes, bytes], + inner_enum: { Second: bytes }, + }; + const tx = await predicate.setData(INPUT).transfer(receiver.address, amountToReceiver); + await tx.waitForResult(); + + // Check the balance of the receiver + const finalReceiverBalance = await receiver.getBalance(); + expect(bn(initialReceiverBalance).add(amountToReceiver).toHex()).toEqual( + finalReceiverBalance.toHex() + ); + + // Check we spent the entire predicate hash input + const finalPredicateBalance = await predicate.getBalance(); + expect(finalPredicateBalance.lte(initialPredicateBalance)).toBeTruthy(); + }); });