Host A · writes
Railway, Singapore
Reads the issuer, derives each asset's regime and cap, and sends every round to MarketClock in one attestBatch transaction. It publishes each round's inputs as a bundle.
MarketClock · X Layer
For each tokenized equity, MarketClock records whether its home market will create and redeem shares right now. An attestor reads the issuer every five minutes and writes the answer to X Layer.
The contract fails closed. An attestation older than 30 minutes reads as unknown, with a cap of zero, so a dead attestor can never leave an asset looking open.
One row per registered asset. The glyph is the regime: a closed ring when the primary cap is above zero, the C with its amber arc when the market is shut but the pool still trades, a dotted ring when the attestation is stale. The next change comes from the venue's published schedule, less the issuer's 300-second early cut.
| Asset | Regime | Primary cap | Next change | Attested | This week, Hong Kong time |
|---|---|---|---|---|---|
wTCENTxTencent · HKEX | … | … | … | … | |
wSHEINxSHEIN · HKEX | … | … | … | … | |
wXIAOxXiaomi · HKEX | … | … | … | … | |
wMEITxMeituan · HKEX | … | … | … | … | |
wNVDAxNvidia · Nasdaq | … | … | … | … | |
wAAPLxApple · Nasdaq | … | … | … | … |
Primary market open Shut, pool still trading Now
Each round is one transaction. It commits an input root: a Merkle root over the exact issuer responses the attestor read. Host A publishes those inputs as a bundle, so anyone can rebuild the root and re-run the derivation.
Rebuilds the root from the bundle, re-runs the derivation, and compares it with what the transaction wrote. Needs Node 22.18 or newer.
npx -y curb-verify tx <round transaction>
MarketClock is free to read, with no key and no licence. Before you liquidate, lend or settle against a tokenized equity, ask whether its primary market is open.
Read regime() and primaryCapNow(), not stateOf(). stateOf() returns the stored struct as written, so on a dead attestor it still shows the last known cap. The staleness check lives in the other two.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
interface IMarketClock {
enum Regime { UNKNOWN, CLOSED, OVERNIGHT, EXTENDED, MARKET }
function regime(address wrapper) external view returns (Regime);
function primaryCapNow(address wrapper) external view returns (uint128);
}
contract UsesTheClock {
// MarketClock on X Layer (chain 196)
IMarketClock constant CLOCK = IMarketClock(0x160Dc415902971a7a9B5ade7f43005b36FE5B09b);
error MarketShut(address wrapper);
// Whole USD the issuer will create or redeem now. 0 = shut, or stale.
function _requireOpen(address wrapper) internal view {
if (CLOCK.primaryCapNow(wrapper) == 0) revert MarketShut(wrapper);
}
function inRegularSession(address wrapper) external view returns (bool) {
return CLOCK.regime(wrapper) == IMarketClock.Regime.MARKET;
}
}
cast call 0x160Dc415902971a7a9B5ade7f43005b36FE5B09b "primaryCapNow(address)(uint128)" 0x41333Df9E7639188BBfca5522dC4844398Af9f9E --rpc-url https://rpc.xlayer.tech
The wrapper above is wTCENTx. The full interface, including isInMultiplierBlackout and rawToShares, is in the verified source (opens OKLink).
One host writes every round. A second host, on a different provider and continent, checks every round it writes. A witness does not change what the contract stores: it is an attributable second check, not a quorum.
Host A · writes
Reads the issuer, derives each asset's regime and cap, and sends every round to MarketClock in one attestBatch transaction. It publishes each round's inputs as a bundle.
Host B · witnesses
For each round host A writes, host B fetches the bundle and re-derives it, checks that the calldata equals the committed claims, and compares them with its own reading of the issuer. Then it signs the result as EIP-712 typed data, pass or fail.
npx -y curb-verify witness <inputRoot>