You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
NODERS is a Web3 engineering team. We build SDKs, wallets, explorers and on-chain programs across privacy ledgers and L1s: the Canton Go SDK (go-daml) and wallet library, the open-source Logos testnet explorer we run today, smart-account and monitoring tooling on Monad, and the RISC Zero prototypes behind our Logos proposals. We also operate validators, RPC and indexing for 60+ networks with a 24/7 on-call rotation (noders.team) — which is what lets us commit to running what we build.
This proposal is filed from the NODERS organisation account (nodersteam).
Project Summary
Hourglass is production-ready, privacy-preserving token vesting for LEZ: cliff+linear, fully linear and milestone schedules; token-denominated escrow held in a program-controlled vault; claims paid — at the beneficiary's choice, at claim time — to a public holding or to a fresh private account the creator never learns; the universal cancellation invariant with one-way non-cancelable conversion; transferable positions; separate cancellation and milestone authorities; batch creation; a typed event schema; and the SDK, CLI and Basecamp mini-app with the pre-claim summary and privacy disclosure the RFP asks for.
The on-chain core is built and running on public testnet 0.2. Every on-chain hard requirement of RFP-017 is implemented and exercised end to end — on the public testnet, including a privacy-preserving claim; batch creation through the zkVM state machine; events through the documented seam (see Known gaps).
tx 3a2828ab… (block 27362): 1,000 tokens from the escrow to a fresh private account in one privacy-preserving transaction
Tests
75 — 17 core · 41 handler · 17 zkVM state-machine; CI green on main
Cycle cost
Claim 376,495 user cycles (524,288 padded, 1.6 % of the public-execution budget); batch of 10: 7 %
Re-verify
scripts/vesting/verify-onchain.sh against the live sequencer — confirms all 21 lifecycle steps (inclusion and non-inclusion), the 8 final balances and the 6 private-claim properties: ALL GOOD
Token-denominated escrow works today. The vault is a program-derived account, funded and paid out by chained Token Program transfers. Although RFP-017 lists LP-0013 as an open custody blocker, the deployed program needs no transfer-authority primitive: LP-0013 in fact landed upstream as a mint-authority model, and escrow of any SPEL token runs on testnet now (Appendix C, E.1).
The private claim runs on the public testnet. The registered public beneficiary signs the claim; the destination is a fresh private account that is not revealed to the creator or to public observers. The recorded transaction claimed 1,000 tokens in a single privacy-preserving transaction. Reproduction steps, the zkVM state-machine tests, the clock-binding design and the proof evidence are in Appendix A, B and D.
What the grant funds is the client surface (SDK, CLI, Basecamp mini-app), program hardening, runtime events, an external audit before mainnet, the testnet 0.3 migration and the mainnet release. Twelve months of maintenance and an operated indexer are included at no extra charge. The repository is public from the day of filing; a fresh schedule with a Logos-held beneficiary key can be provisioned on request so a reviewer can run the private claim end to end.
Technical Approach
Architecture. One schedule account and one escrow vault PDA per schedule. Nine instructions, in discriminant order: CreateSchedule, CreateScheduleBatch, Claim, ClaimTo, Cancel, MakeNonCancelable, SignalMilestone, TransferBeneficiary, ClaimToPrivate. The vault is funded at creation and paid out at claim and cancel through chained Token Program transfers authorised with pda_seeds — the pattern the upstream AMM uses for its own vaults; the runtime applies a call chain only if every call succeeds (LP-0015, delivered in the core runtime), which makes each claim and cancel one atomic transaction. Schedule state carries the parties, amounts, kind, flags, nominated authorities and an event seam. Account layout, PDA derivation and custody mechanics: Appendix C.
How the hard requirements are met.
Schedule types (F1). Cliff+linear with floor pro-rata (vested(end) == total exactly), fully linear, and milestone tranches unlocked in order by the milestone authority with idempotent signalling (R4). M1 adds an optional cliff_amount. Math and overflow argument: Appendix C.6.
Public and private claims (F2, Privacy 1). Every claim is signed by the registered beneficiary holding, so nobody can force a public claim and defeat a later private one. Claim pays that holding; ClaimTo pays any public destination; ClaimToPrivate pays a fresh private account created by the claim itself. Observers see the schedule, the amount and the signing holding; the destination appears on chain only as a commitment, and the creator never learns it. Because a privacy-preserving transaction cannot read the per-block clock without expiring in one block, ClaimToPrivate carries an as_of timestamp and pins it as the lower bound of the runtime's validity window, so it can never pay more than was vested at inclusion. Execution model and clock design: Appendix B and D.
Cancellation (F3).Cancel freezes accrual, returns the unvested remainder to the creator in the same transaction, and leaves vested tokens claimable; MakeNonCancelable is one-way. Both are gated by the nominated cancellation authority (default: the creator holding; a multisig or DAO holding works). SDK, CLI and mini-app default new schedules to cancelable, as the RFP specifies.
Transferability (F4). Fixed at creation; the current beneficiary reassigns the position, after which only the new holding can claim (the old holding's claim is rejected — on chain in the evidence run).
Batch (F5). 10 schedules per transaction. The binding limit is the runtime's 10 chained calls per transaction (one escrow-funding transfer per schedule), not transaction size; pinned by a test; the SDK splits larger lists. Why one vault per schedule rather than a shared vault: Appendix C.4.
Events (F6). Six typed events (Created, Claimed, Cancelled, MadeNonCancelable, MilestoneSignalled, BeneficiaryTransferred), schema documented. LEZ v0.2.4 has no runtime event API, so today the program ships an event seam — event_seq + last_event in the schedule account — that maps 1:1 onto the runtime events the LEZ team merged into dev on 2026-08-27 and is wired to them in the testnet 0.3 milestone.
Reliability and performance (R1–R3, P1–P2). One call chain per claim and per cancel; independent accounts and vaults per schedule; every claim, public or private, is a single transaction; a cycle table for every instruction on the real guest, re-measured on each LEZ release (Appendix G).
Fee structure — the RFP's four questions. The schedule creator pays, at creation, on top of the escrowed amount (claims stay free, so small private claims are not penalised). Rate 0 % at launch behind a governance-activatable switch with a hard cap of 1 % compiled into the guest; the switch is held by an admin holding set at deployment (a Logos-designated multisig if Logos names one, otherwise a NODERS multisig until handover). Routing to a configurable treasury holding; an optional per-schedule broker fee for launchpad integrators, off by default.
Client surface (U1–U7, Privacy 2–3). SDK as a Rust core module with a C ABI (the modules/token pattern) exposing create, query-claimable, claim, claim-to (public and private), cancel, signal and transfer; the private claim becomes an SDK call with an async prove / submit / re-prove state machine and proving-progress reporting. CLI over the IDL with a claimable query and actionable errors computed locally before submission ("nothing claimable — next unlock at …", insufficient gas, not a private account). Basecamp mini-app in QML/C++ (the apps/token pattern): recipient view (position, locked, claimable now, next unlock, claim with pre-claim summary, gas check on the private path, privacy disclosure) and creator view (create with all parameters, list, cancel, signal). The pre-claim summary reads the network's fee schedule; testnet 0.2 charges no fee, so there it shows 0, and the gas check is live the moment a fee exists. The SPEL IDL exists today (artifacts/vesting-idl.json, pinned to the instruction enum by a test) and is frozen at M1.
Known gaps and platform constraints. Each is reproduced by a test or a command in the repository; the full list with the milestone that addresses each is Appendix I.
Runtime events. No event API in LEZ v0.2.4; the seam above is the interim. The runtime does not commit events for privacy-preserving transactions, so F6 for private claims is bounded by the platform, not by the program.
Client surface not yet built. SDK, CLI and mini-app are M2–M3; today the stock spel-cli drives 7 of 9 instructions and the private claim runs through the evidence tool tools/vesting-private-claim.
Known defect in the deployed program. Beneficiary holdings are not validated against the schedule's token definition; a wrong-token holding would leave a non-cancelable schedule unclaimable. Closed in M1.
Private-claim latency. Proving on the claimant's machine plus inclusion took about six minutes in the recorded run (~13 GB RAM).
Pending-proof invalidation. A pending private claim is invalidated by any transaction that touches the schedule, the vault or the beneficiary holding — including a one-unit transfer into that holding by anyone. Nothing is lost; the SDK re-proves automatically and names the interfering transaction; the mini-app recommends a dedicated beneficiary holding.
Authorities today must be program-owned accounts (token holdings), because a plain wallet can act as a signer only once under the current SPEL output filter; plain-wallet authorities come with new_claimed_if_default in M1.
Amount linkability. The opening balance of the private note equals the public claim amount; stated in the privacy disclosure.
Requirement traceability. Status today and the milestone that closes each item (test names per requirement: Appendix F).
Req.
Requirement
Today
Closed in
F1
Cliff+linear, fully linear, milestone schedules
On chain + tests
M1 (cliff_amount)
F2
Beneficiary fixed at creation; claim to public or private account; creator does not learn the private account
On chain, public and private (3a2828ab…) + zkVM tests
Public/private claim in SDK and mini-app; disclosure; private-destination validation
Program path on chain + zkVM tests
M2/M3
Fees
Four questions answered
Above
M1 (switch)
Soft
Separate cancellation and milestone authorities
On chain with nominated holdings + tests
M1 (plain-wallet authorities)
Milestones, Payout and Timeline
#
Milestone
Deliverables
Done gate
Duration
Payout
M1
Program hardening
Design note (fee switch, event mapping, cliff_amount) reviewed with Logos in week 1; program tightenings: cliff_amount, holding-vs-token-definition validation, ClaimToPrivate default-destination check and optional valid_until, plain-wallet authorities, fee switch + broker option; edge-case, property and explicit R1/R2 tests; sequencer e2e in CI; IDL frozen; program re-verified on the current testnet
Suite green vs standalone sequencer; CI green on main
3 wks
$17,000
M2
SDK + CLI
Rust core module + C ABI, full lifecycle; public and private claim paths with private-destination validation and the async prove / submit / re-prove state machine; CLI incl. claimable and local actionable errors
SDK/CLI exercise every flow vs sequencer; SDK private claim tx linked
2.5 wks
$14,000
M3
Basecamp mini-app
Recipient and creator views, pre-claim summary, gas check, privacy disclosure, actionable errors; Figma; loads via git repo
Loads in Basecamp; screenshots + e2e script
2.5 wks
$14,000
M4
Testnet 0.2 release
Deployment + verify script; cycle table pinned to the testnet version (vesting + token guest); README and SDK/CLI doc packets; privacy-properties document (threat model, amount-linkability, re-prove races); audit-ready bundle
Evidence bundle reviewed
1.5 wks
$10,000
M5
External audit
Two-week review of the program by a firm agreed with Logos (Zellic / Trail of Bits class) on the M4 bundle, before mainnet; findings fixed in scope and re-verified
Report published; findings closed
2 wks
$10,000 (passed through at cost)
M6
Testnet 0.3
Program re-verified on 0.3; events wired to the runtime mechanism; CLI serializer re-based on borsh; cycle table re-measured; clients updated
Suite + verify script green on 0.3
0.5 wk
$5,000
M7
Mainnet
Program deployed to mainnet and verified with the same script; clients pointed at mainnet; 12-month maintenance window opens
Mainnet deployment verified
0.5 wk
$5,000
Core delivery M1–M5: 11.5 weeks; 12.5 with M6/M7. M6 and M7 are paid only on the corresponding release; if a release has not shipped within six months of M5, the milestone scope is re-agreed with Logos, not paid early. Of the $75,000, $65,000 is the build (M1–M4, M6, M7) and $10,000 the external audit, paid as the work is delivered; the 12-month maintenance window and the operated indexer (Post-Delivery Plan) add nothing to the price.
On team size and price. Three full-time engineers for ten and a half engineering weeks, with the program already on testnet, is what lets the schedule hold: the grant buys client surface, hardening and two platform migrations, not discovery.
On the audit. The template asks for an audit milestone where user funds are handled; the escrow handles them, so the audit is a milestone. The custody logic is compact with a single custody invariant, and M4 delivers an audit-ready bundle (traceability, invariants, threat notes) so a third-party review is a two-week job. It is inside the price: $10,000 passed through at cost to a firm agreed with Logos, the report published, findings fixed before mainnet.
Total Requested Budget (USD)
$75,000 (M1–M7, external audit included)
Relevant Experience
This RFP: the vesting program above — every on-chain hard requirement implemented, 75 tests, cycle table, full lifecycle on public testnet 0.2 including a privacy-preserving claim, with linked transactions and a re-verification script; platform findings reproduced by tests and a spel-cli fix open upstream (logos-co/spel#266).
Privacy-ledger tooling on Canton (a privacy-preserving ledger with public and private state, like LEZ): the Canton Go SDK (go-daml) and wallet library (go-wallet-daml) — signing, submission and ledger-API clients built from scratch.
On-chain and tooling work elsewhere: session-key smart accounts with spend caps and freeze on Monad (monad-agent-kit), a Rust monitoring agent for validator operators (monad-sentinel), Cosmos and Solana exporters and indexers.
Operations: validators, RPC and indexing for 60+ networks with 24/7 on-call (noders.team) — the base for the maintenance and hosted-indexer commitments below.
Post-Delivery Plan
Continuity, at no additional charge, for 12 months after mainnet: defect fixes across program, SDK, CLI and mini-app; tracking of LEZ, SPEL and RISC Zero releases with the cycle table re-measured on each; the event mapping kept current with the runtime event API; security reports acknowledged within 48 hours; a public verification bundle per release; a maintenance report at month 6 and month 12. After month 12, best-effort maintenance continues as long as we operate LEZ infrastructure, and we hand over cleanly if Logos assigns a successor.
Operated service: a NODERS-hosted vesting indexer with an unlock-notification endpoint (schedule created, cliff reached, claimable now) for LEZ wallets and dashboards, served next to the Logos explorer we already run — REST + WebSocket, open-sourced with the SDK so anyone can run their own; it indexes public schedule state only and learns nothing about private claim destinations.
Adoption: the nominated milestone authority is the hook RFP-015/016 name for creator-collateral vesting; we will offer the integration to whichever teams are awarded those RFPs and publish the three reference flows (team vesting, investor lockup, grant milestones) as SDK examples.
Permissions and Consent
I/We confirm Logos may contact me using the primary contact information provided above for follow-ups and next steps.
I/We consent to Logos using information from this proposal publicly such as blogs case studies social posts or analytical reporting. Redactions can be requested at any time.
Program Requirements
I/We have read and agree to the Logos RFP Terms and Conditions and I understand that no Grant is awarded and no right to payment arises unless a Grant Agreement is executed.
I/We understand that RFP specifications are proposals rather than instructions, that Logos makes no representations as to their legal or regulatory treatment, and that we are responsible for assessing what we build, deploy or operate and for complying with the laws that apply to us.
I/We understand this project must be open-sourced under the MIT and Apache 2.0 Licenses unless explicitly approved otherwise.
I/We are prepared to deliver milestone-based outcomes.
RFP ID
RFP-017 — Privacy-Preserving Token Vesting
Your Project Name
Hourglass
Team or Organization Name
NODERS
Primary Contact
office@noders.team
Team Members
NODERS is a Web3 engineering team. We build SDKs, wallets, explorers and on-chain programs across privacy ledgers and L1s: the Canton Go SDK (go-daml) and wallet library, the open-source Logos testnet explorer we run today, smart-account and monitoring tooling on Monad, and the RISC Zero prototypes behind our Logos proposals. We also operate validators, RPC and indexing for 60+ networks with a 24/7 on-call rotation (noders.team) — which is what lets us commit to running what we build.
This proposal is filed from the NODERS organisation account (nodersteam).
Project Summary
Hourglass is production-ready, privacy-preserving token vesting for LEZ: cliff+linear, fully linear and milestone schedules; token-denominated escrow held in a program-controlled vault; claims paid — at the beneficiary's choice, at claim time — to a public holding or to a fresh private account the creator never learns; the universal cancellation invariant with one-way non-cancelable conversion; transferable positions; separate cancellation and milestone authorities; batch creation; a typed event schema; and the SDK, CLI and Basecamp mini-app with the pre-claim summary and privacy disclosure the RFP asks for.
The on-chain core is built and running on public testnet 0.2. Every on-chain hard requirement of RFP-017 is implemented and exercised end to end — on the public testnet, including a privacy-preserving claim; batch creation through the zkVM state machine; events through the documented seam (see Known gaps).
noders-team/lez-programs→programs/vesting, tagtestnet-0.2-evidence-v4, on upstreamlogos-blockchain/lez-programs6b53f3a(LEZ v0.2.4)952b031fecf9e357c76daca7c307e0debb4949d30d419b3c3a1db402a1fa46be, deploy tx5feaa17a…(block 27324)docs/vesting/testnet-evidence.md3a2828ab…(block 27362): 1,000 tokens from the escrow to a fresh private account in one privacy-preserving transactionmainClaim376,495 user cycles (524,288 padded, 1.6 % of the public-execution budget); batch of 10: 7 %scripts/vesting/verify-onchain.shagainst the live sequencer — confirms all 21 lifecycle steps (inclusion and non-inclusion), the 8 final balances and the 6 private-claim properties: ALL GOODdocs/vesting/TECHNICAL-APPENDIX.md— mechanics, platform findings, test matrix, cycle table, reproduction commandsTwo results matter most for this RFP.
Token-denominated escrow works today. The vault is a program-derived account, funded and paid out by chained Token Program transfers. Although RFP-017 lists LP-0013 as an open custody blocker, the deployed program needs no transfer-authority primitive: LP-0013 in fact landed upstream as a mint-authority model, and escrow of any SPEL token runs on testnet now (Appendix C, E.1).
The private claim runs on the public testnet. The registered public beneficiary signs the claim; the destination is a fresh private account that is not revealed to the creator or to public observers. The recorded transaction claimed 1,000 tokens in a single privacy-preserving transaction. Reproduction steps, the zkVM state-machine tests, the clock-binding design and the proof evidence are in Appendix A, B and D.
What the grant funds is the client surface (SDK, CLI, Basecamp mini-app), program hardening, runtime events, an external audit before mainnet, the testnet 0.3 migration and the mainnet release. Twelve months of maintenance and an operated indexer are included at no extra charge. The repository is public from the day of filing; a fresh schedule with a Logos-held beneficiary key can be provisioned on request so a reviewer can run the private claim end to end.
Technical Approach
Architecture. One schedule account and one escrow vault PDA per schedule. Nine instructions, in discriminant order:
CreateSchedule,CreateScheduleBatch,Claim,ClaimTo,Cancel,MakeNonCancelable,SignalMilestone,TransferBeneficiary,ClaimToPrivate. The vault is funded at creation and paid out at claim and cancel through chained Token Program transfers authorised withpda_seeds— the pattern the upstream AMM uses for its own vaults; the runtime applies a call chain only if every call succeeds (LP-0015, delivered in the core runtime), which makes each claim and cancel one atomic transaction. Schedule state carries the parties, amounts, kind, flags, nominated authorities and an event seam. Account layout, PDA derivation and custody mechanics: Appendix C.How the hard requirements are met.
vested(end) == totalexactly), fully linear, and milestone tranches unlocked in order by the milestone authority with idempotent signalling (R4). M1 adds an optionalcliff_amount. Math and overflow argument: Appendix C.6.Claimpays that holding;ClaimTopays any public destination;ClaimToPrivatepays a fresh private account created by the claim itself. Observers see the schedule, the amount and the signing holding; the destination appears on chain only as a commitment, and the creator never learns it. Because a privacy-preserving transaction cannot read the per-block clock without expiring in one block,ClaimToPrivatecarries anas_oftimestamp and pins it as the lower bound of the runtime's validity window, so it can never pay more than was vested at inclusion. Execution model and clock design: Appendix B and D.Cancelfreezes accrual, returns the unvested remainder to the creator in the same transaction, and leaves vested tokens claimable;MakeNonCancelableis one-way. Both are gated by the nominated cancellation authority (default: the creator holding; a multisig or DAO holding works). SDK, CLI and mini-app default new schedules to cancelable, as the RFP specifies.Created,Claimed,Cancelled,MadeNonCancelable,MilestoneSignalled,BeneficiaryTransferred), schema documented. LEZ v0.2.4 has no runtime event API, so today the program ships an event seam —event_seq+last_eventin the schedule account — that maps 1:1 onto the runtime events the LEZ team merged intodevon 2026-08-27 and is wired to them in the testnet 0.3 milestone.Client surface (U1–U7, Privacy 2–3). SDK as a Rust core module with a C ABI (the
modules/tokenpattern) exposing create, query-claimable, claim, claim-to (public and private), cancel, signal and transfer; the private claim becomes an SDK call with an async prove / submit / re-prove state machine and proving-progress reporting. CLI over the IDL with aclaimablequery and actionable errors computed locally before submission ("nothing claimable — next unlock at …", insufficient gas, not a private account). Basecamp mini-app in QML/C++ (theapps/tokenpattern): recipient view (position, locked, claimable now, next unlock, claim with pre-claim summary, gas check on the private path, privacy disclosure) and creator view (create with all parameters, list, cancel, signal). The pre-claim summary reads the network's fee schedule; testnet 0.2 charges no fee, so there it shows 0, and the gas check is live the moment a fee exists. The SPEL IDL exists today (artifacts/vesting-idl.json, pinned to the instruction enum by a test) and is frozen at M1.Known gaps and platform constraints. Each is reproduced by a test or a command in the repository; the full list with the milestone that addresses each is Appendix I.
spel-clidrives 7 of 9 instructions and the private claim runs through the evidence tooltools/vesting-private-claim.new_claimed_if_defaultin M1.Requirement traceability. Status today and the milestone that closes each item (test names per requirement: Appendix F).
cliff_amount)3a2828ab…) + zkVM testsspel-cliover the IDL, 7/9 instructionsartifacts/vesting-idl.json+ order testMilestones, Payout and Timeline
cliff_amount) reviewed with Logos in week 1; program tightenings:cliff_amount, holding-vs-token-definition validation,ClaimToPrivatedefault-destination check and optionalvalid_until, plain-wallet authorities, fee switch + broker option; edge-case, property and explicit R1/R2 tests; sequencer e2e in CI; IDL frozen; program re-verified on the current testnetmainclaimableand local actionable errorsCore delivery M1–M5: 11.5 weeks; 12.5 with M6/M7. M6 and M7 are paid only on the corresponding release; if a release has not shipped within six months of M5, the milestone scope is re-agreed with Logos, not paid early. Of the $75,000, $65,000 is the build (M1–M4, M6, M7) and $10,000 the external audit, paid as the work is delivered; the 12-month maintenance window and the operated indexer (Post-Delivery Plan) add nothing to the price.
On team size and price. Three full-time engineers for ten and a half engineering weeks, with the program already on testnet, is what lets the schedule hold: the grant buys client surface, hardening and two platform migrations, not discovery.
On the audit. The template asks for an audit milestone where user funds are handled; the escrow handles them, so the audit is a milestone. The custody logic is compact with a single custody invariant, and M4 delivers an audit-ready bundle (traceability, invariants, threat notes) so a third-party review is a two-week job. It is inside the price: $10,000 passed through at cost to a firm agreed with Logos, the report published, findings fixed before mainnet.
Total Requested Budget (USD)
$75,000 (M1–M7, external audit included)
Relevant Experience
spel-clifix open upstream (logos-co/spel#266).Post-Delivery Plan
Continuity, at no additional charge, for 12 months after mainnet: defect fixes across program, SDK, CLI and mini-app; tracking of LEZ, SPEL and RISC Zero releases with the cycle table re-measured on each; the event mapping kept current with the runtime event API; security reports acknowledged within 48 hours; a public verification bundle per release; a maintenance report at month 6 and month 12. After month 12, best-effort maintenance continues as long as we operate LEZ infrastructure, and we hand over cleanly if Logos assigns a successor.
Operated service: a NODERS-hosted vesting indexer with an unlock-notification endpoint (schedule created, cliff reached, claimable now) for LEZ wallets and dashboards, served next to the Logos explorer we already run — REST + WebSocket, open-sourced with the SDK so anyone can run their own; it indexes public schedule state only and learns nothing about private claim destinations.
Adoption: the nominated milestone authority is the hook RFP-015/016 name for creator-collateral vesting; we will offer the integration to whichever teams are awarded those RFPs and publish the three reference flows (team vesting, investor lockup, grant milestones) as SDK examples.
Permissions and Consent
Program Requirements