MarketClock · X Layer

Six assets, open or shut right now

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.

The board

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.

MarketClock state for each registered asset.
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

The latest round

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.

Transaction
Reading the last 400 blocks…
Block
…
Input root
…
Assets in the round
…

Check it yourself

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>

Read it from a contract

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.

UsesTheClock.sol
// 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).

Two hosts, one writer

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 B · witnesses

Tencent, Silicon Valley

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.

Check a witness
npx -y curb-verify witness <inputRoot>