KANN.tech
DocsBlogContact

Overview

  • Introduction
  • Alpha Demo

Components

  • KANN Compute
  • Issuance Workflow

Technical

  • Smart Contracts
  • API Reference

Overview

  • Introduction
  • Alpha Demo

Components

  • KANN Compute
  • Issuance Workflow

Technical

  • Smart Contracts
  • API Reference
Technical

Technical Architecture

Transparency through code

Every calculation, every compliance check, every ownership change - recorded permanently on-chain. Not in a database you can't see. Not in a spreadsheet that changes between versions. On a public blockchain where anyone can verify.

Why On-Chain Matters

Traditional asset management operates on trust. You trust the issuer to calculate correctly, to maintain proper records, to not modify historical data. That trust has failed investors repeatedly.

On-chain infrastructure changes the trust model:

  • Immutable record - once data is anchored, it cannot be altered or deleted
  • Open verification - anyone can audit, no special access required
  • Cryptographic proof - mathematical certainty, not institutional promises

The Trust Stack

Three smart contracts work together to secure your investment:

1.

AnchorRegistry

Locks every calculation result permanently. Your NAV, your cashflows, your payment schedules - all cryptographically sealed.

2.

Allowlist

Ensures only verified investors can hold and trade. Compliance built into the infrastructure, not bolted on after.

3.

PermissionedNoteToken

Your ownership, represented as a standard token. Tradeable, verifiable, linked to the anchored calculation state.

AnchorRegistry - The Audit Trail

Every time KANN Compute runs a calculation, the results are anchored here. This creates an append-only audit trail that even the issuer cannot modify.

What this means for you: When you want to verify a NAV calculation or payment schedule, you don't ask the issuer for records. You query the blockchain directly. The data is public, permanent, and cryptographically linked to the exact inputs that produced it.

IAnchorRegistry.solsolidity
interface IAnchorRegistry {
    event Anchored(
        uint256 indexed anchorId,
        bytes32 indexed canonicalAssetId,
        bytes32 inputHash,
        bytes32 outputHash,
        bytes32 issuerIdentityHash,
        bytes32 legalContractHash,
        bytes32 assetParamsHash,
        bytes32 modelHash,
        bytes32 witnessHash,
        address indexed submitter
    );

    function anchor(
        bytes32 inputHash,
        bytes32 outputHash,
        bytes32 issuerIdentityHash,
        bytes32 legalContractHash,
        bytes32 assetParamsHash,
        bytes32 modelHash,
        bytes32 witnessHash
    ) external returns (uint256 anchorId);

    function getAnchor(uint256 anchorId) external view returns (...);
    function latestAnchorForAsset(bytes32 canonicalAssetId) external view returns (uint256);
    function computeCanonicalAssetId(...) external pure returns (bytes32);
}

Key Properties

  • Anchors are immutable - no update, no delete, no exceptions
  • Every anchor links to a canonical asset identity
  • Multiple anchors can exist for the same asset (one per calculation)
  • All hashes are content-addressed - the hash proves the content

Allowlist - Compliance Built In

Security tokens have transfer restrictions by law. Most platforms enforce these with centralized checks that can fail, be bypassed, or be changed without notice.

What this means for you: The allowlist is code, not policy. Every eligibility decision is recorded on-chain. If you're eligible today, that fact is publicly verifiable. If your eligibility is revoked, that's recorded too - with a reason code and timestamp.

IAllowlist.solsolidity
interface IAllowlist {
    event EligibilityAdded(address indexed account, address indexed addedBy, bytes32 reason);
    event EligibilityRemoved(address indexed account, address indexed removedBy, bytes32 reason);

    function addEligibility(address account, bytes32 reason) external;
    function removeEligibility(address account, bytes32 reason) external;
    function addEligibilityBatch(address[] calldata accounts, bytes32 reason) external;
    function removeEligibilityBatch(address[] calldata accounts, bytes32 reason) external;

    function isEligible(address account) external view returns (bool);
    function canTransfer(address from, address to) external view returns (bool);
}

Key Properties

  • Binary eligibility - you're either on the list or not
  • Both parties must be eligible for a transfer to succeed
  • Every change emits an auditable event with reason code
  • No automatic expiration - explicit revocation required

PermissionedNoteToken - Your Ownership

This is the token you actually hold. It follows the ERC-20 standard (the same standard used by USDC, DAI, and thousands of other tokens), which means it works with existing wallets and infrastructure.

What this means for you: Your ownership is a real token on a real blockchain. It's not an entry in someone's database. It's not a PDF certificate. It's a cryptographic asset that you control with your private key, that can only be transferred according to the allowlist rules, and that's always linked to the latest anchored calculation state.

IPermissionedNoteToken.solsolidity
interface IPermissionedNoteToken is IERC20 {
    event AnchorStateUpdated(uint256 indexed previousAnchorId, uint256 indexed newAnchorId, address indexed updatedBy);
    event AllowlistUpdated(address indexed previousAllowlist, address indexed newAllowlist, address indexed updatedBy);
    event Minted(address indexed to, uint256 amount, address indexed mintedBy);
    event Burned(address indexed from, uint256 amount, address indexed burnedBy);
    event Paused(address indexed pausedBy);
    event Unpaused(address indexed unpausedBy);

    function canonicalAssetId() external view returns (bytes32);
    function anchorRegistry() external view returns (address);
    function allowlist() external view returns (address);
    function currentAnchorId() external view returns (uint256);
    function isPaused() external view returns (bool);

    function canTransfer(address from, address to, uint256 amount) external view returns (bool, string memory);
    function mint(address to, uint256 amount) external;
    function burn(address from, uint256 amount) external;
    function pause() external;
    function unpause() external;
    function updateAnchorState(uint256 newAnchorId) external;
    function updateAllowlist(address newAllowlist) external;
}

Key Properties

  • ERC-20 compatible - works with standard wallets and tooling
  • Every transfer checks the allowlist automatically
  • Linked to the AnchorRegistry for calculation state
  • Pausable for emergency situations (with on-chain record)

ERC Compatibility

The architecture aligns with established security token standards:

  • ERC-3643 (T-REX) - transfer restrictions via compliance modules
  • ERC-1404 - canTransfer function with reason codes

This isn't a proprietary system. It builds on years of security token development and integrates with existing compliance infrastructure.

KANN Assistant

Ask me anything about KANN

Tokenized private credit infrastructure

Suggested