Commit Graph
45 Commits
Author SHA1 Message Date
Ricardo Guilherme Schmidt e63d09f793 docs(stablecoin): list all five OpenPosition accounts and qualify size_of_val
The `Instruction::OpenPosition` doc claimed four required accounts but the
handler and IDL take five — the collateral token definition was missing.
Update the list to match the actual contract.

Also fully qualify `std::mem::size_of_val` in `From<&Position> for Data`
so the call no longer relies on Rust 1.80+ prelude additions for the
2021 edition.
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
Andrea Franz 22b41bdb3d chore(amm-ui): reorganize liquidity page components 2026-05-12 16:11:24 +02:00
Andrea Franz 9375129c9e chore(amm-ui): add layout and reorganize swap UI files 2026-05-12 16:11:24 +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
Andrea Franz 6eed55d7e4 chore(amm-ui): add SlippageToleranceControl 2026-05-11 10:15:52 +02:00
Andrea Franz 476087a36b chore(amm-ui): swap form activates exact input or output based on the fields updated
closes #56
2026-05-11 10:15:52 +02:00
Andrea Franz 3df3c3d7c4 feat(amm/ui): show swap summary under the swap card 2026-05-11 10:15:52 +02:00
r4bbit c8a192e377 chore(amm): validate fee tier in sync_reserves
All other entry functions validate the pools fee tier, except for this
function. This is likely because it doesn't make use of the fees.

To make the code consistent (and auditing easier), we're now validating
the fees in `sync_reserves` the same way.
2026-05-08 12:58:01 +02:00
r4bbit 0d532a8fd3 chore(amm): add defensive check for lp token solvency
This check is added to fulfill the program invariant that no more tokens
than owned can be burned. This was not a bug before, because the `token`
program will revert on `Transfer::Burn` when one tries to burn more
tokens than available.

So this change is merely for making the invariant explicit.
2026-05-08 12:43:22 +02:00
r4bbit e69c9107f0 fix(amm): validate user deposit accounts are owned by vault's token program
An attacker could pass user holding accounts owned by a malicious token
program. Since chained calls are dispatched to the program_owner of the
user holding account, a fake program could accept the transfer instruction
without actually moving tokens.

Add assertions in add_liquidity, remove_liquidity, swap_exact_input, and
swap_exact_output that user_holding_a and user_holding_b must share the
same program_owner as vault_a. The vault accounts are PDA-verified via
their account_id, making vault_a's program_owner the authenticated
reference. new_definition already validated that both user holdings use
the same program.

Adds 8 regression tests covering the wrong-program case for each
operation and each user holding slot.

Closes #69
2026-05-08 12:10:06 +02:00
r4bbit 6b21c3695a feat(amm)!: add transaction deadlines to swap and liquidity instructions
All mutable AMM instructions now require a `deadline: u64` field (Unix
timestamp in milliseconds). Enforcement uses the LEZ-native timestamp
validity window set on ProgramOutput; the runtime rejects the
transaction if the sequencer submission timestamp is at or past the
deadline.

BREAKING CHANGE: AddLiquidity, RemoveLiquidity, SwapExactInput,
SwapExactOutput, and NewDefinition instruction variants now require a
`deadline` field.

Closes #8
2026-05-06 13:26:11 +02:00
Andrea Franz 5a61cf39f2 chore(amm-ui): add swap confirmation modal
closes #58
2026-05-05 17:29:37 +02:00
Andrea Franz 37fc2ea088 chore(amm-ui): update styles to match the liquidity page 2026-04-30 12:42:43 +02:00
r4bbit 06a141ef6e chore: fix RISC-V guest build on macOS 26
Add .cargo/config.toml setting CFLAGS_riscv32im_risc0_zkvm_elf to
"-march=rv32im -nostdlib". This prevents cc-rs from injecting
macOS-specific flags (-arch arm64, -mmacosx-version-min) into the
riscv32-unknown-elf-gcc cross-compiler when building C dependencies
(e.g. ring) for the guest target, which causes build failures on
macOS 26 Tahoe.
2026-04-29 10:12:09 +02:00
Ricardo Guilherme Schmidt a3bdc964c7 feat(amm/ui): add mock confirmation flow (#64)
Fixes #64
2026-04-28 16:11:30 +02:00
Ricardo Guilherme Schmidt d92a61fd9b feat(amm/ui): add slippage min received controls (#63)
Fixes #63
2026-04-28 16:11:30 +02:00
Ricardo Guilherme Schmidt bf9001c363 feat(amm/ui): add remove-liquidity preview (#62)
Fixes #62
2026-04-28 16:11:30 +02:00
Ricardo Guilherme Schmidt 67b1e501e8 feat(amm/ui): add liquidity deposit preview (#61)
Fixes #61
2026-04-28 16:11:30 +02:00
Ricardo Guilherme Schmidt f5a01063ed feat(amm/ui): add pool position summary (#60)
Fixes #60
2026-04-28 16:11:30 +02:00
r4bbit 0cec2e2573 feat(amm-ui): add navbar to switch between views 2026-04-28 16:11:30 +02:00
Andrea Franz e18f0f3c32 chore(amm-ui): add basic swap UI for Token Pair Selector & Swap Direction
closes #55
2026-04-28 14:11:53 +02:00
Andrea Franz 29d949d75a feat(amm/ui): add initial AMM UI module 2026-04-22 10:52:48 +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
Ricardo Guilherme Schmidt 6c86b5b9ce feat(amm): apply trading fees to LP accounting
Implement Uniswap V2-style fees-in-reserves: the full swap_amount_in is
deposited into the reserve (growing k = reserve_a * reserve_b), while
only the fee-adjusted effective_amount_in is used to compute the output
amount. This means LPs earn fees proportionally on every removal via
k-growth rather than through a separate vault surplus.

- swap_logic: add fee_bps parameter; compute effective_amount_in for
  output formula only; return full swap_amount_in as the reserve deposit
- Fix all integration test fixture values to match fees-in-reserves math
- Remove dead-code vault_a/b_init_zero helpers from unit tests
2026-04-20 11:29:00 +02:00
Andrea Franz 1f8eea8442 chore(amm): new_definition allows only uninitialized pools 2026-04-14 13:10:09 +02:00
Ricardo Guilherme Schmidt 4a9a441ccd refactor(amm)!: derive pool active state from LP supply instead of explicit flag
Remove the `active: bool` field from `PoolDefinition` and replace it with an
implicit invariant: a pool is considered active when
`liquidity_pool_supply >= MINIMUM_LIQUIDITY`.

BREAKING CHANGE: `PoolDefinition` Borsh serialization format has changed.
Existing on-chain pool accounts encoded with the `active` field are
incompatible with this version.

Closes #25
2026-04-14 11:57:26 +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 9824cd8f90 feat(amm): add configurable fee tiers
- accept a supported fee tier in pool creation
- store fee tiers in AMM pool state and validate them
- update AMM tests and IDL for the new pool creation argument
2026-04-10 13:16:05 +02:00
r4bbit d0f398814c test(ata): add integration for private accounts create public ATAs 2026-04-09 19:13:03 +02:00
Andrea Franz 36f78a21aa fix(amm): use checked mul/add/sub to avoid overflows/underflows 2026-04-09 19:11:36 +02:00
Andrea Franz 4419e1e9a0 chore(amm)!: rename Swap instruction to SwapExactInput
Renames the Swap instruction and its guest handler to SwapExactInput to
distinguish it from the newly added SwapExactOutput, and to make the
intent of each variant explicit at the call site.

BREAKING CHANGE: the Swap instruction variant and swap() function are
renamed to SwapExactInput and swap_exact_input(). Callers must update
instruction construction and any IDL-generated bindings.
2026-04-09 19:11:36 +02:00
Andrea Franz 664fd849bd feat(amm): add swap exact output instruction
Adds SwapExactOutput to the AMM, allowing callers to specify the exact
desired output amount while the protocol computes the required input
(ceiling division to prevent rounding in the protocol's favour).

The swap-exact-output success tests now use a dedicated small-pool
fixture (reserve_a=1_000, reserve_b=500) rather than the shared
pool_definition_init, which had its reserves bumped to 5_000/2_500 in a
later commit to satisfy the MINIMUM_LIQUIDITY invariant introduced for
new_definition. Using a dedicated fixture keeps each test self-contained
and avoids hardcoded expected values silently breaking when shared
baselines change.
2026-04-09 19:11:36 +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
Ricardo Guilherme Schmidt fddd6e15bd feat(amm)!: introduce minimum liquidity lock on pool initialization
Permanently lock `MINIMUM_LIQUIDITY` (1_000) LP tokens in a dedicated
LP-lock holding PDA on pool creation, following the Uniswap v2 "dead
shares" pattern. The pool creator receives `initial_lp - MINIMUM_LIQUIDITY`
tokens instead of the full initial_lp amount.

Adds `compute_lp_lock_holding_pda` and `LP_LOCK_HOLDING_PDA_SEED` to
amm_core, updates new_definition to emit two sequential chained calls
(create LP definition + lock holding, then mint user share), and adjusts
remove liquidity to account for the permanently locked floor.

BREAKING CHANGE: NewDefinition instruction requires an additional LP-lock
holding account derived via `compute_lp_lock_holding_pda(amm_program_id, pool_id)`.
2026-04-09 14:33:49 +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 9ebd9fcc12 cleanup(ata): remove redundant test directive 2026-04-01 17:11:51 +02:00
r4bbit cb8426cbf1 skills: update spel-cli references to use spel 2026-04-01 12:17:52 +02:00
r4bbit 6287bd9df9 chore(ata): add IDL for ata program 2026-04-01 12:17:26 +02:00
r4bbit 45ed284825 chore: initial repository setup for programs v0.1.0 2026-03-30 23:58:43 +02:00
r4bbit d61d02adf6 Initial commit 2026-03-17 10:18:51 +01:00