Contract Reference

Complete API reference for every ETH Strategy smart contract — function signatures, parameters, return values, access control, and revert conditions.

This is the canonical API reference for ETH Strategy smart contracts. Every public and external function is documented with a consistent template:

SignatureParametersReturnsAccess ControlRevertsWhy It Exists

For integration patterns, production warnings, and working code examples, see the Integration Guide. For deployed addresses, see Contracts.


esETH

Non-rebasing ERC-20 wrapper around multiple liquid staking tokens (wstETH, rETH, cbETH, weETH, aWETH), pegged 1:1 with ETH. The denomination layer for the entire treasury.

circle-info

Status: Deploying soon. Address will be published on the Contracts page before permissionless launch.

mint(address lst, uint256 amount, address recipient) → uint256 esEthAmount

Deposit a supported LST and receive esETH at a 1:1 ratio with the ETH value of the deposit.

Parameter
Type
Description

lst

address

Address of the LST to deposit (wstETH, rETH, cbETH, weETH, or aWETH)

amount

uint256

Amount of the LST to deposit

recipient

address

Address to receive the minted esETH

Returns
Type
Description

esEthAmount

uint256

Amount of esETH minted

Access

Caller

Any (permissionless)

Requires

Caller must have approved esETH contract to spend amount of lst

Reverts
When

lst is not a supported token

amount is zero

ERC-20 revert

Caller has insufficient lst balance or allowance

Why: Primary entry point for adding collateral to the protocol. Wrapping multiple LSTs into a single non-rebasing token pegged 1:1 with ETH simplifies treasury accounting and enables a unified denomination layer across all protocol operations.


mint(address recipient) → uint256 esEthAmount

Deposit raw ETH and receive esETH. The sent ETH is staked via the most favorable LST route.

Parameter
Type
Description

recipient

address

Address to receive the minted esETH

Returns
Type
Description

esEthAmount

uint256

Amount of esETH minted

Access

Caller

Any (permissionless)

Requires

msg.value > 0

Reverts
When

msg.value is zero

Why: Convenience overload so users don't need to manually acquire an LST before minting. The contract routes ETH to the most favorable LST automatically.


redeem(address lst, uint256 esEthAmount, address recipient) → uint256 lstAmount

Redeem esETH for a supported LST held by the contract.

Parameter
Type
Description

lst

address

Address of the desired LST to receive

esEthAmount

uint256

Amount of esETH to burn

recipient

address

Address to receive the LST

Returns
Type
Description

lstAmount

uint256

Amount of the LST returned

Access

Caller

Any (permissionless)

Requires

Caller must hold esEthAmount of esETH

Reverts
When

lst is not a supported token

Contract does not hold enough of the requested LST

Caller has insufficient esETH balance

Why: Allows exit from the esETH wrapper back to individual LSTs. Exchange rate is the LST's native rate, not a market price. Redemption depends on contract holdings — if the treasury has rebalanced, a specific LST may have insufficient balance.


ethPerEsEth() → uint256

Returns the ETH value of 1 esETH (in wei, 18 decimals). Always returns 1e18 (1:1 peg).

Access

Caller

Any (view)

Why: The canonical pricing function for esETH. This always returns 1e18 because esETH is pegged 1:1 with ETH — yield from underlying LSTs is harvested separately and does not accrete to the exchange rate. Use this for collateral valuation, lending markets, and portfolio display — never use AMM spot price for fair value.


previewMint(address lst, uint256 lstAmount) → uint256 esEthAmount

Preview: returns the esETH amount that would be minted for a given LST deposit.

Parameter
Type
Description

lst

address

Address of the LST

lstAmount

uint256

Amount of the LST

Returns
Type
Description

esEthAmount

uint256

Equivalent esETH that would be minted

Access

Caller

Any (view)

Why: Allows UIs and smart contracts to display expected output before executing a mint. Essential for slippage protection and user-facing previews.


previewRedeem(address lst, uint256 esEthAmount) → uint256 lstAmount

Preview: returns the LST amount that would be returned for a given esETH redemption.

Parameter
Type
Description

lst

address

Address of the LST

esEthAmount

uint256

Amount of esETH to redeem

Returns
Type
Description

lstAmount

uint256

Equivalent LST that would be returned

Access

Caller

Any (view)

Why: Pre-flight check for redemptions. Critical because redemption depends on contract holdings — previewRedeem() reveals whether the requested LST has sufficient balance before executing.


Standard ERC-20 + ERC-2612

esETH implements the full ERC-20 interface with ERC-2612arrow-up-right permit support.

Function
Description

balanceOf(address) → uint256

Token balance (non-rebasing — never changes except on transfer/mint/burn)

transfer(address to, uint256 amount) → bool

Standard transfer

approve(address spender, uint256 amount) → bool

Standard approval

transferFrom(address from, address to, uint256 amount) → bool

Standard delegated transfer

permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)

Gasless approval via off-chain signature

totalSupply() → uint256

Total esETH in circulation

allowance(address owner, address spender) → uint256

Current spending allowance

Property
Value

Name

esETH

Symbol

esETH

Decimals

18

Rebasing

No

Ownership

Ownable2Step (protocol multisig)


STRAT

ERC-20 equity token with ERC-2612 permit. Does not rebase. Only minted through convertible note conversion.

Property
Value

Name

ETH Strategy

Symbol

STRAT

Decimals

18

Standard

ERC-20 with ERC-2612 permit

Compiler

Solidity v0.8.20, 999,999 optimization runs, Paris EVM

Inherits

MintableBurnableToken → ERC20Permit → Ownable2Step

Ownership

Ownable2Step (protocol multisig)

mint(address to, uint256 amount)

Mint new STRAT tokens.

Parameter
Type
Description

to

address

Recipient of the minted tokens

amount

uint256

Amount to mint

Access

Caller

Authorized minter contracts only (ConvertibleNote)

Reverts
When

Caller is not an authorized minter

to is the zero address

Why: STRAT has no inflation schedule and no emission mechanism. New STRAT only enters circulation when a note holder exercises conversion rights. This restricted minting is the fundamental supply guarantee — STRAT supply only grows when someone converts debt to equity.


burn(uint256 amount)

Burn STRAT tokens from the caller's balance.

Parameter
Type
Description

amount

uint256

Amount to burn

Access

Caller

Any holder (burns from msg.sender)

Reverts
When

Caller has insufficient balance

Why: Public burn function — any holder can destroy their own STRAT. Also used by authorized contracts for protocol operations.


burnFrom(address from, uint256 amount)

Burn STRAT tokens from another address using an allowance.

Parameter
Type
Description

from

address

Address to burn from

amount

uint256

Amount to burn

Access

Caller

Any address with sufficient allowance from from

Reverts
When

Caller has insufficient allowance

from has insufficient balance

Why: Allowance-based burn — used by TreasuryLend to burn STRAT collateral at loan origination. On successful repayment, equivalent STRAT is re-minted. This burn-at-origination model eliminates the need for collateral escrow.


manageMinter(address minter, bool authorized)

Add or remove an authorized minter address.

Parameter
Type
Description

minter

address

Address to authorize or revoke

authorized

bool

true to authorize, false to revoke

Access

Caller

Owner only (protocol multisig via Ownable2Step)

Why: Governance control over which contracts can create new STRAT. In practice, only the ConvertibleNote contract is an authorized minter. This is checked before every mint operation.


Standard ERC-20 + ERC-2612

Function
Description

balanceOf(address) → uint256

Token balance

transfer(address to, uint256 amount) → bool

Standard transfer

approve(address spender, uint256 amount) → bool

Standard approval

transferFrom(address from, address to, uint256 amount) → bool

Standard delegated transfer

permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)

Gasless approval via off-chain signature

totalSupply() → uint256

Total STRAT supply — increases only through note conversion

allowance(address owner, address spender) → uint256

Current spending allowance

nonces(address owner) → uint256

Permit nonce tracking


CDT (Convertible Debt Token)

Fungible ERC-20 representing protocol debt. Each CDT = ~$1 of debt. totalSupply() = total protocol debt.

circle-info

Status: Deploying soon. Address will be published on the Contracts page before permissionless launch.

Property
Value

Name

ETH Strategy Debt

Symbol

CDT

Decimals

18

Standard

ERC-20 with ERC-2612 permit

Ownership

Ownable2Step (protocol multisig)

Minting

Restricted to authorized minter contracts (ConvertibleNote, TreasuryLend)

mint(address to, uint256 amount)

Mint new CDT tokens.

Parameter
Type
Description

to

address

Recipient of the minted CDT

amount

uint256

Amount to mint (1 CDT per ~$1 of notional)

Access

Caller

Authorized minter contracts only (ConvertibleNote, TreasuryLend)

Reverts
When

Caller is not an authorized minter

Why: CDT is minted during convertible note bonding (new debt) and when treasury lending borrowers repay (restoring previously burned CDT). Restricted minting ensures protocol debt cannot be inflated arbitrarily.


burn(address from, uint256 amount)

Burn CDT tokens.

Parameter
Type
Description

from

address

Address to burn from

amount

uint256

Amount to burn

Access

Caller

Authorized contracts (ConvertibleNote burns on conversion/redemption, TreasuryLend burns collateral)

Reverts
When

Caller is not authorized

from has insufficient balance

Why: CDT is destroyed through three paths: conversion (before expiry), redemption (after expiry), and treasury lending collateral deposit. Each burn reduces total protocol debt.


manageMinter(address minter, bool authorized)

Add or remove an authorized minter address.

Parameter
Type
Description

minter

address

Address to authorize or revoke

authorized

bool

true to authorize, false to revoke

Access

Caller

Owner only (protocol multisig via Ownable2Step)

Why: Governance control over which contracts can create or destroy CDT. In practice, ConvertibleNote and TreasuryLend are the only authorized minters.


Standard ERC-20 + ERC-2612

Function
Description

balanceOf(address) → uint256

CDT balance (does not accrue interest)

transfer(address to, uint256 amount) → bool

Standard transfer

approve(address spender, uint256 amount) → bool

Standard approval

transferFrom(address from, address to, uint256 amount) → bool

Standard delegated transfer

permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)

Gasless approval — enables single-tx conversion and redemption

totalSupply() → uint256

Total protocol debt in USD terms

allowance(address owner, address spender) → uint256

Current spending allowance


EthStrategyConvertibleNote

Bonding, note issuance, conversion, and redemption. Issues CDT + NFT pairs on bonding; settles them on conversion or redemption.

circle-info

Status: Deploying soon. Address will be published on the Contracts page before permissionless launch.

bond(address recipient, uint256 minConversionAmountStrat, uint256 minConversionAmountEth, uint256 deadline) → uint256 tokenId

Purchase a USD-denominated convertible note by sending ETH. Receives CDT + NFT option.

Parameter
Type
Description

recipient

address

Address to receive CDT and NFT

minConversionAmountStrat

uint256

Minimum STRAT entitlement (slippage protection)

minConversionAmountEth

uint256

Minimum esETH entitlement (slippage protection)

deadline

uint256

Transaction deadline (block.timestamp must be ≤ deadline)

Returns
Type
Description

tokenId

uint256

The minted NFT token ID

Access

Caller

Any (permissionless, payable)

Requires

msg.value > 0

Reverts
When

NoEthSent

msg.value is zero

ZeroAddress

recipient is address(0)

TransactionStale

block.timestamp > deadline

InsufficientOutput

Conversion entitlements fall below specified minimums

InvalidTimelockOrExpiry

Computed timelock/expiry values are invalid

Why: The protocol's primary growth mechanism. Notes are USD-denominated — the buyer sends ETH, which is priced in USD via an ETH/USD oracle and acquired for the treasury. The buyer receives composable debt (CDT, 1 per ~$1 USD notional) and conversion rights (NFT) — a structure borrowed from TradFi convertible bonds, decomposed into DeFi primitives. Zero-interest debt is possible because the conversion option itself is the buyer's compensation.


convertToStrat(uint256 tokenId, uint256 cdtAmount)

Convert note to STRAT before expiry. Burns CDT, mints STRAT.

Parameter
Type
Description

tokenId

uint256

NFT token ID

cdtAmount

uint256

Amount of CDT to burn (partial exercise supported)

Access

Caller

ownerOf(tokenId) only — NFT approvals are NOT accepted

Requires

CDT approved or permitted to the contract

Reverts
When

TimelockActive

Timelock hasn't passed (~6.9 days after bonding)

OptionExpired

Past expiry (~4.2 years) — use redeem() instead

NotOwnerOrApproved

Caller is not the NFT owner

InvalidExerciseAmount

cdtAmount is 0 or exceeds remaining amountOwedCdt

Why: The equity conversion path. The holder exchanges debt for newly minted STRAT, betting on appreciation. Pro-rata esETH backing moves from encumbered to unencumbered holdings, freeing capital for protocol operations — creating a positive flywheel between conversion activity and available lending capital.


convertToEth(uint256 tokenId, uint256 cdtAmount)

Convert note to esETH before expiry. Burns CDT, transfers esETH from treasury.

Parameter
Type
Description

tokenId

uint256

NFT token ID

cdtAmount

uint256

Amount of CDT to burn (partial exercise supported)

Access

Caller

ownerOf(tokenId) only

Requires

CDT approved or permitted to the contract

Reverts
When

TimelockActive

Timelock hasn't passed

OptionExpired

Past expiry

NotOwnerOrApproved

Caller is not the NFT owner

InvalidExerciseAmount

cdtAmount is 0 or exceeds remaining amountOwedCdt

Why: The risk-off conversion path. The holder exits into ETH-denominated value without selling STRAT on the open market. esETH moves from encumbered → unencumbered → holder's address.


redeem(uint256 tokenId, uint256 minEthOut)

Redeem CDT for USD notional value in esETH after expiry.

Parameter
Type
Description

tokenId

uint256

NFT token ID

minEthOut

uint256

Minimum esETH to receive (slippage protection against oracle movement)

Access

Caller

ownerOf(tokenId) only

Reverts
When

TimelockActive

Timelock hasn't passed

OptionUnexpired

Note hasn't expired yet — use conversion instead

NotOwnerOrApproved

Caller is not the NFT owner

InsufficientOutput

esETH output is below minEthOut

Why: The maturity settlement. After ~4.2 years, conversion rights expire and the holder redeems at USD face value. Single-shot: settles the entire remaining position, burns both CDT and NFT. Pro-rata if the protocol is underwater — all CDT holders treated pari passu.


convertToStratWithPermit(uint256 tokenId, uint256 cdtAmount, uint256 deadline, uint8 v, bytes32 r, bytes32 s)

Combine CDT approval and STRAT conversion in one transaction via ERC-2612 permit.

Parameter
Type
Description

tokenId

uint256

NFT token ID

cdtAmount

uint256

Amount of CDT to burn

deadline

uint256

Permit signature deadline

v, r, s

uint8, bytes32, bytes32

ERC-2612 permit signature

Access

Caller

ownerOf(tokenId) only

Why: Gas optimization — saves one transaction by combining CDT approval with conversion. Same mechanics as convertToStrat() with an inline permit.


convertToEthWithPermit(uint256 tokenId, uint256 cdtAmount, uint256 deadline, uint8 v, bytes32 r, bytes32 s)

Combine CDT approval and esETH conversion in one transaction.

Same parameters and access control as convertToStratWithPermit. Mechanics match convertToEth().


redeemWithPermit(uint256 tokenId, uint256 minEthOut, uint256 deadline, uint8 v, bytes32 r, bytes32 s)

Combine CDT approval and post-expiry redemption in one transaction.

Same access control as redeem(). Adds permit parameters for gasless CDT approval.


conversionEntitlements(uint256 ethAmount) → (uint256 stratAmount, uint256 ethEntitlement, uint256 settlementUsd)

Preview conversion entitlements for a given ETH amount without executing.

Parameter
Type
Description

ethAmount

uint256

Amount of ETH (in wei) to preview

Returns
Type
Description

stratAmount

uint256

STRAT conversion entitlement

ethEntitlement

uint256

esETH conversion entitlement

settlementUsd

uint256

USD notional (CDT amount)

Access

Caller

Any (view)

Why: Essential pre-flight check. Shows exact note terms (in USD) before sending ETH. If the protocol is underwater, ethEntitlement will be zero — this function makes that transparent upfront.


notes(uint256 tokenId) → Note

Returns the full state of a convertible note.

Returns (struct)
Type
Description

conversionEntitlementStrat

uint256

STRAT claimable via conversion

conversionEntitlementEth

uint256

esETH claimable via conversion

settlementEntitlementUsd

uint256

USD notional for post-expiry redemption

amountOwedCdt

uint256

CDT required for full exercise (decrements on partial exercise)

expiry

uint256

Timestamp after which conversion closes

timelock

uint256

Timestamp before which conversion is blocked

Access

Caller

Any (view)

Why: On-chain transparency for note positions. UIs, dashboards, and integrators query this to display note details, calculate remaining value, and determine which actions are available.


releaseEncumbrance(uint256 tokenId)

Move an expired note's backing esETH from encumbered to unencumbered holdings.

Parameter
Type
Description

tokenId

uint256

NFT token ID (must be expired)

Access

Caller

Owner only (protocol multisig)

Reverts
When

EncumbranceAlreadyReleased

Encumbrance was already released for this note

Note has not expired

Why: Administrative function to free protocol liquidity. After a note expires, its backing esETH remains encumbered until released. This allows the protocol to reclaim capital from expired but unredeemed notes without affecting the holder's redemption rights.


StakedStrat (sSTRAT-v2)

On-chain STRAT staking with 7-day anti-frontrunning reward streaming. Accepts STRAT deposits, streams esETH rewards.

circle-info

Status: Deploying soon. Address will be published on the Contracts page before permissionless launch.

Property
Value

Receipt Token

sSTRAT-v2 (ERC-20 with transfers disabled)

Reward Token

esETH

Stream Duration

7 days

Reentrancy

All state-changing functions guarded by nonReentrant

Ownership

Ownable2Step (protocol multisig)

stake(uint256 amount)

Stake STRAT tokens. Receives sSTRAT-v2 1:1.

Parameter
Type
Description

amount

uint256

Amount of STRAT to stake

Access

Caller

Any (permissionless)

Requires

Caller must have approved StakedStrat to spend amount of STRAT

Reverts
When

ZeroAmount

amount is 0

ERC-20 revert

Insufficient STRAT balance or allowance

Why: Entry point for earning protocol revenue. Staking locks STRAT in the contract and issues a non-transferable receipt. Automatically calls syncRewards() before staking to ensure accurate reward accounting.


unstake(uint256 amount)

Unstake STRAT tokens. Burns sSTRAT-v2 proportionally.

Parameter
Type
Description

amount

uint256

Amount of STRAT to unstake

Access

Caller

Any (must have staked position)

Reverts
When

ZeroAmount

amount is 0

InsufficientStake

amount exceeds staked balance

Why: No lock period — unstaking is always available. Automatically claims all pending esETH rewards before reducing the stake, so nothing is forfeited. The 7-day streaming design makes frontrunning uneconomical without requiring lockups.


claim()

Claim accrued esETH rewards without changing staked position.

Access

Caller

Any (must have staked position)

Why: Allows stakers to collect earned yield without modifying their position. Returns silently if no rewards are pending.


syncRewards()

Detect new esETH in the contract and start/extend the reward stream.

Access

Caller

Any (permissionless)

Why: The mechanism that enables anti-frontrunning. When esETH arrives at the contract, syncRewards() detects the new balance and begins a 7-day linear stream. New rewards blend with any active stream using a value-weighted average duration. Called automatically by stake(), unstake(), claim(), and migrateStake() — but anyone can call it directly.


migrateStake(address to, uint256 amount)

Move staked position to a new address without unstaking.

Parameter
Type
Description

to

address

Destination address

amount

uint256

Amount to migrate (0 = full balance)

Access

Caller

Any (must have staked position)

Reverts
When

to is zero address, caller, or the contract itself

InsufficientStake

amount exceeds staked balance

Why: Wallet rotation without leaving the reward stream. Pays out the recipient's pending rewards during migration to prevent accounting corruption. Migrated rewards are proportional to the migrated stake amount.


getPendingRewards(address account) → uint256

View pending (claimable) esETH rewards for an account.

Parameter
Type
Description

account

address

Address to check

Returns
Type
Description

uint256

Pending esETH rewards in wei

Access

Caller

Any (view)

Why: Dashboard and UI function. May undercount if new rewards arrived but syncRewards() hasn't been called — for accurate readings, call syncRewards() first in a static call.


StratETHTreasuryLend

Fixed-rate, fixed-term esETH lending against STRAT + CDT collateral. Positions represented as ERC-721 NFTs.

circle-info

Status: Roadmap — Q2 2026. Will be audited and deployed separately from the core protocol launch.

Property
Value

Position Token

ERC-721 (transferable)

Collateral

STRAT + CDT (burned at origination)

Borrow Asset

esETH

Rate Model

Fixed rate, snapshotted at origination

Liquidation

Time-based only (after expiry) — no price-based liquidation

Reentrancy

All state-changing functions guarded by nonReentrant

Ownership

Ownable2Step (protocol multisig)

borrow(uint256 maxStratIn, uint256 maxCdtIn, uint256 minBorrowAmount, uint256 deadline) → uint256 tokenId

Open a loan position. Burn STRAT + CDT collateral, receive esETH.

Parameter
Type
Description

maxStratIn

uint256

Maximum STRAT to deposit as collateral

maxCdtIn

uint256

Maximum CDT to deposit as collateral

minBorrowAmount

uint256

Minimum esETH to receive (slippage protection)

deadline

uint256

Transaction deadline

Returns
Type
Description

tokenId

uint256

The minted position NFT

Access

Caller

Any (permissionless)

Requires

Caller must hold sufficient STRAT and CDT, both approved to the contract

Reverts
When

ZeroAmount

Either collateral input is zero

InsufficientOutput

Computed borrow amount < minBorrowAmount

TransactionStale

block.timestamp > deadline

Why: Allows STRAT holders to access ETH liquidity without selling, at a fixed rate with no liquidation risk during the term. The interest paid by borrowers flows to STRAT stakers, creating real yield from real demand. Serves as a natural escape valve — any STRAT holder can borrow against NAV-backed value.


repay(uint256 tokenId)

Repay a loan before expiry. Returns principal + accrued interest, re-mints STRAT + CDT collateral.

Parameter
Type
Description

tokenId

uint256

Position NFT token ID

Access

Caller

ownerOf(tokenId) only

Requires

Caller must hold sufficient esETH for principal + accrued interest

Reverts
When

LoanExpired

block.timestamp >= expiry — only liquidation remains

NotOwnerOrApproved

Caller is not the position NFT owner

Why: Early repayment is cheaper — interest accrues linearly, so repaying at the halfway point costs half the maximum interest. Accrued interest flows to stakers; unused interest reserve returns to unencumbered holdings. STRAT and CDT collateral is re-minted to the borrower.


roll(uint256 tokenId, uint256 additionalStrat, uint256 additionalCdt, uint256 minBorrowAmount, uint256 deadline)

Roll an existing position: settle accrued interest, adjust collateral, recompute terms, reset term.

Parameter
Type
Description

tokenId

uint256

Position NFT token ID

additionalStrat

uint256

Additional STRAT to add (0 to keep same or reduce)

additionalCdt

uint256

Additional CDT to add (0 to keep same or reduce)

minBorrowAmount

uint256

Minimum esETH to receive after rolling

deadline

uint256

Transaction deadline

Access

Caller

ownerOf(tokenId) only

Reverts
When

LoanExpired

Position has already expired

TransactionStale

block.timestamp > deadline

InsufficientOutput

New borrow amount < minBorrowAmount

Why: Avoids the gas and friction of close-then-reopen. Settles accrued interest, adjusts collateral, recomputes terms at current governance parameters (which may have changed), and resets the term clock — all in one transaction, preserving the same NFT.


liquidate(uint256 tokenId)

Liquidate an expired position. Permissionless — anyone can call after expiry.

Parameter
Type
Description

tokenId

uint256

Position NFT token ID

Access

Caller

Any (permissionless, after expiry only)

Reverts
When

block.timestamp < expiry (loan not yet expired)

Why: Time-based liquidation — no price oracles, no flash-loan manipulation, no cascading liquidations. On liquidation: full-term interest goes to stakers, delinquent fee goes to unencumbered holdings (increasing ethPerStrat), collateral is forfeited, position NFT is burned. The liquidator receives nothing — liquidation is a public good.


previewBorrow(uint256 maxStratIn, uint256 maxCdtIn) → (uint256 stratIn, uint256 cdtIn, uint256 ethBacking, uint256 borrowAmount, uint256 maxTermInterest, uint256 delinquentFee)

Preview loan terms without executing.

Parameter
Type
Description

maxStratIn

uint256

Maximum STRAT collateral

maxCdtIn

uint256

Maximum CDT collateral

Returns
Type
Description

stratIn

uint256

Actual STRAT that would be consumed

cdtIn

uint256

Actual CDT that would be consumed

ethBacking

uint256

Total ETH backing of the deposited STRAT

borrowAmount

uint256

esETH loan amount

maxTermInterest

uint256

Maximum interest over the full term

delinquentFee

uint256

Fee reserved for default penalty

Access

Caller

Any (view)

Why: Pre-flight check showing exact loan terms. The invariant always holds: borrowAmount + maxTermInterest + delinquentFee = ethBacking. Essential for UIs to display terms before the user commits collateral.


ESPN (EthStrategyPerpetualNote)

ERC-4626 tokenized vault. Deposit USDS, receive ESPN shares.

Property
Value

Name

ETH Strategy Perpetual Note

Symbol

ESPN

Standard

ERC-4626

Deposit Asset

USDS

Deposit Cap

Governance-configurable

Withdrawals

May be disabled by governance; check maxWithdraw()

Compiler

Solidity v0.8.20, 999,999 optimization runs, Shanghai EVM

Inherits

ERC4626, Ownable2Step, ReentrancyGuard

Ownership

Ownable2Step (protocol multisig)

Standard ERC-4626 Interface

ESPN follows the standard ERC-4626 Tokenized Vaultarrow-up-right specification. If your protocol already supports ERC-4626, no custom integration is needed.

Function
Description

deposit(uint256 assets, address receiver) → uint256 shares

Deposit USDS, receive ESPN shares

mint(uint256 shares, address receiver) → uint256 assets

Mint exact ESPN shares by depositing USDS

withdraw(uint256 assets, address receiver, address owner) → uint256 shares

Withdraw USDS by specifying asset amount

redeem(uint256 shares, address receiver, address owner) → uint256 assets

Redeem ESPN shares for USDS

convertToShares(uint256 assets) → uint256

Preview: USDS → ESPN conversion

convertToAssets(uint256 shares) → uint256

Preview: ESPN → USDS conversion

previewDeposit(uint256 assets) → uint256

Preview shares for a given deposit

previewMint(uint256 shares) → uint256

Preview assets needed to mint shares

previewWithdraw(uint256 assets) → uint256

Preview shares burned for a withdrawal

previewRedeem(uint256 shares) → uint256

Preview assets received for a redemption

totalAssets() → uint256

Total USDS managed by the vault

asset() → address

Underlying asset (USDS)

maxDeposit(address) → uint256

Maximum depositable (reflects cap)

maxMint(address) → uint256

Maximum mintable shares

maxWithdraw(address owner) → uint256

Maximum withdrawable (0 when withdrawals disabled)

maxRedeem(address owner) → uint256

Maximum redeemable shares

Owner Functions

Function
Access
Description

setManager(address _manager)

Owner

Set the manager address authorized to deploy deposited assets

setDepositCap(uint256 _depositCap)

Owner

Update the maximum total deposits

setWithdrawalsDisabled(bool _disabled)

Owner

Toggle direct withdrawals on/off

increaseAssetsPerShare(uint256 assets)

Manager

Increase the vault's assets-per-share for yield distribution

Query Functions

Function
Description

manager() → address

Current manager address

depositCap() → uint256

Current deposit cap

withdrawalsDisabled() → bool

Whether direct withdrawals are disabled

circle-exclamation

STRAT Option (StratOption)

ERC-721 representing call options over STRAT. Used for convertible note conversion rights and presale allocations.

Property
Value

Name

STRAT Option

Symbol

oSTRAT

Standard

ERC-721

Compiler

Solidity v0.8.20, 999,999 optimization runs, Paris EVM

Ownership

Ownable2Step (protocol multisig)

Each NFT encodes conversion entitlements, timelock, and expiry. The NFT is the "key" that — when combined with CDT — unlocks conversion to STRAT or esETH. Standard ERC-721 transfers and approvals apply, but settlement authorization requires ownerOf(tokenId) — approvals are not accepted for conversion/redemption.

Per-Token Query Functions

Function
Returns
Description

strikeAmount(uint256 tokenId) → uint256

CDT required to exercise (18 decimals)

The "cost" of exercising the option

notionalUnderlyingAmount(uint256 tokenId) → uint256

STRAT received on exercise (18 decimals)

The equity conversion entitlement

notionalUSDAmount(uint256 tokenId) → uint256

USD notional value of the note at purchase (18 decimals)

Settlement value for post-expiry redemption

expiry(uint256 tokenId) → uint256

Expiration timestamp

After this, conversion closes and redemption opens

timelock(uint256 tokenId) → uint256

Earliest exercise timestamp

Before this, no conversion or redemption

Management Functions

Function
Access
Description

mint(address to, uint256 strikeAmount, uint256 notionalUnderlyingAmount, uint256 notionalUSDAmount, uint256 expiry, uint256 timelock)

Authorized minters

Mint a new option NFT with specified terms

burn(uint256 tokenId)

Token owner

Burn an option NFT

manageMinter(address who, bool canMint)

Owner

Authorize/revoke minter addresses

managerRenderer(address renderer)

Owner

Set the tokenURI renderer contract


Access Control Summary

All ETH Strategy contracts use OpenZeppelin's Ownable2Steparrow-up-right for ownership transfers — a two-step process (propose → accept) that prevents accidental transfers to wrong addresses.

Contract
Owner
Delegatable Roles

esETH

Protocol multisig

STRAT

Protocol multisig

Minter management (manageMinter)

CDT

Protocol multisig

Minter management (manageMinter)

EthStrategyConvertibleNote

Protocol multisig

StakedStrat

Protocol multisig

StratETHTreasuryLend

Protocol multisig

Rate setter, fee setter (can be delegated to automated keepers)

ESPN

Protocol multisig


Immutability Guarantees

ETH Strategy contracts are deployed without proxy-upgrade patterns. Deployed code is immutable.

Governance Can Change (new positions only)
Governance Cannot Change (ever)

PCF/GCF (bonding price factors)

Existing note entitlements

Supported LST whitelist for esETH

Existing note timelock/expiry

Deposit caps

Existing loan terms

Reward distribution addresses

CDT supply accounting

Borrow rate, loan duration (TreasuryLend)

Contract logic (no upgrades)

Rate setter / fee setter delegation

Conversion/redemption mechanics

Last updated