Architecture
This section explains how the protocol works under the hood: the components, the tokens that flow between them, and the lifecycle of a mortgage from creation to resolution.
Protocol Overview
Buttonwood V1 is a decentralized convertible credit protocol for tokenized equities. It enables collateralized lending with a unique conversion mechanism that aligns incentives between borrowers and lenders.
The protocol is chain-agnostic and deploys to any EVM chain carrying supported collateral and a price feed. Support for Robinhood Chain and its tokenized equities is forthcoming.
Core Concept
Traditional DeFi lending forces borrowers to choose: either hold an appreciating asset or access liquidity. Buttonwood eliminates this trade-off with convertible credit — mortgages that can automatically convert if the collateral appreciates, letting borrowers capture upside while guaranteeing lender returns.
Three User Flows
1. Buy Now Pay Later (BNPL)
Users purchase equity tokens with a stablecoin down payment and finance the remainder through origination pools. A Mortgage NFT is minted representing the position, with the purchased equity tokens locked as collateral.
2. Coin Compounding
Users deposit equity tokens they already hold to borrow more on credit (~2x leverage). The position is automatically enrolled in the Conversion Queue, so if the equity appreciates the debt is forgiven in exchange for a portion of the collateral.
3. Lending
Lenders deposit stablecoins into pools that fund borrower mortgages. They earn yield through Consol tokens and can participate via direct pool deposits, automated rollover vaults, or fulfillment vaults.
Architecture Diagram
┌─────────────┐ ┌──────────┐ ┌──────────────────┐
│ Borrower │────►│ Router │────►│ Origination Pools│
│ (BNPL / │ │ │ │ (Lender Capital)│
│ Compound) │ └────┬─────┘ └────────┬─────────┘
└─────────────┘ │ │
▼ ▼
┌─────────────┐ ┌────────────────┐
│ LoanManager │ │ Consol Token │
│ (Mortgage │ │ (Yield-bearing │
│ NFTs) │ │ rebasing) │
└──────┬──────┘ └────────┬────────┘
│ │
▼ ▼
┌─────────────┐ ┌────────────────┐
│ SubConsol │ │ USDX │
│ (Escrow) │ │ (Multi-token │
│ │ │ stablecoin) │
└──────┬──────┘ └────────────────┘
│
▼
┌──────────────┐
│ Conversion │
│ Queue │
└──────────────┘
Price Oracles
The protocol uses Pyth Network pull-oracles for:
- Collateral pricing —
PythPriceOraclereads real-time collateral/USD prices, validates freshness (max 60 seconds old) and confidence thresholds - Interest rates —
PythInterestRateOraclereads 3-year and 5-year US Treasury rates, multiplies by 2, and adds 100 bps. An additional 100 bps is added for mortgages without a payment plan. Reverts if the price age exceeds 60 seconds or confidence exceeds 100 bps. AStaticInterestRateOracleserves as a fallback.
Order Fulfillment
When a borrower submits a BNPL or Compounding order:
- Borrower calls
generalManager.requestMortgageCreation(creationRequest)(via the Router) - A Mortgage NFT is minted with the requested MortgageId
- A
PurchaseOrderis enqueued in theOrderPoolwith the collateral amount and purchase price - An authorized fulfiller monitors the OrderPool and calls
orderPool.processOrders(indices, hintPrevIds) - For each order, the fulfiller swaps collateral for the USDX purchase amount
- The OriginationPool flash-deploys USDX and receives Consol as repayment (via
IOriginationPoolDeployCallback) - Collateral is deposited into SubConsol, and the mortgage is created in LoanManager
- If a ConversionQueue was specified, the mortgage is automatically enqueued
BNPL specifics: The borrower provides USDX for half the collateral purchase; the other half is borrowed from the OriginationPool. Pool fees are added on top.
Compounding specifics: The borrower provides half the collateral directly (not USDX). The other half is purchased with USDX borrowed from the OriginationPool. Pool fees are factored into the borrowed amount.
Orders have a 5-minute expiration window. Expired orders are deleted and NFTs burned, freeing the MortgageId for reuse. The fulfiller collects a gas fee for each processed order.
Key Design Decisions
- Simple interest — Loans use simple (not compound) interest:
totalDebt = principal * (1 + APR * years) - Fixed 36-period terms — All mortgages have a maximum of 36 monthly periods (30 days each)
- Multi-stablecoin support — Users can pay in USDT0 or USDC; the Router auto-wraps to USDX
- NFT-based positions — Each mortgage is an ERC-721 token, making positions transferable
- Rebasing yield — Consol is a rebasing ERC20 that automatically accrues yield for lenders
- Non-upgradeable core — OriginationPool, LoanManager, and token contracts are immutable to minimize smart contract risk. Only GeneralManager and OriginationPoolScheduler are UUPS-upgradeable.
- Permissionless queue processing — Anyone can call
processWithdrawalRequests()on the queues and collect gas fees as incentive - Flash-deploy origination — OriginationPools flash-lend USDX and receive Consol repayment in a single transaction via callbacks
Token System
Buttonwood's protocol uses several interconnected tokens, each serving a specific role in the lending and borrowing lifecycle.
Equity Tokens (Collateral)
Collateral is a tokenized equity — an on-chain token tracking shares in a listed company. Buttonwood extends convertible credit only against equity tokens whose underlying company exceeds $1 trillion of off-chain market capitalization. When a mortgage is created, the equity token is purchased (BNPL) or deposited (Compounding) and locked in the SubConsol escrow contract.
- Used as collateral for all mortgage positions
- Priced via the deployment's oracle price feed
- Locked in SubConsol until the mortgage is redeemed, converted, or foreclosed
Which equity tokens are accepted is configured per deployment and governed on-chain — the protocol itself is asset-agnostic and enforces no fixed list.
USDX (Protocol Stablecoin)
USDX is the protocol's internal unit of account — a multi-token vault that wraps multiple USD stablecoins into a single fungible token.
Supported Underlying Tokens
The accepted stablecoins are configured per deployment and depend on what circulates on the host chain. They have included:
| Token | Description |
|---|---|
| USDC | Circle's USD Coin |
| USDT0 | Omnichain USDT |
How It Works
USDX extends the MultiTokenVault contract. Users deposit any supported stablecoin and receive USDX at a 1:1 ratio. The Router handles wrapping/unwrapping automatically so users can interact with the protocol using whichever stablecoin they prefer.
Key properties:
- 1:1 backing by underlying stablecoins
- Wrap and unwrap at any time
- All protocol-internal accounting is denominated in USDX
Consol (Yield Token)
Consol is a rebasing ERC20 token that represents lender yield. It extends MultiTokenVault and RebasingERC20.
How Yield Accrues
Consol is backed by:
- USDX deposited by lenders and earned from borrower payments
- Forfeited assets from foreclosed positions (via
ForfeitedAssetsPool)
As the backing pool grows from borrower interest payments and forfeited assets, the rebasing mechanism automatically increases each holder's balance proportionally. Lenders earn yield simply by holding Consol tokens.
Earning Consol
Lenders earn Consol through:
- Origination Pool deposits — stablecoins are converted to Consol upon deposit
- Rollover Vault staking — the vault accumulates Consol from rolled-over pool positions
- Fulfillment Vault staking — earns Consol from order fulfillment fees
SubConsol (Escrow)
SubConsol is the escrow contract that holds collateral for active mortgages. It is not a token users interact with directly — it's an internal protocol component.
Responsibilities
- Holds locked equity-token collateral for each Mortgage NFT
- Releases collateral upon redemption (full payoff) or conversion
- Transfers collateral to the ForfeitedAssetsPool upon foreclosure
- Tracks per-mortgage collateral balances
Token Flow Diagram
User deposits stablecoin
│
▼
┌──────────────┐
│ Supported │── wrap ──► USDX ──── mint ────► Consol
│ stablecoins │ │ │
└──────────────┘ │ │
▼ ▼
Borrower debt Lender yield
denominated (rebasing)
in USDX
│
▼
Equity tokens purchased
on the chain's venue
│
▼
Locked in SubConsol (escrow)
Share Tokens
In addition to the core tokens, the protocol issues share tokens for vault participation:
| Token | Vault | What it represents |
|---|---|---|
| Pool Tokens | Origination Pool | Share of a specific lending pool epoch |
| RLV | Rollover Vault | Share of the automated rollover strategy |
| FLV | Fulfillment Vault | Share of the order fulfillment liquidity |
These are standard ERC20 tokens that can be transferred. Redeeming them burns the share tokens and returns the proportional underlying assets.
Mortgage Lifecycle
Every borrowing position in Buttonwood is represented by a Mortgage NFT (ERC-721). This document describes the full lifecycle of a mortgage from creation to resolution.
1. Creation
BNPL Path
- User submits a purchase order with a stablecoin down payment
- The Router wraps stablecoins to USDX and submits the order to the
MortgageQueue - A fulfillment service purchases the equity token on the chain's trading venue
- On-chain settlement mints the Mortgage NFT via
LoanManager - Purchased equity tokens are locked in
SubConsol
Compounding Path
- User deposits equity tokens and requests more on credit
- The protocol executes a flash-loan-equivalent: deposit is used as down payment, borrowed amount finances more equity tokens
- All equity tokens (deposit + borrowed) are locked in
SubConsol - Position is automatically enrolled in the
ConversionQueue
Order Fulfillment Window
- Orders are queued on-chain with a 5-minute expiration
- Fulfillment takes approximately 60 seconds
- If not filled before expiration, all funds are refunded
- Users cannot cancel during the fill window
2. Active Period
Once created, the mortgage enters its active period:
- Term: Up to 36 monthly periods (30 days each)
- Interest: Simple interest —
totalDebt = principal * (1 + APR * years) - Payment schedule: Monthly payments of
totalDebt / 36in USDX (if payment plan is enabled)
Making Payments
Payments are processed through the LoanManager:
- User pays in any supported stablecoin via the Router
- Router wraps to USDX and forwards the payment
LoanManagerrecords the payment against the mortgage- Payment flows to lenders through the Consol system
Late Payments
- Grace period: 3 days after the due date
- Penalty: A percentage of the monthly payment amount accrues as a penalty
- Penalty payment: Must be paid in addition to the regular monthly payment
3. Resolution
A mortgage can resolve in one of three ways:
Redemption (Full Payoff)
All payments made ──► Mortgage marked "Redeemable"
│
▼
User calls redeem()
│
▼
SubConsol releases collateral
Mortgage NFT burned
User receives collateral
- All 36 monthly payments are completed (or bullet payment at maturity)
- Mortgage status changes to Redeemable
- User calls
redeem()on the/managepage - SubConsol releases all locked equity tokens back to the user
- The Mortgage NFT is burned
Conversion (Auto-conversion)
Token price hits trigger ─► ConversionQueue processes position
│
▼
Debt portion of collateral
sent to lenders/protocol
│
▼
Remaining collateral
returned to borrower
│
▼
Mortgage resolved
- The equity token's price reaches the Conversion Trigger Price
- The
ConversionQueueautomatically processes the position - A portion of collateral sufficient to cover remaining debt is taken
- The remaining collateral is returned to the borrower
- Any outstanding payment obligations are adjusted
Foreclosure (Default)
Missed 2+ payments ──► Position eligible for foreclosure
│
▼
Keeper/protocol calls foreclose()
│
▼
All collateral seized
Sent to ForfeitedAssetsPool
Mortgage NFT marked "Foreclosed"
- Borrower misses more than 2 payments
- Position becomes eligible for foreclosure
- A keeper or the protocol calls the foreclosure function
- All locked equity tokens are seized from SubConsol
- Collateral is sent to the
ForfeitedAssetsPool - The Mortgage NFT is marked as foreclosed (not burned — it remains as a record)
Mortgage States
| State | Description |
|---|---|
| Pending | Order submitted, awaiting fulfillment |
| Active | Mortgage is live, payments being made |
| At Risk | Payments missed, approaching foreclosure threshold |
| Redeemable | Fully paid off, ready for collateral redemption |
| Redeemed | Collateral returned, NFT burned |
| Foreclosed | Collateral seized due to payment default |
Conversion Mechanism
The conversion mechanism is the core innovation of Buttonwood's convertible credit system. It allows mortgages to automatically resolve when collateral appreciates — borrowers capture upside while lenders receive guaranteed returns.
How Conversion Works
Trigger Price Calculation
Each convertible mortgage has a Conversion Trigger Price — the collateral price at which auto-conversion activates:
triggerPrice = (1 + conversionPremium%) * amountBorrowed * 2 / collateralAmount
The conversion premium is a protocol-configured percentage that ensures lenders receive a return above the principal.
Example
| Parameter | Value |
|---|---|
| Equity tokens deposited | 100 tokens |
| Token price at deposit | $25 |
| Amount borrowed | $1,250 (50 tokens equivalent) |
| Total collateral locked | ~200 tokens |
| Conversion premium | 50% |
| Trigger price | $37.50 |
If the equity token reaches $37.50:
- The debt portion of collateral (valued at the remaining debt) is transferred to the protocol/lenders
- The borrower keeps the remaining collateral (~64 tokens after accounting for interest)
- At $37.50 per token, the borrower's ~64 tokens are worth ~$2,400 — nearly the same as their original $2,500 but with zero remaining debt
ConversionQueue Contract
The ConversionQueue is a double-queue — it inherits from both LenderQueue (FIFO withdrawal queue) and MortgageQueue (price-sorted linked list). It manages two sides:
- Lender side: Lenders deposit Consol and wait to receive collateral with a premium
- Borrower side: Borrowers submit mortgage positions and wait to be converted when prices trigger
Enrollment
- Coin Compounding positions are automatically enrolled — a
conversionQueueaddress is required when requesting a compounding mortgage - BNPL positions can optionally enable conversion via the UI toggle, or the borrower can later call
generalManager.enqueueMortgage(tokenId, conversionQueue, hintPrevId) - The borrower must be the owner of the mortgage
- A valid
hintPrevIdmust be provided to reduce gas costs (the hint should be as close as possible to the proper sorted index) - Both
GeneralManagerandConversionQueuemust not be paused
Processing
When the oracle reports a collateral price at or above a position's trigger price:
- A permissionless actor calls
conversionQueue.processWithdrawalRequests(numberOfRequests) - The ConversionQueue matches lender withdrawal requests (FIFO) against eligible mortgage positions
- For each matched conversion:
- Portions of qualified mortgages are liquidated at market prices
- Lump-sum interest payments are rewarded to the withdrawing lenders
- SubConsol burns collateral tokens and releases underlying collateral
- Remaining collateral is returned to the borrower
- LoanManager updates the mortgage status via the Conversion Role
- The processor collects gas fees for each processed request
Queue Ordering
The borrower side uses a sorted linked-list (via MortgageQueue) maintaining positions ordered by trigger price, lowest to highest. When the collateral reaches a certain price, all positions with trigger prices at or below that level are eligible for conversion. The processor works through them sequentially, matching against the FIFO lender queue.
Conversion Premium
The conversion premium is a key parameter that balances borrower and lender incentives:
- Higher premium = higher trigger price = less likely to convert, but more profit for lenders if it does
- Lower premium = lower trigger price = more likely to convert, but smaller lender premium
The premium is set at the protocol level and applies to all new mortgages.
Collateral After Conversion
The amount of collateral a borrower keeps after conversion depends on:
- Total collateral locked (deposit + borrowed amount)
- Interest accrued over the loan term
- Remaining debt at the time of conversion
collateralKept = totalCollateral - (remainingDebt / triggerPrice)
Since conversion can happen at any point during the loan term, earlier conversions (before much interest accrues) result in more collateral returned to the borrower.
Integration with Other Components
PythPriceOracle
│
│ price update
▼
QueueProcessor (off-chain keeper)
│
│ identifies eligible positions
▼
ConversionQueue
│
├──► SubConsol ──► release collateral
│
├──► UsdxQueue ──► lender payments
│
└──► LoanManager ──► update mortgage status
The conversion mechanism relies on:
- PythPriceOracle for accurate, low-latency price feeds
- QueueProcessor (off-chain keeper) for monitoring and triggering conversions
- SubConsol for collateral custody and release
- LoanManager for mortgage state management
- UsdxQueue for routing converted collateral to lenders