Aster Payroll is a private, verifiable payroll settlement system on Solana.
It lets a company commit payroll batches onchain, approve the exact payout manifest set, execute a Token-2022 confidential-transfer settlement path in the demo environment, and import verified receipts back into an operator UI without publishing plaintext salaries onchain.
Payroll needs privacy and proof at the same time.
Normal onchain payroll payments expose the sender, recipient, timing, and amount. That is not acceptable for salary settlement. Traditional payroll systems solve privacy by keeping everything in a private database, but then employees and reviewers must trust the operator's internal ledger.
Aster Payroll splits those responsibilities:
- Laravel handles the product UI, employee records, documents, payroll drafting, private proof material, receipt import, and employee self-service views.
- Solana handles the payroll batch lifecycle, proof roots, actor references, and chain-derived timestamps.
- Token-2022 Confidential Transfer provides the private payout path for the current demo.
The result is a payroll flow where settlement can be traced from a local payroll row to Solana accounts, transaction signatures, and committed roots, while compensation amounts stay off the public chain.
This repository contains a working local demo, not a production custody protocol.
Current onchain program:
- Program ID:
4SZ4Fdt4pYurKjtdfEkHvRm9zZ2uTnHmdkGFrQxp1EhE - Cluster in
onchain/Anchor.toml:localnet - Demo validator: Dockerized local validator with Token-2022 and the Aster Payroll program preloaded
The confidential settlement path currently depends on the local validator helper because the demo needs Token-2022 confidential-transfer support. A devnet deployment can be added for the non-confidential batch lifecycle, but this README does not claim a devnet deployment until one is committed and linked.
Company admin flow:
- Create or seed employees under a single demo company.
- Store contract PDFs privately and anchor contract hashes.
- Record compensation amendments with privacy-safe onchain references.
- Draft a payroll batch from effective compensation records.
- Commit
entries_rootonchain. - Prepare one payout manifest per payroll entry.
- Approve the manifest set and commit
approval_rootonchain. - Run the Anchor-side local signer outside Laravel.
- Import Token-2022 confidential-transfer receipts.
- Derive
settlement_rootand finalize the payroll batch onchain.
Employee flow:
- Log in through the employee portal.
- View only the authenticated employee's own contract summary and payroll history.
- View that employee's own proof metadata, entry leaf, amount commitment, batch roots, and transaction references.
- Avoid exposure to other employees' salaries, receipts, proof leaves, or payroll entries.
flowchart LR
Admin["Company admin"] --> Laravel["Laravel + Blade operator UI"]
Employee["Employee portal"] --> Laravel
Laravel --> MySQL["MySQL application data"]
Laravel --> PrivateStorage["Private file storage\ncontracts, manifests, receipts, proof material"]
Laravel --> AnchorBridge["Anchor bridge script"]
AnchorBridge --> AsterProgram["Aster Payroll Anchor program"]
AsterProgram --> BatchState["Batch state\nentries_root\napproval_root\nsettlement_root\nactors and timestamps"]
Laravel --> Manifest["Prepared payout manifests"]
Manifest --> Signer["Anchor-side local signer"]
Signer --> Token2022["Token-2022 Confidential Transfer\nlocal validator demo path"]
Token2022 --> Receipt["Receipt JSON + tx signature"]
Receipt --> Laravel
Laravel --> Verifier["Receipt verifier\nSolana RPC + Token-2022 path checks"]
The Anchor program in onchain/programs/aster_payroll/src/lib.rs exposes six core instructions:
initialize_companycreate_employment_contractamend_compensationcommit_payroll_batchapprove_payroll_batchfinalize_payroll_batch
The payroll batch lifecycle is:
COMMITTED -> APPROVED -> FINALIZED
The program stores:
- company authority and treasury wallet references
- employment contract hashes and current compensation references
- compensation amendment hashes
- payroll period metadata and entry count
entries_rootapproval_rootsettlement_root- approver and finalizer public keys
- chain-derived approval and finalization timestamps
It does not store plaintext salaries, raw contract documents, raw receipts, or per-employee salary mappings.
backend/ Laravel app, Blade UI, models, controllers, services, migrations, feature tests
onchain/ Anchor program, TypeScript tests, local signer, payroll attestation scripts
scripts/ Local validator and Token-2022 helper scripts
The project is designed to run inside the existing devcontainer. The default backend environment expects MySQL at hostname mysql.
Start the full local demo environment:
./scripts/start-demo-env.shStop it without removing the validator container:
./scripts/stop-demo-env.shcd backend
composer install
cp .env.example .env
php artisan key:generate
php artisan migrate --force
php artisan db:seed --force
npm install --ignore-scripts
npm run buildOpen:
http://localhost:8000
Seeded demo accounts:
- Admin:
admin@aster.test/password - Paid employee:
alice.payroll.demo@aster.test/password
cd onchain
yarn install
yarn lint
NO_DNA=1 anchor testBuild the Anchor program first if needed:
cd onchain
anchor buildThen start the local Token-2022 confidential-transfer validator from the repository root:
./scripts/start-confidential-validator.shThe helper exposes:
- host RPC:
http://127.0.0.1:8899 - host WebSocket:
ws://127.0.0.1:8900 - app-container RPC:
http://aster-payroll-confidential-validator:8899
Before running the payroll demo, check the environment from backend/:
php artisan payroll:demo-health- Start the Laravel app and confidential validator.
- Log in as
admin@aster.test. - Confirm seeded employees, contracts, and compensation records.
- Draft a payroll batch.
- Prepare payout manifests in the Confidential Payroll Demo page.
- Run the signer once per manifest:
cd onchain
ASTER_PAYOUT_MANIFEST=/abs/path/to/payout-execution-manifest.json \
ASTER_COMPANY_OWNER_KEYPAIR=/abs/path/to/admin-company-wallet.json \
yarn signer- Import each generated receipt JSON into Laravel.
- Confirm the payroll batch shows commit, approval, and finalization references.
- Log in as
alice.payroll.demo@aster.testand show that the employee sees only her own payroll proof metadata.
Backend tests:
cd backend
composer testOnchain tests:
cd onchain
NO_DNA=1 anchor testDemo health check:
cd backend
php artisan payroll:demo-health- The confidential transfer demo is local-validator based.
- Browser-wallet payout approval is not implemented in this pass.
- The current demo is single-company and single-currency (
USDC, 2 minor units). - Laravel prepares manifests and stores private proof material; the approving signer remains outside Laravel.
- The program does not yet implement program-controlled payroll vaults, PDA-gated fund release, refund paths, slashing, or onchain per-entry payout execution.
- Per-entry proof material remains offchain in Laravel for this demo. Solana stores batch-level roots and state transitions.
The next product step is a separately specified custody model:
- program-controlled payroll vaults
- PDA-gated payout authorization
- refund and failure paths
- stricter public verifier UX
- optional per-entry onchain accounts where they improve external verification
That work needs a separate spec and threat model before implementation.
MIT. See LICENSE.
