# Introduction

## What is dfinance

**dfinance** \[diːfaɪˈnæns] is a truly decentralized infrastructure dedicated to various financial and DeFi instruments and products designed for people.

Our infrastructure on the one hand adopts all the properties of a good blockchain: high transaction throughput with low latency, unconstrained scalability, granular security and quite well designed smart contracts engine. On the other hand it proposes a simple and solid set of instruments to engage all you knowledge in finances on the way to success of your project.

We proudly offer you to employ the **dfinance** infrastructure to publish your ideas and focus on your aim.

## Parts

* A **consensus mechanism** based on Tendermint PoS implemented by Cosmos, enabling a decentralization of block producers and ensuring a real trustless environment
* **PegZone** which enables an interoperability with 1st layer blockchains such as Ethereum, EOS, and Bitcoin and others, tapping into the liquidity captured by these blockchains coins and tokens.
* Libra's **Move language** and virtual machine to enable the creation of a powerful code execution environment on decentralized nodes with all the security offered by language's strict semantics, syntax and ownership model.
* **Decentralized oracles** providing connection between Dfinance platform and the real world financial instruments and sources of data.
* Powerful **high-level visual language** empowering a safe way to design, publish and run your own financial instruments, with no prior knowledge in programming required


# Getting started

Here is a guide on how to install **dncli** command line interface and connect to **dfinance**.

## Installation using precompiled binaries

First of all download the latest version of **dncli** for your system from [release pages](https://github.com/dfinance/dnode/releases).

Install downloaded **dncli** binary.

For Mac OS/Linux:

```
mv <downloaded binary path> ./dncli
chmod +x ./dncli
mv ./dncli /usr/local/bin/dncli
```

For Windows:

1. Go to **"Program Files"** directory.
2. Create there **"dn"** directory.
3. Rename the downloaded file to **"dncli"** and put it into **"dn"** directory.

Now **"cmd"** and execute:

```
setx path "%path%;%ProgramFiles%\dn"
```

Now restart **"cmd"**.

Check that installation successful done by running the command:

```
dncli version
```

Your should see your current version of **dncli** in output.

## Configuration

Let's configure **dncli** and after go to the next step:

```
dncli config chain-id dn-testnet
dncli config output json
dncli config indent true
dncli config trust-node true
dncli config compiler tcp://pub.dfinance.co:50051
dncli config node https://rpc.dfinance.co:443
dncli config keyring-backend file
```

These configurations will connect your local **dncli** with remote nodes.

Check that **dncli** configurated correctly:

```
dncli status
```

## Installation from sources

Before we start you should have a correct 'GOPATH', 'GOROOT' environment variables, also installed [Golang](https://golang.org/).

Required:

* golang 1.13.8 or later.
* protoc - here is [installation instruction](https://www.grpc.io/docs/quickstart/go/).

### Build and Install using Makefile

Clone dfinance node repository to suitable place

```
git clone https://github.com/dfinance/dnode.git
```

Build and install **dncli** as binary using Makefile

```
make install-dncli
```

So after this command **dncli** will be available from console

```
dncli version --long
```

### Build without Makefile

And let's build **dncli**:

```
GO111MODULE=on go build -o dncli cmd/dncli/main.go
```

Command must execute fine, after it you can run **dncli**:

```
./dncli version --long
```


# Meet the network using CLI

Here is a step-by-step guide on how to operate with arbitrary **dfinance** node which covers creation of your first account, receiving free testnet XFI tokens and execution of first transaction.

## Account creation and free XFI

Let's create your first **dfinance** account.

Generate new mnemonic:

```
dncli keys mnemonic
```

Copy **mnemonic** and keep in safe place.

Create new account, use **mnemonic** generated from previous command:

```
dncli keys add -i my-account
```

Save **passphrase** and keep in safe place. **Without mnemonic and passphrase you can't access your new account!**

Go to **dfinance** [**wallet portal**](https://wallet.dfinance.co/), use your **mnemonic** and **passphrase** to login, and request faucet to send your free XFI. Click there on request **Request Tokens** button and wait for few seconds, XFI coins will appear on your account. Also, the faucet sending testnet BTC and USDT coins besides XFI.

After this let's query our account with **dncli**:

```
dncli q account <address>
```

Replace `<address>` with your address. You will see output with your address and with your balances, balances should contains XFI coins if we want to continue to next steps.


# Your first transaction

Here is guide how to send your first transaction in **dfinance** network using **dncli**.

## Transfer coins to recipient

Let's try to send basic coins transfer transactions between two accounts.

Create another account:

```
dncli keys add recipient
```

To send **10 XFI** coins to this account needs to execute the next command:

```
dncli tx bank send <sender> <recipient> 10000000000000000000xfi
```

Replace **\<sender>** with your account address and **\<recipient>** with **\<recipient>** address.

We use **"1000000000000000000xfi"** as the amount because by default **XFI** has 18 decimals places, so to send **10 XFI** you have to keep decimals.

After execution, you will get transaction id in the output. To see transaction status execute:

```
dncli q tx <txId>
```

Also now you can query a recipient account and see how balance updated:

```
dncli q account <address>
```

Replace **\<address>** with recipient address to see updated balance.


# Run smart contract

Here is guide how to run your first smart contract in dfinance network using **dncli**.

## Smart contracts introduction

**Dfinance** platform allows writing smart contracts in Move language developed by Facebook's Libra and can be executed by Move VM.

Also, **Dfinance** provides [VSCode plugin](https://marketplace.visualstudio.com/items?itemName=damirka.move-ide), so you can download [VSCode](https://code.visualstudio.com/) and then install the plugin for Move language with syntax and errors highlight, compilation support, and language server support from the box.

Let's do the same we've done in the previous part of documentation, but with smart contracts: transfer coins between two accounts.

```rust
script {
    use 0x1::Account;
    use 0x1::XFI;

    fun main(sender: &signer, recipient: address, dfi_amount: u128) {
        Account::pay_from_sender<XFI::T>(sender, recipient, dfi_amount);
    }
}
```

As you can see we import core modules from address 0x1. This address (0x1) reserved for core modules. Currently we're importing two modules as part of our standard library: [Account](https://github.com/dfinance/dvm/blob/master/stdlib/modules/account.move) and [XFI](https://github.com/dfinance/dvm/blob/master/stdlib/modules/xfi.move). Account module is developed to work with Dfinance accounts from Move, XFI module contains resources to work with XFI balances of accounts. We will talk more about resources later in this documentation or you can read about them in [Move Book](https://move-book.com) (the book about Move language developed by our team).

Also, you can see the `signer` type. The signer type represents sender authority. In other words - using signer means accessing the sender's address and resources. It has no direct relation to signatures or literally signing, in terms of Move VM it simply represents sender. If you are going to use the `signer` type in your script, it must be the first argument in your main function. **Important**: you don't need to provide an argument for signer type when executing a script, as it will be done automatically.

Read more about Signer in [Move Book](https://move-book.com/resources/signer-type.html).

The script code using function `pay_from_sender` of Account module, that function withdraw balance resource balance from sender account and put withdrawn resource to recipient account. Another methods and options how to work with balances you can read in our [Standard Library](/move_vm/standard_lib) documentation.

Let's continue with such plain example and compile, execute our script.

## Compilation

Put the script under **'./send.move'** name or use [VSCode plugin](https://marketplace.visualstudio.com/items?itemName=damirka.move-ide) and compile using dncli:

```
mkdir out
dncli q vm compile ./send.move <address> --to-file ./out/send.move.json
```

Replace **\<address>** with your **dfinance** address and execute the command.

You will see new file **'./out/send.move.json'** contains the byte code of the script.

## Run

Now let's execute the compiled script.

We should make a transaction that will contain compiled byte code and put the right arguments.

Do it with the command:

```
dncli tx vm execute ./out/send.move.json <recipient> 10000000000000000000 --from my-account
```

Replace **\<recipient>** with recipient address account and execute, you can see the result of command execution by querying txId.

As you see arguments passed to `execute` match arguments in script function **"main"**.

In nutshell, we have done the same, but instead of using **dncli** native functional for sending coins, we used a smart contract.

Now, once the transaction confirmed and executed, you can query the recipient account again to see how balance changed (should be increased by 10 XFI).


# Run your own node

To run your own node and synchronize with current network please, read a [dnode documentation](/architecture/dnode) part.


# Ledger Support

**dncli** and [wallet](https://wallet.dfinance.co) both supports [Ledger](https://www.ledger.com/) via Cosmos Ledger App.

Install Cosmos Ledger App using official [instruction](https://support.ledger.com/hc/en-us/articles/360013713840-Cosmos-ATOM-).

## Wallet

Launch Cosmos App on your ledger device and visit [wallet](https://wallet.dfinance.co), login by clicking on 'Unlock with Ledger' button and follow instructions appear on your screen.

## dncli

To add account to **dncli** use next command:

```
dncli keys add my-account --index 0 --ledger
```

It will add a new account to your ledger, if you need another account just increase the index parameter.

## Offline signatues

Also, if you want to sign something with **dncli**, for example, your validator creation transaction from remote server, you can just generate that transaction by adding `--generate-only` flag and use signer address in `--from` flag, for example:

```
dncli tx staking create-validator ..... --generate-only --from [adress] > tx.json
```

See generated transaction:

```
cat tx.json
```

You can sign and broadcast the transaction using **dncli** from your local machine:

```
# sign transaction
dncli sign tx.json --from [address] > signed.json 

# broadcast transaction
dncli tx broadcast signed.json
```


# Architecture

Dfinance network consists of several main components:

* **dnode** - blockchain node - the core layer. Includes [Tendermint consensus](https://tendermint.com/), Proof Of Stake modules, oracles functional, VM functional, etc. **dnode** is built with [Cosmos SDK](https://github.com/cosmos/cosmos-sdk). See [dnode repository on GitHub](https://github.com/dfinance/dnode).
* **dncli** - command-line interface to iteract with dnode, also allows launching REST API server, has same repository that [dnode](https://github.com/dfinance/dnode).
* **dvm** - Move Virtual Machine by [Libra](https://developers.libra.org/) packed as gRPC server. Allows smart constracts execution via gRPC. Connects to **dnode** to read data from storage, **dnode** connects to VM to execute smart contracts. [See repository](https://github.com/dfinance/dvm). Also, contains compiler of Move language. Requires **dnode** for correct functioning.

You'll find more precise description of every component in other sections of this documentation.


# Dnode

**dnode** is a blockchain node of **dfinance** platform. **dnode** implements core functional of **dfinance**: reach consensus, securing chain with PoS, processing transactions, p2p connections, etc.

You can find dnode source code [in dnode Github repository](https://github.com/dfinance/dnode).

## Run your dnode

There are multiple ways of running your dnode. We've sorted them from easiest to more complicated.

### Join mainnet with bootstrap

For fastest and simplest launch we recommend using [bootstrap repos](https://github.com/dfinance/bootstrap). We've created it to make node launch as easy as it can be. See 4-step launch guide in its [README](https://github.com/dfinance/bootstrap#dfinance-bootstrap).

### Docker Image

Pre-built docker image is available on Docker Hub: [here's the link](https://hub.docker.com/r/dfinance/dnode). It already includes binary file for dnode so if you feel like it - go on - try it yourself.

### Build from source

You can build **dnode** from source, to do so fetch and build dnode from [Github repository](https://github.com/dfinance/dnode), use latest stable tag from [releases](https://github.com/dfinance/dnode/releases) page.

After that you need to:

* Install **dvm** from [dvm repository](https://github.com/dfinance/dvm).
* Launch **dvm** with recommended port setting (or configure your own ports in both dnode and dvm).

## Mainnet configuration (for docker or manual run)

First of all init your local **dnode** with moniker (name) of your node:

```
dnode init <moniker>
```

After that download `genesis.json`:

```bash
# remove default genesis created on init
rm ~/.dnode/config/genesis.json

# this solution requires 'jq' util to be installed
curl https://rpc.dfinance.co/genesis | jq '.result.genesis' > ~/.dnode/config/genesis.json
```

Now replace seeds in (*\~/.dnode/config.toml*) with current seed nodes:

```bash
seeds = "122c6788e6d33718833a6020a534fed146e72ca7@pub.dfinance.co:26656,e12f9bdb7d4490b00743017807327f6172c98b32@pub2.dfinance.co:26656"
```

**Important**: if you set up full-node, you must open `26656` port on your machine, otherwise your node will not be able to broadcast and receive data from other nodes by P2P.

Once you opened port, configure your external address in (*\~/.dnode/config.toml*):

```bash
external_address="your_ip:26656"
```

More detailed instruction on how to build `dnode` from sources can be found in [dnode repository](https://github.com/dfinance/dnode). If want some more space for experiments you can also use `dnode` to launch your own local testnet.

If you'd like to contribute - [see contributors section](https://github.com/dfinance/dnode#contributors). If you have any questions feel free to open [new issue](https://github.com/dfinance/dnode/issues/new).


# Dncli

**dncli** (dfinance node CLI) is a CLI application developed to work with **dnode**. With dncli you can query blockchain data, post transactions, and query network status.

It comes as binary application and can be downloaded from [GitHub release page](https://github.com/dfinance/dnode/releases). Alternatively you can [build it from sources](https://github.com/dfinance/dnode).

## Usage

After installing **dncli**, it should be configured:

```bash
dncli config chain-id dn-testnet
dncli config output json
dncli config indent true
dncli config trust-node true
dncli config compiler tcp://127.0.0.1:50051
dncli config node http://127.0.0.1:26657
dncli config keyring-backend file
```

After configuring, you can try it:

```
dncli version
dncli --help
```

**dncli** contains multiple commands for each **dnode** module.

There are two types of commands in **dncli**: `transaction` and `query`. Transaction commands start with `tx` prefix, query commands start with `query` prefix. Difference between them is that `tx` commands imply building and broadcasting transaction, whereas `query` simply queries data from dnode.

You can try it yourself and see available commands:

```bash
dncli tx --help
dncli query --help

dncli q --help # Short version of query.
```

You can use `--help` option for any command, e.g.:

```bash
dncli tx vm --help
dncli tx vm execute --help

dncli q vm --help
dncli q vm compile --help
```

In case, your VM transaction contains an error, you always can query detailed information about the happened error, check next command:

```bash
dncli q vm tx [txId]
```

## Mainnet configuration

**dncli** by default connects to local **dnode** (at localhost:26657) and **compiler** (inside **dvm**) (at localhost:50051). To connect to remote node or launched mainnet, change these configuration settings:

```bash
dncli config compiler tcp://pub.dfinance.co:50051
dncli config node https://rpc.dfinance.co:443
```

Also, **compiler** address could be passed as `--compiler` option during execution of command requiring compilation, this is:

```bash
# use --help to see full list of options
dncli q vm compile <file> <account>
```


# XFI & Other coins

**XFI** is the main currency in **dfinance** network.

XFI is used for:

* PoS - to stake or delegate XFI.
* Fees - to pay fees in XFI to process transactions.
* Gov - to vote with XFI per proposals: updates, improvements, etc.
* Economic model - users can provide liquidity, loans with XFI.

## Decimals

XFI coin has 18 decimals places, which means 1.0 XFI can be represented as integer as **1000000000000000000**, while 0.**000000000000000001 XFI** as 1 as integer.

When working with **dncli** amounts need to be integers, so convert your amount to integer before executing any command.

As it's the same 18 decimals places, like in ETH, you can use same resources to convert amounts, [like this one](https://www.etherchain.org/tools/unitConverter) (use ether-wei pair).

## Smart contracts

XFI is a built-in type inside Dfinance's standard library which you can use to send transactions envolving XFI coin. Here's how it looks like ([link to GitHub](https://github.com/dfinance/dvm/blob/master/stdlib/modules/xfi.move)):

```rust
module XFI {
    // type representing XFI coin
    struct T {}
}
```

Module can be imported from standard library:

```rust
use 0x1::XFI;
```

The type `XFI::T` inside module `0x1::XFI` can be used as type parameter in generic functions, like in this example:

```rust
script {
     use 0x1::Dfinance;
     use 0x1::Account;
     use 0x1::XFI;

     fun main(sender: &signer, recipient: address, amount: u128) {
         // Withdraw XFI resource from sender balance with provided amount.
         let withdraw : Dfinance::T<XFI::T> = Account::withdraw_from_sender<XFI::T>(sender, amount);

         // Deposit withdrawn XFI balance to recipient address.
         Account::deposit<XFI::T>(sender, recipient, withdraw);
     }
 }
```

Provided script uses functions `withdraw_from_sender<T>` and `deposit<T>` which contain generic type `T`. By passing `XFI::T` as type parameter into these generic functions, we make them work with XFI balances. Note that other coin types can too be passed as type parameters.

You can learn more about generics in Move in the [Move book](https://move-book.com/advanced-topics/understanding-generics.html).

## Other coins

Current mainnet supports other coins along with XFI (just for test purposes):

**IMPORTANT: DON'T DEPOSIT REAL MAINNET ETH VIA PEGZONE**

* **ETH** - ETH representation, can be transfered through [PegZone](/pegzone).
* **BTC** - simulation of BTC, can be recieved by [faucet](https://wallet.dfinance.co).
* **USDT** - simulation of Tether USDT, can be recieved also by [faucet](https://wallet.dfinance.co).

Same as XFI, all coins can be sent between accounts with CLI:

```
dncli tx bank send <sender> <recipient> 1xfi
dncli tx bank send <sender> <recipient> 1eth
dncli tx bank send <sender> <recipient> 1btc
dncli tx bank send <sender> <recipient> 1usdt
```

Also, coins types can be imported from `0x1::Coins` module to use in smart contracts:

```rust
script {
    use 0x1::Account;
    use 0x1::Coins;

    fun main(sender: &signer, recipient: address, eth_amount: u128, btc_amount: u128, usdt_amount: u128) {
        Account::pay_from_sender<Coins::ETH>(sender, recipient, eth_amount);
        Account::pay_from_sender<Coins::BTC>(sender, recipient, btc_amount);
        Account::pay_from_sender<Coins::USDT>(sender, recipient, usdt_amount);
    }
}
```

Coins module follows the same pattern as XFI but has multiple types ([link to GitHub](https://github.com/dfinance/dvm/blob/master/stdlib/modules/coins.move)):

```rust
module Coins {
    struct ETH {}
    struct BTC {}
    struct USDT {}
}
```


# Fees & Gas

Every transaction in **dfinance** protocol requires sender to pay fee, as well as it has maximum amount of **gas** which can be used during transaction execution. Gas is a cost of operation in our blockchain (such as executing smart-contract in **VM** or basic read-write operations on blockchain storage).

## Gas

The gas amount is an integer and is set by `--gas` option in **dncli**:

```bash
dncli tx bank send <sender> <recipient> <amount> --gas <value>
```

The default gas parameter in **dncli** is `500000`, if you see errors related to **"out of gas"** issue, try to increase gas until you find the optimal one for your transaction.

### Block gas limit

The current block gas limit is `5000000` gas. Means that transaction with gas limit greater than `5000000` will be not accepted by validators nodes.

In future this setting will become changeable via Government voting mechanism.

## Fees

Although **dfinance** supports different currencies (like ETH), transaction fees can be paid only in **XFI** currency.

Currently, minimal fee amount is **1 XFI**. Though this value may vary for each validator in the network as it's for validator to decide his minimal fee. This means that even if your transaction fee was too low for current validator, it still may be added in one of the next few blocks by validators whose minimal fee matches your value.

**dncli** sets fees automatically, so you can ignore `--fees` flag, alternatively, if you want to speed up your transaction confirmation time you can can set fees manually by using `--fees` flag, e.g.:

```bash
# Fees amount MUST be written without spaces between amount and denom
dncli tx vm execute <script.mvir.json> <args,...> --fees 1000000000000000000xfi
```


# Addresses

Dfinance protocol uses [Bech32](https://en.bitcoin.it/wiki/Bech32) address format. Bech32 encoding provides robust integrity checks on data and the human readable part (HRP) provides contextual hints that can assist UI developers with providing informative error messages.

* Human readable part is called a prefix and in the case of dfinance it's `wallet`.&#x20;
* Default HDPath for dfinance addresses is `44'/118'/0'/0/0`.

```
wallet173pur9yxzauc7pccwwpk7whnf30czvf53wkcyn # Example of dfinance address, contains prefix 'wallet', then '1' and address bytes.
```

Use [secp256k1](https://en.bitcoin.it/wiki/Secp256k1) algorithm to generate public and private keys, then use Bech32 to create addresses.

Mnemonic based keys supported by [bip39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) and [bip32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) implementations.

Example in Golang:

```go
package main

import (
    "encoding/hex"
    "fmt"

    "github.com/cosmos/cosmos-sdk/crypto/keys/hd"
    sdk "github.com/cosmos/cosmos-sdk/types"
    "github.com/cosmos/go-bip39"
    "github.com/tendermint/tendermint/crypto/secp256k1"
)

func main() {
    // Configure Cosmos SDK.
    prefix := "wallet"
    config := sdk.GetConfig()
    config.SetBech32PrefixForAccount(prefix, prefix + sdk.PrefixPublic)
    config.Seal()

    // Generate new address from new private key.
    privKey := secp256k1.GenPrivKey()
    pubKey  := privKey.PubKey()
    addr    := sdk.AccAddress(pubKey.Address())

    fmt.Printf("Private key: %s\nPublic key: %s\nAddress: %s\n", hex.EncodeToString(privKey[:]), hex.EncodeToString(pubKey.Bytes()), addr)

    // Generate address from new mnemonic.
    entropy, err := bip39.NewEntropy(256)
    if err != nil {
        panic(err)
    }

    passphrase := "12345678" // Replace with your passphrase.
    hdPath := "44'/118'/0'/0/0"
    mnemonic, err := bip39.NewMnemonic(entropy)
    if err != nil {
        panic(err)
    }

    fmt.Printf("\nNew generated mnemonic is: %s\n", mnemonic)

    seed, err := bip39.NewSeedWithErrorChecking(mnemonic, passphrase)
    if err != nil {
        panic(err)
    }

    masterPrivKey, ch := hd.ComputeMastersFromSeed(seed)

    // If hdPath is empty, just use masterPrivKey[:], don't need to derive.
    derivedPrivKey, err := hd.DerivePrivateKeyForPath(masterPrivKey, ch, hdPath)
    if err != nil {
        panic(err)
    }

    derivedPubKey := secp256k1.PrivKeySecp256k1(derivedPrivKey).PubKey()
    derivedAddr   := sdk.AccAddress(derivedPubKey.Address())

    fmt.Printf("Private key: %s\nPublic key: %s\nAddress: %s\n", hex.EncodeToString(derivedPrivKey[:]), hex.EncodeToString(derivedPubKey.Bytes()), derivedAddr)
}
```


# Staking

This documentation introduces dfinance Proof-of-Stake consensus algorithm and contains instructions on how to delegate sXFI or LPT, how to become validator on dfinance, how run a full node, and how to earn rewards for delegation.

**IMPORTANT: during incentivized mainnet users stake their sXFI (Staking XFI) coins and LPT (Liquidity Provider Tokens).**

Users can get their sXFI and LPT on your account using [Staking Gateway](https://stake.dfinance.co/).

## Proof-of-Stake

Any blockchain-based system must have a consensus algorithm, which secures blockchain from attacks (like [Sybil](https://academy.binance.com/security/sybil-attacks-explained) attacks, [Double Spending](https://academy.binance.com/security/double-spending-explained) attacks, [51%](https://academy.binance.com/security/what-is-a-51-percent-attack) attacks), forks, and allowing to validate if block mined/generated correctly and in time.

Dfinance is based on [Proof-Of-Stake (PoS)](https://academy.binance.com/blockchain/delegated-proof-of-stake-explained) consensus algorithm developed by Cosmos team. This means that dfinance has a set of validators who can generate blocks thus securing the network. By utilizing Tendermint protocol dfinance trying to minimize possible attack vectors on the network and amount of forks that could happen.

### Validators

Validator is a user who is ready to set up a full-node, self-delegate minimum amount of sXFI (2500.0 sXFI), keep it with great performance, and in such way secure the network and earn rewards.

There are two kinds of validators: active ones and standby. The top 101 validators are active validators, who indeed can generate new blocks, the rest of validators are standby validators. The top can be generated by sorting all validators by their voting power, from greater to lesser. Each validator has a voting power (voting power of validators is determined by the amount of staking sXFI bonded as collateral). These sXFI coins can be self-delegated directly by validators themselves or delegated from other sXFI holders. For their work active validators receive network fees (collected from transactions) and network rewards (newly generated sXFI). This way to become an active validator standby should get so much voting power as possible to get inside top.

The active validators must generate blocks, sign them with the private key, and broadcast in the network, in a specific time slot that is chosen special for this validator.

Any user of the network can become a validator. The user should send a special transaction to the network, and set up a full node. Read more how to become a validator in [Become a validator](/staking/become_a_validator) documentation.

### Delegators

The procedure of delegation coins to a specific validator or own validator (self delegation) is calling **staking**. Once a user delegates sXFI or LPT, these coins or tokens can't be used anymore while it's delegated, in exchange for delegation users getting part of rewards/fees formed by validator - commission established by the validator.

Any user can delegate his coins to validators to support liked validators and get part of fees received by validators they choose to delegate. By delegating, a user locks his tokens. Delegators should actively participate in choosing validators, because if a user delegates to the performance-less validator (let's say validator which misses blocks or double sign blocks/pre-votes). In such cases, both validator and delegator will be exposed to the slashing procedure.

You can't delegate same sXFI and LPT to different validators, only to one, means, if you have for example 1000 sXFI and 10 LPT, you can delegate 900 sXFI and 6 LPT to validator A, and the rest, 31 sXFI and 4 LPT, to delegator B, but you can't delegate already staked sXFI or LPT to another validator.

LPT delegations doesn't affect validators voting power.

### Full node

A full node is a [dnode](/architecture/dnode) instance that stores all blockchain data including transactions, blocks, consensus settings, and at the same time it validates new coming transactions and blocks. Each full node has a public IP address, so other full nodes can communicate with it via p2p. All validators in the network must run their full node, as validators must have all information about the network to verify and approve transactions, blocks.

After this short introduction to staking, let's continue with current documentation and see how we can delegate.


# Delegate sXFI & LPT

This section describes process of delegation of sXFI and LPT to validators in **dfinance** network.

Any user who has sXFI or LPT on his account's balance can delegate his coins/tokens to one or multiple validators (though a single sXFI or LPT cannot be used twice).

To find validators and delegate you can use our [explorer](https://explorer.dfinance.co/validators) and [wallet](https://wallet.dfinance.co/), or use **dncli**:

```bash
# The staking module contains delegators/validators commands.

# Staking query commands.
dncli q staking --help

# Staking transaction commands.
dncli tx staking --help
```

## How to delegate sXFI & LPT

First, choose the validator you want to delegate your sXFI or LPT to and send `delegate` transaction to the network.

Use [wallet](https://wallet.dfinance.co/) to delegate. Or use **dncli**:

See the list of validators:

```bash
dncli q staking validators
```

Choose validator and check validator extended info:

```bash
 dncli q distribution validator [validator-addr]
```

**Important:** Find `max_bonding_delegations_lvl` parameter and compare with `bonding_tokens`, if you do small math `max_bonding_delegations_lvl` - `bonding_tokens`, you are going to see MAXIMUM amount of sXFI you can delegate to validator. It doesn't affect LPT staking, you can delegate so much LPT as you want.

Choose optimal amount of sXFI or LPT to delegate and send transaction:

```bash
dncli tx staking delegate [validator-addr] [amount] --from [account]
```

As you see, when you delegate, you provide the following arguments:

* \[validator-addr] - validator operator address you want to delegate (has `walletvaloper1` prefix instead of standard `wallet1`);
* \[amount] - sXFI or LPT amount to delegate. e.g. 2500000000000000000000sxfi or 100000000000000000000lpt.
* \[account] - delegator account.

Example:

```bash
dncli tx staking delegate walletvaloper10tyyh... 15000000000000000000000sxfi --from [account] # Delegate 15k sXFI.
dncli tx staking delegate walletvaloper10tyyh... 100000000000000000000lpt --from [account] # Delegate 100 LPT.
```

Once your transaction executed and confirmed, check your account balance - you'll see that it has changed - sXFI you've delegated are not accesible (but not spent - see below):

```bash
dncli q account [delegator-addr]
```

Also, see new delegation done by your account:

```bash
dncli q staking delegations [delegator-addr]
```

Delegated sXFI or LPT coins are stored in the `staking` module, and you can get them back by [unbonding](/staking/delegate#how-to-unbond-undelegate) your coins.

Since you have your first delegation, you can start getting rewards, read more in [Rewards & Inflation](/staking/rewards_inflation). Also, if you choose validators, who are missing blocks or double sign them (trying to attack the network), you can also be punished for supporting him. See [Slashing](/staking/slashing) to see what risks delegation brings.

## How to unbond (undelegate)

When you want to get staked sXFI or LPT back, you can send *unbond* (undelegate) transaction to the network, this will start *unbonding procedure*. Unbonding procedure will take some time, usually, it's 7 days unbonding period for both sXFI and LPT. During this period the delegator still can be slashed for potential misbehaviors committed by the validator before the unbonding process ends.

Use [wallet](https://wallet.dfinance.co/) to unbond or continue with **dncli**.

Find delegations from your address:

```bash
dncli q staking delegations [delegator-addr]
```

Where:

* \[delegator-addr] - delegator address (usually your account address).

Choose validator you want to unbond and run:

```bash
dncli tx staking unbond [validator-addr] [amount] --from [account]
```

Once transaction confirmed, check the status of unbonding sXFI/LPT coins:

```bash
dncli q staking unbonding-delegations [delegator-addr]
```

Once the unbonding period is completed you will get your sXFI or LPT coins back on the account. You can have maximum **7** unbonding stakes and redelegations at the same time.

## Redelegation

In situations when you don't want to unbond your sXFI and at the same time don't want to delegate to a specific validator, or if you want to delegate part of your staked sXFI or LPT to another validator, you can redelegate.

Use [wallet](https://wallet.dfinance.co/your_validators) to redelegate or continue with **dncli**.

Run redelegate command:

```bash
dncli tx staking redelegate [src-validator-addr] [dst-validator-addr] [amount] --from [account]
```

Where:

* \[src-validator-addr] - validator address which already contains delegated sXFI.
* \[dst-validator-addr] - new validator address, which we want to redelegate.
* \[amount] - sXFI or LPT amount to redelegate.
* \[account] - delegator account.

Once your transaction is confirmed, check your delegations:

```bash
dncli q staking delegations [delegator-addr]
```


# Become a validator

Any user can become a validator on dfinance network.

Being one means:

1. Having a full-sync (and always-online) node
2. Having account registered as validator
3. Generating new blocks when having enough votes to be in the top of active validators

## Node Setup

To become a validator:

1. Set up a full node, using a dedicated server or cloud services. The validator machine must have a good performance and latency and must be always online.
2. Install **dnode**/**dncli** on your node using [dnode](/architecture/dnode) and [dncli](/architecture/dncli) instructions.
3. Ensure that your node is in sync with the rest of the network by requesting the latest block. Request the network status to see latest block or use [explorer](https://explorer.dfinance.co/):

Use these commands to compare block height on your node and on the mainnet:

```bash
# Both commands require jq.

# Get latest block from mainnet
curl https://rest.dfinance.co/blocks/latest  | jq '.block.header.height'

# Get latest block from local node
curl localhost:1317/blocks/latest  | jq '.block.header.height'
# Or with dncli.
dncli q block
```

Once the difference between your height and mainnet height is small (just a few blocks), you can start the process of registering your account as a validator.

### Important

Validator's private key is stored under `~/.dnode/config/` path and contains the key file:

* `priv_validator_key.json` - private key of validator, backup it and don't miss, as it's the only way to access your validator.

## Create validator

After you setup a full-node time to create a validator. Make sure you made a backup of `priv_validator_key.json` and store it in a safe place.

Requirements for next steps:

* Synchronized **dnode** (full-node).
* Opened **26656 port** on your machine.
* Installed **dncli** and **dnode** (with docker or not).
* Account with at least 2500.0 sXFI.

During validator creation we will need both **dnode** and **dncli** working from your machine launched with full-node, so make sure they both available from the console:

```bash
dnode version  # Check dnode available.
dncli version  # Check dncli available.
```

In case you're using docker, **dncli** still should be installed in your console (see instruction), while **dnode** you can get inside docker:

First, let's try to find validator public key:

```bash
dnode tendermint show-validator
```

In case you are using [bootstrap](https://github.com/dfinance/bootstrap) docker-compose:

```bash
cd bootstrap # Go to bootstrap directory.
docker-compose exec dnode bash # Run bash inside a dnode container.
dnode tendermint show-validator # Print validator public key, copy it.
exit # Exit from container.
```

If you see the validator consensus public key we can continue, copy the validator consensus address, we will need it in the next step. If you don't see validator public key, you have to init your **dnode** instance, see dnode [documentation](/architecture/dnode).

**dncli** contains staking module, that required both for validator/delegator operations, see help:

```bash
dncli q staking
dncli tx staking
```

Let's create a validator and official register it in the network:

```bash
dncli tx staking create-validator \
  --amount=2500000000000000000000sxfi \
  --pubkey=<pub_key> \
  --moniker=<moniker> \
  --commission-rate="0.10" \
  --commission-max-rate="0.20" \
  --commission-max-change-rate="0.01" \
  --min-self-delegation="2500000000000000000000" \
  --from <account>
```

Where:

* `amount` - sXFI amount to self-stake, currently requires **2500.0 sXFI** to up validator.
* `pubkey` - validator consensus public key received during `dnode tendermint show-validator` command.
* `moniker` - your dnode moniker, use one you used during `dnode init <moniker>` command. You can see it in `~/.dnode/config/config.toml` file
* `commission-rate` - how much your validator is going to take a commission from received rewards/fees, currently 10%.
* `commission-max-rate` - maximum that validator can take as comission.
* `commission-max-change-rate` - how percent per day validator can change comission, currently 1% per day.
* `from` - an account that is going to send transaction and will self-stake coins for your validator, also, you can use this account to manage your validator later.

Replace command values with your own and send the transaction to the network. Most interesting parameters are commission related, we will discuss them later. Once the transaction will be confirmed, you will become a validator in the dfinance network.

Congrats!

To see list of validators use command:

```bash
dncli q staking validators
```

It is the start of the road to become an active validator in the top 31 and start getting rewards and fees for generated blocks. To increase your voting power you can delegate coins to your validator, see [Delegate sXFI & LPT](/staking/delegate).

By changing commission params, making it less, you become more profitable for delegators to vote for you (see [Rewards & Inflation](/staking/rewards_inflation)), so it could be a good start to bring attention. Don't forget to always monitor your validator, it must be online most of the time, if you miss too many blocks, you can be [unbonded](/staking/become_a_validator#unbonding) and [slashed](/staking/slashing).

### Max Bonding Level

Max bonding level is the value of bonded (delegated) tokens you validator can accept from delegators. This value is based on the amount of your self delegated sXFI multiplied by 10.

To see your current max bonding level use next command:

```bash
 dncli q distribution validator [validator-addr]
```

The parameter called `max_bonding_delegations_lvl` is indeed the amount of your maximum bonding level in sXFI. To increase your max bonding level, delegate more sXFI from your account.

In case validator reduces his self-staked amount of sXFI less than delegated sXFI to his validator, validator will be moved to scheduled unbond delay status. This is the period for scheduled (delayed) force validator unbond, it's 3 days. After this period validator will be unbonded.

## Socialize your validator

Having validator in **dfinance** network is not only about setting up validator node and producing blocks, but it's also public work, delegators (especially from the community) want to know to whom they delegate their XFI.

This way you can update your validator with social parameters, that other network users can read:

```bash
dncli tx staking edit-validator \
  --moniker="pirate_boris" \
  --website="https://dfinance.co" \
  --identity=A4094774EFC4F6FC \
  --security-contact="boris@dfinance.co" \
  --details="money printing machine!" \
  --from <account>
```

All flags are optional. See arguments and then replace them with your own:

* `moniker` - moniker of your validator.
* `website` - website of your validator.
* `identity` - can be used to verify identity with systems like [Keybase](https://keybase.io/) or UPort. Also, it's a great way to retrieve your Keybase avatar. See how to [generate identity](/staking/become_a_validator#generate-identity-using-keybase) using keybase.
* `details` - few words about you.
* `security-contact` - a way to send your email/message.

### Generate identity using Keybase

1. Go to [Keybase.io](https://keybase.io/).
2. Create your account and download the app.
3. Add pgp key to your account using the terminal. Click `add a PGP key` and follow instructions.
4. After generating keys, you will get a 16 letters ID, like `ID A4094774EFC4F6FC`.
5. Use ID as a value for `identity`.

## Change comission parameters

If you want to reduce/increase your commission as a validator, you can make another transaction with the new commission rate. Don't forget, that you can't change commission more than on `commission-max-change-rate` per day.

```bash
dncli tx staking edit-validator \
  --commission-rate="0.11" \
  --from <account>
```

Also, an important parameter is minimum self delegation (`--min-self-delegation`), you can change it also, as more self delegation you have, as more trust you will have in eyes of delegators. You can only increase `--min-self-delegation`.

Example (min self delegation to 250000 XFI):

```bash
dncli tx staking edit-validator \
  --min-self-delegation="250000000000000000000000" \
  --from <account>
```

## Statuses

Validators could have the following statuses:

* `Bonded (2)` - active validators in the top 31. Generate blocks, receiving rewards and fees.
* `Unbonded (0)` - validators that don't have enough voting power to be in the top 31. Means, can't generate new blocks, get rewards, etc.
* `Unbonding (1)` - once validator leaves top 31 it becomes unbonding, means, validator and all delegators have to wait during unbonding time to get XFI back, or just redelegate them now. You can read about unbonding period in \[delegation manual]\(/staking/delegate\_dfi.md#how-to-unbond-(undelegate)).

Once you create a validator, and if you don't have enough power to get to top 101, your validator will get status **Unbonded**, then when it reaches enough voting it will automatically move to **Bonded** status and start generating blocks.

### Unbonding

When your validator got **Unbonding** status, that could happen for several reasons:

* Validator goes out from top 31.
* Validator unbound self delegated XFI more than promised (see `--min-self-delegation` parameter). In such a case the validator will be also `jailed`.
* Validator missed too many blocks to sign/propose. The default amount of missed blocks to become unbonding are 50% of blocks during the 31 blocks window. Will be `jailed` also.
* Validator double sign blocks. In this case the validator will be tombstoned and `jailed` forever.

In all cases you still can [redelegate](https://github.com/dfinance/docs/tree/2b9795daaddf18f5c7795c0f9c2a7c4b184e47c4/staking/delegate_dfi.md#redelegate) your sXFI to another validator not to wait **Unbonding** period.

More about jailing and slashing read in [Slashing](/staking/slashing) section.


# Rewards & Inflation

For staking users in the dfinance network getting rewards in sXFI coins. Validators receive rewards by generating and signing new blocks, they take a commission, it's their default reward for supporting the network.

Delegators that delegate sXFI or LPT to validators also receive rewards in proportion to the amount of their staked sXFI and LPT.

Read more about the inflation and rewards model supported by the dfinance network in the current documentation.

## Inflation

Dfinance inflation model is in production version and implemented in current mainnet. We are releasing information about it step by step, as dfinance inflation model very innovative and using a lot of parameters.

You can read about introduction in our latest [article](https://medium.com/dfinance/token-economics-954874a35252).

To see inflation parameters check `mint` module:

```bash
# To see query commands.
dncli q mint --help

# To see tx commands.
dncli tx mint --help
```

More information will be provided soon with coming documentation updates.

## Rewards

Use [wallet](https://wallet.dfinance.co) to see & withdraw rewards or continue with **dncli**.

See `distribution` module:

```bash
# To see query commands.
dncli q distribution

# To see tx commands.
dncli tx distribution
```

To check if you have any rewards use next command:

```bash
dncli q distribution rewards [delegator-addr] [<validator-addr>]
```

Where:

* \[delegator-addr] - address of delegator.&#x20;
* \[] - address of validator. Optional.

If you are validator, see earned commission:

```bash
dncli q distribution commission [validator]
```

**Important:** in current mainnet rewards withdrawing disabled and will become available later.

To withdraw rewards send transaction:

```bash
dncli tx distribution withdraw-all-rewards --from [account]
```

Where:

* \[account] - is an account that has rewards.


# Slashing

This documentation describes the slashing mechanism that carries about punishments on validators and their delegators.

As secure of dfinance network depends on validators, fewer performance validators or attackers validators should be punished.

Each active validator has to pre-vote each new proposed block and also propose to block himself when his time comes, this is how works [Tendermint](https://tendermint.com/). If a validator doesn't sign an approved block or miss his proposed round, such validator could be slashed (because of compromises network security).

More about network security you can read in Tendermint documentation and other links we provide in [More](/staking/more) section. Right now let's see how the validator could be slashed.

To see slashing commands use **dncli** `slashing` module:

```bash
# To see query commands.
dncli q slashing

# To see transactions commands.
dncli tx slashing
```

Slashing parameter described in genesis blocks, you can look at them:

```bash
dncli q slashing params
```

Current mainnet configuration looks so:

```javascript
{
  "signed_blocks_window": "100",
  "min_signed_per_window": "0.500000000000000000",
  "downtime_jail_duration": "600000000000",
  "slash_fraction_double_sign": "0.050000000000000000",
  "slash_fraction_downtime": "0.010000000000000000"
}
```

Where:

* `min_signed_per_window` - the percent of blocks must be signed by the validator during blocks window, currently 50%.
* `signed_blocks_window` - size of blocks window, currently 31 blocks.
* `downtime_jail_duration` - jail duration while validator can't send unjail transaction, currently 600000000000 nanoseconds (10 minutes).
* `slash_fraction_double_sign` - the percent of stake that validator/delegator loses in case validator double sign block, currently 5%.
* `slash_fraction_downtime` - the percentage of stake that validator/delegator loses in case of validator downtime.

**Important:** slashing affects only sXFI delegations, LPT balances can't be slashed.

If validators slashed for downtime (missed signatures/proposals), validator and his delegators loose part of their stakes (see `slash_fraction_downtime`), also, such validator will be `jailed`, after jail period (see `downtime_jail_duration`) validator can send transaction to [unjail](/staking/slashing#unjail) himself. While the validator jailed, he can't propose/sign new blocks and participate in the consensus at all.

If validator double sign block, what's much more critical than downtime, then validator and his delegators will lose part of their stakes (see `slash_fraction_double_sign`), also, validator becoming `jailed` forever, and tombstoned - removed from validators list and can't participate in the consensus at all anymore.

To see your validator slashing statistic, use **dncli**:

```
dncli q slashing signing-info [validator-conspub]
```

Where:

* \[validator-conspub] - is consensus public key of validator, can be found in the output using querying validator commands, like `dncli q staking validators`.

## Unjail

If your validator slashed for downtime, it will be jailed. This is a period when validators can't produce blocks and participate in consensus. To become active again, a validator must send `unjail` transaction. Such a transaction can be sent only after the jail period is completed (see `downtime_jail_duration`), currently, it's 10 minutes.

To send unjail transaction use **dncli**:

```bash
dncli tx slashing unjail --from [account]
```

If the transaction is processed successfully, your validator will be unjailed.


# More

As our documentation describes dfinance protocol futures, we cannot describe everything (such as protocols, libraries, modules, that we're using), but we can provide links for you to learn more.

## Tendermint

Dfinance uses [Tendermint](https://tendermint.com/) protocol. We use Tendermint for consensus, security and p2p communications. Here is [Tendermint documentation](https://docs.tendermint.com/master/#).

## Cosmos SDK

As dfinance is built with Cosmos SDK and inherits standard cosmos modules, you can look at Cosmos documentation, specifically:

* [staking](https://docs.cosmos.network/master/modules/staking/)
* [slashing](https://docs.cosmos.network/master/modules/slashing/01_concepts.html)
* [mint](https://docs.cosmos.network/master/modules/mint/01_concepts.html)
* [distribution](https://docs.cosmos.network/master/modules/distribution/)

Some details that current documentation misses or considers not important you can find there.

## Common

Some other links that could be interesting:

* [What Is a 51% Attack?](https://academy.binance.com/security/what-is-a-51-percent-attack)
* [What Is a Blockchain Consensus Algorithm?](https://academy.binance.com/blockchain/what-is-a-blockchain-consensus-algorithm)
* [Byzantine Fault Tolerance Explained](https://academy.binance.com/blockchain/byzantine-fault-tolerance-explained)
* [Cosmos / Tendermint explained for real idiots](https://medium.com/coinmonks/cosmos-tendermint-explained-for-real-idiots-ab4305cbb41)


# Move VM

This document describes how Move VM works, which types of smart contracts transaction supported by dnode, and how to work with smart contracts in case of **dfinance** blockchain.

## Introduction

Dfinance uses Move VM to implement smart contracts functional: allow users to develop, publish and execute their smart contracts. The current implementation works due to **dnode** implementation with connection to [**dvm**](https://github.com/dfinance/dvm). **DVM** is the implementation of **Move VM** with support of GRPC protocol, that allows communication between dvm and dnode.

Move VM is developed by [Libra](https://libra.org/), a blockchain platform by Facebook. The main difference from other existing virtual machines, like EVM, it's:

* Support of Move language - resource oriented-language developed for Move VM.
* Move VM is resource-oriented: developer can define a resource, place resource under an account and move resources between accounts. But resource can be never duplicated, reused or discarded.
* Bytecode verification. To be executable code must be verifiable.
* Support of transaction-as-script: transaction can contain user script, which won't be published in the blockchain as a smart contract, but instead will be executed. It gives blockchain users more power and flexibility by allowing them to do multiple operations within single transaction written in Move language.

All this makes Move VM much safer than other blockchains VMs. For example, the famous DAO hack just couldn't happen, because of the resource model and bytecode verification.

We recommend reading next parts of this documentation together with [Move book](/move_vm/move_book) which is written by one of our team members.


# Modules

There are two types of smart contracts in **dfinance**: module and script.

Difference between them that module is published into blockchain storage and is stored under the publisher account, while script is simply a transaction-as-script and can only operate with existing modules.

The Move Book also has a section about [modules](https://move-book.com/syntax-basics/module.html) in Move language.

## Write a module

Let's see an example of a small module that will just add two numbers (a and b):

```rust
module Math {
    public fun add(a: u64, b: u64): u64 {
        a + b
    }
}
```

Let's compile this module using **dncli**. Compiler requires sender's address as it's included into bytecode. This address will then be verified on module publish.

```
dncli q vm compile <path-to-mvir> <address> --to-file <output file>
```

Replace variables in this pattern with your own and you will get a compiled module in the specified output file. When it's done, you can publish your module:

```
dncli tx vm publish <output file> --from <account>
```

Check your transaction by querying its id, which was returned in the output.

```
dncli q tx <id>
```

If you see a **contract\_status** event, with status **keep** inside, everything published fine!

When it's done your module is be published under your address, and you and other users can access it in their modules or scripts:

```rust
use {{address}}::Math;
```

Just replace `{{address}}` with yours and you can use this module.


# Scripts

As already mentioned, **dfinance** supports transaction scripting. It means users can compile and execute scripts. Different between modules here is that you can't publish script and use it again in the future, each script executing by new transaction every time.

The Move Book also has a section about [scripts](https://move-book.com/syntax-basics/function.html) in Move language.

## Write a script

Let's write a basic script, accepts two arguments, a and b values, and then using module math make a sum from these two numbers and then fire events.

```rust
script {
   use 0x1::Event;
   use {{sender}}::Math;

   fun main(account: &signer, a: u64, b: u64) {
      let sum = Math::add(a, b);
      Event::emit(account, sum);
   }
}
```

Replace `{{sender}}` with the address you used during publish of the module in the previous part of current documentation.

The script accepts two arguments in function **"main"**, then calculate sum with provided arguments, and fire event with this sum. Both arguments are **u64** integers.

Compile the script using **dncli**:

```
dncli q vm compile <script file> <address> --to-file <output file>
```

And then execute with arguments:

```
dncli tx vm execute <output file> 15 20 --from <my address>
```

You can verify execution with querying transaction by id.

There will be even fired event, that will contain **"keep"** status and the resulting sum, like:

```javascript
[
   {
      "type":"contract_events",
      "attributes":[
         {
            "key":"sender_address",
            "value":"wallet1qjgqxwk55p9ejlupmeza0r02hyextys9rrthgg"
         },
         {
            "key":"source",
            "value":"script"
         },
         {
            "key":"type",
            "value":"u64"
         },
         {
            "key":"data",
            "value":"2300000000000000"
         }
      ]
   },
   {
      "type":"contract_status",
      "attributes":[
         {
            "key":"status",
            "value":"keep"
         }
      ]
   },
   {
      "type":"message",
      "attributes":[
         {
            "key":"action",
            "value":"execute_script"
         },
         {
            "key":"sender",
            "value":"wallet1qjgqxwk55p9ejlupmeza0r02hyextys9rrthgg"
         }
      ]
   },
   {
      "type":"transfer",
      "attributes":[
         {
            "key":"recipient",
            "value":"wallet17xpfvakm2amg962yls6f84z3kell8c5la07d0l"
         },
         {
            "key":"amount",
            "value":"1xfi"
         }
      ]
   }
]
```


# Script Arguments

Each script can contain only one function, usually, it's **"main"**, but you can define it however you want, This function can have arguments and will be executed when you send a transaction with your script.

With **execute** command you can pass arguments to script function, see help:

```
dncli tx vm execute --help
```

**Dncli** **"execute"** supports different kind of arguments, as:

* Boolean values. Example: **true, false**.
* U64, U8, U128 values (unsigned integers).
* vector\ values (hex). Can be used for string values. Example: **0x68656c6c6f2c20776f726c6421**.
* Address values. Example: **wallet1jk4ld0uu6wdrj9t8u3gghm9jt583hxx7xp7he8**.


# Standard Library

Standard **Move VM** library is default modules that already developed and developers can use in developing new modules, scripts.

They all placed on the address **0x1**. So when you import something from **0x1**, you import standard modules, like:

```rust
use 0x1::Account;
use 0x1::Event;
use 0x1::XFI;
use 0x1::Coins;
...
```

You can look for actual standard modules in [dvm](https://github.com/dfinance/dvm/tree/master/stdlib/modules) repository.

## Time

[Time](https://github.com/dfinance/dvm/blob/master/stdlib/modules/time.move) module allows getting current UNIX timestamp of latest block.

Example:

```rust
script {
    use 0x1::Time;

    fun main() {
        let _ = Time::now();
    }
}
```

The method will return u64 value as UNIX timestamp of the latest block.

## Block

[Block](https://github.com/dfinance/dvm/blob/master/stdlib/modules/block.move) module allows getting current blockchain height.

```rust
script {
    use 0x1::Block;

    fun main() {
        let _ = Block::get_current_block_height();
    }
}
```

The method will return u64 value as the height of the latest block.

## Compare

[Compare](https://github.com/dfinance/dvm/blob/master/stdlib/modules/compare.move) module allows comparing two vectors of u8 values (bytes).

Comparing two-byte vectors:

```rust
script {
    use 0x1::Compare;

    fun main() {
        let a = x"00";
        let b = x"01";
        assert(Compare::cmp_lcs_bytes(&a, &b) == 0, 101);
    }
}
```

## XFI && Coins

[XFI](https://github.com/dfinance/dvm/blob/master/stdlib/modules/xfi.move) and [Coins](https://github.com/dfinance/dvm/blob/master/stdlib/modules/coins.move) modules allow to get a type of currency that you going to use in your code.

```rust
script {
    use 0x1::Account;
    use 0x1::XFI;
    use 0x1::Coins;

    fun main(sender: &signer, payee: address, dfi_amount: u128, eth_amount: u128, btc_amount: u128, usdt_amount: u128) {
        Account::pay_from_sender<XFI::T>(sender, payee, dfi_amount);
        Account::pay_from_sender<Coins::ETH>(sender, payee, eth_amount);
        Account::pay_from_sender<Coins::BTC>(sender, payee, btc_amount);
        Account::pay_from_sender<Coins::USDT>(sender, payee, usdt_amount);
    }
}
```

## Oracle

[Coins](https://github.com/dfinance/dvm/blob/master/stdlib/modules/coins.move) module also contains oracles functions: get price and has price.

```rust
script {
    use 0x1::Coins;

    fun main() {
        assert(Coins::has_price<Coins::ETH, Coins::USDT>(), 101);

        let _ = Coins::get_price<Coins::ETH, Coins::USDT>();
    }
}
```

More about work with oracles can see in our [oracles documentation](/oracles).

## Event

[Event](https://github.com/dfinance/dvm/blob/master/stdlib/modules/event.move) module allows us to emit events.

Example with emitting event contains provided number:

```rust
script {
    use 0x1::Event;

    fun main(account: &signer, a: u64) {
        Event::emit<u64>(account, a);
    }
}
```

Or you you can emit event from your module:

```rust
module MyEvent {
    use 0x1::Event;

    struct MyStruct {
        value: u64
    }

    public fun my_event(account: &signer, a: u64) {
        Event::emit(account, MyStruct {
            value: a
        });
    }
}
```

## Signer

[Signer](https://github.com/dfinance/dvm/blob/master/stdlib/modules/signer.move) module allows to work with the `signer` type. To get address of signer:

```rust
script {
    use 0x1::Signer;

    fun main(sender: &signer) {
        let _ = Signer::address_of(sender);
    }
}
```

Signer type is required for functions which work with resources, address of signer could be useful in case of resource related functions: `borrow_global`, `borrow_global_mut`, `exists`, `move_from`.

Read more about the signer type in [Move Book](https://move-book.com/resources/signer-type.html).

## Account

[Account](https://github.com/dfinance/dvm/blob/master/stdlib/modules/account.move) module allows to work with user balances: get balances, deposit coins/tokens to balances, withdraw them to deposit in another module, etc.

Also, it creates an account, if the account doesn't exist yet, and related data, like event handlers for sending/receiving payments.

A lot of different methods can be used to send tokens from account A to account B, as these one-line methods:

```rust
script {
    use 0x1::Account;
    use 0x1::XFI;

    fun main(sender: &signer, payee: address, amount: u128, metadata: vector<u8>) {
        // Move XFI from sender account to payee.
        Account::pay_from_sender<XFI::T>(sender, payee, amount);

        // Again move XFI, but with metadata.
        Account::pay_from_sender_with_metadata<XFI::T>(sender, payee, amount, metadata);
    }
}
```

Also, you can just withdraw from sender balance and deposit to payee:

```rust
script {
    use 0x1::Account;
    use 0x1::XFI;

    fun main(sender: &signer, payee: address, amount: u128) {
        // Move XFI from sender account to payee.
        let xfi = Account::withdraw_from_sender<XFI::T>(sender, amount);

        // Again move XFI, but with metadata.
        Account::deposit(sender, payee, xfi);
    }
}
```

Or deposit to another module:

```rust
script {
    use {{address}}::Swap;
    use 0x1::XFI;
    use 0x1::Coins;
    use 0x1::Account;

    fun main(sender: &signer, seller: address, price: u128) {
        let xfi = Account::withdraw_from_sender(sender, price);

        // Deposit USDT to swap coins.
        Swap::swap<Coins::USDT, XFI::T>(sender, seller, xfi);
    }
}
```

Also, get a balance:

```rust
script {
    use 0x1::Coins;
    use 0x1::Account;

    fun main(sender: &signer, addr: address) {
        // My balance.
        let my_balance = Account::balance<Coins::ETH>(sender);

        // Someone balance.
        let someone_balance = Account::balance_for<Coins::ETH>(addr);

        assert(my_balance > 0, 101);
        assert(someone_balance > 0, 102);
    }
}
```

For the rest of the features of Account module look at [account.move](https://github.com/dfinance/dvm/blob/master/stdlib/modules/account.move).

## Dfinance

[Dfinance](https://github.com/dfinance/dvm/blob/master/stdlib/modules/dfinance.move) module allows you to work with coins balances, get coins info, also register new tokens, etc.

First of all, Dfinance module presents type for all balances in the system, it's `Dfinance::T`:

```rust
resource struct T<Coin> {
    value: u128
}
```

The value field contains information about actual balance for specific coin/token, e.g.:

```rust
script {
    use 0x1::Account;
    use 0x1::XFI;

    fun main(sender: &signer, amount: u128) {
        // Use XFI::T to get Dfinance::T<XFI::T> contains balance.
        let xfi : 0x1::Dfinance::T<XFI::T> = Account::withdraw_from_sender<XFI::T>(sender, amount);
        Account::deposit_to_sender(sender, xfi);
    }
}
```

Also, you can create an empty coin:

```rust
module BankXFI {
    use 0x1::Dfinance;
    use 0x1::XFI;

    resource struct T {
        balance: Dfinance::T<XFI::T>,
    }

    public fun create(account: &signer)  {
        move_to<T>(account, T {
            balance: Dfinance::zero<XFI::T>()
        })
    }
}
```

Get denom, decimals, and actual value:

```rust
script {
    use 0x1::Dfinance;
    use 0x1::Account;
    use 0x1::XFI;

    fun main(sender: &signer, amount: u128) {
        let xfi = Account::withdraw_from_sender<XFI::T>(sender, amount);

        // Get denom vector<8>.
        let _ = Dfinance::denom<XFI::T>();

        // Get value of withdrawed xfi.
        let value = Dfinance::value(&xfi);

        assert(amount == value, 101);

        Account::deposit_to_sender(sender, xfi);
    }
}
```

And check if it's user token or system coin:

```rust
script {
    use {{address}}::MyToken;
    use 0x1::Dfinance;
    use 0x1::XFI;

    fun main() {
        assert(Dfinance::is_token<XFI::T>() == false, 101);
        assert(Dfinance::is_token<MyToken::T>(), 102);
    }
}
```

Also, you can create your resource and make it token too!

```rust
module MyToken {
    use 0x1::Dfinance;

    resource struct Token {
    }

    public fun create(account: &signer): Dfinance::T<Token>  {
        // Create new token with denom "wow" (hex == 776f77).
        Dfinance::tokenize<Token>(account, 10, 0, x"776f77")
    }
}
```

And also deposit it to your balance:

```rust
script {
    use {{sender}}::MyToken;
    use 0x1::Account;

    fun main(sender: &signer) {
        let new_tokens = MyToken::create(sender);
        Account::deposit_to_sender(sender, new_tokens);
    }
}
```

More documentation about the feature provided by Dfinance module see in [dfinance.move](https://github.com/dfinance/dvm/blob/master/stdlib/modules/dfinance.move).

## Vector

[Vector](https://github.com/dfinance/dvm/blob/master/stdlib/modules/vector.move) module contains functions to work with `vector` type.

For example:

```rust
script {
    use 0x1::Vector;

    fun main() {
        let v = Vector::empty<u64>();
        let i = 0;

        loop {
            if (i == 10) {
                break
            };

            Vector::push_back(&mut v, i);
            i = i + 1;
        };
    }
}
```

Vector module great describe in [Move Book](https://move-book.com/advanced-topics/managing-collections-with-vectors.html).

## Signature

[Signature](https://github.com/dfinance/dvm/blob/master/stdlib/modules/signature.move) module allows to verify ed25519 signature:

```rust
script {
    use 0x1::Signature;

    fun main(signature: vector<u8>, pub_key: vector<u8>, message: vector<u8>) {
        let is_verified = Signature::ed25519_verify(signature, pub_key, message);
        assert(is_verified, 101);
    }
}
```


# Events

Each transaction processed by **dfinance** blockchain can have events.

You can see them by querying transaction by id, they're stored under 'events' key:

```javascript
"events": [
    ...
]
```

You can also see events in transaction logs in [block explorer](https://explorer.dfinance.co/txs?page=1).

## VM related events

For smart contracts related transactions, there are reserved types for events, such as:

* **contract\_status** - contains contract execution status. Usually contains **"status"** attribute, which represents one of the possible statuses:
  * **"keep"** - when transaction successful executed by VM (means passed pre-verification, byte code, arguments, etc).
  * **"discard"** - when transaction contains an error, contains attributes:
    * **major\_status** - the major status of error, integer.
    * **sub\_status** - the sub status of error, integer, optional.
    * **message** - text message, optional.
* **contract\_events** -  contains events generated during smart contract execution. In our example of the script, we generated such an event using `Event::emit`. Contains next attributes (attributes always sorted in the same sequence):
  * **sender\_address** - address of account which sent transaction that sent event.
  * **source** - the place where the event was sent, it could be `script` (in case it sent from user script), or path to module which sent event, e.g.: `0x1::Account`.
  * **type** - contains data type, similar to contract arguments, but also could be a struct (in such case there will be reference to which indeed struct used in the event). A struct could be decoded using [lcs](https://github.com/the729/lcs).
  * **data** - [lcs](https://github.com/the729/lcs) encoded data in hex. It could be decoded using [lcs](https://github.com/the729/lcs).

The **data** field always using LCS encoding (Libra Canonical Serialization). There is a community [description](https://github.com/librastartup/libra-canonical-serialization/blob/master/DOCUMENTATION.md) of how it works. Also, Golang [library](https://github.com/the729/lcs), where you can see examples and use for your own projects. So decoding of the **"data"** field should happen with LCS.

There are two reserved events: sent and received events that fire when withdrawing or depositing of resources happens. The implementation you can found in the standard library in [Account](https://github.com/dfinance/dvm/blob/master/stdlib/modules/account.move) module.

Events example:

```javascript
[
   {
      "type":"vm.contract_events",
      "attributes":[
         {
            "key":"sender_address",
            "value":"wallet1qjgqxwk55p9ejlupmeza0r02hyextys9rrthgg"
         },
         {
            "key":"source",
            "value":"0x1::Account"
         },
         {
            "key":"type",
            "value":"0x1::Account::SentPaymentEvent"
         },
         {
            "key":"data",
            "value":"4d01000000000000000000000000000003646669db4b0ed53d2fd0a74ce8f0d106e7ab144eb0fbab00"
         },
         {
            "key":"sender_address",
            "value":"wallet1qjgqxwk55p9ejlupmeza0r02hyextys9rrthgg"
         },
         {
            "key":"source",
            "value":"0x1::Account"
         },
         {
            "key":"type",
            "value":"0x1::Account::ReceivedPaymentEvent"
         },
         {
            "key":"data",
            "value":"4d010000000000000000000000000000036466690490033ad4a04b997f81de45d78deab93265920500"
         },
         {
            "key":"sender_address",
            "value":"wallet1qjgqxwk55p9ejlupmeza0r02hyextys9rrthgg"
         },
         {
            "key":"source",
            "value":"script"
         },
         {
            "key":"type",
            "value":"u64"
         },
         {
            "key":"data",
            "value":"0a00000000000000"
         }
      ]
   },
   {
      "type":"vm.contract_status",
      "attributes":[
         {
            "key":"status",
            "value":"keep"
         }
      ]
   },
   {
      "type":"message",
      "attributes":[
         {
            "key":"action",
            "value":"execute_script"
         },
         {
            "key":"sender",
            "value":"wallet1qjgqxwk55p9ejlupmeza0r02hyextys9rrthgg"
         }
      ]
   },
   {
      "type":"transfer",
      "attributes":[
         {
            "key":"recipient",
            "value":"wallet17xpfvakm2amg962yls6f84z3kell8c5la07d0l"
         },
         {
            "key":"amount",
            "value":"1xfi"
         }
      ]
   }
]
```

Events attributes always sorted in the same sequence, so you can go over `contract_events` attributes to parse event objects.

To catch events you can use REST API, for example, all events from Account module, look at this URL to see how filters work:

```
https://rest.dfinance.co/txs?vm.contract_events.source=0x1::Account
```

Also, look at our [swagger](https://swagger.dfinance.co/) and [Dnode events doc](https://github.com/dfinance/dnode/blob/master/docs/events.md) for details.


# Resources

Resource is the main feature of **Move VM**. Resource is a special type in Move VM, which has strict rules of usage - therefore more safety, and is created to work with digital assets.

Resource type can only be defined and managed in a single module. This module sets rules for accessing, destroying, transfering and checking existence of resources defined in it.

## Develop a resource

Let's create a swap module, that will allow us to swap coins between users.

We will make it easy, it will support only one swap per coin pair, which means, you can't create multiple swaps using the same pair in the same account. Just two functions - to publish your offer and to allow other users to swap it for specified price.

```rust
module Swap {
    use 0x1::Dfinance;
    use 0x1::Account;
    use 0x1::Signer;

    // The resource of module which contains swap parameters.
    resource struct T<Offered, Expected>{
        offered: Dfinance::T<Offered>,
        price: u128,
    }

    // Create a swap deal with two coin pairs: Offered and Expected.
    public fun create<Offered, Expected>(sender: &signer, offered: Dfinance::T<Offered>, price: u128) {
        let sender_addr = Signer::address_of(sender);

        assert(!exists_at<Offered, Expected>(sender_addr), 101);

        move_to<T<Offered, Expected>>(
            sender,
            T<Offered, Expected> {
                offered: offered,
                price
            }
        );
    }

    // Get the price of the swap deal.
    public fun get_price<Offered, Expected>(seller: address): u128 acquires T {
        let offer = borrow_global<T<Offered, Expected>>(seller);
        offer.price
    }

    // Change price before swap happens.
    public fun change_price<Offered, Expected>(sender: &signer, new_price: u128) acquires T {
        let offer = borrow_global_mut<T<Offered, Expected>>(Signer::address_of(sender));
        offer.price = new_price;
    }

    // Swap coins and deposit them to accounts: both creator and buyer.
    public fun swap<Offered, Expected>(sender: &signer, seller: address, exp: Dfinance::T<Expected>) acquires T {
       let T<Offered, Expected> { offered, price } = move_from<T<Offered, Expected>>(seller);
       let exp_value = Dfinance::value<Expected>(&exp);

       assert(exp_value == price, 102);
       Account::deposit(sender, seller, exp);
       Account::deposit_to_sender(sender, offered);
    }

    // Check if the swap pair already exists for the account.
    public fun exists_at<Offered, Expected>(addr: address): bool {
        exists<T<Offered, Expected>>(addr)
    }
}
```

Provided code creates new module **"Swap"** and resource named **"T"** (default name for default resource in modules), which holds information about the deal.

To create a swap use **"create"** function, to make an exchange use **"swap"** function. Other methods in this module provide ability to get/set price, check if swap option already exists at specific address. All methods use generics Offered and Expected, which allow them to make unique resources for each swap.

Even though there's a lot of code inside, we'll focus on 4 main methods: `borrow_global_mut`, `move_to_sender`, `move_from`, `exists` and on `acquires` keyword.

### move\_to\<T>(\&signer, T)

When resource is created, it needs to be moved to address (otherwise it will never be actually created - there's no 'contract storage' - only accounts). It is important to note that newly created resource can be moved only to the sender of transaction - this makes initalization of resource impossible at someone else's address.

To move resource to sender `move_to<T>(&signer, T)` method is used - as obvious as it is - where T is a generic type and instance of this type - a resource:

```rust
// Create a swap deal with two coin pairs: Offered and Expected.
public fun create<Offered, Expected>(sender: &signer, offered: Dfinance::T<Offered>, price: u128) {
    let sender_addr = Signer::address_of(sender);

    assert(!exists<Offered, Expected>(sender_addr), 101);

    move_to<T<Offered, Expected>>(
        sender,
        T<Offered, Expected> {
            offered: offered,
            price
        }
    );
}
```

In `create` function we created new resource which contains information about the swap, and moved it to sender. After this, we can start working with our resources.

### exists\<T>(address)

Allow us to check if the resource already exists on the specific address or not:

```rust
// Check if swap pair already exists for account.
public fun exists_at<Offered, Expected>(addr: address): bool {
    exists<T<Offered, Expected>>(addr)
}
```

### borrow\_global\_mut\<T>(address)

```rust
// Change price before swap happens.
public fun change_price<Offered, Expected>(sender: &signer, new_price: u128) acquires T {
    let offer = borrow_global_mut<T<Offered, Expected>>(Signer::address_of(sender));
    offer.price = new_price;
}
```

Allows getting a mutable reference to a resource, that could be changed then. There is also just `borrow_global` to get immutable reference:

```rust
// Get the price of the swap deal.
public fun get_price<Offered, Expected>(seller: address): u128 acquires T {
    let offer = borrow_global<T<Offered, Expected>>(seller);
    offer.price
}
```

`borrow_global` gives immutable reference to a resource stored under address. You can use this reference to read resource but can't change it.

### acquires

Every function which accesses already created resource must have `acquires` keyword in it signature after which acquired resources are listed. Look at the usage of `borrow_global` and `borrow_global_mut` again. Resource `T` is acquired by both methods `get_price` and `change_price`.

### move\_from\<T>(address)

```rust
public fun swap<Offered, Expected>(sender: &signer, seller: address, exp: Dfinance::T<Expected>) acquires T {
    let T<Offered, Expected> { offered, price } = move_from<T<Offered, Expected>>(seller);
    let exp_value = Dfinance::value<Expected>(&exp);

    assert(exp_value == price, 102);
    Account::deposit(sender, seller, exp);
    Account::deposit_to_sender(sender, offered);
}
```

`move_from<T>(address)` function moves the resource from address. After taking resource off account, it must be used - either destructured (like in example below) or passed to another function. Resources are not automatically destroyed like regular variables and their lifetime must be specified.

### Summary

So `create` function creates a new resource, `swap` function allows to swap (deposit coins to both accounts and *destroy* resource T); we've also added methods to get price of the deal and to change it.

### Publish

You can try to compile and publish module, and then via script call deposit with hash of your secret value, and then withdraw by passing your secret value.

[Here is repository](https://github.com/borispovod/cold-storage-example) to help you. It already contains module and scripts examples.

### Scripts

Here are a few scripts examples, of how you can work with Swap module (don't forget to replace with your address):

**Create**

```rust
script {
    use {{sender}}::Swap;
    use 0x1::XFI;
    use 0x1::Coins;
    use 0x1::Account;

    fun main(sender: &signer, amount: u128, price: u128) {
        let xfi = Account::withdraw_from_sender(sender, amount);

        // Deposit XFI coins in exchange to UDST.
        Swap::create<XFI::T, Coins::USDT>(sender, xfi, price);
    }
}
```

**Swap**

```rust
script {
    use {{sender}}::Swap;
    use 0x1::XFI;
    use 0x1::Coins;
    use 0x1::Account;

    fun main(sender: &signer, seller: address, price: u128) {
        let usdt = Account::withdraw_from_sender(sender, price);

        // Deposit USDT to swap coins.
        Swap::swap<XFI::T, Coins::USDT>(sender, seller, usdt);
    }
}
```

### More about resources

Resources are the most interesting and the most complex topic in Move language. But once you've gotten the idea, the rest is easy.

To know Move better and to learn about resources specifically - see [Move Book](https://move-book.com/resources/index.html). It has a lot to add to the topic and is aimed to make learning Move as easy as possible.


# Move Book

As Move language is very young, there is not much information about it, this is why we are ready to present you **Move Book** - first book about Move language, that contains a lot of information about Move syntax, resources, and techniques, that will increase your performance while you developing something new with Move language.

It will be a good step to read the book at the same time or after reading current documentation, as our documentation is more about Dfinance protocol rather than Move language.

Move book developed by our team member Damir Shamayev with all support of Dfinance and can be found on the official website - [move-book.com](https://move-book.com).


# More

Here is a collection of docs and tutorials, that can help learn more about Move VM and Move language:

* [Libra Documentation](https://developers.libra.org/)
* [Move Technical Paper](https://developers.libra.org/docs/assets/papers/libra-move-a-language-with-programmable-resources/2019-09-26.pdf)
* [Move Whitepaper Deep Dive](https://medium.com/coinmonks/whitepaper-deep-dive-move-facebook-libra-blockchains-new-programming-language-7dbd5b242c2b)


# Oracles

This document described how to work with oracles data in case of **dfinance** network.

## Introduction to price feed oracles

**Dfinance** blockchain supports price feed oracles, every block new transactions coming from oracles nodes and posting prices.

Currently, dfinance supports next tickers:

* **ETH\_USDT** - [Binance](https://www.binance.com/en/trade/ETH_USDT).
* **BTC\_USDT** - [Binance](https://www.binance.com/en/trade/BTC_USDT).
* **XFI\_ETH** - simulation.
* **XFI\_BTC** - simulation.

A list of assets could be updated, so the actual one you can get from [API](https://rest.dfinance.co/oracle/assets).

Currently oracles nodes fetching price from Binance only. Oracle node application published in our Github [repository](https://github.com/dfinance/oracle-app) and we are welcome for contributions: **dfinance** needs more exchanges and ticker pairs.

Every block dfinance platform collect posted prices from whitelisted oracles and then choose median to store final price for the last block.

This functional implemented by dnode in [x/oracle](https://github.com/dfinance/dnode/tree/master/x/oracle) module.


# Query Price

Current **dfinance** VM implementation supports querying the price for the provided ticker thanks to [Coins](https://github.com/dfinance/dvm/blob/master/stdlib/modules/coins.move) module:

```rust
address 0x1 {
/// Enum-like module to make generic type-matching possible, every coin which is
/// officially supported by blockchain (or peg-zone specifically) is added here.
/// Ideally this module should be auto-generated and rarely updated via consensus
module Coins {
    struct ETH {}
    struct BTC {}
    struct USDT {}

    resource struct Price<Curr1, Curr2> {
        value: u128
    }

    public fun get_price<Curr1, Curr2>(): u128 acquires Price {
        borrow_global<Price<Curr1, Curr2>>(0x1).value
    }

    public fun has_price<Curr1, Curr2>(): bool {
        exists<Price<Curr1, Curr2>>(0x1)
    }
}
}
```

There are two functions, get\_price and has\_price, both require two generics (pairs) to make a call, e.g.: BTC\_USDT, ETH\_USDT, XFI\_BTC.

Let's try to query BTC\_USDT price:

```rust
let btc_usd = Coins::get_price<Coins::BTC, Coins::USDT>();
```

As script it looks so:

```rust
script {
    use 0x1::Coins;

    fun main() {
        let _ = Coins::get_price<Coins::BTC, Coins::USDT>();
    }
}
```

Also, you can check, if pair exists:

```rust
script {
    use 0x1::Coins;

    fun main() {
        // If BTC_USDT pair doesn't exist - throw error with code 101.
        assert(Coins::has_price<Coins::BTC, Coins::USDT>(), 101);
    }
}
```

## Price

By default returned **u128** price has reserved **8 decimals places**.

Means price for ETH\_USDT as **100.02** will be presented as **10002000000**.

To see an example look at our [API](https://rest.dfinance.co/oracle/currentprice/btc_usdt), ETH\_USDT part, how price presented there.

## Write a script

Let's write a script that will take BTC\_USDT price and will emit an event with this ticker's price:

```rust
script {
    use 0x1::Event;
    use 0x1::Coins;

    fun main(account: &signer) {
        let price = Coins::get_price<Coins::BTC, Coins::USDT>();

        Event::emit(account, price);
    }
}
```

Compile the script and execute.

You can query results by transaction id to see how events with price fired.

## Usage in module

Similarly, you can write your module, that will use the price from oracles.

Something like:

```rust
module PriceRequest {
    use 0x1::Coins;

    public fun get_eth_usdt_price(): u128 {
        Coins::get_price<Coins::ETH, Coins::USDT>()
    }
}
```

And then just use it in your scripts.


# PegZone

**THIS DOCUMENTATION IS OUT OF DATE. NEW DOCUMENTATION WILL BE AVAILABLE SOON.**

This document described how PegZone works in the case of **dfinance** protocol.

## Introduction

**PegZone** is a protocol allowing to cross-chain values transfers between chains.

Currently dfinance supports Ethereum blockchain: ETH and ERC20 tokens transfers. The protocol built on smart contracts and allowing to lock ETH and ERC20 tokens in smart contract in Ethereum blockchain. This smart contract calling **Bridge** and manages by approved validators list (Proof-Of-Authority).

Once validators nodes see new values locked in the smart contract, validators release equal amount minus fees into dfinance blockchain, on provided address in dfinance network.

Parameters of current **PegZone**:

* Listed coins/tokens: **ETH**.
  * **ETH** parameters:
    * Maximum capacity (ETH): 1 000 000.
    * Minimum exchange (WEI): 1 000.
    * Fees: 0.1%.
* Minimum confirmations: 100.&#x20;

PegZone takes fees only when your deposit your coins/tokens to dfinance, when you withdraw validators don't take fees at all.

Nice UML to see how it works:

![XFI to WETH UML](https://raw.githubusercontent.com/dfinance/eth-peg-zone/master/res/eth_wei_flow.png)

For more details, include smart contracts, check our [eth-peg-zone](https://github.com/dfinance/eth-peg-zone) repository.

**IMPORTANT:** contracts deployed to ropsten testnet, so use only ropsten ETH. This is very experimental software, it could contain critical issues and bugs, use only testnet coins/tokens.


# Deposit

In this documentation explained how to deposit testnet ropsten ETH from your account to **dfinance**.

**Important**: use only ropsten ETH, as all mentioned contracts deployed in ropsten ethereum testnet, and this is experimental software, you can lose your ETH.

## Using wallet

Required:

* [Metamask](https://metamask.io/)
* Ropsten ETH - request from some known faucet, for example, use this [one](https://faucet.ropsten.be/).

Go to [wallet](https://wallet.dfinance.co) portal and recover/create an account.

Then click on **"Transfer"** button to transfer **ETH** from your Metamask account to **dfinance** blockchain.

After 100+ confirmations you ETH will appear on your account in **dfinance**.

## By sending transaction

Using [eth-peg-zone](https://github.com/dfinance/eth-peg-zone) you can write a script in a preferred language, or using [web3](https://github.com/ethereum/web3.js/), or even use any other wallet with support of transaction encoding.

Just send an ethereum transaction to **Bridge** contract address with ETH and signature/parameters of [exchange function](https://github.com/dfinance/eth-peg-zone/blob/cf1ded5369af3c021c47f4bcdea76266462e20af/contracts/Bridge.sol#L199) in **Bridge** contract.

Parameters of **exchange** function:

* **\_currencyId** - you can query from contract, or use **0** for ETH.
* **\_recipient** - your **"wallet1..."** address converted in right format. [Example](https://github.com/dfinance/eth-peg-zone/blob/cf1ded5369af3c021c47f4bcdea76266462e20af/helpers/wb.js) how convert address in the same repository.
* **\_amount** - amount of coins/tokens.

## Contracts

Currenty deployed Bridge contract can be found by address: [0xE2FD9D943FFC4adD2F5952025f32E9a984B3637b](https://ropsten.etherscan.io/address/0xE2FD9D943FFC4adD2F5952025f32E9a984B3637b).


# Usage

Any coin/token deposited with **PegZone** you can use same as you use **XFI**. Means, you can transfer, for example, **ETH**, or use **ETH** in smart contracts.

It's not restricted, just take a examples from current documentation and use **ETH** denom instead of **XFI**.


# Withdraw

You can withdraw your coins/tokens from dfinance back to the chain from which these coins/tokens arrived.

To withdraw your coins/tokens from **PegZone** you need to send only one transaction with **dncli**:

```
dncli tx currencies destroy-currency [chainID] [symbol] [amount] [recipient] [flags]
```

In the case of Ethereum, **chainID** will be **ETH**, and **symbol** also **ETH**, **recipient** is your address in Ethereum network (e.g. **0x01849...**).


