Skip to content

ERC-1155 ids

fact

id = (seriesId << 1) | leg leg 0 = COUPON, leg 1 = SHIELD seriesId = id >> 1 leg = id & 1
seriesIdCOUPON idSHIELD id
001
123
71415
1,0002,0002,001

INoteCoreViews.legId(seriesId, leg) and NoteLegs.seriesOf(id), NoteLegs.legOf(id) implement the mapping on-chain.

One unit equals one quote unit of matched notional, so with 6-decimal USDG a 100,000 USDG position is 100_000_000_000 units. Supply per id is at most matchedNotional and decreases as units are redeemed.

Standard safeTransferFrom and safeBatchTransferFrom. Before balances update, NoteLegs._update calls NoteCore.onLegTransfer(seriesId, leg, from, to, amount), which settles accrued coupons for both parties. Transfers revert while the series is in Subscription (no units exist) and are otherwise unrestricted by the protocol. Stock Token transfer restrictions do not apply to legs; they apply only when stock leaves escrow on redemption.

uri(id) returns the ERC-1155 URI template passed to the NoteLegs constructor by NoteCore (legsUri, default https://note.systems/legs/{id}.json in the deploy script). There is no setter; changing it requires a new deployment. A front-end should render: underlying symbol, leg, s0, barrier and autocall levels, next observation, status. All are available from getSeries(seriesOf(id)).

Track TransferSingle/TransferBatch on NoteLegs for holder balances, and PositionSettled on NoteCore for the lazy mint that follows strike. Because minting is lazy, a holder’s balance can be zero after strike until settle is called; accruedCoupon and previewRedeem account for unsettled deposits, so use them rather than raw balances when displaying a user’s position.

// JS helpers
const couponId = (seriesId) => (BigInt(seriesId) << 1n) | 0n;
const shieldId = (seriesId) => (BigInt(seriesId) << 1n) | 1n;
const seriesOf = (id) => BigInt(id) >> 1n;
const legOf = (id) => Number(BigInt(id) & 1n);