64 Commits

Author SHA1 Message Date
r4bbit
3622016e6c refactor: move programs into programs and UIs into apps
This refactors the repository structure as it has grown over time.
2026-05-26 14:05:52 +02:00
Andrea Franz
cdb53a4d0c feat(stablecoin): implement repay_debt (#93) 2026-05-26 10:31:52 +02:00
Andrea Franz
1ae2b325ff test(stablecoin): move chained-transfer coverage to integration tests 2026-05-26 10:31:52 +02:00
Andrea Franz
7da110a616 fix(stablecoin): leave position_post.program_owner default so the runtime sets it through Claim::Pda 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
Andrea Franz
eb7f44a98a feat(stablecoin): implement withdraw_collateral
closes #92
2026-05-26 10:31:52 +02:00
r4bbit
f4f61be322 chore(Makefile): add idl command to Makefile 2026-05-25 20:57:59 +02:00
Ricardo Guilherme Schmidt
291149b114 chore(twap_oracle): scaffold twap_oracle program
Closes #114
2026-05-25 20:04:33 +02:00
copilot-swe-agent[bot]
9efef64b54 Fix CI regex to use PCRE2 mode for non-greedy quantifier support
Agent-Logs-Url: https://github.com/logos-blockchain/lez-programs/sessions/65c1e83e-b757-457f-bd78-2073df6b2c1a

Co-authored-by: 0x-r4bbit <445106+0x-r4bbit@users.noreply.github.com>
2026-05-22 09:46:53 +02:00
r4bbit
cfa4bb1e36 chore: include stablecoin program in clippy task 2026-05-22 09:46:53 +02:00
r4bbit
20a947137c refactor: rename rust-toolchain file
Fixes #13
2026-05-22 09:46:53 +02:00
r4bbit
6fd87766c2 chore: adjust linting rules and introduce Makefile
This relaxes some of the rules introduced in the previous commit.
To simplify testing, building and formatting locally and on CI, we also
introduce a dedicated makefile
2026-05-22 09:46:53 +02:00
Ricardo Guilherme Schmidt
49d7f91ee5 chore(lint): add staged lint baseline 2026-05-22 09:46:53 +02:00
r4bbit
035f593f5e chore: update spel to v0.3.0 2026-05-19 08:40:35 +02:00
Ricardo Guilherme Schmidt
5229855d57 fix(ata)!: namespace accounts by token program
ATA accounts are now namespaced by token program, so callers must
explicitly pass the token_program_id when invoking ATA::Transfer.

BREAKING CHANGE: `Instruction::Transfer`, `Instruction::Burn`, `Instruction::Create` now requires a
`token_program_id` field. Any existing call site that omits it will
fail to compile.

Closes #83
2026-05-18 12:53:07 +02:00
r4bbit
29b4c01739 fix(integration_tests) remove no longer needed program ID 2026-05-18 12:22:06 +02:00
Ricardo Guilherme Schmidt
f8cbcc6956 fix(ata): lock down ATA::Transfer recipient contract
Enforce at the ATA layer that the recipient token holding is already
initialized, owned by the same token program as the sender ATA, decodes
to a valid `TokenHolding`, and points at the same token definition as
the sender. Align the core instruction doc and guest wrapper doc with
that contract, and cover the boundary with unit tests (default,
foreign-owned, malformed, mismatched-definition recipients, plus the
missing-owner-auth and happy paths) and end-to-end integration tests
(default and mismatched-definition recipients).

Without this, the downstream `token::Transfer` default-recipient
`Claim::Authorized` path was reachable through ATA, so integrators had
to reverse-engineer recipient semantics from token/runtime internals.
2026-05-13 13:32:09 +02:00
Ricardo Guilherme Schmidt
0b078b2dde fix(stablecoin): address open position review feedback 2026-05-13 12:23:20 +02:00
Ricardo Guilherme Schmidt
d6082d0c81 docs(stablecoin): improve documentation for OpenPosition instruction 2026-05-13 12:23:20 +02:00
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