Skip to main content

Purpose and Scope

StableNet implements a two-layer governance system for minting and burning of the native stablecoin.
This architecture clearly separates authorization (who is allowed to be a minter) from execution (who can actually perform mint/burn operations):
  • GovMasterMinter: Approves and manages minter entities
  • GovMinter: Executes mint and burn operations through collective voting
This document explains the architecture, responsibilities, storage interactions, and execution flows between the two governance contracts.
For the operational protocol followed by minters when performing mint/burn operations, see Mint and Burn Protocol.
For how minted tokens are represented on-chain, see NativeCoinAdapter Contract.
For an overview of all system contracts, see System Contracts Overview.

Two-Layer Minting Architecture

Minting governance uses a hierarchical authorization model to balance flexibility and security.
This architecture is implemented through two fixed-address system contracts and storage slots in NativeCoinAdapter.
Key design principles:
LayerContract AddressMembersOperations
Authorization0x0000...1002Master minter membersconfigureMinter(), removeMinter()
Execution0x0000...1003Minter membersmint(), burn() (quorum approval required)
This separation is enforced by access control modifiers in the NativeCoinAdapter contract:
  • onlyMasterMinter: checks msg.sender == masterMinter (slot 0x0)
  • onlyMinters: checks _minters[msg.sender] == true (slot 0x1)
  • Allowance check: _minterAllowed[msg.sender] >= amount (slot 0x2)

GovMasterMinter Contract

Contract Identification and Deployment

GovMasterMinter is deployed as a system contract at genesis:
  • Address: 0x0000000000000000000000000000000000001002
  • Deployment method: Direct injection into the genesis block (no owner)
  • Upgrade mechanism: Replacement only via hard fork
  • Version: Specified in the genesis configuration (e.g. "v1")

Responsibilities

GovMasterMinter acts as the authorization layer for minting operations:
  1. Minter registration: Approves specific addresses as minters
  2. Minter removal: Revokes existing minter permissions
  3. Allowance management: Sets per-minter mint/burn limits
  4. Extensibility: Enables approval of various minter types such as bridge-based or system minters
This structure generalizes the masterMinter concept used in Circle’s FiatToken contracts into an on-chain governance model.

Genesis Parameters

GovMasterMinter is initialized at genesis via params.ChainConfig.Anzeon.SystemContracts.GovMasterMinter:
ParameterTypePurposeExample ValueGenesis Location
membersaddress listMaster minter governance members"0xaa5f...4697"params.GovMasterMinter.Params["members"]
quorumuintMinimum approvals required"1"params.GovMasterMinter.Params["quorum"]
expiryuintProposal expiration time (seconds)"604800"params.GovMasterMinter.Params["expiry"]
memberVersionuintMembership version"1"params.GovMasterMinter.Params["memberVersion"]
fiatTokenaddressNativeCoinAdapter address"0x0000...1000"params.GovMasterMinter.Params["fiatToken"]
mintersaddress listInitially approved minters"0x0000...1003"params.GovMasterMinter.Params["minters"]
maxMinterAllowanceuint256Maximum allowance per minter"10000000000000000000000000000"params.GovMasterMinter.Params["maxMinterAllowance"]
maxProposalsuintMaximum concurrent proposals"3"params.GovMasterMinter.Params["maxProposals"]

Initialization Sequence

  1. core.SetupGenesisBlock() calls core.InjectContracts()
  2. InjectContracts() calls systemcontracts.InjectGovMasterMinter()
  3. InjectGovMasterMinter() directly initializes NativeCoinAdapter storage:
    • Slot 0x0: masterMinter = 0x0000...1002
    • Slot 0x1: _minters[address] = true for each approved minter
    • Slot 0x2: _minterAllowed[address] = maxMinterAllowance for each minter

Storage Layout

GovMasterMinter does not maintain its own storage.
Instead, it manages state via storage slots in NativeCoinAdapter, defined as constants in systemcontracts/coin_adapter.go:
SLOT_COIN_ADAPTER_MASTER_MINTER = "0x0" // address masterMinter
SLOT_COIN_ADAPTER_MINTERS = "0x1" // mapping(address => bool) _minters
SLOT_COIN_ADAPTER_MINTER_ALLOWED = "0x2" // mapping(address => uint256) _minterAllowed
Storage access patterns:
OperationSlotKey DerivationValue Type
Read master minter0x0Direct slot accessaddress
Check minter0x1`keccak256(addressslot)`bool
Read allowance0x2`keccak256(addressslot)`uint256
Mapping slot calculation follows standard Solidity storage layout rules.

Interaction with NativeCoinAdapter

GovMasterMinter can only call permission management functions on NativeCoinAdapter, protected by the onlyMasterMinter modifier. Function signatures:
  • configureMinter(address minter, uint256 minterAllowedAmount) external onlyMasterMinter
  • removeMinter(address minter) external onlyMasterMinter
Access control flow:
  1. A governance proposal reaches quorum and enters execution
  2. The transaction is sent from the GovMasterMinter contract
  3. NativeCoinAdapter compares msg.sender with masterMinter in slot 0x0
  4. On match, slots 0x1 and 0x2 are updated and events are emitted

GovMinter Contract

Contract Identification and Deployment

GovMinter is deployed as a system contract at genesis:
  • Address: 0x0000000000000000000000000000000000001003
  • Deployment method: Direct injection into the genesis block
  • Upgrade mechanism: Hard fork only
  • Version: Specified in the genesis configuration

Responsibilities

GovMinter acts as the execution layer for minting operations:
  1. Mint execution: Issues native stablecoins
  2. Burn execution: Burns native stablecoins
  3. Oracle role: Verifies off-chain fiat deposits and withdrawals
  4. Member governance: Manages its own member set
  5. Multi-approval coordination: Collects quorum approvals for mint/burn proposals
No single member can ever mint or burn unilaterally.

Genesis Parameters

GovMinter is configured at genesis via params.ChainConfig.Anzeon.SystemContracts.GovMinter:
ParameterTypePurposeExample ValueGenesis Location
membersaddress listMinter operator members"0xaa5f...4697"params.GovMinter.Params["members"]
quorumuintMinimum approvals for mint/burn"1"params.GovMinter.Params["quorum"]
expiryuintProposal expiration time"604800"params.GovMinter.Params["expiry"]
memberVersionuintMember version"1"params.GovMinter.Params["memberVersion"]
fiatTokenaddressNativeCoinAdapter address"0x0000...1000"params.GovMinter.Params["fiatToken"]
maxProposalsuintMaximum concurrent proposals"3"params.GovMinter.Params["maxProposals"]

Initialization Prerequisites

GovMinter must be approved as a minter before it can operate:
  1. GovMinter address must be included in GovMasterMinter’s minters list
  2. GovMasterMinter must assign an allowance to GovMinter
  3. During genesis, InjectGovMasterMinter() writes this into NativeCoinAdapter slots 0x1 and 0x2
If these conditions are not met, all mint() / burn() calls will be rejected at the onlyMinters check.

Mint and Burn Workflow

Before any balance change, mint and burn operations must pass the following validation chain: Access control validation chain:
  1. Minter approval check: _minters[msg.sender] == true
  2. Allowance check: _minterAllowed[msg.sender] >= amount
  3. Balance update: Direct native balance modification via StateDB
  4. Allowance deduction: _minterAllowed[msg.sender] -= amount
Function signatures:
  • mint(address to, uint256 amount) external onlyMinters
  • burn(uint256 amount) external onlyMinters

Self-Governance of Members

GovMinter can manage its own membership.
However, if GovMasterMinter revokes GovMinter’s minter approval, GovMinter’s entire execution authority is immediately disabled.

Governance Mechanism

GovMasterMinter and GovMinter share a common GovBase pattern.

Voting Process

Proposal lifecycle:
  1. Creation: A member creates a proposal
  2. Voting: Members vote to approve or reject
  3. Quorum reached: Approvals meet or exceed quorum
  4. Execution: Executed before expiry
  5. Expiration: Automatically discarded if quorum is not reached

Quorum Requirements

Network SizeRecommended QuorumRationale
1 member1Development and testing
2–4 members2Simple majority
5+ members⌈(n/2) + 1⌉BFT-oriented safety
In production environments, a majority or ≥2/3 quorum is recommended.

Member Versioning

memberVersion is incremented on membership changes and prevents execution of proposals created under older versions, mitigating replay attacks.

Proposal Limits

maxProposals limits the number of concurrent proposals to prevent governance-level DoS attacks.

Integration with System Contracts

RelationshipStorage/Code LocationPurpose
GovMasterMinter → Slot 0x0statedb.GetState(nca, 0x0)Master minter verification
GovMinter → Slot 0x1_minters[address]Minter approval check
GovMinter → Slot 0x2_minterAllowed[address]Allowance check
NativeCoinAdapter → PrecompileNative balance updateBalance modification
Genesis → StorageInjectGovMasterMinter()Initial state setup

Summary

The two-layer minting governance architecture guarantees:
FeatureBenefit
Separation of authorization and executionPrevents concentration of power
Multi-approvalBlocks unilateral abuse
ExtensibilitySupports diverse minter types
TransparencyAll actions recorded on-chain
SecurityAllowance-based issuance limits
This design enables StableNet to maintain a 1:1 fiat peg while achieving protocol-level decentralization and strong operational control.