Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions docs/adr/0001-defindex-strategy-pattern.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# ADR 0001 — DeFindex Strategy Pattern

Date: 2026-05-30

## Status

Accepted

## Context

Turbolong needs a composable on-chain execution layer for its leveraged-yield
strategy. Two approaches were considered:

1. **Monolithic contract** — a single Soroban contract that owns collateral,
executes loops, and manages withdrawals.
2. **DeFindex strategy pattern** — a thin vault contract (DeFindex) that
delegates execution to a pluggable `Strategy` contract implementing a
standard interface (`deposit`, `withdraw`, `harvest`, `balance`).

The DeFindex pattern is already deployed on Stellar mainnet and provides
audited vault accounting, share-token issuance, and emergency-pause
infrastructure that would otherwise need to be built from scratch.

## Decision

Adopt the DeFindex strategy pattern. Turbolong implements the `Strategy`
interface and registers with a DeFindex vault. The vault handles:

- Share-token minting/burning
- Pro-rata withdrawal accounting
- Multi-strategy fan-out (future)

The strategy contract handles:

- Blend Protocol supply/borrow loops
- Rebalance logic (HF maintenance)
- BLND emission harvesting

## Consequences

**Positive**
- Reuses audited vault infrastructure; reduces audit surface.
- Share tokens are standard SEP-41 tokens, enabling composability.
- Strategy can be upgraded independently of the vault.

**Negative**
- Adds a cross-contract call hop on every deposit/withdraw, increasing
Soroban instruction cost by ~10–15%.
- Turbolong is coupled to DeFindex's upgrade cadence for vault-level changes.
41 changes: 41 additions & 0 deletions docs/adr/0002-20-loop-cap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# ADR 0002 — 20-Loop Cap on Leverage Loops

Date: 2026-05-30

## Status

Accepted

## Context

The USDC leverage strategy on Blend Protocol achieves leverage by repeatedly
supplying and borrowing the same asset. With a collateral factor `c`, the
theoretical maximum leverage is `1 / (1 − c)`. For `c = 0.95` that is 20×.

Each loop is a separate Soroban transaction invocation. Soroban imposes a
per-transaction instruction budget. Empirical testing shows that beyond 20
loop iterations the transaction exceeds the Soroban instruction limit and
fails on-chain.

Additionally, at 20× leverage the health factor approaches 1.0000, leaving
essentially zero headroom before liquidation. The practical safe maximum is
13–15 loops (HF ≥ 1.05).

## Decision

Hard-cap the number of leverage loops at **20** in both the on-chain strategy
contract and the off-chain simulation scripts. The UI further restricts the
slider to the leverage that keeps HF ≥ 1.01 (normal mode) or HF ≥ 1.00001
(expert mode), which in practice limits loops to ≤ 15 for `c = 0.95`.

## Consequences

**Positive**
- Prevents on-chain transaction failures from instruction-budget exhaustion.
- Provides a clear, documented upper bound for auditors and integrators.

**Negative**
- Users cannot reach the theoretical 20× maximum in practice; the effective
ceiling is ~13–15× at safe HF levels.
- If Soroban raises instruction limits in a future protocol upgrade, the cap
may be revisited.
41 changes: 41 additions & 0 deletions docs/adr/0003-single-asset-vault.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# ADR 0003 — Single-Asset Vault

Date: 2026-05-30

## Status

Accepted

## Context

DeFindex supports multi-asset vaults where depositors contribute a basket of
tokens. Turbolong's leverage strategy, however, loops a single asset (e.g.
USDC) as both collateral and borrowed asset on Blend Protocol.

Two vault configurations were evaluated:

1. **Multi-asset vault** — accepts any token; the strategy rebalances into the
target asset on deposit.
2. **Single-asset vault** — accepts only the strategy's underlying asset
(e.g. USDC); no rebalancing swap is needed.

## Decision

Deploy one **single-asset vault per underlying asset**. Each vault accepts
exactly one token (e.g. USDC) and runs the corresponding Blend loop strategy.

Rationale:
- Eliminates swap slippage and oracle dependency on deposit/withdraw.
- Simplifies accounting: 1 share = `n` underlying tokens, no basket math.
- Reduces attack surface: no DEX integration in the critical deposit path.
- Aligns with the USDC/USDC loop design where price risk is near-zero.

## Consequences

**Positive**
- Simpler share-price calculation and easier auditability.
- No swap failure modes on deposit.

**Negative**
- Users must hold the exact underlying asset before depositing.
- Supporting a new asset requires deploying a new vault + strategy pair.
42 changes: 42 additions & 0 deletions docs/adr/0004-no-flash-loans-soroban.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# ADR 0004 — No Flash Loans on Soroban

Date: 2026-05-30

## Status

Accepted

## Context

EVM-based leverage strategies commonly use flash loans to open or close a
leveraged position atomically in a single transaction, avoiding the need for
iterative supply/borrow loops. This reduces gas cost and eliminates
intermediate HF exposure.

Soroban (Stellar's smart-contract platform) does not support flash loans:

- Soroban's execution model does not allow a contract to borrow funds and
repay them within the same transaction without an external liquidity source.
- Blend Protocol v2 does not expose a flash-loan interface.
- Soroban's re-entrancy restrictions and lack of callback-based token
transfers make the standard EVM flash-loan pattern unimplementable.

## Decision

Do **not** use flash loans. Implement leverage via iterative supply/borrow
loops, capped at 20 iterations (see ADR 0002). Each loop step is a
sequential Soroban invocation within a single transaction envelope.

## Consequences

**Positive**
- No dependency on external flash-loan liquidity providers.
- Strategy is self-contained within Blend Protocol.

**Negative**
- Opening/closing large positions requires more Soroban instructions than a
flash-loan approach would.
- Position is not opened atomically from the user's perspective; intermediate
states are visible on-chain between loop steps.
- If Blend Protocol adds flash loans in a future version, this decision should
be revisited.
49 changes: 49 additions & 0 deletions docs/adr/0005-wallets-kit-over-freighter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# ADR 0005 — Stellar Wallets Kit over Freighter-Only Integration

Date: 2026-05-30

## Status

Accepted

## Context

The Turbolong frontend needs to connect to Stellar wallets for transaction
signing. Two approaches were evaluated:

1. **Freighter-only** — integrate directly with the Freighter browser
extension API (`@stellar/freighter-api`).
2. **Stellar Wallets Kit (SWK)** — use `@creit-tech/stellar-wallets-kit`,
which provides a unified modal and adapter layer for multiple wallets
(Freighter, xBull, Albedo, Lobstr, Hana, and others).

At the time of this decision, Freighter holds the majority of Stellar browser
wallet market share, but xBull and Albedo have meaningful user bases,
particularly among DeFi power users.

## Decision

Use **Stellar Wallets Kit** (`@creit-tech/stellar-wallets-kit`) as the sole
wallet integration layer. The following modules are registered:

- `FreighterModule`
- `xBullModule`
- `AlbedoModule`
- `LobstrModule`
- `HanaModule`

SWK's `authModal` is used for connection; `signTransaction` for signing.

## Consequences

**Positive**
- Single integration point supports five wallets with no per-wallet code.
- SWK's modal provides a consistent UX regardless of which wallet the user
has installed.
- Adding new wallets requires only registering an additional module.

**Negative**
- Adds a dependency on `@creit-tech/stellar-wallets-kit`; if the library is
abandoned, all wallet integrations are affected simultaneously.
- SWK abstracts wallet-specific features (e.g. hardware wallet flows in
Ledger-enabled wallets) that may need custom handling in the future.
38 changes: 38 additions & 0 deletions docs/adr/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Architecture Decision Records

This directory contains Architecture Decision Records (ADRs) for Turbolong,
following the [Michael Nygard template](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions).

## Index

| ADR | Title | Status |
|-----|-------|--------|
| [0001](0001-defindex-strategy-pattern.md) | DeFindex Strategy Pattern | Accepted |
| [0002](0002-20-loop-cap.md) | 20-Loop Cap on Leverage Loops | Accepted |
| [0003](0003-single-asset-vault.md) | Single-Asset Vault | Accepted |
| [0004](0004-no-flash-loans-soroban.md) | No Flash Loans on Soroban | Accepted |
| [0005](0005-wallets-kit-over-freighter.md) | Stellar Wallets Kit over Freighter-Only | Accepted |

## Template

```markdown
# ADR NNNN — Title

Date: YYYY-MM-DD

## Status

Proposed | Accepted | Deprecated | Superseded by [ADR NNNN](NNNN-title.md)

## Context

What is the issue that we're seeing that is motivating this decision or change?

## Decision

What is the change that we're proposing and/or doing?

## Consequences

What becomes easier or more difficult to do because of this change?
```
24 changes: 24 additions & 0 deletions frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,14 @@ <h2 id="disclaimer-title">Important Disclaimer</h2>
<button class="nav-btn" id="proto-swap">Swap</button>
</div>
<div class="top-nav-right" id="wallet-area">
<!-- HF header badge — visible when user has an open position -->
<span id="hf-header-badge" class="hf-header-badge hidden" title="Health Factor" aria-label="Health Factor"></span>

<button id="settings-btn" class="nav-btn" aria-label="Settings">&#9881;</button>
<div id="settings-dropdown" class="settings-dropdown hidden">
<button id="expert-toggle" class="settings-dropdown-item">Expert Mode <span class="settings-badge">Off</span></button>
<button id="theme-toggle" class="settings-dropdown-item">Theme <span class="settings-badge">&#9790;</span></button>
<button id="replay-tour-btn" class="settings-dropdown-item">Replay Tour</button>
</div>
<button id="network-toggle" class="btn btn-ghost btn-sm network-toggle" data-tip="Switch between Mainnet and Testnet">Mainnet</button>
<button id="connect-btn" class="btn btn-primary btn-connect">Connect Wallet</button>
Expand Down Expand Up @@ -802,6 +806,26 @@ <h3>APY Alerts</h3>
<!-- Tooltip popover -->
<div id="tooltip-popover" class="tooltip-popover" role="tooltip"></div>

<!-- Guided tour overlay -->
<div id="tour-overlay" class="tour-overlay hidden" role="dialog" aria-modal="true" aria-label="Guided tour">
<div id="tour-backdrop" class="tour-backdrop"></div>
<div id="tour-card" class="tour-card">
<div class="tour-header">
<span id="tour-step-label" class="tour-step-label"></span>
<button id="tour-skip-btn" class="tour-skip-btn" aria-label="Skip tour">Skip tour</button>
</div>
<h3 id="tour-title" class="tour-title"></h3>
<p id="tour-body" class="tour-body"></p>
<div class="tour-footer">
<div class="tour-dots" id="tour-dots"></div>
<div class="tour-actions">
<button id="tour-prev-btn" class="btn btn-ghost btn-sm">Back</button>
<button id="tour-next-btn" class="btn btn-primary btn-sm">Next</button>
</div>
</div>
</div>
</div>

<script type="module" src="/src/main.ts"></script>
</body>
</html>
Loading