Where you are. Sixteen lessons built the pieces: an issuer, a cage, a business model, a disclosure, a mint and burn path, an arbitrage loop, and two ways for it to fail. This project runs all of it as one system and stresses it until the differences between designs become visible as numbers.
The brief
One script, two halves.
The issuer. Stand up a complete issuer on the miniledger: reserve assets in a bankruptcy-remote entity, a holder ledger, mint and burn as paired postings, and the reserve-yield accrual that pays the issuer and not the holders. Check the one-to-one invariant after every operation, and check that the sheet balances too, because they are different checks.
The stress. Run six seeded scenarios: three reserve compositions crossed with two redemption regimes. All bills, bills plus slower-converting bank deposits, and reserve assets impaired by a tenth; each with the redemption window open throughout and with it gated for a weekend that lifts halfway through. Record the low, the close and the round at which each path returned to par, and classify each run by what its holder actually got.
The idea in one paragraph
Everything this module built is one system, and a single scenario cannot tell you which part of it did what. Running a grid can: hold the redemption policy fixed and vary the reserve assets, then hold the reserve assets fixed and vary the policy, and each variable’s effect separates out. That is why the project is six runs rather than one dramatic one, and why the report has a column for the low, a column for the close and a column for the time to recover. The finished harness is a complete issuer, and the finished result is an attribution.
What the six runs say
Three variables, and each one shows up in a different column of the results. That separation is the whole point of running the grid rather than a single scenario.
| reserve assets | window | lowest | closing | back to par | holder got |
|---|---|---|---|---|---|
| all bills | open | 0.9250 | 1.0035 | round 3 | paid at par |
| all bills | gated for a weekend | 0.8904 | 1.0035 | round 24 | paid, but late |
| bills plus bank deposits | open | 0.9250 | 1.0035 | round 7 | paid at par |
| bills plus bank deposits | gated for a weekend | 0.8904 | 1.0035 | round 30 | paid, but late |
| impaired by a tenth | open | 0.8944 | 0.9035 | never | broke the buck |
| impaired by a tenth | gated for a weekend | 0.8904 | 0.9035 | never | broke the buck |
n = 6 trials · 40 rounds per run, one seed, three compositions by two regimes
The gate sets how deep it goes: the same sound reserve assets bottom at 0.925 with the window open and 0.890 with it shut. The composition sets how long it takes to come back: sound and liquid repairs by round 3, sound and slower by round 7, and under the gate the same ordering stretches to rounds 24 and 30. And only impairment changes where it ends, because only impairment changes what a token is actually worth.
Why the verdicts use the fund’s words
The classification is deliberately borrowed from lesson 16’s money market fund frame: paid at par, paid but late, or broke the buck.
Those three describe what happened to the holder rather than to the issuer, and that is the right frame for judging a design. An issuer that was solvent throughout and paid everybody in full after a week has still done something to its holders, and a vocabulary that only distinguishes solvent from insolvent cannot express it. The fund industry needed that vocabulary and built it; this module borrows it rather than inventing a worse one.
What you have built
Working backwards through the module, the finished harness contains all of it. The two-tier and shared ledger comparison from lesson 1 is the ledger it posts to. The one-to-one invariant from lesson 2 is checked after every operation. Lesson 3’s bankruptcy-remote entity is where the reserve assets sit, and lesson 4’s yield accrual is why the issuer’s equity grows while the holders’ does not. Lesson 5’s liquidity ladder is the same-day parameter. Lesson 6’s paired postings are the mint and burn. Lesson 7’s arbitrage loop is the repair step, and lesson 8’s two failure modes are two of the six runs.
That is a complete stablecoin issuer, stressed six ways, in one file you can read.
Check yourself
1. Three variables, three effects. Which is which?
The redemption gate sets how deep the price falls. The reserve composition sets how long the repair takes, through the same-day capacity of the assets. Only impairment changes where the price ends up, because only impairment changes what a token is actually worth.
2. Why classify the runs by what the holder got rather than by whether the issuer was solvent?
Because an issuer that stayed solvent and paid everybody in full after a week has still done something material to its holders, and a solvent-or-not vocabulary cannot express it. Paid at par, paid but late, and broke the buck describe the outcome that a holder actually experiences.
3. The slower reserve composition still recovers fully. Why is that not reassuring?
Because it recovers within the forty rounds the simulation runs. The composition changed how much time the issuer needed, not where it ended up, and a run is precisely the situation in which time is not available. A shorter horizon turns the same composition into a run that has not recovered.
4. Why does the project check both the backing invariant and the balance sheet?
Because they are different properties, as lesson 2 showed. The sheet balances whenever postings balance, which a token created against equity would satisfy. The backing check tests that tokens in issue equal the reserve assets held. A system can pass either one while failing the other.
Do this
Assemble the issuer and run the grid.
python3 code/stress_harness.py
The starter provides the issuer and the scenario simulator, and leaves you the two classification functions: recovery_round, the first round at which the price is back within a penny of par, and verdict, which maps a path onto the fund frame using that recovery time. The assertions check that the gate deepens the low, that the slower composition takes longer to repair, that only the impaired runs break the buck, and that the six runs split two, two and two across the three verdicts.
The completed version is in solutions/stress_harness.py.
What you can now do. You can build a complete stablecoin issuer on a ledger, stress it across reserve composition and redemption policy, and attribute each part of the outcome to the variable that caused it. Module 7 takes these tokens and builds markets on them, and then closes the loop module 3 opened by settling one ledger’s cash against another ledger’s bond, both legs or neither.