RFP ID
RFP-008 — Lending & Borrowing Protocol
Your Project Name
Agora
Team or Organization Name
Evice Labs
Primary Contact
Discord: @bristinborah.sol, @syafiqeil, @mmlado
Team Members
Member 1
- Name: Bristin Borah
- Social links: https://www.linkedin.com/in/bristin-borah-739b63179/ | https://github.com/bristinWild
- Role: Lead on-chain engineer — singleton core program (SPEL), market registry, supply/withdraw/borrow/repay accounting, liquidation engine, flash loans (LP-0015 capability model), token custody integration (LP-0013 authority model), oracle read interface, reference liquidator daemon, reference risk-monitor daemon, CLI, event integration (LP-0012), and devnet/testnet deployment pipeline.
- LEZ Track Record: Delivered LP-0012 — Structured Event System for LEZ Programs (Winner, Merged). Delivered LP-0013 — Token Program Improvements: Authorities (Winner, Merged as
lez-programs#213). SPEL framework contributor (spel#212, #[require_admin] macro).
- Status: Independent Developer Team.
Member 2
- Name: Syafiq Nabil Assirhindi
- Social links: https://www.linkedin.com/in/syafiq-nabil-assirhindi/ | https://github.com/syafiqeil
- Role: AdaptiveCurveIRM program (separate immutable program, fixed-point rate math), Rust SDK with privacy path (deshield→interact→reshield, ephemeral account enforcement), headless core module extraction, delegated position management, and integration test suite.
- LEZ Track Record: Delivered LP-0016 — Anonymous Forum with Threshold Moderation: a full-stack privacy-preserving protocol spanning SPEL on-chain programs, RISC Zero ZK circuits, a forum-agnostic Rust SDK with C-ABI FFI, and native Logos Basecamp module integration.
- Status: Independent Developer Team.
Member 3
- Name: Mladen Milankovic
- Social links: https://www.linkedin.com/in/mladenmilankovic/ | https://github.com/mmlado
- Role: Admin authority integration (RFP-001) for LLTV/IRM registries and protocol fee, Basecamp mini-app (core module + QML/C++ GUI with position management, market views, LTV preview), formal verification coordination, and Figma designs.
- LEZ Track Record: RFP-001 — Admin Authority Library (Accepted, Development Phase). RFP-002 — Freeze Authority Library (Accepted, Development Phase). SPEL extension-architecture contributor.
- Status: Independent Developer Team.
Project Summary
We propose to build Agora, a faithful Morpho Blue equivalent on LEZ: a single immutable singleton program holding all isolated lending markets, each defined by five immutable parameters (loan token, collateral token, oracle, IRM, LLTV) and keyed by the deterministic hash of those parameters.
Our case for selection is concrete: two of RFP-008's four platform dependencies are our own merged contributions (LP-0012 structured events, LP-0013 token authorities), and a third (RFP-001 admin authority) is being built by our team member. This matters practically: when the lending core hits an executor-level edge case (as LP-0013 repeatedly did — InconsistentAccountPreState on mid-transaction PDA state changes, duplicate-account-id rejection, authorization scope mismatches), we have already debugged that class of failure at source level.
Deliverables cover every hard requirement: permissionless market creation, supply/withdraw with donation-resistant virtual-share accounting, collateralised borrow/repay, the AdaptiveCurveIRM as a separate immutable program, permissionless no-close-factor liquidation with the LLTV-derived LIF formula, lazy interest accrual, zero-fee flash loans over LP-0015 capability continuations, delegated position management, a bounded admin (reusing RFP-001), reference liquidator and risk-monitor daemons built on LP-0012 events, a shared headless core module consumed by CLI + QML/C++ Basecamp GUI, the full deshield→interact→reshield private-account path, formal verification of the four required invariants, and a tier-1 audit programme.
We scope this proposal to the core lending primitives only. Curation layer (single-asset vaults, vault shares, supply/borrow caps) is RFP-012. Mainnet deployment and admin governance are handled through a separate process.
Technical Approach
1. Singleton core and market registry (F1–F3)
One deployed LEZ program owns all market state. Market state lives in PDAs derived from the market id — market_id = H(loan_token, collateral_token, oracle_program, irm_program, lltv) — with per-user position PDAs derived from (market_id, account_id). This keeps per-operation account sets small and constant regardless of total market count (P2).
The SPEL constraint set (mut/init/signer/owner/pda/private_pda/npk) covers everything the account layout needs; verified against SPEL v0.5 source that no framework extension is required for the core. The lending program custodies supplied assets and collateral via token accounts whose mint/transfer authority is a program PDA — the exact self/PDA-authority pattern (Mint/SetAuthority with the definition account as signer) that LP-0013's PR #213 established, and the same pattern the AMM's LP token now uses in production. A known executor constraint shapes the liquidation instruction: LEZ rejects a transaction listing the same account id twice. Liquidation involves the liquidator both repaying (loan token out) and seizing (collateral in); the account layout is designed so no account appears in two roles, mirroring how PR #213 split self/external authority variants for the same reason.
2. Time without an ambient clock (F8, F9)
Each state-mutating instruction takes the CLOCK_01 program account as a read-only input, and accrual computes elapsed = clock.now − market.last_accrual_time. Inside the zkVM this is deterministic and provable; the sequencer's validity window bounds how stale a submitted clock read can be. In the worst case, the interest error is bounded by rate × one validity window, and accrual never rewinds (monotonic last_accrual_time). Accrual is lazy per F9: any interaction with a market first settles interest into the supply/borrow indices, then executes. No crank.
3. AdaptiveCurveIRM as a separate immutable program (F8)
The IRM ships as its own immutable LEZ program implementing the Morpho AdaptiveCurveIRM: utilisation-targeting around ~90%, curve steepness adjusted by cumulative time-decay of the error term. It exposes pure read entrypoints (borrow APR / supply APY for a market id) requiring no state mutation — served from the IRM's own per-market rate-state PDA, updated on accrual. Rate math is fixed-point (WAD-style u128), ported against Morpho's published reference with property tests asserting invariant R3(c): borrow rate monotonically non-decreasing in utilisation.
4. Share accounting and the first-depositor problem (R7)
Virtual shares and virtual assets (VIRTUAL_SHARES, VIRTUAL_ASSETS), exactly as Morpho Blue. The share↔asset conversion is a pure function covered by: (a) unit tests over empty/near-empty markets, (b) a dedicated donation-attack test, and (c) proptest fuzzing over conversion round-trips. Scheduled in Milestone 1, not deferred.
5. Liquidation (F10, R4, R5)
No close factor. The liquidator specifies exactly one of seized_collateral or repaid_debt; the program derives the other via the oracle price so that seized_value = repaid_value × LIF, with LIF = min(1.15, 1 / (0.3·LLTV + 0.7)) fixed in the immutable core. Bad debt remaining after collateral exhaustion is socialised into the market's supply index, isolated per market. Liquidation is a single transaction callable by anyone. If compute benchmarking shows single-transaction liquidation exceeding LEZ's budget, the funded fallback is a two-phase liquidation over an LP-0015 tail-call continuation.
6. Flash loans over LP-0015 (F14)
The flash entrypoint transfers requested tokens to the borrower, then tail-calls the borrower's continuation with an unforgeable repayment capability (per LP-0015's capability-protected continuation model). The borrower's continuation must, before the transaction terminates, tail-call back into the lending program's internal repay_flash continuation with the capability and the exact principal. If the transaction does not complete the chain with full repayment, the entire transaction reverts atomically and no funds leave the market. There is no synchronous reentrancy: control hands off fully at each tail call, so the EVM concepts of CEI ordering and reentrancy locks do not apply. We will document the trust argument explicitly in the security docs, since it differs from EVM intuitions reviewers will bring. Flash loans are zero-fee, matching Morpho Blue's deployed implementation.
7. Oracle integration (F13, R1)
Oracle-agnostic core, matching Morpho: the market's oracle program is called and its price trusted, no staleness check in the core. If a feed halts, only price-dependent operations (borrow, liquidate) on that market fail; supply/withdraw/repay continue. The core integrates against a minimal oracle read interface so any provider (RFP-020 Kanon, RFP-019 TWAP) slots in identically.
8. Bounded admin via RFP-001 (F11, F12)
The admin surface — enable/disable LLTV values, enable IRMs, set protocol fee ≤ 25% hard cap and recipient — reuses Mladen's RFP-001 admin-authority library, which RFP-008's Resources section names as the intended pattern. The fee cap is enforced in the immutable core.
9. Delegated position management (F17)
Per-account authorisation registry ((owner, manager) → bool) with grant/revoke instructions, plus a signature-based path equivalent to setAuthorizationWithSig — using LEZ's native signature verification over a domain-separated message including a nonce, so a third party can submit the authorising transaction on behalf of the position owner. Liquidation bypasses authorisation entirely (permissionless per F10).
10. App architecture, privacy path, and reference daemons
One headless core module (Rust) owns all transaction construction, state querying, and SDK logic. Four consumers, zero business logic outside the core: CLI, QML+C++ GUI (Basecamp-loadable), reference liquidator daemon, reference risk-monitor daemon. The daemons subscribe to LP-0012 structured events rather than polling accounts.
Private-account interaction implements the full deshield→interact→reshield pattern with the reshield step non-skippable, atomic gas funding within the deshield, fresh single-use ephemeral accounts, pre-confirmation visibility summaries, reshield-target validation, and pre-flight balance checks. GUI previews projected position LTV before borrow/collateral-withdraw confirmation.
11. Formal verification and audit (R3, S10)
Four invariants verified before mainnet recommendation: (a) sub-LLTV positions cannot be liquidated, (b) supply-share value monotonic absent socialised bad debt, (c) IRM rate monotonic in utilisation, (d) solvency. Certora targets EVM and recently Solana SBF — not RISC-V — so "Certora-style" formal verification of the deployed program is not directly deliverable on this stack today. Our plan: extract the pure accounting and rate math into a target-independent core and verify that core with the best available tooling at the milestone (Certora if a RISC-V/LEZ target materialises; otherwise exhaustive Kani model checking and proptest-based property testing of the extracted pure math). The verification commitment is to the four invariants, not to a specific vendor. Audit: we intend to engage a tier-1 firm (Trail of Bits is our current preference) for the lending core, IRM, daemons, and bundler if built. The audit scope and pricing will be finalised at the M6 gate; M7's budget covers our remediation and coordination work. A second independent review is strongly targeted given immutability. Reports published with the codebase before mainnet recommendation.
RFP-008 Hard Requirements Coverage
Functionality
| # |
Requirement |
Milestone |
Notes |
| F1 |
Singleton program holding all markets |
M1 |
Single deployment, PDAs per market |
| F2 |
Immutable, non-upgradeable core |
M1 |
No proxy, no migration, no admin pause |
| F3 |
Permissionless market creation (5 params, deterministic hash) |
M1 |
Oracle chosen by creator, not admin-gated |
| F4 |
Supply loan token, internal share tracking per market per account |
M1 |
Virtual shares (R7) |
| F5 |
Withdraw supplied tokens (subject to liquidity) |
M1 |
|
| F6 |
Deposit collateral + borrow up to LLTV |
M2 |
Health check against oracle |
| F7 |
Repay borrowed tokens |
M2 |
Full or partial |
| F8 |
AdaptiveCurveIRM — separate immutable program, ~90% target, time-decay |
M3 |
Pure read APIs, WAD-style u128 |
| F9 |
Lazy interest accrual (on interaction, no crank) |
M2 |
CLOCK_01-bound elapsed time |
| F10 |
Permissionless liquidation, no close factor, LIF formula, bad debt socialization |
M4 |
Single-tx (or two-phase if CU exceeded) |
| F11 |
Bounded admin: LLTV grid, IRM enable, no pause/upgrade |
M1 |
RFP-001 admin authority |
| F12 |
Protocol fee ≤ 25% hard cap |
M1 |
Enforced in immutable core |
| F13 |
Oracle integration (oracle-agnostic, per-market) |
M2 |
Mock oracle for tests; any provider slots in |
| F14 |
Flash loans via LP-0015 capability continuations, zero-fee |
M4 |
Unforgeable repayment capability |
| F15 |
Reference liquidator daemon |
M5 |
LP-0012 events; headless core module |
| F16 |
Reference risk monitor (metrics API) |
M5 |
LP-0012 events; headless core module |
| F17 |
Delegated position management + signature-based auth |
M4 |
Liquidation bypasses auth |
Usability
| # |
Requirement |
Milestone |
Notes |
| U1 |
SPEL framework program with IDL |
M1 |
|
| U2 |
Core module + GUI module architecture |
M5, M6 |
Core: headless Rust; GUI: QML+C++ |
| U3 |
Local build instructions, Basecamp-loadable via git |
M6 |
|
| U4 |
CLI covering core functionality (same core module) |
M5 |
|
| U5 |
Reference daemons built on same core module, headless |
M5 |
|
| U6 |
GUI: create markets, supply, borrow, repay, withdraw, position health |
M6 |
|
| U7 |
Position LTV displayed per market per borrower (CLI + GUI) |
M5, M6 |
|
| U8 |
Supply APY, borrow APR, utilisation per market (CLI + GUI) |
M5, M6 |
|
| U9 |
Atomic deshield (deposit token + gas) as single action |
M5 |
SDK-enforced |
| U10 |
Pre-confirmation balance check (operation + fees) |
M5, M6 |
Actionable error if insufficient |
| U11 |
GUI LTV preview before borrow/collateral-withdraw |
M6 |
Current + projected LTV |
Reliability
| # |
Requirement |
Milestone |
Notes |
| R1 |
Oracle-agnostic core; stale feed → only price-dependent ops fail |
M2 |
Per Morpho trust model |
| R2 |
Permanent feed unavailability → borrow/liquidate rejected; others continue |
M2 |
Per-market isolation |
| R3 |
Bad debt socialised among market suppliers; isolated per market |
M4 |
Supply shares decrease in value |
| R4 |
4 invariants formally verified before mainnet |
M6 |
Best available tooling; see section 11 |
| R5 |
LIF bounded by formula; liquidation at LLTV is profitable for liquidator |
M4 |
Covered by formal verification |
| R6 |
Liquidation: single tx, any account, no privileged role |
M4 |
Permissionless |
| R7 |
Share accounting resists donation/inflation attacks (virtual shares) |
M1 |
Non-negotiable; tested in M1 |
Performance
| # |
Requirement |
Milestone |
Notes |
| P1 |
Document tx size per operation on LEZ |
M6 |
Benchmark report |
| P2 |
Linear scaling in market count; no per-market pollution |
M1 |
Constant account set per operation |
Supportability
| # |
Requirement |
Milestone |
Notes |
| S1 |
Deployed on LEZ testnet |
M6 |
|
| S2 |
E2E integration tests against LEZ sequencer, CI green |
M6 |
|
| S3 |
Every hard requirement has at least one test |
M6 |
|
| S4 |
README with deployment steps, program addresses, usage |
M6 |
|
| S5 |
SDK doc packet |
M5 |
|
| S6 |
CLI doc packet |
M5 |
|
| S7 |
Figma designs for GUI |
M5 |
Delivered before M6 implementation for feedback |
| S8 |
Privacy and anonymisation properties document |
M6 |
|
| S9 |
Supply/withdraw/repay cannot be paused/frozen by any admin |
M1 |
Consequence of immutability |
| S10 |
Audit programme: tier-1 firm named, budget as line item, timeline before mainnet |
M7 |
Trail of Bits; reports published |
Privacy
| # |
Requirement |
Milestone |
Notes |
| PV1 |
SDK + GUI support public and deshield→interact→reshield paths; reshield non-skippable |
M5, M6 |
|
| PV2 |
Pre-confirmation summary: what is visible vs private on-chain |
M6 |
|
| PV3 |
SDK validates reshield target is private account |
M5 |
|
| PV4 |
Ephemeral account never reused; single-use enforcement documented |
M5 |
Deterministic nonce-derived keypair + consumed-key registry |
Soft Requirements
| # |
Requirement |
Milestone |
Notes |
| Soft1 |
On-chain bundler program (approve+supply+borrow in one tail-call chain) |
M4 |
If time permits |
Out of Scope — Acknowledged
| Item |
Reason |
| Mainnet deployment |
Separate process |
| LLTV grid for mainnet |
Deployment governance |
| Admin authority governance (token, DAO, multisig) |
Out of scope |
| Curation layer (vaults, vault shares, caps) |
RFP-012 |
| Alternative IRM implementations |
Future admin-enabled |
| CDP-style minting |
RFP-013 |
| Cross-chain liquidity |
Out of scope |
| Off-chain indexing (subgraph/GraphQL) |
Future RFP |
Milestones, Payout and Timeline
| Milestone |
Payout (USD) |
Duration |
Owner |
Deliverables |
| M1 — Core & Registry |
$18,000 |
Weeks 1–2 |
Bristin (core program), Mladen (admin authority) |
Singleton core program; market creation with deterministic id; admin-enabled LLTV/IRM registries via RFP-001; supply/withdraw with virtual-share accounting; donation-attack test suite green; core program + unit/integration tests against standalone sequencer. Two-week pace is realistic: SPEL-init scaffold exists, the LP-0013 custody pattern ports directly, and the RFP-001 author is on the team. |
| M2 — Borrow, Repay, Accrual, Oracle |
$27,000 |
Weeks 3–5 |
Bristin (positions, accrual, oracle), Syafiq (SDK foundation) |
Position PDAs; health checks against oracle price; CLOCK_01-bound lazy accrual; oracle read interface + mock oracle for tests; full non-liquidation market lifecycle E2E on local sequencer |
| M3 — AdaptiveCurveIRM |
$15,000 |
Weeks 6–7 |
Syafiq (IRM program), Bristin (accrual integration) |
Separate immutable IRM program; pure read APIs; fixed-point rate math; monotonicity property tests; integration with accrual; rate-model test report |
| M4 — Liquidation & Flash Loans |
$27,000 |
Weeks 8–9 |
Bristin (liquidation, flash loans), Syafiq (delegated auth) |
LIF-formula liquidation (either-or spec); bad-debt socialisation; LP-0015 capability flash loans; delegated position management incl. sig-based path; adversarial test suite |
| M5 — Core Module, CLI, Daemons, Privacy, Figma |
$28,000 |
Weeks 10–12 |
Syafiq (core module, SDK, privacy path), Bristin (CLI, daemons), Mladen (Figma designs, mini-app scaffolding) |
Headless core module extraction; CLI; liquidator + risk-monitor daemons on LP-0012 events; full private-account path with single-use ephemeral enforcement; SDK + CLI doc packets; Figma designs for GUI (ready for feedback before M6 implementation); daemons running against testnet |
| M6 — GUI, Verification, Benchmarks, Testnet |
$34,000 |
Weeks 13–16 |
Mladen (GUI implementation), Syafiq (formal verification), Bristin (benchmarks, deployment) |
QML+C++ Basecamp GUI (built from M5 Figma); formal verification of 4 invariants (extracted pure-math core, best available tooling — see section 11); liquidation compute benchmark on testnet (two-phase remediation if required); testnet deployment with program addresses; privacy & anonymisation properties document; audit engagement kicked off |
| M7 — Audit Remediation |
$45,000 |
Weeks 17–24 (external) |
All (remediation) |
Coordination with tier-1 audit firm (Trail of Bits or equivalent); remediation of audit findings; re-verification of fixed issues; mainnet-readiness documentation |
| Total |
$194,000 |
16 weeks dev + audit tail |
|
|
A second independent core audit, if required for mainnet recommendation, would be scoped and budgeted separately at that gate.
Total Requested Budget (USD)
$194,000
| Line item |
Amount (USD) |
| Engineering — M1–M6 (3 engineers × 16 weeks) |
$149,000 |
| Audit remediation — M7 (coordination + remediation + re-verification) |
$45,000 |
| Total requested |
$194,000 |
| Tier-1 audit (Trail of Bits or equivalent; estimated, not included above) |
$60,000–$70,000 |
The RFP requires the audit budget as a line item: we estimate $60K–$70K for a tier-1 engagement covering the lending core, AdaptiveCurveIRM, reference daemons, and bundler if delivered. This estimate is based on comparable scope engagements. The final audit contract is subject to scope finalisation at the M6 gate. If Logos prefers to contract the audit firm directly, the audit fee does not flow through our budget — M7 ($45K) covers our remediation and coordination work regardless of how the audit is funded.
Relevant Experience
Bristin Borah — lead on-chain engineer. Author of two of RFP-008's four platform dependencies, with deep LEZ executor and token-program internals experience. SPEL framework contributor.
-
LP-0012 — Structured Event System for LEZ Programs (Winner, Merged):
-
LP-0013 — Token Program Improvements: Authorities (Winner, Merged as lez-programs#213):
-
SPEL Framework — #[require_admin] macro contribution spel#212:
Active participation in the extension-architecture direction in builder-hub.
Syafiq Nabil Assirhindi — SDK architect and IRM engineer. Hands-on experience with RISC Zero ZK circuits, SPEL program development, and privacy-preserving protocol design on LEZ.
-
LP-0016 — Anonymous Forum with Threshold Moderation (Logos):
-
ZK-AppChain: https://github.com/evice-labs/e-zkappchain
A sovereign ZK rollup with a CLOB matching engine (Velocity-DEX) and MEV protection. Architecture: ZK prover (Winterfell AIR), sequencer node, settlement engine (Alloy-rs) — demonstrating DeFi engineering and fixed-point arithmetic experience applicable to AdaptiveCurveIRM rate math.
Mladen Milankovic — 19 years of professional software development experience. Author of the admin authority library that RFP-008's Resources section names as the intended pattern for the bounded admin surface.
-
RFP-001 — Admin Authority Library (LEZ, Accepted):
- Repo: https://github.com/mmlado/spel-admin-authority
- Docs: admin-authority guide
- Standardised admin authority library for LEZ programs. Implements authority assignment (
admin_initialize), transfer (admin_transfer), and revocation (admin_renounce) as first-class SPEL annotations (#[admin_authority], #[require_admin]). RFP-008's Resources section explicitly names RFP-001 as the reference pattern for the bounded admin authority (F11, F12). As the author, Mladen ensures zero-friction integration. End-to-end tested against LEZ v0.2.0.
-
RFP-002 — Freeze Authority Library (LEZ, Accepted):
-
SPEL Framework — Generic Extension Scanner (in review):
- Docs: Build a SPEL Extension Library
- Framework-side enabling change for the SPEL extension architecture: a metadata-driven discovery mechanism (
[package.metadata.spel]) that lets path-dep extension libraries ship #[instruction] fns auto-discovered by the framework and merged into a consuming program's dispatcher + IDL. The framework carries zero hardcoded knowledge of any specific extension — RFP-001's admin-authority is the first consumer, RFP-002's freeze-authority the second, and any future extension plugs in by declaring the same metadata with no further framework changes required. This decouples extension libraries from the framework's release cadence.
-
LP-0009 — Keycard NIP-46 Nostr Signer Proxy (Logos Ecosystem):
- Repo: https://github.com/mmlado/nip46-keycard
• NIP-44 v2 encryption implemented from scratch with full spec vector test coverage
• Demonstrates cryptographic protocol engineering and daemon architecture
-
LP-0010 — Shell dApp Integration Proof of Concept (Logos Ecosystem):
(Note: LP-0009 and LP-0010 are contributions to the broader Logos ecosystem. RFP-001, RFP-002, and the SPEL extension scanner represent Mladen's current active development on LEZ-native infrastructure.)
Risks & Mitigations
- Liquidation exceeds LEZ per-tx compute budget. Benchmark early (M4); two-phase tail-call liquidation designed and funded as remediation, with position-lock between phases. Benchmark figures published in the README per RFP deliverable.
- Core API churn (rc-series). LP-0013 was merged against a moving target (rc3→rc6 migrations,
nssa_core→lee_core); we have absorbed exactly this churn before and pin against tagged releases with a tracked migration checklist per rc bump.
- RFP-001 not yet merged upstream. The admin authority library is accepted and in active development by Mladen, but not yet merged into SPEL. If upstream merge is delayed, M1's admin integration uses the library from Mladen's branch directly; the switch to the merged crate is a one-line
Cargo.toml change once landed.
- Oracle availability. Hard blocker per RFP. An accepted provider exists: RFP-020 Kanon (#117, accepted). The core is developed against a mock oracle and the read interface is frozen early so any provider integrates without core changes.
- Formal-verification tooling maturity on LEZ targets. Certora does not yet target RISC-V/LEZ. Fallback declared: extracted pure-math core + exhaustive model checking (Kani/proptest) rather than silently weakening the guarantee. The commitment is to the four invariants, not to a specific vendor.
- No emergency pause (by design). We adopt the RFP's trust model as-is. Risk containment via market isolation, RFP-012's vault-layer sentinel (out of scope here), and the risk monitor's staleness signals.
Post-Delivery Plan
Evice Labs will maintain the Agora codebase asynchronously. This includes monitoring the open-source repository, reviewing community Pull Requests, patching potential bugs in non-core components (SDK, CLI, daemons, GUI), and ensuring ongoing compatibility with future LEZ and SPEL framework updates.
Core immutability by design: The core lending program and AdaptiveCurveIRM are immutable post-deployment — no patches, no upgrades. This is a feature, not a limitation: it matches Morpho Blue's trust model and is backed by formal verification + tier-1 audit before mainnet recommendation.
Reference daemons: The liquidator and risk monitor are reference implementations for third parties to fork and operate. Evice Labs will maintain the codebase but does not commit to running production instances; operation is the community's responsibility.
Audit follow-up: Any critical findings from the tier-1 audit will be remediated in non-core components. If a core finding is identified, the finding and its impact analysis will be published transparently; a redeployment of the core with the fix would follow the same formal verification + audit cycle.
Engineering Standards & Continuity: The three-person team structure ensures knowledge is shared across all components from day one — Bristin owns the core + executor internals, Syafiq owns the SDK + IRM, Mladen owns the admin layer + GUI. No single point of failure.
Permissions and Consent
Program Requirements
RFP ID
RFP-008 — Lending & Borrowing Protocol
Your Project Name
Agora
Team or Organization Name
Evice Labs
Primary Contact
Discord: @bristinborah.sol, @syafiqeil, @mmlado
Team Members
Member 1
lez-programs#213). SPEL framework contributor (spel#212,#[require_admin]macro).Member 2
Member 3
Project Summary
We propose to build Agora, a faithful Morpho Blue equivalent on LEZ: a single immutable singleton program holding all isolated lending markets, each defined by five immutable parameters (loan token, collateral token, oracle, IRM, LLTV) and keyed by the deterministic hash of those parameters.
Our case for selection is concrete: two of RFP-008's four platform dependencies are our own merged contributions (LP-0012 structured events, LP-0013 token authorities), and a third (RFP-001 admin authority) is being built by our team member. This matters practically: when the lending core hits an executor-level edge case (as LP-0013 repeatedly did —
InconsistentAccountPreStateon mid-transaction PDA state changes, duplicate-account-id rejection, authorization scope mismatches), we have already debugged that class of failure at source level.Deliverables cover every hard requirement: permissionless market creation, supply/withdraw with donation-resistant virtual-share accounting, collateralised borrow/repay, the AdaptiveCurveIRM as a separate immutable program, permissionless no-close-factor liquidation with the LLTV-derived LIF formula, lazy interest accrual, zero-fee flash loans over LP-0015 capability continuations, delegated position management, a bounded admin (reusing RFP-001), reference liquidator and risk-monitor daemons built on LP-0012 events, a shared headless core module consumed by CLI + QML/C++ Basecamp GUI, the full deshield→interact→reshield private-account path, formal verification of the four required invariants, and a tier-1 audit programme.
We scope this proposal to the core lending primitives only. Curation layer (single-asset vaults, vault shares, supply/borrow caps) is RFP-012. Mainnet deployment and admin governance are handled through a separate process.
Technical Approach
1. Singleton core and market registry (F1–F3)
One deployed LEZ program owns all market state. Market state lives in PDAs derived from the market id —
market_id = H(loan_token, collateral_token, oracle_program, irm_program, lltv)— with per-user position PDAs derived from(market_id, account_id). This keeps per-operation account sets small and constant regardless of total market count (P2).The SPEL constraint set (
mut/init/signer/owner/pda/private_pda/npk) covers everything the account layout needs; verified against SPEL v0.5 source that no framework extension is required for the core. The lending program custodies supplied assets and collateral via token accounts whose mint/transfer authority is a program PDA — the exact self/PDA-authority pattern (Mint/SetAuthoritywith the definition account as signer) that LP-0013's PR #213 established, and the same pattern the AMM's LP token now uses in production. A known executor constraint shapes the liquidation instruction: LEZ rejects a transaction listing the same account id twice. Liquidation involves the liquidator both repaying (loan token out) and seizing (collateral in); the account layout is designed so no account appears in two roles, mirroring how PR #213 split self/external authority variants for the same reason.2. Time without an ambient clock (F8, F9)
Each state-mutating instruction takes the CLOCK_01 program account as a read-only input, and accrual computes
elapsed = clock.now − market.last_accrual_time. Inside the zkVM this is deterministic and provable; the sequencer's validity window bounds how stale a submitted clock read can be. In the worst case, the interest error is bounded by rate × one validity window, and accrual never rewinds (monotoniclast_accrual_time). Accrual is lazy per F9: any interaction with a market first settles interest into the supply/borrow indices, then executes. No crank.3. AdaptiveCurveIRM as a separate immutable program (F8)
The IRM ships as its own immutable LEZ program implementing the Morpho AdaptiveCurveIRM: utilisation-targeting around ~90%, curve steepness adjusted by cumulative time-decay of the error term. It exposes pure read entrypoints (borrow APR / supply APY for a market id) requiring no state mutation — served from the IRM's own per-market rate-state PDA, updated on accrual. Rate math is fixed-point (WAD-style u128), ported against Morpho's published reference with property tests asserting invariant R3(c): borrow rate monotonically non-decreasing in utilisation.
4. Share accounting and the first-depositor problem (R7)
Virtual shares and virtual assets (
VIRTUAL_SHARES,VIRTUAL_ASSETS), exactly as Morpho Blue. The share↔asset conversion is a pure function covered by: (a) unit tests over empty/near-empty markets, (b) a dedicated donation-attack test, and (c) proptest fuzzing over conversion round-trips. Scheduled in Milestone 1, not deferred.5. Liquidation (F10, R4, R5)
No close factor. The liquidator specifies exactly one of
seized_collateralorrepaid_debt; the program derives the other via the oracle price so thatseized_value = repaid_value × LIF, withLIF = min(1.15, 1 / (0.3·LLTV + 0.7))fixed in the immutable core. Bad debt remaining after collateral exhaustion is socialised into the market's supply index, isolated per market. Liquidation is a single transaction callable by anyone. If compute benchmarking shows single-transaction liquidation exceeding LEZ's budget, the funded fallback is a two-phase liquidation over an LP-0015 tail-call continuation.6. Flash loans over LP-0015 (F14)
The flash entrypoint transfers requested tokens to the borrower, then tail-calls the borrower's continuation with an unforgeable repayment capability (per LP-0015's capability-protected continuation model). The borrower's continuation must, before the transaction terminates, tail-call back into the lending program's internal
repay_flashcontinuation with the capability and the exact principal. If the transaction does not complete the chain with full repayment, the entire transaction reverts atomically and no funds leave the market. There is no synchronous reentrancy: control hands off fully at each tail call, so the EVM concepts of CEI ordering and reentrancy locks do not apply. We will document the trust argument explicitly in the security docs, since it differs from EVM intuitions reviewers will bring. Flash loans are zero-fee, matching Morpho Blue's deployed implementation.7. Oracle integration (F13, R1)
Oracle-agnostic core, matching Morpho: the market's oracle program is called and its price trusted, no staleness check in the core. If a feed halts, only price-dependent operations (borrow, liquidate) on that market fail; supply/withdraw/repay continue. The core integrates against a minimal oracle read interface so any provider (RFP-020 Kanon, RFP-019 TWAP) slots in identically.
8. Bounded admin via RFP-001 (F11, F12)
The admin surface — enable/disable LLTV values, enable IRMs, set protocol fee ≤ 25% hard cap and recipient — reuses Mladen's RFP-001 admin-authority library, which RFP-008's Resources section names as the intended pattern. The fee cap is enforced in the immutable core.
9. Delegated position management (F17)
Per-account authorisation registry (
(owner, manager) → bool) with grant/revoke instructions, plus a signature-based path equivalent tosetAuthorizationWithSig— using LEZ's native signature verification over a domain-separated message including a nonce, so a third party can submit the authorising transaction on behalf of the position owner. Liquidation bypasses authorisation entirely (permissionless per F10).10. App architecture, privacy path, and reference daemons
One headless core module (Rust) owns all transaction construction, state querying, and SDK logic. Four consumers, zero business logic outside the core: CLI, QML+C++ GUI (Basecamp-loadable), reference liquidator daemon, reference risk-monitor daemon. The daemons subscribe to LP-0012 structured events rather than polling accounts.
Private-account interaction implements the full deshield→interact→reshield pattern with the reshield step non-skippable, atomic gas funding within the deshield, fresh single-use ephemeral accounts, pre-confirmation visibility summaries, reshield-target validation, and pre-flight balance checks. GUI previews projected position LTV before borrow/collateral-withdraw confirmation.
11. Formal verification and audit (R3, S10)
Four invariants verified before mainnet recommendation: (a) sub-LLTV positions cannot be liquidated, (b) supply-share value monotonic absent socialised bad debt, (c) IRM rate monotonic in utilisation, (d) solvency. Certora targets EVM and recently Solana SBF — not RISC-V — so "Certora-style" formal verification of the deployed program is not directly deliverable on this stack today. Our plan: extract the pure accounting and rate math into a target-independent core and verify that core with the best available tooling at the milestone (Certora if a RISC-V/LEZ target materialises; otherwise exhaustive Kani model checking and proptest-based property testing of the extracted pure math). The verification commitment is to the four invariants, not to a specific vendor. Audit: we intend to engage a tier-1 firm (Trail of Bits is our current preference) for the lending core, IRM, daemons, and bundler if built. The audit scope and pricing will be finalised at the M6 gate; M7's budget covers our remediation and coordination work. A second independent review is strongly targeted given immutability. Reports published with the codebase before mainnet recommendation.
RFP-008 Hard Requirements Coverage
Functionality
Usability
Reliability
Performance
Supportability
Privacy
Soft Requirements
Out of Scope — Acknowledged
Milestones, Payout and Timeline
A second independent core audit, if required for mainnet recommendation, would be scoped and budgeted separately at that gate.
Total Requested Budget (USD)
$194,000
The RFP requires the audit budget as a line item: we estimate $60K–$70K for a tier-1 engagement covering the lending core, AdaptiveCurveIRM, reference daemons, and bundler if delivered. This estimate is based on comparable scope engagements. The final audit contract is subject to scope finalisation at the M6 gate. If Logos prefers to contract the audit firm directly, the audit fee does not flow through our budget — M7 ($45K) covers our remediation and coordination work regardless of how the audit is funded.
Relevant Experience
Bristin Borah — lead on-chain engineer. Author of two of RFP-008's four platform dependencies, with deep LEZ executor and token-program internals experience. SPEL framework contributor.
LP-0012 — Structured Event System for LEZ Programs (Winner, Merged):
• Guest SDK (
emit_event(),EventRecord, Borsh-encoded payloads) in thelez-eventscrate• Event persistence on both success and failure paths (via
FAILURE_SENTINELpattern)•
getTransactionReceiptRPC method for event retrieval• 167 tests passing across all crates; merged into upstream LEZ
• Direct dependency of RFP-008 — the reference liquidator and risk monitor (F15, F16) consume exactly this event system
LP-0013 — Token Program Improvements: Authorities (Winner, Merged as
lez-programs#213):•
AuthoritySlot— reusable authority primitive in standalonelez-authoritycrate• Self/external authority-variant instruction shape (
Mint/MintWithAuthority,SetAuthority/SetAuthorityWithAuthority)• Deep experience with LEZ executor constraints:
InconsistentAccountPreStateon mid-transaction PDA state changes, duplicate-account-id rejection, authorization scope mismatches• Direct dependency of RFP-008 — the lending program custodies tokens via the exact PDA-authority pattern PR #213 established
SPEL Framework —
#[require_admin]macro contribution spel#212:Active participation in the extension-architecture direction in builder-hub.
Syafiq Nabil Assirhindi — SDK architect and IRM engineer. Hands-on experience with RISC Zero ZK circuits, SPEL program development, and privacy-preserving protocol design on LEZ.
LP-0016 — Anonymous Forum with Threshold Moderation (Logos):
• SPEL framework guest program with 4 instructions and per-instance PDA accounts
• Forum-agnostic Rust SDK compiled as both WASM and C-ABI shared library (cbindgen) — directly applicable to the headless core module architecture required by RFP-008
• Native Logos Basecamp integration: core module + QML UI module
• Full deshield→interact→reshield privacy pattern — directly reusable for the lending SDK's private-account path
ZK-AppChain: https://github.com/evice-labs/e-zkappchain
A sovereign ZK rollup with a CLOB matching engine (Velocity-DEX) and MEV protection. Architecture: ZK prover (Winterfell AIR), sequencer node, settlement engine (Alloy-rs) — demonstrating DeFi engineering and fixed-point arithmetic experience applicable to AdaptiveCurveIRM rate math.
Mladen Milankovic — 19 years of professional software development experience. Author of the admin authority library that RFP-008's Resources section names as the intended pattern for the bounded admin surface.
RFP-001 — Admin Authority Library (LEZ, Accepted):
admin_initialize), transfer (admin_transfer), and revocation (admin_renounce) as first-class SPEL annotations (#[admin_authority],#[require_admin]). RFP-008's Resources section explicitly names RFP-001 as the reference pattern for the bounded admin authority (F11, F12). As the author, Mladen ensures zero-friction integration. End-to-end tested against LEZ v0.2.0.RFP-002 — Freeze Authority Library (LEZ, Accepted):
SPEL Framework — Generic Extension Scanner (in review):
[package.metadata.spel]) that lets path-dep extension libraries ship#[instruction]fns auto-discovered by the framework and merged into a consuming program's dispatcher + IDL. The framework carries zero hardcoded knowledge of any specific extension — RFP-001's admin-authority is the first consumer, RFP-002's freeze-authority the second, and any future extension plugs in by declaring the same metadata with no further framework changes required. This decouples extension libraries from the framework's release cadence.LP-0009 — Keycard NIP-46 Nostr Signer Proxy (Logos Ecosystem):
• NIP-44 v2 encryption implemented from scratch with full spec vector test coverage
• Demonstrates cryptographic protocol engineering and daemon architecture
LP-0010 — Shell dApp Integration Proof of Concept (Logos Ecosystem):
• Full ERC-4527 / Uniform Resources protocol implementation; 56 unit tests
• Demonstrates frontend development and UI/UX design for the lending GUI
(Note: LP-0009 and LP-0010 are contributions to the broader Logos ecosystem. RFP-001, RFP-002, and the SPEL extension scanner represent Mladen's current active development on LEZ-native infrastructure.)
Risks & Mitigations
nssa_core→lee_core); we have absorbed exactly this churn before and pin against tagged releases with a tracked migration checklist per rc bump.Cargo.tomlchange once landed.Post-Delivery Plan
Evice Labs will maintain the Agora codebase asynchronously. This includes monitoring the open-source repository, reviewing community Pull Requests, patching potential bugs in non-core components (SDK, CLI, daemons, GUI), and ensuring ongoing compatibility with future LEZ and SPEL framework updates.
Core immutability by design: The core lending program and AdaptiveCurveIRM are immutable post-deployment — no patches, no upgrades. This is a feature, not a limitation: it matches Morpho Blue's trust model and is backed by formal verification + tier-1 audit before mainnet recommendation.
Reference daemons: The liquidator and risk monitor are reference implementations for third parties to fork and operate. Evice Labs will maintain the codebase but does not commit to running production instances; operation is the community's responsibility.
Audit follow-up: Any critical findings from the tier-1 audit will be remediated in non-core components. If a core finding is identified, the finding and its impact analysis will be published transparently; a redeployment of the core with the fix would follow the same formal verification + audit cycle.
Engineering Standards & Continuity: The three-person team structure ensures knowledge is shared across all components from day one — Bristin owns the core + executor internals, Syafiq owns the SDK + IRM, Mladen owns the admin layer + GUI. No single point of failure.
Permissions and Consent
Program Requirements