# Acki Nacki Overview

{% hint style="info" %}
**For developer documentation, please visit** [**the developer portal**](https://dev.ackinacki.com/)
{% endhint %}

## **TLDR** <a href="#secured-decentralized-fast" id="secured-decentralized-fast"></a>

Acki Nacki blockchain technology is a Rust implementation of a novel consensus protocol: ["Acki Nacki: A Probabilistic Proof-of-Stake Consensus Protocol with Fast Finality and Parallelisation"](https://link.springer.com/chapter/10.1007/978-3-031-61486-6_4) and ["Acki Nacki Binary System"](https://tokenomics.ackinacki.com/tokenomics.pdf) tokenomics research.

Acki Nacki is asynchronous, highly effective proof-of-stake protocol optimized for fast finality, while allowing for high throughputs via execution parallelization.

It is a probabilistic protocol that achieves higher Byzantine fault tolerance than Nakamoto, BFT (including Hotstuff and AptosBFT), Solana, and other modern consensus protocols.

Our protocol reaches consensus in two communication steps and has a total number of messages that are subquadratic to the number of nodes, with probabilistic, dynamically adjusted safety guarantees.

We trade off deterministic consensus with theoretical constraints on message complexity and the number of Byzantine agreements, with probabilistic algorithms overtaking these boundaries. We further claim that because of the use of randomness and socioeconomics in blockchain designs, no real trade-off is actually present.

One of the key ingredients of our approach is separating the verification of execution by a consensus committee from the attestation of block propagation by network participants.

Our consensus committee is randomly selected for each block and is not predetermined, while the Leader is deterministic.

## Introduction

Current public blockchains are almost exclusively used for financial applications, be it for the store and transfer of value or decentralized finance. Users are ready to pay gas and transaction fees when transacting in value. The primary reason for this user experience inefficiency is the inherent lack of performance in both transaction execution throughput and time to finality, due to strict requirements on state validation.

We present a highly efficient, scalable, and practical blockchain protocol optimized for heavy parallelization and extremely fast finality times. The goal of the protocol is to produce performance comparable to cluster cloud databases without compromising security.

## **Background**

Consensus protocols in computer science are categorized into probabilistic and deterministic. Since 1978, deterministic protocols have evolved, leading to pBFT's creation for varied applications without addressing decentralized money's double spending challenge.

#### **Bitcoin**

Nakamoto's Bitcoin, introduced on October 31, 2008, first solved double spending with a Proof-of-Work (PoW) probabilistic consensus. Miners compete by solving cryptographic puzzles for block proposal rights, embedding economic incentives into its security. Despite its pioneering role, Bitcoin's low transaction rate (7 transactions per second) and long finalization times limit its functionality beyond a store and transfer of value.

#### **BFT**

Before Ethereum in 2014, S. King and S. Nadal proposed Proof-of-Stake (PoS) in 2012, enabling deterministic protocols like pBFT in cryptocurrencies by staking assets. This shift allowed enhancements over pBFT, but BFT's deterministic nature is diluted in PoS due to economic variables and probabilistic encryption, aligning its security more with cryptography and game theory despite performance sacrifices.

#### **Fast Byzantine Paxos**

This protocol, aiming for rapid asynchronous consensus, requires consensus in two steps normally but necessitates >= 5 \* f + 1 nodes to manage f Byzantine nodes, a stricter requirement than pBFT. It illustrates the deterministic protocols' limitations in efficiently addressing malicious nodes.

### **Modern Blockchains**

Recognizing performance problems of Nakamoto and BFT consensus protocols lately few other approaches surfaced. We will compare with three most performant of them: Solana, Avalanche, Aptos, Algorand and Dfinity.

#### **Solana**

Solana stands out as a blockchain platform designed for decentralized applications (dApps), focusing on high scalability and efficiency. It boasts a superior transaction processing capability, enabling higher transactions per second (TPS) with lower fees. Solana combines Proof of Stake (PoS) with Proof of History (PoH), a concept introduced by Yakovenko, to verify time passage between events, enhancing consensus efficiency. This approach uses validator clusters instead of individual nodes, though its scientific basis has faced scrutiny.

#### **Avalanche**

The Avalanche consensus mechanism involves nodes conducting repeated voting among a small group of validator nodes to determine transaction acceptance. Validators respond with their preferred transaction, and if a significant majority agrees, that transaction is chosen. Parameters like the threshold for agreement and Confidence Threshold are adjustable. Avalanche subsampling has low message overhead regardless of the number of validators. Transitive voting helps with transaction throughput. Delays can occur when multiple blocks are proposed simultaneously. The attack probability in Avalanche dynamically changes based on input parameters, affecting finalization time and message complexity.

#### **AptosBFT**

The Aptos builds on advanced pBFT variants like Hotstuff, focusing on random leader selection for each block to improve consensus. However, this necessitates frequent message replication across all network nodes, adding quadratic complexity and impacting overall performance.

#### **Algorand**

The Algorand is a strongly synchronous 3-step protocol. Algorand relies on a public randomness computed in previous blocks. It is used to elect a committee of leaders and a committee of block validators at each round that will have a sufficient number of honest nodes with overwhelming probability. The Algorand’s communication steps consist of: gossip propagation of blocks from all network leaders, BFT among the committee of validators, and the final gossip propagation of the block to the network. The Algorand requires more than 2/3 of the nodes in the validator committee to be honest to ensure security guarantees during the execution of the BFT protocol.

#### **Dfinity**

The Dfinity consensus protocol has four layers: client identities, decentralized random beacon, blockchain with leader ranking, and decentralized notary for finality. Security assumption requires a certain ratio of honest to malicious nodes. The consensus process involves 4 steps with different latencies based on adversary types. In the original paper, the message complexity is unbounded. However, the proposed modification reduces the expected communication complexities against an adaptive adversary, and against a static or mildly adaptive adversary

## **Sharding**

The Sharding a method aimed at boosting performance through data and execution partitioning, was pioneered by Zilliqa and further developed in Ethereum for state sharding. Protocols like TON, Near, and Elrond also employ sharding with parallel leader selection and state synchronization to enhance throughput. Despite these advancements, sharding and parallel execution technologies have yet to surpass a practical limit of around 100K TPS in controlled tests, indicating persistent scalability challenges in blockchain consensus mechanisms.

## **Construction of Acki Nacki**

The Acki Nacki probabilistic consensus protocol intends to take the performance of fault-tolerant consensus protocols as far as we can. In Acki Nacki, Validator Node can perform three roles: Block Producer, Block Keeper and Verifier (which we call the Acki-Nacki entity). All of these roles could be performed by any network participant in parallel. So many Acki Nacki chains (called Threads) can exist simultaneously, but since their security and functionality do not depend on each other.

### **Definitions** <a href="#definitions" id="definitions"></a>

**Account (contract)** is a record in a distributed database with balance, code and data.

**Thread** is a subset of nodes that serve a particular subset of Accounts.

**Block** is an object that contains new transactions which, once finalized, are stored in the blockchain as a permanent and immutable part of this decentralized ledger. Each block includes information such as transaction data, timestamp, common section, and a reference to the previous block, creating a chain of interconnected blocks.

**Common section** is the section of the block that contains information that needs to be shared among all network participants.

**Validator Node** is a Acki Nacki network participant that can be in one of the three modes : Block Producer, Block Keeper or Acki Nacki at a certain moment.

**Block Producer (BP)** is a leader of a particular Thread responsible for block production.

**Block Keeper (BK)** is an entity having two functions: Receives blocks from BP and sends out an Attestation with block hash and other metadata back to BP. BK does not check block transactions validity, it does not try to execute the block, only apply it to its local state with a mark 'Not Final'. Performs a self check if it needs to become a Verifier for this block as described below. If it does, BK will verify the Block and broadcast the result: Ack, if the Block is ok and Nack, if the block is invalid.

**Verifier (Acki-Nacki)** — is a BK being responsible for block validation and notifying all network participants about his verdict: is block valid or not.

**Attestation** — message that is sent to BP by any BK after receiving the block. Attestation is BLS signature done on BK’s private key. BP of the next block must aggregate all received Attestations for the previous block into one BLS signature and include it into the Common section of the new block.

**Ack** — Verifier’s message that is broadcasted to all network participants by Acki-Nacki if the block is verified and it’s valid.

**Nack** — Verifier’s message that is broadcasted to all network participants by Acki-Nacki if the block is verified and it’s NOT valid.

*Attestations and Verifier’s messages must contain block hash, its BLS signature on BK’s private key. Some extra data may be added. For example, Nack contains the reason for block rejection.*

### **Security Assumptions**

We follow standard assumptions of Safety and Liveness properties for Acki Nacki protocol. These properties make the network operation look like the operation of a monolithic valid server i.e. linearizable consistent block ledger. Safety: there are no two honest BK accepting different blocks of the same height and no block with an incorrect transaction is being finalized Liveness: If an honest BP has received a transaction then it will be eventually included in every honest node’s ledger.

In accordance with these properties, we classify the attacks violating them:

**Safety attacks**

Such attacks include dissemblance and private chain attacks. Dissemblance means that the adversary maintains Byzantine nodes to send different messages to different nodes, which may lead to nodes’ disagreement. Private chain attacks mean that the adversary controls Byzantine nodes to work on a separate blockchain privately while following the protocol.

**Liveness attacks**

Liveness attacks. These types of attacks include the aforementioned dissemblance and withholding attacks. Apart from safety, dissemblance may retain honest nodes to make decisions forever, breaking the liveness. Retaining means that the adversary which controls Byzantine nodes doesn't send messages to particular nodes, which may also retain them to make decisions forever.

### **Block Producer selection**

In Acki-Nacki, the selection of Block Producers (BPs) is not random due to security concerns regarding potentially malicious BPs. Instead, a deterministic algorithm is used where the hash of a block with a shard split or other message serves as a seed for random sampling of one BP from a sorted list of BPs' public keys. The current list of BPs is always included in the Common Section of any Block, which also contains other block-related data such as Attestations, Verifier's messages, slashing/reward conditions, etc.

### **Acki-Nacki Selection Algorithm**

The Acki-Nacki selection algorithm in the Acki Nacki blockchain involves calculating a value based on the block and the BP's secret key, then determining if it meets certain criteria to be considered Acki-Nacki. The process ensures randomness in selecting Acki-Nacki BPs, with each selection being an independent event. This method allows for control over the average number of Acki-Nacki per block.

### **Block Production and broadcast**

In the new block production and broadcast process, a Block Producer (BP) releases a new block every 330 milliseconds by collecting unprocessed messages, executing transactions, and creating a block within certain limits. The BP signs the block with its BLS private key and broadcasts it to all Block Keepers (BKs). Upon receiving the block, a BK computes an Attestation for the block, and sends it back to the BP.

### **Block Verification**

Block verification in the protocol is conducted by Acki-Nacki entities selected through an algorithm. These entities must validate blocks and send Ack/Nack messages to the network to avoid being slashed. Third parties can also validate blocks with a bond but are not obligated to do so. If a Block Producer (BP) creates a block with complex execution, Acki-Nacki may delay verification which may lead to incorrect transactions being accepted. To counter this safety attack, Verifiers will stop after 330 ms and send a special Nack with a "too complex" message, allowing the committee to penalize the BP if necessary.

### **Acki-Nacki Selection Proof**

In the Acki-Nacki selection proof process, a Block Keeper (BK) generates BLS key pairs sorted by sequential number for block verification. The BK commits the hash of each key pair to the network using a Merkle Tree. After each block, the Acki-Nacki BK reveals a private key, SeqNo, and Merkle Proof in the Verification message. Other BKs must also reveal their private keys eventually. Failure to send Verifications or provide keys accurately results in it being slashed.

### **Proof-of-Stake and Fork Choice rule**

A Fork Choice Rule algorithm based on stake weight to resolve situations where two valid blocks exist at the same height. The algorithm determines which block to finalize by considering attestations and stake amounts. Participants are required to attest to only one block at a certain height, with penalties for attesting to multiple blocks. The protocol involves executing the Acki-Nacki Selection Algorithm for blocks with a certain number of attestations or the highest stake amount. After applying the Fork Choice Rule, the BK sends to other BKs either the block with Attestations or the block with Attestations and Ack/Nack, depending on whether they became Acki-Nacki for that block.

### **Block Finalization**

The process of block finalization involves each BK receiving a new block, updating the state, and marking mutations as not final until receiving Attestations from BP in the Common section of subsequent blocks to meet the minimum Attestation Threshold specified in the network configuration. The BK also waits a specified time for block to finalize after collecting the required number of block Attestations. If no negative acknowledgments (Nack) are received within the time frame, the block is marked as final. If there are insufficient block attestations, the block remains unfinalized, prompting network participants to decide on potential actions such as allowing ongoing unfinalized block production, halting the network after a set number of blocks, or considering penalties for BKs failing to provide attestations.

### **Joint Committee**

In the event of a Nack, multiple Attestations on the same block by one Block Keeper (BK), or other malicious actions, the Joint Committee function is invoked. Each BK is requested to vote for slashing malicious BKs, Block Producers (BPs), or rejecting a malicious block. The network requires as many votes, as determined by network participants, to confirm malicious activity and take appropriate actions.

### **Slashing**

The following are slashing conditions which can lead network participants to either lose their entire stake or a portion of it (bleeding). When we say 'lose,' we mean that the stake will be burned and not transferred to any other party. Burning plays a role in security assumptions.

* An accepted Nack will slash the BP and every Acki-Nacki which sent an Ack for their entire stake.
* Attesting to more than one block at the same height will result in the slashing of the entire stake of the BK.
* Producing two blocks at the same height from the same BP will result in the slashing of the BP's entire stake.
* A non-performing Acki-Nacki will result in the bleeding of its stake.
* A non-performing BK will result in the bleeding of its stake.
* Non-randomized BK keys will result in the bleeding of the stake.
* Non-sequential Acki-Nacki Keys in the Acki-Nacki Merkle Tree will result in the bleeding of the BK's stake.
* Too complex execution of a block by BP will result in the bleeding of its stake.
* Sending a Nack for a valid block will slash Acki-Nacki.
* If a BP did not include transactions from another thread in the right order in block, or included incorrect ones, it will be slashed by entire stake.

### **Dynamically adjustable parameters**

One of the main advantages of the Acki Nacki consensus protocol is presence of several dynamically adjustable parameters such as the number of Attestations needed for block finalization, the average expected number of Acki-Nacki per block, the number of votes for Join Committee and the probability of a successful attack with a certain percentage of malicious BKs. All these parameters can be changed by network participants through voting according to their preferences.

For example, one can input the number of BKs, the desired attack probability with a certain number of malicious BKs. Acki Nacki will then automatically adjust the parameters of the number of Attestations and the number of Acki-Nacki so that the network achieves the highest throughput with the shortest finality.

## **Attacks analysis**

In the analysis of attacks, you have the opportunity to conduct experiments with parameters using the following [link](https://simulator.ackinacki.com/).

Here you can create graphs illustrating the relationship between the probability of a successful attack and the number of Acki-Nacki, comparison the Acki Nacki consensus with the Nakamoto consensus and the BFT consensus, and build a graphs of the Acki-Nacki Consensus input parameters.

### **Performance analysis**

Without taking state sharding into account the limitation to performance in Acki Nacki network is down to the two factors: the number of blocks a BK can receive over the network and apply and the number of blocks all network Verifiers can process at any given moment. This performance is entirely dependent on computer and network resources committed by Participants, number of BKs and expected number of Acki-Nacki per block.

With sharded design there is no theoretical limit to the Acki Nacki network throughput. Without sharded design, taking into account modern computer hardware and datacenter Internet connection we calculate a practical limit of 250,000 transactions per second of a minimal 500 byte messages with less than a 1 sec finality. With sharding enabled the protocol can scale to millions of transactions of any complexity just by adding computing resources which makes it comparable with centralized cloud services.

Acki Nacki achieves this performance as a result of vastly reduced message complexity during most of its operation time.

**The Acki Nacki algorithm achieves consensus in two communication steps.** The first step involves sending the block from the BP to the BKs. The second step involves sending Acks from Acki-Nacki to the BP and Nacks to all BKs, in parallel with the sending of Attestations from the BKs to the BP.

In total, the following messages are sent: the block from BP to BKs, the Attestations from BKs to BP, and the Ack/Nack messages from several chosen Acki-Nacki to BKs. Here, the optimistic scenario ends. The Nack message and accidental Forks will trigger more messages, but as we have shown, Nack messages are highly improbable, and Forks are rare events. Most of the time, the network will operate by sending just 3 types of messages.\
The total number of all messages sent equals **2 \* (N - 1) + v**, where **N** — number of BKs (including BP), **v** — number of Acki-Nacki. The message complexity of Acki Nacki depends on the desired security parameters, taking into account that, in practice, v << N.


# Glossary

## **A**

#### **Account (contract)**

A record in a distributed database that includes the balance, code, and data.

#### **Ack**

A message from the Verifier broadcast to all network participants by Block Verifier (Acki-Nacki) when a block is verified and deemed valid.

#### Acki Nacki Igniter

The decentralized network starter protocol (DNSP), it collects Node and [License](#license) information, tests and updates the node software and initiates Zerostate (first block) generation once all DNSP requirements are met.

**Acki Nacki Wallet (Main Network Wallet)**

A non-custodial smart contract wallet serving as the primary wallet of the Acki Nacki network. Available as a mobile and web application. Features ZK Login authentication via zero-knowledge proofs (zk-SNARKs, Groth16) with support for Google, Facebook, and other OpenID providers; multi-factor transaction confirmation; access recovery in case of device or credential loss. No user data is transmitted to external servers — the owner retains full control over assets. The wallet code undergoes formal verification. Install: [ackinacki.com/wallet](https://ackinacki.com/wallet)\
Acki Nacki Wallet is created and operates within the system DAPP ID of the Mobile Verifiers. It is not intended for invoking arbitrary methods of user contracts. For such use cases, you should deploy your own [DAPP ID](#dapp-id) and use a [Multisig Wallet](https://dev.ackinacki.com/how-to-deploy-a-multisig-wallet).

#### **Attestation**

A message sent to the [Block Producer (BP)](#block-producer-bp) by any [Block Keeper (BK)](#block-keeper-bk) after receiving a block. The Attestation is a BLS signature generated using the BK’s private key. The BP of the next block must aggregate all received Attestations for the previous block into one BLS signature and include it in the Common section of the new block.

## B

#### **Bee Engine**

An embeddable client-side mining engine and blockchain verification system for background **NACKL** mining, providing cryptographic validation of computation results and reward distribution based on verifiable user contribution (see [**Bee Engine Integration**](https://dev.ackinacki.com/bee-engine/integration))

#### **Block**

An object containing new transactions, which, once finalized, are stored in the blockchain as a permanent and immutable part of the decentralized ledger. Each block includes transaction data, a timestamp, a common section, and a reference to the previous block, creating a chain of interconnected blocks.

#### **Block Keeper (BK)**

A network participant with a deployed [Epoch](#epoch) contract that receives blocks from the [Block Producer (BP)](#block-producer-bp) and sends back an [Attestation](#attestation) containing the block hash and other metadata. A BK can also perform the roles of a [Block Verifier (Acki-Nacki)](#block-verifier-or-acki-nacki) or a BP.

#### **BK Node (BK node)**

This is a node that performs the role of a [Block Keeper (BK)](#block-keeper-bk).

#### **BK Node Owner**

[BK Node keys](#bk-node-owner-keys) owner.

#### **BK Node Owner keys**

The node management keys that provide access to the BK wallet. They are used for managing the node operations such as staking and adding licenses to the approved list. These keys cannot be used to withdraw Rewards from the BK wallet.

#### **BK Reward System**

Block Keepers earn rewards based on their participation in the network during each [Epoch](https://docs.ackinacki.com/glossary#epoch), regardless of their specific role ([Block Producer](https://docs.ackinacki.com/glossary#block-producer-bp), [Block Verifier (Acki-Nacki)](https://docs.ackinacki.com/glossary#block-verifier-or-acki-nacki), or [Block Keeper](https://docs.ackinacki.com/glossary#block-keeper-bk)). The reward depends on the [stake](https://docs.ackinacki.com/glossary#stake) and [Reputation Coefficient](https://docs.ackinacki.com/glossary#reputation-coefficient), and is evenly distributed among the licenses delegated to it.

#### **BK set**

A set of Block Keepers from which a Block Producer is selected for each [thread](#thread).\
Block Keepers are added to the BK set from the [Future BK set](#future-bk-set).\
The members of the BK‑set ensure the operation of the network: they send [attestations](#attestation), validate blocks, and issue [Ack](#ack)/[Nack](#nack) signals.\
The size of the BK‑set directly affects the network’s security parameters, defining how many attestations are required to confirm blocks and the percentage of [Block Verifiers (or Acki‑Nacki)](#block-verifier-or-acki-nacki) needed for each block.

#### **BK Wallet**

The wallet used for staking. The address of the BK Wallet serves as the identifier of the node.

#### BK Wallet whitelist

A list of [license numbers](#license-number) that can be delegated to this node.

#### **Block Manager (BM)**

A network participant whose primary role is to provide users with blockchain data and process external messages. Block Managers receive a portion of the total block reward based on the number of external messages they process. A BM operates in conjunction with a specific BK, and this pairing is defined during start of BM.

#### **BM Reward System**

The amount of NACKL tokens accrued for processing BM external messages during a single Epoch. The reward should be claimed once per Epoch, but it can only be claimed **after** the slashing period (approximately after 5% of the next epoch’s blocks have been processed).

#### **Block Producer (BP)**

The leader of a particular [Thread](#thread) responsible for block production.

#### **Block Verifier (or Acki-Nacki)**

A Block Keeper responsible for block validation, who notifies all network participants of whether the block is valid or not by sending an [ACK](#ack) or [NACK](#nack) message.

#### **BLS keys**

The keys used by BK to sign blocks. The lifespan of the keys is one [Epoch](#epoch). For a new Epoch, new BLS keys will need to be generated. Each BK stores a list of [BLS](#bls-keys) public keys of other BKs (for the current Epoch), which they use to verify [attestations](#attestation) on blocks. It is recommended to back up BLS keys every time they regenerated.

## C

#### **Common section**

The section of the block that contains information shared among all network participants.

## D

#### **Dapp ID**

The identifier of a Decentralized Contract System on the Acki Nacki blockchain. This ID is equal to the address of the root smart contract, which is deployed using an external message. All contracts deployed with internal messages automatically receive the same Dapp ID. Whether from the same root contract, or from contracts deployed by the root contract.

#### Denominations

A denomination is a fixed lot size when selling [SHELL](#shell). There are four denominations, similar to banknotes:

| Denomination (USDC ecc) | SHELL Equivalent |
| :---------------------: | :--------------: |
|            1            |        100       |
|            10           |       1,000      |
|           100           |      10,000      |
|          1,000          |      100,000     |

No other denominations exist. When selling SHELL, the AN Wallet automatically breaks down your amount into lots of these denominations.

## E

#### **Epoch of the BK**

The participation period in the Acki Nacki protocol during which a participant acts as a [Block Keeper](#block-keeper-bk). It begins immediately after the [Pre-Epoch](#pre-epoch) and lasts for 259,200 blocks (about 24 hours). The duration of a specific BK’s epoch may be extended if the number of BKs in the network is lower than required.

#### **Epoch of the BM**

The participation period in the Acki Nacki protocol during which a participant acts as a [Block Manager](#block-manager-bm). The length of an epoch is 259 200 blocks (about 24 hours).

#### **Extra Currency Collection**

A set of currencies within the Acki Nacki network designed to address various tasks beyond [VMSHELL](#vmshell) tokens, which are used for paying fees. These currencies enhance the flexibility and efficiency of the Acki Nacki ecosystem. They provide diverse functionalities tailored to specific use cases, such as value storage and staking ([NACKL](#nackl), index 1) or transferring funds between different [Dapp IDs](#dapp-id) for subsequent conversion ([SHELL](#shell), index 2) and settlement in a US dollar-pegged stablecoin ([USDC](#usdc-ecc), index 3)

## F

#### Free Reserve

The USDC held in the Accumulator contract that is not reserved for SHELL sellers. It is formed as follows: when a buyer purchases SHELL but there aren't enough sellers in the queues, the system creates (mints) new SHELL. The USDC paid for minted SHELL forms the free reserve. Seller funds are never touched.

#### Future BK set

A list of prospective [Block Keepers (BKs)](#block-keeper-bk) for whom a [Pre‑Epoch](#pre-epoch) contract has already been deployed.\
This list is used for pre‑approving access to the main [BK set](#bk-set).\
After the [Epoch](#epoch) contract is deployed, the future BK must be approved by the current BK set to be added to the active BK set. Otherwise, it will be removed from the Future BK set.

## L

#### License

The [**BK License**](/for-node-owners/protocol-participation/block-keeper/license/acki-nacki-vk-node-license) is a [contract](https://github.com/ackinacki/ackinacki/blob/main/contracts/bksystem/License.sol) that grants the right for a [Block Keeper (BK)](#block-keeper-bk) to participate in the protocol. The license is delegated to a specific BK. Each BK can be delegated up to 20 (twenty) licenses. The Licenses are delegated without restrictions.

The **BM License** is a [contract](https://github.com/ackinacki/ackinacki/blob/main/contracts/bksystem/LicenseBM.sol) that grants a [Block Manager (BM)](#block-manager-bm) the right to participate in the network. Each BM License is delegated to a BM wallet *(1 wallet - 1 license)*.

#### License number

An **on-chain unique number** assigned during the deployment of the License contract.

#### License Owner

A person who [registered at the Acki Nacki Dashboard](https://docs.ackinacki.com/protocol-participation/license/license-dashboard-guide) and has acquired a [License](https://docs.ackinacki.com/protocol-participation/license/acki-nacki-node-license) and License Owner Keys to participate in the Acki Nacki protocol.

#### License Owner Keys

The keys used to manage license contracts (delegate and revoke delegation) and withdraw staking rewards. They can be obtained by [registering in the dashboard](https://docs.ackinacki.com/protocol-participation/license/license-dashboard-guide).

#### Lot

A lot is a single indivisible sell order for SHELL. Each lot is tied to a specific denomination and can only be sold in full. Partial selling of a lot is not possible.

**Example:** a lot with denomination 10 USDC ecc means the seller deposited 1,000 SHELL and is waiting to receive 10 USDC ecc when their turn comes.

## M

#### **Minimal Stake of the BK**

The minimum amount of tokens a Block Keeper must stake to participate in the network. This value dynamically adjusts based on the difference between the current number of Block Keepers and the required number of Block Keepers in the network.

#### **Minimal Stake of the BM**

The minimum amount of tokens locked on Block Manager wallet.\
It is calculated individually and represents the product of a coefficient and the total amount of [**NACKL**](#nackl) earned by the BM. The coefficient depends on the time elapsed since the network launch and decreases over time.\
If a BM stops operating in the middle of an [Epoch](#epoch-of-the-bm), no reward is accrued for that Epoch.

#### Maximum stake

The maximum number of tokens a Block Keeper can stake to participate in the network. This stake remains valid as long as the license stays active. The value is dynamically adjusted based on the current number of Block Keepers in the network, the total number of tokens minted exclusively by Block Keepers, and the number of tokens burned due to slashing penalties.

#### **Mobile Verifier**

A participant in the protocol who occasionally validates transactions in subtrees of accounts. Mobile Verifiers compete in an online game, earning Boosts, to secure a place on the mobile verifiers list, which determines their share of the Block reward.

## N

#### **Nack**

A message from the Verifier broadcast to all network participants by Block Verifier (Acki-Nacki) when a block is verified and deemed invalid.

#### **NACKL**

The native network token, used for security guarantees: staking, slashing and block rewards.\
(currency collection index: 1)

#### Node Provider

An off-chain entity that for provides [Block Keeper (BK) nodes](#bk-node-bk-node) to license owners, allowing them to participate in the protocol by delegating their licenses to specific nodes. Node Provider keys are used to sign and validate the delegation to a particular Node Provider before Network start to form the zerostate, they do not operate on-chain. Subsequently, the license owner receives a share of the rewards earned by the BK for participating in the protocol

## P

#### **Pre-Epoch**

The period before the [Epoch](#epoch) during which a [BK node](#block-keeper-node-bk-node) synchronizes states with the network.

#### Proxy

A specialized network service designed to optimize block exchange between participants in the Acki Nacki network. Its primary purpose is to reduce overall network traffic between nodes and to improve the scalability and stability of the network.

## R

#### **Reputation Coefficient**

A metric that increases the rewards for [Block Keepers](#block-keeper-bk) based on their continuous participation in the protocol.

## S

#### **SHELL**

The utility token within the Acki Nacki network is designed to compensate [NACKL](#nackl) holders for the computing resources the network provides. Minted by depositing eccUSDС, but it isn't collateralized. It can be converted to [VMSHELL](#vmshell) to cover network fees at a 1:1 ratio. However, it is not possible to convert VMSHELL back to SHELL. This token can be transferred between different [Dapp IDs](#dapp-id). (currency collection index: 2). Learn how [to buy SHELL here](https://docs.ackinacki.com/for-users/buy-sell-shell/introduction).

#### **Stake**

The amount of [NACKL](#nackl) tokens required to participate in the Acki Nacki protocol. It is calculated as the total sum of all stakes from licenses delegated to a specific node. At the launch of the Acki Nacki network (zerostate), staking is not required if a [License BK](#license) is present. [Staking](https://github.com/ackinacki/ackinacki/tree/main?tab=readme-ov-file#staking) will become necessary for validation at a later stage.

## T

#### **Thread**

A subset of nodes that serve a particular subset of [Accounts](#account-contract).

## U

#### USDC ecc

A stablecoin pegged to the US dollar. Used for settlements when [buying](/for-users/buy-sell-shell/buying-shell/ways-to-buy-shell) and[ selling](/for-users/buy-sell-shell/selling-shell) SHELL (the rate is fixed and immutable: **1 eccUSDC = 100 SHELL)**. Within the Acki Nacki network, USDC exists as ECC\[3] — an element of the [Extra Currency Collection](#extra-currency-collection).

## V

#### VMSHELL

The unit of account used to cover network fees. It is converted from [SHELL](#shell) and cannot be converted back to SHELL. VMSHELL can be transferred between contracts that belong to the same [Dapp ID](#dapp-id).

## **W**

#### Wallets

Smart contract [accounts](#account-contract) used to hold assets and initiate transactions in the Acki Nacki network. A wallet's behavior is defined by its deployed contract code, which can support different capabilities such as token transfers, multi-signature approvals, access recovery, spending limits, or staking operations. See [Wallets](/for-users/wallets).

## Z

#### **Zerostate**

The initial state of the network, representing the first block state of the blockchain. It is created after all the requirements of the [**Decentralized Network Starter Protocol (DNSP)**](https://docs.ackinacki.com/protocol-participation/block-keeper/join-dnsp-gossip) have been fulfilled.


# Launch & Genesis

Joining the Acki Nacki Network from the Genesis Block

To launch the network, **Igniter DNSP clients** collect data that will be used to generate the **Zerostate**.\
At the time of network launch, the Zerostate will include:

* All **BK wallets** along with their corresponding **whitelists**
* All **license contracts** and mappings to the **Node Owners’ wallet contracts** to which those licenses were delegated

#### ✅ Before the network launch:

* All **License Owners** must delegate all licenses they want to be included in the Zerostate.\
  👉 [See the Delegation Instruction](/for-node-owners/protocol-participation/block-keeper/license/license-delegation-guide)
* All **Node Owners** must:
  * Generate the necessary key pairs
  * Collect **all required signatures**
  * Properly configure the **Igniter DNSP client**
  * Run the Igniter for each node\
    👉 See the [Igniter Setup Guide](https://github.com/ackinacki/ackinacki/blob/main/README.md)

***

#### 🚨 Important:

* The **Igniter** must be running **for each node** using the **same server IP** and **Proxy IP** that will be used for deploying the BK node later.
* The **same keys and licenses** used during Igniter setup must also be used when deploying the BK.

***

#### ⏱ Network Launch Timing

The **Gosh team will announce the exact network launch time in advance** (including day, hour, and minute).\
So, you must either:

* Set up an **automatic launch** of the deployment scripts and staking on each server where the Igniter was run\
  **OR**
* Launch them **manually at the specified time**

👉 [BK Deployment Instructions](broken://spaces/yPWnJ1v4nIPgOrEhPVrK)\
👉 [Proxy Deployment Instructions](https://github.com/gosh-sh/acki-nacki?tab=readme-ov-file#proxy)


# Network Architecture and Participants

Acki Nacki is a live network. Some protocol mechanisms are introduced gradually. Each capability is marked with its current status; please refer to it while reading the document.

**Acki Nacki is a multithreaded Proof-of-Stake network with parallel execution and fast probabilistic block confirmation.**

{% hint style="info" %}
Entrypoint for interacting with the network: <https://mainnet.ackinacki.org>
{% endhint %}

Its architecture separates responsibility across three main layers:

| Layer                    | Purpose                                                                                    | Main participants                                                   |
| ------------------------ | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------- |
| Execution layer          | Distributes state across independent `threads` and processes account messages in parallel. | Block Keepers, temporary Block Producers                            |
| Consensus layer          | Produces, attests, challenges, and finalizes blocks.                                       | Block Keepers, temporary Block Producers, temporary Block Verifiers |
| Transport and user layer | Provides message delivery, network segmentation, API access, and user message ingress.     | Broadcast Proxy, Block Manager                                      |

## Capability Status

This document describes the target Acki Nacki architecture according to the white paper and the current specification.

Some mechanisms are under active development and are marked as:

| Status             | Meaning                                                                             |
| ------------------ | ----------------------------------------------------------------------------------- |
| **Available**      | Available in the current [mainnet](https://mainnet.ackinacki.org/) network.         |
| **Phased rollout** | The base mechanism works, while extensions are introduced through protocol updates. |
| **Planned**        | Described in the specification but not yet available in production.                 |

The base network functions are described separately from mechanisms that are being developed in phases.

### Status Summary

| Capability                                              | Status             | Context                                                                                                                                                                                     |
| ------------------------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Block Keeper consensus, attestations, and finalization  | **Available**      | The base consensus layer is operational in the current network.                                                                                                                             |
| Multithreaded execution and `thread` separation         | **Available**      | Used for parallel processing of independent parts of the state.                                                                                                                             |
| Merging `threads` when load decreases                   | **Planned**        | The logic is behind a feature flag and is not enabled in the current network; merge support must be completed at the state and routing table levels.                                        |
| NACK mechanism for challenging invalid blocks           | **Phased rollout** | The challenge-and-verification flow and slashing path for the producer are available; extended accountability for invalid attestations and false accusations is being introduced in phases. |
| Extended accountability rules for invalid attestations  | **Planned**        | These rules complement the existing slashing path for producers in future protocol updates.                                                                                                 |
| Broadcast Proxy as the transport layer                  | **Available**      | Used for segmented network topology and for reducing direct load between Block Keepers.                                                                                                     |
| Block Manager and BM staking                            | **Available**      | Block Managers provide user/API access and may participate in BM staking through the corresponding license.                                                                                 |
| Mobile Verifier reward game and on-chain infrastructure | **Available**      | The on-chain reward game is active, and rewards are distributed according to the current game rules.                                                                                        |
| Light-verification flow for Mobile Verifier             | **Planned**        | Full integration of light state and transaction checks into the protocol-level security flow is being introduced in phases.                                                                 |

## Network Structure <a href="#network-structure" id="network-structure"></a>

### Threads and Execution Model <a href="#threads-and-execution-model" id="threads-and-execution-model"></a>

The Acki Nacki execution layer consists of dynamic `threads`. Each `thread` serves a subset of accounts and processes messages related to that part of the state.

This model makes it possible to:

* place related accounts in the same execution area;
* execute independent account groups in parallel;
* split overloaded `threads` as load grows;
* merge `threads` back when load decreases (**Planned**).

`Threads` do not directly share mutable state. They interact through cross-thread messages: one `thread` can pass messages to another through finalized blocks and references to them. This allows the network to execute independent parts of state in parallel and gradually synchronize account routing between participants.

### Consensus Layer

Acki Nacki consensus is maintained by a set of Block Keepers. A Block Keeper is a validator participant with active stake, signing keys, and the right to participate in block confirmation.

In each round, one Block Keeper is selected as the Block Producer for a specific `thread`. The Producer forms a new block, executes messages, adds the required metadata, signs the block, and propagates it to other Block Keepers.

The other Block Keepers verify that the block complies with protocol rules and send attestations. An attestation is a cryptographic confirmation of a block by a consensus participant.

Block confirmation happens in two stages:

| Stage           | Purpose                                                                                               |
| --------------- | ----------------------------------------------------------------------------------------------------- |
| Prefinalization | Locks the network onto one branch and reduces the risk of fork conflicts.                             |
| Finalization    | Means the block becomes finalized under the protocol rules after the finalization conditions are met. |

### Verification and the NACK Mechanism <a href="#verification-and-the-nack-mechanism" id="verification-and-the-nack-mechanism"></a>

Acki Nacki uses lazy validation. Block Keepers are not required to fully re-execute every block on the happy path. The base security of the current `mainnet` network is provided by Block Keeper consensus, attestations, finalization rules, and the economic accountability of Block Producers for invalid blocks.

`NACK` is a challenge mechanism. If a Block Verifier detects an invalid block or an invalid state transition, it sends a signed `NACK` accusation. A `NACK` by itself does not finalize punishment and does not automatically make the accusation true: the disputed block must go through independent verification under the protocol rules.

If the accusation is confirmed:

* the invalid block and its descendants are rejected;
* the producer of the invalid block may be punished through the available slashing path (**Available**);
* the network returns to the correct branch according to the fork choice and finalization rules.

Unconfirmed or invalid accusations must not lead to slashing of honest participants. Extended accountability rules, including accountability for invalid attestations and additional rules for false accusations, are being introduced in phases (**Planned**).

{% hint style="info" %}
Thus, the current NACK flow protects the network from accepting invalid blocks through a challenge-and-verification path, while future updates extend the accountability of participants who attest to or initiate invalid actions.
{% endhint %}

### Transport Topology

The Acki Nacki transport network is not a flat mesh where every node connects to every other node. It is built from network segments.

| Segment type          | Description                                                                     |
| --------------------- | ------------------------------------------------------------------------------- |
| `Single node segment` | One Block Keeper without a Proxy, to which other participants connect directly. |
| `Proxied segment`     | One or more Proxies and a group of Block Keepers behind them.                   |

Broadcast Proxy is not a consensus participant and cannot create, modify, or attest to consensus messages on behalf of Block Keepers. Consensus messages are signed by Block Keepers, so Proxy performs only a transport function: it relays data between participants and helps reduce network load.

Proxy segments are not the only connection model. A Block Keeper may operate in a `Single node segment` without a Proxy, or use a proxy segment to optimize network propagation. For fault tolerance, participants may use several network paths and update the transport configuration when a specific Proxy is unavailable.

### User Layer

Block Managers sit outside the consensus core. They subscribe to Block Keeper streams, maintain a local blockchain data database, provide APIs, and receive external messages from users or applications.

The Block Manager forwards received external messages to the current Block Producers of the corresponding `threads`.

In the current model, a Block Manager can participate in BM staking if it has the corresponding license. Rewards are accrued through the BM wallet and depend on BM staking parameters and network state.

## Network Participants

The public network model includes the following main roles:

* `Block Keeper`;
* `Block Producer`;
* `Block Verifier / Acki-Nacki`;
* `Block Manager`;
* `Mobile Verifier`.

{% hint style="warning" %}
Block Producer and Block Verifier are not separate permanent node types. They are temporary functions performed by participants from the current Block Keeper set.
{% endhint %}

`Broadcast Proxy` operates separately at the transport layer: it does not participate in consensus but is an important part of the network topology.

## Block Keeper

Block Keeper is the base consensus participant in Acki Nacki.

### Main Functions

* Receive candidate blocks from Block Producers.
* Verify signatures and protocol conditions.
* Send attestations.
* Participate in prefinalization and finalization.
* Maintain fork choice and network security rules.
* Perform the Block Verifier role when necessary.

### Participation Requirements

* Have the right to participate in consensus through a [license](https://docs.ackinacki.com/for-node-owners/protocol-participation/block-keeper/license) and stake. For the first two years after `mainnet` launch, the license is required; this requirement is removed afterward.
* Have signing keys for consensus participation.
* Run and maintain an available Block Keeper node.
* Be in the active consensus participant set.

### Rewards

* Receives rewards for participating in consensus and maintaining network security.
* Rewards are tied to Block Keeper participation in the network, not to separate temporary roles.

### Slashing

* Slashing mechanics are available for serious protocol violations, including producing invalid blocks. Specific violation detectors and rules apply according to the current protocol version (**Available**).
* Additional accountability rules for invalid attestations will be introduced in protocol updates (**Planned**).

## Block Producer

Block Producer is a Block Keeper selected to produce a block in a specific round and `thread`.

### Main Functions

* Select and process messages.
* Execute transactions.
* Create a block.
* Include state updates, metadata, and cross-thread references.
* Sign and distribute the candidate block.

### Participation Requirements

* Be an active Block Keeper.
* Be selected as the producer for a specific round and `thread`.
* Have up-to-date state and network availability.

### Rewards

* The separate temporary Block Producer role does not have an independent reward.
* Rewards are received through participation of the corresponding Block Keeper in consensus.

### Slashing

* Possible for producing an invalid block, equivocation, or other violations of Block Production rules.

## Block Verifier / Acki-Nacki

Block Verifier, or Acki-Nacki, is a Block Keeper that verifies a disputed block.

### Main Functions

* Detect invalid blocks and incorrect state transitions.
* Send a `NACK` when a violation is detected.
* Participate in independent verification of the disputed block.
* Help the network reject invalid branches after a confirmed `NACK`.

### Participation Requirements

* Be an active Block Keeper.
* Be able to verify the block and sign the verification result.
* Have access to the required state for verification.

### Rewards

* The public model does not define a separate permanent verifier reward.
* The role protects network security and the stake of honest participants.

### Slashing

* A confirmed `NACK` can lead to punishment of the invalid block's producer through the available slashing path (**Available**).
* Accountability for false or incorrect accusations is introduced as part of the accountability layer development (**Planned**).
* Additional rules for invalid attestations will be introduced in protocol updates (**Planned**).

## Broadcast Proxy

Broadcast Proxy is a transport participant in the network. It is not part of the consensus set and does not make consensus decisions.

### Main Functions

* Relay protocol messages between network segments.
* Reduce direct network load between Block Keepers.
* Improve scaling of block and message propagation.

### Participation Requirements

* Have a valid network configuration.
* Be available to participants that use the corresponding proxy segment.
* Maintain stable operation of the transport layer.

### Rewards

* Proxy is not a consensus reward role. Economic terms may be defined operationally between infrastructure participants.

### Slashing

* Proxy does not have consensus stake and is not slashable as a Block Keeper.
* An incorrectly operating Proxy may be removed from the configuration or replaced by the operator.

## Block Manager

Block Manager is a participant in the user-facing and infrastructure part of the network. It is not part of the consensus set, but it provides users and applications with access to the blockchain.

### Main Functions

* Subscribe to Block Keeper streams.
* Store a local blockchain data database.
* Provide APIs and blockchain data services.
* Receive external messages.
* Route external messages to the current Block Producers.
* Maintain fault-tolerant access to multiple Block Keepers.

### Participation Requirements

* Have a BM wallet and delegated BM license.
* Run the Block Manager service.
* Have access to Block Keeper streams and API endpoints.
* Maintain local blockchain data storage.

### Rewards

* Participates in BM staking through the corresponding license.
* Rewards are accrued through the BM wallet according to BM staking parameters and network state.

### Slashing

* The BM wallet supports a slashing mechanism.
* Slashing is tied to the state of the BM license, BM wallet, and participant lifecycle.

## Mobile Verifier

Mobile Verifier is a light participant in Acki Nacki. It is not required to run a full Block Keeper node or validate every block.

The Mobile Verifier role is related to the reward game and the development of the light-verification model. It expands user participation in network verification and creates an operational foundation for light independent checks.

### Main Functions

* Participate in the reward game for light verifiers through on-chain infrastructure;
* Perform selective checks of state or transaction activity within the light-verification flow;
* Confirm verification results according to the rules of the corresponding flow.

### Participation Requirements

* Register as a Mobile Verifier;
* Use the light-verifier client or another supported participation method;
* Follow the rules of the reward game, verification, and result confirmation.

### Rewards

* Rewards are distributed according to the reward game rules;
* Reward parameters depend on the current game rules and on-chain infrastructure.

### **Accountability:**

* Mobile Verifier is responsible for the correctness of submitted results under the rules of the corresponding flow;
* False or invalid checks are handled according to the current reward game rules and light-verification model.

## Operational and Economic Entities

In addition to protocol roles, operational and economic entities exist around the network:

* `License Owner` - the owner of a license associated with participation or delegation rights;
* `Node Owner / Node Provider` - an infrastructure operator that runs and maintains nodes;
* `Proxy Provider` - an operator of proxy infrastructure for network optimization.

These entities are important for deployment, licensing, delegation, and network operations, but they should not be considered independent consensus participants. Consensus responsibility remains with Block Keepers and temporary roles inside the consensus set.

## Summary

Acki Nacki can be understood as a multilayer system:

* `threads` provide parallel execution and account routing;
* Block Keepers maintain consensus, attestations, and finality;
* Block Producers temporarily create blocks inside `threads`;
* Block Verifiers challenge invalid blocks through NACKs;
* Broadcast Proxy scales the transport layer between segments;
* Block Managers provide user access and external message ingress;
* Mobile Verifiers participate in the reward game today and expand the security surface with lightweight independent checks as the light-verification flow develops.

In short, Acki Nacki is a BK consensus network with parallel execution through `threads`, segmented transport topology, user access through Block Managers, and additional verification through Mobile Verifiers that is being developed gradually.


# Synchronization and Consensus Mechanism

This page explains how Acki Nacki reaches consensus on block ordering and validation, including finalization and failure handling.

{% hint style="info" %}
Acki Nacki assumes a Byzantine environment where strictly fewer than one third of Block Keepers are malicious.
{% endhint %}

## Model and Participants

The protocol guarantees:

* **Safety**: there are no two finalized conflicting blocks at the same height.
* **Liveness**: blocks eventually finalize, even if some participants fail or the network is slow.

Roles participating in agreement:

* **Block Producer**: deterministically selected from the active Block Keeper set for a specific round.
* **Block Keeper**: a staker with a BLS key and `SignerIndex` (`u16`). Block Keepers form the consensus voting set and attest blocks.
* **Block Verifier** (Acki-Nacki): a Block Keeper acting in the verifier role. The verifier performs targeted block re-execution when a block is challenged and creates a NACK if the block is invalid.
* **Mobile Verifier**: a lightweight participant that does not vote in consensus directly. In the current production status, the Mobile Verifier reward-game part is active; the selective light-verification flow that should reduce attack probability is under development.
* **Block Manager**: processes external messages and is not part of consensus.

The active Block Keeper set changes by Epochs through on-chain contracts. Its lifecycle is:

```
PreEpoch -> Active -> CalledToFinish -> Expired
```

Each block carries two sets:

* **Current set**: used to verify this block.
* **Descendant set**: includes the changes applied by this block and is used for the next block.

## Block Lifecycle

Synchronization in Acki Nacki is a four-phase pipeline. Each phase latches another piece of consensus state and prevents the state machine from rolling back that fact.

```
Production -> Attestation -> Prefinalization -> Finalization
```

The same active Block Keeper set can perform different functions during this lifecycle. One participant may be a producer in one round, an attester for another block, and an Acki-Nacki verifier when it checks an accused block. Consensus rewards are distributed within the Block Keeper group and do not depend on which of these functions a participant happened to perform in a specific Epoch.

### Production

The producer for a round is determined **deterministically** from the parent's `ProducerSelector` and the round number. No coordination is needed: all nodes independently know who the producer is.

Happy-path flow:

1. The producer executes the message queue through TVM on top of the parent state.
2. It wraps the TVM block with Acki Nacki metadata: thread, round, keeper set changes, and cross-thread references.
3. It signs the block with BLS and broadcasts it.
4. The other Block Keepers accept the block, verify signatures, and start attesting.

A block may include external messages from the API, internal messages from the thread queue in round-robin order, NACK slashing messages, and keeper set changes.

### Block Verifier (Acki-Nacki)

The Acki-Nacki verifier is the correctness-checking function inside the Block Keeper group. It is separate from the producer function: the producer creates and signs the block, while the verifier can independently reconstruct the block from the parent state and the same input queues.

Verifier responsibilities:

* verify the block against the parent state when revalidation is required;
* detect invalid state transitions, excessive execution, or mismatched observable outputs;
* create and sign a NACK when the block is invalid;
* provide evidence that can invalidate the accused block and its descendants;
* expose wrong accusations to a possible `WrongNack` counter-claim.

This verifier path is intentionally lazy. Acki-Nacki does not require every Block Keeper to re-execute every block before attesting. Instead, the verifier role provides an accountability path: a bad block can be challenged, re-executed independently, and either rejected or confirmed despite the accusation.

### Attestation

Each Block Keeper signs `AttestationData` with its BLS key. Individual signatures are **aggregated** into one compact BLS signature, which keeps the protocol scalable with large validator sets.

| Path         | Threshold                | Deadline        | When It Triggers               |
| ------------ | ------------------------ | --------------- | ------------------------------ |
| **Primary**  | `ceil(2N/3)` (`~66%+`)   | `beta` blocks   | Healthy network, fast finality |
| **Fallback** | `floor(N/2)+1` (`50%+1`) | `2*beta` blocks | Primary did not collect 66%    |

{% hint style="info" %}
Primary optimizes for fast finality. Fallback preserves liveness when messages are delayed but enough participants remain online.
{% endhint %}

Votes are staggered with:

```
delay = pulse_timeout * (0.8 + distance_from_producer)
```

Block Keepers closest to the producer vote first. This gives the block time to propagate and makes signature aggregation more orderly.

Aggregation first tries an optimistic merge: merge all signatures at once and verify once. If that fails, the protocol falls back to one-by-one merging and marks invalid signatures as `poisoned`; these signatures become evidence for slashing.

### Prefinalization

**Prefinalization** happens when a block receives the first `50%+1` attestations. Any two `50%+1` sets must intersect. If all Block Keepers are honest, this gives a single prefinalized branch. If a conflict appears, the intersection becomes cryptographic proof of double-signing.

Once a block is prefinalized:

* Block Keepers lock onto it through ActionLock.
* Competing blocks at the same height and their descendants are invalidated.
* The network converges on one chain.

Sibling resolution handles two prefinalized siblings with the same parent:

* **Higher round wins**: the higher-round block was produced later, after more time for convergence; the lower-round block is invalidated.
* **Same round**: the producer double-signed, and both blocks become cryptographic proof for stake slashing.

Prefinalization is write-once: once the signal is set, it cannot be unset. This prevents the state machine from oscillating.

### Finalization

Prefinalization protects against forks, but it does not guarantee irreversibility. A prefinalized block can still be NACKed as invalid. Finalization is the actual commit.

A block becomes final when all eight conditions are satisfied:

1. The parent is finalized.
2. Signatures are verified.
3. The block is not invalidated.
4. All NACK accusations are resolved.
5. The block is applied to the parent state and TVM execution succeeds.
6. All cross-thread references are finalized.
7. Cross-thread reference data is available and prepared.
8. The block appears in `finalizes_blocks` of the corresponding checkpoint-carrier block.

Attestation checkpoints avoid direct vote counting. Each new block carries checkpoints for its ancestors, and the checkpoint distance grows as the chain advances. When the deadline is reached, the vote set is checked.

Primary finalization requires `ceil(2N/3)` attestations by the `beta` deadline. Fallback finalization is two-stage:

1. At `beta`, check for `50%+1` attestations with Primary target type.
2. At `2*beta`, check for `50%+1` attestations with Fallback target type.

Both fallback stages must pass. If they fail, the checkpoint fails, the block does not finalize, and it should be NACKed.

After finalization:

* the finalized block is marked and persisted;
* the attestation cutoff advances;
* descendants are notified through `has_parent_finalized`;
* raw block data is archived;
* all non-finalized blocks at this height or lower are invalidated.

{% hint style="warning" %}
Invalidation is recursive and thread-agnostic. Invalidating a block cascades to all descendants in all threads. A finalized block cannot be invalidated.
{% endhint %}

## ActionLock

ActionLock is the root of double-sign protection. Before sending an attestation or a `NextRound` request, a Block Keeper updates ActionLock and saves it in durable storage.

ActionLock records:

* parent block;
* current round;
* the block already voted for at this height, if any;
* known NACKed blocks at this height.

In production, ActionLock is stored through a durable storage backend. This does not necessarily mean a literal `fsync` of a local file. Some authority-switch states related to starting a new producer still have durability TODOs in the code, so ActionLock should not be described as the only persisted guard for every possible production action.

Lock rules:

* One vote per `(height, round)`.
* A block with a **higher round** may overwrite the lock because a higher round means later network convergence.
* A block with the **same round** but a different hash is rejected for attestation, because signing it would be double-signing.

{% hint style="danger" %}
The durability requirement is protection for the Block Keeper itself. A vote must be persisted before it is sent so that a crash cannot cause accidental self-slashing.
{% endhint %}

## Authority Switch

If the round producer is silent or works invalidly, the network switches authority to the next producer without waiting forever.

### Round Buckets

Round duration grows by buckets. This gives the network a fast response to temporary failure without burning through the producer queue.

| Bucket  | Approximate Round Duration | Rotations |                                               Purpose |
| ------- | -------------------------: | --------: | ----------------------------------------------------: |
| Fast    |                     `~1 s` |      `60` | First response, about 10 minutes for 10 Block Keepers |
| Medium  |                    `~60 s` |       `1` |                    After the fast bucket is exhausted |
| Default |                   `~5 min` | unlimited |                           Final pace for long outages |

### Round-Switch Protocol

1. **Detection**: nodes see that there is no valid block in the current round.
2. **Request**: each node sends `NextRound` to the next producer with its `Lock`.
3. **Quorum**: the next producer waits for a strict majority, `floor(N/2)+1`. Requests with a different NACK set are filtered out.
4. **Resolution**: the block with the highest round is selected from the collected locks.
5. **Rejection**: if the new producer already has a prefinalized block at this height, it replies with `NextRoundReject` and proof of prefinalization.

If a highest-round locked block exists, the producer validates it, aggregates attestations, and broadcasts `NextRoundSuccess`. If no locked block exists, the producer builds a new one if at least `330 ms` remain; otherwise it waits for the next round.

`NextRoundSuccess` messages that arrive before a node is ready are buffered and replayed when the node reaches the required height.

## Node State Synchronization

Consensus synchronization decides which blocks are accepted and finalized. Node state synchronization is the recovery path that lets a joining or lagging node reach that finalized history without replaying the entire network from genesis.

A node enters synchronization when:

* it starts without a usable finalized block for the thread;
* the gap between an incoming block and the local applied/finalized chain exceeds `need_synchronization_block_diff`;
* authority-switch processing detects that the node cannot safely continue from its local view.

### Joining Flow

When a node needs state, it broadcasts `NodeJoining` or `NodeJoiningWithLastFinalized` with its last finalized position. Peers compare that position with their own finalized chain and answer in one of two ways:

* by sending candidate/finalized blocks that can bridge a small gap;
* by sending `SyncFinalized` or `SyncFinalizedWithHeight`, which points to a finalized block and the shared state resources for the relevant thread references.

If the gap is small enough, the node requests the missing block range through `BlockRequest`. Responses include the requested blocks in range, with finalized blocks first and then candidates. If the gap is too large, or a block range cannot be served, the serving side can schedule a future block with `share_state_resources`. After that block finalizes, state is published for synchronization.

### Snapshot Loading

State snapshots are anchored to a finalized block by sequence number or block height. A shared state package contains the data a node needs to resume safely from that finalized point:

* the Block Keeper set;
* the existing thread list;
* the state for each thread;
* cross-thread reference data needed to continue message delivery;
* enough finalized block context to restart processing from the snapshot anchor.

The node downloads the snapshot through the state-sync service, validates that the snapshot still matches the active synchronization target, and applies it only if it is newer than the local finalized state or the local chain can bridge the difference. While a snapshot is loading, the node continues broadcasting `NodeJoining`; newer `SyncFinalized` candidates can replace stale targets so the node converges on the best available finalized state.

After a snapshot is applied, the node resumes normal block processing from the anchor. Incoming candidate blocks are then handled by the regular consensus pipeline: signature checks, attestation, prefinalization, finalization, NACK handling, and cross-thread reference preparation.

## NACK

NACK is the lazy validation and punishment path.

{% hint style="info" %}
Blocks are not re-executed by all Block Keepers on receipt. Block Keepers can attest after signature and consensus checks. Full TVM re-execution is performed only along selected validation paths and when a NACK accusation must be resolved, with the NACK being created by the Block Verifier (Acki-Nacki).
{% endhint %}

NACK flow:

```
Acki-Nacki verifier re-executes a block -> finds it invalid -> NACK with reason
   v
BLS signature and broadcast
   v
Other BKs record the accusation
   v
Block is sent to validation service for independent revalidation
   v
Confirmed invalid -> block and descendants invalidated + slashing message
Confirmed valid   -> possible counter-NACK (WrongNack) against accuser
```

A block cannot finalize while it has unresolved NACKs. Resolution means either there are no accusations or `validated == true` after independent checking.

During revalidation, the Acki-Nacki verifier takes the parent state, re-executes all messages, and assembles an independent block:

1. Exact match means the block is valid.
2. Difference triggers partial comparison of observable outputs: metadata, value flow, message queue changes, and final state hash. Differences in internal execution paths may be tolerated when outputs are deterministic.

## Cross-Thread Synchronization

Acki Nacki is multithreaded: each thread has its own chain. A block can reference **finalized** blocks from other threads to import cross-thread messages.

References are selected from blocks whose cross-thread data is available and finalized. When `delay-references` is enabled, references are delayed by `sqrt(thread_count)` generations so that all threads do not point to the newest block at the same time and create contention.

## Economic Synchronization Layer

Protocol guarantees are multiplied by economics:

* **Reputation coefficient `R in [1, 3]`**: a reward multiplier for continuous participation. It grows exponentially and saturates after roughly five years. Missing an Epoch resets it to `R_min`.
* **Mobile Verifiers**: in the target security model, they multiply attack complexity. The classic probability `(1 - v/(N-1))^(A - N_mal)` receives an additional factor `(1 - lambda_MV)^(N_MV - N_MV_mal)`. In the current production contour, this security contribution is not active yet.
* **Stake with cooling period**: stake is split into an active half and a cooling half used for slashing calculation.
* **No protocol-level delegation**: the Epoch contract accepts only messages signed by the Block Keeper's own private key, not by a delegate.
* **Fair rewards**: within the Block Keeper group, reward does not depend on whether the participant was a producer, Acki-Nacki, or Block Keeper in a specific Epoch.

## End-to-End Scenarios

### Happy Path

```
Round R: producer P builds block B on the parent
  -> P signs B and broadcasts it
  -> BKs attest, staggered by distance from P
  -> 50%+1 attestations: B is prefinalized
  -> at least two thirds within beta: B finalizes through primary path
  -> finalization loop commits B and the chain advances
```

### Slow Network

```
Round R: producer P builds B
  -> BKs attest slowly
  -> primary deadline beta passes without 66%
  -> B transitions to fallback path
  -> at 2*beta: if 50%+1 fallback attestations exist, B finalizes
  -> otherwise, B fails and is NACKed
```

### Producer Failure

```
Round R: producer P is offline, no block
  -> BKs detect stall by round timing
  -> send NextRound to the next producer Q
  -> Q collects majority floor(N/2)+1
  -> if someone locked a block: Q broadcasts it as the winner
  -> if nobody did: Q builds a new block if there is time
  -> authority moves to Q
```

### Invalid Block

```
Round R: producer P produced invalid B
  -> some BKs attested without re-execution
  -> an Acki-Nacki verifier re-executes and finds it invalid
  -> the verifier broadcasts NACK
  -> other BKs record the accusation
  -> validation service independently revalidates B
  -> B and all descendants are invalidated
  -> slashing message is included in the next valid block
  -> Authority Switch moves to the next producer
```

### Double-Sign

```
Round R: producer P signed both B1 and B2
  -> both collected attestations
  -> both reached 50%+1 and are prefinalized
  -> sibling resolution detects the same round
  -> protocol violation: slashing
  -> both blocks are cryptographic proof of P's equivocation
```

## Safety, Liveness, and Accountability

**Safety**:

* Prefinalization at `50%+1` implies intersection of quorum sets.
* Honest Block Keepers do not sign conflicting blocks thanks to ActionLock.
* If conflicting proofs still appear, the intersection gives double-sign evidence.
* Finalization requires prefinalization and all validity conditions, so conflicting blocks cannot both become final.

**Liveness**:

* Healthy producer and network within deadline leads to primary finalization.
* Producer stalls are handled by round buckets and authority switch.
* Slow attestations are handled by fallback finalization.
* Round advancement requires only `floor(N/2)+1`, not 66%.
* Lagging nodes recover through block-range requests or finalized state snapshots.

**Accountability**:

* Double-signing is detected through conflicting prefinalization proofs.
* Invalid blocks are detected through lazy revalidation.
* ActionLock durability prevents a Block Keeper from denying what it signed.
* Slashing messages are included in blocks and become part of chain history.

## Key Synchronization Latches

| Layer            | Mechanism                                                   | What It Fixes                       |
| ---------------- | ----------------------------------------------------------- | ----------------------------------- |
| Local node       | **ActionLock** with durable persistence                     | One vote in `(height, round)`       |
| Network, phase 1 | **Prefinalization @ 50%+1**                                 | Branch lock or evidence on conflict |
| Network, phase 2 | **Finalization @ `ceil(2N/3)` / 50%+1 + 8 conditions**      | Irreversibility                     |
| Recovery         | **Authority Switch @ `floor(N/2)+1`** and round buckets     | Progress under failure              |
| Node sync        | **NodeJoining + BlockRequest + SyncFinalized snapshots**    | Catch-up from finalized state       |
| Correctness      | **NACK + lazy revalidation**                                | Filtering invalid blocks            |
| Cross-thread     | **References only to finalized blocks** and `sqrt(N)` delay | Consistency between threads         |
| Economics        | **Stake + Reputation + Mobile Verifiers**                   | Incentives to follow the protocol   |


# Tokenomics

Acki Nacki tokenomics

The original document can be found here [Tokenomics Paper](https://tokenomics.ackinacki.com/).

For personalized projections of token economic metrics and reward amounts, use the [Reward Calculator](https://rewardcalculator.ackinacki.com/).

## Abstract

We present the Acki Nacki network Tokenomics, optimized for maximum decentralization from the start, as well as for security and fairness.\
For more information on the Acki Nacki protocol, refer to the [Acki Nacki Overview](/).

In Acki Nacki, there are five types of Network Participants: Block Producer, Block Keeper, Block Verifier (also known as Acki-Nacki), Block Manager, and Mobile Verifier.

{% hint style="info" %}
We collectively refer to Block Producer, Block Keeper, and Block Verifier as "Block Keepers" when it is unnecessary to distinguish their individual roles.
{% endhint %}

## Definitions

**Block Keeper** - is a network participant that receives blocks from the Block Producer (BP) and sends back an [Attestation](/glossary#attestation) with the block hash and other metadata. A BK can also become a Block Verifier (Acki-Nacki) or a Block Producer (BP)

**Block Producer (BP)** is a BK that serves as the leader of a particular [Thread](/glossary#thread), responsible for block production.

**Block Verifier (or Acki-Nacki)** - is a BK responsible for block validation and notifying all network participants of their verdict: whether the block is valid or not.

**Block Manager -** is a network participant whose primary role is to provide users with a blockchain database and process external messages. Block Managers receive a portion of the total block reward based on the number of external messages they process.

**Mobile Verifier -** participates in the protocol by validating transactions in subtrees of accounts, occasionally. Mobile Verifiers will compete in an online game, which involves earning Boosts, to secure a place in the mobile verifiers list that determines the fraction of block reward.

## Quick Facts

| Token                    | Supply    | Emission     | Function         |
| ------------------------ | --------- | ------------ | ---------------- |
| [NACKL](/glossary#nackl) | 10.4 B    | Curve, final | Network security |
| [SHELL](/glossary#shell) | Unlimited | Pledge       | Computation      |

## Separation of Tokens

In Acki Nacki there are two tokens: a network token and a computation token.

The separation allows us to have two distinctive properties of Acki Nacki that is not possible under a one common token design.

In Proof-of-Stake systems the security of the network and the participation incentives are largely attributed to the network token price increase over time. This is achieved by bending the Supply/Demand curve in favor of Demand. It can be done by increasing the Token Utility and Decreasing the Supply. But when there is only one token which is used for both security guarantees and network transaction fees its utility will be hampered by its increasing price, which happens with every blockchain we know. To tackle this problem Bitcoin is promoting the Lightning network, Ethereum is trying to balance the gas price and Solana is processing large amounts of transactions with very low fees. We don’t believe any of these approaches work over time and we see problems with all of them: Lightning Network adoption rate is faltering, Ethereum transactions are so expensive, most of the people using L2 networks to transact Ethe and Solana can’t regulate its network usage effectively leading to network stoppage and spam.

We take a different approach by introducing two interconnected tokens separately created to optimally perform each of the functions: network usage and network security.

Computation token, called **SHELL** — is designed to pay for network usage, and **NACKL** coin — designed to guarantee network security.

**NACKL** Coin — is used for Staking and provides a claim for a share of Shell revenues therefore will accumulate value over time.

**SHELL** Token — designed in such a way that its price will never increase, it can only decrease, but will eventually correct itself, as described in more details [below](#shell-equal-or-less)

## NACKL Tokenomics

### Proof Of Stake

In Acki Nacki there is no predetermined Stake Interest rate. Simple and clear — there are no staking rewards. Like in Bitcoin the rewards are paid for Network Participation which comprises several activities like Block Production, Block Verification and Transaction Processing, but unlike Bitcoin all the [Rewards](#rewards) are distributed proportionally between all Network Participants within a common Epoche. If Network Participants are not performing according to current Acki Nacki Network rules or boundaries they may be excluded from the network, penalized or slashed depending on the type of rule they violate. This is according to the main idea of [Proof-of-Stake Protocols](https://decred.org/research/king2012.pdf).

### Delegation

Acki Nacki is trying to avoid delegation of stakes as much as possible. There are special mechanisms in place to make it not economical or not secure to delegate NACKL Token for staking by other Block Keepers: Block Keeper Epoch contract only accepts messages signed by a Block Keeper private key, therefore making it impossible to create decentralized pools and perform staking delegation. Of course, Block Keepers can run off-chain services to obtain stakes from investors, but this is no longer a network concern.

Instead there is a special mechanism to include regular participants into a protocol without a need to become a Block Keeper and have special server equipment etc. ([see section “Mobile Verifiers”](#mobile-verifiers)) Yet it is important to mention that it’s not based on staking pools or delegation either, as mobile verifiers perform very particular and real security verification contributing to network security guarantees.

### Fairness

Acki Nacki is "fair" protocol, where fairness is defined per [Pass and Shi](https://dl.acm.org/doi/10.1145/3087801.3087809): "A blockchain protocol has $$n$$-approximate fairness if, with overwhelming probability, any honest subset controlling $$f$$ fraction of the compute power is guaranteed to get at least a $$(1 − n)f$$ fraction of the blocks in a sufficiently long window".

The fairness in Acki Nacki is achieved by the following logical construction:

*Each Validator receives proportional reward regardless of if they produced blocks or not. The reward depends solely on their honest participation in the network as described below. Thus the network participants are not rewarded specifically for producing the block but for participating in all stages of block livecycle from the creation and up to the finality.*

Because in the Asynchronous transaction model the particular arrangement of incoming external transactions does not determine the execution order of subsequent internal transactions, there is no apparent calculable profit extraction (MEV) opportunity exists for a Block Producer. For example, frontrunning is highly improbable and can instead result in a loss. Since the chances of such loss are high enough no rational actor should try. In Acki Nacki therefore there is simply no game to play around MEV extraction, which in turn makes the equal block rewards model possible.

Therefore in Acki Nacki [the fairness model](https://arxiv.org/pdf/2102.04326) that usually applies to most of the networks does not hold true. We therefore can consider Acki Nacki a “fair protocol” at least according to the above definition.

## Rewards

The curve of the number of minted tokens in Acki Nacki is precomputed and known in advance. This curve is an exponential saturation function. It determines the reward for network participants.

The reward in Acki Nacki is divided among three groups of network participants: Block Keepers, Mobile Verifiers, and Block Managers. The reward for each participant is awarded based on individual Epochs of a certain duration. It is precomputed before the start of the individual [**Epoch**](#user-content-fn-1)[^1] and is awarded at the end of that Epoch. The distribution of the reward within each group of network participants is described in more detail in the sections "Block Keeper Reward", "Mobile Verifier Reward", and "Block Manager Reward".

### General Reward

The General Reward for network participation across the entire network is calculated per second to eliminate dependency on blocks and thereby prevent potential spam activity.

General Reward Per Second is an ever decreasing function of token supply calculated as following:

• $$t$$— Time (in seconds) since the network launch

• $$TotalSupply$$ — Total Supply — The total number of tokens to be minted

• $$GRPS(t)$$ — General Reward Per Second — reward for network participation per one second for all network participants

• Total Minted Token Amount — The number of minted tokens at time $$t$$

• $$TTMT$$ — Total Token Minting Time — The expected time for minting the last fraction of token.

• $$TMTAFC$$ — Total Minted Token Amount Function Coefficient — The parameter regulating the decay rate of the Total Minted Token Amount function

• $$TBBKRPS(t)$$ — Total Base Block Keeper Reward Per Second — the fraction of the reward $$GRPS$$ allocated to Block Keepers

• $$TMVRPS(t)$$ — Total Mobile Verifier Reward Per Second — the fraction of the reward $$GRPS$$ allocated to Mobile Verifiers

• $$TBMRPS(t)$$ — Total Block Manager Reward Per Second — the fraction of the reward $$GRPS$$ allocated to Block Managers

• $$BBKRFC$$ — Base Block Keeper Reward Function Coefficient — coefficient that determines the fraction of the reward $$GRPS$$ allocated to Block Keepers

• $$MVRFC$$ — Mobile Verifier Reward Function Coefficient — coefficient that determines the fraction of the reward $$GRPS$$ allocated to Mobile Verifiers

• $$BMRFC$$ — Block Manager Reward Function Coefficient — coefficient that determines the fraction of the reward $$GRPS$$ allocated to Block Managers

<figure><img src="/files/R4AfUOGaHafedP4eBufx" alt=""><figcaption><p>Formulas 1, 2, 3</p></figcaption></figure>

The resulting reward is divided among the three groups of network participants in predetermined proportions, calculated based on each group’s contribution to the network’s operation.

<figure><img src="/files/gd6dvbdCHqsvA7yqQ1fE" alt=""><figcaption><p>Formulas 4, 5</p></figcaption></figure>

<figure><img src="/files/zoN6TR60Us1vk210EqHD" alt="" width="563"><figcaption><p>Figure 1: Comparison plot of Bitcoin and Acki Nacki NACKL token supplies per year</p></figcaption></figure>

### Reputation Coefficient

For Block Keepers, the reward they receive from $$GRPS$$ is called the Base Reward. This is because on top of the fair block reward, each Block Keeper may receive a Reputation Premium Reward called the Reputation Coefficient. This reward is calculated based on the time the particular Block Keeper, authenticated as Public Key of the cryptographic key pair, controlling the Block Keeper’s wallet has continuously participated in a protocol and restaked their tokens.

The reputation multiplicator can provide much greater rewards than Base Reward, thus providing incentives for Block Keepers to keep uninterrupted network validation.

If a Block Keeper skips at least one Epoch, their Reputation Coefficient is immediately reset to the minimum possible one.

* $$RepCoef$$ — Reputation Coefficient — Additional rewards granted to a Block Keeper for continuous validation
* $$BKRT$$ — Block Keeper Reputation Time — The time during which the Block Keeper has been continuously running validation Epochs
* $$minRC$$ — Minimal Reputation Coefficient
* $$maxRC$$ — Maximal Reputation Coefficient
* $$maxRT$$ — Maximal Reputation Time — The time it takes for the Block Keeper to accumulate maximum reputation for continuous validation
* $$ARFC$$ — Adjustment Reputation Function Coefficient — The parameter regulating the rate of reputation growth over time

<figure><img src="/files/JmEK8WrGEP6czwuU9fDT" alt=""><figcaption><p>Formula 6</p></figcaption></figure>

<div align="center"><figure><img src="/files/NCj5sDKgrAA6K0T0XaUr" alt="" width="559"><figcaption><p>Figure 2: Plot of the Reputation Coefficient depending on the continuous validation time by a particular Block Keeper</p></figcaption></figure></div>

### Block Keeper Reward

As mentioned earlier, each network participant receives a reward for each Epoch. For Block Keepers, we will refer to this Epoch as the Validation Epoch.

We assume that if all network participants act honestly, the reward should be distributed fairly among them, regardless of whether the Block Keeper performs as a Block Producer, Acki-Nacki, or Block Keeper during that Epoch. Thus, the Block Keeper’s reward will depend only on their stake and Reputation Coefficient.

Therefore, the Block Keeper’s reward function $$BKRPS$$ will be calculated as follows:

* $$BKRPS$$ — Block Keeper Reward Per Second — the reward earned by a Block Keeper per second of validation, depending on their stake and current Reputation Coefficient
* $$BKStake$$ — Block Keeper Stake — the specific amount of tokens that a Block Keeper has staked in order to participate in validation
* TotalBKStake — Total Block Keeper Stake — the sum of all Block Keeper stakes at time
* $$TBBKRPS(t)$$ — Total Base Block Keeper Reward Per Second — the fraction of the reward GRPS allocated to Block Keepers
* $$RepCoef$$ — Reputation Coefficient — Additional rewards granted to a Block Keeper for continuous validation
* $$BKRT$$ — Block Keeper Reputation Time — The time during which the Block Keeper has been continuously running validation Epochs
* $$t\_{val}$$ — Validation Epoch Start Time — the time in seconds that has passed from the moment the network was launched until the start of a particular Validation Epoch
* $$BKRPVE$$ — Block Keeper Reward per Validation Epoche — the reward received by a Block Keeper for one Validation Epoch
* $$BKED$$ — Block Keeper Epoch Duration — the duration of one validation Epoch in seconds

<figure><img src="/files/fmgtJK48Xwpl8wKJHOPs" alt=""><figcaption><p>Formula 7</p></figcaption></figure>

For personalized projections of token economic metrics and reward amounts, use the [Reward Calculator](https://rewardcalculator.ackinacki.com/).

#### Block Keeper Epoch Reward

Since a Block Keeper receives a reward at the end of each Validation Epoch, let us convert the reward per second of validation into a reward per Epoch.

To ensure that each Block Keeper can easily calculate their reward for the Validation Epoch at the start of the Epoch, we lock the parameters $$BKStake$$, $$TotalBKStake$$, and $$RepCoef$$ at the beginning of the Epoch and don’t change them during the Epoch. Since the number of Block Keepers in the network remains approximately constant during a Block Keeper’s Epoch, the case where the parameters $$BKStake$$ and $$TotalBKStake$$ are fixed at the start of the Epoch is practically identical to the case where these parameters are dynamically recalculated throughout the Epoch. In other words, for a reasonable Block Keeper, it is disadvantageous to choose the moment when he starts an Epoch to maximize their reward, as the time spent waiting will cause them to lose more reward than they could potentially earn, and they will also reset their accumulated Reputation Coefficient. Additionally, since the Maximal Reputation Coefficient accumulates over a much longer period of time than the duration of a Validation Epoch, it does not make practical sense to recalculate it during an Epoch. It is sufficient to update the value of the Reputation Coefficient when transitioning from one Epoch to the next. For the same reason, it does not make practical sense to recalculate the value of the $$TBBKRPS$$ function during the Validation Epoch.

Thus, let us calculate the reward for a single Block Keeper for the Validation Epoch:

<figure><img src="/files/uPJdFN0m0OexRgg6WhzR" alt=""><figcaption><p>Formula 8</p></figcaption></figure>

If a Block Keeper, for any reason, validates longer than the expected duration of a single Epoch, additional time spent as a Block Keeper will be added to the parameter $$BKED$$.

## Free Float

Acki Nacki largely follows a well-researched Bitcoin free float model. We define Bitcoin’s Free Float as the number of tokens that have been in circulation over the last year. While in Bitcoin the free float average is around 40%, Acki Nacki will theoretically experience exponential saturation growth from nearly 0 to $$\dfrac{1}{3}$$, while $$(1 − Free Float)$$ $$(1 − Free Float)$$of tokens (up to a maximum of $$\dfrac{2}{3}$$) will be locked in staking.

Let’s construct the exponential saturation function for the Free Float (as a percentage of the total number of minted tokens):

* $$maxFreeFloatFrac$$ — Maximal Free Float Fraction — Maximal fraction of Free Float of Total Supply
* $$FreeFloatFrac(t)$$$$(t)$$ — Free Float Fraction — The current fraction of Free Float of Total Supply
* $$FFFC$$ — Free Float Function Coefficient – The parameter regulating the decay rate of the FreeFloatFrac function
* $$TTMT$$ — Total Token Minting Time — The expected time for minting the last fraction of token

<figure><img src="/files/mw2IN36CHe8jcQ1n1Z2n" alt=""><figcaption><p>Formulas 9, 10</p></figcaption></figure>

If Block Keepers do not restake their stakes and withdraw them, thereby increasing the Free Float, the reward remains fixed. Meaning the remaining Block Keepers will start receiving more rewards, which will reduce their motivation to withdraw their stakes even if the token price decreases. Because the min stake will decrease, allowing other Block Keepers to stake their tokens if they couldn’t do so before ([see Section "Block Keeper Min Stake"](#block-keeper-min-stake)).

<figure><img src="/files/bw35zCnkfE45l8eqIoGb" alt="" width="546"><figcaption><p>Figure 3: Plot of the total number of minted tokens and free float (in tokens) over time</p></figcaption></figure>

<figure><img src="/files/1pUmHjMnMRYPMq5NG1Ik" alt="" width="547"><figcaption><p>Figure 4: Comparison plot of Bitcoin and Acki Nacki NACKL Free Floats (as a percentage of the current Supply) per year</p></figcaption></figure>

<figure><img src="/files/XufH18MLKhi2CQ6IjBOy" alt="" width="545"><figcaption><p>Figure 5: Comparison plot of Bitcoin and Acki Nacki NACKL Free Floats (as a percentage of the Total Supply) per year</p></figcaption></figure>

## Block Keeper Min Stake

Because Acki Nacki is a scalable computational network the execution load parameter plays a significant role in its tokenomics.

Acki Nacki is a multithreaded execution environment. Threads grow when computation demand on the network grows, more Block Keepers are required to process the network load. Usually one would argue the rewards should grow to lure more Block Keepers into the network. But that won’t work because of a “spam attack”. In the Spam Attack the Block Keeper may create spam transactions to artificially increase network load so that threads are multiplied to inflate the block rewards. And since in Acki Nacki the payment for computations (electricity) is [stable or less](#shell-equal-or-less) the arbitrage between the compute expanse and block reward is always beneficial to the attacker. Therefore no increase of the Block Reward is possible. Instead the minimum required stake is lowered automatically. Thus allowing lower barriers to entry for new Block Keepers to provide their computing power to participate in a slice of a block rewards. And since Reputation Coefficient plays a much greater role in the Block reward for each Block Keeper over time, it provides a lucrative opportunity for profitable network participation.

* $$NeedBKNum(t)$$ — Needed Block Keeper Number — The number of Block Keepers required in the network at time $$t$$ according to the number of threads
* $$baseMinBKStake(t)$$ — Base Minimal Block Keeper Stake — Minimal Stake when the current number of Block Keepers equals the necessary number of Block Keepers
* $$FreeFloatFrac(t)$$— Free Float Fraction — The current fraction of Free Float of Total Supply
* $$TSTA(t)$$— Total Staked Token Amount — The total number of tokens staked in the network at time $$t$$
* $$BKSFC$$ — Block Keeper Stake Function Coefficient — The coefficient that determines the expected fraction of tokens that will be staked by Block Keepers out of the Total Staked Token Amount
* $$MVSFC$$ — Mobile Verifier Stake Function Coefficient — The coefficient that determines the expected fraction of tokens that will be staked by Mobile Verifiers out of the Total Staked Token Amount
* $$BMSFC$$ — Block Manager Stake Function Coefficient — The coefficient that determines the expected fraction of tokens that will be staked by Block Managers out of the Total Staked Token Amount
* $$TMTA(t)$$— Total Minted Token Amount — The number of minted tokens at time $$t$$
* $$BBKRFC$$ — Base Block Keeper Reward Function Coefficient — coefficient that determines the fraction of the reward GRPS allocated to Block Keepers
* $$MVRFC$$ — Mobile Verifier Reward Function Coefficient — coefficient that determines the fraction of the reward GRPS allocated to Mobile Verifiers
* $$BMRFC$$ — Block Manager Reward Function Coefficient — coefficient that determines the fraction of the reward GRPS allocated to Block Managers
* $$t\_{val}$$ — Validation Epoch Start Time — the time in seconds that has passed from the moment the network was launched until the start of a particular Validation Epoch

The total number of staked tokens is easily calculated from the known total number of minted tokens and the current free float:

<figure><img src="/files/oTe8wvz9iUi1GWzQPnYv" alt=""><figcaption><p>Formula 11</p></figcaption></figure>

Since in Acki Nacki, not only Block Keepers stake but also Mobile Verifiers and Block Managers (see sections "[Mobile Verifier Min Stake](#mobile-verifier-min-stake)", "[Block Manager Min Stake](#block-manager-min-stake)"), let the distribution of their stake from the total number of staked tokens be the same as the reward distribution ([formula 4](#general-reward)):

<figure><img src="/files/C9VETJL4ymh8ScVFtbxa" alt=""><figcaption><p>Formulas 12</p></figcaption></figure>

From which it follows:

<figure><img src="/files/v1fTf5EnFXl0rFtbLCMY" alt=""><figcaption><p>Formula 13</p></figcaption></figure>

Since each Validation Epoch for a Block Keeper requires time to verify the correctness of all Block Keepers’ actions, half of the staked tokens is locked in the current validation cycle, and the other half of the staked tokens is locked in the cooling period for slashing calculation. Therefore, each Block Keeper effectively needs to have two stakes to validate.

Let’s calculate $$baseMinBKStake$$ for Block Keepers, taking into account that the minimum stake should be calculated at the start of the Validation Epoch:

<figure><img src="/files/2DqZgtBR6tHG4gRoVK4P" alt=""><figcaption><p>Formula 14</p></figcaption></figure>

<figure><img src="/files/LHFAa6NjxXWZWRwuPGxP" alt="" width="563"><figcaption><p>Figure 6: Plot of baseMinBKStake over time since the network’s launch with the necessary number of Block Keepers set to 10, 000</p></figcaption></figure>

## Expected APR for Block Keepers

While we are not keen to use terms like Annual Percentage Reward while talking about Acki Nacki staking, it is still important to provide such indicative calculations on the rewards Block Keeper receive for performing Network Participation work in comparison with NACKL Stake they provide as security bond. Please note that we omit all direct Block Keeper operation costs as they are compensated by SHELL Token as described below.

<figure><img src="/files/mBRoyVCHXA1SbAPZUuYS" alt="" width="553"><figcaption><p>Figure 7: APR plot for the first 5 years after network launch</p></figcaption></figure>

<figure><img src="/files/K8j3q9uVRYypv8zobTFH" alt="" width="548"><figcaption><p>Figure 8: APR plot over time</p></figcaption></figure>

<figure><img src="/files/awtUDRQjJjkAaPAmt1Y0" alt="" width="551"><figcaption><p>Figure 9: APR Plot with a logarithmic Y-axis over time</p></figcaption></figure>

## Security Guarantees

The main function of NACKL Token is to provide Network Security guarantees and now we will discuss in more details how this function is performed.

**Lemma 1.** *Total of NACKL min stakes for Block Keepers will make it virtually impossible to attack the network because the sum of money that will be required to collect it for successful attack with probability set by network parameters does not exist in the world economy.*

$$Proof.$$

* $$BKNum$$ — number of Block Keepers
* $$ANNum$$ — average number of Acki-Nacki per block
* $$AtNum$$ —number of attestations required for block finalization
* $$MalBKNum$$ — expected number of malicious Block Keepers
* $$SAP$$ — successful attack probability in a single attempt
* $$FFT$$ — current Free Float (in tokens)
* $$FFTReduction$$ — The coefficient describing how much the Free Float (in tokens) decreased after purchasing tokens for the attack
* $$MAA$$ — Maximum Attack Attempts — Maximum number of attack attempts that the attacker can perform
* $$BNP$$ — Breaking Network Probability — The probability of performing a successful attack on the network in $$MAA$$ attempts
* $$MalStakeNum$$ — Malicious Stake Number — The number of stakes that a malicious Block Keeper needs to purchase for an attack with a probability of $$BNP$$
* $$minBKStake(t)$$ — Minimal Block Keeper Stake — Current minimal Block Keeper stake depending on the particular difference between the current number of Block Keepers and the required number of Block Keepers

**Assumption:** our Bitcoin analysis of free float contribution to the price increase shows that a decrease by 5% of free float leads to doubling of the Bitcoin price over time regardless of existing market demand.

Let’s consider how the probability of an attack and the reduction of Free Float depend on each other. For simplicity, let’s consider the case without Mobile Verifiers, as their presence would only reduce the probability of an attack.

The probability of a successful attack in one attempt:

<figure><img src="/files/WuBoZI8UASzrbdPXOVBQ" alt=""><figcaption><p>Formula 15</p></figcaption></figure>

The probability that the attacker successfully breaks the network in $$i$$ attempts is given by:$$(1 − SAP)^{i−1} \* SAP$$

Let’s sum this probability over all possible numbers of attempts by the attacker and obtain the probability $$BNP$$:

<figure><img src="/files/GKyKjDEm3HMMN3yzdkaw" alt=""><figcaption><p>Formulas 16, 17, 18, 19</p></figcaption></figure>

{% hint style="info" %}
Note that the $$BNP$$ $$(MalBKNum)$$ function will be concave downwards, meaning that a malicious Block Keeper benefits either from attacking many times with a single malicious node or attacking once with multiple malicious nodes.
{% endhint %}

From this it follows that:

<figure><img src="/files/7JrNNJ8ZNLsGWtPS563F" alt=""><figcaption><p>Formula 20</p></figcaption></figure>

If the $$BNP$$ parameter is known,\
then $$MalStakeNum = min (MalStakeNum\_1, MalStakeNum\_2)$$, where

<figure><img src="/files/jnrcW2D9PyX22OvxQQUf" alt=""><figcaption><p>Formula 21</p></figcaption></figure>

and

<figure><img src="/files/G9P0nBeU9RoCMAK4HyxU" alt=""><figcaption><p>Formula 22</p></figcaption></figure>

Therefore

<figure><img src="/files/oA2Ez6jcrvd5nv6MCbEm" alt=""><figcaption><p>Formula 23</p></figcaption></figure>

Even if we do not take into account that the minimum stake increases when the number of Block Keepers exceeds the required amount, we will see a significant reduction in Free Float:

1. In the case of an attack with multiple attempts, due to token burning after slashing a malicious network participant, which will iteratively increase the cost of the attack.
2. In the case of a one-time attack at the moment of purchasing tokens for the attack. Every 5% reduction in Free Float will double the cost of the attack.

Example calculation of $$MalStakeNum$$ with\
$$BKNum = 1000$$,\
$$ANNum = 40$$,\
$$AtNum = 800$$,\
$$BNP = 10^{−8}$$:

<figure><img src="/files/Mw4pu6eGPk9OcuDeHkhi" alt=""><figcaption><p>Formula 24</p></figcaption></figure>

With 1000 Block Keepers,\
$$FFT$$ $$FFT = 2, 253, 808, 534$$ tokens,\
$$minBKStake = 2, 253, 808$$ tokens:

<figure><img src="/files/pTo9MXWrsW3cFoJBDluD" alt=""><figcaption><p>Formula 25</p></figcaption></figure>

This reduction in Free Float increases the token price by $$2^{ln(0.65)/ln(0.95)} = 2^{8.38} = 331.31$$ times, making it practically impossible to collect that much money to purchase tokens for the attack.

## Mobile Verifiers

### Motivation$$f(x) = x \* e^{2 pi i \xi x}$$

Ideally we would want a protocol that everyone can participate in without a need to run expensive server hardware. That would dramatically increase network security and decentralization. From the other side such a network would not be very performant, fast and scalable because of network and computing power limitation of mobile devices.

To solve this we introduce the Mobile Verifier role to Acki Nacki. A mobile user would not need to validate every block on the network, which would be technically impossible, but instead such a user could participate in the protocol as a Verifier by validating transactions in subtrees of accounts, occasionally. Since there is no way to know when such a user would choose to Verify, it would provide additional security guarantees to the network, dramatically decreasing the probability of attack on top of the already great security guarantees of the main Acki Nacki Protocol.

* $$BKNum$$ — number of Block Keepers
* $$ANNum$$ — average number of Acki-Nacki per block
* $$AtNum$$ — number of attestations required for block finalization
* $$MalBKNum$$ — expected number of malicious Block Keepers
* $$MVNum$$ — number of Mobile Verifiers
* $$MalMVNum$$ — expected number of malicious mobile verifiers
* $$λ\_{MV}$$ — verification frequency by Mobile Verifiers — fraction of blocks verified by Mobile Verifiers
* $$MVRPS$$ — Mobile Verifier Reward per Second (accrued only on the condition of owning at least one Boost)
* $$TMVRPS(t)$$ — Total Mobile Verifier Reward Per Second — the fraction of the reward $$GRPS$$ allocated to Mobile Verifiers.
* $$MVStake$$ — Mobile Verifier Stake
* $$TotalMVStake$$ — Total Mobile Verifier Stake of all Block Keepers who have at least one boost
* $$BoostCoef$$ — Boost Coefficient — a coefficient that determines the fraction of the reward allocated to a particular Mobile Verifier based on their position in the sorted in ascending order list of all Mobile Verifiers by the number of boosts. The sum of $$BoostCoef$$ for all Mobile Verifiers equals 1.
* $$SAP$$ — successful attack probability in a single attempt
* $$SAP\_{MV}$$ — successful attack probability in a single attempt with Mobile Verifiers

<figure><img src="/files/2OeYpmK72cqeHrTJAUzM" alt=""><figcaption><p>Formulas 26, 27</p></figcaption></figure>

For the reference, next Figs. are illustrating the successful attack probability from a number of malicious network participants for Bitcoin, pBFT, and Acki Nacki protocols with a total of 1000 Block Keepers.

To calculate the successful attack probability in Bitcoin, we use the commonly accepted number of blocks for probabilistic ’finality’, which is 6. For calculating the successful attack probability in Acki Nacki, we use the number of Acki-Nacki set to 40 and the number of Attestations set to 80.

<figure><img src="/files/AEFvenlqWlwdZapTKUQP" alt="" width="527"><figcaption><p>Figure 10: Comparison of successful attack probabilities in Bitcoin, pBFT and Acki Nack</p></figcaption></figure>

<figure><img src="/files/PNNeTgHFcusqhajOQrXI" alt="" width="535"><figcaption><p>Figure 11: Fig. 10 with log-scaled y-axis</p></figcaption></figure>

### Mobile Verifier Reward

Mobile Verifiers will compete in an online game, which involves earning Boosts, to secure a place in the mobile verifiers list that determines the fraction of block reward they will receive:

<figure><img src="/files/rDMZHtYotDmx0ik6nurT" alt=""><figcaption><p>Formula 28</p></figcaption></figure>

### Boost Coefficient

Our task will be to determine BoostCoef for each Mobile Verifier. To do this, we will create an exponential curve consisting of several sub-curves such that:

1. The domain of the curve will be $$Dom(f ) = \[0, 1]$$, allowing us to distribute the Total Mobile Verifiers Reward regardless of the number of Mobile Verifiers.
2. The integral over the entire domain of the curve equals 1, so we can divide the Total Mobile Verifiers Reward among all Mobile Verifiers.
3. • The first 30% of Mobile Verifiers will receive almost no reward.\
   • The middle 40% will receive 30% of the total reward.\
   • The last 30% with the most boosts will receive 70% of the total reward.

#### Form of the Exponential Curve

An exponential curve with a growth coefficient $$k$$, passing through the points $$(x1, y1)$$ and $$(x2, y2)$$, is defined as follows:

<figure><img src="/files/VXBtzaIUUipS8e3TnAaw" alt=""><figcaption><p>Formula 29</p></figcaption></figure>

Thus, we obtain a function with the following input parameters:

* $$Dot1 = (x1, y1)$$ — The leftmost point of the first sub-curve
* $$Dot2 = (x2, y2)$$ — The connection point between the first and second sub-curves
* $$Dot3 = (x3, y3)$$ — The connection point between the second and third sub-curves 16
* $$Dot4 = (x4, y4)$$ — The rightmost point of the third sub-curve
* $$k1$$ — the growth coefficient of the first sub-curve
* $$k2$$ — the growth coefficient of the second sub-curve
* $$k3$$ — the growth coefficient of the third sub-curve

<figure><img src="/files/nJan7I5DjJZM642CPrrJ" alt=""><figcaption><p>Formula 30</p></figcaption></figure>

Let us denote these sub-curves as I, II, and III.

<figure><img src="/files/gy2ggBrwRG1SOTEehPjC" alt="" width="557"><figcaption><p>Figure 12: Boost Coefficient Curve</p></figcaption></figure>

#### Calculation of Parameters for the Piecewise Exponential Curve

As mentioned earlier (refer to the relevant section), let $$x\_1 = 0$$, $$x\_2 = 0.3$$, $$x\_3 = 0.7$$, and $$x\_4 = 1$$.\
We will empirically choose the following parameters for the curves: $$k\_1 = 10$$, $$y\_3 = 2$$, $$y\_4 = 8$$.

The curve starts at the point $$y\_1 = 0$$. This means that a Mobile Verifier with the fewest Boosts receives almost no reward. (This could be adjusted to provide a very minimal reward, but for simplicity, we’ll leave it as is for now.)

Now we need to find the parameters $$y\_2$$, $$k\_2$$, and $$k\_3$$. To do this, we will calculate the integral for each sub-curve and, based on [point 3](#boost-coefficient), equate these integrals to the following values:

<figure><img src="/files/BH2mpmEHQTE6CbiBHAqd" alt=""><figcaption></figcaption></figure>

Let’s calculate these definite integrals:

<figure><img src="/files/QizdIH48bwGJOPBHbqu5" alt=""><figcaption><p>Formula 31</p></figcaption></figure>

Let’s construct a system of three equations for the three unknowns $$y\_2$$, $$y\_3$$, and $$y\_4$$:

<figure><img src="/files/LeRJixEGGALjvyoL8E06" alt=""><figcaption><p>Formula 32</p></figcaption></figure>

The analytical solution to this system of equations would be too large to include in this document, so we will immediately substitute the known parameter values $$x\_1, x\_2, x\_3, x\_4, y\_1, y\_3, y\_4, k\_1, q\_1, q\_2, q\_3$$ and obtain the following values for $$y\_2, k\_2, k\_3$$:

<figure><img src="/files/nu7TB3mIieLTEdhVzyFX" alt=""><figcaption><p>Formula 33</p></figcaption></figure>

Thus, we have obtained the curve with all known parameters.

#### Calculation of the Boost Coefficient for Different Numbers of Mobile Verifiers

Now, we need to calculate $$BoostCoef$$ from the known function $$BoostCoefFunc$$.\
For this, we introduce the parameter for the number of Mobile Verifiers $$MVNum$$.

The reward of a Mobile Verifier, who is in the i-th position in the list sorted in ascending order of the number of Boosts, will be calculated as the integral over the subinterval corresponding to this Mobile Verifier. In other words, we will divide the interval $$\[0, 1]$$ into $$MVNum$$ parts, and the$$i$$-th Verifier will correspond to the interval  $$\[\frac{i-1}{MVNum},\frac{i}{MVNum}]$$ .

That is,

<figure><img src="/files/dLppI92AEnNLWPo4GY6l" alt=""><figcaption><p>Formula 34</p></figcaption></figure>

#### Mobile Verifier Min Stake

* $$TSTA(t)$$ — Total Staked Token Amount — The total number of tokens staked in the network at time $$t$$
* $$TMTA(t)$$ — Total Minted Token Amount — The number of minted tokens at time $$t$$
* $$MVRH$$ — Mobile Verifier Reward History — Amount of tokens that Mobile Verifier have earned during their entire participation in the network
* $$minMVStake(t)$$ — Minimal Mobile Verifier Stake — Current minimal particular Mobile Verifier stake
* $$FreeFloatFrac(t)$$ — Free Float Fraction — The current fraction of Free Float of Total Supply

The size of the Mobile Verifier’s stake does not affect their reward ([formula 30](#mobile-verifier-reward)), only the presence of the Min Stake on the Mobile Verifier’s wallet matters. For Mobile Verifiers, there is no point in dynamically adjusting the stake based on the current number of Mobile Verifiers (as is done for Block Keepers), since it is impossible to determine the required number of Mobile Verifiers. Therefore, each Mobile Verifier’s Min Stake will be unique and depend solely on the amount of tokens MVRH they have earned during their entire participation in the network. The Min Stake of a Mobile Verifier will be a fraction of the MVRH parameter, just as the Total Staked Token Amount TSTA is a fraction of the Total Minted Token Amount TMTA ([11](#block-keeper-min-stake)), provided that the Mobile Verifier must have two stakes for the same reasons as for Block Keepers.

<figure><img src="/files/Ij8d5iOkL7cM1bd3ac6H" alt=""><figcaption><p>Formula 35</p></figcaption></figure>

If a Mobile Verifier does not have enough tokens in their wallet to place the stake for the next Epoch, their number of Boosts is reset to zero.

#### Mobile Verifier Epoch Reward

* $$MVED$$ — Mobile Verifier Epoch Duration — the duration of one Epoch of Mobile Verifiers in seconds
* $$MVRPE$$ — Mobile Verifier Reward per Epoche — the reward received by a Mobile Verifier for one Epoch
* $$BoostCoef$$ — Boost Coefficient — a coefficient that determines the fraction of the reward allocated to a particular Mobile Verifier based on their position in the sorted in ascending order list of all Mobile Verifiers by the number of boosts. The sum of $$BoostCoef$$ for all Mobile Verifiers equals 1.
* $$TMVRPS(t)$$ — Total Mobile Verifier Reward Per Second — the fraction of the reward $$GRPS$$ allocated to Mobile Verifiers
* $$t\_{verf}$$ — Verification Epoch Start Time — the time in seconds that has passed from the moment the network was launched until the start of a particular Epoch of Mobile Verifiers

The Epoch of Mobile Verifiers, unlike the Epochs of Block Keepers, is common for all Mobile Verifiers. The first Epoch starts when the network is launched, and after that, the current Block Producer must send a message to the Epoch contract. If at least $$ $MVED $$ seconds have passed since the start of the Epoch, all Mobile Verifiers will receive the reward for the Epoch $$MVRPE$$, and the next Epoch will begin for them. The current $$BoostCoefficient$$ is locked at the beginning of each Epoch for its entire duration and updated after the Epoch ends to prevent unnecessary continuous calculations, as the number of Boosts for Mobile Verifiers changes with high frequency. $$TMVRPS$$ is locked at the beginning of the Epoch, as its changes during the epoch are negligible.

<figure><img src="/files/qtqBentaCUxkUJ7Z1mYt" alt=""><figcaption><p>Formula 36</p></figcaption></figure>

## Block Managers

The primary function of Block Managers is to provide the user with a blockchain database and to process external messages. Block Managers receive a portion of the total block reward based on the number of external messages they process. The reward distribution is structured in such a way that spamming the network with external messages to increase rewards is not practically beneficial. This is because generating spam external messages requires certain resources, and the reward increase will slow down significantly if the number of external messages processed by a specific Block Manager exceeds the average number of processed messages across all Block Managers.

### Block Manager Reward

Block Managers do not have a stake because they do not verify transactions and do not impact network security. Therefore, their reward depends only on the number of external messages they processed.

* $$BMRPS$$ — Block Manager’s Reward per Second
* $$TBMRPS(t)$$ — Total Block Manager Reward Per Second — the fraction of the reward $$GRPS$$ allocated to Block Managers.
* $$ExtMesCoef$$ — External Messages Coefficient — the coefficient that determines the fraction of the reward allocated to a particular Block Manager based on their position in the sorted in ascending order list of all Block Managers by the number of processed external messages. The sum of $$ExtMesCoef$$ for all Block Managers equals 1.
*

The reward for Block Managers is calculated using the following formula:

<figure><img src="/files/n4uUZCIg97A0cAwGUKWj" alt=""><figcaption><p>Formula 37</p></figcaption></figure>

For personalized projections of token economic metrics, use the [Reward Calculator](https://rewardcalculator.ackinacki.com/).

### External Messages Coefficient

Let’s determine $$ExtMesCoef$$ for each Block Manager. To do this, we create a complex curve consisting of several sub-curves such that:

1. The domain of the curve will be $$Dom(f ) = \[0, 1]$$, allowing us to distribute the Total Block Managers Reward regardless of the number of Block Managers.
2. The integral over the entire domain of the curve equals 1, so we can divide the Total Block Managers Reward among all Block Managers.
3. • The first 10% of Block Managers will receive almost no reward.\
   • The top 90% will receive almost the entire reward.

#### Form of the Curve

If we establish a direct proportionality between the reward received by a Block Manager and the number of transactions they process, some Block Managers may be incentivized to carry out a spam attack on the network with fake transactions to receive the entire reward. To prevent this, we designed the following $$ExtMesCoefFunc$$ curve, based on the model we had developed for Mobile Verifiers.

* $$Dot1 = (x1, y1)$$ — The leftmost point of the first sub-curve
* $$Dot2 = (x2, y2)$$ — The connection point between the first and second sub-curves
* $$Dot3 = (x3, y3)$$ — The rightmost point of the second sub-curve
* $$k1$$ — the growth coefficient of the first sub-curve

<figure><img src="/files/wQkR3WEUeAIIfhRSRiuM" alt=""><figcaption><p>Formula 38</p></figcaption></figure>

Let us denote these sub-curves as I, II.

<figure><img src="/files/1Oriz1j9ao8TTQTmGxxy" alt="" width="563"><figcaption><p>Figure 13: External Messages Coefficient Curve</p></figcaption></figure>

#### Calculation of Parameters for the Piecewise Curve

As mentioned earlier, let $$x\_1 = 0, x\_2 = 0.1, x\_3 = 1$$.

To remove the incentive for a spam attack on the network, we analyzed the curve and empirically chose the following parameter for the curve: $$y\_3 = 1.2$$.

The curve starts at the point $$y\_1 = 0$$.

This means that a Block Manager with the smallest number of processed external messages will receive almost no reward. Now we need to find the parameters $$y\_2$$, $$k\_1$$. To do this, we will calculate the integral for each sub-curve and, based on point 3, equate these integrals to the following values:

<figure><img src="/files/rFeVmGxInR6i8rYb1fkl" alt=""><figcaption></figcaption></figure>

Let’s calculate these definite integrals:

<figure><img src="/files/xUaHBCsCaiV9FZRBrAwt" alt=""><figcaption><p>Formula 39</p></figcaption></figure>

Let’s construct a system of two equations for the two unknowns $$y\_2$$, $$k\_1$$:

<figure><img src="/files/aLI0H2gkxj8mR0uUW6cd" alt=""><figcaption><p>Formula 40</p></figcaption></figure>

For simplicity, we directly substitute the known parameter values $$x\_1, x\_2, x\_3, y\_1, y\_3, q\_1, q\_2$$ and obtain the following values for $$y\_2, k\_1$$:

<figure><img src="/files/0nEviueqKKvgcZh8kEZh" alt=""><figcaption><p>Formula 41</p></figcaption></figure>

Thus, we have obtained the curve with all known parameters.

#### Calculation of the External Messages Coefficient for Different Numbers of Block Managers

Now, we need to calculate $$ExtMesCoef$$ from the known function $$ExtMesCoefFunc$$. For this, we introduce the parameter for the number of Block Managers $$BMNum$$.

By analogy with the Mobile Verifiers, we define the reward for the Block Manager who is in the i-th position in the list sorted in ascending order of the number of processed external messages, will be calculated as the integral over the subinterval corresponding to this Block Manager. In other words, we will divide the interval $$\[0, 1]$$ into $$BMNum$$ parts, and the $$i$$-th Manager will correspond to the interval  $$\[\frac{i-1}{BMNum},\frac{i}{BMNum}]$$.

That is,

<figure><img src="/files/1Ou3Ix7WaBmoEWKEUtuL" alt=""><figcaption><p>Formula 42</p></figcaption></figure>

### Block Manager Min Stake

* $$BMRH$$ — Block Manager Reward History — Amount of tokens that Block Manager have earned during their entire participation in the network
* $$minBMStake(t)$$ — Minimal Block Manager Stake — Current minimal particular Block Manager stake
* $$FreeFloatFrac(t)$$ — Free Float Fraction — The current fraction of Free Float of Total Supply

Similarly to [Mobile Verifiers](#mobile-verifier-min-stake), the reward of a Block Manager does not depend on the amount of stake they place but only on the presence of the Min Stake. The Min Stake of each Block Manager is unique and depends solely on the amount of tokens they have earned during their participation in the network $$BMRH$$. As with [Block Keepers](#block-manager-min-stake) and Mobile Verifiers, two stakes are required to continuously participate in the network:

<figure><img src="/files/gU8HgggeiAQhnH8NM4xt" alt=""><figcaption><p>Formula 43</p></figcaption></figure>

### Block Manager Epoch Reward

* $$BMED$$ — Block Manager Epoch Duration — the duration of one Epoch of Block Managers in seconds
* $$BKRPE$$ — Block Manager Reward per Epoche — the reward received by a Block Manager for one Epoch
* $$ExtMesCoef$$ — External Messages Coefficient — the coefficient that determines the fraction of the reward allocated to a particular Block Manager based on their position in the sorted in ascending order list of all Block Managers by the number of processed external messages. The sum of $$ExtMesCoef$$ for all Block Managers equals 1.
* $$TBMRPS(t)$$ — Total Block Manager Reward Per Second — the fraction of the reward $$GRPS$$ allocated to Block Managers
* $$t\_{manage}$$ — Management Epoch Start Time — the time in seconds that has passed from the moment the network was launched until the start of a particular Epoch of Block Managers

Similarly to [Mobile Verifiers](#mobile-verifier-epoch-reward), the Epoch of Block Managers is common for all Block Managers and starts and ends after a message is sent to the contract by the Block Producer. $$ExtMesCoef$$ is calculated each time at the end of the epoch and reset after its completion. This means that the reward of a Block Manager is influenced only by their position in the sorted in ascending order list of all Block Managers by the number of processed external messages at the end of the epoch. $$TVMRPS$$ is locked at the beginning of the Epoch, as its changes during the epoch are negligible.

<figure><img src="/files/M3AaMnOTt8jxjsCPYSeB" alt=""><figcaption><p>Formula 44</p></figcaption></figure>

## SHELL — Equal or Less

SHELL is a network usage token, designed to provide compensation for Block Keepers for their computing resources. Anyone who wishes to execute a transaction on Acki Nacki needs to pay Block Keepers for their computing resources and storage. Since main expenses for running a Block Keeper are electricity and network traffic costs and server amortization (wherever hardware or lease costs), and all of them are paid in fiat currency the SHELL price should try to reflect those. SHELL Tokens will be sold via a System Pool in exchange for any currency Block Keepers decided to accept. Block Keepers will provide liquidity for such exchange and set up a SHELL minting rate for that pair, which will constitute their collective vote on current conversation price for a particular pair. Any SHELL holder may decide to sell their unused SHELL tokens which will be placed in the pool setting the price lower, respectively until the supply is not sold. Therefore the SHELL Token can be sold at the price Block Keepers set up in the Pool, or less. Hence — equal or less. All the payments collected for SHELL tokens are then directed into an Accumulator Contract where they are locked. Any NACKL token holder has a proportional right to the content of the Accumulator Contract. At any time NACKL holder can decide to burn their tokens and receive the proportional amount locked in Accumulator Contract. A NACKL holder would rarely (or never) use such a mechanism because most of the time the open market price of NACKL will be higher than revenues divided by tokens outstanding because of future revenues expectations and decreasing supply mechanism built into the market price of NACKL. Since all SHELL revenues go to the Accumulator Contract, the amount of Revenue divided by the amount of NACKL Tokens will constitute the “intrinsic” or a “floor” value of the NACKL. This intrinsic value will always rise while the NACKL supply will always decrease.

[^1]: **Epoch** - a participation period in the Acki Nacki protocol during which a participant acts as a Block Keeper.


# Tokens Acki Nacki

Acki Nacki uses a unique **Binary Token System**, consisting of two native tokens — [**NACKL**](/glossary#nackl) and [**SHELL**](/glossary#shell) — each with distinct roles in the network’s economy:

## NACKL

**NACKL** is the core value-holding and staking token of the Acki Nacki ecosystem.

It is:

* **Deflationary**, with a minting curve identical to Bitcoin’s issuance model — but smoothed.
* **Used for staking**, securing the network via Proof-of-Stake (PoS).
* **Burnable** to access deposited USD stablecoins in the **Accumulator Contract**.
* Rather than halving every 4 years like Bitcoin, NACKL supply **decreases gradually each block**.

<figure><img src="/files/Z4Ia5pOvm34Uyv8dAtWj" alt="" width="563"><figcaption></figcaption></figure>

**NACKL is decentralized**: no ICO, no TGE, no IDO — 100% fair distribution and PoS-based value system.

## **SHELL**

**SHELL** is a utility token made **exclusively for use within the Acki Nacki ecosystem**. It’s **not meant for speculation**, and its price **never goes above $1**.

**How it works:**

* To mint **100 SHELL**, you deposit **1 USD stablecoin** (like USDC or USDT) into a smart contract.
* You can use SHELL to compensate NACKL holders for the computing resources the network provides. It can be converted to [VMSHELL](/glossary#vmshell) to cover network fees at a 1:1 ratio.
* **You can’t redeem SHELL back into stablecoins directly**, but you can:
  * Sell it on the open market
  * Return it to the **Mint Pool** (a network mechanism)

> SHELL is **not a stablecoin** — it’s not pegged, not algorithmic, and not redeemable. But its value is always **equal to or less than $1**.

**📜 Regulatory-Friendly**

SHELL is designed to be **fully compliant** with regulations like the **EU MiCA** and **Digital Asset Act**, since it doesn’t behave like a traditional stablecoin and makes no promise of redemption.for network fees or payments.

### VMSHELL

**VMSHELL** is the token used to **pay for network fees** (like gas).

* It is created by **converting SHELL** into VMSHELL.
* **You can’t convert it back** to SHELL after that — it’s one-way.
* VMSHELL can be **transferred between smart contracts** that are part of the **same Dapp** (same [Dapp ID](/glossary#vmshell)).

> Think of VMSHELL like prepaid gas credits for your app — once converted, it’s only for powering activity inside the network.

## 🔁 Token Interactions

Here's how the Binary System works in practice:

<table><thead><tr><th width="246.800048828125">Action</th><th width="456.14990234375">Description</th></tr></thead><tbody><tr><td>💵 Deposit 1 USD stablecoin</td><td>→ Mint 100 SHELL</td></tr><tr><td>🧠 Use SHELL</td><td>→ Pay for compute resources on-chain using VMSHELL</td></tr><tr><td>🔁 Burn NACKL</td><td>→ Claim proportional USD from the Accumulator</td></tr><tr><td>⚙ Protocol Participants (Node Owners)</td><td>→ Earn NACKL by providing compute services</td></tr></tbody></table>

#### The Accumulator Contract

* All USD stablecoins used to mint SHELL are held in the **Accumulator Contract**.
* Only NACKL holders can **access these funds** — by **burning their tokens proportionally**.
* Example: Hold 1% of all NACKL, Burn them to withdraw 1% of the stablecoins in the Accumulator. However NACKL holders rarely (more likely never) will burn for USD (would lose future value). NACKL supply decreases naturally, reinforcing value.
* USD stablecoins are the "floor" for NACKL, but the "ceiling" for SHELL. NACKL's market value always exceeds all USD in the accumulator contract, as the market always predicts higher future utility.

This setup creates a natural **value floor** under NACKL and incentivizes **holding** over redeeming.

#### Token Comparison Table

| TOKENs                | NACKL                                                                                                | SHELL                                                                                                                                                | VMSHELL                                                                                                     |
| --------------------- | ---------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| **How it's created**  | <p>- Earned as rewards for network participation (staking, validating)<br>- Bought on the market</p> | <p>- Minted by depositing fiat or crypto (USD stablecoins)<br>- Fixed rate: 1 USD stable = 100 SHELL</p>                                             | - Converted from SHELL (1:1)                                                                                |
| **What you can do**   | <p>- Stake<br>- Earn rewards<br>- Restake<br>- Trade on the market</p>                               | <p>- Transfer between different DApps and DApp IDs<br>- Convert to VMSHELL to pay for network/contract fees<br>- Deposit back into the Mint Pool</p> | <p>- Pay for compute/network fees<br>- Can only be transferred between contracts with the same Dapp ID.</p> |
| **What happens next** | - Accumulates in user wallets (no forced burning or expiration)                                      | <p>- Does not expire or burn automatically<br>- May be deposited back or traded</p>                                                                  | - Burned after use                                                                                          |

This architecture ensures a sustainable, non-speculative, and self-reinforcing crypto economy — built for long-term scalability and decentralization.


# Fee System

All accounts in the Acki Nacki network are identified by **Dapp ID**.

Transactions in Acki Nacki always consume network resources and therefore include protocol-level fees. **However, if a Dapp has a `DappConfig` contract, fees paid for transactions between contracts within the same thread are compensated by the built-in fee factory mechanism regardless of whether the contracts belong to a specific Dapp ID. Fees are not compensated when transactions are initiated by messages between different threads or when no `DappConfig` contract is configured for the Dapp ID.**

### Built-in Fee Factory

To enable this mechanism for your Dapp ID, deploy the special [`DappConfig`](https://github.com/ackinacki/ackinacki/blob/main/contracts/dappconfig/DappConfig.sol) contract.

`DappConfig` is **not the main contract of your Dapp**. It is a service contract that manages the Dapp credit limit and automatically replenishes its contracts.

{% hint style="info" %}
`DappConfig` can be deployed at any time. It is deployed once per Dapp ID.\
These contracts do not have an owner, so any user can top up their balance.
{% endhint %}

#### How It Works

1. You deploy `DappConfig` and top up its balance with SHELL tokens.
2. When your Dapp contracts run out of funds, they call the TVM instruction [`gosh.mintshell` or `gosh.mintshellq`](https://github.com/gosh-sh/TVM-Solidity-Compiler/blob/master/API.md#goshmintshell-and-goshmintshellq). It allows an account to receive tokens from the credit limit of its `DappConfig`, mints VMSHELL at a 1:1 ratio, and credits them to the calling contract balance (see the [guide](https://dev.ackinacki.com/dapp-id-full-guide-creation-fees-centralized-replenishment#centralized-replenishment-of-contracts-within-a-dapp-id)).
3. During block production, the **Block Keeper (BK)** processes these calls and checks whether `DappConfig` exists for the specified Dapp ID.
4. If it exists, the BK calculates how much VMSHELL was generated in the block and then subtracts from that amount the gas actually spent on internal messages inside the Dapp.
5. As a result, the `DappConfig` available limit is charged **not for the full generated amount, but only for the remainder after this adjustment**.

This is how the fee factory works: fees paid for messages within the same thread are compensated through this adjustment. For a Dapp with `DappConfig`, this mechanism allows fees to circulate inside the Dapp instead of becoming direct account expenses.

At the protocol level, transactions are paid from the balance of the account that executes the transaction, or from message funds depending on the send flags. `DappConfig` does not replace this payment source for regular transaction fees: it gives an account the ability to top up its VMSHELL balance in advance. In practice, transactions become direct expenses when they are initiated by messages between different threads or when no `DappConfig` contract is configured for the Dapp ID.

{% hint style="info" %}
System contracts use a system `DappConfig` with the `is_unlimit` flag. For this config, the available limit does not restrict minting: system contracts can take tokens from the system `DappConfig` without decreasing `available_balance`.
{% endhint %}

The full Dapp ID guide is available [here](https://dev.ackinacki.com/dapp-id-full-guide-creation-fees-centralized-replenishment).

### Automatic Replenishment

Add balance checks and a `gosh.mintshell` minting call to your Dapp ID contracts. When the balance of any contract in your Dapp ID falls below the minimum threshold you define, the contract can take tokens from the available limit of its `DappConfig`: VMSHELL is minted at a 1:1 ratio and credited to the target contract balance. `available_balance` in `DappConfig` defines the maximum SHELL credit amount within which contracts of this Dapp ID can mint VMSHELL.

{% hint style="info" %}
Developers decide for themselves how to implement automatic replenishment inside their Dapp ID.

However, note that if you replenish contracts directly without deploying `DappConfig`, your Dapp ID will not have the mechanism that allows fees to circulate indefinitely inside the system.
{% endhint %}

### Fee Types

Transaction fees are the sum of several different fees related to the execution of a single transaction. Transactions themselves are complex processes, and fees are charged for different stages of their execution.

**Storage Fee** - charged for storing data in the blockchain if the account has been inactive for more than 30 days.

**Compute Fee** - paid for executing operations inside smart contracts. Each operation consumes a certain amount of gas.

**Action Fee** - charged for processing the action list produced after smart contract code execution.

**Inbound External Message Fee** - charged for importing inbound external messages into the blockchain.

**Outbound Internal Message Fee** - the sum of import fees for outbound internal messages.

For more details, see [Gas Calculation Basics](https://dev.ackinacki.com/~/changes/35/gas-calculation-basics).

{% hint style="info" %}
Fees are paid in VMSHELL tokens.
{% endhint %}

### Fee Payment Process

In Acki Nacki, fees are paid in VMSHELL during transaction processing. The main payment source is the balance of the account that executes the transaction or sends the message. Depending on the send flags (see the [detailed documentation](https://github.com/gosh-sh/TVM-Solidity-Compiler/blob/master/API.md#addresstransfer)), part of the fees may also be withheld from `msg.value`.

`DappConfig` is used to replenish the balances of Dapp ID accounts. An account can call `gosh.mintshell/gosh.mintshellq`, receive VMSHELL from the available limit of its `DappConfig`, and then pay for the transaction from its own balance. Therefore, `DappConfig` is not the direct payer of fees: fees are deducted from the VMSHELL balance of the account that executes the transaction.

For system contracts, a system `DappConfig` with `is_unlimit = true` is used. Such contracts can mint VMSHELL from the system config without being limited by `available_balance`.

#### Storage Fee

Storage Fee is charged for storing account state if the account has been inactive for more than **30 days**. The fee is deducted from the account's own VMSHELL balance during the next transaction processing, before the contract logic is executed.

If the balance is insufficient, the available part is deducted, and the outstanding remainder is recorded as storage debt. `DappConfig` does not pay Storage Fee directly: it can only replenish the account balance in advance through `gosh.mintshell(...)` so that the account has VMSHELL to pay fees. During subsequent inbound internal messages, the debt may be repaid from incoming funds. If the debt exceeds protocol thresholds, the account may be frozen or deleted.

#### Compute Fee

Compute Fee is charged for executing contract code. The fee amount depends on the gas used. The fee is paid from the funds available for transaction execution, including the account balance and the applicable inbound message processing rules.

#### Action Fee

Action Fee is charged for executing the actions produced by the contract after the compute phase, such as sending messages, reserving funds, or changing state. These fees are paid by the account that performs the actions.

#### Inbound External Message Fee

Inbound External Message Fee is charged for importing an external message into the network and processing it by the target account. If the account does not have enough funds to process the external message, the transaction may be rejected or completed without executing code.

#### Outbound Internal Message Fees

Outbound Internal Message Fees are charged when internal messages are sent between contracts. Depending on the send flags, the fee may be paid separately from the sender balance or withheld from `msg.value`, reducing the amount received by the recipient.

For messages within the same thread, the corresponding amount may be compensated through the Block Keeper adjustment described above. For a Dapp with `DappConfig`, this makes internal activity effectively free for accounts after their balance is replenished, while messages between threads or Dapp IDs without `DappConfig` remain direct expenses.

When messages are passed between contracts with different Dapp IDs in different threads, the entire token amount specified in `msg.value` (VMSHELL) is **zeroed out**. In this case, the recipient contract must take responsibility for executing the initiated transaction by calling `tvm.accept()` inside the called function. Otherwise, the transaction fails with `Not enough funds`.


# Protocol Participation


# Block Keeper


# License

General Information

The [**BK License**](https://docs.ackinacki.com/for-node-owners/protocol-participation/block-keeper/license/acki-nacki-vk-node-license) is a [contract](https://github.com/ackinacki/ackinacki/blob/main/contracts/bksystem/License.sol) that grants a [Block Keeper (BK) ](/glossary#block-keeper-bk)the right to participate in the protocol Acki Nacki.

{% hint style="info" %}
To generate rewards, a License must be delegated to a BK node.\
How to delegate is described [here](/for-node-owners/protocol-participation/block-keeper/license/license-delegation-guide).
{% endhint %}

Each BK can be delegated up to **20 licenses**. Licenses are delegated without restrictions.

## License status

### Privileged Status and Reputation

From the moment is first delegated, all Licenses have **privileged status**.\
This status allows a BK Node, where all Licenses are privileged, to operate with a stake below the protocol [minimum stake](/glossary#minimal-stake-of-the-vk) (“min-stake”).\
If any License on the Node loses privileged status, the Node must meet the full min-stake requirement.\
\
From the moment is first delegated, all Licenses also have a **Reputation Coefficient** =1.\
The coefficient is a multiplier on License rewards and increases gradually with continuous staking, from 1 up to a protocol-defined maximum = 3.\
\
Both privileged status and the reputation coefficient are lost simultaneously if:

* Any part of the stake is withdrawn from the Block Keeper contract system, or
* The License does not participate in validation for longer than half an [Epoch](/glossary#epoch-of-the-bk)\
  (259,200 blocks, \~12 hours).\
  This period is measured from the time the stake is placed in the cooler until it reappears in the [Pre-Epoch](/glossary#pre-epoch) or subsequent epoch after resuming continuous staking.

**Restaking After Loss**\
To resume staking after loss of privileged status, the License Owner must increase their stake to at least the min-stake requirement.

## Slashing

In the event that a BK node is subject to:

* [**Partial slashing**](/#slashing): the reputation resets to the minimum, and part of the stake is lost.
* [**Full slashing**](/#slashing): the license is permanently destroyed.

## Ownership Transfers

A License may be transferred to another owner **without leaving validation**, provided the License and its staked tokens are transferred together.

If the License Owner wishes to withdraw the stake during transfer, the License must first lock its stake, exit validation, withdraw funds, and only then may ownership be changed. In this case, the License loses privileged status and, if it remains outside of validation beyond the permitted period, it also loses reputation. Restaking after such a transfer requires the new owner to meet the min-stake requirement.

You can learn more about how to transfer ownership of a License [here](/for-node-owners/protocol-participation/block-keeper/license/working-with-licenses).

## Mitigation of reduced BK rewards caused by a License

* If a stake is withdrawn from the Block Keeper wallet, the corresponding License negatively affects neighbouring Licenses, since rewards are redistributed as (stake ÷ 20 × 19)
* If a license loses its privileged status and the Node’s total stake is below Minimal stake - the Node will not be able to continue staking.
* If the License Owner fails to remove such a License from the Wallet, Node Owner may perform the license lock operation with Node Owner keys to.
* If a License remains outside validation (with locked status) for a prolonged period, it is deemed to reduce the rewards of other Licenses because of the reduced total stake of the Node.
* If a third-party License Owner reduces rewards for others, Node Provider may create a new wallet and migrate all compliant Licenses to it.

How to work with licenses can be found [here](/for-node-owners/protocol-participation/block-keeper/license/working-with-licenses).


# Acki Nacki ВК Node License

BLOCKCHAIN SOURCE LICENSE AGREEMENT

For good and valuable consideration, the receipt and sufficiency of which are hereby acknowledged, the Licensor grants the Licensee the rights to use the Licensed Work as outlined in this Agreement, contingent upon full payment of the applicable Node License Fee

## General provisions <a href="#docs-internal-guid-4161382e-7fff-ecd7-e663-bd3495bbf308" id="docs-internal-guid-4161382e-7fff-ecd7-e663-bd3495bbf308"></a>

* Acki Nacki Node License (“ANNL”, “Node License”) is an exclusive Blockchain Source License agreement
* The final number of licenses to be issued under set Terms will be determined as a result of the Acki Nacki Node Sale but won’t exceed 10,000 Block Keepers Node Licenses and 10,000 of Block Manager Node Licenses
* Node Licenses can be used to run Acki Nacki Nodes from the start of the Acki Nacki Network (zero state) without a need for initial stake
* The stake is required for the validation at a later date according to Minimum Stake Network Protocol Parameters
* The Licenses are transferable without restrictions
* Acki Nacki network is fully decentralized. Software modifications may be issued by anybody provided they are distributed under the Terms of this ANNL. There will be no mechanisms for developers to change any of the network or license parameters without Node Owners consensus agreement manifesting in running such software update.

<table data-full-width="false"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td>Licensor:</td><td>GOSH TECHNOLOGY LTD. (“GOSH”)</td></tr><tr><td>Licensed Work:</td><td>The Licensed Work is (c) 2023 GOSH Technology Ltd</td></tr><tr><td>Use Grant:</td><td>You may make production use of the Licensed Work as part of the Acki Nacki Public Network as published by GOSH</td></tr><tr><td>Other Use Grant Restriction:</td><td>You may make production use of the Licensed Work, provided Your use does not include offering the Licensed Work to third parties as a public, permissionless Blockchain Network</td></tr><tr><td>Change Date:</td><td>Two years from the date the Licensed Work is published</td></tr><tr><td>Change License:</td><td><a href="https://www.gnu.org/licenses/agpl-3.0.html">GNU AFFERO GENERAL PUBLIC LICENSE</a></td></tr></tbody></table>

## Terms <a href="#docs-internal-guid-b53efbf3-7fff-d5ec-9fbc-f36f07561fec" id="docs-internal-guid-b53efbf3-7fff-d5ec-9fbc-f36f07561fec"></a>

The Licensor hereby grants you the right to copy, modify, create derivative works, redistribute, and make non-production use of the Licensed Work. The Licensor may make an Additional Use Grant, above, permitting limited production use.

Effective on the Change Date, or the second anniversary of the first publicly available distribution of a specific version of the Licensed Work under this License, whichever comes first, the Licensor hereby grants you rights under the terms of the Change License, and the rights granted in the paragraph above terminate.

If your use of the Licensed Work does not comply with the requirements currently in effect as described in this License, you must purchase a commercial license from the Licensor, its affiliated entities, or authorized resellers, or you must refrain from using the Licensed Work.

All copies of the original and modified Licensed Work, and derivative works of the Licensed Work, are subject to this License. This License applies separately for each version of the Licensed Work and the Change Date may vary for each version of the Licensed Work released by Licensor.

You must conspicuously display this License on each original or modified copy of the Licensed Work. If you receive the Licensed Work in original or modified form from a third party, the terms and conditions set forth in this License apply to your use of that work.

Any use of the Licensed Work in violation of this License will automatically terminate your rights under this License for the current and all other versions of the Licensed Work.

This License does not grant you any right in any trademark or logo of Licensor or its affiliates (provided that you may use a trademark or logo of Licensor as expressly required by this License).

Yes, if you do not want to include any indemnification obligations in the license, you can simply omit the "No Indemnification" section altogether.

The revised disclaimer of warranties and limitation of liability sections provide sufficient legal protection by clarifying that:

The Licensed Work is provided "as is."

No warranties are provided.

Your liability is limited to the amount paid for the license, without including any indemnification provisions.

Final Revised Section:

Here’s how the relevant sections of your license should look after dropping the "No Indemnification" section and replacing the original disclaimer:

Disclaimer of Warranties:

TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN “AS IS” AND “AS AVAILABLE” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. THIS INCLUDES, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.

Limitation of Liability:

TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT WILL THE LICENSOR BE LIABLE FOR ANY INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL, OR EXEMPLARY DAMAGES ARISING OUT OF OR IN CONNECTION WITH THIS LICENSE OR THE USE OF THE LICENSED WORK, INCLUDING BUT NOT LIMITED TO DAMAGES FOR LOSS OF PROFITS, GOODWILL, USE, OR DATA, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. THE LICENSOR’S TOTAL LIABILITY TO THE LICENSEE FOR ALL CLAIMS ARISING OUT OF OR RELATED TO THIS LICENSE SHALL NOT EXCEED THE AMOUNT PAID BY THE LICENSEE TO THE LICENSOR FOR THE LICENSED WORK.

Limited Grant of Rights:

The Licensee is granted the rights to use the Licensed Work solely in accordance with the terms of this License. Production use of the Licensed Work is permitted, provided that such use does not include offering the Licensed Work to third parties as a public, permissionless Blockchain Network. This License does not provide any warranties, support, or other protections beyond the right to use the software as specified.


# Working with Licenses

The described flow will be applicable after the network is launched.

<figure><img src="/files/LfLeFTNTAWC8OJeL1ac4" alt="" width="563"><figcaption></figcaption></figure>

## Obtaining License Owner Keys and License Contract Addresses

The License Owner [registers](https://docs.ackinacki.com/protocol-participation/license/license-dashboard-guide) in the [dashboard](https://dashboard.ackinacki.com) using a third-party crypto wallet \[1.1] that was used to purchase the license. Upon registration, the License Owner will receive a generated seed phrase and a corresponding key pair \[1.2].

{% hint style="warning" %}
To manage their license contacts, it is recommended that the License Owner save the obtained keys in a file named `License.keys.json`.
{% endhint %}

The **public** key from this pair must be sent to a GOSH representative via email \[1.3]. This key will be used by the [`LicenseRoot`](https://github.com/ackinacki/ackinacki/blob/main/contracts/bksystem/LicenseRoot.sol) system contract \[1.4] to deploy the [`License`](https://github.com/ackinacki/ackinacki/blob/main/contracts/bksystem/License.sol) contract \[1.5].

{% hint style="info" %}
A separate License contract is deployed for each license purchased.
{% endhint %}

Once the License contract is deployed, the GOSH representative will provide the License Owner with the contract address and [License number](/glossary#license-number) \[1.7].

## Adding a License to a BK Wallet Whitelist

For the license to be delegated, its license number must be added to the [BK wallet whitelist](/glossary#bk-wallet-whitelist).

To do this, the License Owner must provide their License Number \[2.1] to the Node Owner, who will then add it to their whitelist \[2.2].

{% hint style="warning" %}
There is no limit to the number of licenses that can be added to a BK Wallet whitelist;\
however, only **20 (twenty)** of them can be delegated.
{% endhint %}

## BK Wallet Deployment

The BK wallet [is deployed by the Node Owner](https://github.com/ackinacki/ackinacki/tree/main?tab=readme-ov-file#block-keeper-wallet-deployment) using the [deployment script](https://github.com/ackinacki/ackinacki/blob/main/scripts/create_block_keeper_wallet.sh) \[3].

{% hint style="info" %}
The wallet can be deployed with an empty whitelist or pre-filled with any number of licenses the Node Owner chooses to authorize. But only **20 (twenty)** licenses of these can be delegated later.
{% endhint %}

{% hint style="info" %}
The Node Owner can modify the whitelist at any time by using the setLicenseWhiteList(mapping(uint256 => bool) whiteListLicense) method in the [`AckiNackiBlockKeeperNodeWallet`](https://github.com/ackinacki/ackinacki/blob/main/contracts/bksystem/AckiNackiBlockKeeperNodeWallet.sol) contract.\
Pass in the license numbers you received from the License Owners.

* **`uint256` (key)** – the license number.
* **`bool` (value)** – set to `true` to **add** the license on the whitelist, or `false` to **remove** it.<br>

Example command:

{% code overflow="wrap" %}

```sh
tvm-cli call BK_WALLET_ADDR setLicenseWhiteList '{"whiteListLicense": {"1": true, "2": true, "5": true}}' --abi acki-nacki/contracts/bksystem/AckiNackiBlockKeeperNodeWallet.abi.json --sign BK_NODE_OWNER_KEYS
```

{% endcode %}

\
You will need the ABI file [AckiNackiBlockKeeperNodeWallet.abi.json](https://raw.githubusercontent.com/ackinacki/ackinacki/refs/heads/main/contracts/bksystem/AckiNackiBlockKeeperNodeWallet.abi.json) to run this command.
{% endhint %}

## Providing the BK Node Owner Public Key

To initiate delegation, the Node Owner must send their public key (`BK_NODE_OWNER_PUBKEY`) to the License Owner \[4].

## Delegating a License

{% hint style="warning" %}
A maximum of **20 (twenty)** licenses can be delegated to a single node.\
However, the fewer licenses delegated, the lower the Block Keeper’s total reward will be — and consequently, the lower the reward per license.
{% endhint %}

To delegate a license to a specific node, the License Owner must call the `addBKWallet(uint256 pubkey)` method on their [`License` contract](https://github.com/ackinacki/ackinacki/blob/main/contracts/bksystem/License.sol) \[5.1]:

```

tvm-cli call <LICENSE_ADDRESS> addBKWallet '{"pubkey": "0x<BK_NODE_OWNER_PUBKEY>"}' --abi License.abi.json --sign License.keys.json
```

Where:

* `pubkey` is the public key of the Node Owner received in step 4,
* [`License.abi.json`](https://github.com/ackinacki/ackinacki/blob/main/contracts/bksystem/License.abi.json) is the ABI of the License contract,
* `License.keys.json` is the keys obtained by the License Owner during registration in the dashboard.

The License contract will send a request to the [BK wallet contract](https://github.com/ackinacki/ackinacki/blob/main/contracts/bksystem/AckiNackiBlockKeeperNodeWallet.sol) \[5.2], which will verify whether the License is included in its BK wallet whitelist.\
If the License is whitelisted, the BK wallet accepts the delegation.\
Otherwise, the delegation request is denied.

To check the current delegation status, the `getBK()` method can be called on the `License` contract:

```

tvm-cli -j runx --addr <LICENSE_ADDRESS> --abi acki-nacki/contracts/bksystem/License.abi.json --method getBK
```

It will return the address of the BK wallet to which the license has been delegated,\
or `NULL` if no delegation has taken place.

## Staking

Only after successful delegation of at least 1 license can the Node Owner proceed to run the [staking script](https://github.com/ackinacki/ackinacki/tree/main?tab=readme-ov-file#block-keeper-documentation) \[6].

{% hint style="warning" %}
At least one license must be delegated to the node in order to initiate staking.
{% endhint %}

## **How to transfer a License to another owner**

*(coming soon)*

## **How to lock your stake for participation in the next staking round**

*(coming soon)*

## **How to remove a License from a BK wallet**

{% hint style="danger" %}
A License Owner cannot remove their license from the BK wallet while it is staked.
{% endhint %}

To remove a license from a BK wallet, the License Owner must call the `removeBKWallet()` function in the contract of the corresponding license:

```

tvm-cli call <LICENSE_ADDRESS> removeBKWallet {} --abi License.abi.json --sign License.keys.json

```

Where:

* [`License.abi.json`](https://github.com/ackinacki/ackinacki/blob/main/contracts/bksystem/License.abi.json) is the ABI of the License contract,
* `License.keys.json` is the keys obtained by the License Owner during registration in the dashboard.


# License Delegation Guide

After purchasing a [**BK license**](/for-node-owners/protocol-participation/block-keeper/license), it does not become active automatically. To activate its participation in the protocol and start receiving rewards, the license must be delegated to a node that will perform validator functions.

Failure to do so may result in the License Stake not validating, loss of reputation, or loss of other privileges.

In order for the licenses to be added to the zerostate and start getting rewards from the 1st block, this delegation has to happen before the network launch.

{% hint style="info" %}
A maximum of **20 (twenty)** licenses can be delegated to a single node.
{% endhint %}

You can find more details about working with licenses [here](/for-node-owners/protocol-participation/block-keeper/license/working-with-licenses).

## Delegation via Acki Nacki Dashboard

To use the dashboard, you need to register and obtain [License Owner Keys](https://docs.ackinacki.com/glossary#license-owner-keys) .

To do this, follow [the onboarding guide for the dashboard](/for-node-owners/protocol-participation/block-keeper/license/license-delegation-guide/dashboard-onboarding).

{% hint style="warning" %}
If, after completing the registration, you don't see your licenses on the **Licenses** tab, contact a Gosh representative through any publicly available channel or community group, and provide them with your `License Owner's public key`.
{% endhint %}

You can delegate your licenses directly through the [Acki Nacki Dashboard](https://dashboard.ackinacki.com/licenses) in two ways:

* [By submitting a request to one of the official Node Provider partners](#request-delegation-via-node-provider)
* [By manually entering a Custom Node Provider’s public key](#delegate-using-a-node-providers-public-key), if you already know which Provider you want to delegate to.

### **Request Delegation via Node Provider**

After registering in [the dashboard](https://dashboard.ackinacki.com/licenses), go to the **`Licenses`** tab and click the **`Delegate`** button.

<figure><img src="/files/68CkBVCrZjXDEd80gpVD" alt=""><figcaption></figcaption></figure>

Choose a Node Provider to whom you want to delegate your Licenses:

<figure><img src="/files/17WpAgaASKQKfmhmLFmi" alt="" width="375"><figcaption></figcaption></figure>

and submit a delegation request by filling in the following fields:

* **Block Keeper Licenses amount** – specify the number of available licenses you want to delegate to this provider’s nodes.
* Also provide your contact details so the Node Provider can get in touch with you:
  * **`Name`**
  * **`Email`**
  * **`Telegram`**

Confirm the entered information by entering your passcode in the **`Passcode`** field.

Contact the selected Node Provider to agree on the delegation fee and complete the payment process, then confirm by checking the box.

{% hint style="warning" %}
Be sure to contact the selected Node Provider to coordinate and complete the delegation payment.
{% endhint %}

Confirm this by checking the box.

Then click the **`Sign and send request`** button:

{% hint style="info" %}
By doing so, you confirm that you are intentionally delegating your licenses to this Node Provider. This action generates a `delegation_sig`, which is required to validate the delegation.
{% endhint %}

<figure><img src="/files/Jznh2WgQbG18ptaESOBe" alt="" width="304"><figcaption></figcaption></figure>

You will see a confirmation that your request has been signed.

<figure><img src="/files/HQMaGrlEaLn444sm3oJm" alt="" width="254"><figcaption></figcaption></figure>

Once the request is signed, the **`Provider`** column will display the name of the Node Provider to whom you delegated your licenses, and the counter at the top will update to reflect the increased number of delegated licenses:

<figure><img src="/files/8uIBHNDtLu2xpdqVFSlR" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
**Inform your Node Provider about the delegation and share your `License Owner public key` with them. This is important for data verification.**
{% endhint %}

Now proceed to [the next step after delegation](#next-steps-after-delegation).

### **Delegate Using a Node Provider’s Public Key**

If the Node Provider has shared their public key with you, then after registering in the dashboard, go to the **Licenses** tab and click the **Delegate** button:

<figure><img src="/files/68CkBVCrZjXDEd80gpVD" alt=""><figcaption></figcaption></figure>

In the list of Node Providers that appears, click the **Custom** button:

<figure><img src="/files/sS4RECGwcB0PwWlaJ2rH" alt="" width="375"><figcaption></figcaption></figure>

Please fill out the delegation form, enter your passcode to confirm the delegation, and click `Sign Delegation`

{% hint style="info" %}
By doing so, you confirm that you are intentionally delegating your licenses to this Node Provider. This action generates a `delegation_sig`, which is required to validate the delegation.
{% endhint %}

<figure><img src="/files/el71IK6ShGVLjqjgDRYx" alt="" width="312"><figcaption></figcaption></figure>

You will see a confirmation that your request has been signed.

<figure><img src="/files/DTFpHKLC5XXYQSxEpHH1" alt="" width="310"><figcaption></figcaption></figure>

{% hint style="warning" %}
**Inform your Node Provider about the delegation and share your `License Owner public key` with them. This is important for data verification.**
{% endhint %}

## Self-Delegation (Node Owners)

If you are both a License Owner and a Node Owner (Node Provider), you can delegate your licenses directly to your own node.

You can do this **Using the Dashboard** by specifying the `Node Provider public key` you generated, [as described in the section above](#delegate-using-a-node-providers-public-key).

## Next Steps After Delegation

At this stage, preparations for the network launch are underway. For licenses delegated during this phase to be included in the [Zerostate](/glossary#zerostate), the node to which you delegated your license must join the [Decentralized Network Starter Protocol (DNSP)](https://docs.ackinacki.com/protocol-participation/block-keeper/join-dnsp-gossip).

Once the DNSP client is launched by your Node Provider, the license will show an `Online` status in the Dashboard (this feature is still in development).

## **Revoke License**

**Before revoking the delegation of your license, please notify your Node Provider.**

{% hint style="danger" %}
A delegation signature on a running node is only invalidated by a newer delegation signature on another running node.
{% endhint %}

{% hint style="danger" %}
If a Node Provider had already started a node with your license - ask to remove your license from the node
{% endhint %}

**If you signed the delegation via Dashboard** - also revoke the delegation to delete the signature - click on the name of the Node Provider to whom the license has been delegated.

<figure><img src="/files/AAgWX4iaODfgOIzs7TxD" alt=""><figcaption></figcaption></figure>

Confirm your decision by checking the box and clicking the **`Revoke Delegation`** button:

<figure><img src="/files/mekQo0MTkjr8PS7KhMSh" alt="" width="315"><figcaption></figcaption></figure>

You will see the changes reflected in the Dashboard, The "Provider" column will be empty

You can now delegate your license again. Remember, if the license is not delegated, it will not generate any rewards.


# Dashboard Onboarding

After purchasing a [license](/glossary#license), all further operations with it are carried out through the [dashboard](https://dashboard.ackinacki.com/). To access your licenses, follow these steps:

* Go to the [dashboard page](https://dashboard.ackinacki.com/).
* Connect the cryptocurrency wallet that was used to purchase the license, by clicking the `Connect Wallet` button.

{% hint style="warning" %}
Use the exact wallet from which the purchase was made; otherwise, access to the license will not be granted.
{% endhint %}

<figure><img src="/files/MhgreBC9eMwWXiT453gK" alt=""><figcaption></figcaption></figure>

* Confirm that you are the wallet owner by signing a message:

<figure><img src="/files/rGokrMhjlbzyw4ZD92Fd" alt="" width="349"><figcaption></figcaption></figure>

* Generate **Acki Nacki License Owner Phrase** and public key or click the `Import an existing phrase` button to import your existing phrase from Acki Nacki app.

{% hint style="warning" %}
This seed phrase will be linked to your dashboard Account through a public key.\
**This can only be done once.** You will use it to withdraw BK rewards for your delegated licenses.
{% endhint %}

<figure><img src="/files/MmzvPrXa7K3OUGJ3xfUe" alt="" width="331"><figcaption></figcaption></figure>

The seed phrase will be required to manage your licenses. After the network starts, you will be able to update the license contract owner to a wallet address, such as a multisig. This way, the withdrawal of rewards can be confirmed by multiple custodians.

<figure><img src="/files/Pjj8IBlZju8MnOqdgccv" alt="" width="306"><figcaption></figcaption></figure>

{% hint style="danger" %}
Write down your **`seed phrase`** and store it in a secure location.\
Never share it with anyone. Avoid storing it in plain text, screenshots, or any other insecure method. If you lose it, you lose access to your assets. Anyone who obtains it will have full access to your assets.
{% endhint %}

A very important point: make sure you have memorized your seed phrase correctly:

<figure><img src="/files/NAY2aX7YzXTgx7jBOulo" alt="" width="375"><figcaption></figcaption></figure>

* Create and confirm a `passcode`:

{% hint style="info" %}
The **passcode** is used to encrypt the seed phrase in the device storage.
{% endhint %}

<figure><img src="/files/A9lRjPN6qzAItVKAj4i2" alt="" width="375"><figcaption></figcaption></figure>

* Information about your keys will be available in the top right corner:

<figure><img src="/files/ncVhjMRCOmYRZbgeOHZQ" alt=""><figcaption></figcaption></figure>

To copy **the license owner's public key**, click the button <img src="/files/Fys4jJdb9ZZhp679HdiG" alt="" data-size="line">

To view **the seed phrase, private key, and public key of the license owner**, click the button <img src="/files/JHhJk9jvzv2yMh3WOUKc" alt="" data-size="line">

and enter your `passcode`**:**

{% hint style="info" %}
If you forgot your passcode, log out of your account, reconnect your wallet, enter your seed phrase, and you will be able to create a new passcode.
{% endhint %}

<figure><img src="/files/kQzMe2ndmNBbhD16Kugo" alt="" width="315"><figcaption></figcaption></figure>

{% hint style="danger" %}
**Be careful and ensure the security of your data!**\
Avoid storing it in plain text, screenshots, or any other insecure methods. If you lose it, you will lose access to your assets.
{% endhint %}

<figure><img src="/files/SHaM6z014Hibdyu72oZJ" alt="" width="315"><figcaption></figcaption></figure>

{% hint style="warning" %}
If, after completing the registration, you don't see your licenses on the **Licenses** tab, contact a Gosh representative through any publicly available channel or community group, and provide them with your `License Owner's public key`.
{% endhint %}


# Setting up Block Keeper Node

## **System Requirements**

<table><thead><tr><th width="155">Component</th><th width="446.31640625">Requirements</th></tr></thead><tbody><tr><td>CPU</td><td>16 dedicated physical cores on a single CPU, or 16 vCPUs ≥ 2.4 GHz. Hyper-threading must be disabled.</td></tr><tr><td>RAM</td><td>128 GB</td></tr><tr><td>Storage</td><td>1 TB of high performance NVMe SSD (PCIe Gen3 with 4 lanes or better)</td></tr><tr><td>Network</td><td>The effective bandwidth may be limited to 1 Gbps full-duplex total traffic, meaning no more than 1 Gbps in each direction (ingress and egress). A 2.5 Gbps or better full-duplex network interface card (NIC) should be installed to support anticipated future load increases and avoid hardware replacement.</td></tr></tbody></table>

## How to run

Follow the instructions in [ackinacki repo.](https://github.com/ackinacki/ackinacki)

## API access

After the Block Keeper is successfully provisioned the gql endpoint will be on `localhost:3000/graphql`


# Join DNSP Gossip

Join Decentralized Network Starter Protocol

The **Decentralized Network Starter Protocol (DNSP)** (i.e. Igniter Gossip) collects Node and License information, tests and updates the node software, and initiates [Zerostate](https://docs.ackinacki.com/glossary#zerostate) (first block) generation once all DNSP requirements are met.

{% hint style="warning" %}
Igniter must be running on each node that you want to include in the Zerostate.
{% endhint %}

### **How to join**

Follow the instructions in the [*Acki Nacki Igniter* repository](https://github.com/ackinacki/acki-nacki-igniter/blob/main/README.md).

\
Link to the [source code](https://github.com/ackinacki/acki-nacki-igniter).


# How does it work?

[Here](https://tokenomics.ackinacki.com/) you can review multiple plots detailing various aspects of [Tokenomics](/tokenomics).

[Glossary](/glossary)

### **Contracts**

In its operation, the Block Keeper (BK) uses the following contracts:

* **BlockKeeperContractRoot (Root)** - The main system contract that manages a [Block Keeper's (BK)](/glossary#block-keeper-bk) participation in the network.
* **AckiNackiBlockKeeperNodeWallet (Wallet)** - The BK wallet contract, responsible for [stake](/glossary#stake) management.
* **BlockKeeperPreEpochContract (Pre Epoch)** - The contract responsible for BK's preparation during the [Epoch](/glossary#epoch).
* **BlockKeeperEpochContract (Epoch)** - The contract that indicates its owner is an active BK.
* **BlockKeeperCoolerContract (Cooler)** - The contract where the stake (plus [rewards](/glossary#bk-reward-system)) is locked for the duration of the BK's operation verification.

### **Stage 1: Initializing the Block Keeper Wallet before joining the Acki Nacki protocol**

<figure><img src="/files/y6byZgQZdRdMnpfY7e4e" alt=""><figcaption></figcaption></figure>

1. To become a network member, a prospective BK must lock their stake. To do this, the Owner needs to deploy a wallet for every BK.\
   To deploy BK wallet Owner should send an external message to the Root contract, signed with their public key:

```
deployAckiNackiBlockKeeperNodeWallet(pubkey)
```

2. The Root contract will deploy the BK wallet using the owner's public key:

```
constructor (
     TvmCell BlockKeeperPreEpochCode,
     TvmCell AckiNackiBlockKeeperNodeWalletCode,
     TvmCell BlockKeeperEpochCode,
     TvmCell BlockKeeperEpochCoolerCode,
     TvmCell BlockKeeperSlashCode,
     uint256 walletId
)
```

3. To restrict access to the wallet but allow node operations, the [Node Owner ](/glossary#bk-node-owner)should set a service key by calling a function in the Wallet contract:

```
setServiceKey(optional(uint256))
```

4. **Top Up with** [**NACKL**](/glossary#nackl) **(from any source):**

<pre><code><strong>receive()
</strong></code></pre>

{% hint style="warning" %}
Ensure that the NACKL amount sent to the wallet exceeds 2 minimum stakes if you want continuous re-staking.
{% endhint %}

{% hint style="info" %}
To determine the minimum stake amount, you can request this information from the Root contract.:

`tvm-cli -u -j run 0:7777777.....7777 getDetails {} --abi <BlockKeeperContractRoot_ABI_FILE>`
{% endhint %}

### Stage 2: Preparing the node for participation in the protocol

<figure><img src="/files/0Aaca1EClTzi9uAJNcyn" alt=""><figcaption></figcaption></figure>

5. Send a request to the Wallet contract for registration as a BK in the Acki Nacki Protocol (this must be signed with either the owner’s public key or the service key):

```
sendBlockKeeperRequestWithStake(bytes bls_pubkey, varuint32 stake)
```

6. The Wallet contract sends a request with the NACKL stake attached.

```
receiveBlockKeeperRequestWithStakeFromWallet(uint256 pubkey, bytes bls_pubkey )
```

7. The Root contract permits the Wallet to deploy the Pre Epoch contract with the NACKL stake attached:

```
deployPreEpochContract(
    uint32 epochDuration,
    uint64 epochCliff,
    uint64 waitStep,
    bytes bls_pubkey
)
```

8. The Wallet deploys the Pre Epoch contract, attaching the NACKL stake:

```
constructor (
     uint64 waitStep,
     uint32 epochDuration,
     bytes bls_pubkey,
     mapping(uint8 => TvmCell) code,
     uint256 walletId
)
```

9. The [Pre-Epoch](/glossary#pre-epoch) contract sends a message to the Wallet contract to lock the stake:

```
setLockStake(uint64 seqNoStart, uint256 stake)
```

### Stage 3: Starting the Epoch

<figure><img src="/files/s5yRieOZwEG9iRdYzCxd" alt=""><figcaption></figcaption></figure>

10. The BK script calls a function in the Pre-Epoch contract to join the Acki Nacki protocol:

```
touch()
```

11.1. The Pre-Epoch contract deploys the Epoch contract with the stake attached:

```
constructor (
     uint64 waitStep,
     uint32 epochDuration,
     bytes bls_pubkey,
     mapping(uint8 => TvmCell) code,
     bool isContinue, // is false in this case
     uint256 walletId,
     uint32 reputationTime
)
```

11.2 The Pre Epoch contract destructs itself:

```
selfdestruct(epoch)
```

12.1 The Epoch contract sends a message to the Root contract to increase the number of BKs:

```
increaseActiveBlockKeeperNumber(
    uint256 pubkey,
    uint64 seqNoStart,
    uint256 stake
)
```

12.2 The Epoch contract sends a message to the Wallet to update information about the previously locked stake:

```
updateLockStake(
    uint64 seqNoStart,
    uint32 timeStampFinish,
    uint256 stake
)
```

### Stage 4: Preparing the stake for the next epoch

BKs receive a base reward for blocks, but their Reputation Coefficient adds a premium reward depending on how long they have continuously participated in network work and restaked their tokens.

The longer a BK operates without missing any epochs, the higher their Reputation Coefficient, which can significantly increase their total reward.

{% hint style="danger" %}
However, if a BK skips even one epoch, the coefficient is reset to the minimum value.
{% endhint %}

If the Node Owner wants to remain on the Acki Nacki network after the epoch ends they must send another stake upfront.

When the active Epoch contract will be destroyed:

* the old stake will be transferred to the Cooler contract
* The new Epoch contract will be deployed with the new stake
* If no slashing occurred then the stake + rewards will be transferred from the Cooler Contract when the cooling period is over to Block Keeper wallet, so that they become available to be re-staked again

{% hint style="danger" %}
This process is not automatically repeatable, it just allows transitioning from one epoch to another without time gaps and, therefore, reputation loss but you still need to do it every epoch.
{% endhint %}

<figure><img src="/files/qNvl6Jhn8QqFHgHiWgdI" alt=""><figcaption></figcaption></figure>

13. To initiate this, send an external message to the Wallet contract with next stake attached while the current epoch is still active:

```
   sendBlockKeeperRequestWithStakeContinue(
    bytes bls_pubkey,
    varuint32 stake,
    uint64 seqNoStartOld
)
```

14. The Root contract accepts the stake and sends a permission to deploy a new Epoch contract to the Wallet contract:

```
receiveBlockKeeperRequestWithStakeFromWalletContinue(
    uint256 pubkey,
    bytes bls_pubkey,
    uint64 seqNoStartOld
)
```

15. The BK script calls a function in the Wallet contract to lock the stake for rejoining the Acki Nacki network:

```
 deployBlockKeeperContractContinue(
        uint32 epochDuration,
        uint64 waitStep,
        uint64 seqNoStartold, 
        bytes bls_pubkey
)
```

16. A flag is activated in the existing Epoch contract, indicating that the BK will remain for the next epoch:

```
continueStake(
    uint32 epochDuration,
    uint64 waitStep,
    bytes bls_pubkey
)
```

### Stage 5: Finalizing the Active Epoch

<figure><img src="/files/R3ehGYzwo1COnvNGwlt3" alt=""><figcaption></figcaption></figure>

17\. Block Producer checks Block Keeper set and epochs duration and when it sees that some BK's epoch is over, it sends a touch message to it:

```
touch()
```

18\. The Epoch contract requests permission from the Root contract to delete itself.\
If, after deletion, the number of BKs is less than the required minimum, the function returns false, making it impossible to complete the epoch.

```
canDeleteEpoch(
    uint256 pubkey,
    uint64 seqNoStart,
    uint256 stake,
    uint32 epochDuration,
    uint32 reputationTime,
    uint256 totalStakeOld
)
```

19\. The Root contract authorizes the deletion of the Epoch contract, with the reward attached:

```
canDelete(uint256 reward)
```

20.1 The Epoch contract initiates its own self-destruction:

```
destroy(bool isSlash) 
```

20.2 The Epoch contract notifies the Root contract about the decrease in the number of BKs:

<pre><code>decreaseActiveBlockKeeperNumber(
    uint256 pubkey,
<strong>    uint64 seqNoStart,
</strong>    uint256 stake
)
</code></pre>

20.3 The Epoch contract will call the Wallet contract function, which will deploy a new Epoch contract for the next iteration:

```
deployBlockKeeperContractContinueAfterDestroy(
    uint32 epochDuration,
    uint64 waitStep,
    bytes bls_pubkey,
    uint64 seqNoStartOld,
    uint32 reputationTime
)
```

20.4 The Wallet contract deploys a new Epoch contract if there is already another stake with `isContinue=true` flag ([see the previous step)](#stage-4-preparing-the-stake-for-the-next-epoch-optional).\
At the same time, the number of active BKs is updated in the Root Contract, and information about the previously blocked stake is refreshed (steps [12.1 and 12.2](#stage-3-starting-the-epoch) ):

```
  constructor (
        uint64 waitStep,
        uint32 epochDuration,
        bytes bls_pubkey,
        mapping(uint8 => TvmCell) code,
        bool isContinue,
        uint256 walletId,
        uint32 reputationTime
   
```

20.5 The Epoch contract deploys the Cooler contract with the NACKL stake (+reward) attached:

```
constructor (
     uint64 waitStep,
     address owner,
     address root,
     bytes bls_pubkey,
     mapping(uint256 => bool) slashMember,
     uint128 slashed,
     mapping(uint8 => TvmCell) code,
     uint256 walletId
)
```

20.6 The active Epoch contract destructs itself:

```
selfdestruct(
    BlockKeeperWalletAddress,
    _root,
    _owner_pubkey
)
```

21. An unsigned external message is sent by Block Keeper script to notify that the Cooling stage has finished:

```
touch()
```

22.1 The stake and reward are unlocked in the Wallet contract:

```
unlockStakeCooler(uint64 seqNoStart)
```

22.2 The Cooler contract destroys itself:

```
destroy(address to)
```

### Stage 6: Withdrawing a Portion of the Rewards

After the Cooler contract sends the tokens to the Wallet, they can be withdrawn.

To do this, send an external message to the Wallet contract.

{% hint style="warning" %}
Only the Node Owner is authorized to perform this action.
{% endhint %}

```
withdrawToken(
    address to, 
    varuint32 value
)
```

### Stage 7: Stopping the Work as a BK

To conclude their activity as a BK, the Node Owner must wait for the end of the epoch and the cooling period, then call a specific function in the Wallet contract. This function triggers the process of exiting the Acki Nacki protocol and unlocking the staked funds.

```
sendBlockKeeperRequestWithCancelStakeContinue(uint64 seqNoStartOld)
```


# Guide for Block Keeper testing on Shellnet

Test joining the protocol

**1. Obtaining the License Owner's Key Pair**

Go to the [Acki Nacki staging dashboard](https://dashboard-dev.ackinacki.com/).

Follow the instructions in the [License Dashboard Guide](https://docs.ackinacki.com/protocol-participation/license/license-dashboard-guide) to obtain the License Owner's key pair.

{% hint style="info" %}
Save the generated key pair in the `License.keys.json` file. You will need it later to manage the License contracts.
{% endhint %}

**2. Gaining Access to the User's License Contracts**

The License Owner should send their **`public key`** to a GOSH representative via [Telegram](https://t.me/Oxydixi).

The GOSH team will deploy licenses and provide you with the their addresses and unique on-chain numbers.

**3. Deploying a Block Keeper Wallet with a Whitelist**

{% hint style="warning" %}
Before deploying a BK Wallet all the delegating licenses have to be deployed,\
and their on-chain unique numbers have to be collected.\
They will be placed into the wallet's whitelist during deployment.
{% endhint %}

To deploy the BK wallet, follow the instructions in the [Deployment Guide](https://github.com/ackinacki/ackinacki/tree/main?tab=readme-ov-file#block-keeper-wallet-deployment).

As a result, you will get something like the following:

```

File ../../../../bk_wallet/master.keys.json not found. Generating master keys...
Deploying wallet...
...
Wallet 0:dac2f1bf07a23e8c85393022de358a017d605ebe930d6dad6fd4777ce5a4c09b is deployed.
License number 6 and license address is 0:7f2f945faaae4cce286299afe74dac9460893dd5cba1ac273b9e91f55f1141ec
License number 7 and license address is 0:deffa917f23c45afb263fadbb08406c2291447017f79f480417ca4de5551d1e2
Current minimum stake is 1 NACKLs
Sending 1 NACKLs
...
Checking wallet balance...
Current wallet balance: 1
Node ID: dac2f1bf07a23e8c85393022de358a017d605ebe930d6dad6fd4777ce5a4c09b
Initial steps have been done. Save your node id
```

{% hint style="warning" %}
Save your BK wallet address —which also serves as the node identifier (without the `0:` prefix)—and the file containing the BK Node Owner keys; you’ll need to run the staking script.
{% endhint %}

**4. Delegating a License to a BK Wallet**

{% hint style="warning" %}
A maximum of 20 (twenty) licenses can be delegated to a single node.
{% endhint %}

To delegate a license, a License Owner should call the `addBKWallet(uint256 pubkey)` method in a [License contract](https://github.com/ackinacki/ackinacki/blob/main/contracts/bksystem/License.sol) in each License contract.

Where:

`pubkey` - the BK Node Owner's pubkey.

Example of calling the method:

```

tvm-cli -j callx --addr 0:7f2f945faaae4cce286299afe74dac9460893dd5cba1ac273b9e91f55f1141ec --abi acki-nacki/contracts/bksystem/License.abi.json --keys license_owner_keys/license.keys.json --method addBKWallet '{"pubkey": "0xfa4edc8b63c4e66241a57c11e0a522769ca4a4f106692512fc92f2d658169bcc"}'
```

**You can check the delegation status by calling the `getBK()` method in the License contract.**

Example command:

```

tvm-cli -j runx --addr 0:7f2f945faaae4cce286299afe74dac9460893dd5cba1ac273b9e91f55f1141ec --abi acki-nacki/contracts/bksystem/License.abi.json --method getBK
```

The method will return the BK wallet address to which the license has been delegated:

```
{
  "bkwallet": "0:dac2f1bf07a23e8c85393022de358a017d605ebe930d6dad6fd4777ce5a4c09b"
}
```

or `null` if no delegation has occurred:

```
{
  "bkwallet": null
}
```

You can obtain the on-chain unique number of the License by calling the `getDetails()` method in the License contract:

```
tvm-cli -j runx --addr 0:deffa917f23c45afb263fadbb08406c2291447017f79f480417ca4de5551d1e2 --abi acki-nacki/contracts/bksystem/License.abi.json --method getDetails
```

result:

```
{
    "license_number": "0x0000000000000000000000000000000000000000000000000000000000000007",
    "bkwallet": "0:dac2f1bf07a23e8c85393022de358a017d605ebe930d6dad6fd4777ce5a4c09b",
    "owner_pubkey": "0x90f19f961898d394f68151a756140942767a91e354607f24150d180de1a085d7",
    "owner_address": null,
    "reputationTime": "0"
}
```

**Learn more about** [**how to work with licenses**](/for-node-owners/protocol-participation/block-keeper/license/working-with-licenses)**.**

**5. Block Keeper Deployment and Staking**

Only after completing all previous steps can the Node Owner begin [deploying the node software and starting staking.](broken://spaces/yPWnJ1v4nIPgOrEhPVrK)

{% hint style="warning" %}
To initiate staking, at least one license must be delegated to the node.
{% endhint %}


# Formal Verification

About Formal Verification approach

The formal verification of Block Keeper smart contracts was performed by the [Pruvendo Team](https://pruvendo.com/).

[Learn what formal verification is and find out about Pruvendo's formal verification approach.](https://drive.google.com/file/d/1xcZ5-1uLzTSMFbfHiq-4onhfwSoUWNZ2/view?usp=sharing)<br>

On the following pages, you will find:

* BLS - [Business Level Specification](https://docs.ackinacki.com/protocol-participation/block-keeper/formal-verification/block-keeper-contracts-business-level-specification),
* HLS - [High Level Specification](https://docs.ackinacki.com/protocol-participation/block-keeper/formal-verification/block-keeper-contracts-high-level-specification),
* LLS - Low Level Specification of Block Keeper contracts.


# Block Keeper Contracts Business-Level Specification

Prepared by Pruvendo

<div align="right"><figure><img src="/files/TXX59WZP6YO9ArMYnQoM" alt=""><figcaption></figcaption></figure></div>

## Purpose <a href="#docs-internal-guid-9795c783-7fff-46c9-b911-6f08cd34ef9c" id="docs-internal-guid-9795c783-7fff-46c9-b911-6f08cd34ef9c"></a>

The purpose of the present document is to create business-level specification (highest-level of specification) for the Block Keeper set of smart contracts. This document is intended to:

* Be thoroughly reviewed by the Customer
* Act as a base for the high-level specification

## Introduction <a href="#docs-internal-guid-5550335e-7fff-89ab-4f37-277c3ef4ff70" id="docs-internal-guid-5550335e-7fff-89ab-4f37-277c3ef4ff70"></a>

The key intention of the *Block Keeper* set of smart contracts is to let any participant become a *Block Keeper* either for a single participation (in Acki Nacki protocol as Block Keeper) period (called *Epoch*) or repeatedly.

### Single participation period <a href="#docs-internal-guid-ce3f9b2b-7fff-ec17-ca31-cd55d9f52bfc" id="docs-internal-guid-ce3f9b2b-7fff-ec17-ca31-cd55d9f52bfc"></a>

In this case the following stages are introduced:

* *Pre Epoch*. This stage is relatively short (a few minutes) and intended to let the *Block Keeper* to finish synchronizing its node if necessary
* *Epoch* - the main stage where the participant acts as a *Block Keeper*. Its duration is usually is most than one day
* *Cooling* - the terminating stage where the *Block Keeper* can still be slashed (up to 30% of Epoch’s duration)

The workflow described below must be followed:

* Participant must be registered as a *Block Keeper*
* Stake (exceeding minimally allowed value, which is a dynamic parameter) must be deposited
* *Pre Epoch* must be started and, then, finished
* Then, *Epoch*:
  * Must be started
  * Throughout the *Epoch*, the participant is a *Block Keeper*
  * Later *Epoch* must be finished
* Then, Cooling:
  * Must be started
  * At any time the *Block Keeper* can be slashed
  * Later *Cooling* must be finished and:
  * Then, stake can be withdrawn or reinvested

Graphically, the described workflow can be presented by the following chart:

<figure><img src="/files/tFxTvKYkYxtCdUrQqidz" alt=""><figcaption><p>Single participation period</p></figcaption></figure>

### Repeated participation <a href="#docs-internal-guid-f718a19a-7fff-f6ed-34b0-ca7b74dab25c" id="docs-internal-guid-f718a19a-7fff-f6ed-34b0-ca7b74dab25c"></a>

The main difference with the Single Participation Period is that upon *Epoch* completion, a new *Epoch* starts immediately.

The workflow described below must be followed:

* Participant must be registered as a *Block Keeper*
* Stake (exceeding minimally allowed value) must be deposited
* *Pre Epoch* must be started and, then, finished
* Then, *Epoch*:
  * Must be started
  * **Another (additional) stake must be deposited making the workflow repeated thus turning Epoch into continue state**
  * Later *Epoch* must be finished
* Then:
  * New *Epoch* (in non-continued state) starts immediately with `additional stake`
  * Cooling:
    * Must be started with the rest of stake
    * At any time the *Block Keeper* can be slashed
    * Later Cooling must be finished and:
    * Then, stake can be withdrawn or reinvested any time in future

The described workflow is illustrated by the following diagram:

<figure><img src="/files/oYoH2jsHMgjDW9gM2Fto" alt=""><figcaption><p>Repeated participation</p></figcaption></figure>

### Stake workflow <a href="#docs-internal-guid-920047f6-7fff-4afa-4d1e-b3f9cb182c05" id="docs-internal-guid-920047f6-7fff-4afa-4d1e-b3f9cb182c05"></a>

Throughout the loop, stakes are transferred from one entity to another. For single participation their workflow can be illustrated by the following diagram (the second row indicated what entity the stake belongs to at each stage):

<figure><img src="/files/ZzgMDSexWCYYMGKuyAMx" alt=""><figcaption><p>Stake workflow (single participation period)</p></figcaption></figure>

For repeated participation the diagram is more complicated:

<figure><img src="/files/k0r3bZI44WoMLwHlONn7" alt=""><figcaption><p>Stake workflow (repeated participation period)</p></figcaption></figure>

It’s important to mention that in case the participant (owner) reinvests each stake for the repeated participation immediately after cooling down by continuing the current *Epoch*, he gets some kind of a carousel of continuous participation.

Such a carousel is illustrated in the diagram below. For simplicity, all the “gray” periods between ending of the particular stages and external actions are omitted. Green dots stay for the “first” stake, while the red one - for the “second” stake.

<figure><img src="/files/pfwFAsM8mtreDdImEYja" alt=""><figcaption></figcaption></figure>

### Auxiliary values <a href="#docs-internal-guid-2be41919-7fff-941b-035d-464cde51524c" id="docs-internal-guid-2be41919-7fff-941b-035d-464cde51524c"></a>

#### Number of active blockkeepers

* Increased when a new blockkeeper arranges its first stake
* Decreased when a blockkeeper is fully slashed

#### Is\_min <a href="#docs-internal-guid-4c0c0303-7fff-635d-69d8-a10d878ebbd4" id="docs-internal-guid-4c0c0303-7fff-635d-69d8-a10d878ebbd4"></a>

This value indicates if the low stakes (below minimal value) are accepted (using the mechanism of [virtual stakes](#docs-internal-guid-42f56a2c-7fff-ff7e-aec1-f40b75a545af)) or rejected. It’s calculated using the following formula:

$$
\prod\_{l \in L}
\bigg(r(l)+s(l)+\frac 3 2 d\geq t\bigg)
\land (\sigma \geq \sigma\_0)
\land (f \geq t)
$$

where:

* *L* - set of licenses assigned to the wallet
* *r* - reputation time of the license
* *s* - start time of the license
* *d* - Epoch duration
* *t* - current time
* 𝜎 - current stake
* 𝜎｡ - last stake
* *f* - time, when the licenses become free

#### Minimal Stake <a href="#docs-internal-guid-db255fd8-7fff-a64b-97ab-11411a69ab2a" id="docs-internal-guid-db255fd8-7fff-a64b-97ab-11411a69ab2a"></a>

Minimal stake is calculated is by calling a special TVM instruction with the following parameters:

* $$r - s$$, where:
  * *r* - total reward assigned
  * *s* - total amount slashed
* $$t - t\_0 + \frac w 3$$, where:
  * *t* - current time
  * *t*｡ - time when network started
  * *w* - wait step
* [Number of active blockkeepers](#number-of-active-blockkeepers) at block start
* Number of active blockkeepers

#### Virtual Stake <a href="#docs-internal-guid-42f56a2c-7fff-ff7e-aec1-f40b75a545af" id="docs-internal-guid-42f56a2c-7fff-ff7e-aec1-f40b75a545af"></a>

Virtual stake is a value assigned in case of [Is\_min](#docs-internal-guid-4c0c0303-7fff-635d-69d8-a10d878ebbd4) is true and stake is lower than a

[minimal Stake](#docs-internal-guid-db255fd8-7fff-a64b-97ab-11411a69ab2a).

#### Local Stake

* If some virtual stake exists, then it’s a [virtual Stake](#docs-internal-guid-42f56a2c-7fff-ff7e-aec1-f40b75a545af)
* Otherwise, it’s just a stake

#### Total Stake

Total stake is a sum of all [Local Stakes](#local-stake) ever deposited.

#### Planned Epoch Finish Time <a href="#docs-internal-guid-6f797f0b-7fff-a8b0-0a7d-01c5d0e4c6ea" id="docs-internal-guid-6f797f0b-7fff-a8b0-0a7d-01c5d0e4c6ea"></a>

Calculated as $$s+d$$, where:

* *s* - Epoch start time
* *d* - Epoch duration

### Reward <a href="#docs-internal-guid-1f906f17-7fff-a48a-cfe6-45b9f1f96bf1" id="docs-internal-guid-1f906f17-7fff-a48a-cfe6-45b9f1f96bf1"></a>

Reward is calculated at the end of Epoch, but remains locked until the cooler stage ends.. It is implemented using a special TVM instruction and depends on:

* [Reward adjustment](#docs-internal-guid-ca7f15ea-7fff-6ed8-88f0-ca3ceb888318)
* [Number of active blockkeepers](#number-of-active-blockkeepers)
* Total reward already assigned at the time of calculation
* $$t - t\_0$$, where:
  * *t* - current time
  * *t*｡ - time when the Epoch started
* [Total Stake](#total-stake)
* [Local Stake](#local-stake)
* Reputation time, that is calculated according to the following formula: $$\frac s n+d+t-f$$, where:
  * *s* - [Sum Reputation Coefficient](#user-content-fn-1)[^1]
  * *n* - number of participating licenses
  * *d* - Epoch duration
  * *t* - current time
  * *f* - [planned Epoch finish time](#docs-internal-guid-6f797f0b-7fff-a8b0-0a7d-01c5d0e4c6ea)

#### Reward Adjustment <a href="#docs-internal-guid-ca7f15ea-7fff-6ed8-88f0-ca3ceb888318" id="docs-internal-guid-ca7f15ea-7fff-6ed8-88f0-ca3ceb888318"></a>

Invoked every time the Root method is called and $$l+p\<t \lor n=0$$, where:

* *l* - last time adjustment was performed
* *p* - minimal period between adjustments
* *t* - current time
* *n* - number of adjustments

When performed the special TVM instruction is called with the following parameters and the number of adjustments is increased as well as a reward period:

* Total amount of assigned rewards
* Reputation coefficient, that is:
  * *MIN\_REP\_COEF* constant, in case if [average reputation coefficient](#user-content-fn-2)[^2] equals to zero
  * average reputation coefficient, otherwise
* Reward period, that is calculated as follows:
  * $$n=0 \implies t-l$$
  * $$n>0\implies \frac{\pi n+t-l}{n+1}$$, where 𝜋 - the previous value of reward period
* Previous value of Reward Adjustment
* Current time

## Licences

<figure><img src="/files/NSBqFLZLxKVNH5olIVrD" alt="" width="563"><figcaption></figcaption></figure>

*License* smart contract is controlled by the License Owner’s cryptographic keys (*ED25519*). Without an active *License* smart contract, *Block Keeper* won’t function (it won’t be able to submit a stake to *Epoch* smart contract).

In order to submit stakes at least one *License* must be delegated to *BK Wallet*. Up to *20* *Licenses* can be delegated. A *License* can be delegated just to one *BK wallet*.

The rewards are split equally between all *Licenses* currently delegated. The stake is blocked for active wallet *Licenses*, in proportion to their wallet balances. If a slashing occurred the remaining stake will be divided proportionally between original stake owners.

The *License* contains text of provisions of *GOSH Business License and AGPL*. The *License* contains a provision that changes the *Business License* for AGPL two years after the first *Acki Nacki* block has been produced.

*Licenses* are transferable, i.e. their keys can be changed by the key owner without interrupting operations.

Within the first 2 years *License* (under *Business License terms*) give users an ability to join the network at any time without a minimum required stake, when certain conditions are met. This is further described in Block Keeper System Root below.

#### License Root

*Licenses* are always deployed by *License Root* to avoid a possibility of unauthorized/non-existent *Licenses* to be deployed.

*GOSH* holds keys for the *License Root* contract that allows it to issue new *Licenses*, but not revoke already issued ones.

#### Reputation

Reputation coefficient is recorded in the *License* contract and updated by *Epoch* smart contract with start block *sequence number* and end block *sequence number*. *Epoch* Smart Contract won’t be deployed if the reputation coefficient \[1.0…3.0] between all licenses is inconsistent.

**Reputation time**

Reputation time is the total time of the license usage in stakes since the latter of:

* License start
* The last full slashing of the stake where the license participated

**Average Reputation Coefficient**

The Average Reputation Coefficient is recalculated in case of changing the [number of active blockkeepers](#number-of-active-blockkeepers).

In case of increase:

* In case the [Total Stake](#total-stake) is zero, it’s assigned to *MIN\_REP\_COEF* constant
* Otherwise, it’s assigned to $$\frac {a(t-l)+rl} {t}$$, where:
  * *a* - the previous value of the Average Reputation Coefficient
  * *t* - [Total Stake](#total-stake)
  * *l* - [Local Stake](#local-stake)
  * $$r=\frac s n$$, where:
    * *s* - [Sum Reputation Coefficient](#user-content-fn-3)[^3]
    * *n* - quantity of licenses assigned for the particular Epoch

In case of decrease:

* In case the [Total Stake](#total-stake) equals to [Local Stake](#local-stake), it’s assigned to *MIN\_REP\_COEF* constant
* Otherwise, it’s assigned to $$\frac {a-rl} {t-l}$$, where:
* * *a* - the previous value of the Average Reputation Coefficient
  * *t* - [Total Stake](#total-stake)
  * *l* - [Local Stake](#local-stake)
  * $$r=\frac s n$$, where:
    * *s* - [Sum Reputation Coefficient](#user-content-fn-3)[^3]
    * *n* - quantity of licenses assigned for the particular Epoch

**Sum Reputation Coefficient**

The Sum Reputation Coefficient is a sum of all the [Reputation Coefficien](#user-content-fn-4)[^4]t of all the participating licenses at the time of Epoch creation, but slashed.

**Reputation Coefficient**

Reputation Coefficient is calculated by applying a special TVM instruction with [Reputation Time](#user-content-fn-5)[^5] as a parameter.

**Auxiliary values**

**Balance**

Each license has a balance associated with it.

* Balance can be increased by running a public method to the wallet (the license must be owned by the wallet)
* In case of license removal the balance must be zeroed, all the assets are to be transferred to the address provided by the license owner
* In case of full slashing, the balance is decreased by the stake amount
* In case of partial slashing, the balance is decreased by the corresponding portion of the stake amount

**Lock Stake**

The amount owned by the license but locked by the current Epoch.

* In case of Epoch starting the following amount is locked: $$\frac {\sigma(b(\lambda)-c(\lambda))} {\sum\_{l \in L}{( b(l)-c(l))}}$$, where:
  * 𝜎 - stake
  * 𝜆 - the current license
  * *L* - the set of the all participating licenses
  * *b* - the license balance[^6]
  * *c* - the amount locked by the Cooler
* In case of too long PreEpoch it must be unlocked
* In case of repeated Epoch the following amount is locked: $$\frac {\sigma(b(\lambda)-c(\lambda)-e(\lambda))} {\sum\_{l \in L}( b(l)-c(l)-e(l))}$$, where:
  * e - locked stake
* The locked amount can not be used for withdrawal
* In case of slashing the locked amount is either zeroed or decreased proportionally
* The locked stake must be released upon finished Epoch without continuation

**Lock Cooler**

This value represents the share of the license balance locked throughout the cooling phase.

* Upon normal end of the cooling phase the locked amount is released
* In case of slashing:
  * In case of full slashing the full amount is released
  * In case of partial slashing the proportional amount is released

#### Block Keeper Wallet <a href="#docs-internal-guid-92cb0b04-7fff-60c4-10f0-f74156ec6cb3" id="docs-internal-guid-92cb0b04-7fff-60c4-10f0-f74156ec6cb3"></a>

It is a smart contract which transmits user funds to an *Epoch* smart contract for staking, receives rewards, manages *License* rights and administers stakes in the *Epoch* contracts.

#### Block Keeper System Root

*Block Keeper System Root* is a smart contract which performs minimum stake validation, stores active validators number, manages *Wallet* and *Epoch* contract deployments, calculates rewards and mints them.

Any new *License* owner joining the network within the first 2 years is able to start validating without a need for stake. Note that such *License* owners can only join the network on these terms once. The perfect reputation count must be ensured therefore. In order to combat potential loss of stake due to bleeding the check is performed that the last stake without rewards is not less than a previous stake without rewards. The bleeding will come only from Rewards.

### Slashing <a href="#docs-internal-guid-8723d135-7fff-e745-55e6-74e28adf5277" id="docs-internal-guid-8723d135-7fff-e745-55e6-74e28adf5277"></a>

Slashing is initiated by the node itself and can be applied both at Epoch and Cooler stages.

When the slashing is full:

* All the deposited stakes are confiscated
* The reputation time of all licenses, including old ones (possibly, owned by other people), is zeroed
* Auxiliary values of each license are changed as described in the [corresponding section](#docs-internal-guid-2be41919-7fff-941b-035d-464cde51524c)
* All the keys are invalidated
* [Sum Reputation Coefficient](#user-content-fn-3)[^3] is decreased accordingly in case the slashed license has participated

In case of partial slashing:

* The provided percentage of the deposited stakes is confiscated
* The reputation time of all licenses, including old ones (possibly, owned by other people), is zeroed
* Auxiliary values of each license are changed as described in the corresponding section
* [Sum Reputation Coefficient](#user-content-fn-3)[^3] is decreased accordingly in case the slashed license has participated

## Details <a href="#docs-internal-guid-241e8147-7fff-2b71-1594-f76f0c85dd1a" id="docs-internal-guid-241e8147-7fff-2b71-1594-f76f0c85dd1a"></a>

### Common

Before any action any participating system contract must be supplied with gas enough to perform this action, if necessary.

### Participant registration

* External request comes from anybody
* New unique *BNW* (*Block Keeper* Node Wallet) is created
* Newly created *BNW* is initialized

### Withdraw <a href="#docs-internal-guid-3e37f6b7-7fff-d99f-edc7-2e69529cee3a" id="docs-internal-guid-3e37f6b7-7fff-d99f-edc7-2e69529cee3a"></a>

Can be called by *License* only.

Checks

* if:
  * the required amount of tokens is available, and
  * the required amount of tokens is available at the *License* balance
* If yes:
  * The balance of tokens is decreased by the required amount from the node wallet
  * The balance of the *License* is decreased by the required amount
  * The balance of tokens is increased by the required amount to the recipient
* Otherwise:
  * Exception is raised

### Participation <a href="#docs-internal-guid-78439742-7fff-f48b-a23b-c0100394e514" id="docs-internal-guid-78439742-7fff-f48b-a23b-c0100394e514"></a>

#### Stake placement

* Owner sends a request to *BNW*
* *BNW* checks if:
  * *Owner* is correct
  * Stake value is available (in ECC that serves as a secondary currency)
  * No stake already exists or being processed
  * At least one license is available
  * In case of success:
    * For each license:
      * There are “issues” if and only if:

        * Any *License* was not used at lease for a half of *Epoch*,

        or

        * Provided stake is less than last stake,

        or

        * GPL license is still in place
      * Reputation time becomes the sum of the reputation times of all the *Licenses*
      * *Root* is informed (alongside side with other information, it is informed, whether there were any issues, as well as sum of reputation times of all licenses being used)
* *Root* checks if:
  * Stake exceeds minimally allowed value and no issues were received, otherwise it must be sent back
  * In case of success:
    * *BLS* key is created
    * *BLS* key is asked for acceptance
* *BLS* key:
  * transfers this request to *Root*, informing alongside with other information, whether this was already used
    * marks the key as used
* *Root*:
  * checks if the *BLS* key was not used, otherwise it sends stake back
  * In case of success:
    * *Signer* is created
    * *Signer* is asked for acceptance
* *Signer*:
  * transfers this request to *Root*, informing alongside with other information, whether this was already used
  * marks the key as used
* Root:
  * checks if the *Singer* was not used, otherwise:
    * it sends stake back
    * destroys *BLS* key
  * In case of success *BNW* is informed
* New BKPE (Block Keeper Pre Epoch) created
* Stake is moved to Pre Epoch

#### Pre Epoch <a href="#docs-internal-guid-291272fc-7fff-380d-f5cd-4ba270049a4d" id="docs-internal-guid-291272fc-7fff-380d-f5cd-4ba270049a4d"></a>

* Upon creation:
  * *BKPE* is initialized
  * *BNW* is moved to “Pre Epoch” state
* Then, at any moment external *touch* message can be received
* If time for the next stage still did not come, nothing happens
* Otherwise:
  * New *Epoch* created
  * Stake is moved to *Epoch*
  * *BKPE* is self-destructed and all its assets are transferred to *Epoch*

#### Epoch <a href="#docs-internal-guid-28db9cf3-7fff-7ebe-57c2-a861dc3a97f0" id="docs-internal-guid-28db9cf3-7fff-7ebe-57c2-a861dc3a97f0"></a>

* Upon creation:
  * *Epoch* is initialized
  * *Root* is informed to enlist the *Block Keeper*
  * *BNW* is moved to “Epoch” state
* Then, at any moment external *touch* message can be received
* Also, at any moment external *slash* message can be received, and:
  * The whole stake will be confiscated
    * Reputation time for all existing and previous licenses is zeroed
    * *BLS* *key* is destroyed
    * *Signer* is destroyed
  * Wallet will be delisted
  * Continuation is canceled
    * All the licences mark as unused
    * *BLS key* is destroyed
    * *Signer* is destroyed
* If time for the next stage still did not come, nothing happens
* Otherwise:
  * *Root* is informed
  * Root checks if it’s possible to end an *Epoch* and does nothing if negative
  * Otherwise:
    * *Block Keeper* is delisted
    * *Epoch* is informed and:
      * *Cooler* is created
      * Stake (with reward) is moved to *Cooler*
      * *Epoch* is self-destructed in favor of *Cooler*

#### Cooler <a href="#docs-internal-guid-1ebbe22d-7fff-2a13-5bcc-e45aa558d473" id="docs-internal-guid-1ebbe22d-7fff-2a13-5bcc-e45aa558d473"></a>

* Upon creation:
  * *Cooler* is initialized
  * *BNW* is moved to “Cooler” state
* Then, at any moment external *touch* message can be received
* Also, at any moment external *slash* message can be received, and:
  * The whole stake will be confiscated
    * Reputation time for all existing and previous licenses is zeroed
    * *BLS key* is destroyed
    * *Signer* is destroyed
  * Wallet will be delisted
  * Continuation is canceled
    * All the licences mark as unused
    * *BLS* *key* is destroyed
    * *Signer* is destroyed
* If time for the next stage still did not come, nothing happens
* Otherwise:
  * *BNW* is moved to initial state
  * *BKPE* is self-destructed and all stake transferred to the *BNW*
  * If any license exists, the profit is distributed evenly among them
  * *BLS* key is destroyed
  * *Signer* is destroyed

#### Epoch (Repeated) <a href="#docs-internal-guid-93348152-7fff-466d-5233-e681983b2f30" id="docs-internal-guid-93348152-7fff-466d-5233-e681983b2f30"></a>

* Upon creation:
  * *Epoch* is initialized
  * *Root* is informed to enlist the *Block Keeper*
  * *BNW* is moved to “Epoch” state
* Then, at any moment `additional stake` request can be received with *continue* flag, following the [Stake Placement](#stake-placement) logic, where the *Epoch* repeated instead of *PreEpoch* creation
* Then, at any moment external *touch* message can be received
* Also, at any moment external *slash* message can be received, and [Epoch](#docs-internal-guid-28db9cf3-7fff-7ebe-57c2-a861dc3a97f0) logic is followed
* If time for the next stage still did not come, nothing happens
* Otherwise:
  * *Root* is informed
  * *Root* checks if it’s possible to end an *Epoch* and does nothing if negative
  * Otherwise:
    * *Epoch* is informed and:
      * New repeated *Epoch* is created with `additional stake`
      * *Cooler* is created is the rest of stake with reward
      * *Epoch* is self-destructed in favor of *Cooler*

### Proxy <a href="#docs-internal-guid-1e8dc41d-7fff-7ed1-d0a7-82df0b31a89b" id="docs-internal-guid-1e8dc41d-7fff-7ed1-d0a7-82df0b31a89b"></a>

This scenario handles the proxy system. *Proxy List* is created for any Epoch and stays until it ends (as an uncontinued one). In case of continued *Epoch*, the same *Proxy List* stands until it is canceled. Throughout the lifetime of the *Proxy List*, *Proxy* elements can be added or removed to/from it.

* Initialization the proxy (during *Pre Epoch* creation)
* Destruction of the proxy (by the end of an uncontinued *Epoch*)
* Adding new elements to the *Proxy* List
* Removal of elements from the *Proxy* List

### License management <a href="#docs-internal-guid-24aec3b0-7fff-a663-b899-ede3c4ec4504" id="docs-internal-guid-24aec3b0-7fff-a663-b899-ede3c4ec4504"></a>

All the licenses can be created by *License Root* only.

Before moving to *GPL* they can be created by *Owner* only, later by anybody.

#### Attach to BK Wallet

*License* can be attached to *BK Wallet* by request from the license *Owner*.

In this case:

* *License*:
  * Checks if the *License* is not attached to any other *BK Wallet*
  * Checks if the *License* attachment is not in progress
  * Informs the *BK Wallet* that it is going to be added
* *BK Wallet*:
  * Checks if a number of *Licenses* does not exceed maximally allowed value
  * Increased a number of licenses
  * Increases a total reputation time
  * Informs *License* about acceptance
* *License*:
  * Starts the license, if not started yet
  * Attaches the license to the *BK Wallet*

#### Detaching from BK Wallet <a href="#docs-internal-guid-9ae33e10-7fff-397e-3d35-9998ca45a88f" id="docs-internal-guid-9ae33e10-7fff-397e-3d35-9998ca45a88f"></a>

*License* can be detached from *BK Wallet* by request from the license *Owner*.

In this case:

* *License*:
  * Checks if the *License* is attached to some *BK Wallet*
  * Informs the *BK Wallet* that it is going to be removed
* *BK Wallet*:
  * Checks if the *License* exists
  * Decreased a number of licenses
  * Decreases a total reputation time
  * Transfers all the *License* balance to the specified address
  * Informs *License* about acceptance
* *License*:
  * Detaches the license from the *BK Wallet*
  * Keeps the reputation time

#### Deploying a new license <a href="#docs-internal-guid-674a502c-7fff-85a7-5c41-0e98a5e9e36d" id="docs-internal-guid-674a502c-7fff-85a7-5c41-0e98a5e9e36d"></a>

Deploying a new license

* For commercial deployment can be initiated by the Owner only.
* For free deployment can be initiated by anybody
* Reputation is set to zero for a new license
* License counter is increased by one

#### License locking

License locking

Locks or unlocks the license.

* Can be initiated by the Owner only
* Fails if the license is unbound

## Top-level scenarios <a href="#docs-internal-guid-c89ba548-7fff-9bea-b59c-11855d35d726" id="docs-internal-guid-c89ba548-7fff-9bea-b59c-11855d35d726"></a>

To formally specify the behavior briefly described above the following top-level scenarios were identified for further creation of high-level and, then, low-level formal specification:

* Registration
* ECC Withdrawal
* Participation
* Proxy
* License management

[^1]: **Sum Reputation Coefficient**

    The Sum Reputation Coefficient is a sum of all the [Reputation Coefficients](#reputation) of all the participating licenses at the time of Epoch creation, but slashed.

[^2]: **Average Reputation Coefficient**

    The Average Reputation Coefficient is recalculated in case of changing the [number of active blockkeepers](#number-of-active-blockkeepers).

[^3]: **Sum Reputation Coefficient**

    The Sum Reputation Coefficient is a sum of all the [Reputation Coefficien](#user-content-fn-4)[^4]t of all the participating licenses at the time of Epoch creation, but slashed.

[^4]: **Reputation Coefficient**

    Reputation Coefficient is calculated by applying a special TVM instruction with Reputation Time as a parameter.

[^5]: **Reputation time**

    Reputation time is the total time of the license usage in stakes since the latter of:

    * License start
    * The last full slashing of the stake where the license participated

[^6]: **Balance**

    Each license has a balance associated with it.

    * Balance can be increased by running a public method to the wallet (the license must be owned by the wallet)
    * In case of license removal the balance must be zeroed, all the assets are to be transferred to the address provided by the license owner
    * In case of full slashing, the balance is decreased by the stake amount
    * In case of partial slashing, the balance is decreased by the corresponding portion of the stake amount


# Block Keeper Contracts High Level Specification

[HLS is presented as a Web Application.](https://ursus-tools.dev/03272f6a-b0aa-4bc0-835a-5f1b15b843ff/HLS.html)


# Network Participation


# Proxy service

How it works and why it is recommended to use it

## Overview

**Broadcast Proxy** — is a specialized network service designed to optimize block exchange between participants in the Acki Nacki network. Its primary purpose is to reduce overall network traffic between nodes and to improve the scalability and stability of the network.

## How the Proxy Works

The IP addresses of the Proxies are registered on the network using the Gossip protocol and will be stored on-chain in the future.

Each BK node **without Proxy:**

* Sends blocks to all the other BK nodes' Proxies and directly to the BK nodes without Proxies
* Receives blocks from all the other BK nodes' Proxies and directly from the BK nodes without Proxies

Each BK node **that is connected to the network via Proxy**:

* Sends blocks only to its designated Proxy.
* Receives blocks only from its designated Proxy.

Each **Proxy**:

* Forwards blocks from its own BK nodes to Proxies of other node providers and BK nodes without Proxies.
* Receives blocks from other Proxies and nodes without Proxies and broadcasts them to its own BK nodes.

## Why Everyone Should Connect via a Proxy

In the network, there may be from several hundred to thousands of nodes, and the number of threads (and accordingly, Block Producers) and the load on them can dynamically change. A Block Producer must deliver its blocks to every Block Keeper, and each Block Keeper, in turn, must receive blocks from all Block Producers.

### What does this mean for the Block Keeper’s network requirements?

It implies two key points:

* Incoming data volume is equal to BLOCK\_SIZE × 3 × THREADS\_NUMBER per second.

  Assuming an average block with 300 transactions is \~100 KB, and the network card limit is 1 Gbps (125 MBps), the maximum number of threads a Block Keeper with such a card can handle is:

  125 / (0.1 × 3) = 416 threads.
* Outgoing data volume depends on the number of nodes in the network.

  In a non-proxied network, the outgoing traffic equals BLOCK\_SIZE × 3 × NODES\_NUMBER per second.

  In a 250-node network, this results in 75 MB = 0.6 Gbps.

  If the network grows to 500 nodes, this exceeds 1 Gbps.

  Furthermore, if multiple nodes are deployed in a single datacenter, router limitations on outbound traffic and internet bandwidth costs must be considered — without proxies, all traffic is routed via the public internet, making it inefficient and expensive for all participants.

The Proxy Service aggregates all or part of the outbound traffic from its datacenter and forwards it directly to other proxies, reducing inter-datacenter traffic by a factor equal to the number of Block Keeper nodes behind the proxy in that datacenter.

{% hint style="warning" %}
Therefore, if a node operator runs more than one node, it is strongly recommended to run them behind a proxy to optimize traffic across the network.<br>
{% endhint %}

## Proxy network requirements

The network requirements for a proxy are equal to the network requirements of a single Block Keeper multiplied by the number of Block Keepers behind it.

For example, for 100 nodes behind a proxy, the required bandwidth is 100 Gbps.

## Fault Tolerance and limitations

{% hint style="danger" %}
For fault tolerance, **you must run at least two instances** of the Proxy service in each data center: **one master, and one failover.**
{% endhint %}

{% hint style="warning" %}
It is **not recommended** to run more than **100 BK nodes** behind a Proxy instance.
{% endhint %}

## Proxy System requirements

<table><thead><tr><th width="155">Configuration</th><th width="483.1015625">Recommended</th></tr></thead><tbody><tr><td>CPU</td><td>8c/16t</td></tr><tr><td>RAM</td><td>32 GB</td></tr><tr><td>Storage</td><td>500 GB NVMe</td></tr><tr><td>Network</td><td><p>1Gb *(multiply) the number of nodes behind proxy.</p><p>For example, for 100 nodes behind a proxy, the required bandwidth is 100 Gb.</p></td></tr></tbody></table>

## Proxy Deployment

Instructions for deploying a Proxy service are available [here](https://github.com/ackinacki/ackinacki/tree/main?tab=readme-ov-file#deployment-with-ansible-1).


# Block Manager


# Licence


# Acki Nacki ВM Node License


# Guide to BM License Delegation

After purchasing a Block Manager (BM) License, it is **not** activated automatically.\
To start earning rewards, the License must be **delegated.**\
\
If you plan to deploy the BM service on your own, [please follow this guide](/for-node-owners/network-participation/block-manager/licence/bm-license-pre-deployment-verification).

Delegation to a Provider can be done through the **Acki Nacki Dashboard**.

#### **Step 1. Log in to your** [**Acki Nacki Dashboard**](https://dashboard.ackinacki.com/) **account**

If you don’t have an account yet, please follow the [onboarding guide](https://docs.ackinacki.com/for-node-owners/protocol-participation/block-keeper/license/license-delegation-guide/dashboard-onboarding) to create one.

After logging in, go to the **Licenses** tab — there you can view all your licenses.

{% hint style="warning" %}
If, after completing the registration, you don't see your licenses on the **Licenses** tab, contact a Gosh representative through any publicly available channel or community group, and provide them with your `License Owner's public key`.
{% endhint %}

#### **Step 2. Filter BM Licenses**

You can use the filter to display only your **BM Licenses**.

<figure><img src="/files/xCmZtoOoAx1S53PxWcpx" alt="" width="140"><figcaption></figcaption></figure>

#### **Step 3. Delegate your License**

Click the **`Delegate`** button.

<figure><img src="/files/Ew8TQoAuF2zzpDAEu0o8" alt=""><figcaption></figcaption></figure>

In the pop-up window, click on **`Block Manager`** and select **TVM Labs** as the Node Provider.

<figure><img src="/files/4hYvVDQHPCclWXMuuaIk" alt="" width="320"><figcaption></figcaption></figure>

Submit a delegation request by filling in the following fields:

* **`Block Manager Licenses amount`** – specify how many of your available licenses you want to delegate
* **Contact details** – provide information so the Node Provider can reach you:
  * Name
  * Email
  * Telegram

Enter your **passcode** in the **`Passcode`** field to confirm the information you entered above.

Check the box to confirm your intention to contact the provider to agree on the **delegation fee** and proceed with the **payment process**.

<figure><img src="/files/4odRTmwFFUR755b9wXqC" alt="" width="318"><figcaption></figcaption></figure>

#### **Step 4. Confirmation**

You will see a message confirming that your request has been signed.

<figure><img src="/files/QpPiC3QiszNUDXrZuYQ5" alt="" width="319"><figcaption></figcaption></figure>

Once the request is signed, the **Provider** column will display the name of the Node Provider to whom you delegated your licenses, and the **Total Delegated** counter will be updated.

<figure><img src="/files/kock34ubSVZkVqitrFcz" alt=""><figcaption></figcaption></figure>

#### **Step 5. License Activation**

After your license becomes active and the **BM service** is launched, you will be able to view your **reputation coefficient**, **stake**, and **rewards** on the same tab.


# BM License Pre-Deployment Verification

Веfore the BM License contract is deployed to the **Acki Nacki** network, the **BM License Owner** **must launch the Block Manager (BM) service** **and provide it for functionality auditing by a GOSH representative**

For this, it’s necessary to:

### Preparing the BM Service

1. The BM License owner must agree on cooperation with the owner of one of the BK nodes, who must:

* Open a port for connection to the block streaming service.
* Provide the following:
  * **BK node IP address:** `NODE_IP`
  * **API access token** to retrieve accounts: `BK_API_TOKEN`

{% hint style="warning" %}
Only **one Block Manager service** can be registered per **NODE\_IP**
{% endhint %}

2. Generate two key pairs:

* One key pair will be used to operate the **BM wallet**.
* The other will be used to **sign external message authentication tokens**.

```
tvm-cli genphrase --dump block_manager.keys.json
tvm-cli genphrase --dump block_manager_signing.keys.json
```

3. Deploy the BM wallet using the following command:

```
tvm-cli --abi ../contracts/bksystem/BlockManagerContractRoot.abi.json --addr 0:6666666666666666666666666666666666666666666666666666666666666666 -m deployAckiNackiBlockManagerNodeWallet '{"pubkey": "0xBLOCK_MANAGER_PUB_KEY", "signerPubkey": "0xBLOCK_MANAGER_SINING_PUB_KEY", "whiteListLicense": {}}'
```

{% hint style="warning" %}
At this stage, the `whiteListLicense` field must remain **empty**.
{% endhint %}

4. Prepare an **Ansible inventory file** for BM deployment, specifying all required variables.\
   [An example inventory file can be found here](https://github.com/ackinacki/ackinacki?tab=readme-ov-file#create-an-ansible-inventory)

### Verification and Functionality Confirmation

After successfully launching the BM service, make sure to:

* Verify that the BM is correctly connected to the blockchain and is receiving block streams.
* Provide the IP address of your BM (`HOST_PUBLIC_IP`) for verification.

#### 3. License Activation

After the service is verified:

* The **BM License contract** will be deployed to the network.
* The **contract address `LICENSE_ADDR`** and your **License number** will be received from a GOSH representative.

The BM License Owner must then update the whitelist in the BM wallet by adding their License number, thereby granting permission for delegation:

<pre><code>
<strong>tvm-cli -j callx --addr BM_WALLET_ADDR --abi contracts/bksystem/AckiNackiBlockManagerNodeWallet.abi.json --keys block_manager.keys.json --method setLicenseWhiteList '{"whiteListLicense": {"YOUR_LICENSE_NUMBER": true}}'
</strong></code></pre>

* then delegated the License to the wallet:

```

tvm-cli -j callx --addr LICENSE_ADDR --abi contracts/bksystem/LicenseBM.abi.json --keys BM_LICENSE_OWNER.keys.json --method addBMWallet '{"pubkey": "0xBLOCK_MANAGER_PUB_KEY"}'
```


# Setting up Block Manager Node

## **System Requirements**

<table><thead><tr><th width="155">Configuration</th><th width="185">Minimum</th><th width="178">Recommended</th></tr></thead><tbody><tr><td>CPU</td><td>4c/8t</td><td>8c/16t</td></tr><tr><td>RAM</td><td>32 GB</td><td>64 GB</td></tr><tr><td>Storage</td><td>1 TB NVMe</td><td>2 TB NVMe</td></tr><tr><td>Network</td><td>1 Gbit synchronous unmetered Internet connection</td><td>1 Gbit synchronous unmetered Internet connection</td></tr></tbody></table>

## How to run

BM license holders are **not required** to join the Acki Nacki network from the Genesis block.\
A BM node can be launched after the network starts.

However, if you want your BM to launch from Genesis block, you must:

* **Participate in `PreNet` testing.**\
  Only `PreNet` participants receive access to the configurations and tools needed to deploy nodes from Zerostate.
* **Contact a GOSH representative.**\
  Reach out to the team to participate in PreNet testing and request your BM license be added to the Zerostate.

## API access

After the Block Manager is successfully provisioned the gql endpoint will be on `localhost:3000/graphql`


# Getting Started with Acki Nacki

Welcome to the **Acki Nacki Developer Portal**!\
This portal will walk you through the key concepts of building on Acki Nacki — even if you're completely new to it.

Whether you're deploying your first smart contract, testing transactions, or building a full-scale Dapp, this section will help you get up and running quickly.

### 🧠 Core Concepts

In the **Acki Nacki** blockchain, every user action begins with a [**message**](/for-developers/messages).\
Messages trigger [**transactions**](/for-developers/transactions), which then modify the **state of** [**accounts**](/for-developers/accounts) **(smart contracts)**.

#### 🔐 Account = Smart Contract

Every contract is an **account** in the blockchain. It includes:

* **Balance**
* **Code**
* **State (data)**

Contracts:

* Can **own and send funds**
* Can **execute code**
* Can **create other contracts**
* Interact **asynchronously** with other contracts

All logic — user behavior, applications, business systems — lives inside these contracts.

### 🧩 Dapp ID — A Unique Application Identity

Acki Nacki introduces a unique concept called **Dapp ID** — a logical identifier that connects related contracts into one unified Dapp.

**Dapp ID is used for:**

* Grouping contracts into a single application unit
* Routing messages and managing execution priorities
* Implementing **freemium** models (subsidized transactions)
* Simplifying balance/state management across the Dapp

> All accounts on Acki Nacki are identified by a **Dapp ID** — this makes it easier to structure, scale, and monetize your Dapps.

Before diving into DAPP development, it is recommended to first understand the [basic principles of how a blockchain works](https://docs.ackinacki.com/), as well as the architecture and decentralization mechanisms of the Acki Nacki network.

🔗You can learn more about Dapp [here](https://dev.ackinacki.com/dapp-id-full-guide-creation-fees-centralized-replenishment).

### 💸 Freemium Transaction Model

Acki Nacki supports a **freemium model** for transactions:\
You can often **interact with contracts, send messages, and store data without paying fees**.

This opens the door to new UX possibilities: free onboarding, subsidized interactions, and seamless microservices.

### ⚙️ Smart Contract Development

Smart contracts on Acki Nacki are written in **Solidity**. If you’re familiar with Ethereum development, you’ll feel right at home.

🔗Check out our Solidity-based contract development [guide](https://dev.ackinacki.com/dapp-id-full-guide-creation-fees-centralized-replenishment#prepare-contract-source-code).

#### 🧪 Executing WASM binaries within a smart contract

Need to run compute-heavy operations inside your contract?

Acki Nacki supports **running precompiled WebAssembly (WASM)** code using the `RUNWASM` instruction.\
This lets you execute binaries built to the [WASI Preview 2 Component Model Standard](https://github.com/WebAssembly/component-model) directly inside the contract, powered by **Wasmtime**.

This makes Acki Nacki ideal for:

* High-performance computation
* Data science workflows
* Gaming logic
* On-chain AI modules

More details here:\
📄 [RUNWASM Instruction](https://github.com/tvmlabs/tvm-sdk/blob/main/tvm_vm/WASM.md)

### 🛠 Developer Tools & SDKs

You can interact with the blockchain using the official **Acki Nacki SDK** and developer tools.

* Perform queries, send transactions, monitor events
* Integrate GraphQL directly into your app or backend

🔍 You can learn more about Developer Tools [here](/for-developers/developer-tools-and-sdk).

### 🔗 Useful Links

| Resource              | Link                                                                     |
| --------------------- | ------------------------------------------------------------------------ |
| 🧑‍💻 GitHub          | [github.com/ackinacki/ackinacki](https://github.com/ackinacki/ackinacki) |
| 💬 Telegram           | [t.me/tvmlabs](https://t.me/tvmlabs)                                     |
| 🔍 Explorer (Mainnet) | [mainnet.ackinacki.org/graphql](https://mainnet.ackinacki.org/graphql)   |
| 🧪 Explorer (Testnet) | [shellnet.ackinacki.org/graphql](https://shellnet.ackinacki.org/graphql) |

***

### 📩 Feedback & Support

* Have a question? Need help? → [Join our Telegram](https://t.me/tvmlabs)
* Found a bug? → Submit an issue on [GitHub](https://github.com/ackinacki/ackinacki/issues)


# Messages

In the Acki NAcki blockchain, a **message** is the fundamental unit of interaction between accounts (contracts). All actions, state changes, and logic execution within accounts are triggered by messages.

### Message types

There are three types of messages in Acki Nacki:

* External incoming: sent from outside the blockchain → received by a smart contract
* Internal: sent from a smart contract → received by a smart contract
* External outgoing: sent from a smart contract → received outside the blockchain

You can learn more at the following link: <https://dev.ackinacki.com/abi/abi#message-body>


# Transactions

In the **Acki Nacki** blockchain, any change to an account's state is recorded as a **transaction**.\
A transaction is a record of an account state update caused by the processing of an **incoming message**.\
\
Depending on the contract logic, a transaction may also produce one or more **outgoing messages**.

You can learn more at the following link: *(coming soon)*


# Accounts

#### Core Principles

* **Account (Contract)** – a record in the distributed database that includes the balance, code, and data.
* All user, application, and system logic and state are stored in contracts.
* Each contract is an account capable of sending messages, executing code, holding funds, and creating other contracts.
* Contracts can interact with other contracts asynchronously.
* Accounts are identified and grouped using **Dapp ID**.

**Dapp ID** **is a unique identifier for a logical application, linking together contracts that operate within the same Dapp.**

Before diving into building a Dapp, it’s recommended to first understand the [basic principles of how blockchain works](/), as well as the architecture and decentralization mechanisms of the Acki Nacki network.

***

#### Purpose of Dapp ID:

* Represents a logical "group of accounts" (contracts) acting as a single application
* Used for message routing and execution priority management
* Enables transaction subsidization and freemium models
* Simplifies state and balance management across the entire Dapp

***

#### Dapp ID Assignment Rules:

* Every initialized and active contract has a Dapp ID.
* If a contract is created directly (via an external message), its Dapp ID matches its own address.
* If a contract is created by another contract (via an internal message), it inherits the Dapp ID of its creator.

***

You can learn how to create your first Dapp using [this guide](https://dev.ackinacki.com/dapp-id-full-guide-creation-fees-centralized-replenishment).


# Smart Contracts

Smart contracts in Acki Nacki are the core of all logic and state in the network.\
They are written in **Solidity**, compiled into bytecode, and executed within the **TON Virtual Machine (TVM)**.

This page introduces the key tools, standards, and guides you’ll need to write, deploy, and maintain smart contracts on Acki Nacki.

* **TON Virtual Machine (TVM)**.
* [VM Instruction Set](https://dev.ackinacki.com/vm-instructions/acki-nacki-vm-instructions)
* [Guide to Development and Deployment](https://dev.ackinacki.com/dapp-id-full-guide-creation-fees-centralized-replenishment)
* [ABI Specification and Data Encoding](https://github.com/tvmlabs/tvm-abi/blob/main/README.md)

  Acki Nacki uses a strict ABI (Application Binary Interface) format for:

  * Encoding and decoding input/output
  * Defining function signatures
  * Structuring on-chain communication
* [Compilation](https://github.com/gosh-sh/TVM-Solidity-Compiler)\
  Compilation transforms your Solidity code into bytecode executed by the TVM.
* Security Best Practices
* [The Acki Nacki Fee System →](https://docs.ackinacki.com/tokenomics/fee-system)


# Developer Tools & SDK

[About Acki Nacki SDK](https://dev.ackinacki.com/)

[About CLI tools](broken://spaces/yPWnJ1v4nIPgOrEhPVrK)

[GraphQL API](https://dev.ackinacki.com/graphql/graphql-api)

[Quick starts](https://dev.ackinacki.com/quick-starts)

[GraphQL playground](https://shellnet.ackinacki.org/graphql)

[Testnet block explorer](https://shellnet.ackinacki.org/)


# Bee Engine

**Bee Engine** is an embeddable mining engine and contract system that allows applications to run [**NACKL**](/glossary#nackl) **mining** on the client side and securely verify results on the blockchain. Mining operates as a background process and is independent of the application type — users can play games, edit documents, or use services while contributing computational work.

👉 **Go to the full** [**Bee Engine documentation section**](https://dev.ackinacki.com/bee-engine/bee-engine-overview) for a detailed overview of the architecture and integration flow.


# Wallets

In the Acki Nacki blockchain, every account is a smart contract. This means a wallet is not a separate entity — its behavior, logic, and capabilities are entirely defined by the type of deployed contract. Different use cases call for different wallet types, from everyday transactions to multi-party fund management.

### How Wallets Work in Acki Nacki <a href="#how-wallets-work-in-acki-nacki" id="how-wallets-work-in-acki-nacki"></a>

Unlike many blockchains where an account is simply a key pair with a balance, in Acki Nacki an Account is a record in a distributed database containing a balance, code, and data. The contract type determines what operations are available to the owner: sending tokens, multisig approval, access recovery, spending limits, and more.Thanks to this architecture, Acki Nacki natively supports account abstraction — every wallet can have its own unique logic defined by its smart contract.

### Wallet Types <a href="#wallet-types" id="wallet-types"></a>

#### Acki Nacki Wallet (Main Network Wallet) <a href="#acki-nacki-wallet-main-network-wallet" id="acki-nacki-wallet-main-network-wallet"></a>

The primary wallet of the Acki Nacki network is a non-custodial smart contract wallet with advanced security features. It is available as a mobile and web application.

**Key features:**

* **ZK Login** — authentication based on zero-knowledge proofs (zk-SNARKs, Groth16). Allows you to sign in using Google, Facebook, and other OpenID providers without exposing private data to the blockchain.
* **Multi-factor protection** — the wallet supports multiple transaction confirmation factors.
* **Access recovery** — ability to recover wallet access in case of device loss or OpenID credential loss.
* **Non-custodial** — no user data is sent to any server; the owner retains full control over their assets.
* **Formal verification** — the wallet code undergoes formal verification for maximum security assurance.

**Contract interaction scope:** the Acki Nacki Wallet App is designed for supported wallet flows, token operations, application connection, and mining authorization. It cannot invoke arbitrary methods of user contracts. The app operates in the system `mvsystem` DAPP ID, so custom contract interaction should be implemented in the DAPP that owns the user flow.

If your users need to interact with your contracts, build a dedicated DAPP for that experience. Start with the [DAPP development prerequisites](https://dev.ackinacki.com/#prerequisites). If your scenario requires wallet-based calls to contract methods, use a Multisig Wallet instead.

**Install:** [ackinacki.com/wallet​​](https://ackinacki.com/wallet)

***

#### Multisig Wallet <a href="#multisig-wallet" id="multisig-wallet"></a>

If you need a custodial solution or multi-party fund management, you can deploy a Multisig Wallet. This is a smart contract that requires transaction confirmations from a specified number of owners (custodians).

**Key features:**

* **Multiple owners** — the wallet can have one or more owners, each with their own key.
* **Confirmation threshold** — the number of required signatures to execute a transaction is configured at deployment (`reqConfirms`).
* **Contract method calls** — Unlike the MultiFactor Wallet (Acki NAcki Wallet), the Multisig Wallet allows users to invoke methods of other contracts by including the corresponding payload in the transaction.
* **Flexibility** — suitable for both personal use (single owner) and team or corporate scenarios.
* **Deployment via TVM CLI** — the wallet is deployed using the `tvm-cli` command-line tool.

**Deployment guide:** [dev.ackinacki.com/how-to-deploy-a-multisig-wallet​​](https://dev.ackinacki.com/how-to-deploy-a-multisig-wallet)


# Connecting an Acki Nacki Wallet and Setting Up Mining Keys

This guide explains how to connect your Acki Nacki (AN) Wallet to apps and authorize mining

### Overview

Applications integrated with the Acki Nacki ecosystem typically require two types of permissions: Wallet Authentication and Mining Authorization

Applications may handle wallet connection and mining authorization differently.

Some applications combine both actions into a single approval flow. Others, such as **Popit Music**, require them to be completed separately:

1. **Wallet Authentication** — connect your AN Wallet and create a secure session.
2. **Mining Authorization** — allows an application to use Mining Keys associated with your wallet for NACKL mining activities.

The examples in this guide use **Popit Music** to demonstrate the two-step setup process.

> **What are Mining Keys?**
>
> **Mining Keys** are cryptographic keys associated with your Acki Nacki Wallet that allow approved applications to participate in NACKL mining on your behalf.
>
> When you grant mining access, you are **not sharing your wallet ownership or private keys**. Instead, you authorize a specific application (such as Popit Music) to use dedicated mining permissions linked to your wallet for earning mining rewards.
>
> Mining Keys can be managed, revoked, or reassigned at any time in **AN Wallet → Settings → Connected Mining Apps**.

***

## Step 1 — Wallet Authentication

Wallet Authentication creates a secure connection between your AN Wallet and the application.

### 1. Select Connect AN Wallet

Open the application and tap **"Connect or sign in",**\
then choose: "**Connect Acki Nacki Wallet"**

<figure><img src="/files/SPQA0SU7UkHaMx7KMEPX" alt="" width="143"><figcaption></figcaption></figure>

***

### 2. Scan the QR Code

Popit Music displays a QR code for wallet connection.\
Open AN Wallet and **scan the QR** code or tap "**Open AN Wallet**" and you will be redirected directly to your wallet

<figure><img src="/files/NgUVZ68VJQGKz1cbsqTv" alt="" width="142"><figcaption></figcaption></figure>

***

### 3. Enter Your Wallet Password

AN Wallet requests your password to approve the authentication request.

<figure><img src="/files/ewh11lBjJUfRmpgWSMLZ" alt="" width="143"><figcaption></figcaption></figure>

***

### 4. Approve the Connection Request

Review the request details and confirm the connection.

<figure><img src="/files/Ls9bDxXt1SUX8a7d9yTw" alt="" width="142"><figcaption></figcaption></figure>

When approved:

* Wallet ownership is verified
* Wallet identity is shared with the application
* A secure application session is created

The application receives:

* Wallet Name
* Wallet Address

No private keys, passwords, or seed phrases are shared.

***

### 5. Wallet Authentication Completed

The wallet confirms that the connection has been established.

<figure><img src="/files/VXCW6ipgBtATGgitHc5w" alt="" width="143"><figcaption></figcaption></figure>

***

### 6. Verify Connected Applications (Optional)

You can review active application sessions in:

**AN Wallet → Settings → Connected Apps**

<figure><img src="/files/03VS16CdLTK5r2cSLUum" alt="" width="143"><figcaption></figcaption></figure>

***

## Step 2 — Mining Authorization

Mining Authorization allows the application to use Mining Keys for NACKL mining activities.

> Wallet Authentication alone does not grant mining permissions.
>
> Applications that use a two-step setup require a separate Mining Authorization approval.

***

### 1. Open Mining Setup

In Popit Music, in the user settings select: "**Setup Mining Keys"**

<figure><img src="/files/MarMjcY8rMyGQIOJEyaE" alt="" width="143"><figcaption></figcaption></figure>

***

### 2. Request Mining Access

Popit Music is requesting permission to enable mining. Tap "Request Mining".\
The application will redirect you to AN Wallet. To continue, tap "Open AN Wallet".

<div><figure><img src="/files/s3f0nZzL36AzYKoDb4zE" alt="" width="144"><figcaption></figcaption></figure> <figure><img src="/files/HRW891Va7VSxdzPM6q94" alt="" width="143"><figcaption></figcaption></figure></div>

***

### 3. Review Mining Permission Request

AN Wallet displays the mining authorization request. Select "**Allow Mining"** if you permit mining

<figure><img src="/files/hh2iYmLclTllzcKkZJxk" alt="" width="143"><figcaption></figcaption></figure>

***

### 6. Verify Connected Mining Applications

After approval, the application appears under:

**AN Wallet → Settings → Connected Mining Apps**

<figure><img src="/files/rHv4ZMKYBYTy0vT3GtFW" alt="" width="142"><figcaption></figcaption></figure>

***

### 7. Mining Activated

Return to the application. Mining is now active and Mining Keys have been successfully assigned.

<figure><img src="/files/nOfmUAJcHcDzXDqhRCfZ" alt="" width="144"><figcaption></figcaption></figure>

***

## Managing Permissions

### Connected Apps

Connected Apps are applications authorized to access your wallet identity and maintain an authenticated session.

Location: **AN Wallet → Settings → Connected Apps**

**Screenshot:** `5-w-settings.jpg`

<figure><img src="/files/03VS16CdLTK5r2cSLUum" alt="" width="143"><figcaption></figcaption></figure>

***

### Connected Mining Apps

Connected Mining Apps are applications authorized to use Mining Keys.

Location: **AN Wallet → Settings → Connected Mining Apps**

**Screenshot:** `12-w-settings.jpg`

<figure><img src="/files/rHv4ZMKYBYTy0vT3GtFW" alt="" width="142"><figcaption></figcaption></figure>

***

### Revoke Access

To remove an application:

1. Open AN Wallet Settings
2. Locate the application
3. Tap the **X** icon
4. Confirm removal

The application will immediately lose the associated permission.

<div><figure><img src="/files/gsG6oaBD4n3aW7SURnhl" alt="" width="143"><figcaption></figcaption></figure> <figure><img src="/files/rHv4ZMKYBYTy0vT3GtFW" alt="" width="142"><figcaption></figcaption></figure></div>


# ZK Login Authentication Flow

## Overview

Aсki Naсki employs an Zk-auth authentication scheme for conducting Multi-factor Wallet smart-contract transactions. Zk-auth is based on the OpenID Connect protocol and zk-SNARK system Groth16. It combines convenience for users and security. Transactions are confirmed via existing OpenID credentials. Multiple OpenID based providers like Google, Facebook, Apple etc are already supported by Zk-auth, and we are going to extend the list. The anonymity is preserved. Blockchain accounts and OpenID accounts are not publicly linked. This is achieved using zk-SNARK.

Zk-auth allows for quick authentication. The user is not burdened with remembering cumbersome seed phrase in the majority of cases. But we still use seed phrase for recovery.

Our scheme is inspired by [zkLogin](https://arxiv.org/abs/2401.11735). But we modify it by removing extra service for salt back up since the corrupted salt service may deanonymize the link between blockchain account and OpenID account. To prevent possible privacy violations we replace the server-generated salt with a user-owned Password that is self-maintained by the user.\
Also, we add the ability to recover access to Wallet smart-contract in accidental cases like the loss of device or OpenID credentials.

Our multi-factor authentication scheme allows users not to input any extra information to confirm transactions while the JWT token is valid and not expired. So the user story is rather simple. At the same time, an attacker who compromised OpenID credentials cannot transact unless he separately compromised the user-owned Password.

If the user has lost the device and Password, he still will be able to restore access and at the same time to prevent the adversary from using the wallet.

Let’s summarize the properties that Zk-auth provides:

* In the majority of cases, one may transact on Acki Nacki using the familiar OpenID authentication flow. However, we do not eliminate the necessity in mnemonics to provide the ability to recover access to Wallet.
* Transaction requires approval from the user via the standard OpenID credentials, but the OpenID provider (or attacker who compromised an OpenID account) cannot transact himself, pretending to be the user. This is provided by extra user-owned Salt Password and by the fact that the OpenID provider does not know the matching between blockchain accounts and OpenID accounts. The last one is achieved using zero-knowledge proofs.

{% hint style="info" %}
At the present moment we support the following list of OpenID providers: Google, Facebook, AWS, Twitch, Apple, Slack, Kakao, Microsoft, KarrierOne, Credenza3.
{% endhint %}

## Multi-factor Wallet initialization

To initialize a Multi-factor Wallet, the user must have valid OpenId credentials (for example related to Google email). Also, there are some extra secrets that the user creates during signUp to handle the access to Multi-factor Wallet: Salt Password, Recovery Password and Seed Phrase.

At first the user creates the **Salt Password**. It must be simple and convenient to remember and use it. At second the user creates a strong **Recovery Password**, meeting certain security conditions: be long enough and contain both digits and special characters. Finally **Seed Phrase** is generated by a Client Application exploited by the user. All this data is produced just before Multi-factor Wallet smart-contract deploying, and it is used for deployment.

{% hint style="danger" %} <mark style="color:red;">The user should store</mark> <mark style="color:red;">**Salt**</mark> <mark style="color:red;">**Password, Recovery Password,**</mark> <mark style="color:red;">and your</mark> <mark style="color:red;">**Seed Phrase**</mark> <mark style="color:red;">in a secret place.</mark>
{% endhint %}

Directly before Multi-factor Wallet smart-contract deployment, Seed Phrase and Recovery Password are used by Client Application to derive corresponding ed25519 keypairs (*SK\_SeedPhrase, PK\_SeedPhrase*) and (*SK\_Recovery, PK\_Recovery*). Also, Poseidon hash *zkID* is computed based on OpenID account data (stable id) and user-owned Password. *zkID* hash is used to link Multi-factor Wallet smart-contract and OpenID account, but anonymously.

So for deployment of Multi-factor Wallet smart-contract the following triple is prepared: hash *zkID*, ed25519 public key *PK\_SeedPhrase* and ed25519 public key *PK\_Recovery*.

{% hint style="warning" %}
This Client Application does not backup user-owned Password, Recover Password, Seed Phrase and related secret keys. It will store only fresh JWT token related to OpenId Connect, zero-knowledge proof and some extra data, which we will discuss in more detail below.
{% endhint %}

{% hint style="info" %}
Issuer value on the diagram below is a string identifying OpenId provider like Google, Facebook etc.
{% endhint %}

<figure><img src="/files/11KTIX8SI62jLi4hoCHJ" alt=""><figcaption></figcaption></figure>

## Transactions Authentication sketch

Key aspects of transacting with OpenID credentials:

* A **JWT** is a signed access token obtained from an OpenID provider, containing a payload that includes a field named 'nonce'. We add into nonce: user’s temporary ephemeral public key, timestamp of its expiration and some extra randomness.
* **Client Application** generates and stores the temporary ephemeral key pair, where the ephemeral public key is added into nonce of JWT. The ephemeral private key is used to sign transactions during some predetermined period of time (\~ 2 weeks), eliminating the need for the user to back it up.
* The Groth16 zero-knowledge proof is generated based on JWT. The aim is to prove that the user really owns an OpenID account, i.e. has a related signed valid JWT. However, JWT contains fields deanonymizing users. Thus we generate zero-knowledge proof per JWT to hide some JWT fields.
* A transaction is submitted on-chain being signed by an ephemeral secret key and supplied with valid zero-knowledge proof. TVM executes the transaction after verifying the ephemeral signature and the zero-knowledge proof.

## Main Entities

* **Application frontend (Client Application)**: This is the Client frontend application that supports our flow to create and authenticate transactions. Client Application is responsible for deploying Wallet smart-contract with valid user's data, storing the ephemeral private key, maintaining OpenID, creating and signing transactions.
* **Proof Service**: This is a backend service responsible for generating zero-knowledge proofs based on JWT, extra randomness, Salt Password and expiration timestamp (for ephemeral keypair). The proof is submitted on-chain along with the ephemeral signature for the transaction.

{% hint style="info" %}
The delegation of zero-knowledge proof computation to the extra Proof Service backend is a necessary step for now. This is motivated by the fact that the protocol deals with non-ZK-friendly cryptographic primitives: SHA-2, modular exponentiation for RSA signature verification. It causes an essential number of R1CS constraints in the corresponding circuit that was written for Zk-auth protocol in Circom language. Our circuit was essentially inspired by [zkLogin](https://docs.sui.io/concepts/cryptography/zklogin) existing implementation. We did only very small optimizations for the part related to JWT token parsing. But the circuit is still cumbersome and has about 2^20 constraints. This makes the proof computation impractical in Client Application. That’s why following the experience of [zkLogin](https://docs.sui.io/concepts/cryptography/zklogin) we chose to delegate proof computation to a powerful service. The corruption of Proof Service (corruption = control by the adversary) will lead to deanonymization immediately. The adversary in this case gets access to JWT token and user-owned Salt Password, he can calculate *zkId* and discover the link between blockchain and OpenID accounts. However user Wallet assets are still safe and can not be maintained by the adversary. Since the related JWT token ephemeral private key is still hidden, and the adversary can not create a valid signature for the transaction. Only corrupting both Proof Service and OpenID provider is required to steal the Wallet. Since in this case the adversary may create a valid JWT token for his new independent ephemeral key pair and then he will be able to provide valid proof per JWT and sign the transaction by his ephemeral private key.

Since the problem of deanonymization exists in the case of Proof Service corruption, we continue researching the possibility to compute proofs on the client's side. Some extra circuit optimizations are required to reduce the number of constraints. This problem is still under review.
{% endhint %}

## Keys priorities and loss case handling

(***SK\_SeedPhrase, PK\_SeedPhrase***) – master key pair that is used to maintain Multi-factor Wallet smart-contract. It is used for recovery. Knowledge of *SK\_SeedPhrase* (Seed Phrase) allows one to change *zkID* or *PK\_RecoveryPassword* in contract.

{% hint style="warning" %}
To change *PK\_SeedPhrase* in contract one should have: access to OpenID account, Salt Password, Recovery Password.
{% endhint %}

We have protection against several of the most likely accident scenarios of loss.

* **If mobile device and/or access to OpenID account and/or Salt Password are lost**, then use Seed Phrase to change *zkID* in Multi-factor Wallet smart-contract.
* **If Recovery Password is lost**, then use Seed Phrase to replace *PK\_RecoveryPassword* by fresh *PK\_NewRecoveryPassword* in contract.
* **If Seed Phrase is lost**, then the user must have a mobile device with not yet expired JWT, related zero-knowledge proof and Recovery Password. It allows one to change PK\_SeedPhrase in contract.
* **If Seed Phrase is lost and mobile phone is lost (or JWT is expired)**, then to change *PK\_SeedPhrase* the user needs OpenID account access, Salt Password and Recovery Password.

{% hint style="info" %}
For now, it is the responsibility of a user to make a strong Recovery Password and backup it. The ideal Recovery Password is the second Seed Phrase, but this is too cumbersome. So our requirements for the Recovery Password are more lightweight.
{% endhint %}

{% hint style="info" %}
(*SK\_RecoveryPassword, PK\_RecoveryPassword*) is a key pair that is used only in the case the Seed Phrase was lost by the user.
{% endhint %}

## Multi-factor Wallet transactions maintenance details

### Transaction WITH signIn to OpenID provider

At the first time the user starts with signIn to the relevant OpenID account. To make a signIn request, the user generates an ephemeral random temporary ed25519 key pair (*SK\_e, PK\_e*). Public key *PK\_e*, its expiration timestamp *T\_max* and extra generated randomness *R* are concatenated and the concatenation is hashed using Poseidon hash function. The hash is put into a 'nonce' field that is added into a semi-finished JWT token prepared by Client Application. JWT payload is sent to the OpenID provider together with standard authenticating data. OpenID provider authenticates the user, signs JWT payload with public fresh JWK RSA private key and sends signed JWT back. Signed JWT is used as a certificate for *PK\_e* issued by an OpenID provider.

Since we want to provide anonymity, we can not send JWT into Wallet smart-contract to prove that the user is a valid owner of an OpenID account embedded into both JWT and *zkID* previously stored by contract. Instead, we produce zero-knowledge Groth16 proof to prove that the user really got such JWT. And the contract verifies the zk-proof.

We suppose that the Client Application will run on a device having small computational power. Groth16 proof calculation is computationally hard, that's why we can not handle it on mobile devices. We deploy our own Proof service for computing proofs. Client Application sends a request to Proof service providing as input JWT and Salt Password. Private input to calculate zk-proof contains the following data: signed JWT, Salt Password, extra randomness *R* used for nonce computation. Public input consists of ephemeral public key *PK\_e*, its expiration timestamp *T\_max*, OpenID provider public RSA JWK key, *zkID*. The Proof service generates zero-knowledge proof for a related Zk-auth arithmetic circuit (AC) that takes aforementioned private and public inputs. Zk-auth AC does the following computations:

* partially parse JWT token (payload);
* checks that `nonce` claim in JWT is correctly formed,\
  i.e. `nonce = Poseidon(PK_e || T_max || R)`;
* checks that `iss` claim in JWT contains the valid OpenID provider name;
* verifies the RSA signature (third part of JWT token) that was done by OpenID provider using his private JWK key for this JWT (recall that JWT header and payload of JWT are signed by provider using RSA private key).
* checks that *zkID* is correct,\
  i.e. *`zkID`*` `` ``= Poseidon(stable id || issuer || Salt Password) `

{% hint style="info" %}
`iss` claim in JWT token is constant identifying OpenId provider.\
For example, for Google `iss` claim equals to "<https://accounts.google.com>".
{% endhint %}

{% hint style="info" %}
The extra randomness *R* during nonce computation is added to strengthen unlink ability between blockchain and OpenID accounts. The data about ephemeral public keys is publicly available in blockchain. More particularly, Wallet contract stores *zkID* and fresh ephemeral public key. Hence, an honest but curious OpenID provider knowing stable ids of all his users can carry out dictionary attack to deanonymize blockchain accounts.

Groth16 zk-proof computed by Proof Service is sent to Wallet smart-contract to authenticate the user. To prevent the case of malicious Proof service pretending to be the user and some other possible attacks, an extra step into the authentication process is added. The user must sign a message sent into the Wallet smart-contract by *SK\_e* that only the user knows.
{% endhint %}

{% hint style="info" %}
There is a single public key pair (*proof\_key, verify\_key*) generated during the trusted setup phase called Powers-of-tau ceremony, which we describe in a separate document. This key pair is generated only once and depends on a related Zk-auth AC that we briefly discussed already. This key pair is not a secret and used for all clients later. Proof service uses *proof\_key* (that is the same for everyone) to generate proofs. In the meantime, *verify\_key* (that is also public) is embedded into TVM that has a respective instruction VERGRTH16, using this key to verify zero-knowledge proofs. The last instruction is used by the Multi-factor Wallet smart-contract.

The described process is fulfilled by the user at the first time. And then each time when the keypair (*SK\_e, PK\_e*) becomes expired, the user must relogin to get a fresh JWT for the new *PK\_e*. But until *PK\_e* is not expired, Client Application must store and use JWT and related zero-knowledge proof generated by Proof service. The frequency of OpenID relogin is regulated by us, since we choose *T\_max* ourselves and completely ignore standard `exp` claim in JWT that is set by the OpenID provider.

Let’s summarize how a transaction is conducted at the first time (or if an ephemeral key pair/JWT is expired).

* The user makes a signIn in an OpenID account, gets signed JWT and requests zk-proof for it from Proof service using Salt Password.
* The user sends to the Multi-factor Wallet contract fresh zk-proof and related *PK\_e, T\_max*, OpenID JWK RSA public key data.
* Multi-factor Wallet contract checks that *T\_max* is not expired valid Unix timestamp. Then it verifies zk-proof using VERGRTH16 instruction. The public data used for zk-proof verification: *PK\_e, T\_max*, OpenID JWK RSA public key and *zkID*. If *T\_max* is not expired and zk-proof is valid, then the Wallet contract saves a pair (*PK\_e, T\_max*) into mapping \_factors.
* The user sends a message/transaction to Wallet to transfer some amount. The message is signed by *SK\_e*. Multi-factor Wallet contract checks that the related public key *PK\_e* was previously added into mapping *\_factors* and its timestamp *T\_max* is not smaller than the latest block time. If this is true, then transfer will be done.
  {% endhint %}

{% hint style="warning" %}
The secret key *SK\_e* is stored in local storage in the browser or secure storage/element in a smartphone, locked by standard passkey.
{% endhint %}

{% hint style="info" %}
The *T\_max* timestamp aimed to limit operation time of ephemeral keypair (*PK\_e, SK\_e*). Using the parameter *T\_max* we maintain the required reasonable frequency of OpenID relogin to handle Wallet transactions. We must keep a balance between security and user comfort. It’s reasonable to choose *T\_max* quite big to avoid cumbersome using experience to relogin too often. But the user always has an option to add/change ephemeral keypair at any moment of time. At the same time multiple ephemeral key pairs could be handled by the Wallet contract for the same OpenId account (for example each key pair per new device).
{% endhint %}

<figure><img src="/files/dZWPLZdNRCf9nQwgqygQ" alt=""><figcaption></figcaption></figure>

### Transaction WITHOUT signIn to OpenID provider

This is the case when the user has not expired ephemeral key pair (*SK\_e, PK\_e*), for which public key *PK\_e* was previously added into the Multi-factor Wallet contract (like we described above). Then the user sends only a message signed by *SK\_e*. Multi-factor Wallet contract checks that the related public key *PK\_e* was previously added into mapping \_factors and *T\_max* is fresh. If this is true, then the message will be accepted by contract.

{% hint style="info" %}
We minimize the number of VERGRTH16 instruction calls to achieve the best transaction performance. VERGRTH16 is quite cumbersome. So the user calls it only once for a fresh JWT zk-proof. The Wallet contract validates zk-proof. If it’s ok, then it saves the related ephemeral public key and the time of its expiration. Then the user only sends to contract messages signed by ephemeral secret key. The contract checks that the key is present, not expired and the signature is valid.
{% endhint %}

<figure><img src="/files/8oaa3ZCk5qXx0SHCEQqR" alt=""><figcaption></figcaption></figure>

## More details on handling OpenID via zero-knowledge proofs

In Acki Nacki blockchain we allow users to login into their Wallets with OpenID accounts credentials. For this we use JWT tokens obtained after successful authentication from Google, Facebook and other major services supporting OpenID. We do not reveal JWT tokens themselves and therefore do not leak access to the original service and preserve anonymity. This is achieved through a zero-knowledge proof protocol that provides blind verification of the properties of JWT tokens. We use Groth16 over the elliptic curve BN254, a non-interactive zero-knowledge proof verification system.

### OpenID and JSON Web Tokens (JWTs)

We use the OpenID protocol. In this protocol a user can log into a trusted third party (Google, Facebook, etc.) and get a signed access token attesting that they logged in the form of a signed JSON Web Token (JWT). A signed JWT looks like three base64-encoded payloads separated by a dot:

<figure><img src="/files/DPRALinRCvvwxPVg7rdu" alt=""><figcaption></figcaption></figure>

When decoded, the first part of the payload is a header, the second is the JWT's content itself (called the payload), and the third one is the signature that is done by the OpenID provider secret JWK key. One can use the debugger on jwt.io to inspect such JWTs:

<figure><img src="/files/yjZUdA498lyqXbSIi1nR" alt=""><figcaption></figcaption></figure>

There are the following important fields in the JWT payload :

* the issuer `iss` field, indicates who issued and signed the JWT.
* the audience, `aud` field, indicates who the JWT was meant for.
* the subject `sub` field, represents a unique user ID (from the point of view of the issuer) who the JWT is authenticating.
* the `nonce` field contains a user nonce for the application to prevent replay attacks.

### Verifying JWTs

To verify a JWT, one needs to verify the signature over the JWT. To verify a signature one must know the public key of the issuer of the JWT. All issuers have a published JSON Web Key Set (JWKS). For example, Facebook's JWKS can be downloaded from <https://www.facebook.com/.well-known/oauth/openid/jwks> and looks like the picture below.

<figure><img src="/files/MOBbgZirH5tYVItIqZwF" alt="" width="543"><figcaption></figcaption></figure>

JWKS contains several JSON Web Keys (JWKs) identified by their key ID `kid`. Several keys are often displayed to provide support for key rotation. Since this information is external to the JWT, the network must know who the issuer is, and specifically `kid` that was used to issue the JWT.

Since the issuer of a JWT is contained in the payload, not in the header, the Zk-auth circuit (described below) must extract this value and witness it in its public input.

### Zk-auth arithmetic circuit

Here we discuss what the Zk-auth circuit does at a high level. Given the following public input:

* the issuer `iss` field (that we expect to find in JWT);
* the RSA public key of the issuer.

It extracts the following as public output:

* the ephemeral public key contained in the `nonce` field of the JWT, as well as expiration information;
* *zkID* value introduced before, which is a hash linking user's OpenID account (stable ID) with blockchain address;
* the header of the JWT (which the network needs to validate, and also contains the key ID used by the issuer)
* the audience `aud` field of the JWT.

Zk-auth circuit in addition to extracting above public outputs performs the following:

* It inserts the actual JWT in the Zk-auth circuit as a private witness.
* It checks that the issuer passed as public input is indeed the one contained in the JWT.
* It hashes the JWT with SHA-256 and then verifies the signature (passed as private input) over the obtained digest using the issuer's public key (passed as public input).
* It derives *zkID* value deterministically using the Poseidon hash function and the user identifier (e.g., an email) as well as some user randomness.

The signature is verified in zk-auth circuit to avoid issuers from being able to track users on-chain via the signatures and digests.

The idea at this point is for the network to make sure that, besides the validity of the zk-proof, the address is strongly correlated to the user.


# Formal Verification


# Multi-Factoring Business-level Specification


# Troubleshooting


# What to Do if Your Authentication Factor Has Expired

This guide explains how to refresh an expired authentication factor in AN Wallet

If AN Wallet shows **Security factor expired**, you need to refresh the ZK factor by signing in again with the same wallet name and the same social account.

<figure><img src="/files/oagGzLFbr6UuW8HrbNrZ" alt="" width="364"><figcaption></figcaption></figure>

While the security factor is expired, wallet operations will not work. This also affects connected features that depend on the wallet, including mining keys.

{% hint style="info" %}
**The ZK factor lets AN Wallet confirm that you signed in with the correct social account without publicly linking that account to your wallet on-chain**. When the factor is valid, the wallet can use it for operations without asking you to complete the full social sign-in flow each time. When it expires, you need to sign in again to refresh it.
{% endhint %}

### Before You Sign Out

{% hint style="danger" %}
**Before signing out, make sure you know your seed phrase and that it is saved in a secure place.**\
You may need the seed phrase to restore access to your wallet.
{% endhint %}

<figure><img src="/files/WKpzbAq84Sd5TFblOUVq" alt="" width="317"><figcaption></figcaption></figure>

### Refresh the Authentication Factor

#### 1. Sign Out of the Wallet

Open the AN Wallet settings and sign out by tapping "Log Out" at the bottom of the screen.

<figure><img src="/files/No9kfYvmcDJTzaue0SQy" alt="" width="317"><figcaption></figcaption></figure>

***

#### 2. Sign In Again

Launch the AN Wallet flow again. On the sign-in screen, select the option "Recover existing wallet".

<figure><img src="/files/ezfhtMiCZf3HZRsRizzc" alt="" width="315"><figcaption></figcaption></figure>

***

#### 3. Sign In with the Same Wallet Details

Use exactly the same wallet name that you used before signing out, enter the wallet password, and sign in with the same social account that were used for this wallet (Google, Facebook or Telegram).

<div><figure><img src="/files/X4KZgPl84EIJeHjbUEvc" alt=""><figcaption></figcaption></figure> <figure><img src="/files/7bDETQXergV7NgCABCIp" alt=""><figcaption></figcaption></figure> <figure><img src="/files/PMLnKKTys0r8BmbWgyRL" alt=""><figcaption></figcaption></figure></div>

***

#### 4. Confirm the New ZK Factor

After successful sign-in, AN Wallet will set up a fresh ZK authentication factor for your wallet.

<figure><img src="/files/B2njQgNqy15gyRoe13Ce" alt="" width="325"><figcaption></figcaption></figure>

### Result

Your authentication factor is refreshed. You can continue using the wallet with the same wallet name and the same social authentication factor.


# Buy/Sell Shell


# Introduction

## What is SHELL?

[**SHELL**](/glossary#shell) is the utility token of the Acki Nacki network ([ECC](/glossary#extra-currency-collection) index 2), designed to compensate [NACKL](/glossary#nackl) holders for the computing resources the network provides. It can be converted to [VMSHELL](/glossary#vmshell) to cover network fees at a 1:1 ratio (reverse conversion is not possible). It can be freely transferred between different [Dapp IDs](/glossary#dapp-id).

## Fixed Exchange Rate

The SHELL exchange rate is fixed and the same for all participants:

> **1 USDC = 100 SHELL**

This rate never changes and is independent of market conditions. When buying, you always receive exactly 100 SHELL for every USDC spent. When selling, you always receive exactly 1 USDC for every 100 SHELL.

## Ways to Buy SHELL

| Method                      | Application or interface                          | Payment                            | Speed                       |
| --------------------------- | ------------------------------------------------- | ---------------------------------- | --------------------------- |
| Direct contract interaction | `tvm-cli`                                         | eccUSDC (ECC\[3])                  | Instant                     |
| Cryptocurrency              | [Shell Buyer App](https://shellbuy.ackinax.com/)  | Visa, Mastercard, USDT, USDC, etc. | Depends on payment provider |
| ECC USDC in the wallet      | [Acki Nacki Wallet](https://ackinacki.com/wallet) | ECC USDC (network-native currency) | Instant                     |

## Selling SHELL

Selling SHELL is done exclusively through the **Acki Nacki Wallet**. You place an order (lots), and when a buyer comes along, your lots are sold automatically on a first-come-first-served (FIFO) basis. Learn more in [How to Sell SHELL](/for-users/buy-sell-shell/selling-shell/how-to-sell-shell#prerequisites).

## What's Next?

If you're just getting started with SHELL, we recommend reading [Key Concepts](/for-users/buy-sell-shell/key-concepts) first, then proceeding to the relevant buying or selling section.


# Key Concepts

Before buying or selling SHELL, it helps to understand the core terms and mechanisms.

## Ecosystem Tokens

### SHELL (ECC\[2])

The primary tradable token. Used for transferring value between different Dapp IDs and subsequent conversion within the Acki Nacki ecosystem to VMSHELL for payment network fees.

### USDC (ECC\[3])

A stablecoin pegged to the US dollar. Used for settlements when buying and selling SHELL. Within the Acki Nacki network, USDC exists as ECC\[3] — an element of the Extra Currency Collection.

### NACKL (ECC\[1])

The native token of the Acki Nacki network. Used for value storage and staking. Can be burned (Redeem) to receive a share of the free USDC reserve.

## Extra Currency Collection (ECC)

The set of currencies within the Acki Nacki network designed for various tasks: paying fees, transferring value, staking. Each currency has its own index: NACKL — 1, SHELL — 2, USDC — 3.

## Exchange Rate

The rate is fixed and immutable:

**1 USDC ecc = 100 SHELL**

{% hint style="info" %}
This means buying 10 USDC worth of SHELL always yields 1,000 SHELL, and selling 5,000 SHELL always yields 50 USDC.
{% endhint %}

## Denominations

A denomination is a fixed lot size when selling SHELL. There are four denominations, similar to banknotes:

| Denomination (USDC ecc) | SHELL Equivalent |
| :---------------------: | :--------------: |
|            1            |        100       |
|            10           |       1,000      |
|           100           |      10,000      |
|          1,000          |      100,000     |

No other denominations exist. When selling SHELL, the wallet automatically breaks down your amount into lots of these denominations.

## Lot

A lot is a single indivisible sell order for SHELL. Each lot is tied to a specific denomination (1, 10, 100, 1,000 USDC ecc) and can only be sold in full. Partial selling of a lot is not possible.

**Example:** a lot with denomination 10 USDC means the seller deposited 1,000 SHELL and is waiting to receive 10 USDC when their turn comes.

## Queue (FIFO)

Each denomination has its own separate queue of lots (4 queues total). Queues work on a First-In-First-Out (FIFO) basis. If you placed your order before others, your lot will be sold first.

## Free Reserve

The free reserve is the USDC held in the contract that is not reserved for any seller. It is formed as follows: when a buyer pays USDC, the system first uses SHELL from seller queues. If there aren't enough sellers, the system creates (mints) the missing SHELL. The USDC received for minted SHELL forms the free reserve.

The free reserve is used exclusively for Redeem NACKL payouts.

## Claim

The process of a seller receiving USDC after their lot has been sold. In Acki Nacki Wallet, this happens automatically in the background.

## Mint

The creation of new SHELL tokens by the system. Occurs when a buyer wants to purchase SHELL but there aren't enough sellers in the queues.

## Redeem (Burn) NACKL

The operation of burning NACKL to receive a share of the free USDC reserve. Irreversible.

## Root (ShellAccumulatorRootUSDC)

The central smart contract of the Accumulator system. Processes SHELL purchases, manages seller queues, performs minting, and handles payouts.

## SellOrderLot (ShellSellOrderLot)

A smart contract representing a single seller lot. Created when a sell order is placed. Self-destructs after USDC payout.


# Buying SHELL


# Ways to Buy SHELL

There are three ways to purchase SHELL tokens. The choice depends on your payment method and whether you prefer a graphical application or direct smart-contract interaction.

## Option 1: Accumulator Contract — Exchange eccUSDC Directly

**For:** advanced users and operators who already have eccUSDC (ECC\[3]) and want to submit the exchange transaction with `tvm-cli`.

**Interface:** the Accumulator smart contract on Mainnet/Shellnet.

**How it works:**

1. Prepare a wallet transaction containing a whole-number amount of eccUSDC
2. Send the transaction to the Accumulator contract with the required VMSHELL value
3. The contract exchanges eccUSDC at the fixed rate of 1 eccUSDC = 100 SHELL
4. SHELL is credited to the sending contract or to a recipient encoded in the payload

Detailed guide: [Exchange eccUSDC for SHELL via the Accumulator](/for-users/buy-sell-shell/buying-shell/exchange-eccusdc-for-shell-via-accumulator)

***

## Option 2: Shell Buyer App — Pay with Card or Crypto

**For:** users who want to buy SHELL using fiat currency (credit/debit card) or cryptocurrency (USDT, USDC).

**Application:** [Shell Buyer App](https://shellbuy.ackinax.com/) — a web application accessible through any browser. A mobile version is planned for the future.

**How it works:**

1. Open the Buy Shell App
2. Connect your Acki Nacki Wallet
3. Choose a payment method (card or cryptocurrency)
4. Enter the amount
5. Payment is processed through the payment provider
6. SHELL is credited to your wallet

Detailed guide: [Buy via Shell Bayer App](https://shellbuy.ackinax.com/)

***

## Option 3: Acki Nacki Wallet — Pay with eccUSDC

**For:** users who already have eccUSDC in their balance on the Acki Nacki wallet.

**Application:** [Acki Nacki Wallet (mobile app)](https://ackinacki.com/wallet).

**How it works:**

1. Open the Buy/Sell SHELL section in the wallet
2. Enter the eccUSDC amount
3. Confirm the transaction
4. SHELL is instantly credited to your balance

Detailed guide: [Buy via Acki Nacki Wallet](/for-users/buy-sell-shell/buying-shell/exchange-eccusdc-for-shell-via-acki-nacki-wallet-android-only)

***

## Which Method Should I Choose?

* **Already have eccUSDC and prefer a graphical interface?** Use the Acki Nacki Wallet — it's instant and has no additional fees.
* **Need to exchange eccUSDC programmatically?** Send the exchange transaction directly to the Accumulator contract.
* **Have a bank card or crypto on another blockchain?** Use the Shell Buyer App — it lets you buy SHELL without needing to acquire eccUSDC first.


# Exchange eccUSDC for SHELL via Accumulator

This guide explains how to exchange [eccUSDC](/glossary#usdc-ecc) for SHELL by sending an internal message from a user wallet to the Accumulator contract.

## Prerequisites

* [tvm-cli](https://github.com/tvmlabs/tvm-sdk/releases)
* A deployed `UpdateCustodianMultisigWallet_v2` wallet; the Acki Nacki Wallet app cannot submit this raw contract transaction. To deploy one: [How to deploy a Multisig Wallet](https://dev.ackinacki.com/how-to-deploy-a-multisig-wallet)
* The wallet's full `<WALLET_DAPP_ID>::<WALLET_ACCOUNT_ID>` address and the keys file required to sign transactions
* The `UpdateCustodianMultisigWallet_v2.abi.json` ABI file available locally
* At least `1 eccUSDC` (ECC currency ID `3`); only whole eccUSDC amounts can be exchanged
* More than `0.1 VMSHELL` in the wallet to cover the message value and transaction fees

## Summary

To perform the exchange, send the following to the Accumulator address:

* eccUSDC as an ECC currency with ID `3`;
* `0.1 VMSHELL` (`100000000` base units) to execute the message;
* an empty `payload`.

The purchased SHELL will be sent back to the address of the contract from which the Accumulator received the message.

The current Accumulator address is:

```
0:3535353535353535353535353535353535353535353535353535353535353535
```

This is the legacy address format that must be used in ABI fields such as `dest`, `buyer`, `recipient`, and other message parameters.

In `tvm-cli` 3.x commands where the address is the target of the command itself (`--addr`, `account`, `runx`, or `callx`), Mainnet/Shellnet requires the full `dapp_id::account_id` format. The full CLI address of the Accumulator is:

```
0000000000000000000000000000000000000000000000000000000000000001::3535353535353535353535353535353535353535353535353535353535353535
```

## Exchange Rate and Base Units

The exchange rate is fixed:

```
1 eccUSDC = 100 SHELL
```

Message amounts are specified in base units:

* `1 eccUSDC = 1,000,000` eccUSDC units;
* `1 SHELL = 1,000,000,000` SHELL units.

The Accumulator accepts only whole USDC amounts. The eccUSDC amount must be greater than zero and divisible by `1,000,000`.

|        Sent | Value in `cc["3"]` |     Received |
| ----------: | -----------------: | -----------: |
|   1 eccUSDC |          `1000000` |    100 SHELL |
|  10 eccUSDC |         `10000000` |  1,000 SHELL |
| 100 eccUSDC |        `100000000` | 10,000 SHELL |

Use this formula when preparing the message:

```
cc["3"] = eccUSDC amount × 1,000,000
```

## Before You Exchange

{% stepper %}
{% step %}

### Confirm the wallet has eccUSDC

The wallet has enough eccUSDC with ID `3`.
{% endstep %}

{% step %}

### Confirm the wallet has VMSHELL

The wallet has enough VMSHELL to send the message and pay the transaction fee.
{% endstep %}

{% step %}

### Confirm the destination

The destination address matches the Accumulator address.
{% endstep %}

{% step %}

### Include only eccUSDC

The message contains only one ECC currency: eccUSDC with ID `3`.
{% endstep %}

{% step %}

### Use a whole-eccUSDC amount

The eccUSDC amount is divisible by `1,000,000`.
{% endstep %}

{% step %}

### Set the required value and flags

The `value` field is `100000000` and the `flags` field is `0`.
{% endstep %}
{% endstepper %}

{% hint style="warning" %}
Do not send eccUSDC together with other ECC currencies in the same message. The Accumulator rejects messages containing multiple currencies.
{% endhint %}

## Message Parameters

Use these parameters to purchase SHELL for `1 USDC`:

```json
{
  "dest": "0:3535353535353535353535353535353535353535353535353535353535353535",
  "value": "100000000",
  "cc": {
    "3": "1000000"
  },
  "bounce": true,
  "flags": 0,
  "payload": ""
}
```

| Field     | Value               | Purpose                                               |
| --------- | ------------------- | ----------------------------------------------------- |
| `dest`    | Accumulator address | Contract that performs the exchange                   |
| `value`   | `100000000`         | 0.1 VMSHELL for executing the internal message        |
| `cc`      | `{"3":"1000000"}`   | 1 eccUSDC in base units                               |
| `bounce`  | `true`              | Returns the message to the sender if execution fails  |
| `flags`   | `0`                 | Deducts the forwarding fee from the specified `value` |
| `payload` | Empty string        | Invokes the Accumulator's `receive()` handler         |

{% hint style="info" %}
Use the `value = 100000000` and `flags = 0`. After the fee is deducted, the Accumulator receives approximately `0.098731 VMSHELL`, which is enough to execute the exchange. Do not set `value = 0`: no outgoing message will be created, and the fee for the failed attempt will still be charged.
{% endhint %}

Some wallets may name the ECC currency field `ecc` or `currencies` instead of `cc`. The meaning is the same: key `3` is the eccUSDC identifier, and its value is the amount in base units.

## Send from an UpdateCustodianMultisigWallet\_v2 Multisig

For a wallet with one custodian, call the `sendTransaction` method.

The following Shellnet example exchanges `1 USDC`:

{% hint style="info" %}
For the Mainnet network, use the `mainnet.ackinacki.org` endpoint.
{% endhint %}

```bash
tvm-cli -j -u shellnet.ackinacki.org callx \
  --addr <WALLET_DAPP_ID>::<WALLET_ACCOUNT_ID> \
  --abi contracts/0.81.0_compiled/updatecustodianmultisigwallet_v2/UpdateCustodianMultisigWallet_v2.abi.json \
  --keys <WALLET_KEYS_FILE> \
  --method sendTransaction \
  '{
    "dest":"0:3535353535353535353535353535353535353535353535353535353535353535",
    "value":"100000000",
    "cc":{"3":"1000000"},
    "bounce":true,
    "flags":0,
    "payload":"",
    "dapp_id":"0x0000000000000000000000000000000000000000000000000000000000000001"
  }'
```

The `dapp_id` field in this wallet version is used for transfer reporting. The Accumulator DApp ID is `1`.

{% hint style="warning" %}
Do not use the legacy `0:<WALLET_ACCOUNT_ID>` address in the `--addr` parameter. The current `tvm-cli` accepts only the full `<WALLET_DAPP_ID>::<WALLET_ACCOUNT_ID>` format here. The `dest` value inside the JSON must remain in the legacy `0:3535...` format.
{% endhint %}

If the wallet has multiple custodians, use `submitTransaction` with the same parameters instead of `sendTransaction`, and then collect the required number of confirmations through the wallet's usual process.

{% hint style="warning" %}
Do not use outdated multisig versions.
{% endhint %}

## Receive SHELL at Another Address

With an empty `payload`, the SHELL recipient is `msg.sender`. If a multisig contract sends the message, the SHELL is credited to that multisig contract's balance.

To send the purchased SHELL to another address, call the following Accumulator method:

```
buyShellFor(address buyer)
```

First, generate the ABI-encoded call body:

```bash
tvm-cli -j body \
  --abi contracts/0.79.3_compiled/accumulator/ShellAccumulatorRootUSDC.abi.json \
  buyShellFor \
  '{"buyer":"0:<RECIPIENT_ACCOUNT_ID>"}'
```

Pass the resulting `Message` value in the transaction's `payload` field instead of an empty string. The message must still include eccUSDC with ID `3` and `0.1 VMSHELL` for execution.

Example wallet parameters:

```json
{
  "dest": "0:3535353535353535353535353535353535353535353535353535353535353535",
  "value": "100000000",
  "cc": {
    "3": "1000000"
  },
  "bounce": true,
  "flags": 0,
  "payload": "<ENCODED_BUY_SHELL_FOR_MESSAGE>",
  "dapp_id": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
```

The `buyer` address determines the SHELL recipient. In this case, the SHELL is not returned to the sender.

## Verify the Result

{% stepper %}
{% step %}

### Confirm the eccUSDC balance decreased

The sender's eccUSDC balance with ID `3` decreases by the amount sent.
{% endstep %}

{% step %}

### Confirm the SHELL balance increased

The recipient's SHELL balance with ID `2` increases according to the exchange rate.
{% endstep %}

{% step %}

### Check the event

The Accumulator emits a `ShellPurchased` event.
{% endstep %}
{% endstepper %}

The event contains:

* `buyer`: the SHELL recipient address;
* `usdcAmount`: the amount of eccUSDC received;
* `shellFromSellers`: SHELL obtained from existing seller orders;
* `shellMinted`: additional SHELL minted by the system.

The source of the SHELL does not change the result for the user: `shellFromSellers + shellMinted` is sent to the recipient in a single transaction.

How the queues, lots and payouts work: [Accumulator contract system](https://dev.ackinacki.com/accumulator-contract-system/overview).

Check the wallet balance with:

{% hint style="info" %}
For the Mainnet network, use the `mainnet.ackinacki.org` endpoint.
{% endhint %}

```bash
tvm-cli -j -u shellnet.ackinacki.org account \
  <WALLET_DAPP_ID>::<WALLET_ACCOUNT_ID>
```

In the `ecc_balance` field:

* key `3` contains the eccUSDC balance in micro-USDC;
* key `2` contains the SHELL balance in nanoSHELL.

After exchanging `1 USDC`, the balance under key `3` should decrease by `1000000`, and the balance under key `2` should increase by `100000000000`.

## Common Errors

<details>

<summary>Amount Is Not a Whole USDC Value</summary>

A `cc["3"]` value such as `1500000` represents `1.5 USDC` and will be rejected. Use only whole amounts such as `1000000`, `2000000`, or `10000000`.

</details>

<details>

<summary>Incorrect ECC ID</summary>

Use ID `3` to purchase SHELL. ID `2` represents SHELL and starts a different operation: creating a SHELL sell order.

</details>

<details>

<summary>Multiple ECC Currencies Included</summary>

The `cc` object must contain only one entry with key `3`. A message containing multiple ECC currencies will be rejected.

</details>

<details>

<summary>SHELL Was Credited to the Multisig Instead of a Personal Address</summary>

This is expected with an empty `payload`: the recipient is the contract that sent the message. Use `buyShellFor` if the SHELL must be sent to another address.

</details>

<details>

<summary>Standard TIP-3 USDC Was Used for the Exchange</summary>

The Accumulator accepts eccUSDC, the ECC currency with ID `3`. Standard TIP-3 USDC must first be converted to eccUSDC through the appropriate bridge.

</details>

## Important

{% hint style="warning" %}
Before sending a large amount, perform a test exchange of `1 USDC` and confirm that the SHELL arrived at the expected address. Blockchain transactions are irreversible.
{% endhint %}


# Exchange eccUSDC for SHELL via Acki Nacki Wallet (Android only)

If you already have ECC USDC in your balance, you can instantly buy SHELL directly in the Acki Nacki Wallet mobile app.

## Prerequisites

* Acki Nacki Wallet app installed
* ECC USDC in your balance (minimum 1 USDC)

## Step-by-Step Guide

{% stepper %}
{% step %}

#### Open the Exchange Section

On the main wallet screen, where your balances are displayed, tap the **Exchange** button button and select **Buy and Sell SHELL**

<div><figure><img src="/files/PijRoudLPjBx1Jm6BBc0" alt=""><figcaption></figcaption></figure> <figure><img src="/files/vxYZyfIkGABNG7pEkxfO" alt=""><figcaption></figcaption></figure></div>
{% endstep %}

{% step %}

#### Select Buy

In the exchange screen, make sure the **Buy** mode is selected.

<figure><img src="/files/H4c2hZD9Jf2dJHG7kj7I" alt="" width="287"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Enter the USDC Amount

In the **Select amount** field, enter the amount of USDC (ecc) you want to spend on SHELL. The system will instantly show how much SHELL you'll receive.

**Input rules:**

* Whole numbers only (1, 5, 100, etc.)
* Minimum amount — 1 USDC
* Cannot exceed your ECC USDC balance

Your current USDC balance is displayed at the bottom of the screen.

**Example:** you enter 50 USDC — the system shows you'll receive 5,000 SHELL.

<figure><img src="/files/lhvvZLwUYcZeRLqDh3k6" alt="" width="285"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Tap "Buy SHELL"

After entering the amount, tap the **Buy SHELL** button at the bottom of the screen
{% endstep %}

{% step %}

#### Confirm the Purchase

A confirmation screen appears with the details:

<figure><img src="/files/8kMgWC4QOqGHf2n8lAvI" alt="" width="280"><figcaption></figcaption></figure>

Tap **Confirm** to proceed or **Cancel** to go back
{% endstep %}

{% step %}

#### Wait for Execution

The transaction is being processed on the blockchain.
{% endstep %}

{% step %}

#### Purchase Complete

On success, you'll see the confirmation:

<div><figure><img src="/files/vDCrBWzl5YA0MsD3HnYa" alt="" width="278"><figcaption></figcaption></figure> <figure><img src="/files/ymnmdw7HuN6tfDYX2uZl" alt="" width="287"><figcaption></figcaption></figure></div>

Tap **Close** to return to the main screen. Your SHELL balance will update automatically.
{% endstep %}
{% endstepper %}

## What Happens Under the Hood

When you buy SHELL, the system follows this algorithm:

1. Your USDC is sent to the Accumulator smart contract
2. The contract checks if there is SHELL available in seller queues
3. If sellers exist — their SHELL is transferred to you, and USDC is reserved for seller payouts
4. If there aren't enough sellers — the missing SHELL is created (minted) by the system
5. All SHELL is sent to you in a single transaction

As a buyer, it doesn't matter where the SHELL came from — you always receive exactly **amount × 100 SHELL**.

## Possible Errors

| Message                       | Cause                         | Solution                                 |
| ----------------------------- | ----------------------------- | ---------------------------------------- |
| Buy SHELL button inactive     | Amount field is empty or zero | Enter an amount greater than 0           |
| Enter a whole number          | A decimal number was entered  | Enter a whole number                     |
| Insufficient USDC ecc balance | Not enough USDC ecc           | Reduce the amount or top up your balance |
| Transaction failed. Try again | Transaction error             | Try again after a few seconds            |


# Purchase with Crypto or Card (Credit/Debit)

Shell Buyer is a web application for purchasing SHELL tokens using a credit/debit card or cryptocurrency. Available at [shellbuy.ackinax.com](https://shellbuy.ackinax.com/).

## How It Works

The purchase consists of three steps:

1. **Connect Wallet** — scan a QR code with your Acki Nacki Wallet to link it
2. **Choose Package** — select a token package and pay with a card or crypto
3. **Confirm & Receive** — SHELL tokens are delivered directly to your wallet

## Prerequisites

* A browser (Chrome, Firefox, Safari, or any modern browser)
* [Acki Nacki Wallet app](https://ackinacki.com/wallet) installed on your phone
* A credit/debit card (Visa, MasterCard) **or** cryptocurrency (USDC, USDT)

## Step-by-Step Guide

{% stepper %}
{% step %}

#### Open Shell Buyer

Navigate to [https://shellbuy.ackinax.com](https://shellbuy.ackinax.com/) in your browser.\
A **Connect Your Wallet** card appears with the **Generate QR Code** button. Click it.

<figure><img src="/files/ZHRWNadXO0jJGPjQG2nU" alt="" width="375"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Choose Your Packages

The **Choose Your Packages** screen displays five token packages:

<figure><img src="/files/UXmVPdI3cLkwWqjeWlsy" alt=""><figcaption></figcaption></figure>

Each package has a quantity selector (−/+). You can add multiple packages to your order. The **Order Summary** panel on the right updates in real time, showing the selected packages, total SHELL, and subtotal.

When ready, tap **Connect Wallet**.
{% endstep %}

{% step %}

#### Scan the QR Code

A QR code is displayed on screen with the message **Approve in your wallet**. You can scan the code either with your phone's camera or with the scanners in the Acki Nacki Wallet app. The page shows "Waiting for wallet confirmation…"

<figure><img src="/files/Y7BHeBkFEVw1I8119Q0D" alt="" width="133"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Confirm Connection in the Wallet

Open your Acki Nacki Wallet app. A prompt appears: **Do you want to connect your wallet to Shell Buyer?** Tap **Connect** to confirm.

<figure><img src="/files/Q80XhLd6tpabWsPEePjj" alt="" width="188"><figcaption></figcaption></figure>

After confirming, the wallet shows a success screen: **Wallet has been connected**.

<figure><img src="/files/ieUHJ1qmp6drulCVcID6" alt="" width="188"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Wallet Connected

Returning to your browser, you'll see the "Order Summary" page with your wallet name, address, and package details.

If everything is correct, click "Proceed to Checkout."

<figure><img src="/files/KLLki09WONUvwbty4p0Y" alt="" width="267"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Fill in Contact Information

On the Checkout page, fill in:

* **Full Name**
* **Email Address**
* **Country**

{% hint style="info" %}
The **Order Summary** on the right shows your selected packages, SHELL amount, subtotal, any applicable fees and taxes, and the total.
{% endhint %}
{% endstep %}

{% step %}

#### Select Payment Method

{% tabs %}
{% tab title="Credit Card" %}
In the **Payment Method** section, select **Credit Card** (selected by default). The button at the bottom reads **Pay $X.XX with Card**.

Tap **Pay with Card**.

<figure><img src="/files/lL4x4OL2REGPG3lJuLAM" alt=""><figcaption></figcaption></figure>
{% endtab %}

{% tab title="Cryptocurrency" %}
In the **Payment Method** section, select **Crypto**. Additional fields appear:

* **Currency** — choose USDC or USDT

<figure><img src="/files/a7C3T1PBUkN2ffmnAfMt" alt="" width="233"><figcaption></figcaption></figure>

* **Network** — choose from Arbitrum, Ethereum, BSC, Polygon, Optimism, or Tron

<figure><img src="/files/gfGyGCvnCnkMKUgDKACU" alt="" width="234"><figcaption></figcaption></figure>

After selecting the currency and network, the button reads **Pay $X.XX with \[currency]**.

Tap the **Pay** button:

<figure><img src="/files/Jw0m9Nr8vrILvhyP6Iyj" alt="" width="375"><figcaption></figcaption></figure>
{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### Complete Payment

{% tabs %}
{% tab title="Credit Card" %}
You are redirected to the payment provider's page (Stripe). Here you can:

* Choose the payment currency (e.g. EUR or USD)
* Enter card details (card number, expiry, CVC, cardholder name)
* Select your country or region
* Optionally use Amazon Pay or other available methods (Bancontact, EPS, etc.)

Complete the payment by tapping **Pay**.

<figure><img src="/files/1DffXtpLift2gZpupFA0" alt="" width="375"><figcaption></figcaption></figure>

{% hint style="info" %}
Payments are securely processed. Card details never touch Shell Buyer servers.
{% endhint %}
{% endtab %}

{% tab title="Cryptocurrency" %}
You are redirected to the NOWPayments page.\
The page displays:

* A **QR code** for the payment address
* The exact **amount** to send (e.g. 10.22142717 USDC)
* The **address** to send to
* A countdown **timer** for the exchange rate lock
* Payment status: Waiting for payment → Processing payment → Success

Send the specified amount of the selected cryptocurrency to the provided address on the correct network.

<figure><img src="/files/onNqoepYLsB2e785zHXb" alt="" width="375"><figcaption></figcaption></figure>

{% hint style="warning" %}
**Important:** send the exact amount shown. The payment must be sent before the timer expires. Payments below the minimum amount cannot be processed. Completed payments are non-refundable.
{% endhint %}

Once the payment is detected, the status changes to **Payment Processing**:

<figure><img src="/files/q5VGIyH8ic8J06R8mwKN" alt="" width="375"><figcaption></figcaption></figure>
{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### Track Your Order

After payment, the **Order Status** page shows a progress bar with five stages:

1. **PENDING** — order created
2. **PAYMENT CREATED** — payment initiated
3. **PAYMENT CONFIRMED** — payment confirmed by the provider
4. **MINTING** — SHELL tokens are being minted on the Acki Nacki chain
5. **DELIVERED** — tokens have been sent to your wallet

The **Order Details** section displays: Order ID, Status, Amount, SHELL Tokens, Payment Method, Created timestamp, Delivery Transaction link, and Delivered At timestamp.

<figure><img src="/files/RhUaX4VMx4gmlDavUqph" alt="" width="375"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Order Delivered

When all stages are complete, the status shows **DELIVERED** with confirmation badges: **Minter** ✓ and **On-Chain** ✓. An **On-Chain Verified** timestamp confirms that the tokens have been verified on the Acki Nacki blockchain.

<figure><img src="/files/f7WUfB2QzuOCLX0EPUuN" alt="" width="375"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Check Your Wallet

Open your Acki Nacki Wallet. Your SHELL balance now reflects the purchased tokens (e.g. 800 SHELL).

<figure><img src="/files/X4BJc17mw9zW4JTFgopI" alt="" width="188"><figcaption></figcaption></figure>
{% endstep %}
{% endstepper %}

## Important Notes

* Payment provider fees (card processing fee, VAT) may be added depending on your country and payment method
* Processing time depends on the payment method: card payments usually take a few minutes, cryptocurrency transfers may take up to 5 minutes after confirmation
* After payment, SHELL minting and delivery happen automatically
* You can track order progress on the Order Status page at any time

## Possible Errors

| Message                  | Cause                            | Solution                                    |
| ------------------------ | -------------------------------- | ------------------------------------------- |
| Payment failed           | Payment provider error           | Try again or use a different payment method |
| Wallet connection failed | QR code expired or network issue | Generate a new QR code and try again        |


# Selling SHELL


# How to Sell SHELL

Selling SHELL is done through the Acki Nacki Wallet. You choose a lot denomination, confirm — and your SHELL is locked until sold. When a buyer arrives, the lot is sold automatically on a first-come-first-served (FIFO) basis.

{% hint style="warning" %}
**Important:** once a sell order is confirmed, cancellation is not possible.\
Your SHELL will remain locked until sold.
{% endhint %}

## Prerequisites

* [Acki Nacki Wallet app](https://ackinacki.com/wallet) installed
* SHELL in your balance (minimum 100 SHELL for the smallest lot)

## Step-by-Step Guide

{% stepper %}
{% step %}

### Open Exchange

On the wallet's main screen, tap the **Exchange** button.

<figure><img src="/files/Pq0q9CnM7VJ1IbQ6bB1X" alt="" width="167"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

### Select Buy & Sell SHELL

On the Exchange screen you'll see two options. Tap **Buy & Sell SHELL** (Trade SHELL with USDC).

<figure><img src="/files/oOtkNQS0q1aaAQoKNEKR" alt="" width="165"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

### Switch to Sell

On the "Buy & Sell SHELL for USDC" screen, two buttons are displayed at the bottom: **Sell** and **Buy**. Tap **Sell**.

<figure><img src="/files/GWA5ca6Yl8oSDcnzsZOX" alt="" width="166"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

### Choose a Lot Denomination

The **Sell SHELL** panel opens with the prompt "Choose how much USDC you want to receive." Four denominations are available:

|    You Sell   | You Receive |
| :-----------: | :---------: |
|   100 SHELL   |    1 USDC   |
|  1,000 SHELL  |   10 USDC   |
|  10,000 SHELL |   100 USDC  |
| 100,000 SHELL |  1,000 USDC |

Denominations that exceed your SHELL balance are unavailable. Your current SHELL balance is displayed at the bottom of the screen.

Tap the desired denomination. In this example, the **1,000 SHELL → 10 USDC** lot is selected.

<figure><img src="/files/E6oCIaJP4JF3fpqon8ZV" alt="" width="167"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

### Confirm the Sale

A confirmation screen appears:

<figure><img src="/files/13RbtU2AUDvBoWNrQlh8" alt="" width="167"><figcaption></figcaption></figure>

Tap **Confirm** to proceed or **Cancel** to go back.
{% endstep %}

{% step %}

### Order Placed

After confirmation, you'll see a screen with the order details:

* **Sell:** 1,000 SHELL
* **Receive:** 10 USDC
* **Position in queue:** #1

The queue number shows how many lots of this denomination are ahead of you. The lower the number, the sooner your lot will be sold.

Tap **Close** to return.

<figure><img src="/files/Ic2RRPbtlLUfXHWK1XUV" alt="" width="165"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

### Check the Result

After placing the order:

* Your SHELL balance decreased (was 5,000, now 4,000 — 1,000 SHELL is locked)
* The SHELL token screen now shows a **My Orders** section with your lot and its queue position

<figure><img src="/files/83WBb7ACUfCl0Ss0Oh5K" alt="" width="165"><figcaption></figcaption></figure>

Your SHELL balance on the main wallet screen updates automatically.

<figure><img src="/files/AlVzxqg7ebogNNOo5GV7" alt="" width="166"><figcaption></figcaption></figure>
{% endstep %}
{% endstepper %}

## How to Sell a Larger Amount

Each transaction creates one lot of one denomination. To sell more SHELL, simply repeat the process multiple times, choosing the denominations you need.

**Example:** you want to sell 15,400 SHELL (= 154 USDC). Create lots:

1. 1 × 100,000 SHELL (= 1,000 USDC) — if you have enough balance, or skip
2. 1 × 10,000 SHELL (= 100 USDC)
3. 5 × 1,000 SHELL (= 5 × 10 USDC)
4. 4 × 100 SHELL (= 4 × 1 USDC)

Each lot joins its denomination's queue independently and is sold separately.

## Denominations Work Like Banknotes

The system uses four fixed denominations, similar to paper bills. A lot can only be sold in full — partial selling is not possible.

Choosing a denomination is a trade-off:

* **Smaller denominations** (1, 10 USDC) — sell faster, as even small purchases can fill them
* **Larger denominations** (100, 1,000 USDC) — fewer transactions needed, but may take longer to find a buyer

## Transaction History

On the SHELL token screen, the **Transaction history** section shows all operations:

* **Sent to Accumulator** — SHELL locked when the sell order was placed
* **Received from Accumulator** — SHELL received (from a purchase)

<figure><img src="/files/ivNkaLDbEqthOWZV7gcC" alt="" width="167"><figcaption></figcaption></figure>

## What Happens Next

After placing your order, your lot waits in the queue. Learn more about status tracking: [Tracking Your Orders](broken://pages/31c5d607b90a0484f3f75aebbe9f54e770806288). About receiving USDC after the sale: [Receiving USDC (Claim)](broken://pages/4a68c01959125f6dcd554e0a91ed8733b8b21b6f).

## Possible Errors

| Message                               | Cause                                  | Solution                      |
| ------------------------------------- | -------------------------------------- | ----------------------------- |
| Denomination unavailable (grayed out) | Not enough SHELL for this denomination | Choose a smaller denomination |
| Transaction failed. Try again         | Transaction error                      | Try again                     |


# Tracking Your Orders

After placing a sell order for SHELL, you can track the status of each lot in the Acki Nacki Wallet.

## Where to Check Status

Open the SHELL token screen (tap the SHELL row on the main screen). The **My Orders** section displays all your active sell orders.

For each lot, you can see:

* The SHELL and USDC amounts (e.g., 1,000 SHELL → 10 USDC)
* Your position in the queue (e.g., **#1 in queue**)

<figure><img src="/files/83WBb7ACUfCl0Ss0Oh5K" alt="" width="165"><figcaption></figcaption></figure>

## Lot Statuses

Each lot goes through three states:

| Status                     | Description                                                             |
| -------------------------- | ----------------------------------------------------------------------- |
| **In queue** (#N in queue) | Lot is in the queue waiting for a buyer. The number shows your position |
| **Sold**                   | Lot has been sold; USDC is ready for collection                         |
| **Claimed**                | USDC has been received in your balance                                  |

## How Fast Do Lots Sell?

Selling speed depends on buyer activity. Key factors:

* **Denomination:** lots with smaller denominations (1 and 10 USDC) typically sell faster, as even small purchases can fill them
* **Queue position:** the lower the number, the sooner you'll be sold. Position #1 means your lot will be sold first
* **Purchase priority:** the system processes queues from large to small denominations (1000 → 100 → 10 → 1), so large purchases first fill 1000-denomination lots, then 100, and so on

## Transaction History

In the **Transaction history** section on the SHELL token screen, you can see all operations:

* **Sent to Accumulator** — SHELL sent when the sell order was placed (locked)
* **Received from Accumulator** — SHELL received (from a purchase)

Each entry includes the date, time, and amount.

<figure><img src="/files/ivNkaLDbEqthOWZV7gcC" alt="" width="167"><figcaption></figcaption></figure>

## Multiple Lots

If you created multiple lots (different or same denominations), each is shown separately in **My Orders**. Lots are independent — they are sold and paid out separately.

## Empty State

If you have no active sell orders, the **My Orders** section is not displayed.


# Receiving eccUSDC (Claim)

When your lot is sold, ECC USDC becomes available for collection. In the Acki Nacki Wallet, the claim process happens **automatically**.

## How It Works

1. The wallet periodically checks the status of your lots
2. When a lot transitions to **Sold** status, the wallet automatically initiates the eccUSDC claim
3. ECC USDC is credited to your balance
4. The lot transitions to **Claimed** status
5. The lot's receipt contract self-destructs after payout

{% hint style="info" %}
**Automatic claim** works in the background while the wallet is open.\
**You just need to open the SHELL details on the main screen.**
{% endhint %}

## What Happens at the Smart Contract Level

For a deeper understanding, here's how the claim works technically:

1. The wallet sends a `Claim()` command to your lot contract (`ShellSellOrderLot`)
2. The `ShellSellOrderLot` verifies the call comes from the owner
3. \`ShellSellOrderLot\` sends a `ClaimUSDC` request to the main contract (`ShellAccumulatorRootUSDC`)
4. \`ShellAccumulatorRootUSDC\` verifies:
   * The lot has actually been sold (it's within the sold prefix of the queue)
   * The request comes from a genuine lot contract (address verification)
   * There is an outstanding debt to pay
5. \`ShellAccumulatorRootUSDC\` transfers eccUSDC directly to you (the lot owner)
6. The lot contract confirms receipt and self-destructs

## If Claim Happens Too Early

It's possible that the wallet attempts to claim eccUSDC before the lot has actually been sold. In this case:

* The transaction is rejected by the Root contract
* The lot contract automatically resets its status via the `onBounce` mechanism
* The wallet will retry later

This is completely transparent to you and requires no action on your part.

## Lots Receive eccUSDC Independently

Each lot is an independent entity. If you created 8 lots, each one will be sold and paid out separately. You'll start receiving eccUSDC as each individual lot sells, without waiting for all of them to sell.

**Example:** you sold 5,300 SHELL (8 lots). An hour later, 3 lots of 10 eccUSDC each are sold — you receive 30 eccUSDC. The remaining 5 lots continue waiting in their queues.


# Burn NACKL for eccUSDC

Burn NACKL is a mechanism that lets you burn (permanently destroy) your NACKL tokens and receive a share of the free eccUSDC reserve in return. This is a separate process, unrelated to buying or selling SHELL.

{% hint style="warning" %}
**Irreversible operation:** burned NACKL cannot be recovered. Make sure you want to burn the specified amount.
{% endhint %}

## How It Works

When burning NACKL, you receive a portion of the free eccUSDC reserve proportional to your share of the total NACKL in circulation.

**Formula:**

```
Payout = USDC reserve × (Your NACKL / NACKL total supply)
```

There is no fixed price for NACKL. The value of one NACKL is floating and depends on the size of the reserve and the total supply. The more NACKL you hold relative to the total supply, the larger your share of the reserve.

## Prerequisites

* [Acki Nacki Wallet app](https://ackinacki.com/wallet) installed
* NACKL in your balance

## Step-by-Step Guide

{% stepper %}
{% step %}

#### Open the NACKL Details Screen

On the wallet's main screen, tap the **NACKL** row in the token list.

<figure><img src="/files/nHunSLNSMC8JrEt0Uzks" alt="" width="285"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Tap Burn

The NACKL token screen shows your balance, address, and transaction history. Tap the **Burn** button.

<figure><img src="/files/bIoRpdz8F9WfePtyDBWv" alt="" width="285"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Tap Burn my NACKL

The **Burn NACKL to eccUSDC** screen opens tap the **Burn my NACKL** button to proceed to the amount entry screen

<figure><img src="/files/WAoeqsyJzbfL4UxlUtE1" alt="" width="288"><figcaption></figcaption></figure>

You can tap **How it works?** to see an explanation of the mechanism.
{% endstep %}

{% step %}

#### Enter the NACKL Amount

The amount entry screen displays:

* **Select amount** — field to enter the NACKL amount
* **You will receive** — estimated eccUSDC payout, updates in real time (e.g., ≈ 0.000390 USDC)
* **Approximate rate** — current rate (e.g., 1 NACKL ≈ 0.0001300 eccUSDC)
* **How it counts?** — button with calculation details
* **NACKL total supply** — total NACKL in circulation (e.g., 85,546,454)
* **eccUSDC reserve** — size of the free eccUSDC reserve (e.g., 11,122)
* **Your unlocked NACKL** — your available balance with a **Max** button

Enter the amount of NACKL to burn. Tap **Max** to select your entire available balance.

In this example: entering 3 NACKL yields ≈ 0.000390 eccUSDC.

Tap **Burn & Redeem:**

<figure><img src="/files/LVCfqOD7IDJEhBmlwl14" alt="" width="285"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Confirm the Burn

A confirmation screen appears:

Tap **Confirm burn** to proceed or **Cancel** to go back.

<figure><img src="/files/H0HDj3f0O14NHLf6T3sk" alt="" width="288"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Operation Complete

On success, you'll see the **NACKL redeemed** screen.

Tap **Close** to return.

<figure><img src="/files/qYkGKbWrq3pq2atFM2Sl" alt="" width="286"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Check the Result

After burning:

* Your NACKL balance decreased (was 10, now 7)
* The NACKL transaction history shows a **Sent to Accumulator** entry with amount -3

<figure><img src="/files/Tq2LkE8VYxslpEPppCHn" alt="" width="285"><figcaption></figcaption></figure>

Your NACKL balance on the main wallet screen updates automatically.

<figure><img src="/files/2d7uOlYxdgi6U5ripI6X" alt="" width="281"><figcaption></figcaption></figure>

The received eccUSDC can be seen on the eccUSDC token screen in the **Transaction history** section — a **Received from Accumulator** entry with amount +0.00039.

<figure><img src="/files/68rKYht3otXGYQZQORnX" alt="" width="285"><figcaption></figcaption></figure>
{% endstep %}
{% endstepper %}

## What Is the Free Reserve?

The free reserve is the eccUSDC held in the contract that is not reserved for SHELL sellers. It is formed as follows: when a buyer purchases SHELL but there aren't enough sellers in the queues, the system creates (mints) new SHELL. The eccUSDC paid for minted SHELL forms the free reserve. Seller funds are never touched.

## When Is Redeem Unavailable?

Redeem is not possible when the free reserve is zero. This means all eccUSDC in the contract is reserved for SHELL sellers. The reserve grows as SHELL is purchased and there aren't enough sellers in the queues.

## Possible Errors

| Message                             | Cause                  | Solution                     |
| ----------------------------------- | ---------------------- | ---------------------------- |
| Burn & Redeem button inactive       | Field is empty or zero | Enter the NACKL amount       |
| Insufficient NACKL balance          | Not enough NACKL       | Reduce the amount            |
| No eccUSDC available for redemption | Free reserve is 0      | Wait for the reserve to grow |
| Transaction failed                  | Transaction error      | Try again                    |


# Acki Nacki News

This update brings together the main Acki Nacki  progress from the week

## Update - 21.08.26

### **DEX.DO**

* **`dexdo-cli` is undergoing a major UX update.** The team is implementing **three ways to link your wallet**:

  * local multisig for deep technical CLI integrations,
  * **Acki Nacki Wallet** application for Wallet users and **Points and Rewards Program** participants
  * **gosh.ai** platform for the people outside the comminity.

  Overall CLI UX will also be significantly improved in the next release.
* [**dexdo-cli v0.0.23**](https://github.com/gosh-sh/dexdo-cli/releases/tag/v0.0.23) has been released with the 1st part of UX improvements:
  * The onboarding QR code now renders as a real image in `kitty`, `iTerm2`, and `sixel`-capable terminals.
  * Fewer required flags — `--pool`, `--contracts`, and the multisig pair are no longer mandatory, making the CLI easier to use.
  * The CLI now runs from any directory: the contracts manifest ships inside the binary.
  * `note balance` now shows whether a note is busy.
  * Buyers see the probe-tick cost before paying.
  * Windows: the seller no longer crashes silently.
* Support for **Acki Nacki Mainnet** on [markets.dex.do](https://markets.dex.do) is in active development and will be available shortly.

### **Node & SDK**

* The rollout of [**v0.19.0**](https://github.com/ackinacki/ackinacki/releases/tag/v0.19.0) to the network is in progress. The release introduces a **DApp execution scheduler**, so that mining no longer affects neighbouring DApps. This will reduce the number of `queue is full` errors for all applications outside DApp 1, but does not address indexer overload.
* The **Block Manager API** now parses `src_dapp_id` (source DApp ID) for type 4 events — a new event type supported starting from [TVM Solidity Compiler v0.81.0](https://github.com/gosh-sh/TVM-Solidity-Compiler/releases/tag/gosh_0.81.0), already available in both Shellnet and Mainnet. Dapp developers can now query precisely their DApp's events which dramatically reduces the data processing on the DApp side.

### **gosh.ai**

The **gosh.ai subscription and sub-account creation service** for funding payments on DEX.DO is in active development and will be available in integration with dexdo-cli shortly.

## Update - 14.08.26

### DEX.DO

**DEX.DO is now live on Mainnet**, **with full public access coming alongside the next public dexdo-cli release.**

This week, **DEX.DO CLI** development focused on Mainnet readiness, introducing new wallet onboarding and automated funding flows, network selection and deployment support, operator tooling, and improved model and deal diagnostics. Multiple fixes also improved buyer and seller recovery, settlement and refunds, gas handling, wallet safety, gateway reliability, and overall CLI stability.

### **Bridge**

Both **deposit and withdrawal circuits** have successfully passed their final audits. The complete deposit flow and supporting infrastructure are now undergoing audit.

### Node & SDK

* Performance testing of the multithreaded node implementation has been completed, with the results meeting our expectations at this stage. **MessageDB** has moved to the load testing stage. Several fixes have also been made to the node synchronization mechanism in a multithreaded environment, while work continues on an external message queue scheduler to ensure fair processing of external messages.
* **TVM-SDK v3.0.5.an** <https://github.com/tvmlabs/tvm-sdk/releases/tag/v3.0.5.an> has been released. The update makes the execution fee constant for executions that fail due to an execution timeout, improving fee predictability in timeout scenarios.

### Popit Music

Popit Music An update is coming in the next few days, fixing the 7:59 track length issue and the related sound quality drop toward the end of tracks, while also improving the sound of TECHNO and ACID genres. COMPOSER has also been improved with a fix for the LENGTH 16 display and new contextual hints explaining NOTE / VEL / AUTO modes.

### **Documentation**

A new guide on [**exchanging eccUSDC for SHELL via the Accumulator**](https://docs.ackinacki.com/for-users/buy-sell-shell/buying-shell/exchange-eccusdc-for-shell-via-accumulator) has been published in the Acki Nacki documentation.

## Update - 07.08.26

### DEX.DO

🚀 **DEX.DO Season 2 launches on Mainnet next week!**\
Stay tuned for the official announcement.

* A new **`dexdo-cli`** release is coming with support for the latest contract updates. Key improvements will include:
  * **deadline** support for both BUY and SELL orders;
  * improved access to AI models for users connecting via VPN;
  * **AON|FOK** is now the default execution mode for immediate BUY orders;
  * the new `--wait-for-seller` option, allowing buyers to place orders even when no seller is currently available.
* The release also will include numerous fixes and improvements across buyer and seller workflows, further enhancing the reliability, stability, and overall trading experience in DEX.DO.

### **Bridge**

* The Deposit Circuit has successfully passed verification and is now undergoing its final audit.
* **History data proofs** are now being successfully submitted to the **Sepolia** contract, keeping it synchronized with the latest **Acki Nacki** block history and completing a key step toward withdrawal support.

### Node

Active performance testing of the multithreaded node implementation is underway to optimize scalability and throughput, while development of the new **MessageDB** storage layer continues.

## Update - 31.07.26

### DEX.DO

🎉 `Shellnet` **Points & Rewards Season 1 has officially concluded!**

A huge thank you to everyone who participated and helped shape the future of **Acki Nacki**. ❤️

We apologize for the reward calculation issue that occurred on the final day of the season. The historical data has been successfully reprocessed, and all rewards for the last 24 hours have now been restored and credited.

We're working on a new feature that will allow buyers and sellers to fund their Private Notes directly from their Acki Nacki Wallet, making it even easier to manage your trading funds on DEX.DO.

🚀 Stay tuned for the announcement of **DEX.DO Season 2 on Mainnet**!

* **DEX.DO CLI** has been updated through **v0.0.16–v0.0.19**, adding support for the latest `Shellnet` contracts (v4.0.31) and the new multisig wallet (v2.2.0), while improving transaction safety, recovery mechanisms, diagnostics, security, and the overall reliability of DEX.DO trading workflows. DEX.DO CLI v0.0.20 is expected to be released soon.

### SDK

* **Bee Engine** now supports the new `UpdateCustodianMultisigWallet_v2` multisig wallet, ensuring compatibility with the latest wallet infrastructure across the Acki Nacki ecosystem.

## Update - 24.07.26

### DEX.DO

* The new version of [**dexdo-cli**](https://github.com/gosh-sh/dexdo-cli/releases/tag/v0.0.15) is now available, bringing a range of fixes and improvements for greater reliability and a smoother user experience. The update resolves issues with model-only orders, Private Note deployment, buyer and seller workflows, Anthropic API support, clock-skew validation, error reporting, and fund provisioning, while also strengthening recovery mechanisms and improving Hermez SRS validation.
* `Shellnet` has been fully prepared for the upcoming contract upgrade. All testers must **close all active deals and withdraw their rewards from Private Notes to their wallet in app.dex.do before 16:00 CET on July 25** to ensure no funds are left on the old contracts.

### Node & SDK

The network upgrade to [**v0.18.1**](https://github.com/ackinacki/ackinacki/releases/tag/v0.18.1) has begun. The release improves node finalization time, performance and stability.

### Bridge

Another audit cycle has been completed. Several issues were identified during the review, and the team is actively working to address them before the Bridge Public Beta release.

### Popit Music

A major [Popit Music](https://popit.music/?utm_source=socials\&utm_medium=annoncments\&utm_campaign=tvmupdate_2026_07_24\&utm_content=tvmupdate) update is live just in time for the weekend!

* The song creation engine has been upgraded to a new version, with more generation controls and a more stable creation flow.
* We’ve also introduced a new entry point: the Sequencer.
* A large number of bugs and service issues have been fixed.
* You can now sort your created tracks, completely hide them from the list, regenerate covers for tracks and playlists, generate images for artists and Popcoins, and download them.

## Update - 17.07.26

### DEX.DO

* **DEX.DO Bug Bounty program is in development. Stay tuned!**
* [**DEX.DO CLI** ](https://github.com/gosh-sh/dexdo-cli)**has been updated to v0.0.12.**

  The release fixes a critical security issue affecting withdrawals from previous-generation Private Notes, restores compatibility with the updated Shellnet and the new `Halo2/Hermez KZG prover`, and improves order management by ensuring that scanning no longer stops when it encounters already executed orders.

  All changes have been successfully validated through a complete end-to-end DEX workflow.
* The migration to the **Hermez trusted setup–based KZG** has been completed. **This significantly simplifies `halo2-prover` setup and reduces initialization time of private note deployment.** All components are now running on the final secure configuration, providing the foundation for future development and releases.

### Node & SDK

* The rollout of **network upgrade v0.18.0** has started. <https://github.com/ackinacki/ackinacki/releases/tag/v0.18.0>\
  **This release unlocks the technical possibility to release DEX.DO in Mainnet.**

  It introduces major enhancements, including the integration of a fully on-chain DEX and the AI Inference Market, the completion of the USDC Bridge with Halo2 proof verification, a new History Proof system and Poseidon Merkle Tree-based block identifiers, required for ZK Bridge, significant node performance and reliability improvements, as well as updated TVM-SDK and infrastructure for the ZK bridge.
* TVM-SDK v3.0.4.an has been released: <https://github.com/tvmlabs/tvm-sdk/releases/tag/v3.0.4.an>. The SDK now supports verification of `Halo2/KZG zero-knowledge proofs` through the new TVM instructions `ZKHALO2VERIFY` and `ZKHALO2VERIFYWITHVK`, extending the existing support for Groth16 and Poseidon. The release also introduces the `CHKHISTPROOF` instruction for verifying Merkle proofs of block history in TVM.
* TVM Solidity Compiler v0.81.0 has been released: <https://github.com/gosh-sh/TVM-Solidity-Compiler/releases/tag/gosh_0.81.0>

  `dapp_id` field is added to the contract events, allowing DApp developers to query only their DApp's events for indexing.

### Bridge

Bridge TVM instructions are being rolled out to the network in v0.18.0 release. These may be not the final version of them, as the audit is still ongoing. With this v0.18.0 Network Update we are getting very close to the ZK Bridge release.

## Update - 10.07.26

### DEX.DO

* **Released** [**DEX.DO CLI** ](https://github.com/gosh-sh/dexdo-cli)- the official command-line interface for DEX.DO, making it easier to automate trading workflows, test the API, and integrate DEX.DO with AI agents.\
  **Community feedback is welcome** — report issues at <https://github.com/gosh-sh/dexdo-cli/issues> and **support the project by starring the repository**.
* The Season 1 Points & Rewards program continues on Shellnet, with ongoing testing and refinement.
* Secondary markets (predictions on AI events and model prices) are coming to the Points & Rewards program soon.
* Published the DEX.DO Points & Rewards [FAQ](https://t.me/c/3819653418/428/910).
* Started work on a Bug Bounty program for DEX.DO — rewards for finding and reporting bugs, so we harden the protocol together. More soon.
* Continued preparations for bringing DEX.DO to Mainnet.

### Bridge

The bridge integration layer is now being implemented, including the relayer and the components responsible for end-to-end proof generation and delivery.

### Node & SDK

Continued preparations for the next releases required for DEX.DO. The upcoming SDK introduces Halo2 proof verification instructions (`ZKHALO2VERIFY`, `ZKHALO2VERIFYWITHVK`) and a new instruction for block history Merkle proof verification (`CHKHISTPROOF`).

## Update - 03.07.26

### DEX.DO

The DEX.DO Points & Rewards program has officially launched.

DEX: <https://dex.do/>

Incentive Program: <https://seasons.dex.do/>

### Bridge

The final version of the node supporting deposits from EVM to Acki Nacki has been deployed to Shellnet. On the Pruvendo side, the end-to-end deposit flow from EVM to Shellnet has been successfully validated. This component is now entering the final audit phase. On the withdrawal side, the audit of the single-threaded circuit implementation is still in progress.

### Node & SDK

The Poseidon instruction has been added. It is required for the Bridge and will be included in the next mainnet release.

## Update - 26.06.26

### DEX.DO

* **The** [**Points and Rewards program terms have been published**](https://seasons.dex.do/)**. The program launch is coming — stay tuned for updates!**
* [**https://app.dex.do/**](https://app.dex.do/) **dashboard and leaderboards for Points and Rewards program participants is released.**
* Debugging of the AI Token Market client is in progress. AI Token exchange contracts are ready.
* The skills library has been expanded with a new set of DEX.DO automation and trading skills, covering Multisig setup, deposits, account registration, market data, trading, and withdrawals. Learn more: <https://github.com/gosh-sh/dexdo/tree/dev/.claude/skills>

### Node & Network & SDK

* Node testing with blockchain multithreading continues. Synchronization stability has been improved, and Poseidon integration is in progress (instruction required for Bridge).
* Published [Bee SDK](https://www.npmjs.com/package/@teamgosh/bee-sdk) on npm (`@teamgosh/bee-sdk`)

### Bridge

* The StateV2 release with multithreading is getting closer, so the team has moved to the stage of supporting multithreading in the bridge circuits.
* Pruvendo brought in additional resources to audit the EVM side of the bridge. The issues found have already been fixed, and the final version of the chain for depositing USDC into Acki Nacki will be deployed during the next Shellnet restart.

### Documentation

* Published a new user guide: [What to Do If Your Authentication Factor Has Expired](https://docs.ackinacki.com/for-users/wallets/troubleshooting/what-to-do-if-your-authentication-factor-has-expired), with step-by-step instructions for updating an expired authentication factor.

## Update - 19.06.26

### DEX.DO

* **The Points and Rewards program terms have been finalized, and the new landing page is ready for publication. Stay tuned for announcements!**
* The backend for calculating program points, the participant account, and leaderboard are in development.
* A smart contract system with a primary market for model tokens is being developed in parallel. The program launch will not be blocked by primary market support for model tokens.
* Added an AI skill for deploying the Multisig, as well as deploying and topping up Private Notes on Shellnet: [dexdo-onboarding-shellnet](https://github.com/gosh-sh/dexdo/blob/dev/.claude/skills/dexdo-onboarding-shellnet/SKILL.md).

### Ecosystem

* The PR to add Acki Nacki to the SLIP-0044 registry has been accepted. The project has been assigned number `1331`, creating the foundation for further integration with wallets and blockchain infrastructure services.

### Node & Network & SDK

* The network has been upgraded to `v0.16.3` with support for the new addressing scheme.
* A new `bee-engine` has been published. The release includes `bee-connect` and `bee-wallet` for the first time. Usage examples are available in the [miner-react example](https://github.com/gosh-sh/bee-engine/tree/main/examples/javascript/miner-react).

### Bridge

* The latest bridge updates have been rolled out to Shellnet. Infrastructure preparation has started for calculating heavy proofs of key blocks on the EVM side. Since Mainnet BK set updates may happen as often as once every 5 minutes, proof calculation will be parallelized. This will allow the heavy part of the proof to move faster, leaving the user only to complete the lightweight event proof.

### Popit Music

* Popit Music has been updated: generation token logic has been fully migrated to GoshAI Agent Tokens, Agent Tokens can now be purchased with fiat, localization has been added for popular languages, and the track creation flow has been improved. It is now more stable and produces results closer to the user's prompt. Try the update here: [Popit Music](https://popit.music/?utm_source=community\&utm_medium=social\&utm_campaign=update_2026_06_19\&utm_content=community_update).

### Documentation

Added page: [**Connecting an Acki Nacki Wallet and Setting Up Mining Keys**](https://docs.ackinacki.com/for-users/wallets/connecting-an-acki-nacki-wallet-and-setting-up-mining-keys)

## Update - 12.06.26

### DEX.DO

* **While preparing the Points & Rewards program, we made an important product decision: DEX.DO will expand beyond prediction markets into a decentralized trading layer for AI model access. We are updating the program structure to reflect this broader product direction and reward meaningful participation across DEX.DO. More details will follow.**
* Added a public Trades API that does not require authorization, allowing retrieval of the latest market price and recent trade history.

### Node & Network & SDK

* Testing of the `v0.16.3` release with the new addressing scheme has been completed. Network upgrade announcements will be published separately.
* `bee-engine` and `ackinacki-kit` now support `SDK 3.0.0`.

### Bridge

* Published the repository for generating proofs for withdrawals from Acki Nacki: <https://github.com/gosh-sh/acki-nacki-to-eth-bridge-halo2-prover>
* Local end-to-end tests of withdrawals from Acki Nacki to EVM were successfully completed on a local network without BK set updates.
* The BK Set Update circuit has completed the first audit cycle by Pruvendo. The circuit is currently being covered with additional tests.
* The next step is to determine the optimal circuit parameters to ensure acceptable withdrawal timings to EVM.

### Apps

* Wallet have been migrated to SDK 3.0 and sent to App Store and Play Market for review.
* Popits and Batteries have been migrated to SDK 3.0. Migration of Popit Music and Ludo is planned for next week.

## Update - 05.06.26

### DEX.DO

* **The terms for the Points & Rewards incentive program are being prepared to help attract testers and participants to DEX.DO. The program terms will be published soon.**
* **Launched the public Oracle API** — a new endpoint for accessing oracle information and available events for market creation.
* An open-source release of the DEX.DO stack - including halo2 libraries, the indexer, API, and exchange integration libraries: [dexdo](https://github.com/gosh-sh/dexdo), [dexdo-halo2-kit](https://github.com/gosh-sh/dexdo-halo2-kit), [DEX.DO documentation](https://gosh-sh.github.io/dexdo/).
* A new giver has been published in Shellnet with support for parallel top-ups to speed up testing.

### Block Manager Licenses

Sales of [Block Manager Licenses](https://bm.gosh.sh/) have started. These licenses are intended for independent operators of Acki Nacki network access infrastructure.

### Popits

[Popits 3.0](https://popit.music/home) has launched together with a new Boosts season. Popits has evolved into an AI ecosystem for creating, distributing, and monetizing music: users can generate original tracks with AI, publish and mint them, and participate in community-driven contests and reward programs.

The new season includes NACKL mining mechanics linked to music listening and platform activity. At launch, more than 1,000 AI-generated tracks created by the community during closed testing were available. Popits is also available through the [Telegram bot](https://t.me/PopitMusic_Bot).

### Node & Network & SDK

* [TVM SDK 3.0.0](https://github.com/tvmlabs/tvm-sdk/releases/tag/v3.0.0.an) has been released, and the new addressing scheme has been rolled out to Shellnet. Shellnet is now compatible only with SDK 3.0.0, so application developers should migrate to this version now. The [migration guide is here](https://github.com/tvmlabs/tvm-sdk/blob/main/docs/MIGRATION-3.0.md).
* `bee-engine` and `ackinacki-kit` do not support SDK 3.0.0 yet. A release with 3.0.0 support will follow soon; stay tuned for announcements.
* The Mainnet release of the new addressing scheme is still being tested.

### Network Status

A public [Acki Nacki network status](https://grafana.ackinacki.org/) page has been launched.

### Bridge

* A repository for generating proofs for withdrawals from Acki Nacki has been prepared. It will be published soon.
* Deposit testing from a test EVM network to Acki Nacki Shellnet has been completed; a guide will be published soon. The latest version of the bridge contract with deposit support has been deployed to Shellnet.
* Work on the circuit for BK set updates has resumed.

### Wallet

AN Wallet is currently not compatible with Shellnet: to speed up development and testing, the final API version with the new addressing scheme was rolled out there first. An AN Wallet release with Shellnet support is expected in the coming days.

## Update - 29.05.26

### Node & Network & SDK

TVM-SDK 3.0.0 with new addressing scheme is coming. All the applications MUST migrate to it before StateV2 release.

### Bridge

End-to-end positive deposit/withdraw scenarios testing is ongoing. The audit excludes BK set update proof verification, as Shellnet currently does not perform BK set updates. User documentation for transfers from the test EVM network to Shellnet is also in preparation. Stay tuned for upcoming announcements!

### DEX.DO

* Added account balance APIs covering both collateral and per-market outcome tokens.
* Exposed maker and taker commission rates on the markets endpoint.
* Published the OpenAPI specification.
* Released POST `/api/v1/buyFullSet` for buying a full set of outcome tokens with collateral;\
  the matching sellFullSet and claim endpoints are specified and will follow.

An open-source release of the DEX.DO stack - including halo2 libraries, the indexer, API, and exchange integration libraries - is coming. Stay tuned. 🚀

### Documentation

A new [Synchronization and Consensus Mechanism](https://docs.ackinacki.com/synchronization-and-consensus-mechanism) section was added. It explains how Acki Nacki reaches consensus on block order and validation, including finalization and error handling.

### Support

Support requests were simplified and now go through a single bot: [@ackinackisupport\_bot](https://t.me/ackinackisupport_bot). A questionnaire and screenshot upload option were added. Bot links are available in all official chats, and requests are reviewed daily.

We established a new automated process of collecting feedback from the community across all chat channels for further discussion and follow-up with the core team.

## Update - 22.05.26

### Node & Network

After the Durable State release, the network team identified a bug in external message processing. Patch releases [`v0.16.1`](https://github.com/ackinacki/ackinacki/releases/tag/v0.16.1) and [`v0.16.2`](https://github.com/ackinacki/ackinacki/releases/tag/v0.16.2) were prepared and have already been rolled out to the network.

Work on State V2 is currently in progress.

{% hint style="danger" %}
**Attention!!!!!**

Account addressing in State V2 will use the DApp ID + address format. At the moment, all applications are still using the old addressing scheme.

We are planning to prepare a migration guide for applications to support the transition.

The SDK with new account addressing support is already available (latest version: [v2.24.21](https://github.com/tvmlabs/tvm-sdk/releases/tag/v2.24.21.an))
{% endhint %}

### API Access

Degraded public API performance over the last 1.5 week was caused by increased miner bot activity. These bots abused public infrastructure from a set of IP addresses.

To prevent this load from affecting other network users, the rate limit policy for public endpoints was tightened. API request optimizations were also made to improve response speed.

Miner applications may acquire a Block Manager license to avoid these limits. There will be an additional post on this topic the next week.

<mark style="color:$success;">**The internal network economy is evolving, and that is great to see!**</mark>

### Bridge

Changes made to the TokenBridge event circuit based on the results of the Pruvendo audit.

Decision was made to replace `vergrth16WithVK` instruction with `ZKHALO2VERIFYWITHVK` - this will simplify the integration a lot.

### DODEX

Dodex development focused on the Market Maker API and Shellnet testing tools. Added Cancel Order API, all orders API (including cancelled, rejected and fulfilled orders), and batched API support. Prepared the first version of scripts for producing artificial load for end-to-end API testing on Shellnet.

Maker and Taker commission supported in DODEX core smart contracts.

### Wallet

A wallet release with support for the new DAPP ID + Account ID addressing format is planned in the near future. Please follow upcoming announcements.\
After the State V2 release, the old addressing format will no longer be supported.\
We will keep you updated.

### Documentation & Developer Experience

A separate documentation page was added for receiving test tokens on Shellnet: [Get test tokens from giver in Shellnet](https://dev.ackinacki.com/readme/get-test-tokens-from-giver-in-shellnet).

## Update - 15.05.26

### Node & Network

* Durable State was released in [`v0.16.0`](https://github.com/ackinacki/ackinacki/releases/tag/v0.16.0). Network providers are coordinating the update to keep the transition aligned across the network.

### Bridge

On the bridge side, we continue building the infrastructure for ZKP-proof verification and safe asset movement between EVM and Acki Nacki.

* The SDK now includes the `vergrth16WithVK` instruction for proving an EVM-to-Acki Nacki transfer proof on the Acki Nacki side. The instruction is not included in a public release yet. The next step in this direction is integrating `vergrth16WithVK` instruction into the Acki Nacki bridge and testing the full deposit to Acki Nacki scenario.
* The `Exchange` contract was renamed to `TokenBridge` and withdrawal bridge interface was added to `TokenBridge`: it will allow initiating USDC withdrawals to the EVM network with event generation for a later ZKP-proof on the EVM side. The withdrawal bridge interface is currently under audit by the Pruvendo team. These changes are in Shellnet only, not in Mainnet.
* The circuit for layer hash movement, which proves that a block belongs to network history, was tested in an EVM test network. Based on the test results, the node-side logic for storing hash movement data needs additional refinement.

{% hint style="info" %}
There are no `Mainnet` changes yet: integration testing is running on `Shellnet`
{% endhint %}

### DODEX

For Dodex, we are continuing to develop the API and contract layer

* The orderbook API is complete.
* The first synchronous version of the API for order creation and cancellation has been prepared. But, based on market maker scenarios, we decided to move the order creation and cancellation API to an asynchronous model to make placing large numbers of orders easier. This is a WIP.
* The API for fetching a market maker's open orders is in progress.
* Contract fixes were made based on new test results.

### Wallet

In wallet, we continue improving the user experience and adding developer tools.

* In the coming release `Dev setting` page is added
* When developer mode is enabled,
  * the Multifactor contract address, its `DAPP ID`, and the network switcher become visible.
  * users can see an option to send SHELL to a precomputed contract address for a future deployment; this option is hidden in the regular mode.
* The release is already available as an APK. App Store publication is coming, and Google Play publication will be later.
* Transaction history and SHELL sell order history display were fixed: the data no longer disappears in the scenarios reported by a user.
* Fixed an Android login issue for test wallets on `Shellnet`.

### Popits

We are preparing Popits 3.0 for the new boosts season.

In the new season, users will be able to create AI tracks as Popits and receive boosts for them.

We are also preparing a NACKL mining scenario while listening to tracks from the bucket feed or minted Popcoins.

### Documentation & Developer Experience

* A new developer documentation section on cryptography, mnemonic phrases, and keys was added: [Mnemonics and Keys](https://dev.ackinacki.com/cryptography/mnemonics-and-keys).
* A prominent [SHELL purchase](https://docs.ackinacki.com/for-users/buy-sell-shell) button was added to the [developer portal documentation](https://dev.ackinacki.com/) so users can find the token purchase flow more easily

Thanks to everyone who asks questions, reports issues, and helps make Acki Nacki clearer and more convenient for the community.

## Update - 08.05.26

This week, the team made progress across several Acki Nacki workstreams: ecosystem integrations, DEX infrastructure, Bridge, SDK, and documentation.

### Ecosystem

A PR has been opened to register Acki Nacki in the SLIP-0044 registry under number `1331`. This is an important step toward deeper integration with wallet infrastructure and ecosystem tools.\
Support our PR :rocket: [satoshilabs/slips#2016](https://github.com/satoshilabs/slips/pull/2016)

### State

Durable state (3/4) is in the final testing phase.

### Bridge

This week, the Bridge team focused on reliable verification of Acki Nacki data from the EVM infrastructure side.

* The circuit for proving attestations in Acki Nacki block on the EVM network side has been successfully tested in an EVM testnet.
* Integration and testing are underway for the circuit that proves Layer Hashes movement. This mechanism confirms that a block belongs to the Acki Nacki network history.

### Dodex

Dodex continues to expand the infrastructure needed by market makers and applications to work with the DEX effectively.

#### Completed

* Finalized the DEX API specification for market makers and web applications.
* Prepared a library for writing to the Orderbook, including order creation and cancellation.
* Implemented an API for retrieving the list of Prediction Markets.

#### In progress

* Orderbook read API
* Orderbook write API for market makers.

### Documentation

In parallel, we continue improving the documentation so users, developers, and partners can better understand the ecosystem and complete key flows faster.

* Published a detailed overview of the network architecture and participant roles:\
  [Network Architecture and Participants](https://docs.ackinacki.com/network-architecture-and-participants).
* Updated the documentation for buying SHELL tokens to reflect the simplified user flow in [shellbuy.ackinax.com](https://shellbuy.ackinax.com):\
  [Purchase with crypto or card](https://docs.ackinacki.com/for-users/buy-sell-shell/buying-shell/purchase-with-crypto-or-card-credit-debit).
* Clarified the steps for obtaining `app_dapp_id` in the Bee Engine SDK integration documentation:\
  [Bee Engine SDK Integration Documentation](https://dev.ackinacki.com/bee-engine/bee-engine-sdk-integration-documentation).

Thank you to everyone following Acki Nacki's progress, supporting the team's initiatives, and helping move the ecosystem forward.


