31. Token & Resource Standards (KRS)
Smart contract standards establish unified interfaces, storage layouts, and invariant guarantees across the ecosystem. On Kortana, protocol and token standards are codified under the Kortana Resource Standards (KRS) framework (§21, §9.1.3, §9.8). Implemented in native Quorlin, these standards execute on the register-based Kortana Virtual Machine (KVM) while offering complete interoperability with Ethereum ABI tooling and external indexers.
This chapter walks through practical, developer-ready smart contract examples showing how to write, understand, and deploy contracts for all 12 KRS standards in Quorlin, complete with detailed breakdowns of how each mechanism works.
31.1 Architecture & Storage Layout Rules
The KRS ecosystem is organized into three architectural tiers:
┌────────────────────────────────────────────────────────┐
│ Kortana Resource Standards (KRS) │
└────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────┼────────────────────────────────────────────┐
│ │ │
┌───────────────────────────┐ ┌───────────────────────────┐ ┌───────────────────────────┐
│ TIER 1 │ │ TIER 2 │ │ TIER 3 │
│ Ethereum-Equivalent │ │ RWA & Financial Prims │ │ DePIN & Machine-M2M │
├───────────────────────────┤ ├───────────────────────────┤ ├───────────────────────────┤
│ • KRS-20 (Fungible) │ │ • KRS-1579 (RWA Assets) │ │ • KRS-3311 (Streaming) │
│ • KRS-721 (NFTs) │ │ • KRS-2186 (Delegated) │ │ • KRS-5502 (Device Reg) │
│ • KRS-1155 (Multi-Token) │ │ • KRS-4317 (Debt/Credit) │ │ • KRS-8290 (Telemetry) │
│ │ │ • KRS-6821 (Attestation) │ │ │
│ │ │ • KRS-7743 (Payments) │ │ │
│ │ │ • KRS-9064 (Escrow) │ │ │
└───────────────────────────┘ └───────────────────────────┘ └───────────────────────────┘The Slot-Prefix Rule
Quorlin assigns contract storage slots (0, 1, 2, etc.) in declaration order. External indexers (The Graph, subgraphs, explorers) calculate storage slots based on these fixed positions:
- Mandated standard variables must be declared first in your contract (slots 0 to N-1).
- Custom application variables must be declared after them (slots N and above).
Storage Layout in Your Contract
┌─────────────────────────────────────────┐
Slot 0 │ Standard Variable (e.g. owners) │ ◄── External Indexers
├─────────────────────────────────────────┤ (Explorer, Subgraphs)
Slot 1 │ Standard Variable (e.g. counts) │
├─────────────────────────────────────────┤
Slot 2 │ Standard Variable (e.g. approvals) │
├─────────────────────────────────────────┤
Slot 3 │ Standard Variable (e.g. operators) │
├─────────────────────────────────────────┤
Slot 4+ │ Your Custom State (mintFee, baseURI...)│ ◄── Your Application
└─────────────────────────────────────────┘Compile-Time Verification (--strict-storage-layout)
The Quorlin compiler (quorlinc) automatically checks your storage layout against the standard at compile time:
# Compiling with KRS layout verification
qlc compile MyNFT.ql --strict-storage-layout --standard KRS-721 -o build/
qlc compile MyToken.ql --strict-storage-layout --standard KRS-20 -o build/
qlc compile GameItems.ql --strict-storage-layout --standard KRS-1155 -o build/31.2 Example: NFT Collection Contract (KRS-721)
KRS-721 defines non-fungible tokens on the Kortana blockchain with full ERC-721 ABI compatibility.
Problem & Motivation
Unique digital assets such as domain names, event tickets, game characters, or collectible passes require verifiable ownership, transfer restrictions, and safe contract receiver callbacks.
Contract Implementation (KortanaPass.ql)
// Interface for smart contracts that receive NFTs
interface IERC721Receiver {
writes number onERC721Received(address operator, address from, number tokenId, bytes data);
}
contract KortanaPass {
// Mandated KRS-721 Storage Slots (Slots 0..3)
map<number, address> owners; // Slot 0
map<address, number> counts; // Slot 1
map<number, address> approvals; // Slot 2
map<address, map<address, truth>> operators; // Slot 3
// Custom Application State (Slots 4+)
address owner;
number minted;
number maxSupply;
number mintPrice;
map<number, text> uris;
// Standard ERC-721 Events
event Transfer(address indexed from, address indexed to, number indexed tokenId);
event Approval(address indexed owner, address indexed approved, number indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, truth approved);
constructor {
owner = caller;
minted = 0;
maxSupply = 10000;
mintPrice = 10000000000000000; // 0.01 KTN in wei
}
// Identification & Metadata
reads truth supportsInterface(bytes4 interfaceId) {
// 0x80ac58cd (ERC-721) or 0x01ffc9a7 (ERC-165)
return interfaceId == 0x80ac58cd00000000000000000000000000000000000000000000000000000000
|| interfaceId == 0x01ffc9a700000000000000000000000000000000000000000000000000000000;
}
reads number krsStandard() { return 721; }
reads text name() { return "Kortana Founder Pass"; }
reads text symbol() { return "KPASS"; }
reads text tokenURI(number tokenId) {
address holder = owners[tokenId];
require holder != nobody, "token does not exist";
return uris[tokenId];
}
// Read Queries
reads number balanceOf(address holder) {
require holder != nobody, "query for zero address";
return counts[holder];
}
reads address ownerOf(number tokenId) {
address holder = owners[tokenId];
require holder != nobody, "no such token";
return holder;
}
reads address getApproved(number tokenId) {
require owners[tokenId] != nobody, "no such token";
return approvals[tokenId];
}
reads truth isApprovedForAll(address holder, address operator) {
return operators[holder][operator];
}
reads number totalSupply() {
return minted;
}
// Minting
writes number mint(address recipient, text metadataUri) {
require recipient != nobody, "cannot mint to nobody";
require minted < maxSupply, "collection is sold out";
require sentAmount >= mintPrice, "insufficient payment";
number tokenId = minted + 1;
minted = tokenId;
owners[tokenId] = recipient;
counts[recipient] = counts[recipient] + 1;
uris[tokenId] = metadataUri;
emit Transfer(nobody, recipient, tokenId);
return tokenId;
}
// Approvals & Transfers
writes truth approve(address to, number tokenId) {
address holder = owners[tokenId];
require holder != nobody, "no such token";
if (caller != holder) {
require operators[holder][caller], "not owner nor operator";
}
approvals[tokenId] = to;
emit Approval(holder, to, tokenId);
return yes;
}
writes truth setApprovalForAll(address operator, truth approved) {
require operator != caller, "cannot approve yourself";
operators[caller][operator] = approved;
emit ApprovalForAll(caller, operator, approved);
return yes;
}
writes truth transferFrom(address from, address to, number tokenId) {
address holder = owners[tokenId];
require holder != nobody, "no such token";
require holder == from, "from is not token owner";
require to != nobody, "transfer to nobody";
if (caller != holder) {
if (caller != approvals[tokenId]) {
require operators[holder][caller], "not authorized";
}
}
// Clear approval on transfer to prevent token reuse drains
approvals[tokenId] = nobody;
owners[tokenId] = to;
counts[from] = counts[from] - 1;
counts[to] = counts[to] + 1;
emit Transfer(from, to, tokenId);
return yes;
}
// Safe transfer (overload with empty data bytes)
writes truth safeTransferFrom(address from, address to, number tokenId) {
bytes emptyData = bytes(0);
return safeTransferFrom(from, to, tokenId, emptyData);
}
// Safe transfer with contract receiver hook
writes truth safeTransferFrom(address from, address to, number tokenId, bytes data) {
// Perform state transfer
transferFrom(from, to, tokenId);
// Reflection guard: only call receiver hook if recipient is a smart contract
if (hasCode(to)) {
number answer = IERC721Receiver(to).onERC721Received(caller, from, tokenId, data);
// Must return magic selector 0x150b7a02
require answer == 0x150b7a0200000000000000000000000000000000000000000000000000000000,
"receiver contract rejected token";
}
return yes;
}
}Deconstructing the Implementation
- Mandatory Storage Prefix: Slots 0 through 3 are occupied by
owners,counts,approvals, andoperators. This ordering guarantees that external tools and explorers computingkeccak256(tokenId . 0)can locate token owners without custom ABI configuration. - The
hasCode(to)Reflection Guard: InsafeTransferFrom, the contract checks whether the recipient address contains executable code before dispatchingonERC721Received. Regular user wallets have no bytecode; calling a receiver hook on an ordinary account would revert the transaction. ThehasCodeguard allows transfers to user wallets to succeed while still protecting against sending tokens to smart contracts that cannot move them. - Clearing Approvals on Transfer: In
transferFrom,approvals[tokenId]is explicitly reset tonobody. If this reset were omitted, an approved marketplace or spender could steal the token from the new buyer after a trade. - Payment Enforcement (
sentAmount): Themintmethod checkssentAmount >= mintPricebefore incrementingminted, ensuring that payments in native KTN are validated before state changes occur.
31.3 Example: Fungible Token with Mint & Burn (KRS-20)
KRS-20 is the standard for interchangeable, fungible tokens (currencies, staking shares, governance tokens) with ERC-20 parity.
Problem & Motivation
Fungible assets require atomic balance transfers, third-party spending allowances (for automated routers and decentralized exchanges), and balance conservation (the sum of all balances must always equal the total supply).
Contract Implementation (CommunityToken.ql)
contract CommunityToken {
// Mandated KRS-20 Storage Slots (Slots 0..2)
map<address, number> balances; // Slot 0
map<address, map<address, number>> allowances; // Slot 1
number supply; // Slot 2
// Custom Application State (Slots 3+)
address admin;
number maxCap;
event Transfer(address indexed from, address indexed to, number value);
event Approval(address indexed owner, address indexed spender, number value);
event Mint(address indexed to, number amount);
event Burn(address indexed from, number amount);
constructor {
admin = caller;
maxCap = 100000000000000000000000000; // 100 million cap (18 decimals)
// Initial supply to deployer: 1,000,000 tokens
number initialSupply = 1000000000000000000000000;
supply = initialSupply;
balances[caller] = initialSupply;
emit Transfer(nobody, caller, initialSupply);
}
// Standard Identity & Metadata
reads number krsStandard() { return 20; }
reads text name() { return "Community Governance Token"; }
reads text symbol() { return "COMM"; }
reads number decimals() { return 18; }
// Read Methods
reads number totalSupply() { return supply; }
reads number balanceOf(address owner) { return balances[owner]; }
reads number allowance(address owner, address spender) { return allowances[owner][spender]; }
// Write Methods
writes truth approve(address spender, number value) {
allowances[caller][spender] = value;
emit Approval(caller, spender, value);
return yes;
}
writes truth transfer(address to, number value) {
require to != nobody, "transfer to nobody";
number held = balances[caller];
require held >= value, "insufficient balance";
balances[caller] = held - value;
balances[to] = balances[to] + value;
emit Transfer(caller, to, value);
return yes;
}
writes truth transferFrom(address from, address to, number value) {
require to != nobody, "transfer to nobody";
number held = balances[from];
require held >= value, "insufficient balance";
if (caller != from) {
number allowed = allowances[from][caller];
require allowed >= value, "insufficient allowance";
allowances[from][caller] = allowed - value;
}
balances[from] = held - value;
balances[to] = balances[to] + value;
emit Transfer(from, to, value);
return yes;
}
// Application Extensions: Mint and Burn
writes truth mint(address recipient, number amount) {
require caller == admin, "only admin can mint";
require recipient != nobody, "cannot mint to nobody";
require supply + amount <= maxCap, "exceeds maximum cap";
supply = supply + amount;
balances[recipient] = balances[recipient] + amount;
emit Mint(recipient, amount);
emit Transfer(nobody, recipient, amount);
return yes;
}
writes truth burn(number amount) {
number held = balances[caller];
require held >= amount, "burn exceeds balance";
balances[caller] = held - amount;
supply = supply - amount;
emit Burn(caller, amount);
emit Transfer(caller, nobody, amount);
return yes;
}
}Deconstructing the Implementation
- Checked Balance Transfers: The statement
balances[caller] = held - value;utilizes Quorlin's default checked arithmetic. Ifvalue > held, execution halts immediately. - Allowance Spending: In
transferFrom, ifcaller != from, the allowance is decreased byvaluewhile re-checking thatallowed >= value. If the owner callstransferFromon their own account, allowance checks are bypassed. - Cap Guarding: The
mintfunction enforcessupply + amount <= maxCap, preventing governance dilution beyond the hard-coded maximum supply. - Audit Trail: Every mint emits both a custom
Mintevent and a canonicalTransfer(nobody, recipient, amount)event so that external portfolio trackers detect newly issued tokens.
31.4 Example: Multi-Token Game Inventory (KRS-1155)
KRS-1155 provides a multi-token standard for handling fungible and non-fungible items within a single smart contract.
Problem & Motivation
In gaming and fractional asset protocols, deploying separate contract addresses for every sword, shield, gold coin, or potion creates massive gas costs and storage fragmentation. KRS-1155 pools all items under one contract and enables atomic batch transfers.
Contract Implementation (GameInventory.ql)
interface IERC1155Receiver {
writes number onERC1155Received(address operator, address from, number id, number amount, bytes data);
writes number onERC1155BatchReceived(address operator, address from, list<number> ids, list<number> amounts, bytes data);
}
contract GameInventory {
// Mandated storage layout (slots 0..1)
map<number, map<address, number>> balances; // Slot 0: [tokenId][owner] -> amount
map<address, map<address, truth>> operatorApprovals; // Slot 1: [owner][operator] -> approved
// Custom state
address gameMaster;
map<number, text> uris;
event TransferSingle(address indexed operator, address indexed from, address indexed to, number id, number value);
event ApprovalForAll(address indexed owner, address indexed operator, truth approved);
constructor {
gameMaster = caller;
}
reads truth supportsInterface(bytes4 interfaceId) {
return interfaceId == 0xd9b67a2600000000000000000000000000000000000000000000000000000000; // ERC-1155
}
reads number balanceOf(address owner, number id) {
return balances[id][owner];
}
reads truth isApprovedForAll(address owner, address operator) {
return operatorApprovals[owner][operator];
}
writes truth setApprovalForAll(address operator, truth approved) {
require operator != caller, "cannot approve yourself";
operatorApprovals[caller][operator] = approved;
emit ApprovalForAll(caller, operator, approved);
return yes;
}
// Minting items (Fungible currencies or 1-of-1 gear)
writes truth mintItem(address player, number itemId, number amount, text itemUri) {
require caller == gameMaster, "only game master";
require player != nobody, "cannot mint to nobody";
balances[itemId][player] = balances[itemId][player] + amount;
uris[itemId] = itemUri;
emit TransferSingle(caller, nobody, player, itemId, amount);
return yes;
}
writes truth safeTransferFrom(address from, address to, number id, number amount, bytes data) {
require to != nobody, "transfer to nobody";
if (caller != from) {
require operatorApprovals[from][caller], "not authorized";
}
number held = balances[id][from];
require held >= amount, "insufficient balance";
balances[id][from] = held - amount;
balances[id][to] = balances[id][to] + amount;
emit TransferSingle(caller, from, to, id, amount);
// Safe receiver hook check
if (hasCode(to)) {
number answer = IERC1155Receiver(to).onERC1155Received(caller, from, id, amount, data);
require answer == 0xf23a6e6100000000000000000000000000000000000000000000000000000000,
"receiver rejected item";
}
return yes;
}
}Deconstructing the Implementation
- Dual-Key Storage Structure: The
balancesmapping is declared asmap<number, map<address, number>>. The first key is thetokenId, and the second key is the useraddress. Ifamount == 1, the token behaves as a non-fungible asset; ifamount > 1, it acts as a fungible resource (like gold coins). - Universal Operator Approval: Rather than approving spenders token-by-token,
setApprovalForAllauthorizes a game router or auction house to manage all items owned by the caller. - Receiver Verification: On contract transfers,
safeTransferFromexpects the recipient contract to return the 4-byte selector0xf23a6e61(bytes4(keccak256("onERC1155Received(...)"))).
31.5 Example: Real-World Asset (RWA) Financing (KRS-1579)
KRS-1579 establishes a lifecycle state machine for physical assets, receivables, and invoices, verified live against on-chain attestations (KRS-6821).
Problem & Motivation
Tokenizing physical real-world assets (such as freight invoices or real estate) requires strict legal disclosure: on-chain tokens are operational records, not legal title. Furthermore, an asset cannot be financed if its off-chain custody or KYC validation has lapsed.
Contract Implementation (InvoiceVault.ql)
// Interface to verify external legal/KYC attestations
interface IAttestationRegistry {
reads truth isValid(number attestationId);
}
contract InvoiceVault {
number invoiceValue;
address custodian;
address attestationRegistry;
number attestationId;
number status; // 0 = Registered, 1 = Financed, 2 = Settled, 3 = Defaulted
event InvoiceRegistered(number value, number attestationId);
event InvoiceFinanced();
event InvoiceSettled();
constructor {
custodian = caller;
}
reads number krsStandard() { return 1579; }
writes truth registerInvoice(number value, address registry, number attestId) {
require caller == custodian, "only custodian";
require status == 0, "already registered";
// Invariant: Verify the invoice attestation is currently valid on chain
require IAttestationRegistry(registry).isValid(attestId), "invalid attestation";
invoiceValue = value;
attestationRegistry = registry;
attestationId = attestId;
status = 0;
emit InvoiceRegistered(value, attestId);
return yes;
}
writes truth financeInvoice() {
require caller == custodian, "only custodian";
require status == 0, "must be registered";
// Live check: Attestations revoked or expired prior to funding block the transaction!
require IAttestationRegistry(attestationRegistry).isValid(attestationId),
"attestation expired or revoked";
status = 1; // Financed
emit InvoiceFinanced();
return yes;
}
writes truth settleInvoice() {
require caller == custodian, "only custodian";
require status == 1, "must be financed";
status = 2; // Settled
emit InvoiceSettled();
return yes;
}
}Deconstructing the Implementation
- Live Attestation Verification: Notice that
financeInvoicedoes not rely on a boolean flag stored during registration. It performs a live external call toIAttestationRegistry.isValid(attestationId). If the custodian or regulatory authority revoked the invoice's credential between registration and funding, financing reverts immediately. - Deterministic State Transitions: State moves strictly forward through three sequential statuses:
Registered (0)──►Financed (1)──►Settled (2). Skipping steps or financing an already settled invoice is rejected byrequire status == ...checks.
31.6 Example: Delegated Authorization & Session Grants (KRS-2186)
KRS-2186 implements capability-based delegated authorization.
Problem & Motivation
Users wanting gasless transactions, automated trading bots, or in-game session keys should never export their private keys. KRS-2186 allows accounts to grant scoped, gas-metered execution permissions with automatic time expiration.
Contract Implementation (GaslessRelayer.ql)
record Grant {
address grantor;
address grantee;
number limit;
number spent;
number expiresAt; // 0 = no expiry
truth revoked;
number scopeHash;
}
contract GaslessRelayer {
map<number, Grant> grants;
number nextGrantId;
event GrantCreated(number indexed grantId, address indexed grantor, address indexed grantee, number limit);
event GrantUsed(number indexed grantId, address indexed grantee, number amount);
event GrantRevoked(number indexed grantId, address indexed by);
reads number krsStandard() { return 2186; }
reads truth isValid(number grantId) {
Grant g = grants[grantId];
if (g.grantee == nobody) { return no; }
if (g.revoked) { return no; }
if (g.expiresAt != 0 and blockTime > g.expiresAt) { return no; }
return g.spent < g.limit;
}
writes number createGrant(address grantee, number limit, number expiresAt, number scopeHash) {
require grantee != nobody, "grantee is nobody";
require limit > 0, "limit must be positive";
number id = nextGrantId;
nextGrantId = id + 1;
grants[id].grantor = caller;
grants[id].grantee = grantee;
grants[id].limit = limit;
grants[id].spent = 0;
grants[id].expiresAt = expiresAt;
grants[id].revoked = no;
grants[id].scopeHash = scopeHash;
emit GrantCreated(id, caller, grantee, limit);
return id;
}
writes truth useGrant(number grantId, number amount) {
Grant g = grants[grantId];
require caller == g.grantee, "caller not grantee";
require isValid(grantId), "grant not valid";
require g.spent + amount <= g.limit, "limit exceeded";
g.spent = g.spent + amount;
grants[grantId] = g;
emit GrantUsed(grantId, caller, amount);
return yes;
}
writes truth revokeGrant(number grantId) {
Grant g = grants[grantId];
require caller == g.grantor, "only grantor can revoke";
require g.revoked == no, "already revoked";
grants[grantId].revoked = yes;
emit GrantRevoked(grantId, caller);
return yes;
}
}Deconstructing the Implementation
- The
record GrantCompound Struct: Bundles grantor identity, grantee address, spend allowances, expiry timestamp, and ascopeHash(the hash of allowed action selectors). - Live Headroom & Expiration Checks: The read method
isValid(grantId)checks four constraints simultaneously:- The grant exists (
grantee != nobody). - The grant is not revoked (
revoked == no). - The current block timestamp has not surpassed the expiry deadline (
blockTime <= expiresAt). - The cumulative spend has not hit the ceiling (
spent < limit).
- The grant exists (
- Spending Control: Every time
useGrantis called by the delegate,spentincreases. Oncespent + amount > limit, the grant refuses further execution. - Instant Revocation: The grantor can unilaterally terminate the grant at any block by invoking
revokeGrant, immediately invalidating subsequent calls.
31.7 Example: Formalized Obligation & Debt (KRS-4317)
KRS-4317 defines structured debt instruments, promissory notes, and bilateral credit obligations.
Problem & Motivation
DeFi lending often deals with pooled collateral, but peer-to-peer loans, supplier trade credit, and corporate bonds need individualized repayment tracking, maturity dates, and automated default evaluation.
Contract Implementation (PromissoryLoan.ql)
record Obligation {
address obligor; // debtor
address obligee; // creditor
address token;
number amount;
number repaid;
number dueBy;
number status; // 0 = Open, 1 = Settled, 2 = Defaulted
}
contract PromissoryLoan {
map<number, Obligation> obligations;
number nextObligationId;
event LoanCreated(number indexed id, address indexed obligor, address indexed obligee, number amount, number dueBy);
event LoanRepaid(number indexed id, address indexed by, number amount);
event LoanDefaulted(number indexed id);
reads number krsStandard() { return 4317; }
reads truth isDefaulted(number id) {
Obligation o = obligations[id];
if (o.status != 0) { return no; }
if (o.dueBy == 0) { return no; }
return blockTime > o.dueBy;
}
writes number createLoan(address debtor, address tokenAddress, number amount, number dueBy) {
require debtor != nobody, "debtor cannot be nobody";
require amount > 0, "amount must be positive";
number id = nextObligationId;
nextObligationId = id + 1;
obligations[id].obligor = debtor;
obligations[id].obligee = caller;
obligations[id].token = tokenAddress;
obligations[id].amount = amount;
obligations[id].repaid = 0;
obligations[id].dueBy = dueBy;
obligations[id].status = 0;
emit LoanCreated(id, debtor, caller, amount, dueBy);
return id;
}
writes truth repayLoan(number id, number amount) {
Obligation o = obligations[id];
require o.status == 0, "loan not open";
o.repaid = o.repaid + amount;
if (o.repaid >= o.amount) {
o.status = 1; // Settled
}
obligations[id] = o;
emit LoanRepaid(id, caller, amount);
return yes;
}
}Deconstructing the Implementation
- Bilateral Parties: The contract explicitly identifies
obligor(the borrowing entity obligated to repay) andobligee(the lender or creditor holding the debt claim). - Live Default Calculation: In
isDefaulted, default is evaluated dynamically againstblockTime > o.dueBywithout needing an off-chain oracle or cron job to flip a stored flag. - Partial Repayment & Settlement: The
repayLoanmethod incrementsrepaid. Once cumulative repayments meet or exceedamount, the status advances to1(Settled).
31.8 Example: Verifiable Attestation Registry (KRS-6821)
KRS-6821 provides an on-chain registry for cryptographic attestations, identity claims, and compliance verifications.
Problem & Motivation
DeFi protocols frequently require compliance checks (e.g., verifying that a trader is not in a sanctioned jurisdiction, or confirming accredited investor status) without storing private personal data directly on chain.
Contract Implementation (KYCCredentialRegistry.ql)
record Attestation {
address issuer;
address subject;
number claimType; // identifier or hash of claim type
number claimHash; // keccak256 hash of credential data
number issuedAt;
number revokedAt; // 0 = active
}
contract KYCCredentialRegistry {
map<number, Attestation> attestations;
number nextAttestationId;
event AttestationIssued(number indexed id, address indexed issuer, address indexed subject);
event AttestationRevoked(number indexed id, address indexed issuer);
reads number krsStandard() { return 6821; }
reads truth isValid(number id) {
Attestation a = attestations[id];
if (a.issuer == nobody) { return no; }
return a.revokedAt == 0;
}
writes number issueAttestation(address subject, number claimType, number claimHash) {
require subject != nobody, "subject cannot be nobody";
require claimHash != 0, "empty claim hash";
number id = nextAttestationId;
nextAttestationId = id + 1;
attestations[id].issuer = caller;
attestations[id].subject = subject;
attestations[id].claimType = claimType;
attestations[id].claimHash = claimHash;
attestations[id].issuedAt = blockTime;
attestations[id].revokedAt = 0;
emit AttestationIssued(id, caller, subject);
return id;
}
writes truth revokeAttestation(number id) {
Attestation a = attestations[id];
require caller == a.issuer, "only issuer can revoke";
require a.revokedAt == 0, "already revoked";
attestations[id].revokedAt = blockTime;
emit AttestationRevoked(id, caller);
return yes;
}
}Deconstructing the Implementation
- Privacy Preservation: The contract records
claimHash—a cryptographic hash of the off-chain credential document. No personal identification data (names, passport numbers, tax IDs) is stored on the public blockchain. - Issuer Authority: Anyone can record an attestation; its credibility depends on the address of the
issuer. Consuming contracts inspecta.issuerto ensure it matches their approved auditor or verification authority. - Instant Revocation Mechanism: Setting
revokedAt = blockTimeimmediately causesisValidto returnno, disabling downstream permissions across all integrating contracts within the same block.
31.9 Example: Structured Milestone Payments (KRS-7743)
KRS-7743 formalizes milestone disbursements, conditional escrow releases, and automated invoicing.
Problem & Motivation
Contractors, software teams, and service providers often work on deliverables. Releasing total compensation upfront creates counterparty risk, while post-delivery payments risk non-payment. KRS-7743 locks funds in escrow and releases them as milestones are completed.
Contract Implementation (MilestoneEscrow.ql)
record PaymentOrder {
address payer;
address payee;
address token;
number amount;
number reference;
number status; // 0 = Pending, 1 = Released, 2 = Cancelled
}
contract MilestoneEscrow {
map<number, PaymentOrder> payments;
number nextPaymentId;
event PaymentScheduled(number indexed id, address indexed payer, address indexed payee, number amount);
event PaymentReleased(number indexed id, address indexed payee, number amount);
event PaymentCancelled(number indexed id);
reads number krsStandard() { return 7743; }
writes number schedulePayment(address payee, address token, number amount, number reference) {
require payee != nobody, "payee cannot be nobody";
require amount > 0, "amount must be positive";
number id = nextPaymentId;
nextPaymentId = id + 1;
payments[id].payer = caller;
payments[id].payee = payee;
payments[id].token = token;
payments[id].amount = amount;
payments[id].reference = reference;
payments[id].status = 0;
emit PaymentScheduled(id, caller, payee, amount);
return id;
}
writes truth releaseMilestone(number id) {
PaymentOrder p = payments[id];
require caller == p.payer, "only payer can release";
require p.status == 0, "payment not pending";
payments[id].status = 1;
emit PaymentReleased(id, p.payee, p.amount);
return yes;
}
}Deconstructing the Implementation
- Separation of Commitments:
schedulePaymentrecords the payer's explicit commitment, identifying the designated contractor (payee), currency token address, agreed payout, and an external reference number (e.g., ticket ID or invoice hash). - Guarded Release: In
releaseMilestone, the checkcaller == p.payerprevents unauthorized third parties or the payee from withdrawing funds prematurely. - Replay Protection: Updating
p.status = 1ensures that a payment order cannot be released more than once.
31.10 Example: Programmable Escrow with Arbiter (KRS-9064)
KRS-9064 provides multi-party conditional escrow with dispute arbitration and deadline-based refund windows.
Problem & Motivation
In over-the-counter (OTC) token trading or physical good exchanges, neither party wants to send first. A trusted third-party arbiter can resolve disputes, while a deadline guarantees the buyer can retrieve deposited funds if the seller disappears.
Contract Implementation (PeerToPeerEscrow.ql)
record TradeEscrow {
address buyer;
address seller;
address arbiter;
number amount;
number deadline;
number status; // 0 = Locked, 1 = Released, 2 = Refunded, 3 = Disputed
}
contract PeerToPeerEscrow {
map<number, TradeEscrow> escrows;
number nextEscrowId;
event EscrowLocked(number indexed id, address indexed buyer, address indexed seller, number amount);
event EscrowReleased(number indexed id);
event EscrowRefunded(number indexed id);
event EscrowDisputed(number indexed id);
reads number krsStandard() { return 9064; }
writes number openEscrow(address seller, address arbiter, number deadline) {
require seller != nobody, "seller cannot be nobody";
require sentAmount > 0, "must fund escrow";
number id = nextEscrowId;
nextEscrowId = id + 1;
escrows[id].buyer = caller;
escrows[id].seller = seller;
escrows[id].arbiter = arbiter;
escrows[id].amount = sentAmount;
escrows[id].deadline = deadline;
escrows[id].status = 0;
emit EscrowLocked(id, caller, seller, sentAmount);
return id;
}
writes truth releaseToSeller(number id) {
TradeEscrow e = escrows[id];
require caller == e.buyer or caller == e.arbiter, "unauthorized to release";
require e.status == 0 or e.status == 3, "invalid escrow state";
escrows[id].status = 1;
emit EscrowReleased(id);
return yes;
}
writes truth refundToBuyer(number id) {
TradeEscrow e = escrows[id];
if (caller == e.buyer) {
require blockTime > e.deadline, "deadline not reached";
} else {
require caller == e.arbiter, "only buyer after timeout or arbiter";
}
require e.status == 0 or e.status == 3, "invalid escrow state";
escrows[id].status = 2;
emit EscrowRefunded(id);
return yes;
}
}Deconstructing the Implementation
- Atomic Funding: The buyer invokes
openEscrowwith attached native tokens (sentAmount > 0), locking funds directly into contract storage. - Dual-Authority Release: Funds can be released to the seller either voluntarily by the
buyerupon receipt of goods, or by thearbiterif a dispute was resolved in the seller's favor. - Timeout-Protected Refund: If the seller fails to deliver and the deadline expires (
blockTime > e.deadline), the buyer can trigger a refund unilaterally without needing the arbiter or seller's consent.
31.11 Example: Continuous Micro-Payment Streaming (KRS-3311)
KRS-3311 enables continuous second-by-second token streaming.
Problem & Motivation
Billing for cloud computing, bandwidth consumption, VPN tunnels, or energy metering by sending individual on-chain transactions every second would congest the network and cost astronomical gas fees. KRS-3311 resolves this by calculating claimable earnings dynamically on withdrawal using constant-time O(1) calculation.
Contract Implementation (BandwidthStreamer.ql)
record PaymentStream {
address payer;
address recipient;
number ratePerSecond;
number deposited;
number withdrawn;
number startedAt;
number status; // 0 = Open, 1 = Closed
}
contract BandwidthStreamer {
map<number, PaymentStream> streams;
number nextStreamId;
event StreamOpened(number indexed streamId, address indexed payer, address indexed recipient);
event StreamWithdrawn(number indexed streamId, address indexed recipient, number amount);
reads number krsStandard() { return 3311; }
reads number claimable(number streamId) {
PaymentStream s = streams[streamId];
if (s.status == 1) { return 0; }
number duration = blockTime - s.startedAt;
number totalEarned = duration * s.ratePerSecond;
if (totalEarned > s.deposited) {
totalEarned = s.deposited;
}
if (totalEarned <= s.withdrawn) {
return 0;
}
return totalEarned - s.withdrawn;
}
writes number withdraw(number streamId) {
PaymentStream s = streams[streamId];
require caller == s.recipient, "not recipient";
number available = claimable(streamId);
require available > 0, "nothing to withdraw";
s.withdrawn = s.withdrawn + available;
streams[streamId] = s;
emit StreamWithdrawn(streamId, caller, available);
return available;
}
}Deconstructing the Implementation
- Constant-Time O(1) Accrual Calculation:
No loops, no periodic cron updates, and zero state bloat. Whether 10 seconds or 10 months have elapsed, calculating the payout requires only one multiplication and subtraction.code
claimable = min(deposited, (blockTime - startedAt) * ratePerSecond) - withdrawn - Cap Guarding:
totalEarnedis clamped ats.deposited, ensuring that a stream never permits withdrawals beyond the amount originally deposited by the payer. - Continuous Partial Withdrawals: The recipient can withdraw accrued funds whenever desired.
withdrawnaccumulates over time without resettingstartedAt.
31.12 Example: Hardware Device Registry (KRS-5502)
KRS-5502 pairs physical IoT hardware (solar inverters, cellular hotspots, environmental sensors) directly with on-chain identities.
Problem & Motivation
Decentralized Physical Infrastructure Networks (DePIN) rely on real-world devices generating telemetry. To prevent spoofing, devices must sign their data with hardware cryptographic keys embedded inside Trusted Execution Environments (TEE/TPM).
Contract Implementation (SolarDeviceRegistry.ql)
record DeviceRecord {
address owner;
address operator;
address signingKey;
number deviceClass;
number registeredAt;
number status; // 0 = Active, 1 = Revoked, 2 = Suspended
}
contract SolarDeviceRegistry {
map<number, DeviceRecord> devices;
number nextDeviceId;
event DeviceRegistered(number indexed deviceId, address indexed owner, address indexed signingKey);
event DeviceRevoked(number indexed deviceId);
reads number krsStandard() { return 5502; }
reads truth isActive(number deviceId) {
return devices[deviceId].status == 0;
}
reads address signingKeyOf(number deviceId) {
return devices[deviceId].signingKey;
}
writes number registerDevice(address operator, address signingKey, number deviceClass) {
require signingKey != nobody, "signing key cannot be nobody";
number id = nextDeviceId;
nextDeviceId = id + 1;
devices[id].owner = caller;
devices[id].operator = operator;
devices[id].signingKey = signingKey;
devices[id].deviceClass = deviceClass;
devices[id].registeredAt = blockTime;
devices[id].status = 0;
emit DeviceRegistered(id, caller, signingKey);
return id;
}
writes truth revokeDevice(number deviceId) {
require caller == devices[deviceId].owner, "only device owner can revoke";
require devices[deviceId].status == 0, "not active";
devices[deviceId].status = 1; // Revoked
emit DeviceRevoked(deviceId);
return yes;
}
}Deconstructing the Implementation
- Owner vs. Operator Separation: The
ownerholds administrative authority (e.g. key rotation and revocation), while theoperatoris the entity or smart contract managing the daily device fleet. - Hardware Signing Key:
signingKeycorresponds to the public key generated inside the physical device's secure element. External verifiers match signatures againstsigningKeyOf(deviceId). - Revocation Protection: Once
statusis set to1(Revoked),isActivereturnsno, immediately cutting off the compromised hardware from protocol rewards or downstream data acceptance.
31.13 Example: Telemetry Merkle Commitments (KRS-8290)
KRS-8290 allows DePIN networks to commit cryptographic Merkle roots of large sensor datasets on chain.
Problem & Motivation
IoT sensors generate thousands of readings per minute. Storing every reading on chain would overwhelm storage and gas limits. Instead, nodes aggregate readings into an off-chain Merkle tree and post a single 32-byte Merkle root on chain for verification.
Contract Implementation (SensorBatchCommitment.ql)
interface IDeviceRegistry {
reads truth isActive(number deviceId);
}
record TelemetryBatch {
address committer;
number deviceId;
number merkleRoot;
number leafCount;
number committedAt;
number status; // 0 = Committed, 1 = Challenged, 2 = Finalized
}
contract SensorBatchCommitment {
map<number, TelemetryBatch> batches;
number nextBatchId;
address deviceRegistry;
event BatchCommitted(number indexed batchId, number indexed deviceId, number merkleRoot, number count);
constructor {
deviceRegistry = caller;
}
reads number krsStandard() { return 8290; }
writes truth setRegistry(address reg) {
require deviceRegistry == caller, "only admin";
deviceRegistry = reg;
return yes;
}
writes number commitBatch(number deviceId, number merkleRoot, number leafCount) {
// Invariant: Verify the physical sensor device is active in the registry
require IDeviceRegistry(deviceRegistry).isActive(deviceId), "device is not active";
require merkleRoot != 0, "empty merkle root";
number id = nextBatchId;
nextBatchId = id + 1;
batches[id].committer = caller;
batches[id].deviceId = deviceId;
batches[id].merkleRoot = merkleRoot;
batches[id].leafCount = leafCount;
batches[id].committedAt = blockTime;
batches[id].status = 0;
emit BatchCommitted(id, deviceId, merkleRoot, leafCount);
return id;
}
}Deconstructing the Implementation
- Hardware Cross-Validation: Before accepting a telemetry batch root,
commitBatchcallsIDeviceRegistry(deviceRegistry).isActive(deviceId). A decommissioned or revoked sensor cannot submit data proofs. - Merkle Root Representation: The
merkleRootstores the cryptographic root hash of all leaves in that batch, enabling off-chain auditors to prove any single reading's inclusion using a compact Merkle branch proof. - Dispute Windows: Batches are recorded with
committedAt = blockTime, establishing an on-chain timeline for challenge and finalization windows.
31.14 Complete KRS Developer Reference Matrix
| Standard ID | Tier | Name | Mandatory Storage Prefix | Standard Selectors / Methods | Common Use Cases |
|---|---|---|---|---|---|
KRS-20 | Tier 1 | Fungible Token | balances, allowances, supply | totalSupply(), balanceOf(), transfer(), approve() | Currencies, rewards, governance tokens |
KRS-721 | Tier 1 | Non-Fungible Token | owners, counts, approvals, operators | ownerOf(), safeTransferFrom(), tokenURI() | Digital collectibles, gaming items, domain names |
KRS-1155 | Tier 1 | Multi-Token | balances, operatorApprovals | balanceOf(), safeTransferFrom(), safeBatchTransferFrom() | In-game inventories, fractional real estate, bundle passes |
KRS-1579 | Tier 2 | Real-World Asset | Custom | registerAsset(), finance(), redeem() | Tokenized real estate, invoices, commodity receipts |
KRS-2186 | Tier 2 | Delegated Auth | Custom | createGrant(), useGrant(), revokeGrant() | Gasless meta-transactions, smart account session keys |
KRS-3311 | Tier 3 | Streaming Settlement | streams, nextStreamId | claimable(), withdraw(), openStream() | DePIN bandwidth, energy metering, SaaS subscriptions |
KRS-4317 | Tier 2 | Obligation & Debt | Custom | createLoan(), repayLoan(), isDefaulted() | Undercollateralized loans, corporate credit lines |
KRS-5502 | Tier 3 | Device Registry | devices, nextDeviceId | registerDevice(), signingKeyOf(), revokeDevice() | IoT hardware identity, smart meter telemetry |
KRS-6821 | Tier 2 | Attestation Registry | Custom | issueAttestation(), isValid(), revokeAttestation() | KYC/AML verification, accreditation proofs |
KRS-7743 | Tier 2 | Structured Payment | Custom | schedulePayment(), releaseMilestone() | Escrow milestones, royalty splits, automated vesting |
KRS-8290 | Tier 3 | Telemetry Commitment | Custom | commitBatch(), setRegistry() | DePIN sensor data proof, environmental audit logs |
KRS-9064 | Tier 2 | Programmable Escrow | Custom | openEscrow(), releaseToSeller(), refundToBuyer() | Over-the-counter trades, freelance payments |