Skip to main content

Native Program

A Nigo Native Program is a protocol program that validates state-transition rules for a PROGRAM_VALIDATED_CELL transaction. It is written in Solidity and runs as EVM bytecode, but unlike a general Ethereum smart contract, it does not mutate contract storage directly or call other accounts.

Its primary purpose is to separate business rules from hard-coded Java Core and storage logic, representing them instead as versioned artifacts with immutable descriptors.

Differences from a general EVM contract

AreaGeneral EVM contractNative Program
Execution purposeMutate application stateValidate declared StateCell transitions
RevisionGeneral Osaka profileParis, pinned in the descriptor
State accessEVM storage and account hostInputs and outputs in canonical context
External callsAllowedForbidden
SLOAD / SSTOREAllowedForbidden
Contract creationAllowedForbidden
ResultEVM state, logs, and return valueValidation result for authorization, state transitions, and events

Solidity and the EVM serve as the language and engine for deterministic validators. Core applies the actual ledger change only after exact-matching the Native Program result against the transaction's declared transition.

Execution flow

State-closed validator

A Native Program receives all required state through the transaction and the context built by Core:

  • chain ID, block height, and timestamp;
  • transaction hash, signer, and intent hash;
  • input and output StateCells;
  • signed asset scope;
  • Asset, Policy, and Supply views validated by Core;
  • method selector and arguments; and
  • protocol fee.

The runtime cannot use:

  • SLOAD or SSTORE;
  • account balance or code queries;
  • external calls;
  • contract creation; or
  • self-destruct.

Executable instructions are inspected before a runtime is installed in the registry. The inspection rejects forbidden behavior while correctly skipping PUSHn data rather than misinterpreting it as opcodes.

This structure prevents a validator from producing different results based on node-local databases or call order, and makes the access set derivable from transaction inputs and outputs.

Program identity and revision

Native Programs separate stable identity from immutable revisions.

ValueRole
programIdRevision-independent program identity and Program State namespace
revisionPositive UINT32 revision number
descriptorHashIdentity of one immutable revision descriptor
runtimeCodeHashContent address of the runtime bytecode
previousDescriptorHashLink to the previous descriptor in the revision chain

A transaction's ProgramInvocation signs all of the following:

programId
expectedRevision
expectedDescriptorHash
methodSelector
assetScopes
arguments

Execution is rejected if the registry's active revision differs from the revision and hash expected by the transaction. A PINNED consumer uses an exact revision; a FOLLOW_GOVERNED consumer resolves the available governance default at the execution height.

Registry and consensus state

Program identities, revision descriptors, runtimes, status, defaults, and authority schedules are stored in NATIVE_SYSTEM StateCells. Artifact manifests and classpath/filesystem loaders are inputs used to create that state during genesis or publication; they do not overwrite consensus state with a separate runtime catalog.

Runtimes are content-addressed by code hash, and (programId, revision, descriptorHash) forms the execution-cache key. Both admission and actual block execution validate the revision and hash.

Program classes and capabilities

A program class sets the upper bound on publication and activation privileges.

  • USER: a general validator installable through the public publication path
  • ASSET_CONTROLLER: a privileged program that validates Native Asset transitions
  • PROTOCOL: a protocol-level privileged program

A public USER installation cannot create privileged classes or capabilities. Asset Controller and Protocol classes must pass the governance and activator policy pinned by the profile.

Capabilities restrict the effects that a validator result may request. Returning a canonical result from bytecode does not grant authorization, event, or state-transition capabilities absent from the descriptor.

Built-in fungible asset controllers

Current artifacts include the Native Asset Registry and three controller tiers.

ProgramFunctionOrdinary owner transferRepresentative configuration
Asset RegistryRegisters non-zero Asset IDs and validates descriptors and zero supplyNot applicableRegistry
Basic ControllerAllowance approval/update/revoke and transferFromDirect CellNIGO
Mintable ControllerBasic plus mint/burnDirect CellBWGC example
Managed ControllerMintable plus controller-validated transferProgram-validated CellKRWN example

Representative asset names are display information that helps explain profiles. Consensus state stores exact programId, revision mode, revision, and descriptor hash rather than these strings.

The existence of a controller does not mean the policy for a particular security or asset is complete. Investor eligibility, transfer restrictions, freezes, forced transfers, rights exercises, and institutional integration require separate product and policy design and validation.

Lifecycle governance

A governed program can change revision and authority schedules through canonical lifecycle actions.

INSTALL
STAGE
ACTIVATE
SET_DEFAULT
DEACTIVATE
ROTATE_AUTHORITY
MIGRATE
ABORT

The action wire binds expected and target revisions, descriptor hashes, activation height, authority revision, lifecycle nonce, and deadline. The action hash is a content hash, not an independent authorization signature.

The fixed Lifecycle Extension is the stateful protocol boundary through which a general EVM contract may request a governance action.

address: 0x4e49474f00000000000000000000000000000001
ABI: requestLifecycle(bytes) -> bytes32

Only direct CALL, zero value, and the strict ABI are allowed. Authorization exact-matches the EVM frame's msg.sender against current StateCell authority; it does not trust tx.origin or a role encoded in calldata.

Consumed and produced Cells and events from an approved action bind into the transaction proof journal. All are rolled back if a parent frame reverts or runs out of gas. State or authority rejection is transaction-fatal so a contract cannot catch it and partially commit only the governance effect.

MIGRATE and ABORT fail closed while no current state-migration machine exists.

Public publication

Artifact publication and installation for a public USER Program use a separate Publication Extension.

address: 0x4e49474f00000000000000000000000000000002
ABI: requestPublication(bytes) -> bytes32
actions: PUBLISH, INSTALL_USER

PUBLISH writes the descriptor and runtime to content-addressed StateCells. INSTALL_USER derives a program ID from the chain ID, msg.sender, and salt, then installs published revision 1.

The public path can create only USER, IMMUTABLE, and capabilities within the allowed ceiling. It remains separate from privileged asset and protocol activation paths.

Artifacts

Each artifact revision contains:

FileRole
runtime.binDeployed runtime bytecode executed by NigoVM
manifest.jsonCompiler, identity, revision, hash, capability, and schema manifest
abi.jsonSolidity ABI for development and analysis
opcodes.txtRuntime opcode review material

The build pins the compiler profile and source/runtime hashes, then validates generated output as an exact gate. An operating node uses the validated runtime and descriptor rather than recompiling Solidity source.

Current boundaries

Current support scope
  • Current built-in Programs use immutable revision 1 by default.
  • Lifecycle scheduling and publication foundations do not imply that every business migration is implemented.
  • The Rust consumer is classified as SPECIFIED_NOT_IMPLEMENTED in canonical vectors.
  • The Native Program foundation alone does not automatically provide regulatory compliance for regulated assets or STO workflows.

Next