# Welcome!

The Vexanium Blockchain is the next-generation, open-source Public Blockchain with industry-leading transaction speed and a flexible utility.

The Vexanium blockchain is designed for enterprise-grade use cases and is customizable to fit a wide range of businesses needs.

Developing blockchain-based applications on Vexanium is similar to developing non-blockchain applications using common programming languages and development patterns. Developers who are familiar with the development environment have a better user experience as it allows them to use their preferred tools.

The Vexanium blockchain provides functionalities such as accounts, authentication, databases, and the scheduling of applications across multiple CPU cores and clusters. These features are also seen in other software development environments.

## About Blockchain

A blockchain is a decentralized system that helps to create trustless networks. Blockchains are systems that use cryptography to keep data secure and tamper-proof. They're also decentralized, meaning they're not controlled by any one person or organization, and they can't be altered or deleted. Lastly, blockchains are immutable, meaning once a block of data has been added to the blockchain, it can't be changed.

The transactions on the blockchain are permanent and unalterable. The blockchain makes the history of transactions and changes transparent.

## Want to jump right in?

{% content-ref url="/pages/oR4VANQ5hs6zuVqFW2rW" %}
[Overview](/overview)
{% endcontent-ref %}

## Want to deep dive?

Dive a little deeper and start exploring our API reference to get an idea of everything that's possible with the API:

{% content-ref url="/pages/4PdpHjjVBvdxKnVOyb0D" %}
[API Reference](/reference/api-reference)
{% endcontent-ref %}


# Overview

Vexanium is an open-source blockchain platform that offers exceptional transaction speed and versatility. Its enterprise-grade design caters to both public and private blockchain deployment.

The platform offers several functionalities, including accounts, authentication, databases, asynchronous communication, and the scheduling of applications across multiple CPU cores and clusters. These functionalities are typical in non-blockchain software development environments.

Learn about Vexanium's available tools, the core concepts and underlying technical features:

* [Framework and Toolchain](/overview/vexanium-toolchain)
* [Core Concepts](/overview/core-concepts)
* [Technical Features](/overview/technical-features)


# Vexanium Toolchain

Vexanium platform provides a number of components and libraries which are used to operate blockchain nodes, collect blockchain data, to interact with these nodes, and to build smart contracts.

The VEXANIUM blockchain is made up of the following components and toolchain.

1. `nodeos`: the core VEXANIUM (VexChain) node daemon that can be configured with plugins to run a node. Example uses are block production, dedicated API endpoints, and local development.
2. `cleos` or `clivex`: (CLI + VEX = `clivex`), the command line interface to interact with the blockchain and to manage wallets.
3. `keosd`: the component that securely stores VEX keys in wallets.
4. `VEX.CDT`: the Contract Development Toolkit is a C/C++ toolchain targeting WebAssembly (WASM) and a set of tools to facilitate development of smart contracts written in C/C++ that are meant to be deployed to the VEXANIUM blockchain.

The basic relationship between these components is illustrated in the following diagram.

<figure><img src="/files/4ZHLj9q2JwDUftHZX017" alt=""><figcaption><p>VEXANIUM Development Lifecycle</p></figcaption></figure>

{% hint style="info" %}

#### Note

VEXANIUM also provides a library for javascript development called `vexaniumjs` together with Swift and Java SDK for developing mobile applications natively.
{% endhint %}

### **Node OS** <a href="#nodeos" id="nodeos"></a>

`nodeos` is the core VEXANIUM node daemon. Nodeos handles the blockchain data persistence layer, peer-to-peer networking, and contract code scheduling. For development environments, `nodeos` enables you to set up a single node blockchain network. `nodeos` offers a wide range of features through plugins which can be enabled or disabled at start time via the command line parameters or configuration files.

You can read detailed documentation about `nodeos` at here.

### **Cleos/Clivex**

`cleos` or `clivex` is a command line tool that interfaces with the REST APIs exposed by `nodeos`. You can also use one of them to deploy and test Vexanium smart contracts.

You can read detailed documentation about `cleos` at [here](broken://spaces/CZNVNWNLqWkyBEBOg8PH).

### **Keosd**

`keosd` is a key manager daemon for storing private keys and signing digital messages. `keosd` provides a secure key storage medium for keys to be encrypted in the associated wallet file. The `keosd` daemon also defines a secure enclave for signing transaction created by `cleos` or a third party library.

{% hint style="info" %}

#### **NOTE**

`keosd` can be accessed using the wallet API, but it is important to note that the intended usage is for local light client applications. `keosd` is not for cross network access by web applications trying to access user's wallets.
{% endhint %}

You can read detailed documentation about `keosd` at here.

### **VEX.CDT**

VEX.CDT is a toolchain for WebAssembly (Wasm) and a set of tools to facilitate contract writing for the Vexanium blockchain. In addition to being a general-purpose WebAssembly toolchain, VEX-specific optimizations are available to support building VEXANIUM smart contracts. This new toolchain is built around Clang 7, which means that VEX.CDT has most of the current optimizations and analyses from LLVM.

You can read more about `VEX.CDT` at here.

### **VEXANIUMJS**

A Javascript API SDK for integration with the VEXANIUM blockchain using the VEXANIUM RPC API.

#### **What's Next?**

Core Concepts: Learn about VEXANIUM's core concepts.


# Core Concepts

Accounts, Wallets ,Permissions and Smart contracts

## Accounts, Wallets , and Permissions <a href="#accounts-wallets-and-permissions" id="accounts-wallets-and-permissions"></a>

### **Accounts**&#x20;

An account is a human-readable name that is stored on the blockchain. It can be owned through authorization by an individual or group of individuals depending on permissions configuration. An account is required to transfer or push any valid transaction to the blockchain.

### **Wallets**

Wallets are clients that store keys that may or may not be associated with the permissions of one or more accounts. Ideally, a wallet has a locked (encrypted) and unlocked (decrypted) state that is protected by a high entropy password.&#x20;

### **Permissions**

Permissions are arbitrary names used to define the requirements for a transaction sent on behalf of that permission. Permissions can be assigned for authority over specific contract actions by *linking authorization* or linkauth.

## **Smart Contracts**

A smart contract is a piece of code that can execute on a blockchain and keep the state of contract execution as a part of the immutable history of that blockchain instance. Therefore, developers can rely on that blockchain as a trusted computation environment in which inputs, execution, and the results of a smart contract are independent and free of external influence.

{% hint style="info" %}

#### **NOTE**

The VEXANIUM blockchain use C++ and Solidity (in VEXEVM version).
{% endhint %}

## **DPOS Consensus**

The VEXANIUM blockchain implements a proven decentralized consensus algorithm capable of meeting the performance requirements of applications on the blockchain called the *Delegated Proof of Stake* (DPOS). Under this algorithm, if you hold tokens on the VEXANIUM blockchain, you can select block producers through a continuous approval voting system. Anyone can choose to participate in the block production and will be given an opportunity to produce blocks, provided they can persuade token holders to vote for them.

For more information about DPOS BFT, see VEXANIUM Consensus.

## System Resources

### **RAM**

RAM, in the VEXANIUM blockchain, is one of the important system resources consumed by blockchain accounts and smart contracts. RAM acts as a permanent storage and is used to store account names, permissions, token balance and other data for speedy on-chain data access. RAM needs to be purchased and is not based on staking as it is a limited persistent resource.

More details about RAM as a system resource can be found here.

### **CPU**

CPU, in the VEXANIUM blockchain, represents the processing time of an action and is measured in microseconds (μs). CPU is referred to as cpu bandwidth in the `cleos get account` command output and indicates the amount of processing time an account has at its disposal when pushing actions to a contract. CPU is a transient system resource and falls under the staking mechanism of the VEXANIUM blockchain.

More details about CPU as a system resource can be found here.

### **Network (NET)**

Besides CPU and RAM, NET is also a very important resource on the VEXANIUM blockchain. NET is the network bandwidth, measured in bytes, of transactions and is referred to as net bandwidth on the `cleos get account` command. NET is a also a transient system resource and falls under the staking mechanism of the VEXANIUM blockchain.

More details about NET as a system resource can be found here.

#### **What's Next?**

Technical Features: Learn about VEXANIUM technical features

###


# Technical Features

## WebAssembly C++ Compilation <a href="#webassembly-c-compilation" id="webassembly-c-compilation"></a>

VEXANIUM uses C++ as the smart contract programming language. If you are a C++ developer, you do not need to learn a new programming language to understand Smart Contract APIs and how VEXANIUM supports smart contract development through C++ classes and structures. With your existing C++ programming capabilities, you can onboard Vexanium development faster and be able to program Vexanium smart contracts using specific Vexanium canonical C++ code constructs and Smart Contract APIs in no time.

On top of the Vexanium core layer, a WebAssembly (Wasm) virtual machine, `VEXVM`, executes smart contract code, and it is designed from the ground up for the high demands of blockchain applications which require far more from a WebAssembly engine than those designed for web browsers or standards development. The design choice of using Wasm enables VEX to reuse optimized and battle-tested compilers and toolchains which are being maintained and improved by a broader community. In addition, adopting Wasm standard also makes it easier for compiler developers to port other programming languages onto the VEXANIUM CHAIN blockchain.

## **High Throughput, Faster Confirmations and Lower Latency**

VEXANIUM is designed with high transactions throughput in mind and each new version is achieving significant improvements.

The consensus mechanism of Delegated Proof of Stake (DPOS) achieves high transaction throughputs because DPOS does not need to wait for all the nodes to complete a transaction to achieve finality. This behavior results in faster confirmations and lower latency.

The `VEXVM` mentioned earlier, and all its blockchain-dedicated features and improvements add significant contribution to the overall performance of the EOS blockchain.

## **Programmable Economics and Governance**

The resource allocation and governance mechanism of the VEXANIUM blockchain are programmable through smart contracts. You can modify the system smart contracts to customize the resource allocation model and governance rules of the VEXANIUM blockchain. The on-chain governance mechanism can be modified using system smart contracts, as the core layer code does not always have to be updated for the changes to take place.

## **Staking Mechanism**

In the VEXANIUM blockchain, access to the system resources is regulated by a process called the staking mechanism. The system resources that fall under the scope of the staking mechanism are CPU and NET. You can directly interact with the blockchain through the cleos CLI, the RPC APIs, or an application to access CPU and NET by staking system tokens.

{% hint style="info" %}
**NOTE**

RAM is a persistent system resource on the VEXANIUM blockchain and does not fall in the scope of the staking mechanism.
{% endhint %}

When you stake tokens for CPU and NET, you gain access to system resources proportional to the total amount of tokens staked by all other users for the same resource at the same time. This means you can perform transactions at no cost but in the limitations of the staked tokens. The staked tokens guarantee the proportional amount of resources regardless of any variations in the free market.

You can also allocate the system resources to VEXANIUM accounts in a programmatic manner by customizing the resource allocation model in the system smart contract. This flexibility is provided by the programmable economics of the VEXANIUM blockchain.

## **Business Model Flexibility**

Applications built on VEXANIUM can adopt a freemium model in which application users do not need to pay for the cost of resources needed to execute transactions.

The execution of the costless transactions under the freemium model is facilitated by applications co-signing the transactions with the user. Alternatively, applications can also stake enough system tokens to guarantee the resources needed.

## **Comprehensive Permission Schema**

The VEXANIUM blockchain has a comprehensive permission system for creating custom permission schemata for various use cases. For example, you can create a custom permission and use it to protect a specific feature of a smart contract. You can also split the authority required to modify a smart contract across multiple accounts with different levels of authority. This comprehensive permission system allows you to build a permissioned application on top of a flexible infrastructure.

## **Upgradability**

Applications deployed on the VEXANIUM blockchain are upgradeable. This means you can deploy code fix, add features, and change the application’s logic, as long as sufficient authority is provided. As a developer, you can iterate your application without the risk of being locked-in to a software bug permanently. It is also possible, however, to deploy smart contracts that cannot be modified on the VEXANIUM blockchain. These decisions are at the discretion of developers rather than restricted by the protocol.

## **Efficient energy consumption**

With DPOS as the consensus mechanism, VEXANIUM consumes much less energy to validate transactions and secure a blockchain compared to other consensus algorithms.

#### **What's Next?**

* Get Started: Learn how to develop on the VEXANIUM blockchain
* Protocol: Understand the protocols that make up the VEXANIUM blockchain
* Get Involved: Learn how to get involved and contribute to the VEXANIUM ecosystem


# Getting Started

* Installing vex.cdt
* Using Keosd as a local development wallet
* Starting the Nodeos daemon
* Creating accounts
* Vexanium Smart contract fundamentals
* Tokens
* Inline actions
* Custom Permission
* Payable actions using Vexanium `notify` declarations

**What's next?**

* Get Started: Install VEXANIUM in your local development environment.


# Development Environment

Learn about VEXANIUM Development Environment:

* [Prerequisites](/getting-started/development-environment/prerequisites)
* [Before You Begin](/getting-started/development-environment/before-you-begin)
* [Install the Contract Dev. Toolkit](/getting-started/development-environment/install-vex.cdt)
* [Create Development Wallet](/getting-started/development-environment/create-development-wallet)
* [Start `keosd` and `nodeos`](/getting-started/development-environment/start-keosd-and-nodeos)
* [Create Development Accounts](/getting-started/development-environment/create-development-wallet)


# Prerequisites

### VEXANIUM versions

The subsequent tutorials are up to date with the following VEXANIUM components.

|       Component      | Version |
| :------------------: | :-----: |
|         Leap         |         |
|          CDT         |         |
| eos-system-contracts |         |

### Development Experience

The VEXANIUM blockchain executes user-generated applications and code using WebAssembly (WASM). WASM is an emerging web standard with widespread support from Google, Microsoft, Apple, and industry leading companies.

At the moment the most mature toolchain for building applications that compile to WASM is clang/llvm with their C/C++ compiler. For best compatibility, it is recommended that you use the VEXANIUM C++ toolchain.

Other toolchains in development by 3rd parties include: Rust, Python, and Solidity. While these other languages may appear simpler, their performance will likely impact the scale of application you can build. We expect that C++ will be the best language for developing high-performance and secure smart contracts and plan to use C++ for the foreseeable future.

### Operating System

The VEXANIUM software supports the following environments for development and/or deployment:

1. Ubuntu 18.04
2. Ubuntu 20.04
3. MacOS 10.14 (Mojave)

{% hint style="info" %}
**NOTE**

If you are developing on Windows, unfortunately we do not provide PowerShell ports and instructions at this time. In the future we may append PowerShell commands. In the mean-time your best bet is to use a VM with Ubuntu, and set up your development environment inside this VM. If you're an advanced Window's developer familiar with porting Linux instructions, you should encounter minimal issues.
{% endhint %}

### Command Line Knowledge

There are a variety of tools provided along with VEXANIUM which requires you to have basic command line knowledge in order to interact with.

### Development Tools

We can use any text editor that, preferably, supports C++ syntax highlighting. Some of the popular editors are Sublime Text and Atom. Another option is an IDE, which provides a more sophisticated code completion and more complete development experience. You are welcome to use the software of your personal preference, but if you're unsure what to use we've provided some options for you to explore.

1. Potential Editors and IDEs
2. Sublime Text
3. Visual Studio Code

{% hint style="info" %}
**INFO**

The resources listed above are developed, offered, and maintained by third-parties and not by VEXANIUM Foundation. Providing information, material, or commentaries about such third-party resources does not mean we endorse or recommend any of these resources. We are not responsible, and disclaim any responsibility or liability, for your use of or reliance on any of these resources. Third-party resources may be updated, changed or terminated at any time, so the information below may be out of date or inaccurate. USAGE AND RELIANCE IS ENTIRELY AT YOUR OWN RISK.
{% endhint %}

### What you'll learn

Only a sample of what you'll learn

* How to quickly spin up a node
* Manage wallets and keys
* Create Accounts
* Write some contracts
* Compilation and ABI
* Deploy contracts

#### What's Next?

* Before You Begin: Steps to download and install binaries on your system.


# Before You Begin

### Step 1: Install binaries

To get started as quickly as possible we recommend using pre-built binaries.&#x20;

{% hint style="info" %}
**INFO**

You can find how to install VEXANIUM from source [here](https://github.com/vexanium/VexChain).
{% endhint %}

### Step 2: Setup a development directory, stick to it.

You're going to need to pick a directory to work from, it's suggested to create a `contracts` directory somewhere on your local drive.

```bash
mkdir contracts
cd contracts
```

### Step 3: Enter your local directory below.

Get the path of that directory and save it for later, as you're going to need it, you can use the following command to get your absolute path.

```bash
pwd
```

#### What's Next?

* Install the CDT: Steps to install the VEXANIUM Contract Development Toolkit (CDT) on your system.


# Install VEX.CDT

### Install the CDT

The VEXANIUM Contract Development Toolkit, CDT for short, is a collection of tools related to smart contract compilation. Subsequent tutorials use the CDT primarily for compiling contracts and generating ABIs.

#### Install from Binaries

To install the latest CDT binaries, visit the [CDT Binary Packages](https://github.com/vexanium/vex.cdt/releases) page.

#### What's Next?

* Create Development Wallet: Steps to create a new development wallet used to store public-private key pair.


# Create Development Wallet

Wallets are repositories of public-private key pairs. Private keys are needed to sign operations performed on the blockchain. Wallets are accessed using `cleos` or `clivex`.

### Step 1: Create a Wallet

The first step is to create a wallet. Use `cleos wallet create` to create a new "default" wallet using the option `--to-console` for simplicity. If using cleos in production, it's wise to instead use -`-file` so your wallet password is not in your bash history. For development purposes and because these are development and not production keys `--to-console` poses no security threat.

```bash
cleos wallet create --to-console
```

`cleos` will return a password, save this password somewhere as you will likely need it later in the tutorial.

```
Creating wallet: default
Save password to use in the future to unlock this wallet.
Without password imported keys will not be retrievable.
"PW5Kewn9L76X8Fpd....................t42S9XCw2"
```

{% hint style="info" %}

#### ABOUT WALLETS

A common misconception in cryptocurrency regarding wallets is that they store tokens. However, in reality, a wallet is used to store private keys in an encrypted file to sign transactions. Wallets do not serve as a storage medium for tokens.
{% endhint %}

A user builds a transaction object, usually through an interface, sends that object to the wallet to be signed, the wallet then returns that transaction object with a signature which is then broadcast to the network. When/if the network confirms that the transaction is valid, it is included into a block on the blockchain.

### Step 2: Open the Wallet

Wallets are closed by default when starting a keosd instance, to begin, run the following.

```bash
cleos wallet open
```

Run the following to return a list of wallets.

```bash
cleos wallet list
```

and it will return.

```bash
Wallets:
[
  "default"
]
```

### Step 3: Unlock it

The keosd wallet(s) have been opened, but is still locked. Moments ago you were provided a password, you're going to need that now.

```bash
cleos wallet unlock
```

You will be prompted for your password, paste it and press enter.

Now run the following command

```bash
cleos wallet list
```

It should now return

```bash
Wallets:
[
  "default *"
]
```

Pay special attention to the asterisk (\*). This means that the wallet is currently unlocked.

### &#x20;Step 4: Import keys into your wallet

Generate a private key, cleos has a helper function for this, just run the following.

```bash
cleos wallet create_key
```

It will return something like below.

```bash
Created new private key with a public key of:
"VEX8PEJ5FM42xLpHK...X6PymQu97KrGDJQY5Y"
```

### Step 5: Import the Development Key

Every new VEXANIUM chain comes with a development key, and this key is the same. Load this key to sign transactions on behalf of the system user

```bash
cleos wallet import
```

You'll be prompted for a private key, enter the development key provided below

```bash
5JjMtcY2j264vChLogZk3Y7sySSC4z3hWjBTvwLhJoqXv6YP4X3
```

{% hint style="info" %}
**IMPORTANT**

Never use the development key for a production account! Doing so will most certainly result in the loss of access to your account, this private key is publicly known.
{% endhint %}

Wonderful, you now have a default wallet unlocked and loaded with a key, and are ready to proceed.

#### What's Next?

* Start Your Node: Steps to start keosd and nodeos.


# Start keosd and nodeos

### Step 1: Boot Node and Wallet

#### Step 1.1: Start keosd

First let us start keosd:

```bash
keosd &
```

You should see some output in the console that looks like this:

```sh
info  2023-03-23T21:08:18.642 keosd     wallet_plugin.cpp:38          plugin_initialize    ] initializing wallet plugin
info  2023-03-23T21:08:18.642 keosd     wallet_api_plugin.cpp:84      plugin_startup       ] starting wallet_api_plugin
info  2023-03-23T21:08:18.642 keosd     http_plugin.cpp:983           add_handler          ] add api url: /v1/wallet/create
info  2023-03-23T21:08:18.642 keosd     http_plugin.cpp:983           add_handler          ] add api url: /v1/wallet/create_key
info  2023-03-23T21:08:18.642 keosd     http_plugin.cpp:983           add_handler          ] add api url: /v1/wallet/get_public_keys
info  2023-03-23T21:08:18.642 keosd     http_plugin.cpp:983           add_handler          ] add api url: /v1/wallet/import_key
info  2023-03-23T21:08:18.642 keosd     http_plugin.cpp:983           add_handler          ] add api url: /v1/wallet/list_keys
info  2023-03-23T21:08:18.642 keosd     http_plugin.cpp:983           add_handler          ] add api url: /v1/wallet/list_wallets
info  2023-03-23T21:08:18.642 keosd     http_plugin.cpp:983           add_handler          ] add api url: /v1/wallet/lock
info  2023-03-23T21:08:18.642 keosd     http_plugin.cpp:983           add_handler          ] add api url: /v1/wallet/lock_all
info  2023-03-23T21:08:18.642 keosd     http_plugin.cpp:983           add_handler          ] add api url: /v1/wallet/open
info  2023-03-23T21:08:18.642 keosd     http_plugin.cpp:983           add_handler          ] add api url: /v1/wallet/remove_key
info  2023-03-23T21:08:18.642 keosd     http_plugin.cpp:983           add_handler          ] add api url: /v1/wallet/set_timeout
info  2023-03-23T21:08:18.642 keosd     http_plugin.cpp:983           add_handler          ] add api url: /v1/wallet/sign_digest
info  2023-03-23T21:08:18.642 keosd     http_plugin.cpp:983           add_handler          ] add api url: /v1/wallet/sign_transaction
info  2023-03-23T21:08:18.642 keosd     http_plugin.cpp:983           add_handler          ] add api url: /v1/wallet/unlock
info  2023-03-23T21:08:18.643 keosd     http_plugin.cpp:983           add_handler          ] add api url: /v1/node/get_supported_apis
```

Press enter to continue

#### Troubleshooting

After entering `keosd &`, you may encounter this message:

```bash
warn  2023-03-23T21:06:41.294 keosd     wallet_plugin.cpp:65          plugin_initialize    ] 3120000 wallet_exception: Wallet exception
Failed to lock access to wallet directory; is another keosd running?
    {}
    keosd  wallet_manager.cpp:304 initialize_lock
Failed to initialize
```

This is because another instance of keosd process might be running in the background. Kill all instances by `pkill keosd` and rerun `keosd &`.

#### Step 1.2: Start nodeos

Set configurations to start nodeos can be read here.

First create new directory to run nodeos.

```sh
mkdir nodeos
cd nodeos
```

Download the latest snapshot from [here](https://v2.vexascan.com/snapshots). Or you can download by command below and replace the \[filename] with the latest snapshot.

```sh
wget https://v2.vexascan.com/files/download/[filename].bin
```

Create new bash file.

```sh
touch bash.sh
code .
```

Paste the command below to the bash file, replace the \[filename] with snapshot’s filename that downloaded and save it.

```bash
if [ ! -d $DATADIR ]; then
  mkdir -p $DATADIR;
fi

nodeos \
--snapshot ./[filename].bin \
--plugin eosio::producer_plugin \
--plugin eosio::producer_api_plugin \
--plugin eosio::chain_plugin \
--plugin eosio::chain_api_plugin \
--plugin eosio::state_history_plugin \
--plugin eosio::http_plugin \
--plugin eosio::history_api_plugin \
--plugin eosio::history_plugin \
--data-dir $DATADIR \
--blocks-dir $DATADIR"/blocks" \
--config-dir $DATADIR \
--http-server-address 0.0.0.0:8888 \
--p2p-listen-endpoint 0.0.0.0:9010 \
--chain-state-db-size-mb 20480 \
--access-control-allow-origin=* \
--access-control-allow-headers 'content-type' \
--contracts-console \
--disable-replay-opts \
--http-validate-host=false \
--verbose-http-errors \
--enable-stale-production \
--p2p-peer-address  explorer.vexanium.com:8091 \
--p2p-peer-address 188.166.233.69:8092 \
--p2p-peer-address 139.180.136.160:9090 \
--p2p-peer-address 167.179.103.141:9090 \
--p2p-peer-address 178.128.217.200:9090 \
--p2p-peer-address 178.128.217.200:9090 \
--p2p-peer-address 45.32.122.5:9095 \
--p2p-peer-address 159.65.142.132:8080 \
--p2p-peer-address 139.180.192.207:8092 \
--p2p-peer-address 209.97.162.124:8091 \
--p2p-peer-address 34.81.37.55:9010 \
>> "nodeos.log" 2>&1 & \
echo $! > $DATADIR"/eosd.pid"
```

Run the command below.

```bash
./bash.sh
```

These settings accomplish the following:

* Run Nodeos. This command loads all the basic plugins, set the server address, enable CORS and add some contract debugging and logging.
* Enable CORS with no restrictions (\*) and development logging

{% hint style="danger" %}
**DANGER**

In the above configuration, CORS is enabled for \* for development purposes only, you should never enable CORS for \* on a node that is publicly accessible!
{% endhint %}

#### Troubleshooting

After starting `nodeos`, if you see an error message similar to "Database dirty flag set (likely due to unclean shutdown): replay required", try to start nodeos with `--replay-blockchain`. More details on troubleshooting nodeos can be found here.

### Step 2: Check the installation

#### Step 2.1: Check that Nodeos is Producing Blocks

Run the following command

```bash
tail -f nodeos.log
```

You should see some output in the console that looks like this:

```sh
info  2023-05-04T07:58:58.016 nodeos    chain_plugin.cpp:527          operator()           ] Support for builtin protocol feature 'FIX_LINKAUTH_RESTRICTION' (with digest of 'e0fb64b1085cc5538970158d05a009c24e276fb94e1a0bf6a528b48fbc4ff526') is enabled with preactivation required
info  2023-05-04T07:58:58.028 nodeos    chain_plugin.cpp:637          operator()           ] Saved default specification for builtin protocol feature 'FIX_LINKAUTH_RESTRICTION' (with digest of 'e0fb64b1085cc5538970158d05a009c24e276fb94e1a0bf6a528b48fbc4ff526') to: /nodeos/./data/protocol_features/BUILTIN-FIX_LINKAUTH_RESTRICTION.json
info  2023-05-04T07:58:58.029 nodeos    chain_plugin.cpp:527          operator()           ] Support for builtin protocol feature 'REPLACE_DEFERRED' (with digest of 'ef43112c6543b88db2283a2e077278c315ae2c84719a8b25f25cc88565fbea99') is enabled with preactivation required
info  2023-05-04T07:58:58.042 nodeos    chain_plugin.cpp:637          operator()           ] Saved default specification for builtin protocol feature 'REPLACE_DEFERRED' (with digest of 'ef43112c6543b88db2283a2e077278c315ae2c84719a8b25f25cc88565fbea99') to: /nodeos/./data/protocol_features/BUILTIN-REPLACE_DEFERRED.json
info  2023-05-04T07:58:58.043 nodeos    chain_plugin.cpp:527          operator()           ] Support for builtin protocol feature 'NO_DUPLICATE_DEFERRED_ID' (with digest of '4a90c00d55454dc5b059055ca213579c6ea856967712a56017487886a4d4cc0f') is enabled with preactivation required
info  2023-05-04T07:58:58.055 nodeos    chain_plugin.cpp:637          operator()           ] Saved default specification for builtin protocol feature 'NO_DUPLICATE_DEFERRED_ID' (with digest of '4a90c00d55454dc5b059055ca213579c6ea856967712a56017487886a4d4cc0f') to: /nodeos/./data/protocol_features/BUILTIN-NO_DUPLICATE_DEFERRED_ID.json
info  2023-05-04T07:58:58.056 nodeos    chain_plugin.cpp:527          operator()           ] Support for builtin protocol feature 'ONLY_LINK_TO_EXISTING_PERMISSION' (with digest of '1a99a59d87e06e09ec5b028a9cbb7749b4a5ad8819004365d02dc4379a8b7241') is enabled with preactivation required
info  2023-05-04T07:58:58.069 nodeos    chain_plugin.cpp:637          operator()           ] Saved default specification for builtin protocol feature 'ONLY_LINK_TO_EXISTING_PERMISSION' (with digest of '1a99a59d87e06e09ec5b028a9cbb7749b4a5ad8819004365d02dc4379a8b7241') to: /nodeos/./data/protocol_features/BUILTIN-ONLY_LINK_TO_EXISTING_PERMISSION.json
info  2023-05-04T07:58:58.070 nodeos    chain_plugin.cpp:540          operator()           ] Support for builtin protocol feature 'PREACTIVATE_FEATURE' (with digest of '0ec7e080177b2c02b278d5088611686b49d739925a92d9bfcacd7fc6b74053bd') is enabled without activation restrictions
info  2023-05-04T07:58:58.082 nodeos    chain_plugin.cpp:637          operator()           ] Saved default specification for builtin protocol feature 'PREACTIVATE_FEATURE' (with digest of '0ec7e080177b2c02b278d5088611686b49d739925a92d9bfcacd7fc6b74053bd') to: /nodeos/./data/protocol_features/BUILTIN-PREACTIVATE_FEATURE.json

```

Let the `nodeos` run until the output looks like this and blocks become synchronized.

```sh
info  2023-05-04T08:13:32.253 net-1     net_plugin.cpp:1717           operator()           ] requesting range 231504310 to 231504409, from bp-dejave2:9090 - 60245f9
info  2023-05-04T08:13:33.047 net-0     net_plugin.cpp:1717           operator()           ] requesting range 231504410 to 231504509, from ubuntu-tukargulingbp:9090 - 37af369
info  2023-05-04T08:13:33.880 net-1     net_plugin.cpp:1717           operator()           ] requesting range 231504510 to 231504609, from vultr.guest:9095 - 441ecee
info  2023-05-04T08:13:34.822 net-1     net_plugin.cpp:1717           operator()           ] requesting range 231504610 to 231504709, from mainnet-node-01:8080 - 46085be
info  2023-05-04T08:13:35.463 net-0     net_plugin.cpp:1717           operator()           ] requesting range 231504710 to 231504809, from vps-vexascan:8092 - 7224d49
info  2023-05-04T08:13:36.745 net-1     net_plugin.cpp:1717           operator()           ] requesting range 231504810 to 231504909, from bp-bnkri:9090 - 2b55aa2
info  2023-05-04T08:13:38.236 net-1     net_plugin.cpp:1717           operator()           ] requesting range 231504910 to 231505009, from bp-dejave2:9090 - 60245f9
info  2023-05-04T08:13:39.221 nodeos    producer_plugin.cpp:421       on_incoming_block    ] Received block e9492f536a6d4266... #231505000 @ 2023-05-03T12:47:24.500 signed by ekasepbanjar [trxs: 28, lib: 231504674, conf: 0, latency: 69974721 ms]

```

Press ctrl + c to close the log

{% hint style="warning" %}
**WARNING**

If you want to stop `nodeos`, run command `pkill nodeos` .

After this, before you start `nodeos`, remove the line of --snapshot configuration from the bash file. Then you can rerun `nodeos`.
{% endhint %}

#### Step 2.2: Check the Wallet

Open the shell and run the cleos command to list available wallets. We will talk more about wallets in the future. For now, we need to validate the installation and see that the command line client cleos is working as intended.

```bash
cleos wallet list
```

You should see a response with an empty list of wallets:

```sh
Wallets:
[]
```

From this point forward, you'll be executing commands from your local system (Linux or Mac).

#### Step 2.3: Check Nodeos endpoints

This will check that the RPC API is working correctly, pick one.

* Check the `get_info` endpoint provided by the `chain_api_plugin` in your browser: <http://localhost:8888/v1/chain/get\\_info>
* Check the same thing, but in the console on your host machine

```sh
curl http://localhost:8888/v1/chain/get_info
```

#### What's Next?

Create Test Accounts: Learn how to create test accounts in the VEXANIUM blockchain along with troubleshooting steps.


# Create Development Accounts

### What is an account?

An account is a collection of authorizations, stored on the blockchain, and used to identify a sender/recipient. It has a flexible authorization structure that enables it to be owned either by an individual or group of individuals depending on how permissions have been configured. An account is required to send or receive a valid transaction to the blockchain.

### Step 1: Create Accounts

In section **1.4 Create Development Wallet**, you created a development key pair. Now, create new account in VEXANIUM blockchain.

{% hint style="info" %}
**NOTE**

Follow the tutorials [here](https://belajar.vexanium.com/membuat-vex-account-dengan-vexwallet-mobile-dan-melakukan-import-ke-vexwallet-pc/) for a simple way of creating account on VEXANIUM blockchain.
{% endhint %}

Throughout these tutorials the accounts `[YOUR_VEX_ACCOUNT_1]` and `[YOUR_VEX_ACCOUNT_2]` are used. Create accounts using below command.

{% hint style="info" %}
**INFO**

Before you do action to the blockchain, there are two options by start nodeos or endpoint. If you want to push action without run nodeos, you can add --url configuration after `cleos` command like below.
{% endhint %}

```bash
cleos --url https://explorer.vexanium.com:6960 system newaccount --transfer [CREATORACC] [NEWACC] --buy-ram "0.0500 VEX" --stake-net "0.0000 VEX" --stake-cpu "0.0001 VEX" [YOUR_PUBLIC_KEY]
```

```bash
cleos --url https://explorer.vexanium.com:6960 system newaccount --transfer belajarsc1111 belajarsc222 --buy-ram "0.1000 VEX" --stake-net "0.0000 VEX" --stake-cpu "0.0001 VEX" VEX8ZcARNPyCfoez2ooUPWzykh94FzYbNSftk5Ri3Lj6DUsA4QPoP
```

You should then see a confirmation message similar to the following for each command that confirms that the transaction has been broadcast.

```bash
executed transaction: 10953eb9368082f816e80a4905024e626b454623c7f9987d728fa5a81ffb6850  344 bytes  1559 us
#       vexcore <= vexcore::newaccount          {"creator":"belajarsc111","name":"belajarsc111","owner":{"threshold":1,"keys":[{"key":"VEX8ZcARNPyCf...
#       vexcore <= vexcore::buyram              {"payer":"belajarsc111","receiver":"belajarsc111","quant":"0.1000 VEX"}
#       vexcore <= vexcore::delegatebw          {"from":"belajarsc111","receiver":"belajarsc111","stake_net_quantity":"0.0000 VEX","stake_cpu_quanti...
#     vex.token <= vex.token::transfer          {"from":"belajarsc111","to":"vex.ram","quantity":"0.0995 VEX","memo":"buy ram"}
#     vex.token <= vex.token::transfer          {"from":"belajarsc111","to":"vex.ramfee","quantity":"0.0005 VEX","memo":"ram fee"}
#     vex.token <= vex.token::transfer          {"from":"vex.ramfee","to":"vex.rex","quantity":"0.0005 VEX","memo":"transfer from vex.ramfee to vex....
#  belajarsc111 <= vex.token::transfer          {"from":"belajarsc111","to":"vex.ram","quantity":"0.0995 VEX","memo":"buy ram"}
#       vex.ram <= vex.token::transfer          {"from":"belajarsc111","to":"vex.ram","quantity":"0.0995 VEX","memo":"buy ram"}
#  belajarsc111 <= vex.token::transfer          {"from":"belajarsc111","to":"vex.ramfee","quantity":"0.0005 VEX","memo":"ram fee"}
#    vex.ramfee <= vex.token::transfer          {"from":"belajarsc111","to":"vex.ramfee","quantity":"0.0005 VEX","memo":"ram fee"}
#    vex.ramfee <= vex.token::transfer          {"from":"vex.ramfee","to":"vex.rex","quantity":"0.0005 VEX","memo":"transfer from vex.ramfee to vex....
#       vex.rex <= vex.token::transfer          {"from":"vex.ramfee","to":"vex.rex","quantity":"0.0005 VEX","memo":"transfer from vex.ramfee to vex....
#     vex.token <= vex.token::transfer          {"from":"belajarsc111","to":"vex.stake","quantity":"0.0001 VEX","memo":"stake bandwidth"}
#  belajarsc111 <= vex.token::transfer          {"from":"belajarsc111","to":"vex.stake","quantity":"0.0001 VEX","memo":"stake bandwidth"}
#     vex.stake <= vex.token::transfer          {"from":"belajarsc111","to":"vex.stake","quantity":"0.0001 VEX","memo":"stake bandwidth"}
warning: transaction executed locally, but may not be confirmed by the network yet         ]

```

### Step 2: Public Key

Note in cleos command a public key is associated with account alice. Each VEX account is associated with a public key.

Be aware that the account name is the only identifier for ownership. You can change the public key but it would not change the ownership of your VEXANIUM account.

Check which public key is associated with belajarsc222 using `cleos get account`

```bash
cleos --url http://explorer.vexanium.com:8080 get account belajarsc222
```

You should see a message similar to the following:

```bash
created: 2023-03-23T21:39:18.000
permissions:
     owner     1:    1 VEX8ZcARNPyCfoez2ooUPWzykh94FzYbNSftk5Ri3Lj6DUsA4QPoP
        active     1:    1 VEX8ZcARNPyCfoez2ooUPWzykh94FzYbNSftk5Ri3Lj6DUsA4QPoP
memory:
     quota:     5.735 KiB    used:     3.365 KiB

net bandwidth:
     staked:          0.0000 VEX           (total stake delegated from account to self)
     delegated:       0.0000 VEX           (total staked delegated to account from others)
     used:                 0 bytes
     available:            0 bytes
     limit:                0 bytes

cpu bandwidth:
     staked:          0.0001 VEX           (total stake delegated from account to self)
     delegated:       0.0000 VEX           (total staked delegated to account from others)
     used:                 0 us
     available:           10 us
     limit:               10 us

producers:     <not voted>

```

Notice that actually belajarsc222 has both owner and active public keys. VEXANIUM has a unique authorization structure that has added security for your account. You can minimize the exposure of your account by keeping the owner key cold, while using the key associated with your active permission. This way, if your active key were ever compromised, you could regain control over your account with your owner key.

In term of authorization, if you have a owner permission you can change the private key of active permission. But you cannot do so other way around.

{% hint style="info" %}
**USING DIFFERENT KEYS FOR ACTIVE/OWNER ON A PRODUCTION NETWORK**

In this tutorial we are using the same public key for both owner and active for simplicity. In production network, two different keys are strongly recommended
{% endhint %}

#### Troubleshooting

If you get an error while creating the account, make sure your wallet is unlocked

```bash
cleos wallet list
```

You should see an asterisk (\*) next to the wallet name, as seen below.

```bash
Wallets:
[
  "default *"
]
```

#### What's Next?

Hello World: The Hello World of VEXANIUM! Learn how to set up your environment and deploy your first smart contract.


# Smart Contract Development

Learn Smart Contract Developemnt on VEXANIUM:

* Hello World Contract
* Deploy, Issue and Transfer Tokens
* Understanding ABI Files
* Data Persistence
* Secondary Indices
* Adding Inline Actions
* Inline Actions to External Contracts
* Creating and Linking Custom Permissions
* Payable actions


# Hello World Contract

### Create the Contract[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/hello-world#create-the-contract) <a href="#create-the-contract" id="create-the-contract"></a>

Create a new directory called **hello** in the **contracts** directory you previously created and enter the newly created directory.

```sh
cd CONTRACTS_DIR
mkdir hello
cd hello
```

Create a new file, **hello.cpp**, and open it in your preferred text editor:

```sh
touch hello.cpp
```

Below the `eosio.hpp` header file is included. The `eosio.hpp` file includes a few classes required to write a smart contract.

```cpp
#include <eosio/eosio.hpp>
```

Using the `eosio namespace` will reduce clutter in your code. For example, by setting `using namespace eosio;`, `eosio::print("foo")` can be written `print("foo").`

```cpp
using namespace eosio;
```

Create a standard C++11 class. The contract class needs to extend `eosio::contract` class which is included earlier from the eosio.hpp header:

```cpp
#include <eosio/eosio.hpp>

using namespace eosio;

class [[eosio::contract]] hello : public contract {};
```

An empty contract is not enough. Add a public access specifier and a using-declaration. The `using` declaration will allow us to write more concise code:

```cpp
#include <eosio/eosio.hpp>

using namespace eosio;

class [[eosio::contract]] hello : public contract {
  public:
   using contract::contract;
};
```

This contract needs to do something. In the spirit of **hello world** write an action that accepts a "name" parameter, and then prints that parameter out:

Actions implement the behavior of a contract

```cpp
#include <eosio/eosio.hpp>

using namespace eosio;

class [[eosio::contract]] hello : public contract {
  public:
      using contract::contract;

      [[eosio::action]]
      void hi( name user ) {
         print( "Hello, ", user);
      }
};
```

The above action accepts a parameter called `user`, that's a `name` type. VEXANIUM comes with a number of typedefs, one of the most common typedefs you'll encounter is `name`. Using the `eosio::print` library previously included, concatenate a string and print the `user` parameter. Use the braced initialization of `name{user}` to make the `user` parameter printable.

As is, the ABI generator in `cdt` won't know about the `hi()` action without an attribute. Add a C++11 style attribute above the action, this way the abi generator can produce more reliable output:

```cpp
#include <eosio/eosio.hpp>

using namespace eosio;

class [[eosio::contract]] hello : public contract {
  public:
      using contract::contract;

      [[eosio::action]]
      void hi( name user ) {
         print( "Hello, ", user);
      }
};
```

Everything together, here's the completed hello world contract:

```cpp
#include <eosio/eosio.hpp>

using namespace eosio;

class [[eosio::contract]] hello : public contract {
  public:
      using contract::contract;

      [[eosio::action]]
      void hi( name user ) {
         print( "Hello, ", user);
      }
};
```

### Compile the Contract[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/hello-world#compile-the-contract) <a href="#compile-the-contract" id="compile-the-contract"></a>

{% hint style="info" %}
**INFO**

The ABI Generator in eosio.cdt supports several different style of attributes, see the ABI usage guide here.
{% endhint %}

Compile your code to web assembly (.wasm) as follows:

```sh
eosio-cpp hello.cpp -o hello.wasm
```

### Deploy the Contract[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/hello-world#deploy-the-contract) <a href="#deploy-the-contract" id="deploy-the-contract"></a>

When you deploy a contract, it is deployed to an account, and the account becomes the interface for the contract. As mentioned earlier these tutorials use the same public key for all of the accounts to keep things simple.

View the wallet keys by:

```
cleos wallet keys
```

Create an account for the contract using `cleos create account`, with the command provided below.

<pre><code>cleos --url http//explorer.vexanium.com:8080 set contract hello CONTRACTS_DIR/hello -p <a data-footnote-ref href="#user-content-fn-1">[YOUR_ACCOU</a>NT_NAME_1]@active
</code></pre>

Deploy the compiled `wasm` to the blockchain with `cleos set contract`.

In previous steps you should have created a \`contracts\` directory and obtained the absolute path and then saved it into a cookie. Replace "CONTRACTS\_DIR" in the command below with the absolute path to your \`contracts\` directory.

```sh
cleos --url http//explorer.vexanium.com:8080 set contract hello CONTRACTS_DIR/hello -p [YOUR_ACCOUNT_NAME_1]@active
```

{% hint style="info" %}
**GET AN ERROR?**

Check if your wallet needs to be unlocked.
{% endhint %}

### Execute the Contract[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/hello-world#execute-the-contract) <a href="#execute-the-contract" id="execute-the-contract"></a>

Great! Now the contract is set. Push an action to it.

```sh
cleos --url http://explorer.vexanium.com:8080 push action hello hi '["harry"]' -p belajarsc222@active
```

```
executed transaction: 4c10c1426c16b1656e802f3302677594731b380b18a44851d38e8b5275072857  244 bytes  1000 cycles
#    hello.code <= hello.code::hi               {"user":"harry"}
>> Hello, harry
```

As written, the contract will allow any account to say **hi** to any user:

```
cleos --url http://explorer.vexanium.com:8080 push action hello hi '["harry"]' -p [YOUR_ACCOUNT_NAME_1]]@active
```

```
executed transaction: 28d92256c8ffd8b0255be324e4596b7c745f50f85722d0c4400471bc184b9a16  244 bytes  1000 cycles
#    hello.code <= hello.code::hi               {"user":"[YOUR_ACCOUNT_NAME_1]"}
>> Hello, harry
```

As expected, the console output is **Hello, harry**

In this case "`[YOUR_ACCOUNT_NAME_1]`" is the one who authorized it and `user` is just an argument. Modify the contract so that the authorizing user, "`[YOUR_ACCOUNT_NAME_1]`" in this case, must be the same as the user the contract is responding "hi" to. Use the `require_auth` method. This method takes a `name` as a parameter, and will check if the user executing the action matches the provided parameter.

```cpp
void hi( name user ) {
   require_auth( user );
   print( "Hello, ", name{user} );
}
```

Recompile the contract

```
eosio-cpp -abigen -o hello.wasm hello.cpp
```

And then update it

```
cleos --url http://explorer.vexanium.com:8080 set contract hello CONTRACTS_DIR/hello -p [YOUR_ACCOUNT_NAME_1]@active
```

Try to execute the action again, but this time with mismatched authorization.

```
cleos --url http://explorer.vexanium.com:8080 push action hello hi '["harry"]' -p belajarsc222@active
```

As expected, `require_auth` halted the transaction and threw an error.

```sh
Error 3090004: Missing required authority
Ensure that you have the related authority inside your transaction!;
If you are currently using 'cleos push action' command, try to add the relevant authority using -p option.
```

Now, with our change, the contract verifies the provided `name user` is the same as the authorising user. Try it again, but this time, with the authority of the "alice" account.

```
cleos --url http://explorer.vexanium.com:8080 push action hello hi '["taylor"]' -p [YOUR_ACCOUNT_NAME_1]@active
```

```
executed transaction: 235bd766c2097f4a698cfb948eb2e709532df8d18458b92c9c6aae74ed8e4518  244 bytes  1000 cycles
#    hello <= hello::hi               {"user":"taylor"}
>> Hello, taylor
```

### What's Next?[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/hello-world#whats-next) <a href="#whats-next" id="whats-next"></a>

* Deploy, Issue and Transfer Tokens: Learn how to deploy, issue and transfer tokens.

[^1]:


# Deploy, Issue and Transfer Tokens

### Step 1: Obtain Contract Source[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/deploy-issue-and-transfer-tokens#step-1-obtain-contract-source) <a href="#step-1-obtain-contract-source" id="step-1-obtain-contract-source"></a>

Navigate to your contracts directory.

```sh
cd CONTRACTS_DIR
```

Pull the latest release

This repository contains several contracts, but it's the `eosio.token` contract that is important for this section.

```sh
cd reference-contracts/contracts/eosio.token
```

### Step 2: Create Account for Contract[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/deploy-issue-and-transfer-tokens#step-2-create-account-for-contract) <a href="#step-2-create-account-for-contract" id="step-2-create-account-for-contract"></a>

Before we can deploy the token contract we must create an account to deploy it to, we'll use the **eosio development key** for this account.

{% hint style="info" %}
**INFO**

You need to unlock your wallet prior to the next step.
{% endhint %}

```sh
cleos create account eosio eosio.token EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
```

### Step 3: Compile the Contract[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/deploy-issue-and-transfer-tokens#step-3-compile-the-contract) <a href="#step-3-compile-the-contract" id="step-3-compile-the-contract"></a>

```
cdt-cpp -I include -o eosio.token.wasm src/eosio.token.cpp --abigen
```

### Step 4: Deploy the Token Contract[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/deploy-issue-and-transfer-tokens#step-4-deploy-the-token-contract) <a href="#step-4-deploy-the-token-contract" id="step-4-deploy-the-token-contract"></a>

```
cleos set contract eosio.token CONTRACTS_DIR/reference-contracts/contracts/eosio.token --abi eosio.token.abi -p eosio.token@active
```

```
Reading WASM from ...reference-contracts/contracts/eosio.token/eosio.token.wasm...
Publishing contract...
executed transaction: a68299112725b9f2233d56e58b5392f3b37d2a4564bdf99172152c21c7dc323f  6984 bytes  6978 us
#         eosio <= eosio::setcode               {"account":"eosio.token","vmtype":0,"vmversion":0,"code":"0061736d0100000001a0011b60000060017e006002...
#         eosio <= eosio::setabi                {"account":"eosio.token","abi":"0e656f73696f3a3a6162692f312e310008076163636f756e7400010762616c616e63...
warning: transaction executed locally, but may not be confirmed by the network yet         ]
```

### Step 5: Create the Token[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/deploy-issue-and-transfer-tokens#step-5-create-the-token) <a href="#step-5-create-the-token" id="step-5-create-the-token"></a>

To create a new token, call `create` action with the correct parameters. This action accepts 1 argument, it consists of:

* An issuer that is an eosio account. In this case, it's `alice`. This issuer will be the one with the authority to call `issue` and/or perform other actions such as closing accounts or retiring tokens.
* An `asset` type composed of two pieces of data, a floating-point number sets the maximum supply and a `symbol` in capitalized alpha characters which represents the asset. For example, "1.0000 SYS".

Below is a concise way to call this method, using positional arguments:

```
cleos push action eosio.token create '[ "alice", "1000000000.0000 SYS"]' -p eosio.token@active
```

The command above created a new token `SYS` with a precision of 4 decimals and a maximum supply of 1000000000.0000 SYS. It also designates `alice` as the issuer. To create this token, the contract requires the permission of the `eosio.token` account. For this reason, `-p eosio.token@active` was passed to authorize this action.

An alternate approach uses named arguments:

```
cleos push action eosio.token create '{"issuer":"alice", "maximum_supply":"1000000000.0000 SYS"}' -p eosio.token@active
```

Execute the command above:

```
executed transaction: 10cfe1f7e522ed743dec39d83285963333f19d15c5d7f0c120b7db652689a997  120 bytes  1864 us
#   eosio.token <= eosio.token::create          {"issuer":"alice","maximum_supply":"1000000000.0000 SYS"}
warning: transaction executed locally, but may not be confirmed by the network yet         ]
```

### Step 6: Issue Tokens[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/deploy-issue-and-transfer-tokens#step-6-issue-tokens) <a href="#step-6-issue-tokens" id="step-6-issue-tokens"></a>

The issuer `alice` can now issue new tokens. As mentioned earlier only the issuer can do so, therefore, `-p alice@active` must be provided to authorize the `issue` action.

```
cleos push action eosio.token issue '[ "alice", "100.0000 SYS", "memo" ]' -p alice@active
```

```
executed transaction: d1466bb28eb63a9328d92ddddc660461a16c405dffc500ce4a75a10aa173347a  128 bytes  205 us
#   eosio.token <= eosio.token::issue           {"to":"alice","quantity":"100.0000 SYS","memo":"memo"}
warning: transaction executed locally, but may not be confirmed by the network yet         ]
```

This time the output contains several actions: one `issue` action and three `transfer` actions. While the only action signed was `issue`, the `issue` action performed an `inline transfer` and the `inline transfer` notified the sender and receiver accounts. The output indicates all the action handlers that were called, the order they were called in, and whether any output was generated by the action.

Technically, the `eosio.token` contract could have skipped the `inline transfer` and opted to just modify the balances directly. However, in this case the `eosio.token` contract is following a token convention that requires that all account balances be derivable by the sum of the transfer actions that reference them. It also requires that the sender and receiver of funds be notified so they can automate handling deposits and withdrawals.

To inspect the transaction, try using the `-d -j` options, which indicate "don't broadcast" and "return the transaction as json", which you may find useful during development.

```
cleos push action eosio.token issue '["alice", "100.0000 SYS", "memo"]' -p alice@active -d -j
```

### Step 7: Transfer Tokens[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/deploy-issue-and-transfer-tokens#step-7-transfer-tokens) <a href="#step-7-transfer-tokens" id="step-7-transfer-tokens"></a>

Now that account `alice` has been issued tokens, transfer some of them to account `bob`.

```
cleos push action eosio.token transfer '[ "alice", "bob", "25.0000 SYS", "m" ]' -p alice@active
```

```
executed transaction: 800835f28659d405748f4ac0ec9e327335eae579a0d8e8ef6330e78c9ee1b67c  128 bytes  1073 us
#   eosio.token <= eosio.token::transfer        {"from":"alice","to":"bob","quantity":"25.0000 SYS","memo":"m"}
#         alice <= eosio.token::transfer        {"from":"alice","to":"bob","quantity":"25.0000 SYS","memo":"m"}
#           bob <= eosio.token::transfer        {"from":"alice","to":"bob","quantity":"25.0000 SYS","memo":"m"}
warning: transaction executed locally, but may not be confirmed by the network yet         ]
```

Now check if `bob` received the tokens using [cleos get currency balance](http://docs.eosnetwork.com/leap/latest/cleos/command-reference/get/currency-balance)

```
cleos get currency balance eosio.token bob SYS
```

```
25.0000 SYS
```

Check `alice`'s balance. Notice that tokens were deducted from the account.

```
cleos get currency balance eosio.token alice SYS
```

```
75.0000 SYS
```

Excellent! Everything adds up.

### What's Next?[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/deploy-issue-and-transfer-tokens#whats-next) <a href="#whats-next" id="whats-next"></a>

* [Understanding ABI Files](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files): Introduction to Application Binary Files (ABI) and how the ABI file correlates to the `eosio.token` contract.


# Understanding ABI Files

### Introduction[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#introduction) <a href="#introduction" id="introduction"></a>

Previously you deployed the `eosio.token` contract using the provided ABI file. This tutorial will overview how the ABI file correlates to the `eosio.token` contract.

ABI files can be generated using the `cdt-cpp` utility provided by `cdt`. However, there are several situations that may cause ABI's generation to malfunction or fail altogether. Advanced C++ patterns can trip it up and custom types can sometimes cause issues for ABI generation. For this reason, it's **imperative** you understand how ABI files work, so you can debug and fix if and when necessary.

### What is an ABI[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#what-is-an-abi) <a href="#what-is-an-abi" id="what-is-an-abi"></a>

The Application Binary Interface (ABI) is a JSON-based description on how to convert user actions between their JSON and Binary representations. The ABI also describes how to convert the database state to/from JSON. Once you have described your contract via an ABI then developers and users will be able to interact with your contract seamlessly via JSON.

{% hint style="info" %}
**SECURITY NOTE**

ABI can be bypassed when executing transactions. Messages and actions passed to a contract do not have to conform to the ABI. The ABI is a guide, not a gatekeeper.
{% endhint %}

### Create an ABI File[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#create-an-abi-file) <a href="#create-an-abi-file" id="create-an-abi-file"></a>

Start with an empty ABI, name it `eosio.token.abi`

```
{
   "version": "eosio::abi/1.0",
   "types": [],
   "structs": [],
   "actions": [],
   "tables": [],
   "ricardian_clauses": [],
   "abi_extensions": [],
   "___comment" : ""
}
```

### Types[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#types) <a href="#types" id="types"></a>

An ABI enables any client or interface to interpret and even generate a GUI for your contract. For this to work consistently, describe the custom types that are used as a parameter in any public action or struct that needs to be described in the ABI.

{% hint style="info" %}
**BUILT-IN TYPES**

EOS implements a number of custom built-ins. Built-in types don't need to be described in an ABI file. If you would like to familiarize yourself with EOS built-ins, they are defined here
{% endhint %}

```
{
   "new_type_name": "name",
   "type": "name"
}
```

The ABI now looks like this:

```
{
   "version": "eosio::abi/1.1",
   "types": [{
     "new_type_name": "name",
     "type": "name"
   }],
   "structs": [],
   "actions": [],
   "tables": [],
   "ricardian_clauses": [],
   "abi_extensions": []
}
```

### Structs[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#structs) <a href="#structs" id="structs"></a>

Structs that are exposed to the ABI also need to be described. By looking at eosio.token.hpp, it can be quickly determined which structs are utilized by public actions. This is particularly important for the next step.

A struct's object definition in JSON looks like the following:

```
{
   "name": "issue", //The name
   "base": "",          //Inheritance, parent struct
   "fields": []         //Array of field objects describing the struct's fields.
}
```

### Fields[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#fields) <a href="#fields" id="fields"></a>

```
{
   "name":"", // The field's name
   "type":""   // The field's type
}
```

In the `eosio.token` contract, there's a number of structs that require definition. Please note, not all of the structs are explicitly defined, some correspond to an actions' parameters. Here's a list of structs that require an ABI description for the `eosio.token` contract:

### Implicit Structs[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#implicit-structs) <a href="#implicit-structs" id="implicit-structs"></a>

The following structs are implicit in that a struct was never explicitly defined in the contract. Looking at the [create](http://docs.eosnetwork.com/reference/mandel-contracts/classeosio_1_1token.html#a5277670549e2458dd4a4fab4c56a9599) action, you'll find two parameters, `issuer` of type `name` and `maximum_supply` of type `asset`. For brevity this tutorial won't break down every struct, but applying the same logic, you will end up with the following:

#### create[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#create) <a href="#create" id="create"></a>

```
{
  "name": "create",
  "base": "",
  "fields": [
    {
      "name":"issuer",
      "type":"name"
    },
    {
      "name":"maximum_supply",
      "type":"asset"
    }
  ]
}
```

#### issue[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#issue) <a href="#issue" id="issue"></a>

```
{
  "name": "issue",
  "base": "",
  "fields": [
    {
      "name":"to",
      "type":"name"
    },
    {
      "name":"quantity",
      "type":"asset"
    },
    {
      "name":"memo",
      "type":"string"
    }
  ]
}
```

#### retire[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#retire) <a href="#retire" id="retire"></a>

```
{
  "name": "retire",
  "base": "",
  "fields": [
    {
      "name":"quantity",
      "type":"asset"
    },
    {
      "name":"memo",
      "type":"string"
    }
  ]
}
```

#### transfer[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#transfer) <a href="#transfer" id="transfer"></a>

```
{
  "name": "transfer",
  "base": "",
  "fields": [
    {
      "name":"from",
      "type":"name"
    },
    {
      "name":"to",
      "type":"name"
    },
    {
      "name":"quantity",
      "type":"asset"
    },
    {
      "name":"memo",
      "type":"string"
    }
  ]
}
```

#### close[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#close) <a href="#close" id="close"></a>

```
{
  "name": "close",
  "base": "",
  "fields": [
    {
      "name":"owner",
      "type":"name"
    },
    {
      "name":"symbol",
      "type":"symbol"
    }
  ]
 }
```

### Explicit Structs[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#explicit-structs) <a href="#explicit-structs" id="explicit-structs"></a>

These structs are explicitly defined, as they are a requirement to instantiate a multi-index table. Describing them is no different than defining the implicit structs as demonstrated above.

#### account[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#account) <a href="#account" id="account"></a>

```
{
  "name": "account",
  "base": "",
  "fields": [
    {
      "name":"balance",
      "type":"asset"
    }
  ]
}
```

### Actions[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#actions) <a href="#actions" id="actions"></a>

An action's JSON object definition looks like the following:

```
{
  "name": "transfer",           //The name of the action as defined in the contract
  "type": "transfer",           //The name of the implicit struct as described in the ABI
  "ricardian_contract": ""  //An optional ricardian clause to associate to this action describing its intended functionality.
}
```

Describe the actions of the `eosio.token` contract by aggregating all the public functions described in the `eosio.token` contract's header file.

Then describe each action's *type* according to its previously described struct. In most situations, the function name and the struct name will be equal, but are not required to be equal.

Below is a list of actions that link to their source code with example JSON provided for how each action would be described.

#### create[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#create-1) <a href="#create-1" id="create-1"></a>

```
{
  "name": "create",
  "type": "create",
  "ricardian_contract": ""
}
```

#### issue[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#issue-1) <a href="#issue-1" id="issue-1"></a>

```
{
  "name": "issue",
  "type": "issue",
  "ricardian_contract": ""
}
```

#### retire[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#retire-1) <a href="#retire-1" id="retire-1"></a>

```
{
  "name": "retire",
  "type": "retire",
  "ricardian_contract": ""
}
```

#### transfer[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#transfer-1) <a href="#transfer-1" id="transfer-1"></a>

```
{
  "name": "transfer",
  "type": "transfer",
  "ricardian_contract": ""
}
```

#### close[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#close-1) <a href="#close-1" id="close-1"></a>

```
{
  "name": "close",
  "type": "close",
  "ricardian_contract": ""
}
```

### Tables[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#tables) <a href="#tables" id="tables"></a>

Here's a table's JSON object definition:

```
{
  "name": "",       //The name of the table, determined during instantiation.
  "type": "",       //The table's corresponding struct
  "index_type": "", //The type of primary index of this table
  "key_names" : [], //An array of key names, length must equal length of key_types member
  "key_types" : []  //An array of key types that correspond to key names array member, length of array must equal length of key names array.
}
```

The eosio.token contract instantiates two tables, accounts and stat.

The `accounts` table is an i64 index, based on the `account` struct, has a `uint64` as it's primary key

Here's how the accounts table would be described in the ABI

```
{
  "name": "accounts",
  "type": "account", // Corresponds to previously defined struct
  "index_type": "i64",
  "key_names" : ["primary_key"],
  "key_types" : ["uint64"]
}
```

The `stat` table is an i64 index, based on the `currency_stats` struct, has a `uint64` as it's primary key

Here's how the stat table would be described in the ABI

```
{
  "name": "stat",
  "type": "currency_stats",
  "index_type": "i64",
  "key_names" : ["primary_key"],
  "key_types" : ["uint64"]
}
```

You'll notice the above tables have the same "key name." Naming your keys similar names is symbolic in that it can potentially suggest a subjective relationship. As with this implementation, implying that any given value can be used to query different tables.

### Putting it all Together[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#putting-it-all-together) <a href="#putting-it-all-together" id="putting-it-all-together"></a>

Finally, an ABI file that accurately describes the `eosio.token` contract.

```
{
  "version": "eosio::abi/1.1",
  "types": [
    {
      "new_type_name": "name",
      "type": "name"
    }
  ],
  "structs": [
    {
      "name": "create",
      "base": "",
      "fields": [
        {
          "name":"issuer",
          "type":"name"
        },
        {
          "name":"maximum_supply",
          "type":"asset"
        }
      ]
    },
    {
       "name": "issue",
       "base": "",
       "fields": [
          {
            "name":"to",
            "type":"name"
          },
          {
            "name":"quantity",
            "type":"asset"
          },
          {
            "name":"memo",
            "type":"string"
          }
       ]
    },
    {
       "name": "retire",
       "base": "",
       "fields": [
          {
            "name":"quantity",
            "type":"asset"
          },
          {
            "name":"memo",
            "type":"string"
          }
       ]
    },
    {
       "name": "close",
       "base": "",
       "fields": [
          {
            "name":"owner",
            "type":"name"
          },
          {
            "name":"symbol",
            "type":"symbol"
          }
       ]
    },
    {
      "name": "transfer",
      "base": "",
      "fields": [
        {
          "name":"from",
          "type":"name"
        },
        {
          "name":"to",
          "type":"name"
        },
        {
          "name":"quantity",
          "type":"asset"
        },
        {
          "name":"memo",
          "type":"string"
        }
      ]
    },
    {
      "name": "account",
      "base": "",
      "fields": [
        {
          "name":"balance",
          "type":"asset"
        }
      ]
    },
    {
      "name": "currency_stats",
      "base": "",
      "fields": [
        {
          "name":"supply",
          "type":"asset"
        },
        {
          "name":"max_supply",
          "type":"asset"
        },
        {
          "name":"issuer",
          "type":"name"
        }
      ]
    }
  ],
  "actions": [
    {
      "name": "transfer",
      "type": "transfer",
      "ricardian_contract": ""
    },
    {
      "name": "issue",
      "type": "issue",
      "ricardian_contract": ""
    },
    {
      "name": "retire",
      "type": "retire",
      "ricardian_contract": ""
    },
    {
      "name": "create",
      "type": "create",
      "ricardian_contract": ""
    },
    {
      "name": "close",
      "type": "close",
      "ricardian_contract": ""
    }
  ],
  "tables": [
    {
      "name": "accounts",
      "type": "account",
      "index_type": "i64",
      "key_names" : ["currency"],
      "key_types" : ["uint64"]
    },
    {
      "name": "stat",
      "type": "currency_stats",
      "index_type": "i64",
      "key_names" : ["currency"],
      "key_types" : ["uint64"]
    }
  ],
  "ricardian_clauses": [],
  "abi_extensions": []
}
```

### Cases not Covered by Token Contract[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#cases-not-covered-by-token-contract) <a href="#cases-not-covered-by-token-contract" id="cases-not-covered-by-token-contract"></a>

#### Vectors[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#vectors) <a href="#vectors" id="vectors"></a>

When describing a vector in your ABI file, simply append the type with `[]`, so if you need to describe a vector of permission levels, you would describe it like so: `permission_level[]`

#### Struct Base[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#struct-base) <a href="#struct-base" id="struct-base"></a>

It's a rarely used property worth mentioning. You can use **base** ABI struct property to reference another struct for inheritance, as long as that struct is also described in the same ABI file. Base will do nothing or potentially throw an error if your smart contract logic does not support inheritance.

You can see an example of base in use in the system contract source code and ABI

#### Extra ABI Properties[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#extra-abi-properties) <a href="#extra-abi-properties" id="extra-abi-properties"></a>

A few properties of the ABI specification were skipped here for brevity, however, there is a pending ABI specification that will outline every property of the ABI in its entirety.

#### Ricardian Clauses[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#ricardian-clauses) <a href="#ricardian-clauses" id="ricardian-clauses"></a>

Ricardian clauses describe the intended outcome of a particular actions. It may also be utilized to establish terms between the sender and the contract.

#### ABI Extensions[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#abi-extensions) <a href="#abi-extensions" id="abi-extensions"></a>

A generic "future proofing" layer that allows old clients to skip the parsing of "chunks" of extension data. For now, this property is unused. In the future each extension would have its own "chunk" in that vector so that older clients skip it and newer clients that understand how to interpret it.

### Maintenance[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#maintenance) <a href="#maintenance" id="maintenance"></a>

Every time you change a struct, add a table, add an action or add parameters to an action, use a new type, you will need to remember to update your ABI file. In many cases forgetting to update your ABI file will not produce any error.

### Troubleshooting[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#troubleshooting) <a href="#troubleshooting" id="troubleshooting"></a>

#### Table returns no rows[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#table-returns-no-rows) <a href="#table-returns-no-rows" id="table-returns-no-rows"></a>

Check that your table is accurately described in the ABI file. For example, If you use `cleos` to add a table on a contract with a malformed ABI definition and then get rows from that table, you will receive an empty result. `cleos` will not produce an error when adding a row nor reading a row when a contract has failed to properly describe its tables in its ABI.

### What's Next[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/understanding-ABI-files#whats-next) <a href="#whats-next" id="whats-next"></a>

* Data Persistence: Learn how data persistence works on VEXANIUM by writing a simple smart contract that functions as an address book.


# Data Persistence

To learn about data persistence, you write a simple smart contract that functions as an address book. While this use case is not very practical as a production smart contract, it is a good contract to start with to learn how data persistence works on EOS without being distracted by business logic that does not pertain to the `multi_index` functionality.

### Step 1: Create a new directory[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#step-1-create-a-new-directory) <a href="#step-1-create-a-new-directory" id="step-1-create-a-new-directory"></a>

Earlier, you created a contract directory, navigate there now.

```
cd CONTRACTS_DIR
```

Create a new directory for our contract and enter the directory

```
mkdir addressbook
cd addressbook
```

### Step 2: Create and open a new file[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#step-2-create-and-open-a-new-file) <a href="#step-2-create-and-open-a-new-file" id="step-2-create-and-open-a-new-file"></a>

```
touch addressbook.cpp
```

Open the file in your favorite editor.

### Step 3: Write an Extended Standard Class[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#step-3-write-an-extended-standard-class) <a href="#step-3-write-an-extended-standard-class" id="step-3-write-an-extended-standard-class"></a>

If you followed the previous tutorial, you created a hello world contract and learned the basics. The code snippet uses a similiar structure with a class named `addressbook`:

```cpp
#include <eosio/eosio.hpp>

using namespace eosio;

class [[eosio::contract("addressbook")]] addressbook : public eosio::contract {
  public:

  private:

};
```

### Step 4: Create The Data Structure for the Table[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#step-4-create-the-data-structure-for-the-table) <a href="#step-4-create-the-data-structure-for-the-table" id="step-4-create-the-data-structure-for-the-table"></a>

Before a table can be configured and instantiated, we need to define a struct that represents the data structure of the address book. The address book will contain people, therefore for this exercise, create the `struct` called "person" in the private section of the "addressbook" class.

```cpp
struct person {};
```

When defining the structure of a multi\_index table, you use a unique value as the primary key.

For this contract, use a field called "key" with type `name` based on the user's `name`. This contract has one unique entry per user, so this key will be a consistent and guaranteed unique value.

```cpp
struct person {
 name key;
};
```

Since this contract is an address book it should store some relevant details for each entry or *person*

```cpp
struct person {
 name key;
 std::string first_name;
 std::string last_name;
 std::string street;
 std::string city;
 std::string state;
};
```

Great. The basic data structure is now complete.

Next, define a `primary_key` method. Every `multi_index` struct requires a *primary key* method. Behind the scenes, this method is used according to the index specification of your `multi_index` instantiation. VEXANIUM `multi_index` wraps boost::multi\_index

Create a method `primary_key()` and return a struct member, in this case, the `key` member as previously discussed.

```cpp
struct person {
 name key;
 std::string first_name;
 std::string last_name;
 std::string street;
 std::string city;
 std::string state;

 uint64_t primary_key() const { return key.value;}
};
```

{% hint style="danger" %}
**DANGER**

A table's data structure cannot be modified while it has data in it. If you need to make changes to a table's data structure in any way, you first need to remove all its rows
{% endhint %}

### Step 5: Configure the Multi-Index Table[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#step-5-configure-the-multi-index-table) <a href="#step-5-configure-the-multi-index-table" id="step-5-configure-the-multi-index-table"></a>

Now that the data structure of the table has been defined with a `struct` we need to configure the table. The eosio::multi\_index constructor needs to be named and configured to use the struct we previously defined.

```cpp
using address_index = eosio::multi_index<"people"_n, person>;
```

With the above `multi_index` configuration there is a table named **people**, that

1. Uses the `_n` operator to define an `eosio::name` type and uses that to name the table. This table contains a number of different singular "persons", so name the table "people".
2. Pass in the singular `person` struct defined in the previous step.
3. Declare this table's type. This type will be used to instantiate this table later.

So far, our file should look like this.

```cpp
#include <eosio/eosio.hpp>

using namespace eosio;

class [[eosio::contract("addressbook")]] addressbook : public eosio::contract {

  public:

  private:
    struct [[eosio::table]] person {
      name key;
      std::string first_name;
      std::string last_name;
      std::string street;
      std::string city;
      std::string state;

      uint64_t primary_key() const { return key.value;}
    };
    
  using address_index = eosio::multi_index<"people"_n, person>;
};
```

### Step 6: The Constructor[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#step-6-the-constructor) <a href="#step-6-the-constructor" id="step-6-the-constructor"></a>

When working with C++ classes, the first public method you should create is a constructor.

Our constructor will be responsible for initially setting up the contract.

VEXANIUM contracts extend the *contract* class. Initialize our parent *contract* class with the code name of the contract and the receiver. The important parameter here is the `code` parameter which is the account on the blockchain that the contract is being deployed to.

```cpp
addressbook(name receiver, name code, datastream<const char*> ds):contract(receiver, code, ds) {}
```

### Step 7: Adding a record to the table[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#step-7-adding-a-record-to-the-table) <a href="#step-7-adding-a-record-to-the-table" id="step-7-adding-a-record-to-the-table"></a>

Previously, the primary key of the multi-index table was defined to enforce that this contract will only store one record per user. To make it all work, some rules about the design need to be established.

1. The only account authorized to modify the address book is the user.
2. The **primary\_key** of our table is unique, based on username
3. For usability, the contract should have the ability to both create and modify a table row with a single action.

On the EOS blockchain an account name is unique, therefore the `name` type is an ideal candidate as a **primary\_key**. Behind the scenes, the name type is an `uint64_t` integer.

Next, define an action for the user to add or update a record. This action will need to accept any values that this action needs to be able to emplace (create) or modify.

For user-experience and interface simplicity, have a single method be responsible for both creation and modification of rows. Because of this behavior, name it "upsert," a combination of "update" and "insert."

```cpp
void upsert(
  name user,
  std::string first_name,
  std::string last_name,
  std::string street,
  std::string city,
  std::string state
) {}
```

Earlier, it was mentioned that only the user has control over their own record, as this contract is opt-in. To do this, utilize the require\_auth method provided by the `cdt`. This method accepts an `name` type argument and asserts that the account executing the transaction equals the provided value and has the proper permissions to do so.

```cpp
void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
  require_auth( user );
}
```

Previously, a multi\_index table was configured, and declared as `address_index`. To instantiate a table, two parameters are required:

1. The first parameter "code", which specifies the owner of this table. As the owner, the account will be charged for storage costs. Also, only that account can modify or delete the data in this table unless another payer is specified. Here we use the `get_self()` function which will pass the name of this contract.
2. The second parameter "scope" which ensures the uniqueness of the table in the scope of this contract. In this case, since we only have one table we can use the value from `get_first_receiver()`. The value returned from the *`get_first_receiver` function is the account name on which this contract is deployed to.*

Note that scopes are used to logically separate tables within a multi-index (see the eosio.token contract multi-index for an example, which scopes the table on the token owner). Scopes were originally intended to separate table state in order to allow for parallel computation on the individual sub-tables. However, currently inter-blockchain communication has been prioritized over parallelism. Because of this, scopes are currently only used to logically separate the tables as in the case of eosio.token.

```cpp
void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
  require_auth( user );
  address_index addresses(get_self(), get_first_receiver().value);
}
```

Next, query the iterator, setting it to a variable since this iterator will be used several times

```cpp
void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
  require_auth( user );
  address_index addresses(get_self(), get_first_receiver().value);
  auto iterator = addresses.find(user.value);
}
```

Security has been established and the table instantiated, great! Next up, write the code for creating or modifying the table.

First, detect whether a particular user already exists in the table. To do this, use table's find method by passing the `user` parameter. The find method will return an iterator. Use that iterator to test it against the [end](http://docs.eosnetwork.com/cdt/latest/reference/Modules/group__multiindex#function-end) method. The "end" method is an alias for "null".

```cpp
void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
  require_auth( user );
  address_index addresses(get_self(), get_first_receiver().value);
  auto iterator = addresses.find(user.value);
  if( iterator == addresses.end() )
  {
    //The user isn't in the table
  }
  else {
    //The user is in the table
  }
}
```

Create a record in the table using the multi\_index method emplace. This method accepts two arguments, the "payer" of this record who pays the storage usage and a callback function.

The callback function for the emplace method must use a lamba function to create a reference. Inside the body assign the row's values with the ones provided to `upsert`.

```cpp
void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
  require_auth( user );
  address_index addresses(get_self(), get_first_receiver().value);
  auto iterator = addresses.find(user.value);
  if( iterator == addresses.end() )
  {
    addresses.emplace(user, [&]( auto& row ) {
      row.key = user;
      row.first_name = first_name;
      row.last_name = last_name;
      row.street = street;
      row.city = city;
      row.state = state;
    });
  }
  else {
    //The user is in the table
  }
}
```

Next, handle the modification, or update, case of the "upsert" function. Use the modify method, passing a few arguments:

* The iterator defined earlier, presently set to the user as declared when calling this action.
* The "payer", who will pay for the storage cost of this row, in this case, the user.
* The callback function that actually modifies the row.

```cpp
void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
  require_auth( user );
  address_index addresses(get_self(), get_first_receiver().value);
  auto iterator = addresses.find(user.value);
  if( iterator == addresses.end() )
  {
    addresses.emplace(user, [&]( auto& row ) {
      row.key = user;
      row.first_name = first_name;
      row.last_name = last_name;
      row.street = street;
      row.city = city;
      row.state = state;
    });
  }
  else {
    addresses.modify(iterator, user, [&]( auto& row ) {
      row.first_name = first_name;
      row.last_name = last_name;
      row.street = street;
      row.city = city;
      row.state = state;
    });
  }
}
```

The `addressbook` contract now has a functional action that will enable a user to create a row in the table if that record does not yet exist, and modify it if it already exists.

But what if the user wants to remove the record entirely?

### Step 8: Remove record from the table[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#step-8-remove-record-from-the-table) <a href="#step-8-remove-record-from-the-table" id="step-8-remove-record-from-the-table"></a>

Similar to the previous steps, create a public method in the `addressbook`, making sure to include the ABI declarations and a require\_auth that tests against the action's argument `user` to verify only the owner of a record can modify their account.

```cpp
    void erase(name user){
      require_auth(user);
    }

```

Instantiate the table. In `addressbook` each account has only one record. Set `iterator` with find

```cpp
...
    void erase(name user){
      require_auth(user);
      address_index addresses(get_self(), get_first_receiver().value);
      auto iterator = addresses.find(user.value);
    }
...
```

A contract *cannot* erase a record that doesn't exist, so check that the record indeed exists before proceeding.

```cpp
...
    void erase(name user){
      require_auth(user);
      address_index addresses(get_self(), get_first_receiver().value);
      auto iterator = addresses.find(user.value);
      check(iterator != addresses.end(), "Record does not exist");
    }
...
```

Finally, call the erase method, to erase the iterator. Once the row is erased, the storage space will be free up for the original payer.

```cpp
...
  void erase(name user) {
    require_auth(user);
    address_index addresses(get_self(), get_first_receiver().value);
    auto iterator = addresses.find(user.value);
    check(iterator != addresses.end(), "Record does not exist");
    addresses.erase(iterator);
  }
...
```

The contract is now mostly complete. Users can create, modify and erase records. However, the contract is not quite ready to be compiled.

### Step 9: Preparing for the ABI[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#step-9-preparing-for-the-abi) <a href="#step-9-preparing-for-the-abi" id="step-9-preparing-for-the-abi"></a>

#### 9.1 ABI Action Declarations[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#91-abi-action-declarations) <a href="#id-91-abi-action-declarations" id="id-91-abi-action-declarations"></a>

eosio.cdt includes an ABI Generator, but for it to work will require some declarations.

Above both the `upsert` and `erase` functions add the following C++11 declaration:

```
[[eosio::action]]
```

The above declaration will extract the arguments of the action and create necessary ABI *struct* descriptions in the generated ABI file.

#### 9.2 ABI Table Declarations[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#92-abi-table-declarations) <a href="#id-92-abi-table-declarations" id="id-92-abi-table-declarations"></a>

Add an ABI declaration to the table. Modify the following line defined in the private region of your contract:

```cpp
struct person {
```

To this:

```cpp
struct [[eosio::table]] person {
```

The `[[eosio.table]]` declaration will add the necessary descriptions to the ABI file.

Now our contract is ready to be compiled.

Below is the final state of our `addressbook` contract:

```cpp
#include <eosio/eosio.hpp>

using namespace eosio;

class [[eosio::contract("addressbook")]] addressbook : public eosio::contract {

public:

  addressbook(name receiver, name code,  datastream<const char*> ds): contract(receiver, code, ds) {}

  [[eosio::action]]
  void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
    require_auth( user );
    address_index addresses( get_self(), get_first_receiver().value );
    auto iterator = addresses.find(user.value);
    if( iterator == addresses.end() )
    {
      addresses.emplace(user, [&]( auto& row ) {
       row.key = user;
       row.first_name = first_name;
       row.last_name = last_name;
       row.street = street;
       row.city = city;
       row.state = state;
      });
    }
    else {
      addresses.modify(iterator, user, [&]( auto& row ) {
        row.key = user;
        row.first_name = first_name;
        row.last_name = last_name;
        row.street = street;
        row.city = city;
        row.state = state;
      });
    }
  }

  [[eosio::action]]
  void erase(name user) {
    require_auth(user);

    address_index addresses( get_self(), get_first_receiver().value);

    auto iterator = addresses.find(user.value);
    check(iterator != addresses.end(), "Record does not exist");
    addresses.erase(iterator);
  }

private:
  struct [[eosio::table]] person {
    name key;
    std::string first_name;
    std::string last_name;
    std::string street;
    std::string city;
    std::string state;
    uint64_t primary_key() const { return key.value; }
  };
  using address_index = eosio::multi_index<"people"_n, person>;
};    
```

### Step 10 Prepare the Ricardian Contract \[Optional][​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#step-10-prepare-the-ricardian-contract-optional) <a href="#step-10-prepare-the-ricardian-contract-optional" id="step-10-prepare-the-ricardian-contract-optional"></a>

Contracts compiled without a Ricardian contract will generate a compiler warning for each action missing an entry in the Ricardian clause.

```
Warning, action <upsert> does not have a ricardian contract
Warning, action <erase> does not have a ricardian contract
```

To define Ricardian contracts for this smart contract, create a new file called addressbook.contracts.md. Notice that the name of the Ricardian contracts must match the name of the smart contract.

```
touch addressbook.contracts.md
```

Add Ricardian Contract definitions to this file:

```
<h1 class="contract">upsert</h1>
---
spec-version: 0.0.2
title: Upsert
summary: This action will either insert or update an entry in the address book. If an entry exists with the same name as the specified user parameter, the record is updated with the first_name, last_name, street, city, and state parameters. If a record does not exist, a new record is created. The data is stored in the multi index table. The ram costs are paid by the smart contract.
icon:

<h1 class="contract">erase</h1>
---
spec-version: 0.0.2
title: Erase
summary: This action will remove an entry from the address book if an entry in the multi index table exists with the specified name.
icon:
```

### Step 11 Prepare the Ricardian Clauses \[Optional][​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#step-11-prepare-the-ricardian-clauses-optional) <a href="#step-11-prepare-the-ricardian-clauses-optional" id="step-11-prepare-the-ricardian-clauses-optional"></a>

To define Ricardian clauses for this smart contract create and open a new file called addressbook.clauses.md. Notice again that the name of the Ricardian clauses must match the name of the smart contract.

```
touch addressbook.clauses.md
```

Add Ricardian clause definitions to this file:

```
<h1 class="clause">Data Storage</h1>
---
spec-version: 0.0.1
title: General Data Storage
summary: This smart contract will store data added by the user. The user consents to the storage of this data by signing the transaction.
icon:


<h1 class="clause">Data Usage</h1>
---
spec-version: 0.0.1
title: General Data Use
summary: This smart contract will store user data. The smart contract will not use the stored data for any purpose outside store and delete.
icon:

<h1 class="clause">Data Ownership</h1>
---
spec-version: 0.0.1
title: Data Ownership
summary: The user of this smart contract verifies that the data is owned by the smart contract, and that the smart contract can use the data in accordance to the terms defined in the Ricardian Contract.
icon:

<h1 class="clause">Data Distribution</h1>
---
spec-version: 0.0.1
title: Data Distribution
summary: The smart contract promises to not actively share or distribute the address data. The user of the smart contract understands that data stored in a multi index table is not private data and can be accessed by any user of the blockchain.  
icon:


<h1 class="clause">Data Future</h1>
---
spec-version: 0.0.1
title: Data Future
summary: The smart contract promises to only use the data in accordance of the terms defined in the Ricardian Contract, now and at all future dates.
icon:

```

### Step 12: Compile the Contract[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#step-12-compile-the-contract) <a href="#step-12-compile-the-contract" id="step-12-compile-the-contract"></a>

Execute the following command from your terminal.

```
eosio-cpp addressbook.cpp -o addressbook.wasm
```

If you created a Ricardian contract and Ricardian clauses, the definitions will appear in the .abi file. An example for the addressbook.cpp, built including the contract and clause definitions described above is shown below.

```
{
    "____comment": "This file was generated with eosio-abigen. DO NOT EDIT ",
    "version": "eosio::abi/1.1",
    "types": [],
    "structs": [
        {
            "name": "erase",
            "base": "",
            "fields": [
                {
                    "name": "user",
                    "type": "name"
                }
            ]
        },
        {
            "name": "person",
            "base": "",
            "fields": [
                {
                    "name": "key",
                    "type": "name"
                },
                {
                    "name": "first_name",
                    "type": "string"
                },
                {
                    "name": "last_name",
                    "type": "string"
                },
                {
                    "name": "street",
                    "type": "string"
                },
                {
                    "name": "city",
                    "type": "string"
                },
                {
                    "name": "state",
                    "type": "string"
                }
            ]
        },
        {
            "name": "upsert",
            "base": "",
            "fields": [
                {
                    "name": "user",
                    "type": "name"
                },
                {
                    "name": "first_name",
                    "type": "string"
                },
                {
                    "name": "last_name",
                    "type": "string"
                },
                {
                    "name": "street",
                    "type": "string"
                },
                {
                    "name": "city",
                    "type": "string"
                },
                {
                    "name": "state",
                    "type": "string"
                }
            ]
        }
    ],
    "actions": [
        {
            "name": "erase",
            "type": "erase",
            "ricardian_contract": "---\nspec-version: 0.0.2\ntitle: Erase\nsummary: his action will remove an entry from the address book if an entry exists with the same name \nicon:"
        },
        {
            "name": "upsert",
            "type": "upsert",
            "ricardian_contract": "---\nspec-version: 0.0.2\ntitle: Upsert\nsummary: This action will either insert or update an entry in the address book. If an entry exists with the same name as the user parameter the record is updated with the first_name, last_name, street, city and state parameters. If a record does not exist a new record is created. The data is stored in the multi index table. The ram costs are paid by the smart contract.\nicon:"
        }
    ],
    "tables": [
        {
            "name": "people",
            "type": "person",
            "index_type": "i64",
            "key_names": [],
            "key_types": []
        }
    ],
    "ricardian_clauses": [
        {
            "id": "Data Storage",
            "body": "---\nspec-version: 0.0.1\ntitle: General data Storage\nsummary: This smart contract will store data added by the user. The user verifies they are happy for this data to be stored.\nicon:"
        },
        {
            "id": "Data Usage",
            "body": "---\nspec-version: 0.0.1\ntitle: General data Use\nsummary: This smart contract will store user data. The smart contract will not use the stored data for any purpose outside store and delete \nicon:"
        },
        {
            "id": "Data Ownership",
            "body": "---\nspec-version: 0.0.1\ntitle: Data Ownership\nsummary: The user of this smart contract verifies that the data is owned by the smart contract, and that the smart contract can use the data in accordance to the terms defined in the Ricardian Contract \nicon:"
        },
        {
            "id": "Data Distirbution",
            "body": "---\nspec-version: 0.0.1\ntitle: Data Ownership\nsummary: The smart contract promises to not actively share or distribute the address data. The user of the smart contract understands that data stored in a multi index table is not private data and can be accessed by any user of the blockchain.  \nicon:"
        },
        {
            "id": "Data Future",
            "body": "---\nspec-version: 0.0.1\ntitle: Data Ownership\nsummary: The smart contract promises to only use the data in accordance to the terms defined in the Ricardian Contract, now and at all future dates. \nicon:"
        }
    ],
    "variants": []
}
```

### Step 13: Deploy the Contract[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#step-13-deploy-the-contract) <a href="#step-13-deploy-the-contract" id="step-13-deploy-the-contract"></a>

Create an account for the contract, execute the following shell command

```
cleos create account eosio addressbook YOUR_PUBLIC_KEY -p eosio@active
```

Deploy the `addressbook` contract

```
cleos set contract addressbook CONTRACTS_DIR/addressbook -p addressbook@active
```

```
5f78f9aea400783342b41a989b1b4821ffca006cd76ead38ebdf97428559daa0  5152 bytes  727 us
#         eosio <= eosio::setcode               {"account":"addressbook","vmtype":0,"vmversion":0,"code":"0061736d010000000191011760077f7e7f7f7f7f7f...
#         eosio <= eosio::setabi                {"account":"addressbook","abi":"0e656f73696f3a3a6162692f312e30010c6163636f756e745f6e616d65046e616d65...
warning: transaction executed locally, but may not be confirmed by the network yet    ]
```

### Step 14: Test the Contract[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#step-14-test-the-contract) <a href="#step-14-test-the-contract" id="step-14-test-the-contract"></a>

Add a row to the table

```
cleos push action addressbook upsert '["alice", "alice", "liddell", "123 drink me way", "wonderland", "amsterdam"]' -p alice@active
```

```
executed transaction: 003f787824c7823b2cc8210f34daed592c2cfa66cbbfd4b904308b0dfeb0c811  152 bytes  692 us
#   addressbook <= addressbook::upsert          {"user":"alice","first_name":"alice","last_name":"liddell","street":"123 drink me way","city":"wonde...
```

Check that **alice** cannot add records for another user.

```
cleos push action addressbook upsert '["bob", "bob", "is a loser", "doesnt exist", "somewhere", "someplace"]' -p alice@active
```

As expected, the `require_auth` in our contract prevented alice from creating/modifying another user's row.

```
Error 3090004: Missing required authority
Ensure that you have the related authority inside your transaction!;
If you are currently using 'cleos push action' command, try to add the relevant authority using -p option.
Error Details:
missing authority of bob
```

Retrieve alice's record.

```
cleos get table addressbook addressbook people --lower alice --limit 1
```

```
{
  "rows": [{
      "key": "alice",
      "first_name": "alice",
      "last_name": "liddell",
      "street": "123 drink me way",
      "city": "wonderland",
      "state": "amsterdam"
    }
  ],
  "more": false,
  "next_key": ""
}
```

Test to see that **alice** can remove the record.

```
cleos push action addressbook erase '["alice"]' -p alice@active
```

```
executed transaction: 0a690e21f259bb4e37242cdb57d768a49a95e39a83749a02bced652ac4b3f4ed  104 bytes  1623 us
#   addressbook <= addressbook::erase           {"user":"alice"}
warning: transaction executed locally, but may not be confirmed by the network yet    ]
```

Check that the record was removed:

```
cleos get table addressbook addressbook people --lower alice --limit 1
```

```
{
  "rows": [],
  "more": false，
  "next_key": ""
}
```

Looking good!

### Wrapping Up[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#wrapping-up) <a href="#wrapping-up" id="wrapping-up"></a>

You've learned how to configure tables, instantiate tables, create new rows, modify existing rows and work with iterators. You've learned how to test against an empty iterator result. Congrats!

### What's Next?[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/data-persistence#whats-next) <a href="#whats-next" id="whats-next"></a>

* Secondary Indices: Learn how to add another index to the `addressbook` contract that you created in the preceding **Data Persistence** section.


# Secondary Indices

VEXANIUM has the ability to sort tables by up to 16 indices. In the following section, we're going to add another index to the `addressbook` contract, so we can iterate through the records in a different way.

### Step 1: Remove existing data from table[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/secondary-indices#step-1-remove-existing-data-from-table) <a href="#step-1-remove-existing-data-from-table" id="step-1-remove-existing-data-from-table"></a>

As mentioned earlier, *a table's struct cannot be modified when it contains data.* This first step allows the removal of the data already added.

Remove all records of alice and bob that were added in previous tutorial.

```
cleos push action addressbook erase '["alice"]' -p alice@active
```

```
cleos push action addressbook erase '["bob"]' -p bob@active
```

### Step 2: Add new index member and getter[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/secondary-indices#step-2-add-new-index-member-and-getter) <a href="#step-2-add-new-index-member-and-getter" id="step-2-add-new-index-member-and-getter"></a>

Add a new member variable and its getter to the `addressbook.cpp` contract. Since the secondary index needs to be numeric field, a `uint64_t` age variable is added.

```cpp
uint64_t age;
uint64_t get_secondary_1() const { return age;}
```

### Step 3: Add secondary index to `addresses` table configuration[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/secondary-indices#step-3-add-secondary-index-to-addresses-table-configuration) <a href="#step-3-add-secondary-index-to-addresses-table-configuration" id="step-3-add-secondary-index-to-addresses-table-configuration"></a>

A field has been defined as the secondary index, next the `address_index` table needs to be reconfigured.

```cpp
using address_index = eosio::multi_index<"people"_n, person,
indexed_by<"byage"_n, const_mem_fun<person, uint64_t, &person::get_secondary_1>>
>;
```

In the third parameter, we pass a `indexed_by` struct which is used to instantiate a index.

In that `indexed_by` struct, we specify the name of index as `"byage"` and the second type parameter as a function call operator which extracts a const value as an index key. In this case, we point it to the getter we created earlier so this multiple index table will index records by the `age` variable.

```
indexed_by<"byage"_n, const_mem_fun<person, uint64_t, &person::get_secondary_1>>

```

### Step 4: Modify code[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/secondary-indices#step-4-modify-code) <a href="#step-4-modify-code" id="step-4-modify-code"></a>

With all the changes in previous steps, we can now update the `upsert` function. Change the function parameter list to the following:

```cpp
void upsert(name user, std::string first_name, std::string last_name, uint64_t age, std::string street, std::string city, std::string state)
```

Add additional lines to update `age` field in `upsert` function as the following:

```cpp
void upsert(name user, std::string first_name, std::string last_name, uint64_t age, std::string street, std::string city, std::string state) {
  require_auth( user );
  address_index addresses( get_first_receiver(), get_first_receiver().value);
  auto iterator = addresses.find(user.value);
  if( iterator == addresses.end() )
  {
    addresses.emplace(user, [&]( auto& row ) {
      row.key = user;
      row.first_name = first_name;
      row.last_name = last_name;
      // -- Add code below --
      row.age = age;
      row.street = street;
      row.city = city;
      row.state = state;
    });
  }
  else {
    addresses.modify(iterator, user, [&]( auto& row ) {
      row.key = user;
      row.first_name = first_name;
      row.last_name = last_name;
      // -- Add code below --
      row.age = age;
      row.street = street;
      row.city = city;
      row.state = state;
    });
  }
}
```

### Step 5: Compile and Deploy[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/secondary-indices#step-5-compile-and-deploy) <a href="#step-5-compile-and-deploy" id="step-5-compile-and-deploy"></a>

Compile

```
eosio-cpp --abigen addressbook.cpp -o addressbook.wasm
```

Deploy

```sh
cleos set contract addressbook CONTRACTS_DIR/addressbook
```

### Step 6: Test it[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/secondary-indices#step-6-test-it) <a href="#step-6-test-it" id="step-6-test-it"></a>

Insert records

```
cleos push action addressbook upsert '["alice", "alice", "liddell", 9, "123 drink me way", "wonderland", "amsterdam"]' -p alice@active
```

```
cleos push action addressbook upsert '["bob", "bob", "is a guy", 49, "doesnt exist", "somewhere", "someplace"]' -p bob@active
```

Look up alice's address by the age index. Here the `--index 2` parameter is used to indicate that the query applies to the secondary index

```
cleos get table addressbook addressbook people --upper 10 \
--key-type i64 \
--index 2
```

You should see something like the following

```
{
  "rows": [{
      "key": "alice",
      "first_name": "alice",
      "last_name": "liddell",
      "age": 9,
      "street": "123 drink me way",
      "city": "wonderland",
      "state": "amsterdam"
    }
  ],
  "more": false,
  "next_key": ""
}
```

Look it up by Bob's age

```
cleos get table addressbook addressbook people --upper 50 --key-type i64 --index 2
```

It should return

```
{
  "rows": [{
      "key": "alice",
      "first_name": "alice",
      "last_name": "liddell",
      "age": 9,
      "street": "123 drink me way",
      "city": "wonderland",
      "state": "amsterdam"
    },{
      "key": "bob",
      "first_name": "bob",
      "last_name": "is a guy",
      "age": 49,
      "street": "doesnt exist",
      "city": "somewhere",
      "state": "someplace"
    }
  ],
  "more": false
}
```

### Wrapping Up[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/secondary-indices#wrapping-up) <a href="#wrapping-up" id="wrapping-up"></a>

The complete `addressbook` contract up to this point:

```cpp
#include <eosio/eosio.hpp>
#include <eosio/print.hpp>

using namespace eosio;

class [[eosio::contract("addressbook")]] addressbook : public eosio::contract {

public:

  addressbook(name receiver, name code,  datastream<const char*> ds): contract(receiver, code, ds) {}

  [[eosio::action]]
  void upsert(name user, std::string first_name, std::string last_name, uint64_t age, std::string street, std::string city, std::string state) {
    require_auth( user );
    address_index addresses(get_first_receiver(),get_first_receiver().value);
    auto iterator = addresses.find(user.value);
    if( iterator == addresses.end() )
    {
      addresses.emplace(user, [&]( auto& row ) {
       row.key = user;
       row.first_name = first_name;
       row.last_name = last_name;
       row.age = age;
       row.street = street;
       row.city = city;
       row.state = state;
      });
    }
    else {
      addresses.modify(iterator, user, [&]( auto& row ) {
        row.key = user;
        row.first_name = first_name;
        row.last_name = last_name;
        row.age = age;
        row.street = street;
        row.city = city;
        row.state = state;
      });
    }
  }

  [[eosio::action]]
  void erase(name user) {
    require_auth(user);

    address_index addresses(get_self(), get_first_receiver().value);

    auto iterator = addresses.find(user.value);
    check(iterator != addresses.end(), "Record does not exist");
    addresses.erase(iterator);
  }

private:
  struct [[eosio::table]] person {
    name key;
    std::string first_name;
    std::string last_name;
    uint64_t age;
    std::string street;
    std::string city;
    std::string state;

    uint64_t primary_key() const { return key.value; }
    uint64_t get_secondary_1() const { return age; }

  };

  using address_index = eosio::multi_index<"people"_n, person, indexed_by<"byage"_n, const_mem_fun<person, uint64_t, &person::get_secondary_1>>>;

};
```

### What's Next?[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/secondary-indices#whats-next) <a href="#whats-next" id="whats-next"></a>

* [Adding Inline Actions](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/adding-inline-actions): Learn how to construct actions and send those actions from within a contract.


# Adding Inline Actions

### Introduction[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/adding-inline-actions#introduction) <a href="#introduction" id="introduction"></a>

It was previously demonstrated by authoring the `addressbook` contract the basics of multi-index tables. In this part of the series you'll learn how to construct actions, and send those actions from within a contract.

### Step 1: Adding eosio.code to permissions[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/adding-inline-actions#step-1-adding-eosiocode-to-permissions) <a href="#step-1-adding-eosiocode-to-permissions" id="step-1-adding-eosiocode-to-permissions"></a>

In order for the inline actions to be sent from `addressbook`, add the `eosio.code` permission to the contract's account's active permission. Open your terminal and run the following code:

```
cleos set account permission addressbook active --add-code
```

The `eosio.code` authority is a pseudo authority implemented to enhance security, and enable contracts to execute inline actions.

### Step 2: Notify Action[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/adding-inline-actions#step-2-notify-action) <a href="#step-2-notify-action" id="step-2-notify-action"></a>

If not still opened, open the `addressbook.cpp` contract authored in the last tutorial. Write an action that dispatches a "transaction receipt" whenever a transaction occurs. To do this, create a helper function in the `addressbook` class.

```cpp
[[eosio::action]]
void notify(name user, std::string msg) {}
```

This function is very simple, it just accepts a user account as a `name` type and a message as a `string` type. The user parameter dictates which user gets the message that is sent.

### Step 3: Copy action to sender using require\_recipient[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/adding-inline-actions#step-3-copy-action-to-sender-using-require_recipient) <a href="#step-3-copy-action-to-sender-using-require_recipient" id="step-3-copy-action-to-sender-using-require_recipient"></a>

This transaction needs to be copied to the user so it can be considered as a receipt. To do this, use the require\_recipient method. Calling `require_recipient` adds an account to the require\_recipient set and ensures that these accounts receive a notification of the action being executed. The notification is like sending a "carbon copy" of the action to the accounts in the require\_recipient set.

```
  [[eosio::action]]
  void notify(name user, std::string msg) {
   require_recipient(user);
  }
```

This action is very simple, however, as written, any user could call this function, and "fake" a receipt from this contract. This could be used in malicious ways, and should be seen as a vulnerability. To correct this, require that the authorization provided in the call to this action is from the contract itself, for this, use get\_self

```cpp
  [[eosio::action]]
  void notify(name user, std::string msg) {
    require_auth(get_self());
    require_recipient(user);
  }
```

Now if user `bob` calls this function directly, but passes the parameter `alice` the action will throw an exception.

### Step 4: Notify helper for sending inline transactions[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/adding-inline-actions#step-4-notify-helper-for-sending-inline-transactions) <a href="#step-4-notify-helper-for-sending-inline-transactions" id="step-4-notify-helper-for-sending-inline-transactions"></a>

Since this inline action will be called several times, write a quick helper for maximum code reuse. In the private region of your contract, define a new method.

```cpp
...
  private:
    void send_summary(name user, std::string message){}
```

Inside of this helper construct an action and send it.

### Step 5: The Action Constructor[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/adding-inline-actions#step-5-the-action-constructor) <a href="#step-5-the-action-constructor" id="step-5-the-action-constructor"></a>

Modify the `addressbook` contract to send a receipt to the user every time they take an action on the contract.

To begin, address the "create record" case. This is the case that fires when a record is not found in the table, i.e., when `iterator == addresses.end()` is `true`.

Save this object to an `action` variable called `notification`

```cpp
...
  private:
    void send_summary(name user, std::string message){
      action(
        //permission_level,
        //code,
        //action,
        //data
      );   
    }
```

The action constructor requires a number of parameters:

* A permission\_level struct
* The contract to call (initialised using `eosio::name` type)
* The action (initialised using `eosio::name` type)
* The data to pass to the action, a tuple of positionals that correlate to the actions being called.

### The Permission struct[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/adding-inline-actions#the-permission-struct) <a href="#the-permission-struct" id="the-permission-struct"></a>

In this contract the permission should be authorized by the `active` authority of the contract using `get_self()`. As a reminder, to use the `active` authority inline you will need your contract's to give active authority to `eosio.code` pseudo-authority (instructions above)

```cpp
...
  private:
    void send_summary(name user, std::string message){
      action(
        permission_level{get_self(),"active"_n},
      );
    }
```

### The "code" AKA "account where contract is deployed"[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/adding-inline-actions#the-code-aka-account-where-contract-is-deployed) <a href="#the-code-aka-account-where-contract-is-deployed" id="the-code-aka-account-where-contract-is-deployed"></a>

Since the action called is in this contract, use get\_self. `"addressbook"_n` would also work here, but if this contract were deployed under a different account name, it wouldn't work. Because of this, `get_self()` is the superior option.

```cpp
...
  private:
    void send_summary(name user, std::string message){
      action(
        permission_level{get_self(),"active"_n},
        get_self(),
        //action
        //data
      );
    }
```

### The action[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/adding-inline-actions#the-action) <a href="#the-action" id="the-action"></a>

The `notify` action was previously defined to be called from this inline action. Use the \_n operator here.

```cpp
...
  private:
    void send_summary(name user, std::string message){
      action(
        permission_level{get_self(),"active"_n},
        get_self(),
        "notify"_n,
        //data
      );
    }
```

### The Data[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/adding-inline-actions#the-data) <a href="#the-data" id="the-data"></a>

Finally, define the data to pass to this action. The notify function accepts two parameters, an `name` and a `string`. The action constructor expects data as type `bytes`, so use `make_tuple`, a function available through `std` C++ library. Data passed in the tuple is positional, and determined by the order of the parameters accepted by the action that being called.

* Pass the `user` variable that is provided as a parameter of the `upsert()` action.
* Concatenate a string that includes the name of the user, and include the `message` to pass to the `notify` action.

```cpp
...
  private:
    void send_summary(name user, std::string message){
      action(
        permission_level{get_self(),"active"_n},
        get_self(),
        "notify"_n,
        std::make_tuple(user, name{user}.to_string() + message)
      );
    }
```

### Send the action.[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/adding-inline-actions#send-the-action) <a href="#send-the-action" id="send-the-action"></a>

Finally, send the action using the `send` method of the action struct.

```cpp
...
  private:
    void send_summary(name user, std::string message) {
      action(
        permission_level{get_self(),"active"_n},
        get_self(),
        "notify"_n,
        std::make_tuple(user, name{user}.to_string() + message)
      ).send();
    }
```

### Step 6: Call the helper and inject relevant messages[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/adding-inline-actions#step-6-call-the-helper-and-inject-relevant-messages) <a href="#step-6-call-the-helper-and-inject-relevant-messages" id="step-6-call-the-helper-and-inject-relevant-messages"></a>

Now that the helper is defined, it should probably be called from the relevant locations. There's three specific places for the new `notify` helper to be called from:

* After the contract `emplaces` a new record: `send_summary(user, "successfully emplaced record to addressbook");`
* After the contract `modifies` an existing record: `send_summary(user, "successfully modified record in addressbook.");`
* After the contract `erases` an existing record: `send_summary(user, "successfully erased record from addressbook");`

### Step 7: Recompile and Regenerate the ABI File[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/adding-inline-actions#step-7-recompile-and-regenerate-the-abi-file) <a href="#step-7-recompile-and-regenerate-the-abi-file" id="step-7-recompile-and-regenerate-the-abi-file"></a>

Now that everything is in place, here's the current state of the `addressbook` contract:

```cpp
#include <eosio/eosio.hpp>
#include <eosio/print.hpp>

using namespace eosio;

class [[eosio::contract("addressbook")]] addressbook : public eosio::contract {

public:

  addressbook(name receiver, name code,  datastream<const char*> ds): contract(receiver, code, ds) {}

  [[eosio::action]]
  void upsert(name user, std::string first_name, std::string last_name, uint64_t age, std::string street, std::string city, std::string state) {
    require_auth(user);
    address_index addresses(get_first_receiver(), get_first_receiver().value);
    auto iterator = addresses.find(user.value);
    if( iterator == addresses.end() )
    {
      addresses.emplace(user, [&]( auto& row ) {
       row.key = user;
       row.first_name = first_name;
       row.last_name = last_name;
       row.age = age;
       row.street = street;
       row.city = city;
       row.state = state;
      });
      send_summary(user, " successfully emplaced record to addressbook");
    }
    else {
      addresses.modify(iterator, user, [&]( auto& row ) {
        row.key = user;
        row.first_name = first_name;
        row.last_name = last_name;
        row.street = street;
        row.city = city;
        row.state = state;
      });
      send_summary(user, " successfully modified record to addressbook");
    }
  }

  [[eosio::action]]
  void erase(name user) {
    require_auth(user);

    address_index addresses(get_first_receiver(), get_first_receiver().value);

    auto iterator = addresses.find(user.value);
    check(iterator != addresses.end(), "Record does not exist");
    addresses.erase(iterator);
    send_summary(user, " successfully erased record from addressbook");
  }

  [[eosio::action]]
  void notify(name user, std::string msg) {
    require_auth(get_self());
    require_recipient(user);
  }

private:
  struct [[eosio::table]] person {
    name key;
    std::string first_name;
    std::string last_name;
    uint64_t age;
    std::string street;
    std::string city;
    std::string state;

    uint64_t primary_key() const { return key.value; }
    uint64_t get_secondary_1() const { return age;}
  };

  void send_summary(name user, std::string message) {
    action(
      permission_level{get_self(),"active"_n},
      get_self(),
      "notify"_n,
      std::make_tuple(user, name{user}.to_string() + message)
    ).send();
  };

  typedef eosio::multi_index<"people"_n, person,
    indexed_by<"byage"_n, const_mem_fun<person, uint64_t, &person::get_secondary_1>>
  > address_index;
};
```

Open your terminal, and navigate to `CONTRACTS_DIR/addressbook`

```
cd CONTRACTS_DIR/addressbook
```

Now, recompile the contract, including the `--abigen` flag since changes have been made to the contract that affects the ABI. If you've followed the instructions carefully, you shouldn't see any errors.

```
cdt-cpp -o addressbook.wasm addressbook.cpp --abigen
```

Smart contracts on EOS are upgradeable so the contract can be redeployed with changes.

```
cleos set contract addressbook CONTRACTS_DIR/addressbook
```

```
Publishing contract...
executed transaction: 1898d22d994c97824228b24a1741ca3bd5c7bc2eba9fea8e83446d78bfb264fd  7320 bytes  747 us
#         eosio <= eosio::setcode               {"account":"addressbook","vmtype":0,"vmversion":0,"code":"0061736d0100000001a6011a60027f7e0060077f7e...
#         eosio <= eosio::setabi                {"account":"addressbook","abi":"0e656f73696f3a3a6162692f312e30010c6163636f756e745f6e616d65046e616d65...
```

Success!

### Step 8: Testing it[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/adding-inline-actions#step-8-testing-it) <a href="#step-8-testing-it" id="step-8-testing-it"></a>

Now that the contract has been modified and deployed, test it. In the previous tutorial, alice's addressbook record was deleted during the testing steps, so calling `upsert` will fire the inline action just written inside of the "create" case.

Run the following command in your terminal:

```
cleos push action addressbook upsert '["alice", "alice", "liddell", 21, "123 drink me way", "wonderland", "amsterdam"]' -p alice@active
```

`cleos` will return some data, that includes all the actions executed in the transaction

```
executed transaction: e9e30524186bb6501cf490ceb744fe50654eb393ce0dd733f3bb6c68ff4b5622  160 bytes  9810 us
#   addressbook <= addressbook::upsert          {"user":"alice","first_name":"alice","last_name":"liddell","age":21,"street":"123 drink me way","cit...
#   addressbook <= addressbook::notify          {"user":"alice","msg":"alicesuccessfully emplaced record to addressbook"}
#         alice <= addressbook::notify          {"user":"alice","msg":"alicesuccessfully emplaced record to addressbook"}
```

The last entry in the previous log is an `addressbook::notify` action sent to `alice`. Use [cleos get actions](http://docs.eosnetwork.com/leap/latest/cleos/command-reference/get/actions) to display actions executed and relevant to alice.

```
cleos get actions alice
```

```
#  seq  when                              contract::action => receiver      trx id...   args
================================================================================================================
#   62   2018-09-15T12:57:09.000       addressbook::notify => alice         685ecc09... {"user":"alice","msg":"alice successfully added record to ad...
```

### What's Next?[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/adding-inline-actions#whats-next) <a href="#whats-next" id="whats-next"></a>

* Inline Actions to External Contracts: Learn how to construct actions and send those actions to an external contract.


# Inline Actions to External Contracts

Previously, we sent an inline action to an action that was defined in the contract. In this part of the tutorial, we'll explore sending actions to an external contract. Since we've already gone over quite a bit of contract authoring, we'll keep this contract extremely simple. We'll author a contract that counts actions written by the contract. This contract has very little real-world use, but will demonstrate inline action calls to an external contract

### Step 1: The Addressbook Counter Contract[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/inline-action-to-external-contract#step-1-the-addressbook-counter-contract) <a href="#step-1-the-addressbook-counter-contract" id="step-1-the-addressbook-counter-contract"></a>

Navigate to `CONTRACTS_DIR` if not already there, create a directory called `abcounter` and then create a `abcounter.cpp` file

```
cd CONTRACTS_DIR
mkdir abcounter
cd abcounter
touch abcounter.cpp
```

Open the `abcounter.cpp` file in your favorite editor and paste the following code into the file. This contract is very basic, and for the most part does not cover much that we haven't already covered up until this point. There are a few exceptions though, and they are covered in full below.

```cpp
#include <eosio/eosio.hpp>

using namespace eosio;

class [[eosio::contract("abcounter")]] abcounter : public eosio::contract {
  public:

    abcounter(name receiver, name code,  datastream<const char*> ds): contract(receiver, code, ds) {}

    [[eosio::action]]
    void count(name user, std::string type) {
      require_auth( name("addressbook"));
      count_index counts(get_first_receiver(), get_first_receiver().value);
      auto iterator = counts.find(user.value);

      if (iterator == counts.end()) {
        counts.emplace("addressbook"_n, [&]( auto& row ) {
          row.key = user;
          row.emplaced = (type == "emplace") ? 1 : 0;
          row.modified = (type == "modify") ? 1 : 0;
          row.erased = (type == "erase") ? 1 : 0;
        });
      }
      else {
        counts.modify(iterator, "addressbook"_n, [&]( auto& row ) {
          if(type == "emplace") { row.emplaced += 1; }
          if(type == "modify") { row.modified += 1; }
          if(type == "erase") { row.erased += 1; }
        });
      }
    }

    using count_action = action_wrapper<"count"_n, &abcounter::count>;

  private:
    struct [[eosio::table]] counter {
      name key;
      uint64_t emplaced;
      uint64_t modified;
      uint64_t erased;
      uint64_t primary_key() const { return key.value; }
    };

    using count_index = eosio::multi_index<"counts"_n, counter>;
};
```

The first new concept in the code above is that we are explicitly restricting calls to the one action to a **specific account** in this contract using [require\_auth](http://docs.eosnetwork.com/cdt/latest/reference/Modules/group__action#function-require-auth) to the `addressbook` contract, as seen below.

```
//Only the addressbook account/contract can authorize this command.
require_auth( name("addressbook"));
```

Previously, a dynamic value was used with `require_auth`.

Another new concept in the code above, is action wrapper. As shown below the first template parameter is the 'action' we are going to call and the second one should point to the action function

```cpp
using count_action = action_wrapper<"count"_n, &abcounter::count>;
```

### Step 2: Create Account for abcounter Contract[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/inline-action-to-external-contract#step-2-create-account-for-abcounter-contract) <a href="#step-2-create-account-for-abcounter-contract" id="step-2-create-account-for-abcounter-contract"></a>

Open your terminal and execute the following command to create the **abcounter** user.

```
cleos create account eosio abcounter YOUR_PUBLIC_KEY
```

### Step 3: Compile and Deploy[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/inline-action-to-external-contract#step-3-compile-and-deploy) <a href="#step-3-compile-and-deploy" id="step-3-compile-and-deploy"></a>

```
eosio-cpp abcounter.cpp -o abcounter.wasm
```

Finally, deploy the `abcounter` contract.

```
cleos set contract abcounter CONTRACTS_DIR/abcounter
```

### Step 4: Modify addressbook contract to send inline-action to abcounter[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/inline-action-to-external-contract#step-4-modify-addressbook-contract-to-send-inline-action-to-abcounter) <a href="#step-4-modify-addressbook-contract-to-send-inline-action-to-abcounter" id="step-4-modify-addressbook-contract-to-send-inline-action-to-abcounter"></a>

Navigate to your addressbook directory now.

```
cd CONTRACTS_DIR/addressbook
```

Open the `addressbook.cpp` file in your favorite editor if not already open.

In the last part of this series, we went over inline actions to our own contract. This time, we are going to send an inline action to another contract, our new `abcounter` contract.

Create another helper called `increment_counter` under the `private` declaration of the contract as below:

```
void increment_counter(name user, std::string type) {
    abcounter::count_action count("abcounter"_n, {get_self(), "active"_n});
    count.send(user, type);
}
```

Let's go through the code listing above.

This time we use the action wrapper instead of calling a function. To do that, we firstly initialised the count\_action object defined earlier. The first parameter we pass is the callee contract name, in this case `abcounter`. The second parameter is the permission struct.

* For the permission, get\_self() returns the current `addressbook` contract. The `active` permission of `addressbook` is used.

Unlike the `Adding Inline Actions` tutorial, we won't need to specify the action because the action wrapper type incorporates the action when it is defined.

In line 3 we call the action with the data, namely `user` and `type` which are required by the `abcounter` contract.

Now, add the following calls to the helpers in their respective action scopes.

```cpp
//Emplace
increment_counter(user, "emplace");
//Modify
increment_counter(user, "modify");
//Erase
increment_counter(user, "erase");
```

Now your `addressbook.cpp` contract should look like this.

```cpp
#include <eosio/eosio.hpp>
#include "abcounter.cpp"

using namespace eosio;

class [[eosio::contract("addressbook")]] addressbook : public eosio::contract {

public:

  addressbook(name receiver, name code,  datastream<const char*> ds): contract(receiver, code, ds) {}

  [[eosio::action]]
  void upsert(name user, std::string first_name, std::string last_name,
      uint64_t age, std::string street, std::string city, std::string state) {
    require_auth(user);
    address_index addresses(get_first_receiver(), get_first_receiver().value);
    auto iterator = addresses.find(user.value);
    if( iterator == addresses.end() )
    {
      addresses.emplace(user, [&]( auto& row ) {
       row.key = user;
       row.first_name = first_name;
       row.last_name = last_name;
       row.age = age;
       row.street = street;
       row.city = city;
       row.state = state;
      });
      send_summary(user, " successfully emplaced record to addressbook");
      increment_counter(user, "emplace");
    }
    else {
      std::string changes;
      addresses.modify(iterator, user, [&]( auto& row ) {
        row.key = user;
        row.first_name = first_name;
        row.last_name = last_name;
        row.age = age;
        row.street = street;
        row.city = city;
        row.state = state;
      });
      send_summary(user, " successfully modified record to addressbook");
      increment_counter(user, "modify");
    }
  }

  [[eosio::action]]
  void erase(name user) {
    require_auth(user);

    address_index addresses(get_first_receiver(), get_first_receiver().value);

    auto iterator = addresses.find(user.value);
    check(iterator != addresses.end(), "Record does not exist");
    addresses.erase(iterator);
    send_summary(user, " successfully erased record from addressbook");
    increment_counter(user, "erase");
  }

  [[eosio::action]]
  void notify(name user, std::string msg) {
    require_auth(get_self());
    require_recipient(user);
  }

private:
  struct [[eosio::table]] person {
    name key;
    std::string first_name;
    std::string last_name;
    uint64_t age;
    std::string street;
    std::string city;
    std::string state;

    uint64_t primary_key() const { return key.value; }
    uint64_t get_secondary_1() const { return age;}
  };

  void send_summary(name user, std::string message) {
    action(
      permission_level{get_self(),"active"_n},
      get_self(),
      "notify"_n,
      std::make_tuple(user, name{user}.to_string() + message)
    ).send();
  };

  void increment_counter(name user, std::string type) {
    abcounter::count_action count("abcounter"_n, {get_self(), "active"_n});
    count.send(user, type);
  }

  typedef eosio::multi_index<"people"_n, person,
    indexed_by<"byage"_n, const_mem_fun<person, uint64_t, &person::get_secondary_1>>
  > address_index;
};
```

### Step 5: Recompile and redeploy the addressbook contract[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/inline-action-to-external-contract#step-5-recompile-and-redeploy-the-addressbook-contract) <a href="#step-5-recompile-and-redeploy-the-addressbook-contract" id="step-5-recompile-and-redeploy-the-addressbook-contract"></a>

Recompile the `addressbook.cpp` contract, we don't need to regenerate the ABI, because none of our changes have affected the ABI. Note here we include the abcounter contract folder with the -I option.

```
eosio-cpp -o addressbook.wasm addressbook.cpp -I ../abcounter/
```

Redeploy the contract

```
cleos set contract addressbook CONTRACTS_DIR/addressbook
```

### Step 6: Test It.[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/inline-action-to-external-contract#step-6-test-it) <a href="#step-6-test-it" id="step-6-test-it"></a>

Now that we have the `abcounter` deployed and `addressbook` redeployed, we're ready for some testing.

```
cleos push action addressbook upsert '["alice", "alice", "liddell", 19, "123 drink me way", "wonderland", "amsterdam"]' -p alice@active
```

```
executed transaction: cc46f20da7fc431124e418ecff90aa882d9ca017a703da78477b381a0246eaf7  152 bytes  1493 us
#   addressbook <= addressbook::upsert          {"user":"alice","first_name":"alice","last_name":"liddell","street":"123 drink me way","city":"wonde...
#   addressbook <= addressbook::notify          {"user":"alice","msg":"alice successfully modified record in addressbook"}
#         alice <= addressbook::notify          {"user":"alice","msg":"alice successfully modified record in addressbook"}
#     abcounter <= abcounter::count             {"user":"alice","type":"modify"}
```

As you can see, the counter was successfully notified. Let's check the table now.

```
cleos get table abcounter abcounter counts --lower alice --limit 1
```

```
{
  "rows": [{
      "key": "alice",
      "emplaced": 1,
      "modified": 0,
      "erased": 0
    }
  ],
  "more": false
}
```

Test each of the actions and check the counter. There's already a row for alice, so upsert *should* **modify** the record.

```
cleos push action addressbook upsert '["alice", "alice", "liddell", 21,"1 there we go", "wonderland", "amsterdam"]' -p alice@active
```

```
executed transaction: c819ffeade670e3b44a40f09cf4462384d6359b5e44dd211f4367ac6d3ccbc70  152 bytes  909 us
#   addressbook <= addressbook::upsert          {"user":"alice","first_name":"alice","last_name":"liddell","street":"1 coming down","city":"normalla...
#   addressbook <= addressbook::notify          {"user":"alice","msg":"alice successfully emplaced record to addressbook"}
>> Notified
#         alice <= addressbook::notify          {"user":"alice","msg":"alice successfully emplaced record to addressbook"}
#     abcounter <= abcounter::count             {"user":"alice","type":"emplace"}
warning: transaction executed locally, but may not be confirmed by the network yet    ]
```

To erase:

```
cleos push action addressbook erase '["alice"]' -p alice@active
```

```
executed transaction: aa82577cb1efecf7f2871eac062913218385f6ab2597eaf31a4c0d25ef1bd7df  104 bytes  973 us
#   addressbook <= addressbook::erase           {"user":"alice"}
>> Erased
#   addressbook <= addressbook::notify          {"user":"alice","msg":"alice successfully erased record from addressbook"}
>> Notified
#         alice <= addressbook::notify          {"user":"alice","msg":"alice successfully erased record from addressbook"}
#     abcounter <= abcounter::count             {"user":"alice","type":"erase"}
warning: transaction executed locally, but may not be confirmed by the network yet    ]
Toaster:addressbook sandwich$
```

Next, we'll test if we can manipulate the data in `abcounter` contract by calling it directly.

```
cleos push action abcounter count '["alice", "erase"]' -p alice@active
```

Checking the table in `abcounter` we'll see the following:

```
cleos get table abcounter abcounter counts --lower alice
```

```
{
  "rows": [{
      "key": "alice",
      "emplaced": 1,
      "modified": 1,
      "erased": 1
    }
  ],
  "more": false
}
```

Wonderful! Since we require\_auth for `name("addressbook")`, only the `addressbook` contract can successfully execute this action, the call by alice to fudge the numbers had no affect on the table.

### Extra Credit: More Verbose Receipts[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/inline-action-to-external-contract#extra-credit-more-verbose-receipts) <a href="#extra-credit-more-verbose-receipts" id="extra-credit-more-verbose-receipts"></a>

The following modification sends custom receipts based on changes made, and if no changes are made during a modification, the receipt will reflect this situation.

```cpp
#include <eosio/eosio.hpp>
#include "abcounter.cpp"

using namespace eosio;

class [[eosio::contract("addressbook")]] addressbook : public eosio::contract {

public:

  addressbook(name receiver, name code,  datastream<const char*> ds): contract(receiver, code, ds) {}

  [[eosio::action]]
  void upsert(name user, std::string first_name, std::string last_name, uint64_t age, std::string street, std::string city, std::string state) {
    require_auth(user);

    address_index addresses(get_first_receiver(), get_first_receiver().value);

    auto iterator = addresses.find(user.value);
    if( iterator == addresses.end() )
    {
      addresses.emplace(user, [&]( auto& row ){
       row.key = user;
       row.first_name = first_name;
       row.last_name = last_name;
       row.age = age;
       row.street = street;
       row.city = city;
       row.state = state;
       send_summary(user, " successfully emplaced record to addressbook");
       increment_counter(user, "emplace");
      });
    }
    else {
      std::string changes;
      addresses.modify(iterator, user, [&]( auto& row ) {

        if(row.first_name != first_name) {
          row.first_name = first_name;
          changes += "first name ";
        }

        if(row.last_name != last_name) {
          row.last_name = last_name;
          changes += "last name ";
        }

        if(row.age != age) {
          row.age = age;
          changes += "age ";
        }

        if(row.street != street) {
          row.street = street;
          changes += "street ";
        }

        if(row.city != city) {
          row.city = city;
          changes += "city ";
        }

        if(row.state != state) {
          row.state = state;
          changes += "state ";
        }
      });

      if(!changes.empty()) {
        send_summary(user, " successfully modified record in addressbook. Fields changed: " + changes);
        increment_counter(user, "modify");
      } else {
        send_summary(user, " called upsert, but request resulted in no changes.");
      }
    }
  }

  [[eosio::action]]
  void erase(name user) {
    require_auth(user);
    address_index addresses(get_first_receiver(), get_first_receiver().value);
    auto iterator = addresses.find(user.value);
    check(iterator != addresses.end(), "Record does not exist");
    addresses.erase(iterator);
    send_summary(user, " successfully erased record from addressbook");
    increment_counter(user, "erase");
  }

  [[eosio::action]]
  void notify(name user, std::string msg) {
    require_auth(get_self());
    require_recipient(user);
  }

private:

  struct [[eosio::table]] person {
    name key;
    std::string first_name;
    std::string last_name;
    uint64_t age;
    std::string street;
    std::string city;
    std::string state;
    uint64_t primary_key() const { return key.value; }
    uint64_t get_secondary_1() const { return age;}
  };

  void send_summary(name user, std::string message) {
    action(
      permission_level{get_self(),"active"_n},
      get_self(),
      "notify"_n,
      std::make_tuple(user, name{user}.to_string() + message)
    ).send();
  };

  void increment_counter(name user, std::string type) {

    action counter = action(
      permission_level{get_self(),"active"_n},
      "abcounter"_n,
      "count"_n,
      std::make_tuple(user, type)
    );

    counter.send();
  }

  typedef eosio::multi_index<"people"_n, person, indexed_by<"byage"_n, const_mem_fun<person, uint64_t, &person::get_secondary_1>>> address_index;
};
```

### What's Next?[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/inline-action-to-external-contract#whats-next) <a href="#whats-next" id="whats-next"></a>

* Linking Custom Permissions: Learn how create a custom permission and how to link the permission to an action of a contract.


# Payable actions

### Goal[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/payable_actions#goal) <a href="#goal" id="goal"></a>

This tutorial illustrates how to write a smart contract that has payable actions. Payable actions are actions that require you to transfer some tokens to actions prior to use other functionality of the smart contract. Also, the VEXANIUM `asset` type is covered in this tutorial.

As for the logic of this smart contract, we're going to write a contract that accepts a particular token but will not allow the tokens to be withdrawn for a specific amount of time.

### The token to HODL[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/payable_actions#the-token-to-hodl) <a href="#the-token-to-hodl" id="the-token-to-hodl"></a>

First create a standard C++ class called "hodl" that extends `eosio::contract`.

```cpp
#include <eosio/eosio.hpp>

using namespace eosio;

class [[eosio::contract("hodl")]] hodl : public eosio::contract{
  private:
  public:
};
```

This contract needs to set up a few constraints:

* What symbol/token does this contract accept?
* When is the hodl over?

Let us now define these constraints as constants:

* `hodl_symbol`: the symbol of tokens this contract accepts. In this case, we use the "SYS" symbol.
* `the_party` constant sets the hodl to end on Tuesday, February 22, 2022 10:22:22 PM.

```cpp
#include <eosiolib/eosio.hpp>

using namespace eosio;

class [[eosio::contract("hodl")]] hodl : public eosio::contract {
  private:
    static const uint32_t the_party = 1645525342;
    const symbol hodl_symbol;
  public:

}
```

Next, let's define a table to track the number of tokens the `hodl` contract has received.

```cpp
struct [[eosio::table]] balance
{
  eosio::asset funds;
  uint64_t primary_key() const { return funds.symbol.raw(); }
};
```

In this multiple index table declaration, a new type called `asset` is used. An `asset` is a type designed to represent a digital token asset. See more details in the asset reference documentation.

The `symbol` member of an asset instance will be used as the primary key. By calling the `raw()` function the `symbol` variable will be converted into an unsigned integer so it can be used as a primary key.

### Constructor[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/payable_actions#constructor) <a href="#constructor" id="constructor"></a>

The constructor initializes the hodl\_symbol as “SYS”, which is a token created in the Deploy, Issue and Transfer Tokens section.

```cpp
public:
  using contract::contract;
  hodl(name receiver, name code, datastream<const char *> ds):contract(receiver, code, ds), hodl_symbol("SYS", 4){}
```

### Get current UTC time[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/payable_actions#get-current-utc-time) <a href="#get-current-utc-time" id="get-current-utc-time"></a>

In order to get time in UTC timezone throughout the code, create a function to easily access the current UTC time.

```
uint32_t now() {
  return current_time_point().sec_since_epoch();
}
```

Next, we'll write the actions of the contract.

### Deposit[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/payable_actions#deposit) <a href="#deposit" id="deposit"></a>

To accept a transfer we need to have a deposit action.

```
[[eosio::on_notify("eosio.token::transfer")]]
void deposit(name hodler, name to, eosio::asset quantity, std::string memo)
{
  if (to != get_self() || hodler == get_self())
  {
    print("These are not the droids you are looking for.");
    return;
  }

  check(now() < the_party, "You're way late");
  check(quantity.amount > 0, "When pigs fly");
  check(quantity.symbol == hodl_symbol, "These are not the droids you are looking for.");

  balance_table balance(get_self(), hodler.value);
  auto hodl_it = balance.find(hodl_symbol.raw());

  if (hodl_it != balance.end())
    balance.modify(hodl_it, get_self(), [&](auto &row) {
      row.funds += quantity;
    });
  else
    balance.emplace(get_self(), [&](auto &row) {
      row.funds = quantity;
    });
}
```

This action should not introduce many new concepts if you have followed this tutorial from the beginning.

Firstly, the action checks that the contract is not transferring to itself:

```
if (to != get_self() || hodler == get_self()) {
  print("These are not the droids you are looking for.");
  return;
}
```

The contract needs to do so because transferring to the contract account itself would create an invalid booking situation in which an account could have more tokens than the account has in the `eosio.token` contract.

Then this action checks a few other conditions:

* The time to withdraw has not already passed
* The incoming transfer has a valid amount of tokens
* The incoming transfer uses the token we specify in the constructor

```cpp
check(now() < the_party, "You're way late");
check(quantity.amount > 0, "When pigs fly");
check(quantity.symbol == hodl_symbol, "These are not the droids you are looking for.");
```

If all constraints are passed, the action updates the balances accordingly:

```cpp
balance_table balance(get_self(), hodler.value);
auto hodl_it = balance.find(hodl_symbol.raw());

if (hodl_it != balance.end())
  balance.modify(hodl_it, get_self(), [&](auto &row) {
    row.funds += quantity;
  });
else
  balance.emplace(get_self(), [&](auto &row) {
    row.funds = quantity;
  });
```

The important thing to note is the deposit function will actually be triggered by the `eosio.token` contract. To understand this behaviour we need to understand the `on_notify` attribute.

### The on\_notify attribute[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/payable_actions#the-on_notify-attribute) <a href="#the-on_notify-attribute" id="the-on_notify-attribute"></a>

```
[[eosio::on_notify("eosio.token::transfer")]]
```

The `on_notify` attribute is one of the CDT [attributes](http://docs.eosnetwork.com/cdt/latest/best-practices/abi/abi-code-generator-attributes-explained) that annotates a smart contract action.

Annotating an action with an [`on_notify`](http://docs.eosnetwork.com/cdt/latest/best-practices/abi/abi-code-generator-attributes-explained#eosioon_notifyvalid_eosio_account_namevalid_eosio_action_name) attribute ensures any incoming notification is forwarded to the annotated action if and only if the notification is dispatched from a specified contract and from a specified action.

In this case, the `on_notify` attribute ensures the incoming notification is forward to the deposit action only if the notification comes from the `eosio.token` contract and is from the `eosio.token`'s `transfer` action.

This is also why we don't need to check if the hodler actually has the appropriate amount of tokens he or she claimed, as the `eosio.token` contract would have done this check prior to the transfer notification reaching the `hodl` `deposit` action.

### Party\![​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/payable_actions#party) <a href="#party" id="party"></a>

The party action will only allow withdrawals after the configured `the_party` time has elapsed. The party action has a similar construct as the deposit action with the following conditions:

* check the withdrawing account is the account which made the deposit initially
* find the locked balance
* transfer the token from the `hodl` contract to the account itself

```cpp
[[eosio::action]]
void party(name hodler)
{
  //Check the authority of hodler
  require_auth(hodler);

  //Check the current time has passed the the_party time
  check(now() > the_party, "Hold your horses");

  balance_table balance(get_self(), hodler.value);
  auto hodl_it = balance.find(hodl_symbol.raw());

  //Make sure the holder is in the table
  check(hodl_it != balance.end(), "You're not allowed to party");

  action{
    permission_level{get_self(), "active"_n},
    "eosio.token"_n,
    "transfer"_n,
    std::make_tuple(get_self(), hodler, hodl_it->funds, std::string("Party! Your hodl is free."))
  }.send();

  balance.erase(hodl_it);
}
```

The complete code listing is the following:

```cpp
#include <eosio/eosio.hpp>
#include <eosio/print.hpp>
#include <eosio/asset.hpp>
#include <eosio/system.hpp>

using namespace eosio;

class [[eosio::contract("hodl")]] hodl : public eosio::contract {
  private:
    static const uint32_t the_party = 1645525342;
    const symbol hodl_symbol;

    struct [[eosio::table]] balance
    {
      eosio::asset funds;
      uint64_t primary_key() const { return funds.symbol.raw(); }
    };

    using balance_table = eosio::multi_index<"balance"_n, balance>;

    uint32_t now() {
      return current_time_point().sec_since_epoch();
    }

  public:
    using contract::contract;

    hodl(name receiver, name code, datastream<const char *> ds) : contract(receiver, code, ds),hodl_symbol("SYS", 4){}

    [[eosio::on_notify("eosio.token::transfer")]]
    void deposit(name hodler, name to, eosio::asset quantity, std::string memo) {
      if (hodler == get_self() || to != get_self())
      {
        return;
      }

      check(now() < the_party, "You're way late");
      check(quantity.amount > 0, "When pigs fly");
      check(quantity.symbol == hodl_symbol, "These are not the droids you are looking for.");

      balance_table balance(get_self(), hodler.value);
      auto hodl_it = balance.find(hodl_symbol.raw());

      if (hodl_it != balance.end())
        balance.modify(hodl_it, get_self(), [&](auto &row) {
          row.funds += quantity;
        });
      else
        balance.emplace(get_self(), [&](auto &row) {
          row.funds = quantity;
        });
    }

    [[eosio::action]]
    void party(name hodler)
    {
      //Check the authority of hodlder
      require_auth(hodler);

      // //Check the current time has pass the the party time
      check(now() > the_party, "Hold your horses");

      balance_table balance(get_self(), hodler.value);
      auto hodl_it = balance.find(hodl_symbol.raw());

      // //Make sure the holder is in the table
      check(hodl_it != balance.end(), "You're not allowed to party");

      action{
        permission_level{get_self(), "active"_n},
        "eosio.token"_n,
        "transfer"_n,
        std::make_tuple(get_self(), hodler, hodl_it->funds, std::string("Party! Your hodl is free."))
      }.send();

      balance.erase(hodl_it);
    }
};
```

Great, let's deploy it.

### Test deposit[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/payable_actions#test-deposit) <a href="#test-deposit" id="test-deposit"></a>

First, create an account and deploy to it:

```
cleos create account eosio hodl YOUR_PUBLIC_KEY
cdt-cpp hodl.cpp -o hodl.wasm
cleos set contract hodl ./ -p hodl@active
```

As mentioned in a previous tutorial, this contract needs an eosio.code permission:

```
cleos set account permission hodl active --add-code
```

Next, create a testing account:

```
cleos create account eosio han YOUR_PUBLIC_KEY
```

Let's transfer some SYS tokens issued in the previous section to `han`:

```
cleos push action eosio.token transfer '[ "alice", "han", "100.0000 SYS", "Slecht geld verdrijft goed" ]' -p alice@active
```

Finally, transfer some SYS tokens to the `hodl` contract from `han`'s account.

```
cleos transfer han hodl '0.0001 SYS' 'Hodl!' -p han@active
```

### Test withdraw[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/payable_actions#test-withdraw) <a href="#test-withdraw" id="test-withdraw"></a>

To test the withdrawal feature, the `the_party` variable needs to be updated. Update the `the_party` variable to a point in time in the past so the withdrawal functionality can be tested.

```

CONTRACT hodl : public eosio::contract {
  private:
    // 9 June 2018 01:00:00
    static const uint32_t the_party = 1528549200;
```

Withdrawing the funds:

```
cleos push action hodl party '["han"]' -p han@active
```

Should produce the following response:

```
executed transaction: 62b1e6848c8c5e6458b9a0f7600e65574eaf60445be114d224adccc5a962a09a  104 bytes  383 us
#          hodl <= hodl::party                  {"hodler":"han"}
#   eosio.token <= eosio.token::transfer        {"from":"hodl","to":"han","quantity":"0.0001 SYS","memo":"Party! Your hodl is free."}
#          hodl <= eosio.token::transfer        {"from":"hodl","to":"han","quantity":"0.0001 SYS","memo":"Party! Your hodl is free."}
#           han <= eosio.token::transfer        {"from":"hodl","to":"han","quantity":"0.0001 
```


# Creating and Linking Custom Permissions

### Introduction[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/linking-custom-permission#introduction) <a href="#introduction" id="introduction"></a>

On the VEXANIUM blockchain, you can create various custom permissions for accounts. A custom permission can later be linked to an action of a contract. This permission system enables smart contracts to have a flexible authorization scheme.

This tutorial illustrates the creation of a custom permission, and subsequently, how to link the permission to an action. Upon completion of the steps, the contract's action will be prohibited from executing unless the authorization of the newly linked permission is provided. This allows you to have greater granularity of control over an account and its various actions.

With great power comes great responsibility. This functionality poses some challenges to the security of your contract and its users. Ensure you understand the concepts and steps prior to putting them to use.

{% hint style="info" %}
**PARENT PERMISSION**

When you create a custom permission, the permission will always be created under a parent permission.

If you have the authority of a parent permission which a custom permission was created under, you can always execute an action which requires that custom permission.
{% endhint %}

### Step 1. Create a Custom Permission[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/linking-custom-permission#step-1-create-a-custom-permission) <a href="#step-1-create-a-custom-permission" id="step-1-create-a-custom-permission"></a>

Firstly, let's create a new permission level on the `alice` account:

```
cleos set account permission alice upsert YOUR_PUBLIC_KEY owner -p alice@owner
```

A few things to note:

1. A new permission called **upsert** was created
2. The **upsert** permission uses the development public key as the proof of authority
3. This permission was created on the `alice` account

You can also specify authorities other than a public key for this permission, for example, a set of other accounts. Check account permission for more details.

### Step 2. Link Authorization to Your Custom Permission[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/linking-custom-permission#step-2-link-authorization-to-your-custom-permission) <a href="#step-2-link-authorization-to-your-custom-permission" id="step-2-link-authorization-to-your-custom-permission"></a>

Link the authorization to invoke the `upsert` action with the newly created permission:

```
cleos set action permission alice addressbook upsert upsert
```

In this example, we link the authorization to the `upsert` action created earlier in the addressbook contract.

### Step 3. Test it[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/linking-custom-permission#step-3-test-it) <a href="#step-3-test-it" id="step-3-test-it"></a>

Let's try to invoke the action with an `active` permission:

```
cleos push action addressbook upsert '["alice", "alice", "liddel", 21, "Herengracht", "land", "dam"]' -p alice@active
```

You should see an error like the one below:

```
Error 3090005: Irrelevant authority included
Please remove the unnecessary authority from your action!
Error Details:
action declares irrelevant authority '{"actor":"alice","permission":"active"}'; minimum authority is {"actor":"alice","permission":"upsert"}
```

Now, try the **upsert** permission, this time, explicitly declaring the **upsert** permission we just created: (e.g. `-p alice@upsert`)

```
cleos push action addressbook upsert '["alice", "alice", "liddel", 21, "Herengracht", "land", "dam"]' -p alice@upsert
```

Now it works:

```
cleos push action addressbook upsert '["alice", "alice", "liddel", 21, "Herengracht", "land", "dam"] -p alice@upsert
executed transaction:

2fe21b1a86ca2a1a72b48cee6bebce9a2c83d30b6c48b16352c70999e4c20983  144 bytes  9489 us
#   addressbook <= addressbook::upsert          {"user":"alice","first_name":"alice","last_name":"liddel","age":21,"street":"Herengracht","city":"land",...
#   addressbook <= addressbook::notify          {"user":"alice","msg":"alice successfully modified record to addressbook"}
#         eosio <= addressbook::notify          {"user":"alice","msg":"alice successfully modified record to addressbook"}
#     abcounter <= abcounter::count             {"user":"alice","type":"modify"}
```

### What's Next?[​](https://docs.eosnetwork.com/docs/latest/getting-started/smart-contract-development/linking-custom-permission#whats-next) <a href="#whats-next" id="whats-next"></a>

* Payable Actions: Learn how write a smart contract that has payable actions.


# Vexanium Protocol

### Core[​](https://docs.eosnetwork.com/docs/latest/protocol/#core) <a href="#core" id="core"></a>

`VEXCHAIN Core` provides the basic building blocks for the `system` layer and because they are not implemented as smart contracts they do not provide the same level of flexibility. Nevertheless, the `core` implementation is also open source and thus it can be modified as well to suit custom business requirements.

The core protocols are:

1. Consensus Protocol
2. Transactions Protocol
3. Network or Peer to Peer Protocol
4. Accounts and Permissions

### System[​](https://docs.eosnetwork.com/docs/latest/protocol/#system) <a href="#system" id="system"></a>

The VEXANIUM blockchain is unique in that the features and characteristics of the blockchain built on it are flexible, that is, they can be changed, or be modified completely to suit each business case requirement. Core blockchain features such as consensus, fee schedules, account creation and modification, token economics, block producer registration, voting, multi-sig, etc., are implemented inside smart contracts which are deployed on the blockchain built on the VEXANIUM blockchain. These smart contracts are referred to as `system contracts` and the layer as the `VEXANIUM system` layer, or simply `system` layer.

VEXANIUM Network Foundation implements and maintains these `system contracts`, as samples only, encapsulating the base functionality for an VEXANIUM based blockchain and they are listed below:

1. eosio.bios
2. eosio.system
3. eosio.msig
4. eosio.token
5. eosio.wrap

Also part of the `system` layer are the following concepts:

1. Account
2. RAM
3. CPU
4. NET


# Consensus Protocol

## 1. Overview

The VEXANIUM blockchain is a highly efficient, deterministic, distributed state machine that can operate in a decentralized fashion. The blockchain keeps track of transactions within a sequence of interchanged blocks. Each block cryptographically commits to the previous blocks along the same chain. It is therefore intractable to modify a transaction recorded on a given block without breaking the cryptographic checks of successive blocks. This simple fact makes blockchain transactions immutable and secure.

### 1.1. Block Producers[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#11-block-producers) <a href="#id-11-block-producers" id="id-11-block-producers"></a>

In the VEXANIUM ecosystem, block production and block validation are performed by special nodes called "block producers". Producers are elected by VEXANIUM stakeholders (see 4. Producer Voting/Scheduling). Each producer runs an instance of an VEXANIUM node through the `nodeos` service. For this reason, producers that are on the active schedule to produce blocks are also called "active" or "producing" nodes.

### 1.2. The Need for Consensus[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#12-the-need-for-consensus) <a href="#id-12-the-need-for-consensus" id="id-12-the-need-for-consensus"></a>

Block validation presents a challenge among any group of distributed nodes. A consensus model must be in place to validate such blocks in a fault tolerant way within the decentralized system. Consensus is the way for such distributed nodes and users to agree upon the current state of the blockchain (see 3. VEXANIUM Consensus (DPoS + aBFT)).

## 2. Consensus Models

There are various ways to reach consensus among a group of distributed parties in a decentralized system. Most consensus models reach agreement through some proof. Two of the most popular ones are Proof of Work (PoW) and Proof of Stake (PoS), although other types of proof-based schemes exist, such as Proof of Activity (a hybrid between PoW and PoS), Proof of Burn, Proof of Capacity, Proof of Elapsed Time, etc. Other consensus schemes also exist, such as Paxos and Raft. This document focuses mainly on the VEXANIUM consensus model.

### 2.1. Proof of Work (PoW)[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#21-proof-of-work-pow) <a href="#id-21-proof-of-work-pow" id="id-21-proof-of-work-pow"></a>

Two of the most common consensus models used in blockchains are Proof of Work and Proof of Stake. In Proof of Work, miner nodes compete to find a nonce added to the header of a block which causes the block to have some desired property (typically a certain number of zeros in the most significant bits of the cryptographic hash of the block header). By making it computationally expensive to find such nonces that make the blocks valid, it becomes difficult for attackers to create an alternative fork of the blockchain that would be accepted by the rest of the network as the best chain. The main disadvantage of Proof of Work is that the security of the network depends on spending a lot of resources on computing power to find the nonces.

### 2.2. Proof of Stake (PoS)[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#22-proof-of-stake-pos) <a href="#id-22-proof-of-stake-pos" id="id-22-proof-of-stake-pos"></a>

In Proof-of-Stake, nodes that own the largest stake or percentage of some asset have equivalent decision power. In other words, voting power is proportional to the stake held. One interesting variant is Delegated Proof-of-Stake (DPoS) in which a large number of participants or stakeholders elect a smaller number of delegates, which in turn make decisions for them.

## 3. VEXANIUM Consensus (DPoS + aBFT)

The VEXANIUM blockchain uses delegated proof of stake (DPoS) to elect the active producers who will be authorized to sign valid blocks in the network. However, this is only one half of the VEXANIUM consensus process. The other half is involved in the actual process of confirming each block until it becomes final (irreversible), which is performed in an asynchronous byzantine fault tolerant (aBFT) way. Therefore, there are two layers involved in the VEXANIUM consensus model:

* Layer 1 - The Native Consensus Model (aBFT).
* Layer 2 - Delegated Proof of Stake (DPoS).

The actual native consensus model used in VEXANIUM has no concept of delegations/voting, stake, or even tokens. These are used by the DPoS layer to generate the first schedule of block producers and, if applicable, update the set at most every schedule round after each producer has cycled through. These two layers are functionally separate in the VEXANIUM software.

### 3.1. Layer 1: Native Consensus (aBFT)[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#31-layer-1-native-consensus-abft) <a href="#id-31-layer-1-native-consensus-abft" id="id-31-layer-1-native-consensus-abft"></a>

This layer ultimately decides which blocks, received and synced among the elected producers, eventually become final, and hence permanently recorded in the blockchain. It gets a schedule of producers proposed by the second layer (see 3.2. Layer 2: Delegated PoS) and uses that schedule to determine which blocks are correctly signed by the appropriate producer. For byzantine fault tolerance, the layer uses a two-stage block confirmation process by which a two-thirds supermajority of producers from the current scheduled set confirm each block twice. The first confirmation stage proposes a last irreversible block (LIB). The second stage confirms the proposed LIB as final. At this point, the block becomes irreversible. This layer is also used to signal producer schedule changes, if any, at the beginning of every schedule round.

#### 3.1.1. VEXANIUM Algorithmic Finality[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#311-eos-algorithmic-finality) <a href="#id-311-eos-algorithmic-finality" id="id-311-eos-algorithmic-finality"></a>

The VEXANIUM consensus model achieves algorithmic finality (differing from the merely probabilistic finality that at best can be achieved in Proof of Work models) through the signatures from the chosen set of special participants (active producers) that are arranged in a schedule to determine which party is authorized to sign the block at a particular time slot. Changes to this schedule can be initiated by privileged smart contracts running on the VEXANIUM blockchain, but any initiated changes to the schedule do not take effect until after the block that initiated the schedule change has been finalized by two stages of confirmations. Each stage of confirmations is performed by a supermajority of producers from the current scheduled set of active producers.

### 3.2. Layer 2: Delegated PoS (DPoS)[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#32-layer-2-delegated-pos-dpos) <a href="#id-32-layer-2-delegated-pos-dpos" id="id-32-layer-2-delegated-pos-dpos"></a>

The Delegated PoS layer introduces the concepts of tokens, staking, voting/proxying, vote decay, vote tallying, producer ranking, and inflation pay. This layer is also in charge of generating new producer schedules from the rankings generated from producer voting. This occurs in schedule rounds of approximately two minutes (126 seconds) which is the period it takes for a block producer to be assigned a timeslot to produce and sign blocks. The timeslot lasts a total of 6 seconds per producer, which is the producer round, where a maximum of 12 blocks can be produced and signed. The DPoS layer is enabled by WASM smart contracts.

#### 3.2.1. Stakeholders and Delegates[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#321-stakeholders-and-delegates) <a href="#id-321-stakeholders-and-delegates" id="id-321-stakeholders-and-delegates"></a>

The actual selection of the active producers (the producer schedule) is open for voting every schedule round and it involves all VEXANIUM stakeholders who exercise their right to participate. In practice, the rankings of the active producers do not change often, though. The stakeholders are regular VEX account holders who vote for their block producers of preference to act on their behalf as DPoS delegates. A major departure from regular DPoS, however, is that once elected, all block producers have equal power regardless of the ranking of votes obtained. In other DPoS models, voting power is proportional to the number of votes obtained by each delegate.

### 3.3. The Consensus Process[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#33-the-consensus-process) <a href="#id-33-the-consensus-process" id="id-33-the-consensus-process"></a>

The VEXANIUM consensus process consists of two parts:

* Producer voting/scheduling - performed by the the DPoS layer 2
* Block production/validation - performed by the native consensus layer 1

These two processes are independent and can be executed in parallel, except for the very first schedule round after the boot sequence when the blockchain’s first genesis block is created.

## 4. Producer Voting/Scheduling

The voting of the active producers to be included in the next schedule is implemented by the DPoS layer. Strictly speaking, a token holder must first stake some tokens to become a stakeholder and thus be able to vote with a given staking power.

### 4.1. Voting Process[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#41-voting-process) <a href="#id-41-voting-process" id="id-41-voting-process"></a>

EachVEXANIUM stakeholder can vote for up to 30 block producers in one voting action. The top 21 elected producers will then act as DPoS delegates to produce and sign blocks on behalf of the stakeholders. The remaining producers are placed in a standby list in the order of votes obtained. The voting process repeats every schedule round by adding up the number of votes obtained by each producer. Producers not voted on get to keep their old votes, albeit depreciated due to vote decay. Producers voted on also get to keep their old votes, except for the contribution of the last voting weight for each voter, which gets replaced by their new voting weight.

#### 4.1.1. Voting Weight[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#411-voting-weight) <a href="#id-411-voting-weight" id="id-411-voting-weight"></a>

The voting weight of each stakeholder is computed as a function of the number of tokens staked and the time elapsed since the VEXANIUM block timestamp epoch, defined as January 1, 2000. In the current implementation, the voting weight is directly proportional to the number of tokens staked and base-2 exponentially proportional to the time elapsed in years since the year 2000. The actual weight increases at a rate of $2^{1/52} = 1.013419$ per week. This means that the voting weight changes weekly and doubles each year for the same amount of tokens staked.

#### 4.1.2. Vote Decay[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#412-vote-decay) <a href="#id-412-vote-decay" id="id-412-vote-decay"></a>

Increasing the voting weight produces depreciation of the current votes held by each producer. Such vote decay is intentional and its reason is twofold:

* Encourage participation by allowing newer votes to have more weight than older votes.
* Give more voice to those users actively involved on important governance matters.

### 4.2. Producers schedule[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#42-producers-schedule) <a href="#id-42-producers-schedule" id="id-42-producers-schedule"></a>

After the producers are voted on and selected for the next schedule, they are simply sorted alphabetically by producer name. This determines the production order. Each producer receives the proposed set of producers for the next schedule round within the very first block to be validated from the current schedule round that is about to start. When the first block that contains the proposed schedule is deemed irreversible by a supermajority of producers plus one, the proposed schedule becomes active for the next schedule round.

#### 4.2.1. Production Parameters[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#421-production-parameters) <a href="#id-421-production-parameters" id="id-421-production-parameters"></a>

The VEXANIUM block production schedule is divided equally among the elected producers. The producers are scheduled to produce an expected number of blocks each schedule round, based on the following parameters (per schedule round):

| Parameter                | Description                              | Default | Layer |
| ------------------------ | ---------------------------------------- | ------- | ----- |
| **P** (producers)        | number of active producers               | 21      | 2     |
| **Bp** (blocks/producer) | number of contiguous blocks per producer | 12      | 1     |
| **Tb** (s/block)         | Production time per block (s: seconds)   | 0.5     | 1     |

It is important to mention that Bp (number of contiguous blocks per producer), and Tb (production time per block) are layer 1 consensus constants. In contrast, P (number of active producers) is a layer 2 constant configured by the DPoS layer, which is enabled by WASM contracts.

The following variables can be defined from the above parameters (per schedule round):

| Variable            | Description                  | Equation                             |
| ------------------- | ---------------------------- | ------------------------------------ |
| **B** (blocks)      | Total number of blocks       | Bp (blocks/producer) x P (producers) |
| **Tp** (s/producer) | Production time per producer | Tb (s/block) x Bp (blocks/producer)  |
| **T** (s)           | Total production time        | Tp (s/producer) x P (producers)      |

Therefore, the value of P, being defined at layer 2, can change dynamically in the VEXANIUM blockchain. In practice, however, N is strategically set to 21 producers, which means that 15 producers are required for a two-thirds supermajority of producers plus one to reach consensus.

#### 4.2.2. Production Default Values[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#422-production-default-values) <a href="#id-422-production-default-values" id="id-422-production-default-values"></a>

With the current defaults: P=21 elected producers, Bp=12 blocks created per producer, and a block produced every T=0.5 seconds, current production times are as follows (per schedule round):

| Variable                             | Value                                                           |
| ------------------------------------ | --------------------------------------------------------------- |
| **Tp**: Production time per producer | Tp = 0.5 (s/block) x 12 (blocks/producer) ⇒ Tp = 6 (s/producer) |
| **T**: Total production time         | T = 6 (s/producer) x 21 (producers) ⇒ T = 126 (s)               |

When a block is not produced by a given producer during its assigned time slot, a gap results in the blockchain.

## 5. Block Lifecycle

Blocks are created by the active producer on schedule during its assigned timeslot, then relayed to other producer nodes for syncing and validation. This process continues from producer to producer until a new schedule of producers is approved at a later schedule round. When a valid block meets the consensus requirements (see 3. VEXANIUM Consensus), the block becomes final and is considered irreversible. Therefore, blocks undergo three major phases during their lifespan: production, validation, and finality. Each phase goes through various stages as well.

### 5.1. Block Structure[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#51-block-structure) <a href="#id-51-block-structure" id="id-51-block-structure"></a>

As an inter-chained sequence of blocks, the fundamental unit within the blockchain is the block. A block contains records of pre-validated transactions and additional cryptographic overhead such as hashes and signatures necessary for block confirmation, re-execution of transactions during validation, blockchain replays, protection against replay attacks, etc. (see `block` schema below).

#### block schema[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#block-schema) <a href="#block-schema" id="block-schema"></a>

| Name                 | Type                           | Description                                                                                                                       |
| -------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| `timestamp`          | `block_timestamp_type`         | expected time slot this block is produced (ends in .000 or .500 seconds)                                                          |
| `producer`           | `name`                         | account name for producer of this block                                                                                           |
| `confirmed`          | `uint16_t`                     | number of prior blocks confirmed by the producer of this block in current producer schedule                                       |
| `previous`           | `block_id_type`                | block ID for previous block                                                                                                       |
| `transaction_mroot`  | `checksum256_type`             | merkle tree root hash of transaction receipts included in block                                                                   |
| `action_mroot`       | `checksum256_type`             | merkle tree root hash of action receipts included in block                                                                        |
| `schedule_version`   | `uint32_t`                     | number of times producer schedule has changed since genesis                                                                       |
| `new_producers`      | `producer_schedule_type`       | holds producer names and keys for new proposed producer schedule; null if no change                                               |
| `header_extensions`  | `extensions_type`              | extends block fields to support additional features (included in block ID calculation)                                            |
| `producer_signature` | `signature_type`               | digital signature by producer that created and signed block                                                                       |
| `transactions`       | array of `transaction_receipt` | list of valid transaction receipts included in block                                                                              |
| `block_extensions`   | `extension_type`               | extends block fields to support additional features (NOT included in block ID calculation)                                        |
| `id`                 | `block_id_type`                | UUID of this block ID (a function of block header and block number); can be used to query block for validation/retrieval purposes |
| `block_num`          | `uint32_t`                     | block number (sequential counter value since genesis block 0); can be used to query block for validation/retrieval purposes       |
| `ref_block_prefix`   | `uint32_t`                     | lower 32 bits of block ID; used to prevent replay attacks                                                                         |

Some of the block fields are known in advance when the block is created, so they are added during block initialization. Others are computed and added during block finalization, such as the merkle root hashes for transactions and actions, the block number and block ID, the signature of the producer that created and signed the block, etc. (see Network Peer Protocol: 3.1. Block ID)

### 5.2. Block Production[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#52-block-production) <a href="#id-52-block-production" id="id-52-block-production"></a>

During each schedule round of block production, the producer on schedule must create Bp=12 contiguous blocks containing as many validated transactions as possible. Each block is currently produced within a span of Tb=500 ms (0.5 s). To guarantee sufficient time to produce each block and transmit to other nodes for validation, the block production time is further divided into two configurable parameters:

* **maximum processing interval**: time window to push transactions into the block (currently set at 200 ms).
* **minimum propagation time**: time window to propagate blocks to other nodes (currently set at 300 ms).

All loose transactions that have not expired yet, or dropped as a result of a previous failed validation, are kept in a local queue for both block inclusion and syncing with other nodes. During block production, the scheduled transactions are applied and validated by the producer on schedule, and if valid, pushed to the pending block within the processing interval. If the transaction falls outside this window, it is unapplied and rescheduled for inclusion in the next block. If there are no more block slots available for the current producer, the transaction is picked up eventually by another producing node (via the peer-to-peer protocol) and pushed to another block. The maximum processing interval is slightly less for the last block (from the producer round of Bp blocks) to compensate for network latencies during handoff to the next producer. By the end of the processing interval, no more transactions are allowed in the pending block, and the block goes through a finalization step before it gets broadcasted to other block producers for validation.

Blocks go through various stages during production: apply, finalize, sign, and commit.

#### 5.2.1. Apply Block[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#521-apply-block) <a href="#id-521-apply-block" id="id-521-apply-block"></a>

Apply block essentially pushes the transactions received and validated by the producing node into a block. Internally, this step involves the creation and initialization of the block header and the signed block instance. The signed block instance simply extends the block header with a signature field. This field eventually holds the signature of the producer that signs the block. Furthermore, recent changes in VEXANIUM allow multiple signatures to be included, which are stored in a header extensions field.

#### 5.2.2. Finalize Block[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#522-finalize-block) <a href="#id-522-finalize-block" id="id-522-finalize-block"></a>

Produced blocks need to be finalized before they can be signed, committed, relayed, and validated. During finalization, any field in the block header that is necessary for cryptographic validation is computed and stored in the block. This includes generating both merkle tree root hashes for the list of action receipts and the list of transaction receipts pushed to the block.

#### 5.2.3. Sign Block[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#523-sign-block) <a href="#id-523-sign-block" id="id-523-sign-block"></a>

After the transactions have been pushed into the block and the block is finalized, the block is ready to be signed by the producer. This involves computing a signature digest from the serialized contents of the block header, which includes the transaction receipts included in the block. After the block is signed with the producer’s private key, the signature digest is added to the signed block instance. This completes the block signing.

#### 5.2.4. Commit Block[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#524-commit-block) <a href="#id-524-commit-block" id="id-524-commit-block"></a>

After the block is signed, it is committed to the local chain. This pushes the block to the reversible block database (see Network Peer Protocol: 2.2.3. Fork Database). This makes the block available for syncing with other nodes for validation (see the Network Peer Protocol for more information about block syncing).

### 5.3. Block Validation[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#53-block-validation) <a href="#id-53-block-validation" id="id-53-block-validation"></a>

Block validation is a fundamental operation necessary to reach consensus within the VEXANIUM blockchain. During block validation, producers receive incoming blocks from other peers and confirm the transactions included within each block. Block validation is about reaching enough quorum among active producers to agree upon:

* The integrity of the block and the transactions it contains.
* The deterministic, chronological order of transactions within each block.

The first step towards validating a block begins when a block is received by a node. At this point, some safety checks are performed on the block. If the block does not link to an already known block or it matches the block ID of any block already received and processed by the node, the block is discarded. If the block is new, it is pushed to the chain controller for processing.

#### 5.3.1. Push Block[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#531-push-block) <a href="#id-531-push-block" id="id-531-push-block"></a>

When the block is received by the chain controller, the software must determine where to add the block within the local chain. The fork database, or Fork DB for short, is used for this purpose. The fork database holds all the branches with reversible blocks that have been received but are not yet finalized. To that end, the following steps are performed:

1. Add block to the fork database.
2. If block is added to the main branch that contains the current head block, apply block (see 5.2.1. Apply Block); or
3. If block must be added to a different branch, then:
   1. if that branch now becomes the preferred branch compared to the current main branch: rewind all blocks up to the nearest common ancestor (and rollback the database state in the process), re-apply all blocks in the different branch, add the new block and apply it. That branch now becomes the new main branch.
   2. otherwise: add the new block to that branch in the fork database but do nothing else.

In order for the block to be added to fork database, some block validation must occur. Block header validation must always be done before adding a block to the fork database. And if the block must be applied, some validation of the transactions within the block must occur. The degree to which transactions are validated depends on the validation mode that nodeos is configured with. Two block validation modes are supported: full validation (the default mode), and light validation.

#### 5.3.2. Full Validation[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#532-full-validation) <a href="#id-532-full-validation" id="id-532-full-validation"></a>

In full validation mode, every transaction that is applied is fully validated. This includes verifying the signatures on the transaction and checking authorizations.

#### 5.3.3. Light Validation[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#533-light-validation) <a href="#id-533-light-validation" id="id-533-light-validation"></a>

In light validation mode, blocks signed by trusted producers (which can be configured locally per node) can skip some of the transaction validation done during full validation. For example, signature verification is skipped and all claimed authorizations on actions are assumed to be valid.

### 5.4. Block Finality[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#54-block-finality) <a href="#id-54-block-finality" id="id-54-block-finality"></a>

Block finality is the final outcome of VEXANIUM consensus. It is achieved after a supermajority of active producers have validated the block according to the consensus rules (see 3.1. Layer 1: Native Consensus (aBFT)). Blocks that reach finality are permanently recorded in the blockchain and cannot be undone. In this regard, the last irreversible block (LIB) in the chain refers to the most recent block that has become final. Therefore, from that point backwards the transactions that have been recorded on the blockchain cannot be reversed, tampered, or erased.

#### 5.4.1. Goal of Finality[​](https://docs.eosnetwork.com/docs/latest/protocol/consensus_protocol#541-goal-of-finality) <a href="#id-541-goal-of-finality" id="id-541-goal-of-finality"></a>

The main point of finality is to give users confidence that transactions that were applied prior and up to the LIB block cannot be modified, rolled back, or dropped. The LIB block can also be useful for active nodes to determine quickly and efficiently which branch to build off from, regardless of which is the longest one. This is because a given branch might be longer without containing the most recent LIB, in which case a shorter branch with the most recent LIB must be selected.


# Transaction Protocol

## 1. Overview

Actions define atomic behaviors within a smart contract. At a higher level, transactions define groups of actions that execute atomically within a decentralized application. Analogously to a database transaction, the group of actions that form a blockchain transaction must all succeed, one by one, in a predefined order, or else the transaction will fail. To maintain transaction atomicity and integrity in case of a failed transaction, the blockchain state is restored to a state consistent with the state prior to processing the transaction. This guarantees that no side effects arise from any actions executed prior to the point of failure.

### 1.1. Actions[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#11-actions) <a href="#id-11-actions" id="id-11-actions"></a>

An action can be authorized by one or more actors previously created on the blockchain. Actions can be created explicitly within a smart contract, or generated implicitly by application code. For any given `actor:action` pair there is at most one explicit associated minimum permission. If there are no explicit minimum permissions set, the implicit default is `actor@active`. Each actor can independently set their personal minimum permission for a given action. Also, a complex but flexible authorization structure is in place within the EOS software to allow actors to push actions on behalf of other accounts. Thus, further checks are enforced to authorize an actor to send an action (see 3.4.2. Permission Check).

There are two types of actions involved in a transaction. They mainly differ in the way they are executed by the EOS software:

1. Explicit actions, which are present in a signed transaction (see 2. Transaction Instance).
2. Implicit (inline) actions, which are created as a side effect of processing a transaction.

Implicit (inline) actions are also defined in smart contract code, just like explicit actions. The key difference is that inline actions are not included in the actual transactions propagated through the network and eventually included in a block; they are implicit.

#### 1.1.1. Explicit Actions[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#111-explicit-actions) <a href="#id-111-explicit-actions" id="id-111-explicit-actions"></a>

Regular or explicit actions, as their name implies, are included in the actual list of actions that form a transaction. Explicit actions are encoded as action instances (see 3.4.3. Action Instance) before being pushed into the transaction. Explicit actions also contain the actual payload data, if any, associated with the action to be executed as part of the transaction.

#### 1.1.2. Implicit Actions[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#112-implicit-actions) <a href="#id-112-implicit-actions" id="id-112-implicit-actions"></a>

An implicit (inline) action is generated as a result of an explicit caller action within a transaction (or another inline action, if nested) that requires that implicit action to perform an operation for the caller action to continue. As such, inline actions work within the same scope and permissions of the caller action. Therefore, inline actions are guaranteed to execute within the same transaction.

### 1.2. Smart Contracts[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#12-smart-contracts) <a href="#id-12-smart-contracts" id="id-12-smart-contracts"></a>

In VEXANIUM, smart contracts consist of a set of actions, usually grouped by functionality, and a set of type definitions which those actions depend on. Therefore, actions specify and define the actual behaviors of the contract. Several actions are implemented in the standard VEXANIUM contracts for account creation, producer voting, token operations, etc. Application developers can extend, replace, or disable this functionality altogether by creating custom actions within their own smart contracts and applications. Transactions, on the other hand, are typically created at the application level. Smart contracts are agnostic to them.

#### 1.2.1. Implementation[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#121-implementation) <a href="#id-121-implementation" id="id-121-implementation"></a>

An EOS smart contract is implemented as a C++ class that derives from `eosio::contract`. Actions are implemented as C++ methods within the derived class. Transactions, on the other hand, are generated dynamically (as transaction instances) within an EOS application. The EOS software processes each transaction instance and keeps track of its state as it evolves from creation, signing, validation, and execution.

## 2. Transaction Instance

A transaction instance consists of a transaction header and the list of action instances and transaction extensions that make the actual transaction. The transaction header includes information necessary to assess the inclusion of the transaction in a block based on its expiration time, which is computed when the transaction is pushed for execution. Other fields include the block number that includes the transaction, a block ID prefix used to prevent "cross chain" or "cross fork" attacks, upper limits for CPU and network usage, and the number of seconds to delay the transaction, if applicable. The diagram below depicts a transaction instance.

![](https://docs.eosnetwork.com/assets/images/xacts_instance-4686c098198bd7e6dea7ea7b2a89705d.png)

The action instances may consist of regular actions or context free actions. Signatures are created and validated at the transaction level. Accounts and permissions are handled on a per action basis. Each action instance contains information to validate whether it is authorized to be executed based on the permission levels of the actors specified in the action and the actual authorizations defined in the smart contract for that action (see [3.4.2. Permission Check](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#342-permission-check)).

### 2.1. Transaction ID[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#21-transaction-id) <a href="#id-21-transaction-id" id="id-21-transaction-id"></a>

A transaction instance contains the minimum set of fields that distinguish one transaction from another. Consequently, a transaction ID consists of a cryptographic hash of the basic fields included in a transaction instance. Therefore, the transaction ID is solely determined by the list of actions encapsulated within the transaction, the transaction header, and any embedded transaction extensions, which are optional. The transaction instance can be further specialized into a signed transaction instance or a packed transaction instance.

### 2.2. Signed Transaction Instance[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#22-signed-transaction-instance) <a href="#id-22-signed-transaction-instance" id="id-22-signed-transaction-instance"></a>

A signed transaction extends the basic contents of the transaction schema to include the signature(s) generated by the account(s) that signed the transaction. It also includes any data associated with the context free actions, if any, that were included in the transaction instance (see `signed_transaction` schema below). A transaction is not ready for execution and validation unless it is signed by the applicable actors.

#### signed\_transaction schema[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#signed_transaction-schema) <a href="#signed_transaction-schema" id="signed_transaction-schema"></a>

| Name                     | Type                      | Description                                                                                                            |
| ------------------------ | ------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `expiration`             | `time_point_sec`          | the time the transaction must be confirmed by before it expires                                                        |
| `ref_block_num`          | `uint16_t`                | lower 16 bits of a block number in the last $2^{16}$ blocks                                                            |
| `ref_block_prefix`       | `uint32_t`                | lower 32 bits of block id referred by \`ref\_block\_num'                                                               |
| `max_net_usage_words`    | `unsigned_int`            | upper limit on total network bandwidth billed (in 64-bit words)                                                        |
| `max_cpu_usage_ms`       | `uint8_t`                 | upper limit on total CPU time billed (in milliseconds)                                                                 |
| `delay_sec`              | `unsigned_int`            | number of seconds to delay transaction for                                                                             |
| `context_free_actions`   | array of `action`         | list of context-free actions if any                                                                                    |
| `actions`                | array of `action`         | list of [action instances](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#343-action-instance) |
| `transaction_extensions` | `extensions_type`         | extends fields to support additional features                                                                          |
| `signatures`             | array of `signature_type` | digital signatures after transaction is signed                                                                         |
| `context_free_data`      | array of `bytes`          | context-free action data to send if any                                                                                |

### 2.3. Packed Transaction Instance[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#23-packed-transaction-instance) <a href="#id-23-packed-transaction-instance" id="id-23-packed-transaction-instance"></a>

A packed transaction is an optionally compressed signed transaction with additional housekeeping fields to allow for decompression and quick validation. Packed transactions minimize space footprint and block size in the long run (see `packed_transaction` schema below). A packed transaction forms the most generic type of transaction in the EOS blockchain. Consequently, when transactions are pushed to a block, they are actually packed transactions whether compressed or not.

#### packed\_transaction schema[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#packed_transaction-schema) <a href="#packed_transaction-schema" id="packed_transaction-schema"></a>

| Name                       | Type                  | Description                                              |
| -------------------------- | --------------------- | -------------------------------------------------------- |
| `signatures`               | `signature_type`      | digital signatures after transaction is signed           |
| `compression`              | `compression_type`    | compression method used                                  |
| `packed_context_free_data` | `bytes`               | compressed context-free data (if transaction compressed) |
| `packed_trx`               | `bytes`               | compressed transaction (if compressed)                   |
| `unpacked_trx`             | `signed_transaction`  | cached decompressed transaction                          |
| `trx_id`                   | `transaction_id_type` | transaction ID                                           |

The `unpacked_trx` field holds the cached unpacked transaction after the transaction instance is constructed. If the signed transaction was previously compressed, it is decompressed from the `packed_trx` field and cached to `unpacked_trx`. If the signed transaction was stored uncompressed, it is simply copied verbatim to `unpacked_trx`. The `signatures` field allows a quick signature validation of the transaction without requiring a full decompression of the transaction.

## 3. Transaction Lifecycle

Transactions go through various stages during their lifespan. First, a transaction is created in an application or an EOS client such as cleos by pushing the associated actions into the transaction. Next, the transaction is sent to the locally connected node, which in turn relays it to the active producing nodes for validation and execution via the peer-to-peer network. Next, the validated transaction is pushed to a block by the active producer on schedule along with other transactions. Finally the block that contains the transaction is pushed to all other nodes for validation. When a supermajority of producers have validated the block, and the block becomes irreversible, the transaction gets permanently recorded in the blockchain and it is considered immutable.

### 3.1. Create Transaction[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#31-create-transaction) <a href="#id-31-create-transaction" id="id-31-create-transaction"></a>

Transactions are created within an application by instantiating a transaction object and pushing the related action instances into a list within the transaction instance. An action instance contains the actual details about the receiver account to whom the action is intended, the name of the action, the list of actors and permission levels that must authorize the transaction via signatures and delays, and the actual message to be sent, if any (see `action` schema below).

#### action schema[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#action-schema) <a href="#action-schema" id="action-schema"></a>

| Name            | Type                        | Description                               |
| --------------- | --------------------------- | ----------------------------------------- |
| `account`       | `name`                      | encoded 13-char account name              |
| `action_name`   | `name`                      | encoded 13-char action name               |
| `authorization` | array of `permission_level` | list of `actor:permission` authorizations |
| `data`          | `bytes`                     | action data to send                       |

After the transaction instance is created at the application level, the transaction is arranged for processing. This involves two main steps: signing the transaction and pushing the signed transaction to the local node for actual propagation and execution of the transaction. These steps are typically performed within the EOS application.

### 3.2. Sign Transaction[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#32-sign-transaction) <a href="#id-32-sign-transaction" id="id-32-sign-transaction"></a>

The transaction must be signed by a set of keys sufficient to satisfy the accumulated set of explicit `actor:permission` pairs specified in all the actions enclosed within the transaction. This linkage is done through the authority table for the given permission (see [Accounts and Permissions: 3. Permissions](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#3-permissions)). The actual signing key is obtained by querying the wallet associated with the signing account on the client where the application is run.

The transaction signing process takes three parameters: the transaction instance to sign, the set of public keys from which the associated private keys within the application wallet are retrieved, and the chain ID. The chain ID identifies the actual EOS blockchain and consists of a hash of its genesis state, which depends on the blockchain’s initial configuration parameters. Before signing the transaction, the EOS software first computes a digest of the transaction. The digest value is a SHA-256 hash of the chain ID, the transaction instance, and the context free data if the transaction has any context free actions. Any instance fields get serialized before computing any cryptographic hashes to avoid including reference fields (memory addresses) in the hash computation. The transaction digest computation and the signing process are depicted below.

![](https://docs.eosnetwork.com/assets/images/xact_sign-8de834a2c468a7d372d7c49188188ad7.png)

After the transaction digest is computed, the digest is finally signed with the private key associated with the signing account’s public key. The public-private key pair is usually stored within the local machine that connects to the local node. The signing process is performed within the wallet manager associated with the signing account, which is typically the same user that deploys the application. The wallet manager provides a virtual secure enclave to perform the digital signing, so a message signature is generated without the private key ever leaving the wallet. After the signature is generated, it is finally added to the signed transaction instance.

### 3.3. Push Transaction[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#33-push-transaction) <a href="#id-33-push-transaction" id="id-33-push-transaction"></a>

After the transaction is signed, a packed transaction instance is created from the signed transaction instance and pushed from the application to the local node, which in turn relays the transaction to the active producing nodes for signature verification, execution, and validation. Every producing node that receives a transaction will attempt to execute and validate it in their local context before relaying it to the next producing node. Hence, valid transactions are relayed while invalid ones are dropped. The idea behind this is to prevent bad actors from spamming the network with bogus transactions. The expectation is for bad transactions to get filtered and dropped before reaching the active producer on schedule. When a transaction is received, no assumption is made on its validity. All transactions are validated again by the next producing node, regardless of whether it is producing blocks. The only difference is that the producer on schedule attempts to produce blocks by pushing the transactions it validates into a pending block before pushing the finalized block to its own local chain and relaying it to other nodes.

### 3.4. Verify Transaction[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#34-verify-transaction) <a href="#id-34-verify-transaction" id="id-34-verify-transaction"></a>

The process to verify a transaction is twofold. First, the public keys associated with the accounts that signed the transaction are recovered from the set of signatures provided in the transaction. Such a recovery is cryptographically possible for ECDSA, the elliptic curve digital signature algorithm used in VEXANIUM. Second, the public key of each actor specified in the list of action authorizations (actor:permission) from each action included in the transaction is checked against the set of recovered keys to see if it is satisfied. Third, each satisfied `actor:permission` is checked against the associated minimum permission required for that `actor:contract::action` pair to see if it meets or exceeds that minimum. This last check is performed at the action level before any action is executed (see [3.4.2. Permission Check](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#342-permission-check)).

#### 3.4.1. Transaction Context[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#341-transaction-context) <a href="#id-341-transaction-context" id="id-341-transaction-context"></a>

Once the public keys are recovered, a transaction context is created from the transaction instance. The transaction context keeps track of the trace of actions and the action receipt generated as each action is dispatched and executed. All state generated is kept within a transaction trace instance and a list of action receipts. The transaction trace consists of a list of action traces. Each action trace contains information about the executed action, which includes the action receipt, the action instance, whether it is a context-free action, and the transaction ID that generated the action. The action receipt is generated later during transaction execution and finalization.

#### 3.4.2. Permission Check[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#342-permission-check) <a href="#id-342-permission-check" id="id-342-permission-check"></a>

Since the sequence of actions contained in the transaction must be executed atomically as a whole, the VEXANIUM software first checks that the actors specified in each action have the minimum permission required to execute it. To that end, the software checks the following for each action:

* The named permission of each actor specified in each action instance.
* The named permission of the corresponding `actor:contract::action` pair specified in the smart contract.

If there is at least one actor whose set of named permissions fail to meet the minimum permission level required by the corresponding `actor:contract::action` pair in the smart contract, the transaction fails. The reason why action permissions are checked before any action is executed is due to performance. It is more efficient to cancel a transaction with all actions unexecuted, than doing so after a few actions executed, but later were rolled back as a result of a failed action or authorization. Any state changes incurred during a failed action must be undone to preserve data integrity. Database sessions are expensive in terms of memory usage and computing resources. Therefore, undo operations must be minimized as possible.

#### 3.4.3. Action Instance[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#343-action-instance) <a href="#id-343-action-instance" id="id-343-action-instance"></a>

The diagram below depicts an action instance. It consists of the receiver account, the action name, the list of actors and their permissions, and the action data containing the message to be sent, if any, to the receiver account.

![](https://docs.eosnetwork.com/assets/images/xacts_act_instance-cfe040f43e1f0fdf37be32ad2a7b56b4.png)

#### 3.4.4. Authority Check[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#344-authority-check) <a href="#id-344-authority-check" id="id-344-authority-check"></a>

After the minimum permission levels are checked, the authority table for the receiver account’s permission that matches each actor’s permission within the action instance is checked (see Accounts and Permissions: 3. Permissions for more details).

### 3.5. Execute Transaction[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#35-execute-transaction) <a href="#id-35-execute-transaction" id="id-35-execute-transaction"></a>

To execute the transaction, a chain database session is started and a snapshot is taken. This allows to roll back any changes made to the chain state in case any of the transaction actions fails. A corresponding transaction context keeps the transaction state during execution. To execute the transaction, each action associated with the corresponding transaction instance is dispatched for execution. Context free actions, if any, are dispatched first, followed by regular actions.

#### 3.5.1. Apply Context[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#351-apply-context) <a href="#id-351-apply-context" id="id-351-apply-context"></a>

To prepare for action execution, an apply context instance is created locally for each action. The apply context, as its name implies, contains references to the necessary resources to apply the action, such as an instance to the chain controller (see Network Peer Protocol: 2.2. Chain Controller), the chain database where state is kept, the transaction context where the transaction is running, the actual action instance, and the receiver account to whom the action is intended.

#### 3.5.2. Action Trace[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#352-action-trace) <a href="#id-352-action-trace" id="id-352-action-trace"></a>

To prepare each action for execution, both action receipt and action trace instances are initialized. First, a hash of the action instance itself is computed and stored in the action receipt. Next, the action trace is initialized with statistics about the pending block where the transaction that includes the action will be pushed to. Therefore, an action trace allows an action to be traced to the actual block and transaction that includes the action, including the actual node that produced the block. Finally, the action handler is located by matching the handler name, receiver account, and actor account with the list of action handlers maintained by the chain controller within the producing node. These action handlers are applied in the controller when the system contracts and the client application are loaded. The handlers take the receiver account name, the contract name, the action name, and the action handler.

#### 3.5.3. Action Execution[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#353-action-execution) <a href="#id-353-action-execution" id="id-353-action-execution"></a>

Once the proper action handler is located, the appropriate whitelists and blacklists are checked. If the node is currently producing blocks, the receiver account is checked against the account whitelist and blacklist, if any. The action blacklist is checked next, if any. If the receiver account or the action name are in a blacklist, the action is aborted. If the receiver account is already on the whitelist, the blacklist check is skipped. If all checks pass, the action is finally executed by invoking the corresponding action handler, passing the actor account in the `from` parameter and the receiving account in the `to` parameter.

### 3.6. Finalize Transaction[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#36-finalize-transaction) <a href="#id-36-finalize-transaction" id="id-36-finalize-transaction"></a>

After all actions included in the transaction are executed, the transaction enters the finalization stage. In this step, a corresponding action receipt is produced for each action. The action receipt contains a hash of the corresponding action instance, a few counters used for analytics, and the receiver account to which the action is intended to, if applicable.

#### 3.6.1. Transaction Receipt[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#361-transaction-receipt) <a href="#id-361-transaction-receipt" id="id-361-transaction-receipt"></a>

After all action receipts are generated for the transaction, a transaction receipt is finally created and pushed into the signed block, along with other transaction receipts included in the block. The transaction receipt summarizes the result of the transaction (executed, unexecuted, failed, deferred, expired, etc.), including the actual amount of CPU billed in microseconds, and the total NET storage used (see `transaction_receipt` schema below).

**transaction\_receipt schema**[**​**](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#transaction_receipt-schema)

| Name              | Type           | Description                                |
| ----------------- | -------------- | ------------------------------------------ |
| `status`          | `uint8_t`      | result of transaction execution attempt    |
| `cpu_usage_us`    | `uint32_t`     | total CPU used in microseconds             |
| `net_usage_words` | `unsigned int` | total NET used in 64-bit words             |
| `trx`             | `variant`      | holds transaction ID or packed transaction |

The `status` field is an 8-bit enumeration type that can hold one of the following results:

* `executed` - transaction succeeded, no error handler executed.
* `soft_fail` - transaction failed, error handler succeeded.
* `hard_fail` - transaction failed, error handler failed.
* `delayed` - transaction delayed by user for future execution.
* `expired` - transaction expired, CPU/NET refunded to user.

'DELAYED' STATUS

The `delayed` status only applies to **delayed user transactions**, that is, explicit user-created transactions that have a delay to satisfy authorizations (see [3.6.3. Delayed User Transactions](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#363-delayed-user-transactions) for more information).

The `trx` field holds the transaction ID or the packed transaction itself. The actual choice depends on the transaction type. Receipts generated from Deferred Transactions and Delayed User Transactions are stored by transaction ID; all other types are stored as packed transactions.

#### 3.6.2. Deferred Transactions[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#362-deferred-transactions) <a href="#id-362-deferred-transactions" id="id-362-deferred-transactions"></a>

Deferred transactions are generated as a side effect of processing the blockchain, so their state is stored in the chain database, not within a block. Therefore, there is no need to explicitly include their contents in the transaction receipt. All in-sync nodes should be aware of the form of a deferred transaction as a matter of consensus. Deferred transactions issued by a smart contract have no role or effect on the `delayed` status field of the transaction receipt.

DEPRECATION NOTICE

Deferred transactions are deprecated as of VEXCHAIN v2.0. For more details on their behavior, refer to the [Deferred Transactions](http://docs.eosnetwork.com/cdt/latest/features/deferred_transactions) section on the `cdt` documentation.

#### 3.6.3. Delayed User Transactions[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#363-delayed-user-transactions) <a href="#id-363-delayed-user-transactions" id="id-363-delayed-user-transactions"></a>

Delayed user transactions contain the packed transactions when they are pushed to the network (at the start of the delay timer). However, unlike regular transactions, they bear a "delayed" status so their execution and validation can be postponed. Later on when they execute/fail/expire (at the end of the delay timer), they only contain the transaction ID. This is because any in-sync node will have the transaction content from a previously broadcast block.

### 3.7. Validate Transaction[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#37-validate-transaction) <a href="#id-37-validate-transaction" id="id-37-validate-transaction"></a>

A transaction is verified and validated at various stages during its lifecycle: first when it propagates on the peer-to-peer network as a loose transaction (see 3.4. Verify Transaction), then during block validation as the block is confirmed among a supermajority of block producers, and optionally during a blockchain replay if nodeos is configured to fully re-validate transactions during replays. By default, recorded transactions are not completely re-validated during replays since it is assumed that the node operator has established trust in the local block log, either personally or through a side-channel so it is no longer considered a potential source of byzantine information.

#### 3.7.1. Validation Process[​](https://docs.eosnetwork.com/docs/latest/protocol/transactions_protocol#371-validation-process) <a href="#id-371-validation-process" id="id-371-validation-process"></a>

When validating a transaction as part of a block, multiple validations occur at various levels. In full block validation, all transactions recorded in the block are replayed and the locally calculated merkle tree root hashes (generated from the transaction receipt data and the action receipt data, respectively) are compared against the `transaction_mroot` and `action_mroot` fields in the block header. Therefore, if a recorded transaction is tampered within a block, not only the merkle tree root hashes would cause a mismatch, but also the transaction signature(s) would fail to validate. If the tampering was not performed by a bona-fide block producer, the block signature would fail to validate as well (see Consensus Protocol: 5.3. Block Validation).


# Network Peer Protocol

## 1. Overview

Nodes on the VEXANIUM blockchain must be able to communicate with each other for relaying transactions, pushing blocks, and syncing state between peers. The peer-to-peer (p2p) protocol, part of the `nodeos` service that runs on every node, serves this purpose. The ability to sync state is crucial for each block to eventually reach finality within the global state of the blockchain and allow each node to advance the last irreversible block (LIB). In this regard, the fundamental goal of the p2p protocol is to sync blocks and propagate transactions between nodes to reach consensus and advance the blockchain state.

### 1.1. Goals[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#11-goals) <a href="#id-11-goals" id="id-11-goals"></a>

In order to add multiple transactions into a block and fit them within the specified production time of 0.5 seconds, the p2p protocol must be designed with speed and efficiency in mind. These two goals translate into maximizing transaction throughput within the effective bandwidth and reducing both network and operational latency. Some strategies to achieve this include:

* Fit more transactions within a block for better economy of scale.
* Minimize redundant information among blocks and transactions.
* Allow more efficient broadcasting and syncing of node states.
* Minimize payload footprint with data compression and binary encoding.

Most of these strategies are fully or partially implemented in the VEXANIUM software. Data compression, which is optional, is implemented at the transaction level. Binary encoding is implemented by the net serializer when sending object instances and protocol messages over the network.

## 2. Architecture

The main goal of the p2p protocol is to synchronize nodes securely and efficiently. To achieve this overarching goal, the system delegates functionality into four main components:

* **Net Plugin**: defines the protocol to sync blocks and forward transactions between peers.
* **Chain Controller**: dispatches/manages blocks and transactions received, within the node.
* **Net Serializer**: serializes messages, blocks, and transactions for network transmission.
* **Local Chain**: holds the node’s local copy of the blockchain, including reversible blocks.

The interaction between the above components is depicted in the diagram below:

![](https://docs.eosnetwork.com/assets/images/p2p_system_arch-c4ba2f6db71784e990a7e2a308a5ab97.png)

At the highest level sits the Net Plugin, which exchanges messages between the node and its peers to sync blocks and transactions. A typical message flow goes as follows:

1. Node A sends a message to Node B through the Net Plugin (refer to diagram above).
   1. Node A’s Net Serializer packs the message and sends it to Node B.
   2. Node B’s Net Serializer unpacks the message and relays it to its Net Plugin.
2. The message is processed by Node B’s Net Plugin, dispatching the proper actions.
3. The Net Plugin accesses the local chain via the Chain Controller if necessary to push or retrieve blocks.

### 2.1. Local Chain[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#21-local-chain) <a href="#id-21-local-chain" id="id-21-local-chain"></a>

The local chain is the node’s local copy of the blockchain. It consists of both irreversible and reversible blocks received by the node, each block being cryptographically linked to the previous one. The list of irreversible blocks contains the actual copy of the immutable blockchain. The list of reversible blocks is typically shorter in length and it is managed by the Fork Database as the Chain Controller pushes blocks to it. The local chain is depicted below.

![](https://docs.eosnetwork.com/assets/images/p2p_local_chain-6357867ed4855d3162628af18e191a7a.png)

Each node constructs its own local copy of the blockchain as it receives blocks and transactions and syncs their state with other peers. The reversible blocks are those new blocks received that have not yet reached finality. As such, they are likely to form branches that stem from a main common ancestor, which is the LIB (last irreversible block). Other common ancestors different from the LIB are also possible for reversible blocks. In fact, any two sibling branches always have a nearest common ancestor. For instance, in the diagram above, block 52b is the nearest common ancestor for the branches starting at block 53a and 53b that is different from the LIB. Every active branch in the local chain has the potential to become part of the blockchain.

#### 2.1.1. LIB Block[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#211-lib-block) <a href="#id-211-lib-block" id="id-211-lib-block"></a>

All irreversible blocks constructed in a node are expected to match those from other nodes up to the last irreversible block (LIB) of each node. This is the distributed nature of the blockchain. Eventually, as the blocks that follow the LIB block reach finality, the LIB block moves up the chain through one of the branches as it catches up with the head block (HB). When the LIB block advances, the immutable blockchain effectively grows. In this process, the head block might switch branches multiple times depending on the potential head block numbers received and their timestamps, which is ultimately used as tiebreaker.

### 2.2. Chain Controller[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#22-chain-controller) <a href="#id-22-chain-controller" id="id-22-chain-controller"></a>

The Chain Controller manages the basic operations on blocks and transactions that change the local chain state, such as validating and executing transactions, pushing blocks, etc. The Chain Controller receives commands from the Net Plugin and dispatches the proper operation on a block or a transaction based on the network message received by the Net Plugin. The network messages are exchanged continuously between the VEXANIUM nodes as they communicate with each other to sync the state of blocks and transactions.

#### 2.2.1. Signals' Producer and Consumer[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#221-signals-producer-and-consumer) <a href="#id-221-signals-producer-and-consumer" id="id-221-signals-producer-and-consumer"></a>

The producer and consumer of the signals defined in the controller and their life cycle during normal operation, fork, and replay are as follows:

**pre\_accepted\_block (carry signed\_block\_ptr)**[**​**](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#pre_accepted_block-carry-signed_block_ptr)

* Produced by

| Module     | Function            | Condition                                                                                                                                                         |
| ---------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| controller | push\_block         | before the block is added to the fork db                                                                                                                          |
|            | replay\_push\_block | before the replayed block is added to the fork db (only if the replayed block is not irreversible since irreversible block is not added to fork db during replay) |

* Consumed by

| Module        | Usage                                         |
| ------------- | --------------------------------------------- |
| chain\_plugin | checkpoint validation                         |
|               | forward data to pre\_accepted\_block\_channel |

**accepted\_block\_header (carry block\_state\_ptr)**[**​**](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#accepted_block_header-carry-block_state_ptr)

* Produced by

| Module     | Function            | Condition                                                                                                                                                     |
| ---------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| controller | push\_block         | after the block is added to fork db                                                                                                                           |
|            | commit\_block       | after the block is added to fork db (only if you are the one who produce the block, in other words, this is not applicable to the block received from others) |
|            | replay\_push\_block | after the replayed block is added to fork db                                                                                                                  |

* Consumed by

| Module        | Usage                                            |
| ------------- | ------------------------------------------------ |
| chain\_plugin | forward data to accepted\_block\_header\_channel |

**accepted\_block (carry block\_state\_ptr)**[**​**](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#accepted_block-carry-block_state_ptr)

* Produced by

| Module     | Function      | Condition                   |
| ---------- | ------------- | --------------------------- |
| controller | commit\_block | when the block is finalized |

* Consumed by

| Module      | Usage                          |
| ----------- | ------------------------------ |
| net\_plugin | broadcast block to other peers |

**irreversible\_block (carry block\_state\_ptr)**[**​**](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#irreversible_block-carry-block_state_ptr)

* Produced by

| Module     | Function            | Condition                                                                      |
| ---------- | ------------------- | ------------------------------------------------------------------------------ |
| controller | log\_irreversible   | before it's appended to the block log and before the chainbase db is committed |
|            | replay\_push\_block | when replaying an irreversible block                                           |

* Consumed by

| Module          | Usage                                                 |
| --------------- | ----------------------------------------------------- |
| controller      | setting the current lib of wasm\_interface            |
| chain\_plugin   | forward data to irreversible\_block\_channel          |
| mongodb\_plugin | forward the data to irreversible\_block\_state\_queue |

**accepted\_transaction (carry transaction\_metadata\_ptr)**[**​**](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#accepted_transaction-carry-transaction_metadata_ptr)

* Produced by

| Module     | Function                     | Condition                                                                                                                 |
| ---------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| controller | push\_transaction            | when the transaction executes succesfully (only once, i.e. when it's unapplied and reapplied the signal won't be emitted) |
|            | push\_scheduled\_transaction | when the scheduled transaction executes succesfully                                                                       |
|            |                              | when the scheduled transaction fails (subjective/ soft/ hard)                                                             |
|            |                              | when the scheduled transaction expires                                                                                    |
|            |                              | after applying onerror                                                                                                    |

* Consumed by

| Module          | Usage                                            |
| --------------- | ------------------------------------------------ |
| chain\_plugin   | forward data to accepted\_transaction\_channel   |
| mongodb\_plugin | forward the data to transaction\_metadata\_queue |

**applied\_transaction (carry std::tuple\<const transaction\_trace\_ptr&, const signed\_transaction&>)**[**​**](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#applied_transaction-carry-stdtupleconst-transaction_trace_ptr-const-signed_transaction)

* Produced by

| Module     | Function                     | Condition                                                     |
| ---------- | ---------------------------- | ------------------------------------------------------------- |
| controller | push\_transaction            | when the transaction executes succesfully                     |
|            | push\_scheduled\_transaction | when the scheduled transaction executes succesfully           |
|            |                              | when the scheduled transaction fails (subjective/ soft/ hard) |
|            |                              | when the scheduled transaction expires                        |
|            |                              | after applying onerror                                        |

* Consumed by

| Module          | Usage                                         |
| --------------- | --------------------------------------------- |
| chain\_plugin   | forward data to applied\_transaction\_channel |
| mongodb\_plugin | forward the data to transaction\_trace\_queue |

**bad\_alloc**[**​**](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#bad_alloc)

Not used.

#### 2.2.2. Signals' Life Cycle[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#222-signals-life-cycle) <a href="#id-222-signals-life-cycle" id="id-222-signals-life-cycle"></a>

**A. normal operation where blocks and transactions are input**[**​**](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#a-normal-operation-where-blocks-and-transactions-are-input)

1. When a transaction is pushed to the blockchain (through RPC or broadcasted by peer)
   1. Transaction is executed either succesfully/ fail the validation -> `accepted_transaction` is emitted by the controller
   2. chain\_plugin will react to the signal to forward the transaction\_metadata to accepted\_transaction\_channel
   3. mongodb\_plugin will react to the signal and add the transaction\_metadata to its queue to be processed later on
2. When a scheduled transaction is pushed to the blockchain
   1. Transaction is executed either succesfully/ fail subjectively/ soft fail/ hard fail -> `accepted_transaction` is emitted by the controller
   2. chain\_plugin will react to the signal to forward the transaction\_metadata to accepted\_transaction\_channel
   3. mongodb\_plugin will react to the signal and add the transaction\_metadata to its queue to be processed later on
3. When a block is pushed to the blockchain (through RPC or broadcasted by peer)
   1. Before the block is added to fork db -> `pre_accepted_block` will be emitted by the controller
   2. chain\_plugin will react to the signal to do validation of the block forward the block\_state to accepted\_block\_header\_channel and validate it with the checkpoint
   3. After the block is added to fork db -> `accepted_block_header` will be emitted by the controller
   4. chain\_plugin will react to the signal to forward the block\_state to accepted\_block\_header\_channel
   5. Then the block will be applied, at this time all the transactions and scheduled\_transactions inside the block will be pushed. All signals related to push\_transaction and push\_scheduled\_transaction (see point A.1 and A.2) will be emitted.
   6. When committing the block -> `accepted_block` will be emitted by the controller
   7. net\_plugin will react to the signal and broadcast the block to the peers
   8. If a new block becomes irreversible, signals related to irreversible block will be emitted (see point A.5)
4. When a block is produced
   1. For the block that is produced by you, the block will be added to the fork\_db when it is committed -> `accepted_block_header` will be emitted by the controller
   2. chain\_plugin will react to the signal to forward the block\_state to accepted\_block\_header\_channel and validate it with the checkpoint
   3. Immediately after that (during commiting the block) -> `accepted_block` will be emitted by the controller
   4. net\_plugin will react to the signal and broadcast the block to the peers
   5. If a new block becomes irreversible, signals related to irreversible block will be emitted (see point A.5)
5. When a block becomes irreversible
   1. Once a block is deemed irreversible -> `irreversible_block` will be emitted by the controller before the block is appended to the block log and the chainbase db is committed
   2. chain\_plugin will react to the signal to forward the block\_state to irreversible\_block\_channel and also set the lib of wasm\_interface
   3. mongodb\_plugin will react to the signal and add the transaction\_metadata to its queue to be processed later on

**B. operation where forks are presented and resolved**[**​**](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#b-operation-where-forks-are-presented-and-resolved)

1. When forks are presented, the blockchain will pop all existing blocks up to the forking point and then apply all new blocks in the fork.
2. When applying the new block, all the transactions and scheduled\_transactions inside the block will be pushed. All signals related to push\_transaction and push\_scheduled\_transaction (see point A.1 and A.2) will be emitted.
3. And then when committing the new block -> `accepted_block` will be emitted by the controller
4. net\_plugin will react to the signal and broadcast the block to the peers
5. If If a new block becomes irreversible, signals related to irreversible block will be emitted (see point A.5)

**C. normal replay (with or without replay optimization)**[**​**](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#c-normal-replay-with-or-without-replay-optimization)

1. When replaying irreversible block -> `irreversible_block` will be emitted by the controller
2. Refer to A.5 to see how `irreversible_block` signal is responded
3. When replaying reversible block, before the block is added to fork\_db -> `pre_accepted_block` will be emitted by the controller
4. When replaying reversible block, after the block is added to fork db -> `accepted_block_header` will be emitted by the controller
5. When replaying reversible block, when the block is committed -> `accepted_block` will be emitted by the controller
6. Refer to A.3 to see how `pre_accepted_block`, `accepted_block_header` and `accepted_block` signal are responded

#### 2.2.3. Fork Database[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#223-fork-database) <a href="#id-223-fork-database" id="id-223-fork-database"></a>

The Fork Database (Fork DB) provides an internal interface for the Chain Controller to perform operations on the node’s local chain. As new blocks are received from other peers, the Chain Controller pushes these blocks to the Fork DB. Each block is then cryptographically linked to a previous block. Since there might be more than one previous block, the process is likely to produce temporary branches called mini-forks. Thus, the Fork DB serves three main purposes:

* Resolve which branch the pushed block (new head block) will build off from.
* Advance the head block, the root block, and the LIB block.
* Trim off invalid branches and purge orphaned blocks.

In essence, the Fork DB contains all the candidate block branches within a node that may become the actual branch that continues to grow the blockchain. The root block always marks the beginning of the reversible block tree, and will match the LIB block, except when the LIB advances, in which case the root block must catch up. The calculation of the LIB block as it advances through the new blocks within the Fork DB will ultimately decide which branch gets selected. As the LIB block advances, the root block catches up with the new LIB, and any candidate branch whose ancestor node is behind the LIB gets pruned. This is depicted below.

![](https://docs.eosnetwork.com/assets/images/p2p_local_chain_prunning-53c54854745ab86c00e1a49d544b4453.png)

In the diagram above, the branch starting at block 52b gets pruned (blocks 52b, 53a, 53b are invalid) after the LIB advances from node 51 to block 52c then 53c. As the LIB moves through the reversible blocks, they are moved from the Fork DB to the local chain as they now become part of the immutable blockchain. Finally, block 54d is kept in the Fork DB since new blocks might still be built off from it.

### 2.3. Net Plugin[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#23-net-plugin) <a href="#id-23-net-plugin" id="id-23-net-plugin"></a>

The Net Plugin defines the actual peer to peer communication messages between the VEXANIUM nodes. The main goal of the Net Plugin is to sync valid blocks upon request and to forward valid transactions invariably. To that end, the Net Plugin delegates functionality to the following components:

* **Sync Manager**: maintains the block syncing state of the node with respect to its peers.
* **Dispatch Manager**: maintains the list of blocks and transactions sent by the node.
* **Connection List**: list of active peers the node is currently connected to.
* **Message Handler**: dispatches protocol messages to the corresponding handler. (see 4.2. Protocol Messages).

#### 2.3.1. Sync Manager[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#231-sync-manager) <a href="#id-231-sync-manager" id="id-231-sync-manager"></a>

The Sync Manager implements the functionality for syncing block state between the node and its peers. It processes the messages sent by each peer and performs the actual syncing of the blocks based on the status of the node’s LIB or head block with respect to that peer. At any point, the node can be in any of the following sync states:

* **LIB Catch-Up**: node is about to sync with another peer's LIB block.
* **Head Catch-Up**: node is about to sync with another peer's HEAD block.
* **In-Sync**: both LIB and HEAD blocks are in sync with the other peers.

If the node’s LIB or head block is behind, the node will generate sync request messages to retrieve the missing blocks from the connected peer. Similarly, if a connected peer’s LIB or head block is behind, the node will send notice messages to notify the node about which blocks it needs to sync with. For more information about sync modes see 3. Operation Modes.

#### 2.3.2. Dispatch Manager[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#232-dispatch-manager) <a href="#id-232-dispatch-manager" id="id-232-dispatch-manager"></a>

The Dispatch Manager maintains the state of blocks and loose transactions received by the node. The state contains basic information to identify a block or a transaction and it is maintained within two indexed lists of block states and transaction states:

* **Block State List**: list of block states managed by node for all blocks received.
* **Transaction State List**: list of transaction states managed by node for all transactions received.

This makes it possible to locate very quickly which peer has a given block or transaction.

**2.3.2.1. Block State**[**​**](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#2321-block-state)

The block state identifies a block and the peer it came from. It is transient in nature, so it is only valid while the node is active. The block state contains the following fields:

| Block State Fields | Description                                                                         |
| ------------------ | ----------------------------------------------------------------------------------- |
| `id`               | 256-bit block identifier. A function of the block contents and the block number.    |
| `block_num`        | 32-bit unsigned counter value that identifies the block sequentially since genesis. |
| `connection_id`    | 32-bit unsigned integer that identifies the connected peer the block came from.     |
| `have_block`       | boolean value indicating whether the actual block has been received by the node.    |

The list of block states is indexed by block ID, block number, and connection ID for faster lookup. This allows to query the list for any blocks given one or more of the indexed attributes.

**2.3.2.2. Transaction State**[**​**](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#2322-transaction-state)

The transaction state identifies a loose transaction and the peer it came from. It is also transient in nature, so it is only valid while the node is active. The transaction state contains the following fields:

| Transaction State Fields | Description                                                                  |
| ------------------------ | ---------------------------------------------------------------------------- |
| `id`                     | 256-bit hash of the transaction instance, used as transaction identifier.    |
| `expires`                | expiration time since VEXANIUM block timestamp epoch (January 1, 2000).      |
| `block_num`              | current head block number. Transaction drops when LIB catches up to it.      |
| `connection_id`          | 32-bit integer that identifies the connected peer the transaction came from. |

The `block_num` stores the node's head block number when the transaction is received. It is used as a backup mechanism to drop the transaction when the LIB block number catches up with the head block number, regardless of expiration.

The list of transaction states is indexed by transaction ID, expiration time, block number, and connection ID for faster lookup. This allows to query the list for any transactions given one or more of the indexed attributes.

**2.3.2.3. State Recycling**[**​**](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#2323-state-recycling)

As the LIB block advances (see 3.3.1. LIB Catch-Up Mode), all blocks prior to the new LIB block are considered finalized, so their state is removed from the local list of block states, including the list of block states owned by each peer in the list of connections maintained by the node. Likewise, transaction states are removed from the list of transactions based on expiration time. Therefore, after a transaction expires, its state is removed from all lists of transaction states.

The lists of block states and transaction states have a light footprint and feature high rotation, so they are maintained in memory for faster access. The actual contents of the blocks and transactions received by a node are stored temporarily in the fork database and the various incoming queues for applied and unapplied transactions, respectively.

#### 2.3.3. Connection List[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#233-connection-list) <a href="#id-233-connection-list" id="id-233-connection-list"></a>

The Connection List contains the connection state of each peer. It keeps information about the p2p protocol version, the state of the blocks and transactions from the peer that the node knows about, whether it is currently syncing with that peer, the last handshake message sent and received, whether the peer has requested information from the node, the socket state, the node ID, etc. The connection state includes the following relevant fields:

* **Info requested**: whether the peer has requested information from the node.
* **Socket state**: a pointer to the socket structure holding the TCP connection state.
* **Node ID**: the actual node ID that distinguishes the peer’s node from the other peers.
* **Last Handshake Received**: last handshake message instance received from the peer.
* **Last Handshake Sent**: the last handshake message instance sent to the peer.
* **Handshake Sent Count**: the number of handshake messages sent to the peer.
* **Syncing**: whether or not the node is syncing with the peer.
* **Protocol Version**: the internal protocol version implemented by the peer’s Net Plugin.

The block state consists of the following fields:

* **Block ID**: a hash of the serialized contents of the block.
* **Block number**: the actual block number since genesis.

The transaction state consists of the following fields:

* **Transaction ID**: a hash of the serialized contents of the transaction.
* **Block number**: the actual block number the transaction was included in.
* **Expiration time**: the time in seconds for the transaction to expire.

### 2.4. Net Serializer[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#24-net-serializer) <a href="#id-24-net-serializer" id="id-24-net-serializer"></a>

The Net Serializer has two main roles:

* Serialize objects and messages that need to be transmitted over the network.
* Serialize objects and messages that need to be cryptographically hashed.

In the first case, each serialized object or message needs to get deserialized at the other end upon receipt from the network for further processing. In the latter case, serialization of specific fields within an object instance is needed to generate cryptographic hashes of its contents. Most IDs generated for a given object type (action, transaction, block, etc.) consist of a cryptographic hash of the relevant fields from the object instance.

## 3. Operation Modes

From an operational standpoint, a node can be in either one of three states with respect to a connected peer:

* **In-Sync mode**: node is in sync with peer, so no blocks are required from that peer.
* **LIB Catch-Up mode**: node requires blocks since LIB block is behind that peer’s LIB.
* **HEAD Catch-Up mode**: node requires blocks since HEAD block is behind that peer’s Head.

The operation mode for each node is stored in a sync manager context within the Net Plugin of the nodeos service. Therefore, a node is always in either in-sync mode or some variant of catchup mode with respect to its connected peers. This allows the node to switch back and forth between catchup mode and in-sync mode as the LIB and head blocks are updated and new fresh blocks are received from other peers.

### 3.1. Block ID[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#31-block-id) <a href="#id-31-block-id" id="id-31-block-id"></a>

The VEXANIUM software checks whether two blocks match or hold the same content by comparing their block IDs. A block ID is a function that depends on the contents of the block header and the block number (see Consensus Protocol: 5.1. Block Structure). Checking whether two blocks are equal is crucial for syncing a node’s local chain with that of its peers. To generate the block ID from the block contents, the block header is serialized and a SHA-256 digest is created. The most significant 32 bits are assigned the block number while the least significant 224 bits of the hash are retained. Note that the block header includes the root hash of both the transaction merkle tree and the action merkle tree. Therefore, the block ID depends on all transactions included in the block as well as all actions included in each transaction.

### 3.2. In-Sync Mode[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#32-in-sync-mode) <a href="#id-32-in-sync-mode" id="id-32-in-sync-mode"></a>

During in-sync mode, the node's head block is caught up with the peer's head block, which means the node is in sync block-wise. When the node is in-sync mode, it does not request further blocks from peers, but continues to perform the other functions:

* **Validate transactions**, drop them if invalid; forward them to other peers if valid.
* **Validate blocks**, drop them if invalid; forward them to other peers upon request if valid.

Therefore, this mode trades bandwidth in favor of latency, being particularly useful for validating transactions that rely on TaPoS (transaction as proof of stake) due to lower processing overhead.

Note that loose transactions are always forwarded if valid and not expired. Blocks, on the other hand, are only forwarded if valid and if explicitly requested by a peer. This reduces network overhead.

### 3.3. Catch-Up Mode[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#33-catch-up-mode) <a href="#id-33-catch-up-mode" id="id-33-catch-up-mode"></a>

A node is in catchup mode when its head block is behind the peer’s LIB or the peer’s head block. If syncing is needed, it is performed in two sequential steps:

1. Sync the node’s LIB from the nearest common ancestor + 1 up to the peer’s LIB.
2. Sync the node’s head from the nearest common ancestor + 1 up to the peer’s head.

Therefore, the node’s LIB block is updated first, followed by the node’s head block.

#### 3.3.1. LIB Catch-Up Mode[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#331-lib-catch-up-mode) <a href="#id-331-lib-catch-up-mode" id="id-331-lib-catch-up-mode"></a>

Case 1 above, where the node’s LIB block needs to catch up with the peer’s LIB block, is depicted in the below diagram, before and after the sync (Note: inapplicable branches have been removed for clarity):

![](https://docs.eosnetwork.com/assets/images/p2p_lib_catchup-99b60c03bc9fc67a53e22beff83d0b48.png)

In the above diagram, the node’s local chain syncs up with the peer’s local chain by appending finalized blocks 91 and 92 (the peer’s LIB) to the node’s LIB (block 90). Note that this discards the temporary fork consisting of blocks 91n, 92n, 93n. Also note that these nodes have an “n” suffix (short for node) to indicate that they are not finalized, and therefore, might be different from the peer’s. The same applies to unfinalized blocks on the peer; they end in “p” (short for peer). After syncing, note that both the LIB (lib) and the head block (hb) have the same block number on the node.

#### 3.3.2. Head Catch-Up Mode[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#332-head-catch-up-mode) <a href="#id-332-head-catch-up-mode" id="id-332-head-catch-up-mode"></a>

After the node’s LIB block is synced with the peer’s, there will be new blocks pushed to either chain. Case 2 above covers the case where the peer’s chain is longer than the node’s chain. This is depicted in the following diagram, which shows the node and the peer’s local chains before and after the sync:

![](https://docs.eosnetwork.com/assets/images/p2p_head_catchup-b4a5f57c6c6f91def6ae768ee5a99a85.png)

In either case 1 or 2 above, the syncing process in the node involves locating the first common ancestor block starting from the node’s head block, traversing the chains back, and ending in the LIB blocks, which are now in sync (see 3.3.1. LIB Catch-Up Mode). In the worst case scenario, the synced LIBs are the nearest common ancestor. In the above diagram, the node’s chain is traversed from head block 94n, 93n, etc. trying to match blocks 94p, 93p, etc. in the peer’s chain. The first block that matches is the nearest common ancestor (block 93n and 93p in the diagram). Therefore, the following blocks 94p and 95p are retrieved and appended to the node’s chain right after the nearest common ancestor, now re-labeled 93n,p (see 3.3.3. Block Retrieval process). Finally, block 95p becomes the node’s head block and, since the node is fully synced with the peer, the node switches to in-sync mode.

#### 3.3.3. Block Retrieval[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#333-block-retrieval) <a href="#id-333-block-retrieval" id="id-333-block-retrieval"></a>

After the common ancestor is found, a sync request message is sent to retrieve the blocks needed by the node, starting from the next block after the nearest common ancestor and ending in the peer’s head block.

To make effective use of bandwidth, the required blocks are obtained from various peers, rather than just one, if necessary. Depending on the number of blocks needed, the blocks are requested in chunks by specifying the start block number and the end block number to download from a given peer. The node uses the list of block states to keep track of which blocks each peer has, so this information is used to determine which connected peers to request block chunks from. This process is depicted in the diagram below:

![](https://docs.eosnetwork.com/assets/images/p2p-node-peer-sync-28e46f9ea2fa6d3c66add9512e8c7ded.png)

When both LIB and head blocks are caught up with respect to the peer, the operation mode in the Sync Manager is switched from catch-up mode to in-sync mode.

### 3.4. Mode Switching[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#34-mode-switching) <a href="#id-34-mode-switching" id="id-34-mode-switching"></a>

Eventually, both the node and its peer receive new fresh blocks from other peers, which in turn push the blocks to their respective local chains. This causes the head blocks on each chain to advance. Depending on which chain grows first, one of the following actions occur:

* The node sends a catch up request message to the peer with its head block info.
* The node sends a catch up notice message to inform the peer it needs to sync.

In the first case, the node switches the mode from in-sync to head catchup mode. In the second case, the peer switches to head catchup mode after receiving the notice message from the node. In practice, in-sync mode is short-lived. When the VEXANIUM blockchain is very busy, nodes spend most of their time in catchup mode validating transactions and syncing their chains after catchup messages are received.

## 4. Protocol Algorithm

The p2p protocol algorithm runs on every node, forwarding validated transactions and validated blocks. Starting VEXCHAIN v2.0, a node also forwards block IDs of unvalidated blocks it has received. In general, the simplified process is as follows:

1. A node requests data or sends a control message to a peer.
2. If the request can be fulfilled, the peer executes the request; repeat 1.

The data messages contain the block contents or the transaction contents. The control messages make possible the syncing of blocks and transactions between the node and its peers (see Protocol Messages). In order to allow such synchronization, each node must be able to retrieve information about its own state of blocks and transactions as well as that of its peers.

### 4.1. Node/Peers Status[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#41-nodepeers-status) <a href="#id-41-nodepeers-status" id="id-41-nodepeers-status"></a>

Before attempting to sync state, each node needs to know the current status of its own blocks and transactions. It must also be able to query other peers to obtain the same information. In particular, nodes must be able to obtain the following on demand:

* Each node can find out which blocks and transactions it currently has.
* All nodes can find out which blocks and transactions their peers have.
* Each node can find out which blocks and transactions it has requested.
* All nodes can find out when each node has received a given transaction.

To perform these queries, and thereafter when syncing state, the Net Plugin defines specific communication messages to be exchanged between the nodes. These messages are sent by the Net Plugin when transmitted and received over a TCP connection.

### 4.2. Protocol Messages[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#42-protocol-messages) <a href="#id-42-protocol-messages" id="id-42-protocol-messages"></a>

The p2p protocol defines the following control messages for peer to peer node communication:

| Control Message        | Description                                                          |
| ---------------------- | -------------------------------------------------------------------- |
| `handshake_message`    | initiates a connection to another peer and sends LIB/head status.    |
| `chain_size_message`   | requests LIB/head status from peer. Not currently implemented.       |
| `go_away_message`      | sends disconnection notification to a connecting or connected peer.  |
| `time_message`         | transmits timestamps for peer synchronization and error detection.   |
| `notice_message`       | informs peer which blocks and transactions node currently has.       |
| `request_message`      | informs peer which blocks and transaction node currently needs.      |
| `sync_request_message` | requests peer a range of blocks given their start/end block numbers. |

The protocol also defines the following data messages for exchanging the actual contents of a block or a loose transaction between peers on the p2p network:

| Data Message         | Description                                  |
| -------------------- | -------------------------------------------- |
| `signed_block`       | serialized contents of a signed block.       |
| `packed_transaction` | serialized contents of a packed transaction. |

#### 4.2.1. Handshake Message[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#421-handshake-message) <a href="#id-421-handshake-message" id="id-421-handshake-message"></a>

The handshake message is sent by a node when connecting to another peer. It is used by the connecting node to pass its chain state (LIB number/ID and head block number/ID) to the peer. It is also used by the peer to perform basic validation on the node the first time it connects, such as whether it belongs to the same blockchain, validating that fields are within range, detecting inconsistent block states on the node, such as whether its LIB is ahead of the head block, etc. The handshake message consists of the following fields:

| Message Field                 | Description                                                                           |
| ----------------------------- | ------------------------------------------------------------------------------------- |
| `network_version`             | internal net plugin version to keep track of protocol updates.                        |
| `chain_id`                    | hash value of the genesis state and config options. Used to identify chain.           |
| `node_id`                     | the actual node ID that distinguishes the peer’s node from the other peers.           |
| `key`                         | public key for peer to validate node; may be a producer or peer key, or empty.        |
| `time`                        | timestamp the handshake message was created since epoch (Jan 1, 2000).                |
| `token`                       | SHA-256 digest of timestamp to prove node owns private key of the key above.          |
| `sig`                         | signature for the digest above after node signs it with private key of the key above. |
| `p2p_address`                 | IP address of node.                                                                   |
| `last_irreversible_block_num` | the actual block count of the LIB block since genesis.                                |
| `last_irreversible_block_id`  | a hash of the serialized contents of the LIB block.                                   |
| `head_num`                    | the actual block count of the head block since genesis.                               |
| `head_id`                     | a hash of the serialized contents of the head block.                                  |
| `os`                          | operating system where node runs. This is detected automatically.                     |
| `agent`                       | the name supplied by node to identify itself among its peers.                         |
| `generation`                  | counts `handshake_message` invocations; detects first call for validation.            |

If all checks succeed, the peer proceeds to authenticate the connecting node based on the `--allowed-connection` setting specified for that peer's net plugin when `nodeos` started:

* **Any**: connections are allowed without authentication.
* **Producers**: peer key is obtained via p2p protocol.
* **Specified**: peer key is provided via settings.
* **None**: the node does not allow connection requests.

The peer key corresponds to the public key of the node attempting to connect to the peer. If authentication succeeds, the receiving node acknowledges the connecting node by sending a handshake message back, which the connecting node validates in the same way as above. Finally, the receiving node checks whether the peer’s head block or its own needs syncing. This is done by checking the state of the head block and the LIB of the connecting node with respect to its own. From these checks, the receiving node determines which chain needs syncing.

#### 4.2.2. Chain Size Message[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#422-chain-size-message) <a href="#id-422-chain-size-message" id="id-422-chain-size-message"></a>

The chain size message was defined for future use, but it is currently not implemented. The idea was to send ad-hoc status notifications of the node’s chain state after a successful connection to another peer. The chain size message consists of the following fields:

| Message Field                 | Description                                             |
| ----------------------------- | ------------------------------------------------------- |
| `last_irreversible_block_num` | the actual block count of the LIB block since genesis.  |
| `last_irreversible_block_id`  | a hash of the serialized contents of the LIB block.     |
| `head_num`                    | the actual block count of the head block since genesis. |
| `head_id`                     | a hash of the serialized contents of the head block.    |

The chain size message is superseded by the handshake message, which also sends the status of the LIB and head blocks, but includes additional information so it is preferred.

#### 4.2.3. Go Away Message[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#423-go-away-message) <a href="#id-423-go-away-message" id="id-423-go-away-message"></a>

The go away message is sent to a peer before closing the connection. It is usually the result of an error that prevents the node from continuing the p2p protocol further. The go away message consists of the following fields:

| Message Field | Description                                                              |
| ------------- | ------------------------------------------------------------------------ |
| `reason`      | an error code signifying the reason to disconnect from peer.             |
| `node_id`     | the node ID for the disconnecting node; used for duplicate notification. |

The current reason codes are defined as follows:

* **No reason**: indicate no error actually; the default value.
* **Self**: node was attempting to self connect.
* **Duplicate**: redundant connection detected from peer.
* **Wrong chain**: the peer's chain ID does not match.
* **Wrong version**: the peer's network version does not match.
* **Forked**: the peer's irreversible blocks are different
* **Unlinkable**: the peer sent a block we couldn't use
* **Bad transaction**: the peer sent a transaction that failed verification.
* **Validation**: the peer sent a block that failed validation.
* **Benign other**: reasons such as a timeout. not fatal but warrant resetting.
* **Fatal other**: a catch all for fatal errors that have not been isolated yet.
* **Authentication**: peer failed authentication.

After the peer receives the go away message, the peer should also close the connection.

#### 4.2.4. Time Message[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#424-time-message) <a href="#id-424-time-message" id="id-424-time-message"></a>

The time message is used to synchronize events among peers, measure time intervals, and detect network anomalies such as duplicate messages, invalid timestamps, broken nodes, etc. The time message consists of the following fields:

| Message Field | Description                                                          |
| ------------- | -------------------------------------------------------------------- |
| `org`         | origin timestamp; set when marking the beginning of a time interval. |
| `rec`         | receive timestamp; set when a message arrives from the network.      |
| `xmt`         | transmit timestamp; set when a message is placed on the send queue.  |
| `dst`         | destination timestamp; set when marking the end of a time interval.  |

#### 4.2.5. Notice Message[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#425-notice-message) <a href="#id-425-notice-message" id="id-425-notice-message"></a>

The notice message is sent to notify a peer which blocks and loose transactions the node currently has. The notice message consists of the following fields :

| Message Field  | Description                                              |
| -------------- | -------------------------------------------------------- |
| `known_trx`    | sorted list of known transaction IDs node has available. |
| `known_blocks` | sorted list of known block IDs node has available.       |

Notice messages are lightweight since they only contain block IDs and transaction IDs, not the actual block or transaction.

#### 4.2.6. Request Message[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#426-request-message) <a href="#id-426-request-message" id="id-426-request-message"></a>

The request message is sent to notify a peer which blocks and loose transactions the node currently needs. The request message consists of the following fields:

| Message Field | Description                                                |
| ------------- | ---------------------------------------------------------- |
| `req_trx`     | sorted list of requested transaction IDs required by node. |
| `req_blocks`  | sorted list of requested block IDs required by node.       |

#### 4.2.7. Sync Request Message[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#427-sync-request-message) <a href="#id-427-sync-request-message" id="id-427-sync-request-message"></a>

The sync request message requests a range of blocks from peer. The sync request message consists of the following fields:

| Message Field | Description                                                      |
| ------------- | ---------------------------------------------------------------- |
| `start_block` | start block number for the range of blocks to receive from peer. |
| `end_block`   | end block number for the range of blocks to receive from peer.   |

Upon receipt of the sync request message, the peer sends back the actual blocks for the range of block numbers specified.

### 4.3. Message Handler[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#43-message-handler) <a href="#id-43-message-handler" id="id-43-message-handler"></a>

The p2p protocol uses an event-driven model to process messages, so no polling or looping is involved when a message is received. Internally, each message is placed in a queue and the next message in line is dispatched to the corresponding message handler for processing. At a high level, the message handler can be defined as follows:

```
   receiver/read handler:
      if handshake message:
         verify that peer's network protocol is valid
         if node's LIB < peer's LIB:
            sync LIB with peer's; continue
         if node's LIB > peer's LIB:
            send LIB catchup notice message; continue
      if notice message:
         update list of blocks/transactions known by remote peer
      if trx message:
         insert into global state as unvalidated
         validate transaction; drop if invalid, forward if valid
      else
         close the connection
```

### 4.4. Send Queue[​](https://docs.eosnetwork.com/docs/latest/protocol/network_peer_protocol#44-send-queue) <a href="#id-44-send-queue" id="id-44-send-queue"></a>

Protocol messages are placed in a buffer queue and sent to the appropriate connected peer. At a higher level, a node performs the following operations with each connected peer in a round-robin fashion:

```
   send/write loop:
      if peer knows the LIB:
         if peer does not know we have a block or transaction:
            next iteration
         if peer does not know about a block:
            send transactions for block that peer does not know
            next iteration 
         if peer does not know about transactions:
            sends oldest transactions unknown to remote peer
            next iteration
         wait for new validated block, transaction, or peer signal
      else:
         assume peer is in catchup mode (operating on request/response)
         wait for notice of sync from the read loop
```

## 5. Protocol Improvements

Any software updates to the p2p protocol must also scale progressively and consistently across all nodes. This translates into installing updates that reduce operation downtime and potentially minimize it altogether while deploying new functionality in a backward compatible manner, if possible. On the other hand, data throughput can be increased by taking measures that minimize message footprint, such as using data compression and binary encoding of the protocol messages.


# Accounts and Permissions

## 1. Overview

An account identifies a participant in the VEXANIUM blockchain. A participant can be an individual or a group depending on the assigned permissions within the account. Accounts also represent the smart contract actors that push and receive actions to and from other accounts in the blockchain. Actions are always contained within transactions. A transaction can be one or more atomic actions.

Permissions associated with an account are used to authorize actions and transactions to other accounts. Each permission is linked to an authority table which contains a threshold that must be reached in order to allow the action associated with the given permission to be authorized for execution. The following diagram illustrates the relationship between accounts, permissions, and authorities.

![](https://docs.eosnetwork.com/assets/images/accts_perms_auths-20ceff9bc7190583671475a1c4c488ab.png)

The example above depicts `alice`'s account, her named permissions along with their hierarchical dependencies, and her linked `active` authority table. It also shows that a weight threshold of two must be reached in `alice`'s `active` authority in order to allow an action associated with the active permission to be executed by or on behalf of `alice`.

## 2. Accounts

Each account is identified by a human readable name between 1 and 12 characters in length. The characters can include a-z, 1-5, and optional dots (.) except the last character. This allows exactly one exa ($2^{60}$) accounts minus one:

$$ 31^{1} \cdot \sum\_{n=0}^{n=11} 32^{n} = 2^{60}-1 = 1,152,921,504,606,846,975 $$

which is in the order of $1 \times 10^{18}$.

Ownership of each account on the VEXANIUM blockchain is solely determined by the account name. Therefore, an account can update its keys without having to redistribute them to other parties.

### 2.1. Account Schema[​](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#21-account-schema) <a href="#id-21-account-schema" id="id-21-account-schema"></a>

Besides the account name, the blockchain associates other fields with each account instance stored in the chain database, such as ram quota/usage, cpu/net limits/weights, voter info, etc. (see `account` schema below). More importantly, each account holds the list of named permissions assigned to it. This allows a flexible permission structure that makes single or multi-user authorizations possible (see 3. Permissions).

#### account schema[​](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#account-schema) <a href="#account-schema" id="account-schema"></a>

| Name                       | Type                     | Description                                                                                                          |
| -------------------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------- |
| `account_name`             | `name`                   | encoded 13-char account name                                                                                         |
| `head_block_num`           | `uint32_t`               | last block account was referenced                                                                                    |
| `head_block_time`          | `time_point`             | last time account was referenced                                                                                     |
| `privileged`               | `bool`                   | True, if privileged account, False otherwise                                                                         |
| `last_code_update`         | `time_point`             | time account code was set/updated                                                                                    |
| `created`                  | `time_point`             | time account was created                                                                                             |
| `core_liquid_balance`      | `asset`                  | current balance of token asset                                                                                       |
| `ram_quota`                | `int64_t`                | maximum RAM amount for account                                                                                       |
| `net_weight`               | `int64_t`                | weight for net limit percentage (weight/total)                                                                       |
| `cpu_weight`               | `int64_t`                | weight for cpu limit percentage (weight/total)                                                                       |
| `net_limit`                | `account_resource_limit` | total net used, available, and max                                                                                   |
| `cpu_limit`                | `account_resource_limit` | total cpu used, available, and max                                                                                   |
| `ram_usage`                | `int64_t`                | amount of RAM in bytes used by account                                                                               |
| `permissions`              | array of `permission`    | list of named [permissions](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#3-permissions) |
| `total_resources`          | `variant`                | total cpu/net weights for all accounts                                                                               |
| `self_delegated_bandwidth` | `variant`                | cpu/net stake delegated from self                                                                                    |
| `refund_request`           | `variant`                | cpu/net refund amounts for token unstaking                                                                           |
| `voter_info`               | `variant`                | name of voter, proxy or producers, vote stake                                                                        |
| `rex_info`                 | `variant`                | vote stake and rex balance if applicable                                                                             |

The `name` type consists of a 64-bit value that encodes alphanumeric characters into 5-bit chunks, except the last character, if any, which uses a 4-bit chunk. The `name` type is used to encode account names, action names, etc. The `time_point` type stores timestamps in microseconds. The `asset` type associates a currency or token symbol with a given amount. The `account_resource_limit` type keeps track of the amount used, available, and maximum that can be used in a given window for the given resource (NET or CPU). The `permission` type holds the list of permission levels associated with the account (see 3. Permissions).

### 2.2. Actions and Transactions[​](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#22-actions-and-transactions) <a href="#id-22-actions-and-transactions" id="id-22-actions-and-transactions"></a>

Besides identifying participants in the VEXANIUM blockchain, actions and transactions are the other reason for accounts to exist. An action requires one or more actors to push or send the action, and a receiver account to whom the action is directed. A receiver account is also needed when leaving proof, in an action receipt, that the action was pushed to the intended recipient.

In contrast, transactions are agnostic to accounts, although there is an indirect link to them through their associated keys. Transactions are signed using one or more signing keys belonging to the one or more actors involved in the actions that form the transaction. This can be the receiving account itself or other authorized actors specified on the authority table from the receiving account's permission.

## 3. Permissions

Permissions control what VEX accounts can do and how actions are authorized. This is accomplished through a flexible permission structure that links each account to a list of hierarchical named permissions, and each named permission to an authority table (see `permission` schema below).

### permission schema[​](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#permission-schema) <a href="#permission-schema" id="permission-schema"></a>

| Name            | Type        | Description                                                                                                                |
| --------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------- |
| `perm_name`     | `name`      | named permission                                                                                                           |
| `parent`        | `name`      | parent's named permission                                                                                                  |
| `required_auth` | `authority` | associated [authority](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#32-authority-table) table |

The `parent` field links the named permission level to its parent permission. This is what allows hierarchical permission levels in VEXANIUM.

### 3.1. Permission Levels[​](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#31-permission-levels) <a href="#id-31-permission-levels" id="id-31-permission-levels"></a>

A named permission may be created under another permission, thereby allowing a hierarchical parent-children permission structure. This makes implicit action authorizations possible by allowing a given `actor:child-permission` authorization within an action to be implicitly satisfied if the `actor:parent-permission` is also satisfied. An authorization quorum or "threshold" must still be met for the action to be authorized for execution (see 3.2.2. Authority Threshold).

CONTRACT-LEVEL PERMISSIONS

It is also possible to create an implicit link between two accounts with the same named permission (for authorization satisfaction purposes). This can be achieved by associating an explicit named permission to the smart contract (different from the "minimum permission" for that `contract[::action]`). However, defining explicit `actor:permission` authorizations within actions is preferred versus associating permissions to the whole contract.

Every account has two default named permissions when created, owner and active. They have a parent-child relationship by default, although this can be customized by adding other permission levels and hierarchies.

#### 3.1.1. Owner permission[​](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#311-owner-permission) <a href="#id-311-owner-permission" id="id-311-owner-permission"></a>

The owner permission sits at the root of the permission hierarchy for every account. It is therefore the highest relative permission an account can have within its permission structure. Although the owner permission can do anything a lower level permission can, it is typically used for recovery purposes when a lower permission has been compromised. As such, keys associated with the owner permission are typically kept in cold storage, not used for signing regular operations.

#### 3.1.2. Active permission[​](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#312-active-permission) <a href="#id-312-active-permission" id="id-312-active-permission"></a>

In the current VEXANIUM implementation, the implicit default permission linked to all actions is `active`, which sits one level below the `owner` permission within the hierarchy structure. As a result, the `active` permission can do anything the `owner` permission can, except changing the keys associated with the owner. The `active` permission is typically used for voting, transferring funds, and other account operations. For more specific actions, custom permissions are typically created below the `active` permission and mapped to specific contracts or actions. Refer to the Cleos Set Account Command for more details.

CUSTOM PERMISSIONS

VEXANIUM allows to create custom hierarchical permissions that stem from the owner permission. This allows finer control over action authorizations. It also strengthens security in case the `active` permission gets compromised.

### 3.2. Authority Table[​](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#32-authority-table) <a href="#id-32-authority-table" id="id-32-authority-table"></a>

Each account's permission can be linked to an authority table used to determine whether a given action authorization can be satisfied. The authority table contains the applicable permission name and threshold, the "factors" and their weights, all of which are used in the evaluation to determine whether the authorization can be satisfied. The permission threshold is the target numerical value that must be reached to satisfy the action authorization (see `authority` schema below).

#### authority schema[​](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#authority-schema) <a href="#authority-schema" id="authority-schema"></a>

| Name        | Type                               | Description                                     |
| ----------- | ---------------------------------- | ----------------------------------------------- |
| `threshold` | `uint32_t`                         | threshold value to satisfy authorization        |
| `keys`      | array of `key_weight`              | list of public keys and weights                 |
| `accounts`  | array of `permission_level_weight` | list of `account@permission` levels and weights |
| `waits`     | array of `wait_weight`             | list of time waits and weights                  |

The `key_weight` type contains the actor's public key and associated weight. The `permission_level_weight` type consists of the actor's `account@permission` level and associated weight. The `wait_weight` contains the time wait and associated weight (used to satisfy action authorizations in delayed user transactions (see Transactions Protocol: 3.6.3. Delayed User Transactions). All of these types allow to define lists of authority factors that are used for satisfaction of action authorizations (see 3.2.1. Authority factors below).

#### 3.2.1. Authority Factors[​](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#321-authority-factors) <a href="#id-321-authority-factors" id="id-321-authority-factors"></a>

Every authority table linked to a given permission lists potential "factors" explicitly used in the evaluation of the action authorization. A factor type can be one of the following:

* Actor's account name and permission level
* Actor's public key
* Time wait

The potential actors who may execute the action are specified by either public key or account name in the authority table. Time waits are special factors which are satisfied by publishing a transaction with a delay in excess of the defined time. These carry weights as well that may contribute to satisfy the threshold.

#### 3.2.2. Authority Threshold[​](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#322-authority-threshold) <a href="#id-322-authority-threshold" id="id-322-authority-threshold"></a>

Authorization over a given action is determined by satisfying all explicit authorizations specified in the action instance (see Transactions Protocol: 3.4.3. Action Instance). Those are in turn individually satisfied by evaluating each "factor" (account, public key, wait) for satisfaction (potentially recursively) and summing the weights of those that are satisfied. If the sum equals or exceeds the weight threshold, the action is authorized.

#### 3.2.3. Authority Example[​](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#323-authority-example) <a href="#id-323-authority-example" id="id-323-authority-example"></a>

The authority table for `alice`'s `publish` named permission is shown below. According to its contents, in order to authorize an action under that permission, a threshold of two must be reached. Since both `bob@active` and `stacy@active` factors have a weight of two, either one can satisfy the action authorization. This means that either `bob` or `stacy` with a permission level of `active` or higher can independently execute any action under `alice`'s `publish` permission.

| Permission        | Account / Public Key | Weight | Threshold |
| ----------------- | -------------------- | ------ | --------- |
| publish           | bob\@active          | 2      | 2         |
| stacy\@active     | 2                    |        |           |
| EOS7Hnv4iBfcw2... | 1                    |        |           |
| EOS3Wo1p9er7fh... | 1                    |        |           |

Alternatively, it would require two acounts with public keys `EOS7Hnv4iBfcw2...` and `EOS3Wo1p9er7fh...` to satisfy the action authorization. This is because each public key has a weight of 1 in the authority table.

### 3.3. Permission Mapping[​](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#33-permission-mapping) <a href="#id-33-permission-mapping" id="id-33-permission-mapping"></a>

Any given account can define a mapping between any of its named permissions and a smart contract or action within that contract. This sets the "minimum permission" required for that `contract[::action]`. It does not afford, however, any other account any access or authority to execute that `contract[::action]`. This is by design and the process is controlled by a permission evaluation mechanism, described next.

### 3.4. Permission Evaluation[​](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#34-permission-evaluation) <a href="#id-34-permission-evaluation" id="id-34-permission-evaluation"></a>

When determining whether an action is authorized to be executed, the VEXANIUM software first checks whether the signatures provided in the transaction are valid (see 3.4.2. Signature Validation). Then it proceeds to check the authorization of all the actions included in the transaction. This is where permissions are evaluated. If there is at least one action that fails to be authorized (by not meeting the authority threshold (see 3.2.2. Authority Threshold), the transaction fails.

#### 3.4.1. Custom Permissions[​](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#341-custom-permissions) <a href="#id-341-custom-permissions" id="id-341-custom-permissions"></a>

By default every account on the VEXANIUM blockchain is linked to the `active` permission. Again, this can be customized by creating children permissions under `active` or by creating alternate permissions under `owner` (see 3.1. Permission Levels). Creating custom permissions under `owner` (separate from `active`) is recommended. This is because if the keys associated with the `active` permission are compromised, the security of the account will not be compromised.

USE CASE: SOCIAL MEDIA

Say we have a `publish` permission created for message posting on a social media application. However, we do not want to associate that permission with sensitive actions, such as transferring or withdrawing funds. Under this scenario, it makes sense to link the `social::post` action to the `publish` permission. This allows to define an authority structure which can authorize `post`, but cannot satisfy the default `active` permission for all other actions. That authority structure could delegate itself to a different account at any named permission level. If it did so to another `publish` permission on another account, that would be purely coincidental.

#### 3.4.2. Signature Validation[​](https://docs.eosnetwork.com/docs/latest/protocol/accounts_and_permissions#342-signature-validation) <a href="#id-342-signature-validation" id="id-342-signature-validation"></a>

Satisfying authorities linked to permissions involves first and foremost the validation/recovery of the public keys that signed the transaction. After a signed transaction is received by a node, the set of signatures is extracted from the transaction instance. The set of public keys are then recovered from the signatures. Then for all actions included in the transaction, the node checks that each `actor:permission` meets or exceeds the minimum permission as defined by the per-account permission links.

Once validated, the set of recovered keys are provided to the authorization manager instance along with the amount of time "waited". The authorization manager then proceeds to check whether the provided "factors" satisfy the authorities, potentially recursing into other linked permission levels/authorities (see 3.2. Authority Table and Transactions Protocol: 3.4. Verify Transaction for more information).


# Vexanium DAO - Governance

**What's governance?**&#x20;

{% content-ref url="/pages/aR9bCgMiAr6iVdVDQl2c" %}
[DPOS Governance](/vexanium-dao-governance/dpos-governance)
{% endcontent-ref %}

{% content-ref url="/pages/r3hgaFiwTdSeXinEmgy7" %}
[Active Block Producers](/vexanium-dao-governance/active-block-producers)
{% endcontent-ref %}

**Governance** is the way that decisions get made. To understand what this means, let's compare traditional web2 governance to web3 governance.

**What's governance**? Governance is the way that decisions get made. To understand what this means, let's compare traditional web2 governance to web3 governance.

**Web2 technologies** are traditionally built by corporations governed by a board of directors. This board is usually a small group of people elected by shareholders.

When a corporate decision needs to be made, members of the board meet and vote. The board's decision-making protocols aren't always visible to shareholders. Although the board has a fiduciary duty to its shareholders, shareholders must trust the board. This is a sort of social contract expressed as corporate legalese and enforced by law.

**Web3 technologies** (like Vexanium's protocols and chains) are often built initially by corporations governed by a board of directors. Once these technologies achieve product-market fit and a community of users and stakeholders develops, decision-making authority can be gradually decentralized. This is called progressive decentralization, and it's what Vexanium is doing.

**Delegated Proof Of Stake (DPoS)** is the underlying consensus mechanism of Vexanium . While anyone can run a node to fully validate the Vexanium blockchain in a trustless manner, only special, selected entities known as Block Producers (BPs) are allowed to produce blocks and determine the canonical blockchain. Unlike Proof Of Stake (PoS), the validating entities taking part in the consensus process, the BPs are not required to lock up tokens. Instead, individual token holders delegate their share of tokens to their preferred BP candidates. The top 21 candidates ranked by aggregate delegated token stake are selected as the active block producers.

**VEX holders** can change their delegations at any time, and within minutes the selection of the 21 active BPs can automatically change. So the BPs only maintain their privileges for as long as the delegating token holders continue to trust them to carry out their responsibilities.

**In DPoS**, each active block producer has a limited time window under which they have to publish a new block. Suppose an active BP continually misses their block creation times or consistently produces blocks that are missing expected transactions. In that case, VEX token holders, using their stake, can change their delegations to replace them with better block producers that are on standby.


# DPOS Governance

**Delegate Proof of Stake (DPoS)** is a consensus algorithm used by the Vexanium blockchain. DPoS is designed to achieve both decentralization and efficiency in block production and verification.

In Vexanium's DPoS, VEX holders in the network can vote for delegates who will act as block producers and network maintainers. These delegates are responsible for creating new blocks and validating transactions on the blockchain. The number of delegates in Vexanium is typically limited to a fixed number.

The voting power of token holders is proportional to the number of tokens they hold. They can use their voting power to select delegates they trust to maintain the network effectively. The delegates with the highest number of votes are given the opportunity to produce blocks and earn block rewards.

One of the key features of DPoS is its ability to achieve fast block confirmation times. In Vexanium, blocks are typically confirmed within a few seconds, allowing for quicker transaction processing compared to other consensus algorithms.

DPoS also introduces a mechanism for vote delegation. Token holders can delegate their voting power to trusted individuals or entities, allowing them to vote on their behalf. This feature enables token holders to participate in the network's consensus even if they don't actively vote themselves.

By combining the principles of decentralization, community governance through voting, and efficient block production, Vexanium's DPoS consensus algorithm aims to create a scalable and secure blockchain network.

**Delegated Proof Of Stake (DPoS)** is the underlying consensus mechanism of Vexanium , While anyone can run a node to fully validate the Vexanium blockchain in a trustless manner, only special, selected entities known as Block Producers (BPs) are allowed to produce blocks and determine the canonical blockchain. Unlike Proof Of Stake (PoS), the validating entities taking part in the consensus process, the BPs are not required to lock up tokens. Instead, individual token holders delegate their share of tokens to their preferred BP candidates. The top 21 candidates ranked by aggregate delegated token stake are selected as the active block producers.

VEX holders can change their delegations at any time, and within minutes the selection of the 21 active BPs can automatically change. So the BPs only maintain their privileges for as long as the delegating token holders continue to trust them to carry out their responsibilitie

**Stakeholders and Delegates**

The actual selection of the active producers (the producer schedule) is open for voting every schedule round and it involves all Vexanium stakeholders who exercise their right to participate. In practice, the rankings of the active producers do not change often, though. The stakeholders are regular Vexanium account holders who vote for their block producers of preference to act on their behalf as DPoS delegates. A major departure from regular DPoS, however, is that once elected, all block producers have equal power regardless of the ranking of votes obtained. In other DPoS models, voting power is proportional to the number of votes obtained by each delegate.


# Active Block Producers

What Is A Block Producer?

Block producer is a term used in Vexanium blockchain ecosystems that use Delegated Proof of Stake (DPoS), Block producers similar to miners on a proof-of-work (PoW) network or Validator nodes on a proof-of-stake (PoS) blockchain. Block producers which allows users to vote block producers to validate and generate blocks. Block producers are also known as delegates or witnesses. They are in charge of producing new blocks that contain recent network transactions as well as blockchain evidence that the chain's present state is legitimate.

Block producers are critical to the network's functioning. They collect transaction data and store it in blocks to validate them on blockchain networks. Blocks are transmitted to the network for validation after they have been prepared. Block producer who produce blocks upload the transaction data to the blockchain after they have been validated. To understand the concept of BP in more detail, The Vexanium network is governed by Block Producers, who are decentralized entities. They are in charge of achieving consensus and delivering transaction or data blocks to the Vexanium network.

Delegated proof-of-stake is a variant of PoS in which validators are elected by the network's vex token holders rather than being picked at random.

All VEX coins holders in the Vexanium mainnet vote for 21 trustworthy accounts to act as block producers and make decisions on their behalf. They are chosen from the top 21 Block candidates with the highest votes. 21 Active producers known as "Active block producers." The Vexanium design employs Delegated Proof of Stake (DPOS), which involves the community selecting trusted accounts (also known as "trustees") to produce blocks as Active Block producers . and other Blockproducer that not selected as active Bp will be part of Standby Blockproducer

In Vexanium all Blockproducers will get reward fron network , Active blockproducers reward will get reward from Block creation reward known as BPAY and Votepay known as VPAY , and standby blockproducers will get vote pay rewards

The chosen block producers assist the VEXANIUM mainnet with processing power and bandwidth. Their primary responsibility is to gather transaction data, bundle it into blocks, and disseminate those blocks to other block producers. They submit the blocks to the blockchain and get rewarded after the verification is done. However, if any of the top 21 block producers do not generate any blocks for the next 24 hours, they will be taken off the list.


# API Reference

Dive into the specifics of each API endpoint on Vexanium Blockchain by checking out our complete documentation. , this api is made by community we will update the list  , you can also follow on VEX api monitor on telegram bot > <https://t.me/vexnodemon>

## List API Reference

```
// 
https://api.databisnis.id/
https://explorer.vexanium.com:6960/
http://209.97.162.124:8080/
https://vexascan.com:8443/
https://v2.vexascan.com:2096/v2/docs/static/index.html
http://api.vex.proit.id/v1/chain/get_info
https://vex.speakapp.me/v2/health
```

## Peer per to Peer Address

```
// --p2p-peer-address explorer.vexanium.com:8091
--p2p-peer-address 188.166.233.69:8092
--p2p-peer-address 209.97.162.124:8091
--p2p-peer-address 34.81.37.55:9010 \related to users:
```


# API V2 Migrations

## V1 History Alternatives

The latest VEXANIUM V2 , release officially ends support for the legacy V1 History plugin. Therefore, block producers and node operators who have integrations that rely on V1 History must seek alternative solutions.

### Production Ready Alternatives[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#production-ready-alternatives) <a href="#production-ready-alternatives" id="production-ready-alternatives"></a>

The following battle tested and V1 compliant history solutions are available:

* Hyperion History Solution
* Roborovski History API

## Roborovski History API

### Overview[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#overview) <a href="#overview" id="overview"></a>

Roborovski History API is designed as a drop-in replacement for the V1 history API. It relies on the Trace API Plugin to extract the history data and then packs it in V1 format before it gives it back to the client request.

### Who Runs Roborovski History API[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#who-runs-roborovski-history-api) <a href="#who-runs-roborovski-history-api" id="who-runs-roborovski-history-api"></a>

Roborovski History API is implemented and ran by Greymass Inc.

### What makes the Roborovski History API safe[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#what-makes-the-roborovski-history-api-safe) <a href="#what-makes-the-roborovski-history-api-safe" id="what-makes-the-roborovski-history-api-safe"></a>

Roborovski History API has a high degree of safety because it is created by Greymass Inc. which has been a credible and stable block producer and wallet developer (Anchor) company for EOS, WAX, TELOS, PROTON, FIO and other EOS based chains.

### Understanding the risks associated with hosted solutions[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#understanding-the-risks-associated-with-hosted-solutions) <a href="#understanding-the-risks-associated-with-hosted-solutions" id="understanding-the-risks-associated-with-hosted-solutions"></a>

If you rely on a hosted solution, you are reliant on the correctness of data and processes that you do not control. Therefore, if your application critically relies on on-chain data, it is highly recommended that you host your own history solution. However, since Roborovsky is currently closed source, if you want to run your own node you will need to see Hyperion below.

### Roborovski History API and V1 History Standard[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#roborovski-history-api-and-v1-history-standard) <a href="#roborovski-history-api-and-v1-history-standard" id="roborovski-history-api-and-v1-history-standard"></a>

Roborovski History API is compliant with the V1 history API standard. It also adds two more functions on top of the standard ones.

Existing V1 History Plugin integrators can simply replace their current API url with Greymass' one and it will work flawlessly.

### API Reference[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#api-reference) <a href="#api-reference" id="api-reference"></a>

#### How To Connect[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#how-to-connect) <a href="#how-to-connect" id="how-to-connect"></a>

The Roborovski History API connection endpoint is `https://eos.greymass.com`

#### Functions List[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#functions-list) <a href="#functions-list" id="functions-list"></a>

* Get Actions (V1 compatible)
  * POST `https://eos.greymass.com/v1/history/get_actions`
* Get Transaction (V1 compatible)
  * POST `https://eos.greymass.com/v1/history/get_transaction`
* Get Transaction (new method, not in V1)
  * GET `https://eos.greymass.com/v1/history/get_transaction?id=<TXID>`
* Get Actions (new method, not in V1)
  * GET `https://eos.greymass.com/v1/history/get_actions?account_name=<NAME>`

#### Performance Numbers[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#performance-numbers) <a href="#performance-numbers" id="performance-numbers"></a>

As it was observed and measured so far the Roborovski History API supports at least 50 requests per second; this limit is defined as a low load, the solution is capable of handling more, but no higher specific limits are known at the moment.

Hyperion History Solution

## Hyperion History Solution

### Overview[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#overview-1) <a href="#overview-1" id="overview-1"></a>

Hyperion History is a full history solution for indexing, storing and retrieving EOS-based blockchain historical data. It can be deployed by node operators to provide data querying support for actions, transactions, and blocks stored on the blockchain.

Hyperion History API provides both V2 and V1 (legacy history plugin) endpoints. Therefore, it is fully compliant with V1 history.

### What makes the Hyperion safe[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#what-makes-the-hyperion-safe) <a href="#what-makes-the-hyperion-safe" id="what-makes-the-hyperion-safe"></a>

Hyperion is developed and maintained by EOS Rio: <https://eosrio.io/hyperion/> and has been battle tested on every Antelope public network (EOS, WAX, TELOS, PROTON, FIO, etc).

* Github: <https://github.com/vexanium/hyperion-history-api>

### Requirements[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#requirements) <a href="#requirements" id="requirements"></a>

Hyperion History requires the following components for a fully functional Hyperion API deployment:

* **Elasticsearch Cluster** - stores all indexed data
* **RabbitMQ** - message/data transport/queue for indexer stages
* **Redis** - used as predictive temporary database
* **EOS State History plugin** - feeds action traces and state deltas to indexer via websocket
* **Hyperion Indexer** - indexes State History data (launched from PM2 Node.js manager)
* **Hyperion API** - API server that listens to V1/V2 requests

### Installation[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#installation) <a href="#installation" id="installation"></a>

Providers have the following options to install Hyperion History solution:

* Manual installation: <https://github.com/vexanium/hyperion-history-api>

### Set Up[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#set-up) <a href="#set-up" id="set-up"></a>

To set up Hyperion History solution after a successful installation:

* Configuration:
* Connection Configuration:&#x20;
* Chain Configuration:&#x20;

### V1 History Support[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#v1-history-support) <a href="#v1-history-support" id="v1-history-support"></a>

Hyperion History is compliant with the V1 history API standard.

#### V1 History API reference[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#v1-history-api-reference) <a href="#v1-history-api-reference" id="v1-history-api-reference"></a>

For a full description of the V1 History API endpoints supported by Hyperion History, please visit:&#x20;

* `/v1/history/get_transaction`

  Get transaction by id

  * method: `POST`
  * schema: variable | type | description -|-|- id | string | transaction id
* `/v1/history/get_actions`

  Legacy get actions query

  * method: `POST`
  * schema: variable | type | description -|-|- account\_name | type | description pos | integer | action position (pagination) offset | integer | limit of \[n] actions per page filter | string (minLength: 3) | code:name filter sort | string | sort direction (Enum: \[desc, asc, 1, -1]) after | string($date-time) | filter after specified date (ISO8601) before | string($date-time) | filter before specified date (ISO8601) parent | integer (min: 0) | filter by parent global sequence

#### Usage[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#usage) <a href="#usage" id="usage"></a>

Once Hyperion History is deployed on a server or cluster, existing V1 History Plugin clients can simply replace their current API domain URL with the one provided by the listening server or cluster.

#### Examples[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#examples) <a href="#examples" id="examples"></a>

Some examples to illustrate usage of V1 History endpoints:

* Get all actions from given transaction:

  ```
  curl -X POST https://eos.hyperion.eosrio.io/v1/history/get_transaction -d '{
    "id": "<TXID>"
  }'
  ```
* Get all actions from last 10 transactions for given account:

  ```
  curl -X POST https://eos.hyperion.eosrio.io/v1/history/get_transaction -d '{
    "account_name": "<NAME>",
    "pos": -1
  }'
  ```

### Endpoint List[​](https://docs.eosnetwork.com/docs/latest/migration-guides/v1-history-alternatives#endpoint-list) <a href="#endpoint-list" id="endpoint-list"></a>

For a list of endpoint servers using Hyperion, check:&#x20;


# Smart Contract

**What is a Smart Contract ?**

A **smart contract** is a self-executing contract with the terms of the agreement directly written into lines of code. It operates on a blockchain platform, which is typically decentralized and distributed across a network of computers. The code and the data of the smart contract are stored on the blockchain, making the contract transparent, immutable, and tamper-resistant.

Some key features of smart contracts include:

1. Autonomy: Once deployed, a smart contract operates autonomously, meaning it executes automatically based on the input it receives and the conditions it contains.
2. Trust: The transparency and immutability of blockchain technology inspire trust, as all parties can verify the contract's code and its execution on the blockchain.
3. Security: Smart contracts are protected by the underlying blockchain's consensus mechanism, making them highly secure and resistant to hacking or unauthorized modifications.
4. Cost and Efficiency: By eliminating intermediaries, smart contracts can streamline processes and reduce costs associated with traditional contract execution.

**C++ Smartcontract and Solidity Contract on Vexanium**

There are two smart contract programming languange that run on Vexanium Blockchain ,1st is C++ ( Vexanium Native smartcontract )and Solidity ( solidity contract will activated on Vexanium version 2 in late 2023 ,  These are example of smart contract that you can try to understand the codes, deploy the smart contract, and do the push actions with it.

{% content-ref url="/pages/kDf2pIMMoCxXnZuaRtOX" %}
[C++ Smart Contract](/reference/smart-contract/c++-smart-contract)
{% endcontent-ref %}

{% content-ref url="/pages/z46QK2f2tmGiD1XGXpxL" %}
[Solidity ( EVM )](/reference/smart-contract/solidity-evm)
{% endcontent-ref %}


# C++ Smart Contract

C++ is a general-purpose, free-form programming language created by Bjarne Stroustrup in 1979 at Bell Labs in Murray Hill, New Jersey, as an enhancement to the C language. Since it is an extension of C, it is also known as C with classes. It was specifically designed with an orientation towards large systems and resource-constrained software. Since its inception, C++ has expanded significantly over time. The latest version (C++20) has object-oriented, functional, and generic features in addition to low-level memory manipulation. The biggest advantage of C++ is that it is super scalable and allows developers to have a lot of control over how their applications use up resource

Vexanium Native Protocol  uses C++ as the smart contract programming language. If you are a C++ developer, you do not need to learn a new programming language to understand Smart Contract APIs and how Vexanium supports smart contract development through C++ classes and structures. With your existing C++ programming capabilities,&#x20;

you can also can learn about C++ smartcontract on Eosio c++ development and anthelope c++ contract development&#x20;


# Hello World Contract


# Simple Token Farming Contract

{% code title="examplefarm.hpp" %}

````cpp
#pragma once
#include <eosiolib/asset.hpp>
#include <eosiolib/eosio.hpp>
#include <eosiolib/singleton.hpp>
#include <eosiolib/transaction.hpp>

#define COBAADMIN "cobafinances" //account smart contract
#define COBASTAKE "cobstakepool" //account stake pool
#define COBADRAW "cobdrawpools"  //account reward

#define CBPTOKEN "cbptvextoken" //account token CBP
#define CPPTTOKEN "cobapointvex" //account token CPPT stake
#define VEXTOKEN "vex.token" //account token VEX stake

#define CBP_SYMBOL eosio::symbol("CBP", 8) //CBP decimal 8
#define CPPT_SYMBOL eosio::symbol("CPPT", 5) //CPPT decimal 5
#define VEX_SYMBOL eosio::symbol("VEX", 4) //VEX decimal 4


#define NO_TIME   2000000000
#define SECONDS_THREE_DAY  259200
#define MIN_STAKE_CPPT 1000000 //100 CPPT decimal 4
#define MAX_STAKE_CPPT eosio::asset(40000000000000000, CPPT_SYMBOL)
#define MIN_STAKE_VEX 1000 //0.1 VEX 
#define MAX_STAKE_VEX eosio::asset(40000000000000000, VEX_SYMBOL)

#define MAX_UNSTAKE_CPPT 100000000 //10K
#define MAX_UNSTAKE_VEX 100000000 //10K

// aspt => cbp
// aptt => cppt

#define CBP_VEX_STAGE_MINING eosio::asset(30000000000000, CBP_SYMBOL)
//250ribu decimal 8 token CBP

using eosio::extended_asset;
using namespace eosio;
 
static constexpr int64_t max_amount  = 10000000000000000;

namespace vexdt {
    class [[eosio::contract]] examplefarm :public eosio::contract {
    public:
        examplefarm(eosio::name receiver, eosio::name code, eosio::datastream<const char *> ds) :
                eosio::contract(receiver, code, ds),
                _global(eosio::name(COBAADMIN), eosio::name(COBAADMIN).value),
                _users(eosio::name(COBAADMIN), eosio::name(COBAADMIN).value){
        }

        //更新抵押
        ACTION doissue(const uint64_t &idfrom, const uint64_t &idto);

        ACTION init(); 

        ACTION setstop(const uint8_t &state);

        ACTION claim(const eosio::name &from, const std::string &pooltype);

        ACTION exit(const eosio::name &from, const std::string &pooltype);


        bool iscppttoken(const eosio::extended_asset &quantity)
        {
            if ((quantity.contract == eosio::name(CPPTTOKEN)) && (quantity.quantity.symbol == CPPT_SYMBOL))
            {
                return true;
            }
            return false;
        }

        bool isvextoken(const eosio::extended_asset &quantity)
        {
            if ((quantity.contract == eosio::name(VEXTOKEN)) && (quantity.quantity.symbol == VEX_SYMBOL))
            {
                return true;
            }
            return false;
        }


        void apply(eosio::name code, eosio::name action);

        void stake(const eosio::name &from,
                const eosio::asset &quantity);

        void onTransfer(const eosio::name &from,
            const eosio::name &to,
            const eosio::extended_asset &quantity,
            const std::string &memo);

        TABLE global {
            uint8_t initState;
            uint8_t stopState;

            uint64_t checkfromid;
            uint64_t maxstakeid;
            uint64_t check_update_time_doissue;

            eosio::asset all_pool_reward;//单倍池奖励

            eosio::asset total_staked_cppt;
            eosio::asset total_staked_vex;
            eosio::asset cbp_pool_reward;
            eosio::asset cbp_pool_day_reward;
            eosio::asset vex_pool_reward;
            eosio::asset vex_pool_day_reward;

            eosio::asset total_mininged_cbp_vex;
        };
        typedef eosio::singleton<"global"_n, global> global_table;


        TABLE st_user {
            uint64_t    id = 0;
            eosio::name holder;
            eosio::asset cppt_stake;
            eosio::asset vex_stake;
            uint64_t cppt_update_time;
            uint64_t vex_update_time;
            uint8_t everymonth = 0;

            eosio::asset cppt_bonus;
            eosio::asset vex_bonus;

            uint64_t primary_key() const { return id; }
            uint64_t by_holder() const { return holder.value; }
        };

        typedef eosio::multi_index<"user"_n, st_user,
                                eosio::indexed_by<"holder"_n, eosio::const_mem_fun<st_user, uint64_t, &st_user::by_holder>>
                                    > user_table;

        global_table _global;
        user_table _users;

        ACTION test()
        {
            require_auth(eosio::name(COBAADMIN));

           _global.remove( );
            auto itr = _users.begin();
            while(itr != _users.end()){
                itr = _users.erase(itr);
            }
        }
    };


    struct st_transfer
    {
        eosio::name from;
        eosio::name to;
        eosio::asset quantity;
        std::string memo;
    };

    void examplefarm::apply(eosio::name code, eosio::name action)
    {
        auto &thiscontract = *this;

        if (action == eosio::name("transfer") && (code == eosio::name(CPPTTOKEN) || code == eosio::name(VEXTOKEN)) )
        {
            auto transfer_data = eosio::unpack_action_data<st_transfer>();
            onTransfer(transfer_data.from, transfer_data.to, eosio::extended_asset(transfer_data.quantity, code), transfer_data.memo);
            return;
        }
        
        if (code != eosio::name(COBAADMIN))
            return;
        if( code == eosio::name(COBAADMIN) ) {
            switch(action.value) {
                case eosio::name("init").value: 
                    execute_action(eosio::name(COBAADMIN), eosio::name(code), &examplefarm::init); 
                    break;
                case eosio::name("setstop").value: 
                    execute_action(eosio::name(COBAADMIN), eosio::name(code), &examplefarm::setstop); 
                    break;
                case eosio::name("test").value: 
                    execute_action(eosio::name(COBAADMIN), eosio::name(code), &examplefarm::test); 
                    break;
                case eosio::name("doissue").value: 
                    execute_action(eosio::name(COBAADMIN), eosio::name(code), &examplefarm::doissue); 
                    break; 
                case eosio::name("claim").value: 
                    execute_action(eosio::name(COBAADMIN), eosio::name(code), &examplefarm::claim); 
                    break;
                case eosio::name("exit").value: 
                    execute_action(eosio::name(COBAADMIN), eosio::name(code), &examplefarm::exit); 
                    break;
            }
        }
    }


    extern "C"
    {
        [[noreturn]] void apply(uint64_t receiver, uint64_t code, uint64_t action) {
            eosio::datastream<const char*> ds( nullptr, 0 );
            examplefarm p(eosio::name(receiver), eosio::name(code), ds);
            p.apply(eosio::name(code), eosio::name(action));
            eosio_exit(0);
        }
    }

} /// namespace eosio

```
````

{% endcode %}

{% code title="examplefarm.cpp" %}

````cpp
#include "examplefarm.hpp"

namespace vexdt {
    void examplefarm::stake(const eosio::name &from, const eosio::asset &quantity) {

        auto global = _global.get_or_default();
        eosio_assert(global.stopState == 0, "In stop state!");

        if (from == eosio::name(COBAADMIN) || from == eosio::name(CPPTTOKEN) || from == eosio::name(VEXTOKEN)) {
            return;
        }
        require_auth( from );

        eosio_assert( quantity.is_valid(), "invalid quantity");
        eosio_assert( quantity.amount > 0, "must transfer positive quantity");

        bool iscppt = false;
        bool isvex = false;

        if(quantity.symbol == CPPT_SYMBOL)
        {
            iscppt = true;
        }
        else if(quantity.symbol == VEX_SYMBOL)
        {
            isvex = true;
        }

        auto indexholder = _users.get_index<"holder"_n>();
        auto itr = indexholder.lower_bound(from.value);
        if (itr->holder.value != from.value)
        {
            _users.emplace(eosio::name(COBAADMIN), [&](auto &r) {
                    r.id = _users.available_primary_key();   
                    r.holder = from;

                    r.cppt_stake = iscppt ? quantity : eosio::asset(0, CPPT_SYMBOL);
                    r.cppt_update_time = now();

                    r.vex_stake = isvex ? quantity : eosio::asset(0,VEX_SYMBOL);
                    r.vex_update_time = now();
                    
                    r.cppt_bonus = eosio::asset(0, CBP_SYMBOL);
                    r.vex_bonus = eosio::asset(0, CBP_SYMBOL);
                    
                    auto global = _global.get_or_default();
                    if(iscppt)
                    {
                        global.total_staked_cppt += quantity;
                    }
                    else if(isvex)
                    {
                        global.total_staked_vex += quantity;
                    }
                    global.maxstakeid = r.id;
                    _global.set(global,eosio::name(COBAADMIN));                  
                    });
        } else {             
            auto  itrmd = _users.find(itr->id);
            _users.modify(itrmd,eosio::name(COBAADMIN), [&](auto &r) 
            {
                    if(iscppt)
                    {
                        r.cppt_stake += quantity;
                    }
                    else if(isvex)
                    {
                        r.vex_stake += quantity;
                    }

                    auto global = _global.get_or_default();
                    if(iscppt)
                    {
                        global.total_staked_cppt += quantity;
                    }
                    else if(isvex)
                    {
                        global.total_staked_vex += quantity;
                    }
                    
                    _global.set(global,eosio::name(COBAADMIN)); 
            }); 
        }
    }

    void examplefarm::claim(const eosio::name &from, const std::string &pooltype) {

        auto global = _global.get_or_default();
        eosio_assert(global.stopState == 0, "In stop state!");
        require_auth( from );

        auto indexholder = _users.get_index<"holder"_n>();
        auto itr = indexholder.lower_bound(from.value);
        eosio_assert(itr->holder.value == from.value, "sorry, no bonus for you."); 

        auto available_darw_balance = eosio::asset(0, CBP_SYMBOL);
    
        if(pooltype == "CPPT")
        {
            available_darw_balance = itr->cppt_bonus;
        }
        else if(pooltype == "VEX")
        {
            available_darw_balance = itr->vex_bonus;
        }

        eosio_assert(available_darw_balance.amount > 0, "already drawed.");
        eosio_assert(available_darw_balance.amount < max_amount, "trandfer bonus amount overflow !");

        auto  itrmd = _users.find(itr->id);
        _users.modify(itrmd,eosio::name(COBAADMIN), [&](auto &r) 
        {
            auto zerobalance = eosio::asset(0, CBP_SYMBOL);
            if(pooltype == "CPPT")
            {
                r.cppt_bonus = zerobalance;
            }
            else if(pooltype == "VEX")
            {
                r.vex_bonus = zerobalance;
            }
        });

        action(
                permission_level{ eosio::name(COBADRAW), eosio::name("active")},
                eosio::name(CBPTOKEN),
                eosio::name("transfer"),
                std::make_tuple(eosio::name(COBADRAW),from, available_darw_balance, std::string("claim bonus"))
            ).send();
        
    }

    void examplefarm::exit(const eosio::name &from, const std::string &pooltype) {

        auto global = _global.get_or_default();
        eosio_assert(global.stopState == 0, "In stop state!");
        require_auth( from );

        auto indexholder = _users.get_index<"holder"_n>();
        auto itr = indexholder.lower_bound(from.value);
        eosio_assert(itr->holder.value == from.value, "sorry, no bonus for you."); 

        bool iscppt = false;
        bool isvex = false;

        auto available_darw_balance = eosio::asset(0, CBP_SYMBOL);

        auto paybacktoken = eosio::asset(0, CPPT_SYMBOL);
        auto afterunstake = eosio::asset(0, CPPT_SYMBOL);
        auto nowtime = now();

        if(pooltype == "CPPT")
        {
            available_darw_balance = itr->cppt_bonus;
     
            paybacktoken = itr->cppt_stake;
          
            iscppt = true;
        }
        else if(pooltype == "VEX")
        {
            available_darw_balance = itr->vex_bonus;
    
            paybacktoken = itr->vex_stake;
         
            isvex = true;
        }

        eosio_assert(available_darw_balance.amount < max_amount, "trandfer bonus amount overflow !");

        if(pooltype == "CPPT")
        {
            global.total_staked_cppt -= paybacktoken;
            eosio_assert(global.total_staked_cppt.amount < max_amount, "total_staked_cppt amount overflow !");
        }
        else if(pooltype == "VEX")
        {
            global.total_staked_vex -= paybacktoken;
            eosio_assert(global.total_staked_vex.amount < max_amount, "total_staked_vex amount overflow !");
        }
        
        _global.set(global,eosio::name(COBAADMIN)); 


        //返还抵押币
        if(paybacktoken.amount > 0)
        {
            action(permission_level{eosio::name(COBASTAKE), eosio::name("active")},
                eosio::name(CPPTTOKEN),
                eosio::name("transfer"),
                std::make_tuple(eosio::name(COBASTAKE), from, paybacktoken, std::string("get back 5 percent staked asset")))
                .send();
        }

        if(available_darw_balance.amount > 0)
        {
            action(
                permission_level{ eosio::name(COBADRAW), eosio::name("active")},
                eosio::name(CBPTOKEN),
                eosio::name("transfer"),
                std::make_tuple(eosio::name(COBADRAW),from, available_darw_balance, std::string("claim bonus"))
            ).send();
        }

        auto  itrmd = _users.find(itr->id);
        _users.modify(itrmd,eosio::name(COBAADMIN), [&](auto &r) 
        {
            auto zerobalance = eosio::asset(0, CBP_SYMBOL);
            if(iscppt)
            {
                r.cppt_bonus = zerobalance;
                r.cppt_update_time = now();
                r.cppt_stake = eosio::asset(0, CPPT_SYMBOL);
            }
            else if(isvex)
            {
                r.cppt_bonus = eosio::asset(0, VEX_SYMBOL);
                r.vex_update_time = now();
                r.vex_stake = eosio::asset(0, VEX_SYMBOL);
            }


        });
    }

    void examplefarm::doissue(const uint64_t &idfrom, const uint64_t &idto)
    {
        require_auth2(capi_name(eosio::name(COBAADMIN).value), capi_name(eosio::name("cron").value));
        auto global = _global.get_or_default();
        eosio_assert(global.stopState == 0 , "be stop already!");

        //判断阶段挖矿是否已挖完
        eosio_assert(global.total_mininged_cbp_vex < CBP_VEX_STAGE_MINING, "The current mining has finished!");
        
        //判断按顺序执行
        eosio_assert(global.checkfromid == idfrom, "front position not finish yet!");
        if(idfrom == 0) 
        {
            auto nowtime = now();
            //120s 110s
            eosio_assert(nowtime - global.check_update_time_doissue > 120, "have update recently!");
            global.check_update_time_doissue = nowtime; 
        }
        
        auto itrbegin = _users.find(idfrom);
        eosio_assert(itrbegin != _users.end(), "id not found!");
        auto itrend = _users.find(idto);
        eosio_assert(itrend != _users.end(), "id not found!");

        for (uint64_t itrid = idfrom; itrid <= idto; ++itrid) 
        {
            auto itr = _users.find(itrid);
            if(itr != _users.end())
            {
                auto userbonus_cbp = eosio::asset(0, CBP_SYMBOL);
                auto userbonus_vex = eosio::asset(0, CBP_SYMBOL);
               
                if(global.total_staked_cppt.amount > 0)
                {
                    double total = global.total_staked_cppt.amount;
                    double mystake = itr->cppt_stake.amount;
                    userbonus_cbp = global.cbp_pool_reward;
                    userbonus_cbp.amount *= (mystake/total);
                }
                if(global.total_staked_vex.amount > 0)
                {
                    double total = global.total_staked_vex.amount;
                    double mystake = itr->vex_stake.amount;
                    userbonus_vex = global.vex_pool_reward;
                    userbonus_vex.amount *= (mystake/total);
                }

                
                auto  itrmd = _users.find(itr->id);

                auto leftmining = CBP_VEX_STAGE_MINING - global.total_mininged_cbp_vex;

                if(userbonus_cbp + userbonus_vex >= leftmining)
                {
                    userbonus_vex = (leftmining - userbonus_cbp);
                }
                


                auto usermining = userbonus_vex + userbonus_cbp;

                _users.modify(itrmd,eosio::name(COBAADMIN), [&](auto &r) 
                {
                    r.cppt_bonus += userbonus_cbp;
                    r.vex_bonus += userbonus_vex;
                    global.total_mininged_cbp_vex += (userbonus_cbp + userbonus_vex);
                });

                if(usermining >= leftmining)
                {
                    break;
                }
            }
        }

        //更新正在处理的id
        global.checkfromid = idto + 1;
        if(global.checkfromid > global.maxstakeid)
        {
            global.checkfromid = 0;
        }
        _global.set(global, eosio::name(COBAADMIN));
    }

    void examplefarm::onTransfer(const eosio::name &from,
            const eosio::name &to,
            const eosio::extended_asset &quantity,
            const std::string &memo)
    {
        auto global = _global.get_or_default();
        eosio_assert(global.stopState == 0, "In stop state!");
        eosio_assert((global.total_staked_cppt < MAX_STAKE_CPPT), "Maximum stack reached");
        eosio_assert((global.total_staked_vex < MAX_STAKE_VEX), "Maximum stack reached");

        require_auth(from);

        eosio::action act = eosio::get_action( 1, 0 );
     
        eosio_assert( (act.account == eosio::name("vexcore")) || (act.name== eosio::name("transfer") && (act.account == eosio::name(CPPTTOKEN) || act.account == eosio::name(VEXTOKEN)))  ," Human only! ");

        if((to == eosio::name(COBAADMIN)) && (memo.substr(0, 5) == "stake") )
        {
            bool iscppt = iscppttoken(quantity);
            bool isvex = isvextoken(quantity);
          
            eosio_assert(iscppt || isvex," please use CPPT or VEX token ");
            


            if(iscppt) eosio_assert((quantity.quantity.amount >= MIN_STAKE_CPPT), "Stake quantity must be greater than minimum");
            if(isvex) eosio_assert((quantity.quantity.amount >= MIN_STAKE_VEX), "Stake quantity must be greater than minimum");
           
            stake(from,quantity.quantity);

            action(permission_level{eosio::name(COBAADMIN), eosio::name("active")},
                quantity.contract,
                eosio::name("transfer"),
                std::make_tuple(eosio::name(COBAADMIN), eosio::name(COBASTAKE), quantity.quantity, std::string("to coldwallet all stake asset")))
                .send();
        }
    }

    void examplefarm::setstop(const uint8_t &state)
    {
        require_auth2(capi_name(eosio::name(COBAADMIN).value), capi_name(eosio::name("cron").value));
        eosio_assert(state == 0 || state == 1, "set a wrong state!");
        auto global = _global.get_or_default();
        global.stopState = state;
        _global.set(global,eosio::name(COBAADMIN));
    }

    void examplefarm::init() 
    {
        require_auth(eosio::name(COBAADMIN));
        auto global = _global.get_or_default();
        eosio_assert(global.initState != 1, "have init already!");

        eosio::asset all = eosio::asset(100000000, CBP_SYMBOL);//120s 一次

        //vex usdv vyn djv 7000 2000 500 500 14 4 1 1 
        global.initState = 1;
        global.stopState = 0;

        global.checkfromid = 0;
        global.maxstakeid = 0;
        global.check_update_time_doissue = now();
        global.all_pool_reward = all;

        eosio::asset one = all/20;
        global.total_staked_cppt = eosio::asset(0, CPPT_SYMBOL);//总抵押
        global.total_staked_vex = eosio::asset(0, VEX_SYMBOL);//总抵押

        global.cbp_pool_reward = one * 76; //kalo dikali jumlah 2menit dlm 3 bulan, kalikan dengan 65745
        global.cbp_pool_day_reward = one * 24 * 30 * 7716 / 100; //日奖池

        global.vex_pool_reward = one * 15; //kalo dikali jumlah 2menit dlm 3 bulan, kalikan dengan 65745
        global.vex_pool_day_reward = one * 24 * 30 * 1543 / 100; //日奖池


        global.total_mininged_cbp_vex = eosio::asset(0, CBP_SYMBOL);

        _global.set(global, eosio::name(COBAADMIN));
    }
};

```
````

{% endcode %}


# Employee Attendance Contract

{% code title="kehadiran.cpp" %}

```cpp
#include <string>
#include <eosio/eosio.hpp>
#include <eosio/time.hpp>
#include <eosio/system.hpp>
#include <eosio/print.hpp>

using namespace eosio;
using namespace std;
 
using eosio::check;
using eosio::const_mem_fun;
using eosio::current_time_point;
using eosio::datastream;
using eosio::indexed_by;
using eosio::name;
using eosio::time_point_sec;
using eosio::print;
using std::function;
using std::string;


#define SCACCKEHADIRAN "belajarsc222"

class [[eosio::contract("kehadiran")]] kehadiran : public eosio::contract
{
public:
    kehadiran(name receiver, name code, datastream<const char *> ds) : contract(receiver, code, ds) 
     , peg_instance(receiver, receiver.value), dh_instance(receiver, receiver.value)
    {}
    

    [[eosio::action]] void tambahpeg(name idpeg, name accpeg, string namapeg, string deppeg, string pospeg){
        //hanya account vexakuncoba1 yang bisa action : tambah data pegawai baru
        require_auth(name(SCACCKEHADIRAN));

        auto i = peg_instance.find(idpeg.value);
        auto j = peg_instance.get_index<name("byaccpeg")>();
        auto itr = j.lower_bound(idpeg.value);
        
        //cek : id_pegawai harus belum ada di pegawai_table
        check(i == peg_instance.end(), "id pegawai sudah terpakai oleh karyawan lain, masukkan id karyawan yg baru.");
        check(itr == j.end(), "username pegawai sudah digunakan oleh pegawai lain, masukkan ulang username baru.");

        //insert row baru ke dalam pegawai_table
       peg_instance.emplace(get_self(), [&](auto &i)
                      {              
            
        	i.id_pegawai = idpeg;
        	i.username = accpeg; 
		    i.nama_pegawai = namapeg;
            i.departemen = deppeg;
            i.posisi = pospeg;
        });
    }
 
    [[eosio::action]] void hapuspeg(name &idpeg){
        require_auth(name(SCACCKEHADIRAN));

        auto i = peg_instance.find(idpeg.value);

        check(i != peg_instance.end(), "id pegawai yg akan dihapus tidak ditemukan." );
        peg_instance.erase(i);        
    }


    [[eosio::action]] void isi(name &idpeg, int8_t stat, int8_t ket){
        auto i = peg_instance.find(idpeg.value); //cari id pegawai terdaftar apa engga

        check(i != peg_instance.end(), "idpegawai salah");

        require_auth(name(i->username)); //butuh auth username tsb 

        auto k = dh_instance.get_index<name("byidpeg")>(); 
        auto itrk = k.find(idpeg.value);

        int itrg;

        for(auto itr = k.crbegin(); itrg < itr->id_daftar_hadir; itr++) {
            int a = itr->status;
            int b = itr->keterangan;
            print_f(" % % % % ", itr->id_daftar_hadir, itr->id_pegawai, a, b);
            if(itr->id_pegawai == idpeg){
                itrg = itr->id_daftar_hadir;
                print_f(" % ", itrg);

                if(itrk == k.end() || a == 1 || a == -1 ){
                    dh_instance.emplace(get_self(), [&](auto &i){
                i.id_daftar_hadir = dh_instance.available_primary_key();
                i.id_pegawai = idpeg;
                i.status = stat;
                i.waktu_masuk = current_time_point();
                i.keterangan = ket;
                });
                }
                else if(itr->status == 0){

            auto f = itr->id_daftar_hadir;
            auto g = dh_instance.find(f);

            dh_instance.modify(g, get_self(), [&](auto &i){
                i.status = 1;
                i.waktu_pulang = current_time_point();
            });
            }
                
            }
        } 
    }

    [[eosio::action]] void hapusdh(int8_t nomor){
        require_auth(name(SCACCKEHADIRAN));

        auto i = dh_instance.find(nomor);

        check(i != dh_instance.end(), "nomor daftar hadir yg akan dihapus tidak ditemukan." );
        dh_instance.erase(i);        
    }

private:
enum status_hadir : int8_t
    {
        selesai = 1,
        sedang_bekerja = 0,
        absen = -1
    };

enum status_keterangan : int8_t
    {
        attended = 1,
        sick_leave = 2 ,
        personal_leave = 3,
        no_call_no_shows = 4 
    };

struct [[eosio::table]] pegawai_table{
    name id_pegawai;
    name username;
    string nama_pegawai;
    string departemen;
    string posisi;
    
    uint64_t primary_key() const { return id_pegawai.value;}
    uint64_t by_secondary() const { return username.value; }
    
};

typedef eosio::multi_index<"pegawai"_n, pegawai_table, eosio::indexed_by<"byaccpeg"_n, eosio::const_mem_fun<pegawai_table, uint64_t, &pegawai_table::by_secondary>>> pegawai_index;

pegawai_index peg_instance;

struct [[eosio::table]] dh_table{ //dh = daftar_hadir
    uint64_t id_daftar_hadir;
    name id_pegawai;
    int8_t status;
    int8_t keterangan;
    time_point_sec waktu_masuk;
    time_point_sec waktu_pulang;

    uint64_t primary_key() const { return id_daftar_hadir;}
    uint64_t by_secondary() const { return id_pegawai.value; }
};

typedef eosio::multi_index<"daftarhadir"_n, dh_table, eosio::indexed_by<"byidpeg"_n, eosio::const_mem_fun<dh_table, uint64_t, &dh_table::by_secondary>>> dh_index;

dh_index dh_instance;

using isi_action = action_wrapper<"isi"_n, &kehadiran::isi>;
};


```

{% endcode %}


# Solidity ( EVM )

### Overview <a href="#overview" id="overview"></a>

VEX EVM is a fully compatible Ethereum Virtual Machine (EVM) that runs on the Vexanium Network. This opens up the Vexanium Network to the entire Ethereum developer community and tooling.

VEX  EVM bridges the Vexanium ecosystem to the Ethereum ecosystem by allowing developers to deploy a wide array of Solidity-based smart contracts and innovative dApps on the Vexanium Network to make use of its world class performance and low gas fees. Developers can utilize Ethereum’s battle-tested open source code, tooling, libraries and SDKs while leveraging the superior performance of Vexanium to create a multichain Web3 experience.

### Features of Vexanium EVM <a href="#features" id="features"></a>

* Fully compatible with the Ethereum Virtual Machine (EVM)
* Supports all Ethereum smart contracts and tooling
* High throughput and low latency
* Low transaction fees
* Interoperability with the native layer

**LOW GAS FEE on VEX EVM**&#x20;

#### \~.01 VEX per transaction\*\*

What do the fees cover?

* CPU/NET costs of transactions
* RAM costs for EVM Contract
* RPC Node operation costs
* Remainder can be allocated for future Burns

\*\* Note VEXEVM is using ethereum virtual machine so its different with Native public blockchain and you need GAS fee for do transaction  , if you want free GAS fee you can use Vexanium native blockchain&#x20;


# Setup Metamask

**VEX EVM TESTNET**&#x20;

Testnet RPC URL : <https://testnet.vexascan.com/evmapi&#x20>;

Name Network: VEX EVM&#x20;

ChainID: 97&#x20;

Currency symbol: VEX&#x20;

Block explorer URL: <https://testnet.vexascan.com/evmexplorer>


# To Do List Contract

```
mkdir eth-todo-list
cd eth-todo-list
```

```
truffle init
```

```
touch package.json
```

{% code title="package.json" %}

```
{
  "name": "eth-todo-list",
  "version": "1.0.0",
  "description": "Blockchain Todo List Powered By Ethereum",
  "main": "truffle-config.js",
  "directories": {
    "test": "test"
  },
  "scripts": {
    "dev": "lite-server",
    "test": "echo \"Error: no test specified\" && sexit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "bootstrap": "4.1.3",
    "chai": "^4.1.2",
    "chai-as-promised": "^7.1.1",
    "chai-bignumber": "^2.0.2",
    "lite-server": "^2.3.0",
    "nodemon": "^1.17.3",
    "truffle": "5.0.2",
    "truffle-contract": "3.0.6"
  }
}
```

{% endcode %}

```
npm install
```

```
touch ./contracts/TodoList.sol
```

```
// Some code
```

```solidity
pragma solidity ^0.5.0;

contract TodoList {
  uint public taskCount = 0;

  struct Task {
    uint id;
    string content;
    bool completed;
  }

  mapping(uint => Task) public tasks;

  event TaskCreated(
    uint id,
    string content,
    bool completed
  );

  event TaskCompleted(
    uint id,
    bool completed
  );

  constructor() public {
    createTask("Visit vexanium.com");
  }

  function createTask(string memory _content) public {
    taskCount ++;
    tasks[taskCount] = Task(taskCount, _content, false);
    emit TaskCreated(taskCount, _content, false);
  }

  function toggleCompleted(uint _id) public {
    Task memory _task = tasks[_id];
    _task.completed = !_task.completed;
    tasks[_id] = _task;
    emit TaskCompleted(_id, _task.completed);
  }

}v
```


# Resources

**Eosio**

**Ethereum**&#x20;

**Anthelope**


