Commit Graph
18 Commits
Author SHA1 Message Date
r4bbit 51887aa3fb feat(twap-oracle): implement PublishPrice with real tick-to-price conversion
Add PublishPrice — a permissionless instruction that computes the TWAP over a
PriceObservations buffer and writes it to the consumer-facing OraclePriceAccount.

Because each observations account is calibrated to a specific window_duration via
its sampling guard, the oldest valid entry is always the natural window start, so
the TWAP is computed over the full buffer span with no boundary search:

    t2        = most recent observation (write_index - 1, wrapping)
    t1        = oldest valid entry (0 if not full, write_index if full)
    twap_tick = (t2.tick_cumulative - t1.tick_cumulative) / (t2.ts - t1.ts)

If fewer than two observations exist the call is a silent no-op, leaving the price
account at timestamp = 0 (the uninitialized signal consumers already reject). While
the buffer is young the TWAP is computed over the available span, which may be
shorter than the requested window.

The TWAP tick is converted to an actual price ratio via the Uniswap v3 sqrtPriceX96
representation (pure integer, zkVM-safe): get_sqrt_ratio_at_tick(tick) then
sqrtPriceX96^2 / 2^128, yielding a Q64.64 fixed-point ratio stored in
OraclePriceAccount.price. The OraclePriceAccount stays source-agnostic — no tick or
Uniswap framing leaks into the standard. Out-of-range ticks clamp; ratios above 2^64
saturate at u128::MAX. Adds PRICE_FRACTIONAL_BITS = 64; removes the placeholder
TWAP_PRICE_BIAS / oracle_price_to_tick bias encoding.

Pulls in uniswap_v3_math 0.6.2 and alloy-primitives for the conversion. Pins ruint
to =1.17.0 (transitive via alloy-primitives): 1.18 raised its MSRV to rustc 1.90 but
the risc0 guest toolchain ships 1.88. Guest build verified for riscv32im.

Closes #117
2026-06-02 19:52:48 +02:00
r4bbit c59316b4a2 feat(twap-oracle): implement CreatePriceObservations instruction
Adds the CreatePriceObservations instruction to the TWAP oracle program.
The instruction initialises a PriceObservations PDA for a given price
source account and time window, writing the initial tick and timestamp
as the first entry.

Key design decisions:

- Per-window accounts: each (price_source, window_duration) pair maps to
  a distinct PriceObservations PDA. The window duration is baked into the
  PDA seed so a single price source can support multiple TWAP windows
  (24h, 7d, 30d) at independent sampling rates without sharing a buffer.

- window_duration not stored on struct: it is implicit in the PDA address.
  Any reader that located the account already knows the window duration
  used to derive it. Storing it would be redundant.

- Authorization is implicit: the PriceObservations PDA is derived from
  the price source account ID, so is_authorized = true on the price source
  proves the caller controls it without a redundant authority field.

- Impersonation is prevented by the PDA check: passing a controlled price
  source with a victim's observations account ID fails immediately because
  the computed PDA (from the attacker's source) does not match.

Closes #126
2026-05-29 09:32:37 +02:00
Andrea Franz 1ae2b325ff test(stablecoin): move chained-transfer coverage to integration tests 2026-05-26 10:31:52 +02:00
Ricardo Guilherme Schmidt a0a1e08dfb test(stablecoin): cover invalid withdraw transfer pre-states 2026-05-26 10:31:52 +02:00
Ricardo Guilherme Schmidt 291149b114 chore(twap_oracle): scaffold twap_oracle program
Closes #114
2026-05-25 20:04:33 +02:00
r4bbit 035f593f5e chore: update spel to v0.3.0 2026-05-19 08:40:35 +02:00
Ricardo Guilherme Schmidt 0b078b2dde fix(stablecoin): address open position review feedback 2026-05-13 12:23:20 +02:00
Ricardo Guilherme Schmidt f4f7b45bd4 feat(stablecoin): implement open_position
Adds the `open_position` instruction to the Stablecoin Program. The instruction
claims a per-owner `Position` PDA, initializes a collateral vault token holding
via a chained `Token::InitializeAccount` under the vault's PDA authority, and
moves `collateral_amount` from the user's holding into the vault with a chained
`Token::Transfer`. `Position` is persisted with `collateral_amount` and
`debt_amount = 0`; the debt path is deferred to `generate_debt`.

- Add `Position` struct, `OpenPosition` instruction variant, and
  `compute_position_pda{,_seed}` / `compute_position_vault_pda{,_seed}` helpers
  in `stablecoin_core` with domain-separated PDA seeds.
- Implement `open_position::open_position` mirroring the ATA `create` and AMM
  `new_definition` patterns: authorization and uninitialized-state asserts, PDA
  verification, and same-transaction chained `InitializeAccount` + `Transfer`.
- Wire the new instruction through the SPEL guest and regenerate the stablecoin
  IDL artifact.
- Cover the happy path, all assertion paths, and PDA determinism /
  non-collision in 11 new unit tests.
2026-05-13 12:23:20 +02:00
Ricardo Guilherme Schmidt 8005c74e26 feat(token): verify definition ownership via self_program_id in initialize and mint
Pass `ctx.self_program_id` from `ProgramContext` into `initialize_account`
and `mint`, which now assert that the token definition account is owned by
the token program. This prevents callers from supplying a foreign-owned
account as the definition.

See https://github.com/logos-co/spel/issues/172
2026-05-12 16:10:40 +02:00
r4bbit ceb8a4b597 chore: update spel
This updates the spel dependency, which introduces a breaking change.
To make reviewing changes easier from other changes, this update comes
in a separate commit.
2026-05-12 11:47:35 +02:00
r4bbit f4a0aaf8d0 feat: make use of spel's [#account_type] directive
This annotates custom account data as [#account_type], to allow for deserializing abritrary LEZ account data.

Closes #49
2026-05-12 10:04:22 +02:00
r4bbit e7a69f619f chore: update LEZ to v0.2.0-rc3 2026-05-12 08:46:36 +02:00
Andrea Franz 4178406fda feat(stablecoin): initial stablecoin scaffold
closes #86
2026-05-11 16:53:04 +02:00
Ricardo Guilherme Schmidt 471abef719 refactor!: Update dependencies and implement new required features across multiple modules
- Updated `nssa_core` and `spel-framework` dependencies to their respective release candidates in `Cargo.toml` and `Cargo.lock` files for `amm`, `ata`, and `token` modules.
- Enhanced the `new_definition` function in `amm/src/new_definition.rs` to include new claim logic and updated PDA seed calculations.
- Modified tests in `integration_tests/tests/amm.rs`, `integration_tests/tests/ata.rs`, and `integration_tests/tests/token.rs` to accommodate changes in transaction handling and account initialization.
- Refactored account initialization logic in `ata/src/create.rs` and `token/src/initialize.rs` to include authorization claims.
- Updated various functions in `token/src/mint.rs`, `token/src/new_definition.rs`, and `token/src/transfer.rs` to utilize the new claim system for account states.
- Adjusted the IDL generation tool to use the latest version of `spel-framework-core`.
2026-04-20 12:25:59 +02:00
r4bbit 94f14ae305 ci: add IDL freshness check and consolidate artifacts
Move IDL files to artifacts/ and add a convention-based CI check that
discovers all programs via */methods/guest/src/bin/*.rs and fails if
any program is missing its IDL or has one that is out of date.
2026-04-14 11:22:24 +02:00
Ricardo Guilherme Schmidt e61cd594b5 feat(amm): add SyncReserves instruction
Adds a new `SyncReserves` instruction that updates a pool's recorded
reserves to match the actual vault balances. This allows the pool to
absorb donations (direct token transfers to vaults) without breaking
the invariant — only upward adjustments are permitted; vaults may
not be under-collateralized relative to reserves.

Vault reading helpers (`read_fungible_holding`,
`read_vault_fungible_balances`) are implemented in `amm_core` so they
can be shared across instructions without crossing crate boundaries.
2026-04-09 14:48:35 +02:00
r4bbit f89a8f9865 chore: update spel and logos-execution-zone dependencies
This removes the need to depend on a custom version, since the necessary
changes have landed in `spel` upstream.
2026-04-01 17:19:36 +02:00
r4bbit 45ed284825 chore: initial repository setup for programs 2026-03-30 23:58:43 +02:00