Where you are. Module 2 ended on a promise: across a border, where two banks share no central bank and no ledger, none of the domestic machinery reaches. Five lessons have built the replacement piece by piece. A cross-border payment is a relay of ledger edits (lesson 1); its instruction and its value travel on separate tracks (lesson 2); the relay runs through correspondents, each adding a fee, a delay and a sanctions-screening stop (lesson 3); each pair of banks in the relay is joined by one account with two names, nostro on this book, vostro on that one, mirroring exactly (lesson 4); and that account only works because someone parked money in it yesterday (lesson 5). What you have not yet done is run one. This lesson wires all five pieces into a single simulator on linked miniledgers, sends the same payment three times, and turns days-not-seconds from a slogan into a printed number.
Three sendings, three arrivals
It is Monday in New York, and alice owes kenji in Tokyo three payments of 1,000 each. She sends the first at 09:00, over her second coffee; it lands in kenji’s account at 13:00 the same day. She sends the second at 16:40, twenty minutes before the earliest cutoff anywhere in the chain, and it arrives at midnight, technically tomorrow. She sends the third at 18:20, after dinner, and it arrives at four the next morning. Same amount, same corridor, same four banks doing the same work, and each bank spent the same few seconds of actual effort on all three. Nothing was congested and nobody was slow. The three journeys differ in exactly one input: the time each payment met the machine. By the end of this lesson that claim is not an intuition; it is an assert that passes.
The idea in one paragraph
The corridor is a machine with a fixed shape. An origin bank, two correspondents, a destination bank: Alder to Birch to Ginkgo to Hinoki, three interbank hops. Every hop charges a flat fee. The border hop holds the payment for four hours of sanctions screening. Every hop stops forwarding at its 17:00 cutoff and hands whatever remains to tomorrow. The message walks this machine on a clock; the money follows it in balanced postings across two ledger worlds, dollars in New York, yen in Tokyo, joined at exactly one seam, Birch’s nostro at Ginkgo. Give the machine an entry time and it returns an arrival time and a fee total, deterministically. “Why does the same transfer sometimes take hours and sometimes days” stops being a mystery about distance and becomes a function you can evaluate.
The machine, in four boxes
Wider than the screen; scroll it sideways.
There is no shared ledger anywhere in this picture, so the simulator builds two Worlds that never touch: a USD world holding Alder and Birch, a JPY world holding Ginkgo and Hinoki. The only thing joining them is lesson 4’s account with two names: nostro at Ginkgo, an asset on Birch’s book, mirrored by the birch-nostro deposit on Ginkgo’s - one account, two records, and an assert that they never diverge. Lesson 5 already paid for the connection: Birch pre-funded the nostro with 3,000 of yen, bought in advance against dollars owed to its FX dealer. The dollar leg of that purchase, what it cost and at what rate, is lesson 7’s story; today the machine converts at one for one.
The three hops are three moves you already know. Hop 1 is a domestic USD interbank payment, Alder to Birch, over module 2’s submit-and-settle machinery. Hop 3 is the same thing in yen, Ginkgo to Hinoki. Only hop 2 crosses the border, and it is the hop where no money moves at all: Birch pays away part of its nostro, and value changes hands by editing who owns a Tokyo balance that never leaves Tokyo.
Every number in the machine is stylised - a flat fee of 5 per hop, one shared 17:00 cutoff, a four-hour screening hold, an exchange rate of one - chosen so every diff reads at sight. The shape is the lesson; the prices come later in the module.
The clock walks the chain
The clock half of the simulator is one function, propagate. Per hop it does three things, in a fixed order: charge the fee, always; serve the screening hold, if this hop has one; then check the clock against the cutoff, and if the hop’s local time is past 17:00, roll forward to midnight and forward the payment tomorrow. Three rules, applied three times. Everything in the hook falls out of them.
The 09:00 payment is the corridor on its best day. Fees tick 5, 10, 15. The screening hold carries the clock from 09:00 to 13:00, still comfortably inside the cutoff, and hops 1 and 3 add seconds. Door to door: 4.0 hours, and effectively all four of them are one compliance hold.
The 18:20 payment fails early and pays twice. It reaches hop 1 after the cutoff, so it rolls to midnight before anything else happens. Then the border hop still owes its four hours of screening - the roll answered the cutoff, not the hold - so it serves 00:00 to 04:00 and lands at 04:00 on day 1. Delays never overlap; they queue.
The figure shows the two accumulations that ride along with every payment, on a stylised corridor of its own. The fee line climbs by the same small step at each hop and then stops: tolls scale with the hop count, and the chain has three. The hours line climbs in uneven leaps, and the tall riser in the middle is the screening hold. Same axis, entirely different shapes: fees accumulate with the hops, hours accumulate with the calendar.
One simplification to name before you build it: the simulator runs both cities on one clock and gives every hop the same 17:00 cutoff. Real corridors are crueller. Tokyo’s 17:00 falls in New York’s small hours, so the windows are staggered across time zones, and a payment can miss a cutoff that was never visible from the sending screen. The mechanism is identical - miss a window, wait a day - staggering just multiplies the ways to miss.
The money follows
The other half of the simulator, send_value, moves the money the message described, and it is written for you - read it before you run it. Hop 1 submits and settles a USD interbank payment into Birch’s in transit account, and Birch helps itself to its fee with a two-line posting to its own equity. Hop 2 pays away the nostro, and Ginkgo takes its own fee straight out of that account: the border hop’s toll is collected on the vostro side. The simulator immediately asserts lesson 4’s law - Birch’s nostro and Ginkgo’s record of it still mirror, to the unit. Hop 3 submits and settles yen to kenji, less the last toll. Both worlds re-assert their sheets after every sending, and the harness checks one more conservation law at the end: every fee charged anywhere ends up on some bank’s equity. Tolls reallocate; they never leak.
Then the harness does the thing this course keeps doing: it reconciles two independent models. propagate walked the message on a clock and counted tolls; send_value moved the money in postings and let each bank take its cut. delivered == AMOUNT - fees asserts that they agree - module 2’s differential-testing move, with the clock as one implementation and the ledgers as the other. If they ever disagree, one of your models is lying, and the assert says so before your intuition does.
Check yourself
1. The 16:40 payment beats every cutoff in the chain on paper. Why does it still arrive tomorrow?
Because of the order of operations inside the border hop: fee, then hold, then cutoff check. Screening runs before forwarding - a hop cannot pass on a payment it has not cleared - so the clock reads 20:40 when the cutoff question is finally asked, and the answer is tomorrow. The payment was early; the machine made it late; nothing on the sending screen showed the difference.
2. The 18:20 payment rolls to midnight after missing hop 1’s cutoff. Why does it arrive at 04:00 rather than 00:00?
The roll answers the cutoff, not the hold. At midnight the border hop still owes its four hours of screening and serves them from 00:00 to 04:00; that is comfortably inside the next cutoff, so the last hop forwards at once. Holds are never forgiven, only deferred, and delays queue one behind the other rather than overlapping.
3. Hop 2 is the border crossing, yet no money crosses the border. What moves, and which assert guards it?
Ownership of a Tokyo balance moves. Birch pays away 995 of its nostro at Ginkgo; dollars stay in New York, yen stay in Tokyo, and value crosses by editing who owns the yen. The guard is lesson 4’s mirror assert: Birch’s nostro and Ginkgo’s vostro-side record must still agree after the hop. If they diverge, one bank has recorded a payment the other never saw - and reconciling exactly that divergence is a real correspondent’s daily chore.
4. All three journeys cost exactly 15 in fees, whether they took 4.0 hours or 9.7. What does the corridor charge for, and what does it not?
The toll is per hop, charged for handling, not for waiting: three hops, 5 each, whatever the calendar does in between. Time cost and money cost are separate axes, one set by holds and cutoffs, the other by the hop count. And 15 on 1,000 is suspiciously cheap, because this machine converted currency at a stylised rate of one and charged nothing for it. Lesson 7 opens that toll, the one hidden inside the exchange rate itself.
5. Why is delivered == AMOUNT - fees worth asserting, when both numbers come from the same script?
Because they come from two independent models inside that script. propagate never touches a ledger; it walks a clock and counts tolls. send_value never looks at the clock; it posts balanced entries and lets each bank take its fee. Asserting they agree is a differential test, the same move as module 2’s three-rails comparison: two implementations, one truth. A propagate that, say, charged fees only on same-day forwards would pass every clock assert and fail this one - the ledgers would refuse to confirm its arithmetic.
Do this
Twenty-five minutes, from module-03-across-borders. Open code/chain_simulator.py. The money half is complete: build_corridor raises the two worlds and pre-funds the nostro; send_value walks the postings and re-asserts the sheets and the mirror after every sending. Yours is the clock: propagate, the TODO(you) with three numbered rules per hop - add the fee, always; add the hold, if the hop has one; and if the clock’s minute-of-day is past the 17:00 cutoff, roll to midnight and forward tomorrow. The harness then sends the same 1,000 at 09:00, 16:40 and 18:20 and asserts everything this lesson claimed: the same-afternoon arrival, the screening slip, the double delay, the flat fees, and clock-ledger agreement on every sending.
python3 code/chain_simulator.py
Green is exactly this scoreboard, ending with the final line verbatim:
sent day 0 at 09:00 -> arrives day 0 at 13:00; elapsed 4.0h, fees 15, delivered 985
sent day 0 at 16:40 -> arrives day 1 at 00:00; elapsed 7.3h, fees 15, delivered 985
sent day 0 at 18:20 -> arrives day 1 at 04:00; elapsed 9.7h, fees 15, delivered 985
same corridor, same 1000: 4.0h, 7.3h and 9.7h door to door - days-not-seconds is not slow wires; it is cutoffs, screening holds and time zones stacking
The asserts are written to name your bug. If the 16:40 payment arrives on day 0, the screening hold never reached your clock. If arrivals slide days past the scoreboard, look at your cutoff rule: comparing the raw clock against 1020 instead of clock % DAY makes every hop after the first roll roll again, and clock += DAY carries the missed minute-of-day into tomorrow, where it misses again - the roll is to midnight, (clock // DAY + 1) * DAY, because a payment that misses today forwards at tomorrow’s opening. And if the fee assert fires, you charged the toll only when a hop forwarded same-day: waiting costs time, never fewer fees. The completed version is solutions/chain_simulator.py; compare after you are green.
What you can now do. You can run the canonical corridor end to end and answer the commonest question in cross-border payments - why does the same transfer take hours or days - with a mechanism instead of a shrug: three hops, each charging a flat toll, one holding for screening, all closing at a cutoff, on a machine where delays queue and never overlap. You can show the answer is deterministic, that the ledgers confirm the clock to the unit, and that the nostro seam both carries the value and caps the day. What the machine has not yet charged you for is the thing every real corridor charges most for: the currency conversion it performed at a pretend rate of one. Lesson 7 walks into the dealing room and prices it.