Skip to content

p-token: Add spl-token test fixtures #39

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,35 @@ jobs:
path: ./**/*.so
key: ${{ runner.os }}-builds-${{ github.sha }}

build_ptoken:
name: Build p-token
runs-on: ubuntu-latest
steps:
- name: Git Checkout
uses: actions/checkout@v4

- name: Setup Environment
uses: ./.github/actions/setup
with:
cargo-cache-key: cargo-build-program
solana: true

- name: Build
run: pnpm p-token:build

- name: Upload p-token Builds
uses: actions/upload-artifact@v4
with:
name: p-token-builds
path: ./target/deploy/*.so
if-no-files-found: error

- name: Save p-token Build For Client Jobs
uses: actions/cache/save@v4
with:
path: ./**/*.so
key: ${{ runner.os }}-ptoken-build-${{ github.sha }}

test_client_js:
name: Test Client JS
runs-on: ubuntu-latest
Expand Down Expand Up @@ -212,3 +241,34 @@ jobs:

- name: Test
run: pnpm programs:test

conformance_ptoken:
name: Conformance Test for p-token
runs-on: ubuntu-latest
needs: build_ptoken
steps:
- name: Git Checkout
uses: actions/checkout@v4

- name: Setup Environment
uses: ./.github/actions/setup
with:
cargo-cache-key: cargo-fixtures-ptoken
solana: true

- name: Restore Program Builds
uses: actions/cache/restore@v4
with:
path: ./**/*.so
key: ${{ runner.os }}-ptoken-build-${{ github.sha }}

- name: Install mollusk-svm-cli
uses: taiki-e/cache-cargo-install-action@v2
with:
tool: mollusk-svm-cli

- name: Generate SPL Token Fixtures
run: pnpm fixtures:generate

- name: Run Fixtures
run: pnpm fixtures:run pinocchio_token_program
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@
"rust:publish": "zx ./scripts/rust/publish.mjs",
"rust:semver": "cargo semver-checks",
"p-token:build": "zx ./scripts/rust/build-sbf.mjs p-token",
"p-token:test": "zx ./scripts/rust/test.mjs p-token"
"p-token:test": "zx ./scripts/rust/test.mjs p-token",
"fixtures:clean": "zx ./scripts/rust/fixtures.mjs clean",
"fixtures:generate": "zx ./scripts/rust/fixtures.mjs generate",
"fixtures:run": "zx ./scripts/rust/fixtures.mjs run"
},
"devDependencies": {
"@codama/renderers-js": "^1.2.7",
Expand Down
26 changes: 0 additions & 26 deletions program/tests/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5366,32 +5366,6 @@ fn test_overflow() {
.unwrap();
let account = Account::unpack_unchecked(&account_account.data).unwrap();
assert_eq!(account.amount, u64::MAX);

// manipulate account balance to attempt overflow transfer
let mut account = Account::unpack_unchecked(&account2_account.data).unwrap();
account.amount = 1;
Account::pack(account, &mut account2_account.data).unwrap();

assert_eq!(
Err(TokenError::Overflow.into()),
do_process_instruction(
transfer(
&program_id,
&account2_key,
&account_key,
&owner2_key,
&[],
1,
)
.unwrap(),
vec![
&mut account2_account,
&mut account_account,
&mut owner2_account,
],
&[Check::err(TokenError::Overflow.into())],
)
);
}

#[test]
Expand Down
61 changes: 61 additions & 0 deletions scripts/rust/fixtures.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env zx
import 'zx/globals';
import { existsSync } from 'fs';
import { cliArguments, workingDirectory } from '../utils.mjs';

// Directory where the fixtures are generated.
const FIXTURES_DIR = path.join(workingDirectory, 'target', 'fixtures');
// Directory of the SPL Token program.
const SPL_TOKEN_DIR = path.join(workingDirectory, 'program');
// Directory of the SBF program.
const SBF_OUTPUT_DIR = path.join(workingDirectory, 'target', 'deploy');

const [command, ...args] = cliArguments();

switch (command) {
case 'clean':
await clean();
break;
case 'generate':
await generate();
break;
case 'run':
await run(args);
break;
default:
throw new Error(`Unknown command: ${command}`);
}

async function clean() {
await $`rm -rf ${FIXTURES_DIR}`;
}

async function generate() {
if (existsSync(FIXTURES_DIR)) {
echo(chalk.yellow('[ WARNING ]'), `Fixtures directory already exists.`);
} else {
await $`mkdir ${FIXTURES_DIR}`;

// Fixtures are generated from the SPL Token program.
cd(SPL_TOKEN_DIR);

await $`RUST_LOG=error EJECT_FUZZ_FIXTURES=${FIXTURES_DIR} cargo test-sbf --features mollusk-svm/fuzz`;
}
}

async function run(args) {
if (!existsSync(FIXTURES_DIR)) {
throw new Error(`Fixtures directory does not exist: ${FIXTURES_DIR}`);
}

const [programName] = args;
if (!programName) {
throw new Error('The name of the program file must be provided.');
}

await $`mollusk execute-fixture \
${path.join(SBF_OUTPUT_DIR, programName + '.so')} \
${FIXTURES_DIR} \
TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA \
--ignore-compute-units`;
}