For the complete documentation index, see llms.txt. This page is also available as Markdown.

Miden → EVM Lending Integration

Use TaskType.ProtocolInteraction with Miden P2IDE note collateral to fund an earn / lending deposit on an EVM chain (e.g. dummy-lending on Sepolia) while the user pays from Miden testnet USDC.

This guide is written for Miden wallet / dApp integrators. It mirrors the production flow implemented in the Epoch Intent Widget earn mode.


What the user experience looks like

  1. User connects an EVM wallet (intent sponsor / recipient on the lending market).

  2. User connects a Miden wallet and selects Miden USDC as the funding source.

  3. App requests a quote from the Epoch allocator (smallocator).

  4. User confirms; app creates a P2IDE note on Miden paying the quoted amount to the Epoch allocator account.

  5. Epoch SIO consumes the note, fronts EVM liquidity, runs swap/bridge (if needed), and executes the lending deposit on the destination chain.

  6. App polls intent status until complete.

There is no EVM ERC-20 approval for Miden-funded deposits. Collateral is the Miden note, not Compact on-chain registration.


Architecture

Layer
Role

Your app

Builds intent data, overrides origin chain to Miden, implements createMidenP2IDNote

Epoch allocator

Quote (/checkIfDepositNeeded), submit (/compact), status

SIO

Multi-leg routing: FillerSwapAndBridgeprotocol-interaction (deposit)

Miden note

User collateral; recipient must be allocator P2ID account from GET /miden-recipient


Prerequisites

Requirement
Notes

EVM wallet

Sponsor address on the intent (recipient = same user EVM address)

Miden wallet

Must support sending a public P2IDE note to a hex account id

Epoch allocator URL

Testnet e.g. http://localhost:3000 or hosted allocator

Packages

@epoch-protocol/epoch-intents-sdk, @epoch-protocol/epoch-commons-sdk, viem

Network

Testnet only today (dummy-lending + Miden testnet)

Install:


Critical constants

Constant
Value
Meaning

MIDEN_VIRTUAL_CHAIN_ID

999999999

Origin chain id for all Miden→EVM allocator requests

Miden USDC faucet id

0xfc90f0f4da30e51168453b60eafed7

Default testnet faucet (6 decimals)

Miden USDC decimals

6

Always use 6 for tokenInAmount and P2ID note amount

EVM tokenIn sentinel

0x0000000000000000000000000000000000000000

Signals Miden source (not native ETH)

P2IDE reclaim window

Set when creating the Miden note

Not part of the signed witness; configured on note creation

protocolHashIdentifier

keccak256("dummy-lending")

Amount rule: Miden-side amounts are always in 6-decimal atomic units (1 USDC = 1_000_000). EVM market underlyings may use 18 decimals; Epoch converts internally during quoting. Do not scale Miden amounts to 18 decimals yourself.


Protocol hash

For dummy-lending test markets:

For 1delta mainnet markets, use keccak256(toBytes("1delta")) instead.


Market identifier (marketUid)

Lending markets are addressed by a colon-delimited uid embedded in extraData.marketUid:

Example (USDC market on Ethereum Sepolia):

Field
Description

Prefix

DUMMY_LENDING → routes to dummy-lending earn solver

chainId

Chain where the lending market lives (11155111, 84532, …)

underlyingTokenAddress

ERC-20 deposited into the vault (lowercase ok)

destinationChainId in intentData must match the market chain. outputTokenAddress / payAsset must match the market underlying.


Intent fields (lending deposit)

Task type

TaskType.ProtocolInteraction

Core intentData fields

Field
Miden deposit value

depositTokenAddress

0x0000000000000000000000000000000000000000

tokenInAmount

User input in Miden 6-dec atomic units, e.g. parseUnits("1", 6)

outputTokenAddress

Market underlying ERC-20

minTokenOut

"0" (forward quote from user Miden input)

destinationChainId

Market chain id string, e.g. "11155111"

protocolHashIdentifier

keccak256(toBytes("dummy-lending"))

recipient

User EVM address (sponsor)

extraData schema (lending + Miden)

Miden bridge intents use field inclusion, not an exact suffix string. The witness must declare and include the required Miden → EVM fields (midenSourceAccount, midenFaucetId, midenNoteType, midenNoteId). Earn / lending fields may appear before or after the Miden block.

Use the canonical constants exported from @epoch-protocol/epoch-intents-sdk:

Witness hashing: Miden and earn fields use string (and bool / uint256 where declared) in the typestring. The allocator hashes witness data with EIP-712, matching client signing. The same witnessTypeString is forwarded through quote (/checkIfDepositNeeded), compact submission, and SIO routing.

Miden field
When set

midenSourceAccount

Before quote — user's Miden account id (hex, 15 bytes)

midenFaucetId

Before quote — faucet id for the asset sent in the note (hex, 15 bytes)

midenNoteType

Before quote — use P2IDE for reclaimable collateral notes

midenNoteId

After P2IDE creation — SDK writes this into intentData before /compact


Origin chain override (required)

The allocator SDK uses walletClient.chain.id as the intent origin chain. For Miden deposits you must override it to 999999999 even when the EVM wallet is connected to Sepolia:

Without this, the allocator treats the flow as Sepolia → Sepolia instead of Miden → Sepolia.


Headless SDK flow (full example)

createMidenP2IDNote contract

The SDK calls your callback only after quote confirms resourceLockRequired. Parameters:

Param
Type
Description

faucetId

string

Normalized hex faucet id

amount

string

Atomic Miden units (6 decimals) — usually quote.tokenIn after reverse sizing

allocatorAccountId

string

From GET {allocator}/miden-recipientmust be note recipient

Return { success: true, noteId: "<note_id_string>" } or { success: false, error: "..." }.

The SDK fetches the allocator id automatically via GET /miden-recipient before invoking your callback.


Widget integration (optional)

If you prefer a pre-built UI, use @epoch-protocol/epoch-intent-widget in mode="earn" and inject a Miden adapter:

The widget handles origin-chain override, intent encoding, quote debouncing, and status polling internally.


Allocator HTTP surface

Method
Path
Purpose

POST

/checkIfDepositNeeded

Quote only — returns resourceLockRequired, path, tokenIn, tokenOut

GET

/miden-recipient

{ midenP2IDRecipientAccountId } — P2IDE payee

POST

/compact

Submit intent after note creation

GET

/intent/status/:address/:nonce

Poll execution (nonce is decimal string from submit response)

Quote request body includes "chainId": "999999999" for Miden-origin intents.


Quote response semantics

Field
Miden lending deposit

resourceLockRequired

true

transactions

[] at quote time (no EVM txs until submit)

tokenIn

Miden collateral in 6-dec atomic units (may include routing buffer)

tokenOut

Expected amount credited on EVM side (market underlying decimals)

path

Multi-leg route, typically FillerSwapAndBridgeprotocol-interaction

Display quote.tokenIn formatted with 6 decimals to the user before submit.


P2IDE note checklist


Two-wallet model

Wallet
Chain
Responsibility

Miden

Miden testnet

Holds USDC faucet balance; signs P2IDE send

EVM

Any (Sepolia, Base Sepolia, …)

Intent sponsor address; not used for token approval in Miden flow

The EVM wallet does not need to be on the destination market chain for quoting, but must be connected for SDK initialization.


Local development stack

Service
Default port

smallocator (allocator)

3000

epoch-sio

8080

dex-solver

3002

dummy-lending-solver

3012

dummy-lending positions API

4024

Point the widget / SDK at api.baseUrl: http://localhost:3000.


Common failures

Symptom
Likely cause

Route shows Sepolia → Sepolia

Missing walletClient.chain.id = 999999999 override

P2ID amount ~10¹² USDC

Miden amount expressed in 18-dec instead of 6-dec

NO_QUOTE_AVAILABLE / undefined.includes

Wrong earn solver (lending-solver vs dummy-lending-solver)

Note validation failed

P2IDE recipient ≠ /miden-recipient account

Stuck after quote, no Miden tx

Expected — user must confirm submit; note is created in solveIntent

NO_VALID_TREASURY_CANDIDATE

EVM inventory/treasury not funded on destination chain



Support

Contact the Epoch team for allocator URLs, MIDEN_ALLOCATOR_ACCOUNT_ID alignment, and graph registration of new lending protocols or Miden faucet assets.

Last updated