ElliotWe wanted one number: how far does ADA have to fall before a real share of Indigo's loans gets...
We wanted one number: how far does ADA have to fall before a real share of Indigo's loans gets liquidated? Indigo is a Cardano protocol where you lock ADA and mint synthetic assets (iUSD, iBTC, iETH…) against it. Each position is a CDP, a collateralized debt position.
The protocol's own API was the obvious place to start. When we started (September 9) it listed only the v3 positions: 50 CDPs holding about 6,300 ADA. The real book was about 3,000 times bigger, and it was sitting in plain sight on chain.
This post shows how we read it from a local cardano-db-sync Postgres database, and how we check that the decode is complete. That check matters more than the decode itself.
On Cardano, a smart contract's funds are UTxOs locked at a script address. Every CDP is one UTxO at Indigo's v2 CDP validator, and that address's payment credential is ff0b10bff20e4b68b491492e5ba6c8048a704763b0a45ce2995da0be.
We found it by working backwards: take recent transactions that mint iUSD and look at which script output each one creates. Every one of them lands on that credential.
db-sync ships a utxo_view of unspent outputs. Every CDP carries its state as an inline datum, and db-sync stores those already decoded to JSON in the datum table:
SELECT u.value::numeric AS lovelace,
d.value::text AS datum_json
FROM utxo_view u
LEFT JOIN datum d ON d.id = u.inline_datum_id
WHERE u.payment_cred = decode('ff0b10bff20e4b68b491492e5ba6c8048a704763b0a45ce2995da0be', 'hex');
On 2026-10-06 that returned 314 UTxOs. 311 decode as CDPs; the 3 that don't are reported as undecoded.
The v2 CDP datum is nested Plutus constructors. Stripped down:
con0[ con0[ con0[ bytes owner_pkh ],
bytes iasset_name_hex, -- "iUSD", "iBTC", ...
con0[ bytes policy, bytes name ], -- collateral; ("", "") = ADA
int minted_raw, -- the debt, 6 decimals
con0[ int updated_ms, int interest_acc ] ] ]
In Python:
import json
def decode_cdp(lovelace, datum_json):
f = json.loads(datum_json)["fields"][0]["fields"]
asset = bytes.fromhex(f[1]["bytes"]).decode()
if not asset.startswith("i"):
raise ValueError("not a CDP")
return {
"asset": asset,
"owner": f[0]["fields"][0]["bytes"],
"collateral_ada": int(lovelace) / 1e6,
"collateral_is_ada": f[2]["fields"][0]["bytes"] == "",
"debt": int(f[3]["int"]) / 1e6,
}
Anything that doesn't fit the shape gets counted, not dropped. A decoder that quietly skips rows it doesn't understand will tell you the book is smaller than it is, and it will look fine while doing it.
Every iAsset is minted under one policy (f66d78b4a3cb3d37afa0ec36461e51ecbde00f26c8f0a68f94b69880). The total minted minus the total burned is the amount of each iAsset that exists. If our decode has found every position, the decoded debt per asset should equal that number:
SELECT encode(ma.name, 'escape') AS iasset, SUM(mtm.quantity)::numeric AS net_minted
FROM ma_tx_mint mtm JOIN multi_asset ma ON ma.id = mtm.ident
WHERE encode(ma.policy, 'hex') = 'f66d78b4a3cb3d37afa0ec36461e51ecbde00f26c8f0a68f94b69880'
GROUP BY 1 ORDER BY 1;
Result on 2026-10-06: iADA, iBTC, iETH, iEUR, iJPY and iSOL reconcile to 100.00%. iUSD comes to 95.2%. We have ruled out the redemption script, which holds reference datums rather than CDPs. We still don't know where the rest is, so we publish the gap rather than round it away, and our pipeline refuses to publish if any asset falls below 85%.
mcr = null for every asset, so we show the curve across 110%, 120%, 130% and 150% instead of pretending to know one.As of 2026-10-06 13:18 UTC, with ADA at $0.276:
| Positions in the stress test | 287 (of 311 decoded) |
| iAsset debt | $1.89M |
| Collateral | 17.4M ADA (~$4.81M) |
| Whole-book collateral ratio | 2.54 |
| ADA price where 10% of the debt is under 120% | $0.175 (−36%) |
| ADA price where 50% of the debt is under 120% | $0.143 (−48%) |
It's a snapshot, not a forecast. The live version, with the full curve and CSVs, is at cardanorecord.com/risk.html, and it's refreshed several times a day from the same node.
We run The Cardano Record, a daily show built entirely from our own node's data, with every prediction it makes scored in public, the misses included. Not financial advice.