# Getting Started

The documents contained are intended to educate users on Viction's technology and to provide developer tutorials and documentation for building solutions on Viction public blockchain.

* **For Voters/Stakers**: Staking on Viction[ Masternodes](https://vicmaster.xyz/) secures the network and earns rewards. More information can be in our guide on [how to connect wallets to ](https://docs.viction.xyz/general/how-to-connect-to-viction-network)Viction and [how to vote](https://youtu.be/tXp4WHl_sxY).
* **For Masternode Owners**: 150 Masternodes work to secure the entire Viction ecosystem. Each Masternode is a server that uses its computing power to create and sign blocks. For this contribution, Masternodes receive rewards in the form of VIC. A Masternode must satisfy [minimum system requirements](/masternode/requirements) in computing power, RAM, and storage to stably maintain the network. A financial requirement of 50,000 VIC is needed to [apply](/masternode/apply-your-node) to become a Masternode Candidate. Masternode owners should carefully read our dedicated guide to [running a Masternode](/masternode/run-a-full-node), using [tmn](/masternode/run-a-full-node/tmn) and [Docker](/masternode/run-a-full-node/docker), along with our [tutorial](https://medium.com/Viction/how-to-run-a-Viction-masternode-from-a-to-z-3793752dc3d1) on the Viction Medium page and [wiki page](https://github.com/BuildOnViction/docs/wiki).
* **For Developers**: To support the development of Viction's ecosystem growth, we are maintaining a set of tutorials and documents on developing Dapps to be run on Viction. This [Dapp tutorial ](https://docs.viction.xyz/developer-guide/building-dapp-on-Viction)shows how to deploy a smart contract on Viction. For developers who are curious about Viction's source code, this [private Viction testnet](https://docs.viction.xyz/developer-guide/working-with-Viction/Viction-private-testnet-setup) guides how to set up a private Viction testnet.

| **Documentation**                                     | Description                                                                      |
| ----------------------------------------------------- | -------------------------------------------------------------------------------- |
| [General](/general)                                   | Guidelines for getting started with Viction and Viction World Wide Chain         |
| [Developer Guide](/developer-guide)                   | Guides to build Dapps and services using Viction and Viction World Wide Chain    |
| [Masternode](/masternode)                             | Step-by-step guide on how to run and vote for Masternodes                        |
| [APIs](https://buildonviction.github.io/rpc-swagger/) | This document explains how to use Viction APIs                                   |
| [FAQ](/faq)                                           | Frequently asked questions about Viction                                         |
| [Whitepaper and Research](/whitepaper-and-research)   | Official Whitepaper documents and research papers on new technology developments |
| [Legal](/legal)                                       | Terms and conditions for the use of Viction technology                           |


# General

This section provides a general overview of Viction's technology and products.

Viction is a people-centric blockchain, offering zero-gas transactions and enhanced security to make Web3 easy and safe for everyone.&#x20;

Now with Viction World Wide Chain, we provide a novel solution representing a network of app chains that operate concurrently, anchored by a common settlement on Viction.&#x20;

Build, own, win, and be part of Viction World Wide Chain where everyone scales beyond limits.


# Overview

Viction is a people-centric blockchain, offering zero-gas transactions and enhanced security to make Web3 easy and safe for everyone. Now with Viction World Wide Chain, we provide a novel solution representing a network of app chains that operate concurrently, anchored by a common settlement on Viction. Build, own, win, and be part of Viction World Wide Chain where everyone scales beyond limits.

With a network of 150 masternodes utilizing Proof-of-Stake (PoS) consensus, Viction touts its scalability and stability. It employs advanced techniques like double validation, smart contract staking, and proper randomization to enhance security and chain finality. Viction supports all EVM-compatible smart contracts, protocols, and atomic cross-chain token transfers.

Viction is driven by a mission to build a decentralized platform that empowers humanity to connect, collaborate, and create without limitations, envisioning a world where transparency, accessibility, and growth thrive. That’s why we introduced **Viction World Wide Chain**.&#x20;

Viction World Wide Chain provides a novel solution, representing a network of app chains that operate concurrently, anchored by a common settlement on Viction. These fractal-like chains are interconnected through Viction World Wide Chain Protocol (WWCP), allowing for fluid asset and data transfer within these chains, and establishing a foundation for extensive scalability and a myriad of decentralized applications.

Resources might help you navigate Viction ecosystem:&#x20;

* **Viction**: Viction is the core public blockchain powering every product and Dapp built on it.
* **Vicscan**: [Vicscan](https://www.vicscan.xyz/) provides a user-friendly and detailed blockchain explorer user interface for Viction. All blocks, transactions, finality, smart contracts, Dapps, and token information are captured. Also offered are technical visualizations and useful statistics about Viction's performance, token holders, and other functionalities.
* **VicStats:** [VicStats](https://stats.viction.xyz/) is a system for checking the current and historical operational status of all Viction infrastructure.
* **Viction Bridge:** Viction Bridge is now on [SpaceGate](https://docs.coin98.com/products/spacegate) - a cross-chain bridge designed to seamlessly transfer assets from Ethereum to Viction.
* **VicMaster**: [VicMaster ](https://www.vicmaster.xyz/)is a governance Dapp that allows users to see a list of Masternodes and Masternode Candidates. TomoMaster is also used to launch a Masternode Candidate, vote for Masternodes, and view Masternode performance statistics.
* **Viction Data Availability (Viction DA):** a component of the Viction World Wide Chain. This innovation promises to revolutionize the blockchain space by boosting scalability, flexibility, and interoperability, paving the way for Web3 builders to build blockchain applications primed for global uptake. The seamless integration of Viction DA with other rollup stacks facilitates fluid data communications and transfers, boosting shared liquidity and empowering developers with the confidence to innovate within the Viction World Wide Chain network. This strong infrastructure not only propels the growth of the Viction World Wide Chain but also cultivates a dynamic ecosystem where developers can innovate confidently and users benefit from a broader range of secure, interconnected applications.


# Viction Blockchain

The blockchain as a foundation for decentralized projects, web3 Dapps and the VIC token.

## **About Viction network**

Viction is a scalable blockchain powered via Proof-of-Stake Voting (PoSV) consensus, in mainnet since 2018, taking a community-driven approach to accelerate the mass adoption of web3 applications. Viction achieves 2000 TPS, 2-second blocktime, and \~$0 gas fees without compromising decentralization.

Our mission is to accelerate the onboarding of millions of users by empowering today’s web3 applications with technology that masks the friction of Blockchain, all while retaining its underlying benefits.

The Viction blockchain allows web3 builders to build high-performance, and feature-rich blockchain projects on an enhanced EVM-compatible platform. An array of products designed to support users’ speed, privacy, usability, and liquidity needs all in one platform.

Viction network is built on a performance layer that achieves high transaction speeds without compromising decentralization. Proof of Stake Voting (PoSV) consensus gives an incentive to all Viction token-holders to play an active part in staking across a network of 150 high-quality Masternodes, and to monitor their performance and governance actively. The staking-governance Dapp, [VicMaster](https://www.vicmaster.xyz/), is recognized as one of the leading staking platforms in the industry.

Viction runs on the Proof-of-Stake Voting (PoSV) consensus, which is a PoS-based blockchain protocol with a fair voting mechanism, rigorous security guarantees, and uniform probability eventuality. The consensus has the following key novelties:

* Double Validation to strengthen security and reduce the risk of a blockchain fork
* Randomization provides security, and prevents handshaking attacks
* Fast confirmation time and efficient checkpoints for finality

Recently, Viction introduced Viction World Wide Chain, which is a new framework to empower appchains' economy. This approach allows for fluid asset and data transfer within app chains, and establishes a foundation for extensive scalability and a myriad of decentralized applications.

The interchain connectivity is facilitated by Viction World Wide Chain Protocol (WWCP) - a set of smart contracts on the mainnet that manage asset transfer and message relay between appchains. Assets on Viction World Wide Chain are unified under a shared bridge contract, simplifying liquidity management and enabling seamless transactions across the ecosystem.

Powering the Viction World Wide Chain is the Viction Data Availability (Viction DA). This innovation promises to revolutionize the blockchain space by boosting scalability, flexibility, and interoperability, paving the way for Web3 builders to build blockchain applications primed for global uptake.

Viction DA effortlessly manages data across different Appchains, ensuring verification happens quickly without slowing down the systems. This means faster transactions and top-notch security to keep your data protected.

Moreover, the seamless integration of Viction DA with other rollup stacks facilitates fluid data communications and transfers, boosting shared liquidity and empowering developers with the confidence to innovate within the Viction World Wide Chain network. This strong infrastructure not only propels the growth of the Viction World Wide Chain but also cultivates a dynamic ecosystem where developers can innovate confidently and users benefit from a broader range of secure, interconnected applications.


# PoSV Consensus

Viction uses an innovative consensus method called Proof-of-Stake Voting which provides an incentive to all VIC holders to play an active part in staking across a network of 150 Masternodes.

### Overview

Viction is an EVM-compatible blockchain powered by the scalable Proof-of-Stake Voting consensus mechanism that allows every Ethereum smart contract to run with almost instant transaction confirmation. 150 Masternodes secure the Viction blockchain and allow for the following:

* Token holders deposit 50,000 VIC to become a Masternode Candidate
* Token holders vote for Masternode Candidates
* Most voted Candidates are selected as Masternodes
* Masternodes create blocks in a round-robin and use double validation to prevent collusion
* Masternodes finalizing blocks are incentivized

**High Performance**

Massive acceleration of blockchain performance is one of the most important key features of the Viction public chain. With the PoSV consensus protocol, the Viction network provides:

* At least 2,000 TPS while still enhancing security through Double Validation
* 2-second block time and transaction confirmed within 4 seconds

### Double Validation

Double validation provides a trustworthy validation layer for security enhancement through provable uniform distribution decentralized randomization. Specifically, when a Masternode creates a block, it must be verified by another Masternode that is randomly selected among the set of Masternodes before being added to the blockchain. Double validation strengthens Viction’s security, and reduces the risk of forks, and nothing-at-stake attacks, making Viction unique among Proof-of-Stake based blockchains.


# Comparison

Blockchain comparison overview: Viction, Ethereum, EOS, Cardano and Tendermint.

## Bitcoin, Ethereum, and Blockchain <a href="#id-5994" id="id-5994"></a>

Blockchain, the technology behind Bitcoin, has developed over the last decade into one of today’s biggest and most groundbreaking technologies, with the potential to impact every industry from financial to manufacturing, healthcare, and educational institutions. Launched in 2015 by Vitalik Buterin, Ethereum is the most notable public blockchain infrastructure after Bitcoin. Ethereum provides a Turing complete language for writing smart contracts. The latter can be automatically executed based on a set of criteria established in the Ethereum blockchain.

Despite the explosive momentum gained, and promises of Bitcoin and Ethereum, there are still intrinsic issues, especially related to transaction processing performance. Both Bitcoin and Ethereum use Proof-of-Work (PoW) in their consensus algorithm where an extraordinary amount of computing power is spent for calculations, called mining, to create a block. On the other hand, Bitcoin and the current Ethereum provide very poor performance in terms of transaction processing speed: around 10 transactions per second which is incomparable to traditional electronic payment systems such as VISA and MasterCard.

## The shift to the more environmentally friendly, and more efficient Proof-of-Stake <a href="#e443" id="e443"></a>

Proof-of-Stake (PoS) aims to provide a more environment-friendly and efficient consensus protocol. With PoS, the creator of a new block “[is chosen in a deterministic way, depending on its wealth, also defined as a stake](https://steemkr.com/blockchain/@sheydboss/a-very-brief-history-of-blockchain-technology-everyone-should-read)”. Some notable proponents of this shift are [EOS](https://eos.io/), [Ethereum Casper FFG](https://arxiv.org/pdf/1710.09437.pdf), [Cardano](https://www.cardano.org/en/home/), [Tendermint](https://tendermint.com/), and

> These blockchain solutions are not only trying to provide solutions for the energy and cost savings but also promise to solve the blockchain performance problem as well. While some PoS-related similarity is undoubtedly shared between these blockchains, many differences are yet to be analysed.

In this post, we will show how Viction compares with EOS, Ethereum, Cardano and Tendermint. The aspects used for the comparison include *consensus protocol, decentralization, security, scalability/performance, roadmap, and ecosystem*.

![](/files/S1kNSVPokCcDNrycbW48)

## Overview of Viction <a href="#b088" id="b088"></a>

The blockchain industry and the infrastructure of the Internet of Value are being built rapidly around the globe, and to many the atmosphere is eerily similar to the building of the Internet in the late ’90s, with pioneers and dreamers coming together to build a new future. The objective of Viction is to become a leading part of this phenomenon by seamlessly merging an ecosystem of applications, with cryptographic tokens used by millions of mainstream users and a unique blockchain infrastructure architecture, allowing for fast, frictionless payment and a secure, decentralized, and trusted store of value.

> Viction aims to be a public EVM-compatible blockchain with the following advantages: low transaction fees, fast confirmation time, double validation and randomization for security guarantees. Viction Labs envisions an ecosystem of different Dapps running on the Viction blockchain infrastructure.

In particular, our solution solves the transaction processing performance bottleneck in Ethereum which hinders its adoption into industries, especially finance. More specifically, Viction is an efficient and secured consensus protocol, which tackles the following main bottlenecks of classic blockchains:

* *Efficiency: The small throughput of Bitcoin and Ethereum severely hinders the widespread adoption of such crypto-currencies.*
* *Confirmation times: Bitcoin takes on average 1 hour to confirm a transaction because the confirmation of a Bitcoin block requires 5 subsequent blocks created following it. While Ethereum uses a smaller block-time, the average confirmation time still remains relatively high, around 13 minutes. These long confirmation times hinder many important applications (especially smart contract applications).*
* *Fork generation: The problem of fork chain consumes computational energy, and time, and creates potential vulnerabilities for different types of attacks.*

[In the technical paper](https://viction.xyz/files/technical-whitepaper-1.0.pdf), Viction proposed the Proof-of-Stake Voting (PoSV) consensus, which is a PoS-based blockchain protocol with a fair voting mechanism, rigorous security guarantees, and uniform probability. The consensus has the following key novelties:

* *Double Validation to strengthen security and reduce fork risk*
* *Randomization to guarantee a fair division of labour between Masternodes, and prevent handshaking attacks*
* *Fast confirmation time and efficient checkpoints for finality or rebase*

## Overview of EOS.IO <a href="#c0a8" id="c0a8"></a>

[The EOS.IO blockchain architecture is designed to enable vertical and horizontal scaling of decentralized applications](https://github.com/EOSIO/Documentation/blob/master/TechnicalWhitePaper.md). This is achieved by creating an operating system-like construct upon which applications can be built. EOS.IO offers a blockchain architecture that may ultimately scale to millions of transactions per second, eliminate user fees, and allow for quick and easy deployment and maintenance of decentralized applications, in the context of a governed blockchain. EOS.IO, led by Daniel Larimer, relies on the Delegated Proof-of-Stake (DPoS) consensus protocol, which stems from the Bitshares DPoS. Its performance promises to scale to millions of transactions per second with a great ecosystem of Dapps running on it.

## Overview of Cardano <a href="#cda2" id="cda2"></a>

Cardano is the first full open-source decentralized public blockchain and cryptocurrency project based on peer-reviewed academic work implemented in Haskel. It is developed by IOHK engineering body in conjunction with multiple universities. Cardano uses the a secure Proof of Stake consensus, namely, Ouroboros. The latter is backed by strong researches and sound mathematical formalisations and proofs that provide more confidence about security and scalability. [Cardano promises to allow for developers to build decentralised applications and contracts and run them in a low-cost, secure, private, scalable and legal environment](https://www.cryptomorrow.com/2017/10/10/is-cardano-better-than-ethereum/). On one hand, Cardano Ouroboros is geared towards user privacy. On the other hand, it also takes into consideration the needs of regulators in order to easily upgrade the system. In doing so, Cardano claims being [the first protocol to balance these requirements in a nuanced and effective way, pioneering a new approach for cryptocurrencies.](https://cardanofoundation.org/protocol/#technological-innovation)

## Overview of Tendermint <a href="#f783" id="f783"></a>

[The Tendermint blockchain infrastructure is designed to be easy-to-use, simple-to-understand, highly performant, and useful for a wide variety of distributed applications](https://tendermint.readthedocs.io/projects/tools/en/master/introduction.html). Tendermint aims for secure and consistent replication of an application on many machines. Security means that Tendermint works even if up to 1/3 of machines fail in arbitrary ways. Consistency means that every non-faulty machine sees the same transaction log and computes the same state. These two properties play a critical role in the fault tolerance of a broad range of applications, from currencies, to elections, to infrastructure orchestration, and beyond.

Tendermint consists of a consensus engine, called Tendermint Core and a generic application interface. Tendermint Core relies of the PoS and [Byzatine Fault Tolerance (BFT)](https://medium.com/loom-network/understanding-blockchain-fundamentals-part-1-byzantine-fault-tolerance-245f46fe8419) to ensure that every machine stores the same transactions in the same order. On the other hand, the application interface enables the transactions to be processed in any programming language. Therefore, developers can use Tendermint for BFT state machine replication of applications written in whatever programming language and development environment is right for them.

## Comparison criteria <a href="#id-4c41" id="id-4c41"></a>

## Consensus <a href="#id-2ab4" id="id-2ab4"></a>

Consensus is undoubtedly the core mechanism of any decentralized cryptocurrency. It maintains the consistency, immutability, and security of the blockchain on all full nodes of decentralized systems. Bitcoin blockchain with its Proof-of-Work provides securities and decentralization but leaving its scalability as bottleneck. Since then, many consensus protocols have been proposed to leverage. These mechanisms include many variants of Proof-of-Stake-based consensus protocols that are found in the aforementioned projects. The latter do not only aim for solving the energy wasting problem of current Bitcoin and Ethereum but also for improving transaction processing performance.

## Decentralization <a href="#id-4da0" id="id-4da0"></a>

One of the facts that make the Bitcoin blockchain become a subject of great interest lies in its decentralization. Different from existing centralized systems and/or what we call “closed distributed systems”, Bitcoin operates on an “*open*” or “*permissionless*” decentralized systems where any node can join and leave the network, and makes the joining-leaving of nodes become “*daily activities*” that it must deal with. By this way, the single points of failure problem residing in centralized systems can be eliminated. As a result, the more decentralization a system offers, the more data availability and fault tolerance it supports.

## Security <a href="#bbcc" id="bbcc"></a>

One of the clearly visible and pioneering applications of blockchain is in financial industry. The current total market cap of cryptocurrencies is more than 300 billions of dollars, which incentivizes attackers to penetrate or attack the system. There are many attack types to these systems such as double-spending, nothing-at-stake, spamming, DDoS and long range attacks. Blockchain-based cryptocurrency systems must not only deal with these attacks but also ensure the stability of the system, which includes safety and liveness.

## Scalability/performance <a href="#id-55b8" id="id-55b8"></a>

Current financial technologies such as Visa and Master can handle thousands of transactions per second, which definitely defeat the poor transaction processing performance of Bitcoin and Ethereum. Thus, in order for the latter to gain more adoption to the financial industry as well as other industries such as logistics and manufacturing, blockchain technologies must leverage its scalability/performance. Therefore, we consider performance as one of the key criteria to evaluate the success of a blockchain system.

## Roadmap <a href="#id-1d77" id="id-1d77"></a>

Generally speaking, a technology roadmap is a flexible planning technique to support strategic and long-range planning, by matching short-term and long-term goals with specific technology solutions. Roadmap is one of the important aspects for assessing the potential as well as the vision of a project.

## Ecosystem <a href="#id-08c1" id="id-08c1"></a>

All the aforementioned blockchain projects are building infrastructure upon which other Dapps can be built. The stronger the infrastructure and its support, the more Dapps can be based on it for creating a strong ecosystem. Moreover, a strong ecosystem of Dapps will attract more users of the infrastructure, which in turn motivates improvements and entails the development of the underlying infrastructure. Each of the above blockchain projects provides PoS-based consensus that can handle thousands of transactions per second, thus promises many potentials Dapps for the ecosystem.


# Staking

Viction Labs has on-chain Staking services that allow people to secure the chain and earn VIC as rewards. Follow these instructions to stake and earn rewards on Viction network.

{% content-ref url="/pages/F8khMPNlcv481nmoP3QK" %}
[Staking Requirements](/general/staking/staking-requirements)
{% endcontent-ref %}

{% content-ref url="/pages/Q0gFiIj2u1QQM3vEixww" %}
[Staking Rewards](/general/staking/staking-rewards)
{% endcontent-ref %}


# Staking Requirements

Introduction to stake VIC on Masternodes.

### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

* Have a wallet connected to the VicMaster Governance Dapp

### Introduction <a href="#introduction" id="introduction"></a>

With a connected wallet, it's time to try voting for some Masternodes. If there is any trouble with connecting to the Viction network, go to [How to Connect to Viction Network](/how-to/how-to-connect-to-viction-network).

### How To Vote <a href="#how-to-vote" id="how-to-vote"></a>

Access our Governance Dapp, [VicMaster](https://vicmaster.xyz/), to start voting for Masternodes.

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

Click the "Login" button. VicMaster natively supports multiple options to login including MetaMask, [Ledger](https://app.gitbook.com/@Viction/s/Viction-docs/general/how-to-connect-to-viction-network/ledger), Trezor, and Private Key/Mnemonic. Select the appropriate option and log in.

Once configured, vote for Masternodes by clicking on the `Vote` button.

At least 100 VIC is required per vote. After clicking submit, your VIC will be sent to the voting smart contract and locked there.

### How to Unvote <a href="#how-to-unvote" id="how-to-unvote"></a>

Unvote by clicking the `Unvote` button on the Masternode's page and entering the amount of VIC to unvote.

After unvoting, VIC is still locked in the smart contract for \~48 hours (96 epochs) before it is able to be withdrawn.

### How to Withdraw <a href="#how-to-withdraw" id="how-to-withdraw"></a>

To withdraw after unvoting, wait until the VIC is unlocked from the smart contract after \~48 hours (96 epochs). Then click the `withdraw` button under the account page (the vertical three dots on the top right) and choose from the list of withdrawal options to withdraw back into the wallet.

Note that you might see multiple withdrawals on the account page if there have been multiple unvotes made previously.

Withdraws cannot be attempted before the unlock period expires.


# Staking Rewards

## Token Emission Schedule

* **Following the fundraising commitment**: The total number of tokens at the genesis block is 55 million VIC tokens for circulation; 12 million additionally are reserved for the team vested over 4 years; and another 16 million are reserved for strategic partners and as part of an ecosystem building fund. The final 17 million are reserved as block rewards for 8 years. The amount of tokens in circulation at the end of the 8th year after the genesis block is 100 million VIC. After the mainnet: the block reward for the first and second year is 4 million VIC annually; the block reward for the 3rd, 4th, 5th year is 2 million VIC annually; and the block reward for the 6th, 7th and 8th year is 1 million VIC annually. Subsequently, the block reward will be halted, or activated at a number less than or equal to 1 million VIC annually.
* **Implementation**: Each epoch consists of 900 blocks, which will reward a total of 250 VIC in the first two years. 250 VIC will be divided across all Masternodes proportional to the number of signatures they sign during the epoch. The reward achieved by each Masternode will be divided into three portions. The first portion of 40%, called the “Infrastructure Reward,” goes to the Masternode. The second portion of 50%, called the “Staking Reward,” goes to the pool of all voters for that Masternode shared proportionally based on the number of tokens staked out of the total number of tokens staked. The last portion of 10%, called the “Foundation Reward,” goes to a special account controlled by the Masternode Foundation, which is run by Viction Lab Pte Ltd. initially.
* **Reward frequency**: Every epoch (\~30 minutes), Voters and Masternodes automatically receive rewards.

## Reward Calculation Formula and Details

Note that, for simplification of illustration:

* The total amount of staked VIC for all Masternodes is equal
* The signatures for all Masternodes in the scenarios are equal

With these assumptions, all Masternodes receive the same divided reward (R) and the same infrastructure reward. Furthermore, the reward for Voters with 1,000 staked VIC is equal regardless of which Masternode is voted for.

### Scenario 1: 50 Masternodes, 2.5 million token voting, a total of 5 million token locked.

**Reward per epoch:**

* MN infrastructure reward = 0.4 \* 5 = 2 VIC
* For Voters with 1k staked = (0.5 \* 5 \* 1000) / 100k = 0.025 VIC
* MN staking reward with 50k VIC deposited = 50 \* 0.025 = 1.25 VIC

**Reward per week:**

* MN infrastructure reward = 336 \* 2 = 672 VIC
* For Voters with 1k staked = 336 \* 0.025 = 8.4 VIC
* MN staking reward with 50k VIC deposited = 336 \* 1.25 = 420 VIC

**Reward per year:**

* MN infrastructure reward = 17,520 \* 2 = 35,040 VIC
* For Voters with 1k staked = 17,520 \* 0.025 = 438 VIC
* MN staking reward with 50k deposited = 17,520 \* 1.25 = 21,900 VIC
* Total reward per MN with 50k deposited = 35,040 + 21,900 = 56,940 VIC

### Scenario 2: 100 Masternodes, 3 million token voting, a total of 8 million token locked.

**Reward per epoch:**

* MN infrastructure reward = 0.4 \* 2.5 = 1 VIC
* For Voter with 1k voted = (0.5 \* 2.5 \* 1000) / 80k = 0.015625
* MN staking reward with D = 50k deposited: 50 \* 0.015625 = 0.78125 VIC

**Reward per week:**

* MN infrastructure reward = 336 \* 1 = 336 VIC
* For Voter with 1k voted = 336 \* 0.015625 = 5.25 VIC
* MN staking reward with D = 50k deposited: 336 \* 0.78125 = 262.5 VIC

**Reward per year:**

* MN infrastructure reward = 17,520 \* 1 = 17,520 VIC
* For Voter with 1k voted = 17,520 \* 0.015625 = 273.75 VIC
* MN staking reward with D = 50k deposited: 17,520 \* 0.78125 = 13,687.5 VIC
* Total reward per MN with D = 50k deposited: 17,520 + 13 687.5 = 31,208 VIC

### Scenario 3: 150 Masternodes, 12.5 million token voting, a total of 20 million token locked.

**Reward per epoch:**

* MN infrastructure reward = 0.4 \* 1.6667 = 0.6667 VIC
* For Voter with 1k voted = (0.5 \* 1.6667 \* 1000) / 133,333 = 0.00625 VIC
* MN staking reward with 50k deposited: 50 \* 0.00625 = 0.3125 VIC

**Reward per week:**

* MN infrastructure reward = 336 \* 0.6667 = 224 VIC
* For Voter with 1k voted = 336 \* 0.00625 = 2.1 VIC
* MN staking reward with D = 50k deposited: 336 \* 0.3125 = 105 VIC

**Reward per year:**

* MN infrastructure reward = 17520 \* 0.6667 = 11,680 VIC
* For Voter with 1k voted = 17520 \* 0.00625 = 109.5 VIC
* MN staking reward with D = 50k deposited: 17,520 \* 0.3125 = 5,475 VIC
* Total reward per MN with D = 50k deposited: 11,680 + 5,475 = 17,155 VIC


# How to stake on Viction Wallet

## How to vote for a validator.

Staking/Voting is a function to help you stake your VIC to earn profits right in the Viction Wallet. You need to prepare at least 10 VIC for each vote.

This approach is mostly used for users who already have their own wallets.

**Step 1:** Access to Viction Wallet.

If you do not have any voting/unvoting, you will see the onboarding screen.

<figure><img src="https://lh7-us.googleusercontent.com/j0OMrAckKwuUj1ufmtr3PkSFDElbF-Pi8imgAYrvjEBMGfluXQ2rwBxL1NhEZ8uwqbM_kW38X_RIpgTuKAXKx3sCRJsVaMwOrn2H_OIhAcSzem2cdwah8WeOdB0gd3-ETTgcXKvlb4qXHOQEBxGW568" alt=""><figcaption></figcaption></figure>

If you have already voted, you will see the screen below.

<figure><img src="https://lh7-us.googleusercontent.com/_04ARUk7FTkNrOHGeJugbqEoNuawdLR_oTmx6L9pSvtSKJW-HbGYN1nE0lOUni1SXt8i_rPOL5QRapPkkPWpQUiugNRiXxl8QQ-1Yj6X5p2aBkx4YrmjeQgiTqt0YQ4joj0WKnJg-6ae-UcykwtrV0I" alt="" width="375"><figcaption></figcaption></figure>

**Step 2:** Select a validator then input the vote amount and click **Review** button;

<figure><img src="https://lh7-us.googleusercontent.com/EWcKwMoXW1dJCvPaeJdW_ey3m1EGTbQ4Igj_-n7Eo1luc2ujqh_fDQ3TAzWZ5_0k9f6JIvLqwAQwa2AMjgPk66M3cd3ehL9hP_W6huxsA4trV9UwF2B7zQb-sBINaYl04Ivb663EiLCYPDNvtK9_Re8" alt=""><figcaption></figcaption></figure>

**Step 3:** Recheck the information and **Confirm** to complete\*\*.\*\*

<figure><img src="https://lh7-us.googleusercontent.com/eXrJtnCnEwvTSn3u69TyhvbkqNTYpmtQYMyIsWD979hYf1M59IHgrKJTKsN6L1z3AxDTaRCDrCLAt06eN7xfNjsfboROcj_RwwTYrN7C_HiFYOVDLVumWQOr9BFAR4ecVOqfXoxTIPaBn3ez9aS-FqQ" alt="" width="375"><figcaption></figcaption></figure>

## How to Unvote for a validator?

After unvoting, your unvote balance will be withdrawable after 48 hours.

**Step 1**: Choose the validator you want to unvote, then click **Unvote;**

**Step 2**: Input the unvote amount, then click **Review;**

<figure><img src="https://lh7-us.googleusercontent.com/q31MEKluMf_PV35DLh7Ftzv3yUnoYDlghuaq-vfC_DPcjtz4NfczXV4OKWG5BxnbHEtLr3dpsCdUMFWRpBsZM-s4t-AmEvvLUOrolzyvFPqyMUX004kz7EXl4sqK-gZF5ayH5E7lX4ejmYoP4jTWkKM" alt="" width="375"><figcaption></figcaption></figure>

**Step 3:** Confirm the transaction.

## How to Withdraw?

To withdraw after unvoting, you need to wait until the VIC is unlocked from the smart contract after \~48 hours (96 epochs). Then click the Withdraw button on the Staking feature screen.

**Step 1**: On the home screen, click **Withdraw;**

<figure><img src="https://lh7-us.googleusercontent.com/7Xll1YWi-MuijTzEqnYmlaEuj1DL6M9iVTY-DOX9M4JjFPvnZ59hAJGDhcXrzd1CMU9F0bykzyMJuh-tWf-55TGTqryk7nIy7Y-7Nddj7Ux-BWZXI5bo-b6DWbjWlhMoSWe_D3gZlMzCRxSNnPf5pZk" alt="" width="375"><figcaption></figcaption></figure>

**Step 3**: Confirm the transaction

## Reward Distribution

For every epoch (\~30 minutes), Voters and Masternodes automatically receive rewards.

Notes:

* Ensure you have sufficient funds in your staking wallet for voting or unvoting.
* Transactions may take some time to process.
* Double-check all details before confirming any transaction to avoid errors.


# Network Information


# Viction Mainnet

### Specifications

* Chain ID: `88 or 0x58`
* RPC endpoint: `https://rpc.viction.xyz`
* Websocket endpoint: `wss://ws.viction.xyz`
* HD derivation path: `m/44'/60'/0'/0/`
* Consensus: POSV
* Block finality: `>75%`
* Consensus nodes: up to 150 (masternodes)
* Genesis block date: `December 14th, 2018`
* Transaction fee: gas price 0.25 Gwei
* Solidity Compiler version: <= 0.8.17

### Other RPC Providers

* RockX: <https://access.rockx.com/product/viction-blockchain-api-for-web3-builders>
* BlockPi: <https://blockpi.io/viction>
* dRPC:
  * RPC endpoint: [`https://viction.drpc.org`](https://viction.drpc.org)
  * Websocket endpoint: wss\://viction.drpc.org

### Useful links

* [Status page](https://stats.viction.com/)
* [VicScan](https://www.vicscan.xyz/) (Block explorer)
* [VicMaster](https://vicmaster.xyz/) (Governance dApp)
* [VicIssuer](https://issuer.viction.xyz/) ([Dashboard](https://medium.com/Viction/how-to-deploy-a-trc-21-token-on-Viction-in-a-few-clicks-d0290f918b9a) to issue your token)
* [VicMaster smart contract](https://www.vicscan.xyz/address/0x0000000000000000000000000000000000000088) (for staking and applying a new masternode)

### Bootnodes

```
enode://98b06c30c631ab869c25b4836684b3de632ec7db60db34920095f8039cd49076913a64565dc4d8a06569bd84afa9553b95590ba3dd86263e3b9b5657463693a7@162.19.43.250:30301
enode://4c075010c7c1199240aea58a4e570b13af374a4aa2ed0219360c6017da34ca644706426ab2c75f1da00552ef4a40245ba043854d20e7c1873306023b6790bf03@15.235.228.11:30301
enode://477afcdf9581d0f38f00b2d0376bb536a3c71b13fcfa3d6039efb19c57a69e389b819efeb516609fe3eb3c90a8ffe620e62abaf481de6b07b873cad543a635fb@162.19.103.252:30301
enode://6a03f00972d02bc1f004fd05adf9384fb05a629e69ae894eebe1b55fe667a2313b595a180418f505948f99e5c66661229f8ea1d5c12aadb16433cae3122d1d8a@3.1.61.17:30301
enode://f799bf1da9f8b25891054913d876b1dcc301284fd001078239bcb5fb408078ac89741b8039f9adb0dfbfe72dca0b753e48099de3a059c3e23dc2402434ff8fd6@13.229.196.181:30301
enode://d3a79693bf18fd5136a4b1809193e28f94400b00a65a7f21c918876d986212c8031834b332f39fb8a814fb5e90f0e413fead6953d1aa23a839bba1224e285ed6@122.248.245.143:30301
```

### Stats websocket secret

`getty-site-pablo-auger-room-sos-blair-shin-whiz-delhi`

Host: stats.viction.xyz:443


# Viction Testnet

The Testnet network is meant to be a public demo of products and a way for to test new features.

### Specifications

* **ChainID**: `89`
* **RPC endpoint**:  `https://rpc-testnet.viction.xyz`
* **Websocket endpoint**: `wss://ws-testnet.viction.xyz`
* **HD derivation path**: `m/44'/60'/0'/0/`
* **Consensus**: POSV
* **Block finality**: `>75%`
* **Consensus nodes**: up to 150 (masternodes)
* **Solidity Compiler version**: <= 0.8.17

### Useful links

#### Stats page

[`https://stats-testnet.viction.xyz/`](https://stats-testnet.viction.xyz/)

#### Block Explorer

[`https://testnet.vicscan.xyz`](https://testnet.vicscan.xyz)

#### Governance Dapp

[`https://master-testnet.viction.xyz/`](https://master-testnet.viction.xyz/)

**VICMaster Smart Contract**: for staking and applying a new masternode [`https://testnet.vicscan.xyz/address/0x0000000000000000000000000000000000000088`](https://testnet.vicscan.xyz/address/0x0000000000000000000000000000000000000088)

#### Faucet

[`https://faucet-testnet.viction.xyz`](https://faucet-testnet.viction.xyz)

#### VIC Issuer

[`https://issuer-testnet.viction.xyz/`](https://issuer-testnet.viction.xyz/)

### Bootnodes

<pre><code>enode://77c303c0d7cd03cb0fcfee0b7fc1b162d2fcaf667dc23b416e631196c8d7bed9b937944372b4673bc3d8dcede4b37bf8e7e8855bbda76c96bba3fb573a10f1ad@162.19.43.250:30304
enode://b9b5f61ab47f3681e75240d8b86d05ab451cd47f206d1d3cb69a87c71491236cec10b8a7740ec88616199d6a76d309f41a647e2802a63a8e449773ee3a920ba4@15.235.228.11:30304
<strong>enode://0f41c53da72e07e3514efd7ce9e3f758acc2066d8ae66955e540620f7108fff91f8ebdc734b89dca14db2a70cdaf8c957579ec94e3dfdfe91b2923272f1cc099@13.214.64.64:30601
</strong></code></pre>

### Stats websocket secret

`bgfmsp2r7TgIYA2HW48SkBQE6L4CUc`

Host: wss\://stats-testnet.viction.xyz:443

### For developers

Testnet is the best way to test smart contracts. Configure the deployment tool (truffle for example) to connect to the testnet and deploy new code without having to worry about fees.

### For investors and enthusiasts

The Testnet is the exact same ecosystem as that on the actual Mainnet.

###


# Viction RPC API

This document explains how to use Viction APIs

Viction RPC [APIs](https://buildonviction.github.io/rpc-swagger/)


# Smart Contract Development

This section covers the development resources for Smart Contract development.


# Solidity

This page is a reduced version of the Solidity docs site that is adapted to Viction network to avoid overwhelming information.

### About

Solidity is a contract-oriented, high-level language for implementing smart contracts. It was influenced by Python and JavaScript and is designed to target the Ethereum Virtual Machine (EVM) both Ethereum and Viction.

Solidity is statically typed, supports inheritance, libraries and complex user-defined types among other features.

### Solidity in Viction

Viction support Solidity compiler version **<=0.8.17**, which targets `London` hardfork in Ethereum. However, due the fee mechanism in Viction, `BASEFEE` opcode is unused and not supported by the runtime.

{% hint style="info" %}
For Solidity compiler version >=0.8.18, you may still compile and deploy to Viction. However, use it at your own risk.
{% endhint %}

The table below describes all the opcodes that isn't available in Viction:

<table><thead><tr><th width="143.5">Opcode</th><th>Description</th></tr></thead><tbody><tr><td>BASEFEE</td><td>Return base fee of block, this using for <a href="https://eips.ethereum.org/EIPS/eip-1559">https://eips.ethereum.org/EIPS/eip-1559</a> on London hardfork.</td></tr><tr><td>TLOAD</td><td>This opcode using for Access List Transaction Type, which hasn’t have any implement for now</td></tr><tr><td>TSTORE</td><td>This opcode using for Access List Transaction Type</td></tr><tr><td>PUSH0</td><td>This opcode pushes the constant value 0 onto the stack. It is generated in Solidity version 0.8.20 or higher.</td></tr><tr><td>INVALID</td><td>Improve the traces process.</td></tr><tr><td>BLOBHASH</td><td>Which is specific to DankSharding hardfork.</td></tr></tbody></table>

### Example

As you will see, it is possible to create contracts for voting, crowdfunding, blind auctions, multi-signature wallets and more.

{% hint style="info" %}
The best way to try out Solidity right now is using [Remix](https://remix.ethereum.org/) (it can take a while to load, please be patient). Remix is a web browser-based IDE that allows you to write Solidity smart contracts, then deploy and run the smart contracts.
{% endhint %}

Once you're strong enough, on the next pages, we will first see a [simple smart contract](https://docs.soliditylang.org/en/v0.8.17/introduction-to-smart-contracts.html#simple-smart-contract) written in Solidity followed by the basics about [blockchains](https://docs.soliditylang.org/en/v0.8.17/introduction-to-smart-contracts.html#blockchain-basics) and the [Ethereum Virtual Machine](https://docs.soliditylang.org/en/v0.8.17/introduction-to-smart-contracts.html#the-ethereum-virtual-machine).

The next section will explain several *features* of Solidity by giving useful [example contracts](https://docs.soliditylang.org/en/v0.8.17/solidity-by-example.html#voting). Remember that you can always try out the contracts [in your browser](https://remix.ethereum.org/)!

The last and most extensive section will cover all aspects of Solidity in depth.

If you still have questions, you can try searching or asking on the [Ethereum Stackexchange](https://ethereum.stackexchange.com/) site, or come to our [Gitter channel](https://gitter.im/ethereum/solidity/). Ideas for improving Solidity or this documentation are always welcome! the world:

{% code title="hello.sh" %}

```bash
# Ain't no code for that yet, sorry
echo 'You got to trust me on this, I saved the world'
```

{% endcode %}


# A Simple Smart Contract

A basic example that sets the value of a variable and exposes it for other contracts to access

#### Storage Example

```solidity
pragma solidity 0.8.17;

contract SimpleStorage {
    uint storedData;

    function set(uint256 x) public {
        storedData = x;
    }

    function get() public view returns (uint) {
        return storedData;
    }
}
```

The first line tells you that the source code is written for Solidity version 0.8.17. This is to ensure that the contract is compatible with the current EVM version in Viction.

A contract in the sense of Solidity is a collection of code (its *functions*) and data (its *state*) that resides at a specific address on the Viction blockchain. The line `uint storedData;` declares a state variable called `storedData` of type `uint256` (unsigned integer of *256* bits). You can think of it as a single slot in a database that you can query and alter by calling functions of the code that manages the database. In this example, the contract defines the functions `set` and `get` that can be used to modify or retrieve the value of the variable.

To access a state variable, you do not need the prefix `this` as is common in other languages.

This contract does not do much yet apart from allowing anyone to store a single number that is accessible by anyone in the world without a (feasible) way to prevent you from publishing this number. Anyone could call `set` again with a different value and overwrite your number, but the number is still stored in the history of the blockchain. Later, you will see how you can impose access restrictions so that only you can alter the number.

#### Subcurrency Example

The following contract implements the simplest form of a cryptocurrency. The contract allows only its creator to create new coins (different issuance schemes are possible). Anyone can send coins to each other without a need for registering with a username and password, all you need is a Viction private key.

```solidity
pragma solidity 0.8.17;

contract Coin {
    // The keyword "public" makes variables
    // accessible from other contracts
    address public minter;
    mapping (address => uint256) public balances;

    // Events allow clients to react to specific
    // contract changes you declare
    event Sent(address from, address to, uint256 amount);

    // Constructor code is only run when the contract
    // is created
    constructor() public {
        minter = msg.sender;
    }

    // Sends an amount of newly created coins to an address
    // Can only be called by the contract creator
    function mint(address receiver, uint256 amount) public {
        require(msg.sender == minter);
        require(amount < 1e60);
        balances[receiver] += amount;
    }

    // Sends an amount of existing coins
    // from any caller to an address
    function send(address receiver, uint256 amount) public {
        require(amount <= balances[msg.sender], "Insufficient balance.");
        balances[msg.sender] -= amount;
        balances[receiver] += amount;
        emit Sent(msg.sender, receiver, amount);
    }
}
```

This contract introduces some new concepts, let us go through them one by one.

The line `address public minter;` declares a state variable of type [address](https://docs.soliditylang.org/en/v0.8.17/types.html#address). The `address` type is a 160-bit value that does not allow any arithmetic operations. It is suitable for storing addresses of contracts, or a hash of the public half of a keypair belonging to [external accounts](https://docs.soliditylang.org/en/v0.8.17/introduction-to-smart-contracts.html#accounts).

The keyword `public` automatically generates a function that allows you to access the current value of the state variable from outside of the contract. Without this keyword, other contracts have no way to access the variable. The code of the function generated by the compiler is equivalent to the following (ignore `external` and `view` for now):

```solidity
function minter() external view returns (address) { return minter; }
```

You could add a function like the above yourself, but you would have a function and state variable with the same name. You do not need to do this, the compiler figures it out for you.

The next line, `mapping (address => uint256) public balances;` also creates a public state variable, but it is a more complex datatype. The [mapping](https://docs.soliditylang.org/en/v0.8.17/types.html#mapping-types) type maps addresses to [unsigned integers](https://docs.soliditylang.org/en/v0.8.17/types.html#integers).

Mappings can be seen as [hash tables](https://en.wikipedia.org/wiki/Hash_table) which are virtually initialised such that every possible key exists from the start and is mapped to a value whose byte-representation is all zeros. However, it is neither possible to obtain a list of all keys of a mapping, nor a list of all values. Record what you added to the mapping or use it in a context where this is not needed. Or even better, keep a list, or use a more suitable data type.

The [getter function](https://docs.soliditylang.org/en/v0.8.17/contracts.html#getter-functions) created by the `public` keyword is more complex in the case of a mapping. It looks like the following:

```solidity
function balances(address _account) external view returns (uint256) {
    return balances[_account];
}
```

You can use this function to query the balance of a single account.

The line `event Sent(address from, address to, uint256 amount);` declares an [“event”](https://solidity.readthedocs.io/en/v0.6.3/contracts.html#events), which is emitted in the last line of the function `send`. Viction clients such as web applications can listen for these events emitted on the blockchain without much cost. As soon as it is emitted, the listener receives the arguments `from`, `to` and `amount`, which makes it possible to track transactions.

To listen for this event, you could use the following JavaScript code, which uses [web3.js](https://github.com/ethereum/web3.js/) to create the `Coin` contract object, and any user interface calls the automatically generated `balances` function from above:

```javascript
Coin.Sent().watch({}, '', function(error, result) {
    if (!error) {
        console.log("Coin transfer: " + result.args.amount +
            " coins were sent from " + result.args.from +
            " to " + result.args.to + ".");
        console.log("Balances now:\n" +
            "Sender: " + Coin.balances.call(result.args.from) +
            "Receiver: " + Coin.balances.call(result.args.to));
    }
})
```

The [constructor](https://docs.soliditylang.org/en/v0.8.17/contracts.html#constructor) is a special function run during the creation of the contract and cannot be called afterwards. In this case, it permanently stores the address of the person creating the contract. The `msg` variable (together with `tx` and `block`) is a [special global variable](https://docs.soliditylang.org/en/v0.8.17/units-and-global-variables.html#special-variables-functions) that contains properties which allow access to the blockchain. `msg.sender` is always the address where the current (external) function call came from.

The functions that make up the contract, and that users and contracts can call are `mint` and `send`.

The `mint` function sends an amount of newly created coins to another address. The [require](https://docs.soliditylang.org/en/v0.8.17/control-structures.html#assert-and-require) function call defines conditions that reverts all changes if not met. In this example, `require(msg.sender == minter);` ensures that only the creator of the contract can call `mint`, and `require(amount < 1e60);` ensures a maximum amount of tokens. This ensures that there are no overflow errors in the future.

The `send` function can be used by anyone (who already has some of these coins) to send coins to anyone else. If the sender does not have enough coins to send, the `require` call fails and provides the sender with an appropriate error message string.


# Solidity by Example

### Voting

The following contract showcases a lot of Solidity’s features. It implements a voting contract. Of course, the main problems of electronic voting is how to assign voting rights to the correct persons and how to prevent manipulation. We will not solve all problems here, but at least we will show how delegated voting can be done so that vote counting is **automatic and completely transparent** at the same time.

The idea is to create one contract per ballot, providing a short name for each option. Then the creator of the contract who serves as chairperson will give the right to vote to each address individually.

The persons behind the addresses can then choose to either vote themselves or to delegate their vote to a person they trust.

At the end of the voting time, `winningProposal()` will return the proposal with the largest number of votes.

```solidity
pragma solidity 0.8.17;

/// @title Voting with delegation.
contract Ballot {
    // This declares a new complex type which will
    // be used for variables later.
    // It will represent a single voter.
    struct Voter {
        uint weight; // weight is accumulated by delegation
        bool voted;  // if true, that person already voted
        address delegate; // person delegated to
        uint vote;   // index of the voted proposal
    }

    // This is a type for a single proposal.
    struct Proposal {
        bytes32 name;   // short name (up to 32 bytes)
        uint voteCount; // number of accumulated votes
    }

    address public chairperson;

    // This declares a state variable that
    // stores a `Voter` struct for each possible address.
    mapping(address => Voter) public voters;

    // A dynamically-sized array of `Proposal` structs.
    Proposal[] public proposals;

    /// Create a new ballot to choose one of `proposalNames`.
    constructor(bytes32[] memory proposalNames) public {
        chairperson = msg.sender;
        voters[chairperson].weight = 1;

        // For each of the provided proposal names,
        // create a new proposal object and add it
        // to the end of the array.
        for (uint i = 0; i < proposalNames.length; i++) {
            // `Proposal({...})` creates a temporary
            // Proposal object and `proposals.push(...)`
            // appends it to the end of `proposals`.
            proposals.push(Proposal({
                name: proposalNames[i],
                voteCount: 0
            }));
        }
    }

    // Give `voter` the right to vote on this ballot.
    // May only be called by `chairperson`.
    function giveRightToVote(address voter) public {
        // If the first argument of `require` evaluates
        // to `false`, execution terminates and all
        // changes to the state and to VIC balances
        // are reverted.
        // This used to consume all gas in old EVM versions, but
        // not anymore.
        // It is often a good idea to use `require` to check if
        // functions are called correctly.
        // As a second argument, you can also provide an
        // explanation about what went wrong.
        require(
            msg.sender == chairperson,
            "Only chairperson can give right to vote."
        );
        require(
            !voters[voter].voted,
            "The voter already voted."
        );
        require(voters[voter].weight == 0);
        voters[voter].weight = 1;
    }

    /// Delegate your vote to the voter `to`.
    function delegate(address to) public {
        // assigns reference
        Voter storage sender = voters[msg.sender];
        require(!sender.voted, "You already voted.");

        require(to != msg.sender, "Self-delegation is disallowed.");

        // Forward the delegation as long as
        // `to` also delegated.
        // In general, such loops are very dangerous,
        // because if they run too long, they might
        // need more gas than is available in a block.
        // In this case, the delegation will not be executed,
        // but in other situations, such loops might
        // cause a contract to get "stuck" completely.
        while (voters[to].delegate != address(0)) {
            to = voters[to].delegate;

            // We found a loop in the delegation, not allowed.
            require(to != msg.sender, "Found loop in delegation.");
        }

        // Since `sender` is a reference, this
        // modifies `voters[msg.sender].voted`
        sender.voted = true;
        sender.delegate = to;
        Voter storage delegate_ = voters[to];
        if (delegate_.voted) {
            // If the delegate already voted,
            // directly add to the number of votes
            proposals[delegate_.vote].voteCount += sender.weight;
        } else {
            // If the delegate did not vote yet,
            // add to her weight.
            delegate_.weight += sender.weight;
        }
    }

    /// Give your vote (including votes delegated to you)
    /// to proposal `proposals[proposal].name`.
    function vote(uint proposal) public {
        Voter storage sender = voters[msg.sender];
        require(sender.weight != 0, "Has no right to vote");
        require(!sender.voted, "Already voted.");
        sender.voted = true;
        sender.vote = proposal;

        // If `proposal` is out of the range of the array,
        // this will throw automatically and revert all
        // changes.
        proposals[proposal].voteCount += sender.weight;
    }

    /// @dev Computes the winning proposal taking all
    /// previous votes into account.
    function winningProposal() public view
            returns (uint winningProposal_)
    {
        uint winningVoteCount = 0;
        for (uint p = 0; p < proposals.length; p++) {
            if (proposals[p].voteCount > winningVoteCount) {
                winningVoteCount = proposals[p].voteCount;
                winningProposal_ = p;
            }
        }
    }

    // Calls winningProposal() function to get the index
    // of the winner contained in the proposals array and then
    // returns the name of the winner
    function winnerName() public view
            returns (bytes32 winnerName_)
    {
        winnerName_ = proposals[winningProposal()].name;
    }
}
```

#### Possible Improvements

Currently, many transactions are needed to assign the rights to vote to all participants. Can you think of a better way?

### Blind Auction

In this section, we will show how easy it is to create a completely blind auction contract on Viction network. We will start with an open auction where everyone can see the bids that are made and then extend this contract into a blind auction where it is not possible to see the actual bid until the bidding period ends.

#### Simple Open Auction

The general idea of the following simple auction contract is that everyone can send their bids during a bidding period. The bids already include sending money / VIC in order to bind the bidders to their bid. If the highest bid is raised, the previously highest bidder gets their money back. After the end of the bidding period, the contract has to be called manually for the beneficiary to receive their money - contracts cannot activate themselves.

```solidity
pragma solidity 0.8.17;

contract SimpleAuction {
    // Parameters of the auction. Times are either
    // absolute unix timestamps (seconds since 1970-01-01)
    // or time periods in seconds.
    address payable public beneficiary;
    uint public auctionEndTime;

    // Current state of the auction.
    address public highestBidder;
    uint public highestBid;

    // Allowed withdrawals of previous bids
    mapping(address => uint) pendingReturns;

    // Set to true at the end, disallows any change.
    // By default initialized to `false`.
    bool ended;

    // Events that will be emitted on changes.
    event HighestBidIncreased(address bidder, uint amount);
    event AuctionEnded(address winner, uint amount);

    // The following is a so-called natspec comment,
    // recognizable by the three slashes.
    // It will be shown when the user is asked to
    // confirm a transaction.

    /// Create a simple auction with `_biddingTime`
    /// seconds bidding time on behalf of the
    /// beneficiary address `_beneficiary`.
    constructor(
        uint _biddingTime,
        address payable _beneficiary
    ) public {
        beneficiary = _beneficiary;
        auctionEndTime = now + _biddingTime;
    }

    /// Bid on the auction with the value sent
    /// together with this transaction.
    /// The value will only be refunded if the
    /// auction is not won.
    function bid() public payable {
        // No arguments are necessary, all
        // information is already part of
        // the transaction. The keyword payable
        // is required for the function to
        // be able to receive VIC.

        // Revert the call if the bidding
        // period is over.
        require(
            now <= auctionEndTime,
            "Auction already ended."
        );

        // If the bid is not higher, send the
        // money back (the failing require
        // will revert all changes in this
        // function execution including
        // it having received the money).
        require(
            msg.value > highestBid,
            "There already is a higher bid."
        );

        if (highestBid != 0) {
            // Sending back the money by simply using
            // highestBidder.send(highestBid) is a security risk
            // because it could execute an untrusted contract.
            // It is always safer to let the recipients
            // withdraw their money themselves.
            pendingReturns[highestBidder] += highestBid;
        }
        highestBidder = msg.sender;
        highestBid = msg.value;
        emit HighestBidIncreased(msg.sender, msg.value);
    }

    /// Withdraw a bid that was overbid.
    function withdraw() public returns (bool) {
        uint amount = pendingReturns[msg.sender];
        if (amount > 0) {
            // It is important to set this to zero because the recipient
            // can call this function again as part of the receiving call
            // before `send` returns.
            pendingReturns[msg.sender] = 0;

            if (!msg.sender.send(amount)) {
                // No need to call throw here, just reset the amount owing
                pendingReturns[msg.sender] = amount;
                return false;
            }
        }
        return true;
    }

    /// End the auction and send the highest bid
    /// to the beneficiary.
    function auctionEnd() public {
        // It is a good guideline to structure functions that interact
        // with other contracts (i.e. they call functions or send VIC)
        // into three phases:
        // 1. checking conditions
        // 2. performing actions (potentially changing conditions)
        // 3. interacting with other contracts
        // If these phases are mixed up, the other contract could call
        // back into the current contract and modify the state or cause
        // effects (VIC payout) to be performed multiple times.
        // If functions called internally include interaction with external
        // contracts, they also have to be considered interaction with
        // external contracts.

        // 1. Conditions
        require(now >= auctionEndTime, "Auction not yet ended.");
        require(!ended, "auctionEnd has already been called.");

        // 2. Effects
        ended = true;
        emit AuctionEnded(highestBidder, highestBid);

        // 3. Interaction
        beneficiary.transfer(highestBid);
    }
}
```

#### Blind Auction

The previous open auction is extended to a blind auction in the following. The advantage of a blind auction is that there is no time pressure towards the end of the bidding period. Creating a blind auction on a transparent computing platform might sound like a contradiction, but cryptography comes to the rescue.

During the **bidding period**, a bidder does not actually send their bid, but only a hashed version of it. Since it is currently considered practically impossible to find two (sufficiently long) values whose hash values are equal, the bidder commits to the bid by that. After the end of the bidding period, the bidders have to reveal their bids: They send their values unencrypted and the contract checks that the hash value is the same as the one provided during the bidding period.

Another challenge is how to make the auction **binding and blind** at the same time: The only way to prevent the bidder from just not sending the money after they won the auction is to make them send it together with the bid. Since value transfers cannot be blinded in Viction, anyone can see the value.

The following contract solves this problem by accepting any value that is larger than the highest bid. Since this can of course only be checked during the reveal phase, some bids might be **invalid**, and this is on purpose (it even provides an explicit flag to place invalid bids with high value transfers): Bidders can confuse competition by placing several high or low invalid bids.

```solidity
pragma solidity 0.8.17;

contract BlindAuction {
    struct Bid {
        bytes32 blindedBid;
        uint deposit;
    }

    address payable public beneficiary;
    uint public biddingEnd;
    uint public revealEnd;
    bool public ended;

    mapping(address => Bid[]) public bids;

    address public highestBidder;
    uint public highestBid;

    // Allowed withdrawals of previous bids
    mapping(address => uint) pendingReturns;

    event AuctionEnded(address winner, uint highestBid);

    /// Modifiers are a convenient way to validate inputs to
    /// functions. `onlyBefore` is applied to `bid` below:
    /// The new function body is the modifier's body where
    /// `_` is replaced by the old function body.
    modifier onlyBefore(uint _time) { require(block.timestamp < _time); _; }
    modifier onlyAfter(uint _time) { require(block.timestamp > _time); _; }

    constructor(
        uint _biddingTime,
        uint _revealTime,
        address payable _beneficiary
    ) public {
        beneficiary = _beneficiary;
        biddingEnd = block.timestamp + _biddingTime;
        revealEnd = biddingEnd + _revealTime;
    }

    /// Place a blinded bid with `_blindedBid` =
    /// keccak256(abi.encodePacked(value, fake, secret)).
    /// The sent VIC is only refunded if the bid is correctly
    /// revealed in the revealing phase. The bid is valid if the
    /// VIC sent together with the bid is at least "value" and
    /// "fake" is not true. Setting "fake" to true and sending
    /// not the exact amount are ways to hide the real bid but
    /// still make the required deposit. The same address can
    /// place multiple bids.
    function bid(bytes32 _blindedBid)
        public
        payable
        onlyBefore(biddingEnd)
    {
        bids[msg.sender].push(Bid({
            blindedBid: _blindedBid,
            deposit: msg.value
        }));
    }

    /// Reveal your blinded bids. You will get a refund for all
    /// correctly blinded invalid bids and for all bids except for
    /// the totally highest.
    function reveal(
        uint[] memory _values,
        bool[] memory _fake,
        bytes32[] memory _secret
    )
        public
        onlyAfter(biddingEnd)
        onlyBefore(revealEnd)
    {
        uint length = bids[msg.sender].length;
        require(_values.length == length);
        require(_fake.length == length);
        require(_secret.length == length);

        uint refund;
        for (uint i = 0; i < length; i++) {
            Bid storage bidToCheck = bids[msg.sender][i];
            (uint value, bool fake, bytes32 secret) =
                    (_values[i], _fake[i], _secret[i]);
            if (bidToCheck.blindedBid != keccak256(abi.encodePacked(value, fake, secret))) {
                // Bid was not actually revealed.
                // Do not refund deposit.
                continue;
            }
            refund += bidToCheck.deposit;
            if (!fake && bidToCheck.deposit >= value) {
                if (placeBid(msg.sender, value))
                    refund -= value;
            }
            // Make it impossible for the sender to re-claim
            // the same deposit.
            bidToCheck.blindedBid = bytes32(0);
        }
        payable(msg.sender).transfer(refund);
    }

    /// Withdraw a bid that was overbid.
    function withdraw() public {
        uint amount = pendingReturns[msg.sender];
        if (amount > 0) {
            // It is important to set this to zero because the recipient
            // can call this function again as part of the receiving call
            // before `transfer` returns (see the remark above about
            // conditions -> effects -> interaction).
            pendingReturns[msg.sender] = 0;

            payable(msg.sender).transfer(amount);
        }
    }

    /// End the auction and send the highest bid
    /// to the beneficiary.
    function auctionEnd()
        public
        onlyAfter(revealEnd)
    {
        require(!ended);
        emit AuctionEnded(highestBidder, highestBid);
        ended = true;
        beneficiary.transfer(highestBid);
    }

    // This is an "internal" function which means that it
    // can only be called from the contract itself (or from
    // derived contracts).
    function placeBid(address bidder, uint value) internal
            returns (bool success)
    {
        if (value <= highestBid) {
            return false;
        }
        if (highestBidder != address(0)) {
            // Refund the previously highest bidder.
            pendingReturns[highestBidder] += highestBid;
        }
        highestBid = value;
        highestBidder = bidder;
        return true;
    }
}
```

### Safe Remote Purchase

Purchasing goods remotely currently requires multiple parties that need to trust each other. The simplest configuration involves a seller and a buyer. The buyer would like to receive an item from the seller and the seller would like to get money (or an equivalent) in return. The problematic part is the shipment here: There is no way to determine for sure that the item arrived at the buyer.

There are multiple ways to solve this problem, but all fall short in one or the other way. In the following example, both parties have to put twice the value of the item into the contract as escrow. As soon as this happened, the money will stay locked inside the contract until the buyer confirms that they received the item. After that, the buyer is returned the value (half of their deposit) and the seller gets three times the value (their deposit plus the value). The idea behind this is that both parties have an incentive to resolve the situation or otherwise their money is locked forever.

This contract of course does not solve the problem but gives an overview of how you can use state machine-like constructs inside a contract.

```solidity
pragma solidity 0.8.17;

contract Purchase {
    uint public value;
    address payable public seller;
    address payable public buyer;

    enum State { Created, Locked, Release, Inactive }
    // The state variable has a default value of the first member, `State.created`
    State public state;

    modifier condition(bool _condition) {
        require(_condition);
        _;
    }

    modifier onlyBuyer() {
        require(
            msg.sender == buyer,
            "Only buyer can call this."
        );
        _;
    }

    modifier onlySeller() {
        require(
            msg.sender == seller,
            "Only seller can call this."
        );
        _;
    }

    modifier inState(State _state) {
        require(
            state == _state,
            "Invalid state."
        );
        _;
    }

    event Aborted();
    event PurchaseConfirmed();
    event ItemReceived();
    event SellerRefunded();

    // Ensure that `msg.value` is an even number.
    // Division will truncate if it is an odd number.
    // Check via multiplication that it wasn't an odd number.
    constructor() public payable {
        seller = payable(msg.sender);
        value = msg.value / 2;
        require((2 * value) == msg.value, "Value has to be even.");
    }

    /// Abort the purchase and reclaim the VIC.
    /// Can only be called by the seller before
    /// the contract is locked.
    function abort()
        public
        onlySeller
        inState(State.Created)
    {
        emit Aborted();
        state = State.Inactive;
        // We use transfer here directly. It is
        // reentrancy-safe, because it is the
        // last call in this function and we
        // already changed the state.
        seller.transfer(address(this).balance);
    }

    /// Confirm the purchase as buyer.
    /// Transaction has to include `2 * value` VIC.
    /// The VIC will be locked until confirmReceived
    /// is called.
    function confirmPurchase()
        public
        inState(State.Created)
        condition(msg.value == (2 * value))
        payable
    {
        emit PurchaseConfirmed();
        buyer = payable(msg.sender);
        state = State.Locked;
    }

    /// Confirm that you (the buyer) received the item.
    /// This will release the locked VIC.
    function confirmReceived()
        public
        onlyBuyer
        inState(State.Locked)
    {
        emit ItemReceived();
        // It is important to change the state first because
        // otherwise, the contracts called using `send` below
        // can call in again here.
        state = State.Release;

        buyer.transfer(value);
    }

    /// This function refunds the seller, i.e.
    /// pays back the locked funds of the seller.
    function refundSeller()
        public
        onlySeller
        inState(State.Release)
    {
        emit SellerRefunded();
        // It is important to change the state first because
        // otherwise, the contracts called using `send` below
        // can call in again here.
        state = State.Inactive;

        seller.transfer(3 * value);
    }
}
```

### Micropayment Channel

In this section we will learn how to build an example implementation of a payment channel. It uses cryptographic signatures to make repeated transfers of VIC between the same parties secure, instantaneous, and without transaction fees. For the example, we need to understand how to sign and verify signatures, and setup the payment channel.

#### Creating and verifying signatures

Imagine Alice wants to send a quantity of VIC to Bob, e.g. Alice is the sender and the Bob is the recipient.

Alice only needs to send cryptographically signed messages off-chain (e.g. via email) to Bob and it is similar to writing checks.

Alice and Bob use signatures to authorise transactions, which is possible with smart contracts on Viction. Alice will build a simple smart contract that lets her transmit VIC, but instead of calling a function herself to initiate a payment, she will let Bob do that, and therefore pay the transaction fee.

The contract will work as follows:

> 1. Alice deploys the `ReceiverPays` contract, attaching enough VIC to cover the payments that will be made.
> 2. Alice authorises a payment by signing a message with their private key.
> 3. Alice sends the cryptographically signed message to Bob. The message does not need to be kept secret (explained later), and the mechanism for sending it does not matter.
> 4. Bob claims their payment by presenting the signed message to the smart contract, it verifies the authenticity of the message and then releases the funds.

**Creating the signature**

Alice does not need to interact with the Viction network to sign the transaction, the process is completely offline. In this tutorial, we will sign messages in the browser using [web3.js](https://github.com/ethereum/web3.js) and [MetaMask](https://metamask.io/), using the method described in [EIP-712](https://github.com/ethereum/EIPs/pull/712), as it provides a number of other security benefits.

```javascript
/// Hashing first makes things easier
var hash = web3.utils.sha3("message to sign");
web3.eth.personal.sign(hash, web3.eth.defaultAccount, function () { console.log("Signed"); });
```

Note

The `web3.eth.personal.sign` prepends the length of the message to the signed data. Since we hash first, the message will always be exactly 32 bytes long, and thus this length prefix is always the same.

**What to Sign**

For a contract that fulfils payments, the signed message must include:

> 1. The recipient’s address.
> 2. The amount to be transferred.
> 3. Protection against replay attacks.

A replay attack is when a signed message is reused to claim authorization for a second action. To avoid replay attacks we use the same as in Viction transactions themselves, a so-called nonce, which is the number of transactions sent by an account. The smart contract checks if a nonce is used multiple times.

Another type of replay attack can occur when the owner deploys a `ReceiverPays` smart contract, makes some payments, and then destroys the contract. Later, they decide to deploy the `RecipientPays` smart contract again, but the new contract does not know the nonces used in the previous deployment, so the attacker can use the old messages again.

Alice can protect against this attack by including the contract’s address in the message, and only messages containing the contract’s address itself will be accepted. You can find an example of this in the first two lines of the `claimPayment()` function of the full contract at the end of this section.

**Packing arguments**

Now that we have identified what information to include in the signed message, we are ready to put the message together, hash it, and sign it. For simplicity, we concatenate the data. The [ethereumjs-abi](https://github.com/ethereumjs/ethereumjs-abi) library provides a function called `soliditySHA3` that mimics the behaviour of Solidity’s `keccak256` function applied to arguments encoded using `abi.encodePacked`. Here is a JavaScript function that creates the proper signature for the `ReceiverPays` example:

```javascript
// recipient is the address that should be paid.
// amount, in wei, specifies how much VIC should be sent.
// nonce can be any unique number to prevent replay attacks
// contractAddress is used to prevent cross-contract replay attacks
function signPayment(recipient, amount, nonce, contractAddress, callback) {
    var hash = "0x" + abi.soliditySHA3(
        ["address", "uint256", "uint256", "address"],
        [recipient, amount, nonce, contractAddress]
    ).toString("hex");

    web3.eth.personal.sign(hash, web3.eth.defaultAccount, callback);
}
```

**Recovering the Message Signer in Solidity**

In general, ECDSA signatures consist of two parameters, `r` and `s`. Signatures in Viction include a third parameter called `v`, that you can use to verify which account’s private key was used to sign the message, and the transaction’s sender. Solidity provides a built-in function [ecrecover](https://solidity.readthedocs.io/en/v0.6.3/mathematical-and-cryptographic-functions) that accepts a message along with the `r`, `s` and `v` parameters and returns the address that was used to sign the message.

**Extracting the Signature Parameters**

Signatures produced by web3.js are the concatenation of `r`, `s` and `v`, so the first step is to split these parameters apart. You can do this on the client-side, but doing it inside the smart contract means you only need to send one signature parameter rather than three. Splitting apart a byte array into its constituent parts is a mess, so we use [inline assembly](https://solidity.readthedocs.io/en/v0.6.3/assembly) to do the job in the `splitSignature` function (the third function in the full contract at the end of this section).

**Computing the Message Hash**

The smart contract needs to know exactly what parameters were signed, and so it must recreate the message from the parameters and use that for signature verification. The functions `prefixed` and `recoverSigner` do this in the `claimPayment` function.

**The full contract**

```solidity
pragma solidity 0.8.17;

contract ReceiverPays {
    address owner = msg.sender;

    mapping(uint256 => bool) usedNonces;

    constructor() public payable {}

    function claimPayment(uint256 amount, uint256 nonce, bytes memory signature) public {
        require(!usedNonces[nonce]);
        usedNonces[nonce] = true;

        // this recreates the message that was signed on the client
        bytes32 message = prefixed(keccak256(abi.encodePacked(msg.sender, amount, nonce, this)));

        require(recoverSigner(message, signature) == owner);

        payable(msg.sender).transfer(amount);
    }

    /// destroy the contract and reclaim the leftover funds.
    function shutdown() public {
        require(msg.sender == owner);
        selfdestruct(payable(msg.sender));
    }

    /// signature methods.
    function splitSignature(bytes memory sig)
        internal
        pure
        returns (uint8 v, bytes32 r, bytes32 s)
    {
        require(sig.length == 65);

        assembly {
            // first 32 bytes, after the length prefix.
            r := mload(add(sig, 32))
            // second 32 bytes.
            s := mload(add(sig, 64))
            // final byte (first byte of the next 32 bytes).
            v := byte(0, mload(add(sig, 96)))
        }

        return (v, r, s);
    }

    function recoverSigner(bytes32 message, bytes memory sig)
        internal
        pure
        returns (address)
    {
        (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig);

        return ecrecover(message, v, r, s);
    }

    /// builds a prefixed hash to mimic the behavior of eth_sign.
    function prefixed(bytes32 hash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }
}
```

#### Writing a Simple Payment Channel

Alice now builds a simple but complete implementation of a payment channel. Payment channels use cryptographic signatures to make repeated transfers of VIC securely, instantaneously, and without transaction fees.

**What is a Payment Channel?**

Payment channels allow participants to make repeated transfers of VIC without using transactions. This means that you can avoid the delays and fees associated with transactions. We are going to explore a simple unidirectional payment channel between two parties (Alice and Bob). It involves three steps:

> 1. Alice funds a smart contract with VIC. This “opens” the payment channel.
> 2. Alice signs messages that specify how much of that VIC is owed to the recipient. This step is repeated for each payment.
> 3. Bob “closes” the payment channel, withdrawing their portion of the VIC and sending the remainder back to the sender.

Note

Only steps 1 and 3 require Viction transactions, step 2 means that the sender transmits a cryptographically signed message to the recipient via off chain methods (e.g. email). This means only two transactions are required to support any number of transfers.

Bob is guaranteed to receive their funds because the smart contract escrows the VIC and honours a valid signed message. The smart contract also enforces a timeout, so Alice is guaranteed to eventually recover their funds even if the recipient refuses to close the channel. It is up to the participants in a payment channel to decide how long to keep it open. For a short-lived transaction, such as paying an internet café for each minute of network access, the payment channel may be kept open for a limited duration. On the other hand, for a recurring payment, such as paying an employee an hourly wage, the payment channel may be kept open for several months or years.

**Opening the Payment Channel**

To open the payment channel, Alice deploys the smart contract, attaching the VIC to be escrowed and specifying the intended recipient and a maximum duration for the channel to exist. This is the function `SimplePaymentChannel` in the contract, at the end of this section.

**Making Payments**

Alice makes payments by sending signed messages to Bob. This step is performed entirely outside of the Viction network. Messages are cryptographically signed by the sender and then transmitted directly to the recipient.

Each message includes the following information:

> * The smart contract’s address, used to prevent cross-contract replay attacks.
> * The total amount of VIC that is owed the recipient so far.

A payment channel is closed just once, at the end of a series of transfers. Because of this, only one of the messages sent is redeemed. This is why each message specifies a cumulative total amount of VIC owed, rather than the amount of the individual micropayment. The recipient will naturally choose to redeem the most recent message because that is the one with the highest total. The nonce per-message is not needed anymore, because the smart contract only honours a single message. The address of the smart contract is still used to prevent a message intended for one payment channel from being used for a different channel.

Here is the modified JavaScript code to cryptographically sign a message from the previous section:

```solidity
function constructPaymentMessage(contractAddress, amount) {
    return abi.soliditySHA3(
        ["address", "uint256"],
        [contractAddress, amount]
    );
}

function signMessage(message, callback) {
    web3.eth.personal.sign(
        "0x" + message.toString("hex"),
        web3.eth.defaultAccount,
        callback
    );
}

// contractAddress is used to prevent cross-contract replay attacks.
// amount, in wei, specifies how much VIC should be sent.

function signPayment(contractAddress, amount, callback) {
    var message = constructPaymentMessage(contractAddress, amount);
    signMessage(message, callback);
}
```

**Closing the Payment Channel**

When Bob is ready to receive their funds, it is time to close the payment channel by calling a `close` function on the smart contract. Closing the channel pays the recipient the VIC they are owed and destroys the contract, sending any remaining VIC back to Alice. To close the channel, Bob needs to provide a message signed by Alice.

The smart contract must verify that the message contains a valid signature from the sender. The process for doing this verification is the same as the process the recipient uses. The Solidity functions `isValidSignature` and `recoverSigner` work just like their JavaScript counterparts in the previous section, with the latter function borrowed from the `ReceiverPays` contract.

Only the payment channel recipient can call the `close` function, who naturally passes the most recent payment message because that message carries the highest total owed. If the sender were allowed to call this function, they could provide a message with a lower amount and cheat the recipient out of what they are owed.

The function verifies the signed message matches the given parameters. If everything checks out, the recipient is sent their portion of the VIC, and the sender is sent the rest via a `selfdestruct`. You can see the `close` function in the full contract.

**Channel Expiration**

Bob can close the payment channel at any time, but if they fail to do so, Alice needs a way to recover their escrowed funds. An *expiration* time was set at the time of contract deployment. Once that time is reached, Alice can call `claimTimeout` to recover their funds. You can see the `claimTimeout` function in the full contract.

After this function is called, Bob can no longer receive any VIC, so it is important that Bob closes the channel before the expiration is reached.

**The full contract**

```solidity
pragma solidity 0.8.17;

contract SimplePaymentChannel {
    address payable public sender;      // The account sending payments.
    address payable public recipient;   // The account receiving the payments.
    uint256 public expiration;  // Timeout in case the recipient never closes.

    constructor (address payable _recipient, uint256 duration)
        public
        payable
    {
        sender = payable(msg.sender);
        recipient = _recipient;
        expiration = block.timestamp + duration;
    }

    /// the recipient can close the channel at any time by presenting a
    /// signed amount from the sender. the recipient will be sent that amount,
    /// and the remainder will go back to the sender
    function close(uint256 amount, bytes memory signature) public {
        require(msg.sender == recipient);
        require(isValidSignature(amount, signature));

        recipient.transfer(amount);
        selfdestruct(sender);
    }

    /// the sender can extend the expiration at any time
    function extend(uint256 newExpiration) public {
        require(msg.sender == sender);
        require(newExpiration > expiration);

        expiration = newExpiration;
    }

    /// if the timeout is reached without the recipient closing the channel,
    /// then the VIC is released back to the sender.
    function claimTimeout() public {
        require(block.timestamp >= expiration);
        selfdestruct(sender);
    }

    function isValidSignature(uint256 amount, bytes memory signature)
        internal
        view
        returns (bool)
    {
        bytes32 message = prefixed(keccak256(abi.encodePacked(this, amount)));

        // check that the signature is from the payment sender
        return recoverSigner(message, signature) == sender;
    }

    /// All functions below this are just taken from the chapter
    /// 'creating and verifying signatures' chapter.

    function splitSignature(bytes memory sig)
        internal
        pure
        returns (uint8 v, bytes32 r, bytes32 s)
    {
        require(sig.length == 65);

        assembly {
            // first 32 bytes, after the length prefix
            r := mload(add(sig, 32))
            // second 32 bytes
            s := mload(add(sig, 64))
            // final byte (first byte of the next 32 bytes)
            v := byte(0, mload(add(sig, 96)))
        }

        return (v, r, s);
    }

    function recoverSigner(bytes32 message, bytes memory sig)
        internal
        pure
        returns (address)
    {
        (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig);

        return ecrecover(message, v, r, s);
    }

    /// builds a prefixed hash to mimic the behavior of eth_sign.
    function prefixed(bytes32 hash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }
}
```

#### Note

The function `splitSignature` does not use all security checks. A real implementation should use a more rigorously tested library, such as openzepplin’s [version](https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/ECRecovery.sol) of this code.

**Verifying Payments**

Unlike in the previous section, messages in a payment channel aren’t redeemed right away. The recipient keeps track of the latest message and redeems it when it’s time to close the payment channel. This means it’s critical that the recipient perform their own verification of each message. Otherwise there is no guarantee that the recipient will be able to get paid in the end.

The recipient should verify each message using the following process:

> 1. Verify that the contact address in the message matches the payment channel.
> 2. Verify that the new total is the expected amount.
> 3. Verify that the new total does not exceed the amount of VIC escrowed.
> 4. Verify that the signature is valid and comes from the payment channel sender.

We’ll use the [ethereumjs-util](https://github.com/ethereumjs/ethereumjs-util) library to write this verification. The final step can be done a number of ways, and we use JavaScript. The following code borrows the constructMessage function from the signing **JavaScript code** above:

```solidity
function prefixed(hash) {
    return ethereumjs.ABI.soliditySHA3(
        ["string", "bytes32"],
        ["\x19Ethereum Signed Message:\n32", hash]
    );
}

function recoverSigner(message, signature) {
    var split = ethereumjs.Util.fromRpcSig(signature);
    var publicKey = ethereumjs.Util.ecrecover(message, split.v, split.r, split.s);
    var signer = ethereumjs.Util.pubToAddress(publicKey).toString("hex");
    return signer;
}

function isValidSignature(contractAddress, amount, signature, expectedSigner) {
    var message = prefixed(constructPaymentMessage(contractAddress, amount));
    var signer = recoverSigner(message, signature);
    return signer.toLowerCase() ==
        ethereumjs.Util.stripHexPrefix(expectedSigner).toLowerCase();
}
```

### Modular Contracts

A modular approach to building your contracts helps you reduce the complexity and improve the readability which will help to identify bugs and vulnerabilities during development and code review. If you specify and control the behaviour or each module in isolation, the interactions you have to consider are only those between the module specifications and not every other moving part of the contract. In the example below, the contract uses the `move` method of the `Balances` [library](https://solidity.readthedocs.io/en/v0.6.3/contracts.html#libraries) to check that balances sent between addresses match what you expect. In this way, the `Balances` library provides an isolated component that properly tracks balances of accounts. It is easy to verify that the `Balances` library never produces negative balances or overflows and the sum of all balances is an invariant across the lifetime of the contract.

```solidity
pragma solidity 0.8.17;

library Balances {
    function move(mapping(address => uint256) storage balances, address from, address to, uint amount) internal {
        require(balances[from] >= amount);
        require(balances[to] + amount >= balances[to]);
        balances[from] -= amount;
        balances[to] += amount;
    }
}

contract Token {
    mapping(address => uint256) balances;
    using Balances for *;
    mapping(address => mapping (address => uint256)) allowed;

    event Transfer(address from, address to, uint amount);
    event Approval(address owner, address spender, uint amount);

    function transfer(address to, uint amount) public returns (bool success) {
        balances.move(msg.sender, to, amount);
        emit Transfer(msg.sender, to, amount);
        return true;

    }

    function transferFrom(address from, address to, uint amount) public returns (bool success) {
        require(allowed[from][msg.sender] >= amount);
        allowed[from][msg.sender] -= amount;
        balances.move(from, to, amount);
        emit Transfer(from, to, amount);
        return true;
    }

    function approve(address spender, uint tokens) public returns (bool success) {
        require(allowed[msg.sender][spender] == 0, "");
        allowed[msg.sender][spender] = tokens;
        emit Approval(msg.sender, spender, tokens);
        return true;
    }

    function balanceOf(address tokenOwner) public view returns (uint balance) {
        return balances[tokenOwner];
    }
}
```


# Standards & Specification

In this guide, we take a look at different token standards on the Viction platform.

## **Overview**

In every blockchain ecosystem the token functions as the central element of a new type of economy. A token standard defines a set of rules that governs its issuance and use.

You may be familiar with ERC (Ethereum Request for Comments), which is a technical standard used for smart contracts on the Ethereum. This terminology is the origin of TRC tokens - the equivalent of ERC on Viction.

### **Fungible and Non-fungible token**

There are two token standards on Viction so far: VRC25 and VRC725. These token standards can be divided into two different categories: fungible and non-fungible tokens. Fungible tokens are all equal and divisible, non-fungible tokens (NFTs) are all distinct and non-divisible.

Fungible tokens are interchangeable and can be divided into smaller token units like VIC. The fungible token standard VRC25 as digital assets used to offer access to products and/or services on a platform. Non-fungible tokens of the type VRC725 are those that represent a unique asset, like a certificate or a collectible in-game item. The table below compares the differences between three types of token standards on Viction.

|                                                 | **VRC25**                | **VRC725**        |
| ----------------------------------------------- | ------------------------ | ----------------- |
| **Divisibility**                                | **Divisible**            | **Non-Divisible** |
| **Technical requirements for Dapp integration** | **Moderate**             | **Moderate**      |
| **Technical requirements for exchange listing** | **Moderate**             | **N/A**           |
| **Transaction Fee**                             | **In Transaction Token** | **In VIC**        |

### **VRC25 - Gas-less transaction experience**

VRC25 is an token standard similar to ERC20 plus the ability to let token holders to pay transaction fee using the token itself. Without having store VIC inside their wallet, user can still transfer the token or delegate it to someone. This will create a better experience for non-web3 user when using the ecosystem.

VRC25 also have an expanded use to enable any smart-contract to have transaction fee sponsor for users of their contract.

### **VRC725- Non-fungible token**

Non-fungible tokens (NFTs) are all distinct and special. Every token is rare, with unique characteristics, its own metadata and special attributes. Most of the time when people think about NFT, they refer to the successful CryptoKitties game as the standard for crypto-collectibles. However, there are many other applications for VRC725 tokens.

{% content-ref url="/pages/9hu558dVSfskslA5wwFV" %}
[VRC25 Specification](/smart-contract-development/standards-and-specification/vrc25-specification)
{% endcontent-ref %}

{% content-ref url="/pages/EJezf2WYsIDGgggCb3pb" %}
[VRC725 Specification](/smart-contract-development/standards-and-specification/vrc725-specification)
{% endcontent-ref %}


# VRC25 Specification

VRC25 is the official standard for fungible tokens in Viction ecosystem.

### Abstract <a href="#abstract" id="abstract"></a>

The following standard allows for the implementation of a standard API for tokens within smart contracts. This standard provides basic functionality to transfer tokens, as well as allow tokens to be approved so they can be spent by another on-chain third party. This standard also defines how fee should be managed to prevent abuse of the feature.

### Motivation <a href="#motivation" id="motivation"></a>

For EVM-based blockchain, ERC20 has became the standard for fungible tokens. This standard works perfectly and had been proven for a long time. However, due to the way smart-contract works in blockchain, it's somewhat difficult for new users to understand, especially web2 users.

VRC25 is developed in effort to simplify the way a token works by eliminate the need of gas when using the token. It means that users won't need to keep native token when they transfer, approve or any other actions available on the token. Instead the fee for the network can be paid by the token itself.

### Specification <a href="#specification" id="specification"></a>

```solidity
interface IVRC25 {
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
    event Fee(address indexed from, address indexed to, address indexed issuer, uint256 value);

    function decimals() external view returns (uint8);
    function totalSupply() external view returns (uint256);
    function balanceOf(address owner) external view returns (uint256);
    function issuer() external view returns (address);
    function allowance(address owner, address spender) external view returns (uint256);
    function estimateFee(uint256 value) external view returns (uint256);
    function transfer(address recipient, uint256 value) external returns (bool);
    function approve(address spender, uint256 value) external returns (bool);
    function transferFrom(address from, address to, uint256 value) external  returns (bool);
}
```

Source: [IVRC25.sol](https://github.com/BuildOnViction/trc25/blob/main/contracts/interfaces/IVRC25.sol)

```solidity
interface IVRC25Permit {
    function nonces(address owner) external view returns (uint256);
    function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
}
```

Source: [IVRC25Permit.sol](https://github.com/BuildOnViction/vrc25/blob/main/contracts/interfaces/IVRC25Permit.sol)

{% hint style="info" %}
For protocol contract, IVRC25 is enough.

For token contract, IVRC25 and IVRC25Permit must be satisfied to be fully compatible with gas-less protocol on Viction.
{% endhint %}

#### Methods <a href="#trc25-api-specification" id="trc25-api-specification"></a>

* `decimals`: Return the decimals of the token.

```solidity
function decimals() external view returns (uint8);
```

* `totalSupply`: Returns the token total supply.

```solidity
function totalSupply() external view returns (uint256);
```

* `balanceOf`: Returns the account balance of another account with address `owner`.

```solidity
function balanceOf(address owner) external view returns (uint256);
```

* `allowance`

```solidity
function allowance(address owner, address spender) external view returns (uint256);
```

Returns the amount which `spender` is still allowed to withdraw from `owner`.

* `issuer`: Returns the address of the token issuer.

```solidity
function issuer() external view returns (address);
```

The method returns the address of the token issuer. This is to ensure that only the issuer has the right to decide in regard to paying fees of token-holder transactions to the token contract in terms of the token itself. The method is to verify that no one else is able to change the token contract, except the issuer.

* `estimateFee`: Calculate the transaction fee in terms of the token that the transaction makers will have to pay. Transaction fee will be paid to the issuer of the VRC25 token contract.

```solidity
function estimateFee(uint256 value) external view returns (uint256);
```

Ideally, the function will return the transaction fee based on the value (the number of tokens) that the transaction maker wants to transfer. Transaction fee for `allowance` the function will be estimated if the input parameter `value = 0`. The way fees are computed is not standardized. Token issuers can fully customize the implementation of the function.

This function will also be called by user wallets to evaluate fees the user must pay.

* `transfer`: Transfers `value` amount of tokens to address `recipient`, and MUST fire the `Transfer` and `Fee` event.

```solidity
function transfer(address recipient, uint256 value) public returns (bool success)
```

The function will call `estimateFee` function to compute the transaction fee. The function SHOULD throw if the message caller’s account balance does not have enough tokens to spend and to pay transaction fees. Once succeeded, the token balance of the sender should be reduced by `value` plus the computed transaction fee, the balance of `recipient` should be increasing `value`, while the balance of the token issuer should be increased by the computed transaction fee.

* `approve`

```solidity
function approve(address spender, uint256 value) external returns (bool);
```

Allows `spender` to withdraw from your account multiple times, up to the `value` amount. If this function is called again it overwrites the current allowance with `value`. This function also calls `estimateFee` with input parameter 0 in order to compute the transaction fee in terms of tokens that the transaction sender must pay to the token issuer.

* `transferFrom`

```solidity
function transferFrom(address from, address to, uint256 value) external returns (bool);
```

Transfers `value` amount of tokens from the address `from` to the address `to`. The function must fire the `Transfer` and `Fee` events.

* nonces

```solidity
function nonces(address owner) external view returns (uint256);
```

Returns unused nonce for specified `owner`. Signature with nonce different that this value is invalid thus cannot be used.

* permit

```solidity
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
```

This is the same as `approve` function with the different that caller is not necessary the `owner`. Instead, the caller must provide a valid signature signed by the `owner`.

#### Events <a href="#trc25-event-specification" id="trc25-event-specification"></a>

* `Transfer`

```solidity
event Transfer(address indexed from, address indexed to, uint256 amount);
```

This event MUST be emitted when tokens are transferred in functions `transfer` and `transferFrom`.

* `Approval`

```solidity
event Approval(address indexed owner, address indexed spender, uint256 amount);
```

This event MUST be emitted on any successful call to `approve` function.

* `Fee`

```solidity
event Fee(address indexed from, address indexed to, address indexed issuer, uint256 amount);
```

This event MUST be emitted when tokens are transferred in functions `transfer` and `transferFrom` in order for clients/DApp/third-party wallets to notify their users about the paid transaction fee in terms of tokens.

### Requirement <a href="#requirement" id="requirement"></a>

For a contract to meet VRC25 requirements, it must satisfy the following conditions:

* The contract should be VRC25Upgradable contract in order to use through proxy.
* Implement `IVRC25` interface in the specification.
* Have 3 first storage slots in the contracts as follow:

```solidity
mapping (address => uint256) private _balances;
uint256 private _minFee;
address private _owner;
```

* Implement `Permit` extension, as defined in EIP-2612. Permit acts as a fallback for any gas-less protocol to support your token properly, in the case that your token isn't registered for \[VIC ZeroGas]\(../integration/VIC ZeroGas-integration.md).

```solidity
interface IVRC25Permit {
    function nonces(address owner) external view returns (uint256);
    function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
}
```

### Implementation <a href="#implementation" id="implementation"></a>

To implement the VRC25 standard, the following fields must be put at the beginning of the smart contract.

```solidity
mapping (address => uint256) private _balances;
uint256 private _minFee;
address private _owner;
```

This standard will need some basic information to track and

* `_balances`: record the balance of each token holder
* `_minFee`: the minimum fee in terms of tokens that the transaction sender must pay. Ideally, minFee will be paid when the `approve` function is called or when the transaction fails.
* `_owner`: the address of the token issuer who will receive transaction fees from token holders in terms of the token, but will pay transaction fees to masternodes by means of VIC.

The implementation also defines some additional functions as follows:

* `issuer`: Returns the address of the issuer of the token.
* `minFee`: Returns the minimum fee for any transaction.

```solidity
/**
 * @title Base VRC25 implementation
 * @notice VRC25 implementation for opt-in to gas sponsor program. This replace Ownable from OpenZeppelin as well.
 */
abstract contract VRC25 is IVRC25, IERC165 {
    using Address for address;
    using SafeMath for uint256;

    // The order of _balances, _minFeem, _issuer must not be changed to pass validation of gas sponsor application
    mapping (address => uint256) private _balances;
    uint256 private _minFee;
    address private _owner;
    address private _newOwner;

    mapping (address => mapping (address => uint256)) private _allowances;

    string private _name;
    string private _symbol;
    uint8 private _decimals;
    uint256 private _totalSupply;

    event FeeUpdated(uint256 fee);
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor(string memory name, string memory symbol, uint8 decimals_) internal {
        _name = name;
        _symbol = symbol;
        _decimals = decimals_;
        _owner = msg.sender;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(_owner == msg.sender, "VRC25: caller is not the owner");
        _;
    }

    /**
     * @notice Name of token
     */
    function name() public view returns (string memory) {
        return _name;
    }

    /**
     * @notice Symbol of token
     */
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /**
     * @notice Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     */
    function decimals() public view override returns (uint8) {
        return _decimals;
    }

    /**
     * @notice Returns the amount of tokens in existence.
     */
    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @notice Returns the amount of tokens owned by `account`.
     * @param owner The address to query the balance of.
     * @return An uint256 representing the amount owned by the passed address.
     */
    function balanceOf(address owner) public view override returns (uint256) {
        return _balances[owner];
    }

    /**
     * @notice Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner,address spender) public view override returns (uint256){
        return _allowances[owner][spender];
    }

    /**
     * @notice Owner of the token
     */
    function owner() public view returns (address) {
        return _owner;
    }

    /**
     * @notice Owner of the token
     */
    function issuer() public view override returns (address) {
        return _owner;
    }

    /**
     * @dev The amount fee that will be lost when transferring.
     */
    function minFee() public view returns (uint256) {
        return _minFee;
    }

    /**
     * @notice Calculate fee needed to transfer `amount` of tokens.
     */
    function estimateFee(uint256 value) public view override returns (uint256) {
        if (address(msg.sender).isContract()) {
            return 0;
        } else {
            return _estimateFee(value);
        }
    }

    /**
     * @notice Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external override returns (bool) {
        uint256 fee = estimateFee(amount);
        _transfer(msg.sender, recipient, amount);
        _chargeFeeFrom(msg.sender, recipient, fee);
        return true;
    }

    /**
     * @notice Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external override returns (bool) {
        uint256 fee = estimateFee(0);
        _approve(msg.sender, spender, amount);
        _chargeFeeFrom(msg.sender, address(this), fee);
        return true;
    }

    /**
     * @notice Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) {
        uint256 fee = estimateFee(amount);
        require(_allowances[sender][msg.sender] >= amount.add(fee), "VRC25: amount exeeds allowance");

        _allowances[sender][msg.sender] = _allowances[sender][msg.sender].sub(amount).sub(fee);
        _transfer(sender, recipient, amount);
        _chargeFeeFrom(sender, recipient, fee);
        return true;
    }

    /**
     * @notice Remove `amount` tokens owned by caller from circulation.
     */
    function burn(uint256 amount) external returns (bool) {
        uint256 fee = estimateFee(0);
        _burn(msg.sender, amount);
        _chargeFeeFrom(msg.sender, address(this), fee);
        return true;
    }

    /**
     * @dev Accept the ownership transfer. This is to make sure that the contract is
     * transferred to a working address
     *
     * Can only be called by the newly transfered owner.
     */
    function acceptOwnership() external {
        require(msg.sender == _newOwner, "VRC25: only new owner can accept ownership");
        address oldOwner = _owner;
        _owner = _newOwner;
        _newOwner = address(0);
        emit OwnershipTransferred(oldOwner, _owner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     *
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) external virtual onlyOwner {
        require(newOwner != address(0), "VRC25: new owner is the zero address");
        _newOwner = newOwner;
    }

    /**
     * @notice Set minimum fee for each transaction
     *
     * Can only be called by the current owner.
     */
    function setFee(uint256 fee) external virtual onlyOwner {
        _minFee = fee;
        emit FeeUpdated(fee);
    }

    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     */
    function supportsInterface(bytes4 interfaceId) public view override virtual returns (bool) {
        return interfaceId == type(IVRC25).interfaceId;
    }

    /**
     * @notice Calculate fee needed to transfer `amount` of tokens.
     */
    function _estimateFee(uint256 value) internal view virtual returns (uint256);

    /**
     * @dev Transfer token for a specified addresses
     * @param from The address to transfer from.
     * @param to The address to transfer to.
     * @param amount The amount to be transferred.
     */
    function _transfer(address from, address to, uint256 amount) internal {
        require(from != address(0), "VRC25: transfer from the zero address");
        require(to != address(0), "VRC25: transfer to the zero address");
        require(amount <= _balances[from], "VRC25: insuffient balance");
        _balances[from] = _balances[from].sub(amount);
        _balances[to] = _balances[to].add(amount);
        emit Transfer(from, to, amount);
    }

    /**
     * @dev Set allowance that spender can use from owner
     * @param owner The address that authroize the allowance
     * @param spender The address that can spend the allowance
     * @param amount The amount that can be allowed
     */
    function _approve(address owner, address spender, uint256 amount) internal {
        require(owner != address(0), "VRC25: approve from the zero address");
        require(spender != address(0), "VRC25: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Internal function to charge fee for gas sponsor function. Won't charge fee if caller is smart-contract because they are not sponsored gas.
     * NOTICE: this function is only a helper to transfer fee from an address different that msg.sender. Other validation should be handled outside of this function if necessary.
     * @param sender The address that will pay the fee
     * @param recipient The address that is destination of token transfer. If not token transfer should be address of contract
     * @param amount The amount token as fee
     */
    function _chargeFeeFrom(address sender, address recipient, uint256 amount) internal {
        if (address(msg.sender).isContract()) {
            return;
        }
        if(amount > 0) {
            _transfer(sender, _owner, amount);
            emit Fee(sender, recipient, _owner, amount);
        }
    }
    /**
     * @dev Internal function that mints an amount of the token and assigns it to
     * an account. This encapsulates the modification of balances such that the
     * proper events are emitted.
     * @param to The account that will receive the created tokens.
     * @param amount The amount that will be created.
     */
    function _mint(address to, uint256 amount) internal {
        require(to != address(0), "VRC25: mint to the zero address");
        _totalSupply = _totalSupply.add(amount);
        _balances[to] = _balances[to].add(amount);
        emit Transfer(address(0), to, amount);
    }

    /**
     * @dev Internal function that burns an amount of the token
     * This encapsulates the modification of balances such that the
     * proper events are emitted.
     * @param from The account that token amount will be deducted.
     * @param amount The amount that will be burned.
     */
    function _burn(address from, uint256 amount) internal {
        require(from != address(0), "VRC25: burn from the zero address");
        require(amount <= _balances[from], "VRC25: insuffient balance");
        _totalSupply = _totalSupply.sub(amount);
        _balances[from] = _balances[from].sub(amount);
        emit Transfer(from, address(0), amount);
    }
}
```

Source: [VRC25.sol](https://github.com/BuildOnViction/trc25/blob/main/contracts/VRC25.sol)

```solidity
/**
 * @title VRC25Permit
 * @notice Approval via signature for VRC25. Must be included for token contract.
 */
abstract contract VRC25Permit is VRC25, EIP712, IVRC25Permit {
    bytes32 private constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

    mapping(address => uint256) private _nonces;

    constructor() public EIP712("VRC25", "1") { }

    /**
     * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external override view returns (bytes32) {
        return _domainSeparatorV4();
    }

    /**
     * @dev Returns an the next unused nonce for an address.
     */
    function nonces(address owner) public view virtual override(IVRC25Permit) returns (uint256) {
        return _nonces[owner];
    }

    /**
     * @dev See {IERC20Permit-permit}.
     */
    function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external override {
        require(block.timestamp <= deadline, "VRC25: Permit expired");

        bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));
        bytes32 hash = _hashTypedDataV4(structHash);
        address signer = ECDSA.recover(hash, v, r, s);
        require(signer == owner, "VRC25: Invalid permit");

        uint256 fee = estimateFee(0);
        _approve(owner, spender, value);
        _chargeFeeFrom(owner, address(this), fee);
    }

    /**
     * @dev Consumes a nonce.
     *
     * Returns the current value and increments nonce.
     */
    function _useNonce(address owner) internal returns (uint256) {
        // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be
        // decremented or reset. This guarantees that the nonce never overflows.
        // It is important to do x++ and not ++x here.
        return _nonces[owner]++;
    }
}
```

Source: [VRC25Permit.sol](https://github.com/BuildOnViction/vrc25/blob/main/contracts/VRC25Permit.sol)

### Example <a href="#example" id="example"></a>

The following example demonstrates a token using the VRC25 standard with a custom fee.

The easiest way to implement VRC25 specification is to let first inheritance of your contract to be `VRC25` or `VRC25Permit`.

```solidity
contract SampleVRC25 is VRC25Permit {
    using Address for address;
    event Hello(address sender);

    constructor() public VRC25("Example Fungible Token", "EFT", 0) EIP712("VRC25Permit", "1") {
    }

    /**
     * @notice Calculate fee required for action related to this token
     * @param value Amount of fee
     */
    function _estimateFee(uint256 value) internal view override returns (uint256) {
        return value + minFee();
    }

    function sayHello() public {
        _chargeFeeFrom(msg.sender, address(0), estimateFee(0));

        emit Hello(msg.sender);
    }

    function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
        return interfaceId == type(IVRC25).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @notice Issues `amount` tokens to the designated `address`.
     *
     * Can only be called by the current owner.
     */
    function mint(address recipient, uint256 amount) external onlyOwner returns (bool) {
        _mint(recipient, amount);
        return true;
    }
}
```

Source: [SampleVRC25.sol](https://github.com/BuildOnViction/trc25/blob/main/contracts/tests/SampleVRC25.sol)

### Enable gas-less transaction

Once you have deployed a VRC25 compatible contract. You will also need to register for VIC ZeroGas to enable gas-less transaction for your contract. Please refer to [VIC ZeroGas](/developer-guide/integration/vic-zerogas-integration) page for more information.


# VRC725 Specification

VRC725 is the simplest form of Non-Fungible Token on Viction

VRC725 is the official standard for Non-fungible tokens in Viction ecosystem.

### **Abstract**

The following standard allows for the implementation of a standard API for NFTs within smart contracts. This standard provides basic functionality to track and transfer NFTs.

We considered use cases of NFTs being owned and transacted by individuals as well as consignment to third party brokers/wallets/auctioneers (“operators”). NFTs can represent ownership over digital or physical assets. We considered a diverse universe of assets, and we know you will dream up many more:

* Physical property — houses, unique artwork
* Virtual collectibles — unique pictures of kittens, collectible cards
* “Negative value” assets — loans, burdens and other responsibilities

In general, all houses are distinct and no two kittens are alike. NFTs are *distinguishable* and you must track the ownership of each one separately.

This standards also support gas-free protocol by enabling mechanism that those protocol can utilize while maintaince the security of the token itself.

### **Motivation**

A standard interface allows wallet/broker/auction applications to work with any NFT on Viction. We provide for simple VRC725 smart contracts as well as contracts that track an *arbitrarily large* number of NFTs. Additional applications are discussed below.

VRC725 can work both with VictionZ with some limitation, which you can consider, or without VictionZ. The permit extension required by VRC725 is suffient for any gas-less protocol to work with.

### **Specification**

VRC725 is based on ERC721. VRC725 includes IERC721Metadata extension to make it easier for use. Moreorver, it also includes two custom permit implementation inspired by [EIP-4494](https://eips.ethereum.org/EIPS/eip-4494) to support gas-free operation.

```solidity
interface IERC721 is IERC165 {
    event Transfer(address indexed from, address indexed to, uint indexed tokenId);
    event Approval(address indexed owner, address indexed approved, uint indexed tokenId);
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    function balanceOf(address owner) external view returns (uint balance);
    function getApproved(uint tokenId) external view returns (address operator);
    function isApprovedForAll(address owner, address operator) external view returns (bool);
    function ownerOf(uint tokenId) external view returns (address owner);
    function approve(address to, uint tokenId) external;
    function transferFrom(address from, address to, uint tokenId) external;
    function safeTransferFrom(address from, address to, uint tokenId) external;
    function safeTransferFrom(address from, address to, uint tokenId, bytes calldata data) external;
    function setApprovalForAll(address operator, bool _approved) external;
}
```

Source: [IERC721.sol](https://github.com/BuildOnViction/vrc725/blob/main/contracts/interfaces/IERC721.sol)

```solidity
interface IERC721Metadata is IERC721 {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function tokenURI(uint tokenId) external view returns (string memory);
}
```

Source: [IERC721Metadata.sol](https://github.com/BuildOnViction/vrc725/blob/main/contracts/interfaces/IERC721Metadata.sol)

```solidity
interface IERC4494 is IERC165 {
    function permit(address spender, uint256 tokenId, uint256 deadline, bytes memory sig) external;
    function nonces(uint256 tokenId) external view returns(uint256);
    function DOMAIN_SEPARATOR() external view returns(bytes32);
}
```

Source: [IERC4494.sol](https://github.com/BuildOnViction/vrc725/blob/main/contracts/interfaces/IERC4494.sol)

```solidity
interface IVRC725 is IERC721, IERC4494, IERC721Metadata {
    function permitForAll(address owner, address spender, uint256 deadline, bytes memory signature) external;
    function nonceByAddress(address owner) external view returns(uint256);
}
```

Source: [IVRC725.sol](https://github.com/BuildOnViction/vrc725/blob/main/contracts/interfaces/IVRC725.sol)

**Methods**

* `balanceOf`: Returns the number of tokens in `owner`'s account.

```solidity
function balanceOf(address owner) external view returns (uint balance);
```

* `getApproved`: Returns the account approved for `tokenId` token.

```solidity
function getApproved(uint tokenId) external view returns (address operator);
```

* `isApprovedForAll`: Returns if the `operator` is allowed to manage all of the assets of `owner`.

```solidity
function isApprovedForAll(address owner, address operator) external view returns (bool);
```

* `ownerOf`: Returns the owner of the `tokenId` token.

```solidity
function ownerOf(uint tokenId) external view returns (address owner);
```

* `approve`: Gives permission to `to` to transfer `tokenId` token to another account.

```solidity
function approve(address to, uint tokenId) external;
```

* `transferFrom`: Transfers `tokenId` token from `from` to `to`.

```solidity
function transferFrom(address from, address to, uint tokenId) external;
```

* `safeTransferFrom`: Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients are aware of the ERC721 protocol to prevent tokens from being forever locked.

```solidity
function safeTransferFrom(address from, address to, uint tokenId) external;
```

* `safeTransferFrom`: Safely transfers `tokenId` token from `from` to `to`.

```solidity
function safeTransferFrom(address from, address to, uint tokenId, bytes calldata data) external;
```

* `setApprovalForAll`: Approve or remove `operator` as an operator for the caller. Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.

```solidity
function setApprovalForAll(address operator, bool _approved) external;
```

* `name`: Returns the token collection name.

```solidity
function name() external view returns (string memory);
```

* `symbol`: Returns the token collection symbol.

```solidity
function symbol() external view returns (string memory);
```

* `tokenURI`: Returns the Uniform Resource Identifier (URI) for `tokenId` token.

```solidity
function tokenURI(uint tokenId) external view returns (string memory);
```

* `estimateFee`: Calculate fee needed to transfer `amount` of tokens.

```solidity
function estimateFee(uint256 value) public view returns (uint256) 
```

* `issuer`:Owner of the token

```solidity
function issuer() public view returns (address) 
```

* `nonces`: Returns the nonce of an NFT - useful for creating permits

```solidity
function nonces(uint256 tokenId) external view override returns(uint256)
```

* `isUsedNonce`: Is used nonce

```solidity
function isUsedNonce(address owner, uint256 nonce) external view returns(bool) 
```

* `minFee`: The amount fee that will be lost when transferring.

```solidity
function minFee() public view returns (uint256)
```

* `permit`: Approve for one `tokenId` by using pre-signed signature, allow other users or smart contract to perform the transfer without `owner` calling approve first.

```solidity
function permit(address spender, uint256 tokenId, uint256 deadline, bytes memory sig) external
```

* `permitForAll`: Approve for a `spender` by using pre-signed signature, allow other users or smart contract to perform the transfer without `owner` calling approve first.

```solidity
function permitForAll(address owner, address spender, uint256 nonce, uint256 deadline, bytes memory signature)
```

**Events**

* `Transfer`

```solidity
event Transfer(address indexed from, address indexed to, uint indexed tokenId);
```

Emitted when `tokenId` token is transferred from `from` to `to`. This event MUST be emitted when tokens are transferred in functions `transfer` ,`transferFrom` and `safeTransferFrom`.

* `Approval`

```solidity
event Approval(address indexed owner, address indexed approved, uint indexed tokenId);
```

Emitted when `owner` enables `approved` to manage the `tokenId` token. This event MUST be emitted on any successful call to `approve` function and `permit` function.

* `ApprovalForAll`

```solidity
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
```

Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.This event MUST be emitted on any successful call to `setApprovalForAll` function and `permitForAll` function.

### **Requirement**

For a contract to meet VRC725 requirements, it must satisfy the following conditions:

* Implement `IVRC725` which includes `IERC721`, `IERC721Metadata`.
* Must implement 2 functions: `permit` as defined in EIP- 4494 and its custom variant `permitForAll`.

```solidity
function permit(address spender, uint256 tokenId, uint256 deadline, bytes memory sig) external;
function permitForAll(address owner, address spender, uint256 nonce, uint256 deadline, bytes memory signature);
```

* Have 3 first storage slots in the contracts as follow, this is not required but necessary for integration with VictionZ.

```solidity
mapping (address => uint256) private _balances;
uint256 private _minFee;
address private _owner;
```

### **Implementation**

To implement VRC725, use can extend ERC721 contract from OpenZeppelin contract libraries or your existing NFT contract. The major differences are that `permit` and `permitForAll` functions are required, and the position in storage slots of `_balances`, `_minFee`, `_owner`.

Otherwise, you can inherit the [VRC725](https://github.com/BuildOnViction/vrc725/blob/main/contracts/VRC725.sol) from our repository.&#x20;

````solidity
/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
abstract contract VRC725 is ERC165, IVRC725 {
    using Address for address;
    using Strings for uint256;

    // Mapping owner address to token count
    // The order of _balances, _minFee, _issuer must not be changed to pass validation of gas sponsor application
    mapping (address => uint256) private _balances;
    uint256 private _minFee; // minFee must always be 0 to ensure that VictionZ will work properly in the case you apply for it
    address private _owner;
    address private _newOwner;

    bool isAlreadyInit;

    // EIP 712
    bytes32 private _HASHED_NAME;
    bytes32 private _HASHED_VERSION;
    bytes32 private constant _TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");

    // Permit type hash using for EIP712
    bytes32 public constant PERMIT_TYPEHASH =
        keccak256(
            'Permit(address spender,uint256 tokenId,uint256 nonce,uint256 deadline)'
        );

    // Permit for all type hash using for EIP712
    bytes32 public constant PERMIT_FOR_ALL_TYPEHASH =
        keccak256(
            'PermitForAll(address spender,uint256 nonce,uint256 deadline)'
        );

    mapping(uint256 => uint256) private _nonces;
    mapping(address => uint256) private _noncesByAddress;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    event Fee(address indexed from, address indexed to, address indexed issuer, uint256 value);
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Init function called by child contract
     */
    function __VRC725_init(string memory name_, string memory symbol_, address owner_) internal {
        require(!isAlreadyInit, "VRC725: Contract already init");
        __ERC721_init(name_, symbol_);
        __EIP712_init(name_, "1");

        _owner = owner_;
        isAlreadyInit = true;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(_owner == msg.sender, "VRC725: caller is not the owner");
        _;
    }

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    function __ERC721_init(string memory name_, string memory symbol_) private {
        _name = name_;
        _symbol = symbol_;

        _minFee = 0;
    }

    /**
     * @notice Owner of the token
     */
    function owner() public view returns (address) {
        return _owner;
    }

    /**
     * @notice Owner of the token
     */
    function issuer() public view returns (address) {
        return _owner;
    }

    /**
     * @dev The amount fee that will be lost when transferring.
     */
    function minFee() public view returns (uint256) {
        return _minFee;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            interfaceId == type(IERC4494).interfaceId ||
            interfaceId == type(IVRC725).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: address zero is not a valid owner");
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _ownerOf(tokenId);
        require(owner != address(0), "ERC721: invalid token ID");
        return owner;
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        _requireMinted(tokenId);

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overridden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC4494-permit}.
     */
    function permit(address spender, uint256 tokenId, uint256 deadline, bytes memory signature) external override {
        require(deadline >= block.timestamp, 'VRC725: Permit deadline expired');
        bytes32 digest = _getPermitDigest(spender, tokenId, _nonces[tokenId], deadline);

        (address recoverAddress,, ) = ECDSA.tryRecover(digest, signature);
        require(
            // if the recovered address is owner or approved on token id,
            recoverAddress != address(0)
                && _isApprovedOrOwner(recoverAddress, tokenId)
                // try to recover signature using SignatureChecker, which allows to recover signature made by contracts
                || SignatureChecker.isValidSignatureNow(ownerOf(tokenId), digest, signature)
            , "VRC725: Invalid permit signature"
        );

        _approve(spender, tokenId);
    }

    /**
     * @dev Permit for all
     */
    function permitForAll(address owner, address spender, uint256 deadline, bytes memory signature) external {
        require(deadline >= block.timestamp, 'VRC725: Permit deadline expired');
        bytes32 digest = _getPermitForAllDigest(spender, _noncesByAddress[owner], deadline);

        (address recoverAddress,, ) = ECDSA.tryRecover(digest, signature);
        require(
            // if the recovered address is owner,
            recoverAddress == owner || SignatureChecker.isValidSignatureNow(owner, digest, signature)
            , "VRC725: Invalid permit signature"
        );

        _setApprovalForAll(owner, spender, true);

        _noncesByAddress[owner]++;
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = VRC725.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            msg.sender == owner || isApprovedForAll(owner, msg.sender),
            "ERC721: approve caller is not token owner or approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        _requireMinted(tokenId);

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _setApprovalForAll(msg.sender, operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: caller is not token owner or approved");

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) public virtual override {
        require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: caller is not token owner or approved");
        _safeTransfer(from, to, tokenId, data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
     */
    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
        return _owners[tokenId];
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _ownerOf(tokenId) != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        address owner = VRC725.ownerOf(tokenId);
        return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal virtual {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId, 1);

        // Check that tokenId was not minted by `_beforeTokenTransfer` hook
        require(!_exists(tokenId), "ERC721: token already minted");

        unchecked {
            // Will not overflow unless all 2**256 token ids are minted to the same owner.
            // Given that tokens are minted one by one, it is impossible in practice that
            // this ever happens. Might change if we allow batch minting.
            // The ERC fails to describe this case.
            _balances[to] += 1;
        }

        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);

        _afterTokenTransfer(address(0), to, tokenId, 1);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     * This is an internal function that does not check if the sender is authorized to operate on the token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = VRC725.ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId, 1);

        // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
        owner = VRC725.ownerOf(tokenId);

        // Clear approvals
        delete _tokenApprovals[tokenId];

        unchecked {
            // Cannot overflow, as that would require more tokens to be burned/transferred
            // out than the owner initially received through minting and transferring in.
            _balances[owner] -= 1;
        }
        delete _owners[tokenId];

        emit Transfer(owner, address(0), tokenId);

        _afterTokenTransfer(owner, address(0), tokenId, 1);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        require(VRC725.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId, 1);

        // Check that tokenId was not transferred by `_beforeTokenTransfer` hook
        require(VRC725.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");

        // Clear approvals from the previous owner
        delete _tokenApprovals[tokenId];

        unchecked {
            // `_balances[from]` cannot overflow for the same reason as described in `_burn`:
            // `from`'s balance is the number of token held, which is at least one before the current
            // transfer.
            // `_balances[to]` could overflow in the conditions described in `_mint`. That would require
            // all 2**256 token ids to be minted, which in practice is impossible.
            _balances[from] -= 1;
            _balances[to] += 1;
        }
        _owners[tokenId] = to;

        // increment nonce using for permit
        _incrementNonce(tokenId);

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId, 1);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits an {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(VRC725.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits an {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Reverts if the `tokenId` has not been minted yet.
     */
    function _requireMinted(uint256 tokenId) internal view virtual {
        require(_exists(tokenId), "ERC721: invalid token ID");
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, data) returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    /// @solidity memory-safe-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
     * - When `from` is zero, the tokens will be minted for `to`.
     * - When `to` is zero, ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256, /* firstTokenId */
        uint256 batchSize
    ) internal virtual {
        if (batchSize > 1) {
            if (from != address(0)) {
                _balances[from] -= batchSize;
            }
            if (to != address(0)) {
                _balances[to] += batchSize;
            }
        }
    }

    /**
     * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
     * - When `from` is zero, the tokens were minted for `to`.
     * - When `to` is zero, ``from``'s tokens were burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual {}

    /**
     * @dev Builds the permit digest to sign
     * @param spender the address to approve
     * @param tokenId the index of the NFT to approve the spender on
     * @param nonce the nonce to make a permit for
     * @param deadline a timestamp expiry for the permit
     */
    function _getPermitDigest(address spender, uint256 tokenId, uint256 nonce, uint256 deadline) internal view returns (bytes32) {
        return _hashTypedDataV4(
            keccak256(abi.encode(
                PERMIT_TYPEHASH,
                spender,
                tokenId,
                nonce,
                deadline
            ))
        );
    }

    /**
     * @dev Builds the permit for all digest to sign
     * @param spender the address to approve
     * @param nonce the nonce to make a permit for
     * @param deadline a timestamp expiry for the permit
     */
    function _getPermitForAllDigest(address spender, uint256 nonce, uint256 deadline) internal view returns (bytes32) {
        return _hashTypedDataV4(
            keccak256(abi.encode(
                PERMIT_FOR_ALL_TYPEHASH,
                spender,
                nonce,
                deadline
            ))
        );
    }

    /**
     * @dev Helper to easily increment a nonce for a given tokenId
     */
    function _incrementNonce(uint256 tokenId) internal {
        _nonces[tokenId]++;
    }

    /**
     * @dev See {IERC4494-DOMAIN_SEPARATOR}.
     */
    function DOMAIN_SEPARATOR() external view override returns(bytes32) {
        return _domainSeparatorV4();
    }

    /**
     * @dev See {IERC4494-nonces}.
     */
    function nonces(uint256 tokenId) external view override returns(uint256) {
        require(_exists(tokenId), "ERC721: invalid token ID");
        return _nonces[tokenId];
    }

    /**
     * @dev Find nonce by address
     */
    function nonceByAddress(address owner) external view returns(uint256) {
        return _noncesByAddress[owner];
    }

    /// ------------------------------------- Ownable -------------------------------------

    /**
     * @dev Accept the ownership transfer. This is to make sure that the contract is
     * transferred to a working address
     *
     * Can only be called by the newly transfered owner.
     */
    function acceptOwnership() external {
        require(msg.sender == _newOwner, "VRC725: only new owner can accept ownership");
        address oldOwner = _owner;
        _owner = _newOwner;
        _newOwner = address(0);
        emit OwnershipTransferred(oldOwner, _owner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     *
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) external virtual onlyOwner {
        require(newOwner != address(0), "VRC725: new owner is the zero address");
        _newOwner = newOwner;
    }

    /// ------------------------------------- EIP-712 -------------------------------------

    /* solhint-enable var-name-mixedcase */

    /**
     * @dev Initializes the domain separator and parameter caches.
     *
     * The meaning of `name` and `version` is specified in
     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
     *
     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
     * - `version`: the current major version of the signing domain.
     *
     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
     * contract upgrade].
     */
    function __EIP712_init(string memory name_, string memory version) private {
        __EIP712_init_unchained(name_, version);
    }

    function __EIP712_init_unchained(string memory name_, string memory version) internal {
        bytes32 hashedName = keccak256(bytes(name_));
        bytes32 hashedVersion = keccak256(bytes(version));
        _HASHED_NAME = hashedName;
        _HASHED_VERSION = hashedVersion;
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view returns (bytes32) {
        return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());
    }

    function _buildDomainSeparator(
        bytes32 typeHash,
        bytes32 nameHash,
        bytes32 versionHash
    ) private view returns (bytes32) {
        return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
    }

    /**
     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
     * function returns the hash of the fully encoded EIP712 message for this domain.
     *
     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
     *
     * ```solidity
     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
     *     keccak256("Mail(address to,string contents)"),
     *     mailTo,
     *     keccak256(bytes(mailContents))
     * )));
     * address signer = ECDSA.recover(digest, signature);
     * ```
     */
    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
    }

    /**
     * @dev The hash of the name parameter for the EIP712 domain.
     *
     * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs
     * are a concern.
     */
    function _EIP712NameHash() internal virtual view returns (bytes32) {
        return _HASHED_NAME;
    }

    /**
     * @dev The hash of the version parameter for the EIP712 domain.
     *
     * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs
     * are a concern.
     */
    function _EIP712VersionHash() internal virtual view returns (bytes32) {
        return _HASHED_VERSION;
    }
}

````

Source: [VRC725.sol](https://github.com/BuildOnViction/vrc725/blob/main/contracts/VRC725.sol)

### **Example**

The following example demonstrates a token using the VRC725.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2;

import "../extensions/VRC725Enumerable.sol";

contract TestNFT is VRC725Enumerable {
    constructor(string memory name, string memory symbol, address issuer) {
        __VRC725_init(name, symbol, issuer);
    }

    function _estimateFee(uint256) internal view override returns (uint256) {
        return minFee();
    }

    function mint(address owner, uint256 tokenId) external onlyOwner {
        _safeMint(owner, tokenId);
    }
}
```

Source: [TestNFT.sol](https://github.com/BuildOnViction/vrc725/blob/main/contracts/tests/TestNFT.sol)

### **Enable zero-gas transaction**

VRC725 is not required to apply for VictionZ. Zero-gas operation will be applied through TransferHelper ([click here for example](https://github.com/BuildOnViction/vrc725/blob/main/contracts/helpers/VRC725Helper.sol)) which is integrated VRC25.

In the case you need to apply for VictionZ to support more Zero-gas operations in your token, VRC725 is still compatible with VictionZ. Please refer to [VIC ZeroGas](/developer-guide/integration/vic-zerogas-integration) page for instruction.


# IDEs and Tools

{% content-ref url="/pages/511MPxDOu92WGU6SvtZu" %}
[Remix](/smart-contract-development/ides-and-tools/remix)
{% endcontent-ref %}

{% content-ref url="/pages/aPVdWGOukXmWgf7pfFO4" %}
[Hardhat](/smart-contract-development/smart-contract-verification/hardhat)
{% endcontent-ref %}

{% content-ref url="/pages/PuSyD5TNb3vn5iklXGgp" %}
[Ethers.js](/smart-contract-development/ides-and-tools/ethers.js)
{% endcontent-ref %}

{% content-ref url="/pages/TtfjjdHaPUPhgiBlplDU" %}
[web3.js](/smart-contract-development/ides-and-tools/web3js)
{% endcontent-ref %}

{% content-ref url="/pages/7JvMFlqVpjVVwWBYCM9i" %}
[thirdweb CLI](/smart-contract-development/ides-and-tools/thirdweb-cli)
{% endcontent-ref %}


# Remix

**Remix is a Solidity IDE that’s used to write, compile and debug Solidity code.** [**Solidity**](https://solidity.readthedocs.io/) **is a high-level, contract-oriented programming language for writing smart contracts. It was influenced by popular languages such as C++, Python and JavaScript.**

IDE stands for Integrated Development Environment and is an application with a set of tools designed to help programmers execute different tasks related to software development such as writing, compiling, executing and debugging code.

Before you begin using Remix to develop smart contracts, make sure you’re familiar with some basic concepts. In particular, give these articles about [blockchain](https://www.sitepoint.com/blockchain-what-it-is-how-it-works-why-its-so-popular) and [Ethereum](https://bitfalls.com/2017/09/19/what-ethereum-compare-to-bitcoin/) a read.

#### What’s a Smart Contract/Dapp? <a href="#whatsasmartcontractdapp" id="whatsasmartcontractdapp"></a>

A smart contract is a trust-less agreement between two parties that makes use of blockchain technology, to enforce the parties to adhere to the terms, rather than relying on the traditional ways such as trusting a middleman or using laws to handle disputes.

Using the Ethereum blockchain, you can create smart contracts with the Solidity language (among others). Ethereum is not the only platform that can be used to create smart contacts, but it’s the most popular choice, as it was designed from the start to support building them.

[Dapp](http://ethdocs.org/en/latest/contracts-and-transactions/developer-tools.html#dapps) stands for ***decentralized application*** and is a web3 application that can have a front-end written in traditional languages such as JavaScript, HTML, CSS and a smart contract (as back-end code) which runs on the blockchain. So you can simply think of a Dapp as the front end plus the associated blockchain smart contract(s).

Unlike the smart contract deployed on the blockchain itself, the front end of a Dapp can be either hosted on a centralized server like a CDN or on decentralized storage like [Swarm](http://ethdocs.org/en/latest/contracts-and-transactions/developer-tools.html#swarm).

### Accessing the Remix IDE <a href="#accessingtheremixide" id="accessingtheremixide"></a>

You can access the Remix IDE in different ways: online, via a web browser like Chrome, from a locally installed copy, or from Mist (the Ethereum Dapp browser).

#### Using the In-Browser Remix IDE <a href="#usingtheinbrowserremixide" id="usingtheinbrowserremixide"></a>

You can access the Remix IDE from your web browser without any special installation. Visit <https://remix.ethereum.org/> and you’ll be presented with a complete IDE with a code editor and various panels for compiling, running and debugging your smart contracts. You’ll have a default example *Ballot* contract that you can play with. Beside you should refer [Remix](https://remix-ide.readthedocs.io/en/latest/) document if need more detail.

<figure><img src="/files/2K0RBgGWEHSySvQaYXYB" alt=""><figcaption><p>Main screen</p></figcaption></figure>

### Remix Panels <a href="#remixpanels" id="remixpanels"></a>

After seeing how to open the Remix IDE, let’s now see the various panels composing the IDE.

#### File Explorer <a href="#fileexplorer" id="fileexplorer"></a>

The file explorer provides a view with the created files stored in the browser’s storage. You can rename or delete any file by right-clicking on it, then choosing the right operation from the context menu.

![Workspace](/files/tEMuhBHuQxhdEuB9hDRN)

Please note that the file explorer uses the browser’s local storage by default, which means you can lose all your files if you clear or the operating system automatically clears the storage. For advanced work, it’s recommended to use [Remixd](https://github.com/ethereum/remixd) - a Node.js tool (available from npm `npm install -g remixd`) which allows the Remix IDE to access your computer’s file system.

**Creating/Opening Files in Remix**

You can create a new file in the browser local storage using the first button *file* on the top left. You can then provide a name and press Enter.

Using the second button from top left, you can open an existing Solidity file from your computer file system into the Remix IDE. The file will also be stored in the browser’s local storage.

**Publishing Explorer Files as GitHub Gists**

Using the third and fourth buttons from top left, you can publish files from the IDE as a public GitHub gist.

**Copying Files to Another Instance of Remix IDE**

Using the fifth button from top left, you can copy files from the local storage to another instance of Remix by providing the URL of the instance.

**Connecting to the Local File System**

the last button can be used to connect the Remix IDE to your local file system if you’re running the [Remixd](https://remix-ide.readthedocs.io/en/latest/remixd.html) tool.

#### Solidity Code Editor <a href="#soliditycodeeditor" id="soliditycodeeditor"></a>

The Solidity code editor provides the interface where you can write your code with many features such as syntax highlighting, auto-recompling, auto-saving etc. You can open multiple tabs and also increase/decrease the font size using the *+/-* button in the top-left corner.

![Solidity Code Editor](/files/VxEr1YpWluNIN4SN3k16)

#### Terminal <a href="#terminal" id="terminal"></a>

The terminal window below the editor integrates a JavaScript interpreter and the `web3` object. You can execute JavaScript code in the current context, visualize the actions performed from the IDE, visualize all network transactions or transactions created from the Remix IDE etc. You can also search for data in the terminal and clear the logs.

![Remix terminal](/files/2xNarIgBZcEcOt6yhSIk)

#### Tabs Panel <a href="#tabspanel" id="tabspanel"></a>

The *Tabs* panel provides many tabs for working with the IDE:

* the *Compile* tab: used for compiling a smart contract and publishing on Swarm and used for updating settings like the compiler version and many general settings for the editor.
* the *Run* and *Deploy* tab: used for sending transactions to the configured environment.
* the *Settings* tab: used for updating settings like the compiler version and many general settings for the editor.
* the *Plugin* tab: used for install local plugin in Remix.
* the *Search* tab: used for search file which locates in Remix.
* the *File Explorer* tab: used for display all files and folders in Remix.
* the Debug tab: used for debug when execute contract.

![Remix tabs](/files/RJEPrlS11qDYLDLOGFwk)

### Remix Execution Environments <a href="#remixexecutionenvironments" id="remixexecutionenvironments"></a>

The Remix IDE provides many environments for executing the transactions:

* JavaScript VM: a sandbox blockchain implemented with JavaScript in the browser to emulate a real blockchain.
* Injected Web3: a provider that injects web3 such as [`Metamask`](https://coinsbench.com/how-to-use-remix-ide-to-deploy-your-smart-contract-on-chain-5e37e1faa15a), allow you to connect to real blockchain.
* Web3 Provider: a remote node with geth, parity or any Ethereum client. Can be used to connect to the real network, or to your private blockchain directly without MetaMask in the middle.

![Remix Execution Environments](/files/r46aIeVJ9mGFdQD0bXXq)

### Using Remix IDE to Compile and Deploy a Smart Contract <a href="#usingremixidetocompileanddeployasmartcontract" id="usingremixidetocompileanddeployasmartcontract"></a>

For the sake of demonstrating what we can achieve using Remix IDE, we’ll use an example contract, and we’ll see how we can:

* Compile the contract in Remix IDE.
* See some warnings emitted by the compiler when best practices aren’t followed.
* Deploy the contract on the JavaScript EVM (Ethereum Virtual Machine).
* Make transactions on the deployed contract.
* See example reads and writes in the terminal IDE.

We’ll use the following example contract [from this tutorial](https://bitfalls.com/2018/03/31/solidity-development-crash-course-building-blockchain-raffle/) which implements a simple contract to store variable on blockchain:

```solidity
pragma solidity >=0.8.2 <0.9.0;

/**
 * @title Storage
 * @dev Store & retrieve value in a variable
 * @custom:dev-run-script ./scripts/deploy_with_ethers.ts
 */
contract Storage {

    uint256 number;

    /**
     * @dev Store value in variable
     * @param num value to store
     */
    function store(uint256 num) public {
        number = num;
    }

    /**
     * @dev Return value 
     * @return value of 'number'
     */
    function retrieve() public view returns (uint256){
        return number;
    }
}
```

Now, go ahead and open the Remix IDE from [remix.ethereum.org](https://remix.ethereum.org/).

Next, create a new file by clicking on the button with the *+* icon.

![Create a new file](https://github.com/BuildOnViction/gitbook/blob/main/developer-guide/smart-contract-development/ides-and-tools/broken-reference)

And then you must enter a name , then press Enter:

![Set filename](/files/v0hdsp18gbH7oRK6FoRT)

A new tab will be opened in the code editor where you can start writing your contract. So just copy and paste the previous contract code in there.

<figure><img src="/files/ivHeeKiPQ1vvVSGK3hHo" alt=""><figcaption><p>New blank file</p></figcaption></figure>

Next, let’s deploy the contract with our RemixVM. Switch to the *Deploy and* *Run Transaction* tab, and select *Remix VM* from the dropdown menu.

<figure><img src="/files/dpwLvT79KceYjwNWq9mT" alt=""><figcaption><p>Deployment environments</p></figcaption></figure>

Next, click the *Deploy* button below the contract name.

<figure><img src="https://github.com/BuildOnViction/gitbook/blob/main/developer-guide/smart-contract-development/ides-and-tools/broken-reference" alt=""><figcaption><p>Deploy the contract</p></figcaption></figure>

Once the contract is deployed successfully on the Remix VM, a box will be opened on the bottom as below.

<figure><img src="/files/gEEP4K0VxV7bHLwexssE" alt=""><figcaption><p>Contract is deployed</p></figcaption></figure>

Under the name and address of the deployed contract, we have some buttons with red and blue colors. Red buttons refer to actions that cause a write to the blockchain, where blue buttons refer to reading from blockchain.

The Remix VM provides 15 fake accounts with *100* ether each, which we can use to test the contract. You can select a current account from the dropdown menu with the name *Account* below the *Environment* dropdown.

<figure><img src="/files/3jkPSFy3ixyte9NzIu2q" alt=""><figcaption><p>Built-in account for testing</p></figcaption></figure>

You can see we have 2 functions, therefore we interact with smart contract easily. As below, we just called function store to change global variable number of contract.

<figure><img src="/files/gJuHdLn6qTGmCEAXj6zN" alt=""><figcaption><p>Call a contract</p></figcaption></figure>

After call a function in smart contract, you can check log in terminal as below:

<figure><img src="/files/ebpbJ3fkVYzmmDeguBgL" alt=""><figcaption><p>Transaction log in terminal</p></figcaption></figure>

When compile contract, we might run into several errors. Therefore , Remix support developer by using ChatGPT, as you can see below:

<figure><img src="/files/sRUB4X6pKIuy40pklLYf" alt=""><figcaption><p>ChatGPT support</p></figcaption></figure>

### Remix Alternatives <a href="#remixalternatives" id="remixalternatives"></a>

There are many alternatives for easy development and deployment of smart contracts, such as:

* [Hardhat](https://hardhat.org/hardhat-runner/docs/getting-started#overview): Hardhat is a development environment for Ethereum software. It consists of different components for editing, compiling, debugging and deploying your smart contracts and dApps, all of which work together to create a complete development environment.
* [Embark](https://github.com/embark-framework/embark): a framework that allows you to easily develop and deploy Decentralized Applications (DApps).
* [MetaMask](https://metamask.io/): a bridge that allows you to visit the distributed web of tomorrow in your browser today. It allows you to run Ethereum DApps right in your browser without running a full Ethereum node. For how to develop with MetaMask, check this [faq](https://github.com/MetaMask/faq/).
* [Dapp](https://dapp.readthedocs.io/en/latest/): Dapp is a simple command line tool for smart contract development.
* different plugins for adding Solidity support to popular IDEs such as [this Visual Code plugin](https://marketplace.visualstudio.com/items?itemName=JuanBlanco.solidity) and [this Atom plugin](https://atom.io/packages/language-ethereum) etc.

### Conclusion <a href="#conclusion" id="conclusion"></a>

We’ve introduced you to the Remix IDE for developing smart contracts for the Ethereum blockchain. You can find more detailed information in the [docs](https://remix-ide.readthedocs.io/en/latest/).

With a basic introduction behind you, feel free to dive in deeper and experiment with changing the code and exploring the different functions and tabs the editor offers.


# Ethers.js

### About

The [Ethers.js](https://docs.ethers.org/) library provides a set of tools to interact with Ethereum Nodes with JavaScript, similar to Web3.js. Moonbeam has an Ethereum-like API available that is fully compatible with Ethereum-style JSON-RPC invocations. Therefore, developers can leverage this compatibility and use the Ethers.js library to interact with a Moonbeam node as if they were doing so on Ethereum. For more information on Ethers.js, check their [documentation site](https://docs.ethers.org/v6/).

In this guide, you'll learn how to use the Ethers.js library to send a transaction and deploy a contract on Viction.

### Checking Prerequisites <a href="#user-content-checking-prerequisites" id="user-content-checking-prerequisites"></a>

To test out the examples in this guide on Viction [mainnet](/general/network-information/viction-mainnet) or [testnet](/archive/viction-testnet), you will need to have the corresponding RPC API endpoints and some native VIC tokens.

{% hint style="info" %}
The examples in this guide assumes you have a MacOS or Ubuntu 18.04-based environment and will need to be adapted accordingly for Windows.
{% endhint %}

### Installing Ethers.js <a href="#user-content-install-ethersjs" id="user-content-install-ethersjs"></a>

To get started, you'll need to start a basic JavaScript project. First, create a directory to store all of the files you'll be creating throughout this guide and initialize the project with the following command:

```bash
mkdir ethers-examples
cd ethers-examples
npm init --y
```

For this guide, you'll need to install the Ethers.js library and the Solidity compiler. To install both NPM packages, you can run the following command:

{% tabs %}
{% tab title="npm" %}
npm install ethers solc\@0.8.0
{% endtab %}

{% tab title="yarn" %}
yarn add ethers solc\@0.8.0
{% endtab %}
{% endtabs %}

### Setting up the Ethers Provider <a href="#user-content-setting-up-the-ethers-provider" id="user-content-setting-up-the-ethers-provider"></a>

Throughout this guide, you'll be creating a bunch of scripts that provide different functionality such as sending a transaction, deploying a contract, and interacting with a deployed contract. In most of these scripts you'll need to create an [Ethers provider](https://docs.ethers.org/v6/api/providers/) to interact with the network.

To create a provider, you can take the following steps:

1. Import the `ethers` library.
2. Define the `providerRPC` object, which can include the network configurations for any of the networks you want to send a transaction on. You'll include the `name`, `rpc`, and `chainId` for each network.
3. Create the `provider` using the `ethers.JsonRpcProvider` method.

```javascript
// 1. Import ethers
const ethers = require('ethers');

// 2. Define network configurations
const providerRPC = {
  mainnet: {
    name: 'Viction-mainnet',
    rpc: 'https://rpc.viction.xyz', // Insert your RPC URL here
    chainId: 88,
  },
};
// 3. Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.mainnet.rpc, {
  chainId: providerRPC.mainnet.chainId,
  name: providerRPC.mainnet.name, 
});
```

Save this code snippet as you'll need it for the scripts that are used in the following sections.

### Send a Transaction <a href="#user-content-send-a-transaction" id="user-content-send-a-transaction"></a>

During this section, you'll be creating a couple of scripts. The first one will be to check the balances of your accounts before trying to send a transaction. The second script will actually send the transaction.

You can also use the balance script to check the account balances after the transaction has been sent.

#### **Check Balances Script**

You'll only need one file to check the balances of both addresses before and after the transaction is sent. To get started, you can create a `balances.js` file by running:

```bash
touch balances.js
```

Next, you will create the script for this file and complete the following steps:

1. [Set up the Ethers provider](https://docs.moonbeam.network/builders/build/eth-api/libraries/ethersjs/#setting-up-the-ethers-provider).
2. Define the `addressFrom` and `addressTo` variables.
3. Create the asynchronous `balances` function which wraps the `provider.getBalance` method.
4. Use the `provider.getBalance` function to fetch the balances for the `addressFrom` and `addressTo` addresses. You can also leverage the `ethers.formatEther` function to transform the balance into a more readable number in VIC.
5. Lastly, run the `balances` function.

```javascript
// 1. Import ethers
const ethers = require('ethers');

// 2. Define network configurations
const providerRPC = {
  mainnet: {
    name: 'Viction-mainnet',
    rpc: 'https://rpc.viction.xyz', // Insert your RPC URL here
    chainId: 88,
  },
};
// 3. Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.mainnet.rpc, {
  chainId: providerRPC.mainnet.chainId,
  name: providerRPC.mainnet.name, 
}); // Change to correct network

// Define addresses
const addressFrom = 'INSERT_FROM_ADDRESS';
const addressTo = 'INSERT_TO_ADDRESS';

// Create balances function
const balances = async () => {
  // Fetch balances
  const balanceFrom = ethers.formatEther(
    await provider.getBalance(addressFrom)
  );
  const balanceTo = ethers.formatEther(await provider.getBalance(addressTo));

  console.log(`The balance of ${addressFrom} is: ${balanceFrom} DEV`);
  console.log(`The balance of ${addressTo} is: ${balanceTo} DEV`);
};

// Call the balances function
balances();
```

To run the script and fetch the account balances, you can run the following command:

```
node balances.js
```

If successful, the balances for the origin and receiving address will be displayed in your terminal.

#### **Send Transaction Script**

You'll only need one file for executing a transaction between accounts. For this example, you'll be transferring 1 VIC token from an origin address (from which you hold the private key) to another address. To get started, you can create a `transaction.js` file by running:

```bash
touch transaction.js
```

Next, you will create the script for this file and complete the following steps:

1. [Set up the Ethers provider](https://docs.moonbeam.network/builders/build/eth-api/libraries/ethersjs/#setting-up-the-ethers-provider).
2. Define the `privateKey` and the `addressTo` variables. The private key is required to create a wallet instance. **Note: This is for example purposes only. Never store your private keys in a JavaScript file**.
3. Create a wallet using the `privateKey` and `provider` from the previous steps. The wallet instance is used to sign transactions.
4. Create the asynchronous `send` function which wraps the transaction object and the `wallet.sendTransaction` method.
5. Create the transaction object which only requires the recipient's address and the amount to send. Note that `ethers.parseEther` can be used, which handles the necessary unit conversions from Ether to Wei - similar to using `ethers.parseUnits(value, 'ether')`.
6. Send the transaction using the `wallet.sendTransaction` method and then use `await` to wait until the transaction is processed and the transaction receipt is returned.
7. Lastly, run the `send` function.

```javascript
// 1. Import ethers
const ethers = require('ethers');

// 2. Define network configurations
const providerRPC = {
  mainnet: {
    name: 'Viction-mainnet',
    rpc: 'https://rpc.viction.xyz', // Insert your RPC URL here
    chainId: 88,
  },
};
// 3. Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.mainnet.rpc, {
  chainId: providerRPC.mainnet.chainId,
  name: providerRPC.mainnet.name, 
}); // Change to correct network

// Define accounts and wallet
const accountFrom = {
  privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
const addressTo = 'INSERT_TO_ADDRESS';
const wallet = new ethers.Wallet(accountFrom.privateKey, provider);

// Create send function
const send = async () => {
  console.log(
    `Attempting to send transaction from ${wallet.address} to ${addressTo}`
  );

  // Create transaction
  const tx = {
    to: addressTo,
    value: ethers.parseEther('1'),
  };

  // Send transaction and get hash
  const createReceipt = await wallet.sendTransaction(tx);
  await createReceipt.wait();
  console.log(`Transaction successful with hash: ${createReceipt.hash}`);
};

// Call the send function
send();
```

To run the script, you can run the following command in your terminal:

```bash
node transaction.js
```

If the transaction was succesful, in your terminal you'll see the transaction hash has been printed out.

You can also use the `balances.js` script to check that the balances for the origin and receiving accounts have changed.

### **Deploy a Contract**

The contract you'll be compiling and deploying in the next couple of sections is a simple incrementer contract, arbitrarily named `Incrementer.sol`. You can get started by creating a file for the contract:

```bash
touch Incrementer.sol
```

Next, you can add the Solidity code to the file:

```solidity
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract Incrementer {
    uint256 public number;

    constructor(uint256 _initialNumber) {
        number = _initialNumber;
    }

    function increment(uint256 _value) public {
        number = number + _value;
    }

    function reset() public {
        number = 0;
    }
}
```

The `constructor` function, which runs when the contract is deployed, sets the initial value of the number variable stored on-chain (the default is `0`). The `increment` function adds the `_value` provided to the current number, but a transaction needs to be sent, which modifies the stored data. Lastly, the `reset` function resets the stored value to zero.

{% hint style="info" %}
This contract is a simple example for illustration purposes only and does not handle values wrapping around.
{% endhint %}

#### **Compile Contract Script**

In this section, you'll create a script that uses the Solidity compiler to output the bytecode and interface (ABI) for the `Incrementer.sol` contract. To get started, you can create a `compile.js` file by running:

```bash
touch compile.js
```

Next, you will create the script for this file and complete the following steps:

1. Import the `fs` and `solc` packages.
2. Using the `fs.readFileSync` function, you'll read and save the file contents of `Incrementer.sol` to `source`.
3. Build the `input` object for the Solidity compiler by specifying the `language`, `sources`, and `settings` to be used.
4. Using the `input` object, you can compile the contract using `solc.compile`.
5. Extract the compiled contract file and export it to be used in the deployment script.

```javascript
// 1. Import packages
const fs = require('fs');
const solc = require('solc');

// 2. Get path and load contract
const source = fs.readFileSync('Incrementer.sol', 'utf8');

// 3. Create input object
const input = {
   language: 'Solidity',
   sources: {
      'Incrementer.sol': {
         content: source,
      },
   },
   settings: {
      outputSelection: {
         '*': {
            '*': ['*'],
         },
      },
   },
};
// 4. Compile the contract
const tempFile = JSON.parse(solc.compile(JSON.stringify(input)));
const contractFile = tempFile.contracts['Incrementer.sol']['Incrementer'];

// 5. Export contract data
module.exports = contractFile;
```

#### **Deploy Contract Script**

With the script for compiling the `Incrementer.sol` contract in place, you can then use the results to send a signed transaction that deploys it. To do so, you can create a file for the deployment script called `deploy.js`:

```bash
touch deploy.js
```

Next, you will create the script for this file and complete the following steps:

1. Import the contract file from `compile.js`.
2. [Set up the Ethers provider](https://docs.moonbeam.network/builders/build/eth-api/libraries/ethersjs/#setting-up-the-ethers-provider).
3. Define the `privateKey` for the origin account. The private key is required to create a wallet instance. **Note: This is for example purposes only. Never store your private keys in a JavaScript file**.
4. Create a wallet using the `privateKey` and `provider` from the previous steps. The wallet instance is used to sign transactions.
5. Load the contract `bytecode` and `abi` for the compiled contract.
6. Create a contract instance with signer using the `ethers.ContractFactory` function, providing the `abi`, `bytecode`, and `wallet` as parameters.
7. Create the asynchronous `deploy` function that will be used to deploy the contract.
8. Within the `deploy` function, use the `incrementer` contract instance to call `deploy` and pass in the initial value. For this example, you can set the initial value to `5`. This will send the transaction for contract deployment. To wait for a transaction receipt you can use the `deployed` method of the contract deployment transaction.
9. Lastly, run the `deploy` function.

```javascript
// 1. Import ethers
const ethers = require('ethers');

// 2. Define network configurations
const providerRPC = {
  mainnet: {
    name: 'Viction-mainnet',
    rpc: 'https://rpc.viction.xyz', // Insert your RPC URL here
    chainId: 88,
  },
};
// 3. Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.mainnet.rpc, {
  chainId: providerRPC.mainnet.chainId,
  name: providerRPC.mainnet.name, 
}); // Change to correct network

// Define accounts and wallet
const accountFrom = {
  privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
let wallet = new ethers.Wallet(accountFrom.privateKey, provider);

// Load contract info
const bytecode = contractFile.evm.bytecode.object;
const abi = contractFile.abi;

// Create contract instance with signer
const incrementer = new ethers.ContractFactory(abi, bytecode, wallet);

// Create deploy function
const deploy = async () => {
  console.log(`Attempting to deploy from account: ${wallet.address}`);

  // Send tx (initial value set to 5) and wait for receipt
  const contract = await incrementer.deploy(5);
  const txReceipt = await contract.deploymentTransaction().wait();

  console.log(`Contract deployed at address: ${txReceipt.contractAddress}`);
};

// Call the deploy function
deploy();
```

To run the script, you can enter the following command into your terminal:

```bash
node deploy.js
```

If successful, the contract's address will be displayed in the terminal.

### **Read Contract Data (Call Methods)**

Call methods are the type of interaction that don't modify the contract's storage (change variables), meaning no transaction needs to be sent. They simply read various storage variables of the deployed contract.

To get started, you can create a file and name it `get.js`:

```bash
touch get.js
```

Then you can take the following steps to create the script:

1. Import the `abi` from the `compile.js` file.
2. [Set up the Ethers provider](https://docs.moonbeam.network/builders/build/eth-api/libraries/ethersjs/#setting-up-the-ethers-provider).
3. Create the `contractAddress` variable using the address of the deployed contract.
4. Create an instance of the contract using the `ethers.Contract` function and passing in the `contractAddress`, `abi`, and `provider`.
5. Create the asynchronous `get` function.
6. Use the contract instance to call one of the contract's methods and pass in any inputs if necessary. For this example, you will call the `number` method which doesn't require any inputs. You can use `await` which will return the value requested once the request promise resolves.
7. Lastly, call the `get` function.

```javascript
// 1. Import ethers
const ethers = require('ethers');
const { abi } = require('./compile');

// 2. Define network configurations
const providerRPC = {
  mainnet: {
    name: 'Viction-mainnet',
    rpc: 'https://rpc.viction.xyz', // Insert your RPC URL here
    chainId: 88,
  },
};
// 3. Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.mainnet.rpc, {
  chainId: providerRPC.mainnet.chainId,
  name: providerRPC.mainnet.name, 
}); // Change to correct network

// Contract address variable
const contractAddress = 'INSERT_CONTRACT_ADDRESS';

// Create contract instance
const incrementer = new ethers.Contract(contractAddress, abi, provider);

// Create get function
const get = async () => {
  console.log(`Making a call to contract at address: ${contractAddress}`);

  // Call contract
  const data = await incrementer.number();

  console.log(`The current number stored is: ${data}`);
};

// Call get function
get();
```

To run the script, you can enter the following command in your terminal:

```bash
node get.js
```

If successful, the value will be displayed in the terminal.

### **Interact with Contract (Send Methods)**

Send methods are the type of interaction that modify the contract's storage (change variables), meaning a transaction needs to be signed and sent. In this section, you'll create two scripts: one to increment and one to reset the incrementer. To get started, you can create a file for each script and name them `increment.js` and `reset.js`:

```bash
touch increment.js reset.js
```

Open the `increment.js` file and take the following steps to create the script:

1. Import the `abi` from the `compile.js` file.
2. [Set up the Ethers provider](https://docs.moonbeam.network/builders/build/eth-api/libraries/ethersjs/#setting-up-the-ethers-provider).
3. Define the `privateKey` for the origin account, the `contractAddress` of the deployed contract, and the `_value` to increment by. The private key is required to create a wallet instance. **Note: This is for example purposes only. Never store your private keys in a JavaScript file**.
4. Create a wallet using the `privateKey` and `provider` from the previous steps. The wallet instance is used to sign transactions.
5. Create an instance of the contract using the `ethers.Contract` function and passing in the `contractAddress`, `abi`, and `provider`.
6. Create the asynchronous `increment` function.
7. Use the contract instance to call one of the contract's methods and pass in any inputs if necessary. For this example, you will call the `increment` method which requires the value to increment by as an input. You can use `await` which will return the value requested once the request promise resolves.
8. Lastly, call the `increment` function.

```javascript
// 1. Import ethers
const ethers = require('ethers');
const { abi } = require('./compile');

// 2. Define network configurations
const providerRPC = {
  mainnet: {
    name: 'Viction-mainnet',
    rpc: 'https://rpc.viction.xyz', // Insert your RPC URL here
    chainId: 88,
  },
};
// 3. Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.mainnet.rpc, {
  chainId: providerRPC.mainnet.chainId,
  name: providerRPC.mainnet.name, 
}); // Change to correct network

// Create variables
const accountFrom = {
  privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
const contractAddress = 'INSERT_CONTRACT_ADDRESS';
const _value = 3;

// 4. Create wallet
let wallet = new ethers.Wallet(accountFrom.privateKey, provider);

// 5. Create contract instance with signer
const incrementer = new ethers.Contract(contractAddress, abi, wallet);

// 6. Create increment function
const increment = async () => {
  console.log(
    `Calling the increment by ${_value} function in contract at address: ${contractAddress}`
  );

  // 7. Sign and send tx and wait for receipt
  const createReceipt = await incrementer.increment(_value);
  await createReceipt.wait();

  console.log(`Tx successful with hash: ${createReceipt.hash}`);
};

// 8. Call the increment function
increment();
```

To run the script, you can enter the following command in your terminal:

```bash
node increment.js
```

If successful, the transaction hash will be displayed in the terminal. You can use the `get.js` script alongside the `increment.js` script. Next you can open the `reset.js` file and take the following steps to create the script:

1. Import the `abi` from the `compile.js` file.
2. [Set up the Ethers provider](https://docs.moonbeam.network/builders/build/eth-api/libraries/ethersjs/#setting-up-the-ethers-provider).
3. Define the `privateKey` for the origin account and the `contractAddress` of the deployed contract. The private key is required to create a wallet instance. **Note: This is for example purposes only. Never store your private keys in a JavaScript file**.
4. Create a wallet using the `privateKey` and `provider` from the previous steps. The wallet instance is used to sign transactions.
5. Create an instance of the contract using the `ethers.Contract` function and passing in the `contractAddress`, `abi`, and `provider`.
6. Create the asynchronous `reset` function.
7. Use the contract instance to call one of the contract's methods and pass in any inputs if necessary. For this example, you will call the `reset` method which doesn't require any inputs. You can use `await` which will return the value requested once the request promise resolves.
8. Lastly, call the `reset` function.

```javascript
// 1. Import ethers
const ethers = require('ethers');
const { abi } = require('./compile');

// 2. Define network configurations
const providerRPC = {
  mainnet: {
    name: 'Viction-mainnet',
    rpc: 'https://rpc.viction.xyz', // Insert your RPC URL here
    chainId: 88,
  },
};
// 3. Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.mainnet.rpc, {
  chainId: providerRPC.mainnet.chainId,
  name: providerRPC.mainnet.name, 
}); // Change to correct network

// Create variables
const accountFrom = {
  privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
const contractAddress = 'INSERT_CONTRACT_ADDRESS';

// Create wallet
let wallet = new ethers.Wallet(accountFrom.privateKey, provider);

// Create contract instance with signer
const incrementer = new ethers.Contract(contractAddress, abi, wallet);

// Create reset function
const reset = async () => {
  console.log(
    `Calling the reset function in contract at address: ${contractAddress}`
  );

  // Sign and send tx and wait for receipt
  const createReceipt = await incrementer.reset();
  await createReceipt.wait();

  console.log(`Tx successful with hash: ${createReceipt.hash}`);
};

// Call the reset function
reset();
```

To run the script, you can enter the following command in your terminal:

```bash
node reset.js
```

If successful, the transaction hash will be displayed in the terminal. You can use the `get.js` script alongside the `reset.js` script to make sure that value is changing as expected.


# web3.js

### 1 · What is web3.js? <a href="#id-1" id="id-1"></a>

There are a few different aspects to developing blockchain applications with Ethereum:

1. Smart contract development - writing code that gets deployed to the blockchain with the Solidity programming language.
2. Developing websites or clients that interact with the blockchain - writing code that reads and writes data from the blockchain with smart contracts.

[web3.js](https://web3js.readthedocs.io/en/1.0/) enables you to fulfill the second responsibility: developing clients that interact with The Etherem Blockchain. It is a collection of libraries that allow you to perform actions like send Ether from one account to another, read and write data from smart contracts, create smart contracts, and so much more!

If you have a web development background, you might have used jQuery to make Ajax calls to a web server. That's a good starting point for understanding the function of Web3.js. Instead of using a jQuery to read and write data from a web server, you can use Web3.js to read and write to The Ethereum Blockchain.

Here is a diagram of how a client talks to Ethereum:![web3-js-diagram](https://www.dappuniversity.com/web3-js-diagram.png)

*Image credit:* [*iotbl*](https://iotbl.blogspot.com/2017/03/ethereum-and-blockchain-2.html)*.*

web3.js talks to The Ethereum Blockchain with [JSON RPC](https://en.wikipedia.org/wiki/Remote_procedure_call), which stands for "Remote Procedure Call" protocol. Ethereum is a peer-to-peer network of nodes that stores a copy of all the data and code on the blockchain. Web3.js allows us to make requests to an individual Ethereum node with JSON RPC in order to read and write data to the network. It's kind of like using jQuery with a JSON API to read and write data with a web server.

#### Dependencies

There are a few dependencies that will help you start developing with web3.js.

**Node Package Manager (NPM)**

The first dependency we need is [Node Package Manager](https://nodejs.org/en/), or NPM, which comes with Node.js. You can see if you have node already installed by going to your termial and typing:

```
$ node -v
```

**web3.js Library**

You can install the Web3.js library with NPM in your terminal like this:

```
$ npm install web3
```

**Infura RPC URL**

In order to connect to an Ethereum node with JSON RPC on the Main Net, we need access to an Ethereum node. There are a few ways you could do this. For one, you could run your own Ethereum node with [Geth](https://github.com/ethereum/go-ethereum/wiki/geth) or [Parity](https://www.parity.io/). But this requires you to download a lot of data from the blockchain and keep it in sync. This is a huge headache if you've ever tried to do this before.

Mostly for convenience, you can use [Infura](https://infura.io/) to access an Ethereum node without having to run one yourself. Infura is a service that provides a remote Ethereum node for free. All you need to do is sign up and obtain an API key and the RPC URL for the network you want to connect to.

Once you've signed up, your Infura RPC URL should look like this:

```
https://mainnet.infura.io/YOUR_INFURA_API_KEY
```

#### Checking Account Balances

Now that all of your dependencies are installed, you can start developing with Web3.js! First, you should fire up the Node console in your terminal like this:

```
$ node
```

Now you've got the Node console open! Inside the Node console, you can require Web3.js like this:

```
const Web3 = require('web3')
```

Now you have access to a variable where you can create a new Web3 connection! Before we generate a Web3 connection, we must first assign the Infura URL to a variable like this:

```
const rpcURL = "https://mainnet.infura.io/YOUR_INFURA_API_KEY"
```

Make sure that you replace `YOUR_INFURA_API_KEY` with your actual Infura API key that you obtained earlier. Now you can instantiate a Web3 connection like this:

```
const web3 = new Web3(rpcURL)
```

Now you have a live Web3 connection that will allow you to talk to the Ethereum main net! Let's use this connection to check the account balance for this account: [0x90e63c3d53E0Ea496845b7a03ec7548B70014A91](https://etherscan.io/address/0x90e63c3d53e0ea496845b7a03ec7548b70014a91). We can see how much Ether this account holds by checking its balance with `web3.eth.getBalance()`.

First, let's assign the address to a variable:

```
const account = "0x90e63c3d53E0Ea496845b7a03ec7548B70014A91"
```

Now, let's check the account balance like this:

```
web3.eth.getBalance(address, (err, wei) => {
  balance = web3.utils.fromWei(wei, 'ether')
})
```

First, we use check the balance by calling `web3.eth.getBalance()`, which accepts a callback function with two arguments, an error and the balance itself. We'll ignore the error argument for now, and reference the balance with the `wei` argument. Ethereum expresses balances in Wei, which is the smallest subdivision of Ether, kind of like a tiny penny. We can convert this balance to Ether with `web3.utils.fromWei(wei, 'ether')`.

Now you've seen what the Web3.js library is and you can get started using it to check Ethereum account balances. Here is a summary of the code

```
const Web3 = require('web3')
const rpcURL = '' // Your RPC URL goes here
const web3 = new Web3(rpcURL)
const address = '' // Your account address goes here
web3.eth.getBalance(address, (err, wei) => {
  balance = web3.utils.fromWei(wei, 'ether')
})
```

You can also download all the code examples in this tutorial series from [github](https://github.com/dappuniversity/web3_examples).

Reading through the Web3.js documentation will give you a thorough overview of what you can do with the library. Browse through it, even if you don't understand every aspect of its functionality. You can find the full documentation for Web3.js here:

<https://web3js.readthedocs.io/en/1.0/>

Additionally, note that Web3.js is under active development. You can visit the Web3.js github repository to follow along with its progress, and also read through the code to gain a better understanding of the library itself. You can find the github repository here:

<https://github.com/ethereum/web3.js/>

### 2 · Read Data from Smart Contracts with Web3.js <a href="#id-2" id="id-2"></a>

In order to read data from smart contracts with Web3.js, we need two things:

1. A JavaScript representation of the smart contract we want to interact with
2. A way to call the functions on the smart contract when reading the data

We can get a JavaScript representation of an Ethereum smart contract with the `web3.eth.Contract()` function. This function expects two arguments: one for the smart contract ABI and one for the smart contract address.

A smart contract ABI stands for "Abstract Binary Interface", and is a JSON array that describes how a specific smart contract works. Here is an example an ABI:

```
const abi = [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_releaseTime","type":"uint256"}],"name":"mintTimelocked","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]
```

This example is the ABI for the OmiseGo token, which implements the ERC-20 token standard. You can find more details about this token, including its abi and address on [Etherscan](https://etherscan.io/address/0xd26114cd6EE289AccF82350c8d8487fedB8A0C07).

Go ahead and store the address to the OMG token from the Ethereum main net:

```
const address = "0xd26114cd6EE289AccF82350c8d8487fedB8A0C07"
```

Now that we have both of these values assigned, we can create a complete JavaScript representation of the OMG token smart contract like this:

```
const contract = new web3.eth.Contract(abi, address)
```

So, how to read data from the smart contract by calling its functions. All of the smart contract functions are listed under the `contract.methods` namespace within the assigned Web3 contract. For example, we can call `contract.methods.myFunction()` if the contract implements `myFunction()`.

So we can theoretically call any function that the smart contract implements. But how do we know which functions it implements? For one, we could log `contract.methods` to the console, and see what's returned. However, since this smart contract implements the ERC-20 standard, we know that it implements several functions like `totalSupply()`, `name()`, `symbol()`, and `balanceOf()`. We can read each of those values individually, like this:

First, the total supply of all OMG tokens in existence:

```
contract.methods.totalSupply().call((err, result) => { console.log(result) })
// > 140245398
```

Second, the name of the OMG token:

```
contract.methods.name().call((err, result) => { console.log(result) })
// > OMG Token
```

Third, the symbol of the OMG token:

```
contract.methods.symbol().call((err, result) => { console.log(result) })
// > OMG
```

Last, we can check the balance for a given account. Look for a rich OMG holder on Etherscan, and found this address `0xd26114cd6EE289AccF82350c8d8487fedB8A0C07`. We can check the balance for this account like this:

```
contract.methods.balanceOf('0xd26114cd6EE289AccF82350c8d8487fedB8A0C07').call((err, result) => { console.log(result) })
// > A very large number...
```

That's how to read data from smart contracts with Web3.js. Here is a summary of all the code:

```
const Web3 = require('web3')
const rpcURL = '' // Your RCP URL goes here
const web3 = new Web3(rpcURL)

const abi = [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_releaseTime","type":"uint256"}],"name":"mintTimelocked","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]
const address = '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07'

const contract = new web3.eth.Contract(abi, address)

contract.methods.totalSupply().call((err, result) => { console.log(result) })
contract.methods.name().call((err, result) => { console.log(result) })
contract.methods.symbol().call((err, result) => { console.log(result) })
contract.methods.balanceOf('0xd26114cd6EE289AccF82350c8d8487fedB8A0C07').call((err, result) => { console.log(result) })
```

You can also download all the code examples in this tutorial series from [github](https://github.com/dappuniversity/web3_examples).

### 3 · Inside Ethereum Transactions <a href="#id-3" id="id-3"></a>

Whenever you create a transaction, you're writing data to the blockchain and updating its state. There are several ways to do this, like sending Ether from one account to another, calling a smart contract function that writes data, and deploying a smart contract to the blockchain. We can get a greater understanding of these concepts by performing these actions with the Web3.js library and observing how each step works.

In order to broadcast transactions to the network, we'll need to sign them first. Use an additional JavaScript library to do this called [ethereumjs-tx](https://github.com/ethereumjs/ethereumjs-tx). You can install this dependency from the command line like this:

```
$ npm install ethereumjs-tx
```

The reason we're going to use this library is that we want to sign all of the transactions locally. If we were running our own Ethereum node locally, we could unlock an account that was stored locally and sign all of our transactions locally. If that were the case, we would not necessarily need to use this library. However, we're using a remote node hosted by Infura. While Infura is a trustworthy service, we still want to sign the transactions locally rather than giving the remote node manage our private keys.

In order to create the raw transaction, sign it, then send the transaction and broadcast it to the network, we need to create a simple `app.js` file to run the code, rather than doing everything in the console.

Inside the `app.js` file, we'll first require the newly installed library like this:

```
var Tx = require('ethereumjs-tx')
```

Next, we'll set up a Web3 connection like we did in the previous lessons:

```
const Web3 = require('web3')
const web3 = new Web3('https://ropsten.infura.io/YOUR_INFURA_API_KEY')
```

Notice, that we're using the Ropsten test network, that because all transactions cost gas in the form of Ether. We can use fake Ether on the Ropsten test net without worrying about spending any money. You can obtain fake Ether from a faucet on the Ropsten test network with a faucet. Here are two faucets you can use:

<http://faucet.ropsten.be:3001/>

<https://faucet.metamask.io/>

In order to create a transaction that sends fake Ether from one account to another, we'll need two accounts and their private keys. You can actually create new accounts with Web3.js like this:

```
web3.eth.accounts.create()
// > {
//    address: "0xb8CE9ab6943e0eCED004cDe8e3bBed6568B2Fa01",
//    privateKey: "0x348ce564d427a3311b6536bbcff9390d69395b06ed6c486954e971d960fe8709",
//    signTransaction: function(tx){...},
//    sign: function(data){...},
//    encrypt: function(password){...}
// }
```

Once you have created both of these accounts, make sure you load them up with fake Ether from a faucet. Now, we'll assign them to variables in our script like this:

```
const account1 = '0xb8CE9ab6943e0eCED004cDe8e3bBed6568B2Fa01'
const account2 = '0xb8CE9ab6943e0eCED004cDe8e3bBed6568B2Fa02'
```

Be sure to use the accounts you generated! Now, let's save the private keys to the environment like this:

```
export PRIVATE_KEY_1='your private key 1 here'
export PRIVATE_KEY_1='your private key 2 here'
```

Save these private keys to our environment so that we don't hard code them into our file. It's bad practice to expose private keys like that. What if we accidentally committed them to source in a real project? Someone could steal our Ether! Now we want to read these private keys from our environment and store them to variables. We can do this with the `process` global object in NodeJS like this:

```
const privateKey1 = process.env.PRIVATE_KEY_1
const privateKey2 = process.env.PRIVATE_KEY_2
```

In order to sign transactions with the private keys, we must convert them to a string of binary data with a Buffer, a globally available module in NodeJS. We can do that like this:

```
const privateKey1 = Buffer.from(process.env.PRIVATE_KEY_1)
const privateKey1 = Buffer.from(process.env.PRIVATE_KEY_2)
```

Now all of variables have been set up! From this point, we want to do a few things:

1. Build a transaction object
2. Sign the transaction
3. Broadcast the transaction to the network

We can build the transaction object like this:

```
const txObject = {
    nonce:    web3.utils.toHex(txCount),
    to:       account2,
    value:    web3.utils.toHex(web3.utils.toWei('0.1', 'ether')),
    gasLimit: web3.utils.toHex(21000),
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei'))
  }
```

We're building an object that has all the values needed to generate a transaction, like `nonce`, `to`, `value`, `gasLimit`, and `gasPrice`. Let's break down each of these values:

* `nonce` - this is the previous transaction count for the given account. We'll assign the value of this variable momentarily. We also must convert this value to hexidecimal. We can do this with the Web3.js utilitly `web3.utils.toHex()`
* `to` - the account we're sending Ether to.
* `value` - the amount of Ether we want to send. This value must be expressed in Wei and converted to hexidecimal. We can convert the value to we with the Web3.js utility `web3.utils.toWei()`.
* `gasLimit` - this is the maximum amount of gas consumed by the transaction. A basic transaction like this always costs 21000 units of gas, so we'll use that for the value here.
* `gasPrice` - this is the amount we want to pay for each unit of gas. I'll use 10 Gwei here.

Note, that there is no `from` field in this transaction object. That will be inferred whenever we sign this transaction with `account1`'s private key.

Now let's get assign the value for the `nonce` variable. We can get the transaction nonce with `web3.eth.getTransactionCount()` function. We'll wrap all of our code inside a callback function like this:

```
web3.eth.getTransactionCount(account1, (err, txCount) => {
  const txObject = {
    nonce:    web3.utils.toHex(txCount),
    to:       account2,
    value:    web3.utils.toHex(web3.utils.toWei('0.1', 'ether')),
    gasLimit: web3.utils.toHex(21000),
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei'))
  }
})
```

And there is the completed transaction object! Now we must move on to step 2 where we sign the transaction. We can do that like this:

```
const tx = new Tx(txObject)
tx.sign(privateKey1)

const serializedTx = tx.serialize()
const raw = '0x' + serializedTx.toString('hex')
```

Here we're using the `etheremjs-tx` library to create a new Tx object. We also use this library to sign the transaction with `privateKey1`. Next, we serialize the transaction and convert it to a hexidecimal string so that it can be passed to Web3.

Finally, we send this signed serialized transaction to the test network with the `web3.eth.sendSignedTransaction()` function like this:

```
web3.eth.sendSignedTransaction(raw, (err, txHash) => {
  console.log('txHash:', txHash)
})
```

That's the final step of sending the transaction and broadcasting it to the network. At this point, your completed `app.js` file should look like this:

```
var Tx     = require('ethereumjs-tx')
const Web3 = require('web3')
const web3 = new Web3('https://ropsten.infura.io/YOUR_INFURA_API_KEY')

const account1 = '' // Your account address 1
const account2 = '' // Your account address 2

const privateKey1 = Buffer.from('YOUR_PRIVATE_KEY_1', 'hex')
const privateKey2 = Buffer.from('YOUR_PRIVATE_KEY_2', 'hex')

web3.eth.getTransactionCount(account1, (err, txCount) => {
  // Build the transaction
  const txObject = {
    nonce:    web3.utils.toHex(txCount),
    to:       account2,
    value:    web3.utils.toHex(web3.utils.toWei('0.1', 'ether')),
    gasLimit: web3.utils.toHex(21000),
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei'))
  }

  // Sign the transaction
  const tx = new Tx(txObject)
  tx.sign(privateKey1)

  const serializedTx = tx.serialize()
  const raw = '0x' + serializedTx.toString('hex')

  // Broadcast the transaction
  web3.eth.sendSignedTransaction(raw, (err, txHash) => {
    console.log('txHash:', txHash)
    // Now go check etherscan to see the transaction!
  })
})
```

You can run the `app.js` file from your terminal with NodeJS like this:

```
$ node app.js
```

Or simply:

```
$ node app
```

You can download all the code examples in this tutorial series from [github](https://github.com/dappuniversity/web3_examples).

### 4 · Deploying Smart Contracts with Web3.js <a href="#id-4" id="id-4"></a>

There are multiple ways you can deploy smart contracts to The Ethereum Blockchain. There are even multiple ways to deploy them within Web3.js itself. This example is designed to break the deployment down in to each step in the process.

We will use the same `app.js` file that we used previously. We'll set it up like this:

Check out this code to follow along with the tutorial:

```
var Tx = require('ethereumjs-tx')
const Web3 = require('web3')
const web3 = new Web3('https://ropsten.infura.io/YOUR_INFURA_API_KEY')

const account1 = '' // Your account address 1

const privateKey1 = Buffer.from('YOUR_PRIVATE_KEY_1', 'hex')
```

There will be the same three basic steps as the previous part:

1. Build a transaction object
2. Sign the transaction
3. Send the transaction

These steps are the same because anytime we write data to the blockchain, it always consists of these same basic steps. We're still building a transaction and sending it to the network. The only difference is the transaction parameters.

Let's go ahead and build the transaction object like this:

```
const txObject = {
  nonce:    web3.utils.toHex(txCount),
  gasLimit: web3.utils.toHex(1000000), // Raise the gas limit to a much higher amount
  gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
  data: data
}
```

We're building this transaction object that has many of the same fields as the object from the previous lesson like `nonce`, `gasLimit`, and `gasPrice`. There are also some key differences. Let's break down each of these:

* `nonce` - this is the previous transaction count for the given account. This is the same a the previous lesson.
* `gasLimit` - this is the maximum amount of gas consumed by the transaction. We'll raise this limit because deploying smart contracts requires much more gas than sending Ether.
* `gasPrice` - this is the amount we want to pay for each unit of gas. This is the same as the previous lesson.
* `value` - this parameter is absent in this example because we aren't sending any Ether in this transaction.
* `to` - this parameter is absent because we aren't sending this transaction to a particular account. Instead we're sending it to the entire network because we're deploying a smart contract!
* `data` - this will be the bytecode of the smart contract that we want to deploy. We'll assign this variable value, and I'll explain this more momentarily.

Let's talk about the `data` parameter. This is the compiled bytecode representation of the smart contract in hexidecimal. In order to obtain this value, we first need a smart contract, and then we need to compile it! You are welcome to use any smart contract you like, especially since we're deploying this to a test network. Once you've compiled your contract, you can assign the data value to a variable like this:

```
const data = '0x60806040526040805190810160405280600a81526020017f4441707020546f6b656e000000000000000000000000000000000000000000008152506000908051906020019061004f92919061014e565b506040805190810160405280600481526020017f44415050000000000000000000000000000000000000000000000000000000008152506001908051906020019061009b92919061014e565b506040805190810160405280600f81526020017f4441707020546f6b656e2076312e300000000000000000000000000000000000815250600290805190602001906100e792919061014e565b503480156100f457600080fd5b506000620f4240905080600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600381905550506101f3565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061018f57805160ff19168380011785556101bd565b828001600101855582156101bd579182015b828111156101bc5782518255916020019190600101906101a1565b5b5090506101ca91906101ce565b5090565b6101f091905b808211156101ec5760008160009055506001016101d4565b5090565b90565b610b99806102026000396000f300608060405260043610610099576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde031461009e578063095ea7b31461012e57806318160ddd1461019357806323b872dd146101be5780635a3b7e421461024357806370a08231146102d357806395d89b411461032a578063a9059cbb146103ba578063dd62ed3e1461041f575b600080fd5b3480156100aa57600080fd5b506100b3610496565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f35780820151818401526020810190506100d8565b50505050905090810190601f1680156101205780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561013a57600080fd5b50610179600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610534565b604051808215151515815260200191505060405180910390f35b34801561019f57600080fd5b506101a8610626565b6040518082815260200191505060405180910390f35b3480156101ca57600080fd5b50610229600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061062c565b604051808215151515815260200191505060405180910390f35b34801561024f57600080fd5b5061025861089b565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561029857808201518184015260208101905061027d565b50505050905090810190601f1680156102c55780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156102df57600080fd5b50610314600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610939565b6040518082815260200191505060405180910390f35b34801561033657600080fd5b5061033f610951565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561037f578082015181840152602081019050610364565b50505050905090810190601f1680156103ac5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103c657600080fd5b50610405600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506109ef565b604051808215151515815260200191505060405180910390f35b34801561042b57600080fd5b50610480600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b48565b6040518082815260200191505060405180910390f35b60008054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561052c5780601f106105015761010080835404028352916020019161052c565b820191906000526020600020905b81548152906001019060200180831161050f57829003601f168201915b505050505081565b600081600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60035481565b6000600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561067c57600080fd5b600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561070757600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b60028054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109315780601f1061090657610100808354040283529160200191610931565b820191906000526020600020905b81548152906001019060200180831161091457829003601f168201915b505050505081565b60046020528060005260406000206000915090505481565b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109e75780601f106109bc576101008083540402835291602001916109e7565b820191906000526020600020905b8154815290600101906020018083116109ca57829003601f168201915b505050505081565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a3f57600080fd5b81600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b60056020528160005260406000206020528060005260406000206000915091505054815600a165627a7a723058204c3f690997294d337edc3571d8e77afc5b0e56a2f4bfae6fb59139c8e4eb2f7e0029'
```

Now we can also assign the `nonce` value by getting the transaction count:

```
web3.eth.getTransactionCount(account1, (err, txCount) => {
  const data = '' // Your data value goes here...

  const txObject = {
    nonce:    web3.utils.toHex(txCount),
    gasLimit: web3.utils.toHex(1000000),
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
    data: data
  }
})
```

And finally, we can sign this transaction and send it. At this point, the completed code should look like this:

```
var Tx = require('ethereumjs-tx')
const Web3 = require('web3')
const web3 = new Web3('https://ropsten.infura.io/YOUR_INFURA_API_KEY')

const account1 = '' // Your account address 1
const account2 = '' // Your account address 2

const privateKey1 = Buffer.from('YOUR_PRIVATE_KEY_1', 'hex')
const privateKey2 = Buffer.from('YOUR_PRIVATE_KEY_2', 'hex')

// Deploy the contract
web3.eth.getTransactionCount(account1, (err, txCount) => {
  const data = '0x60806040526040805190810160405280600a81526020017f4441707020546f6b656e000000000000000000000000000000000000000000008152506000908051906020019061004f92919061014e565b506040805190810160405280600481526020017f44415050000000000000000000000000000000000000000000000000000000008152506001908051906020019061009b92919061014e565b506040805190810160405280600f81526020017f4441707020546f6b656e2076312e300000000000000000000000000000000000815250600290805190602001906100e792919061014e565b503480156100f457600080fd5b506000620f4240905080600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600381905550506101f3565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061018f57805160ff19168380011785556101bd565b828001600101855582156101bd579182015b828111156101bc5782518255916020019190600101906101a1565b5b5090506101ca91906101ce565b5090565b6101f091905b808211156101ec5760008160009055506001016101d4565b5090565b90565b610b99806102026000396000f300608060405260043610610099576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde031461009e578063095ea7b31461012e57806318160ddd1461019357806323b872dd146101be5780635a3b7e421461024357806370a08231146102d357806395d89b411461032a578063a9059cbb146103ba578063dd62ed3e1461041f575b600080fd5b3480156100aa57600080fd5b506100b3610496565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f35780820151818401526020810190506100d8565b50505050905090810190601f1680156101205780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561013a57600080fd5b50610179600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610534565b604051808215151515815260200191505060405180910390f35b34801561019f57600080fd5b506101a8610626565b6040518082815260200191505060405180910390f35b3480156101ca57600080fd5b50610229600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061062c565b604051808215151515815260200191505060405180910390f35b34801561024f57600080fd5b5061025861089b565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561029857808201518184015260208101905061027d565b50505050905090810190601f1680156102c55780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156102df57600080fd5b50610314600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610939565b6040518082815260200191505060405180910390f35b34801561033657600080fd5b5061033f610951565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561037f578082015181840152602081019050610364565b50505050905090810190601f1680156103ac5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103c657600080fd5b50610405600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506109ef565b604051808215151515815260200191505060405180910390f35b34801561042b57600080fd5b50610480600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b48565b6040518082815260200191505060405180910390f35b60008054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561052c5780601f106105015761010080835404028352916020019161052c565b820191906000526020600020905b81548152906001019060200180831161050f57829003601f168201915b505050505081565b600081600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60035481565b6000600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561067c57600080fd5b600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561070757600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b60028054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109315780601f1061090657610100808354040283529160200191610931565b820191906000526020600020905b81548152906001019060200180831161091457829003601f168201915b505050505081565b60046020528060005260406000206000915090505481565b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109e75780601f106109bc576101008083540402835291602001916109e7565b820191906000526020600020905b8154815290600101906020018083116109ca57829003601f168201915b505050505081565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a3f57600080fd5b81600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b60056020528160005260406000206020528060005260406000206000915091505054815600a165627a7a723058204c3f690997294d337edc3571d8e77afc5b0e56a2f4bfae6fb59139c8e4eb2f7e0029'

  const txObject = {
    nonce:    web3.utils.toHex(txCount),
    gasLimit: web3.utils.toHex(1000000), // Raise the gas limit to a much higher amount
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
    data: data
  }

  const tx = new Tx(txObject)
  tx.sign(privateKey1)

  const serializedTx = tx.serialize()
  const raw = '0x' + serializedTx.toString('hex')

  web3.eth.sendSignedTransaction(raw, (err, txHash) => {
    console.log('err:', err, 'txHash:', txHash)
    // Use this txHash to find the contract on Etherscan!
  })
})
```

Now you can run the `app.js` file from your terminal with NodeJS like this:

```
$ node app.js
```

Or simply:

```
$ node app
```

You can download all the code examples in this tutorial series from [github](https://github.com/dappuniversity/web3_examples).

### 5 · Calling Smart Contract Functions with Web3.js <a href="#id-5" id="id-5"></a>

We'll use the same basic setup with an `app.js` file that will look like this:

```
const Web3 = require('web3')
const web3 = new Web3('https://ropsten.infura.io/YOUR_INFURA_API_KEY')

const account1 = '' // Your account address 1
const account2 = '' // Your account address 2

const privateKey1 = Buffer.from('YOUR_PRIVATE_KEY_1', 'hex')
const privateKey2 = Buffer.from('YOUR_PRIVATE_KEY_2', 'hex')
```

We'll also build out a transaction object, just like this:

```
const txObject = {
  nonce:    web3.utils.toHex(txCount),
  gasLimit: web3.utils.toHex(800000),
  gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
  to: contractAddress,
  data: data
}
```

Let's make a note of some changes.

* `to` - this parameter will be the address of the deployed contract. We'll obtain that value and assign it momentarily.
* `data` - this will be the hexidecimal representation of the function we want to call on the smart contract. We'll also assign this value momentarily.

In order to fill these values out, we'll need to get the smart contract ABI for this ERC-20 token. We need to obtain the ABI from Remix and get the smart contract address from Etherscan (this was available whenever we deployed the smart contract). Now that we have both of these things, we can create a JavaScript representation of the smart contract with Web3.js like this:

```
const contractAddress = '0xd03696B53924972b9903eB17Ac5033928Be7D3Bc'
const contractABI = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"standard","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]

const contract = new web3.eth.Contract(abi, contractAddress)
```

Now we can fill out the `data` field of the transaction by converting the contract's `transfer()` function to bytecode (that's the function we'll call on this smart contract). We can do this with the Web3.js function `encodeABI()` that is available on the `contract` object. That looks like this:

```
const data = contract.methods.transfer(account2, 1000).encodeABI()
```

Note that we're transferring 1,000 tokens to `account2`. This method takes care of encoding these function parameters.

Now that's everything we need to build the transaction object. We can now sign this transaction and send it. Once we do, we can log the values of the account balances to see that the smart contract function was called, and that the token transfers were complete. The complete code will look like this:

```
const Web3 = require('web3')
const web3 = new Web3('https://ropsten.infura.io/YOUR_INFURA_API_KEY')

const account1 = '' // Your account address 1
const account2 = '' // Your account address 2

const privateKey1 = Buffer.from('YOUR_PRIVATE_KEY_1', 'hex')
const privateKey2 = Buffer.from('YOUR_PRIVATE_KEY_2', 'hex')

// Read the deployed contract - get the addresss from Etherscan
const contractAddress = '0xd03696B53924972b9903eB17Ac5033928Be7D3Bc'
const contractABI = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"standard","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]

const contract = new web3.eth.Contract(abi, contractAddress)

// Transfer some tokens
web3.eth.getTransactionCount(account1, (err, txCount) => {

  const txObject = {
    nonce:    web3.utils.toHex(txCount),
    gasLimit: web3.utils.toHex(800000), // Raise the gas limit to a much higher amount
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
    to: contractAddress,
    data: contract.methods.transfer(account2, 1000).encodeABI()
  }

  const tx = new Tx(txObject)
  tx.sign(privateKey1)

  const serializedTx = tx.serialize()
  const raw = '0x' + serializedTx.toString('hex')

  web3.eth.sendSignedTransaction(raw, (err, txHash) => {
    console.log('err:', err, 'txHash:', txHash)
    // Use this txHash to find the contract on Etherscan!
  })
})

// Check Token balance for account1
contract.methods.balanceOf(account1).call((err, balance) => {
  console.log({ err, balance })
})

// Check Token balance for account2
contract.methods.balanceOf(account2).call((err, balance) => {
  console.log({ err, balance })
})
```

Now you can run the `app.js` file from your terminal with NodeJS like this:

```
$ node app.js
```

Or simply:

```
$ node app
```

You can download all the code examples from [github](https://github.com/dappuniversity/web3_examples).

### 6 · Smart Contract Events with Web3.js <a href="#id-6" id="id-6"></a>

Ethereum smart contracts have the ability to emit events that indicate that something happened within the smart contract code execution. Consumers have the ability to subscribe to these events, and Web3.js will provide us with this functionality.

We're going to continue using an ERC-20 smart contract because this standard specifies that the smart contract must emit a `Transfer` event anytime an ERC-20 token is transferred. We'll actually connect to the Ethereum main net to subscribe to the `Transfer` event for the OmiseGo ERC-20 token.

Let's go ahead and set up the `app.js` file. This time, we'll connect to the Ethereum main net. Paste in the OmiseGo smart contract ABI and address, which can be obtained from Etherscan. Once we have both of these things, we can create a JavaScript representation of the smart contract with Web3.js and assign it to a variable. All of that setup looks like this:

```
const Web3 = require('web3')
const web3 = new Web3('https://mainnet.infura.io/YOUR_INFURA_API_KEY')

// OMG Token Contract
const abi = [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_releaseTime","type":"uint256"}],"name":"mintTimelocked","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]
const address = '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07'

const contract = new web3.eth.Contract(abi, address)
```

Now we can look at the past events for this smart contract with the `getPastEvents()` function available on our contract object. First, let's get all of the events emitted by the contract, for its entire lifetime:

```
contract.getPastEvents(
  'AllEvents',
  {
    fromBlock: 0,
    toBlock: 'latest'
  },
  (err, events) => { console.log(events) }
)
```

Here, this function takes two arguments: the event name, and a set of filtering parameters. We specify that we want to listen to all events by passing `'AllEvents'`. We'll specify a specific event momentarily. Then, we pass some filtering parameters that specify that we want to get events for the entire lifetime of this contract by passing `from: 0`, or the first block in the chain, to `toBlock: 'latest'`, or the latest block in the chain. Just a note, if you run this code, it will probably fail execution because the event stream is so large for this particular contract on the Ethereum main net!

Let's aim for a successful execution by limiting the number of blocks we want to stream from. We can pass in a more recent `fromBlock` like this:

```
contract.getPastEvents(
  'AllEvents',
  {
    fromBlock: 5854000,
    toBlock: 'latest'
  },
  (err, events) => { console.log(events) }
)
```

Now, we can also specify that we *just* want to listen to the `Transfer` event like this:

```
contract.getPastEvents(
  'Transfer',
  {
    fromBlock: 5854000,
    toBlock: 'latest'
  },
  (err, events) => { console.log(events) }
)
```

That's all the code you need to see all of the recent transfer events for the OmiseGo ERC-20 token. With this code, you could easily build something like a transaction history for the OMG token in a crypto wallet. At this point, the completed code should look like this:

```
const Web3 = require('web3')
const web3 = new Web3('https://mainnet.infura.io/YOUR_INFURA_API_KEY')

// OMG Token Contract
const abi = [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_releaseTime","type":"uint256"}],"name":"mintTimelocked","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]
const address = '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07'

const contract = new web3.eth.Contract(abi, address)

// Get Contract Event Stream
contract.getPastEvents(
  'AllEvents',
  {
    fromBlock: 5854000,
    toBlock: 'latest'
  },
  (err, events) => { console.log(events) }
)
```

Now you can run the `app.js` file from your terminal with NodeJS like this:

```
$ node app.js
```

Or simply:

```
$ node app
```

You can download all the code examples from [github](https://github.com/dappuniversity/web3_examples).

### 7 · Inspecting Blocks with Web3.js <a href="#id-7" id="id-7"></a>

Inspecting blocks is often useful when analyzing history on The Ethereum Blockchain. Web3.js has lots of functionality that helps us to do just that. For example, we could build something that looks like this block history feature on Etherscan:![Etherscan Block History](https://www.dappuniversity.com/etherscan-blocks.png)

Let's set up an `app.js` file to start using some of this functionality provided by Web3.js. We'll connect to the main net to inspect blocks there:

```
const Web3 = require('web3')
const web3 = new Web3('https://mainnet.infura.io/YOUR_INFURA_API_KEY')
```

First, we can get the latest block number like this:

```
web3.eth.getBlockNumber().then(console.log)
```

We can also get all the data for the latest block like this:

```
web3.eth.getBlock('latest').then(console.log)
```

If we were going to build a block history feature, we would need to get a list of the most recent blocks in the chain. We can do this by fetching the most recent block and counting backwards until we have the last 10 blocks in the chain. We can do that with a `for` loop like this:

```
web3.eth.getBlockNumber().then((latest) => {
  for (let i = 0; i < 10; i++) {
    web3.eth.getBlock(latest - i).then(console.log)
  }
})
```

Web3.js has another nice feature that allows you to inspect transactions contained within a specific block. We can do that like this:

```
const hash = '0x66b3fd79a49dafe44507763e9b6739aa0810de2c15590ac22b5e2f0a3f502073'
web3.eth.getTransactionFromBlock(hash, 2).then(console.log)
```

That's how to inspect blocks with Web3.js. At this point, all of the code should look like this:

```
const Web3 = require('web3')
const web3 = new Web3('https://mainnet.infura.io/YOUR_INFURA_API_KEY')

// get latest block number
web3.eth.getBlockNumber().then(console.log)

// // get latest block
web3.eth.getBlock('latest').then(console.log)

// get latest 10 blocks
web3.eth.getBlockNumber().then((latest) => {
  for (let i = 0; i < 10; i++) {
    web3.eth.getBlock(latest - i).then(console.log)
  }
})

// get transaction from specific block
const hash = '0x66b3fd79a49dafe44507763e9b6739aa0810de2c15590ac22b5e2f0a3f502073'
web3.eth.getTransactionFromBlock(hash, 2).then(console.log)
```

Now you can run the `app.js` file from your terminal with NodeJS like this:

```
$ node app.js
```

Or simply:

```
$ node app
```

You can download all the code examples from [github](https://github.com/dappuniversity/web3_examples).

### 8 · Web3.js Utilities <a href="#id-8" id="id-8"></a>

This part is designed to show you some cool tips and tricks that you might not know about Web3.js! Let's go ahead and set up the `app.js` and jump into examining these tips. Let's connect to the Ethereum main net like this:

```
const Web3 = require('web3')
const web3 = new Web3('https://mainnet.infura.io/YOUR_INFURA_API_KEY')
```

First, you can actually get the average gas price currently for the network like this:

```
web3.eth.getGasPrice().then((result) => {
  console.log(web3.utils.fromWei(result, 'ether')
})
```

If you've developed on the blockchain before, you have probably dealt with hashing functions. Web3.js has a lot of built in helpers for using hashing functions. You have direct access to the `sha3` function like this:

```
console.log(web3.utils.sha3('Dapp University'))
```

Or as `keccack256`:

```
console.log(web3.utils.keccak256('Dapp University'))
```

You can also handle (pseudo) randomness by generating a 32 byte random hex like this:

```
console.log(web3.utils.randomHex(32))
```

Have you ever found yourself trying to perform an action on a JavaScript array or object, and needed the help of an external library? Thankfully, Web3.js ships with the underscoreJS library:

```
const _ = web3.utils._
_.each({ key1: 'value1', key2: 'value2' }, (value, key) => {
  console.log(key)
})
```

Those are some fancy tips and tricks you can use with Web3.js. Here is the complete tutorial code:

```
const Web3 = require('web3')
const web3 = new Web3('https://mainnet.infura.io/YOUR_INFURA_API_KEY')

// Get average gas price in wei from last few blocks median gas price
web3.eth.getGasPrice().then((result) => {
  console.log(web3.utils.fromWei(result, 'ether')
})

// Use sha256 Hashing function
console.log(web3.utils.sha3('Dapp University'))

// Use keccak256 Hashing function (alias)
console.log(web3.utils.keccak256('Dapp University'))

// Get a Random Hex
console.log(web3.utils.randomHex(32))

// Get access to the underscore JS library
const _ = web3.utils._

_.each({ key1: 'value1', key2: 'value2' }, (value, key) => {
  console.log(key)
})
```

Now you can run the `app.js` file from your terminal with NodeJS like this:

```
$ node app.js
```

Or simply:

```
$ node app
```

You can download all the code examples from [github](https://github.com/dappuniversity/web3_examples).


# thirdweb CLI

thirdweb provides an interactive command line interface, allowing you to create, build, and deploy your smart contracts and apps.

You can use the thirdweb CLI to create and deploy smart contracts to the Viction EVM network.

Visit [Viction's thirdweb](https://portal.thirdweb.com/cli) for more details.


# Deployment & Verification


# Hardhat

This section will guide you through deploying a smart contract on the Viction using Hardhat.

### Prerequisites[​](https://docs.linea.build/build-on-linea/quickstart/deploy-smart-contract/hardhat#prerequisites) <a href="#user-content-prerequisites" id="user-content-prerequisites"></a>

Before you begin, ensure you've:

* Download [Node v16+](https://nodejs.org/en/download/).
* An ethereum wallet.
* Funded your wallet for caring gas fee of transactions.

### Create a Hardhat project[​](https://docs.base.org/guides/deploy-smart-contracts#node-v18)

To create an empty Hardhat project, run the following commands:

```
mkdir hardhat-tomo-tutorial
cd hardhat-tomo-tutorial
npm init
npm install --save-dev hardhat
npx hardhat
```

Select `Create a TypeScript project` then press *enter* to confirm the project root.

Select `y` for both adding a `.gitignore` and loading the sample project. It will take a moment for the project setup process to complete.

### Configure hardhat with Viction

In order to deploy smart contracts to the Viction, you will need to configure your Hardhat project and add the Viction network.

To configure Hardhat to use Viction, add Viction as a network to your project's `hardhat.config.ts` file:

```typescript
import { HardhatUserConfig } from 'hardhat/config';
import '@nomicfoundation/hardhat-toolbox';

require('dotenv').config();

const config: HardhatUserConfig = {
  solidity: {
    version: '0.8.17',
  },
  networks: {
    // for mainnet
    'tomo-mainnet': {
      url: 'https://rpc.viction.xyz',
      accounts: [process.env.PRIVATE_KEY as string],
    },
    // for testnet
    'tomo-testnet': {
      url: 'https://rpc-testnet.viction.xyz',
      accounts: [process.env.PRIVATE_KEY as string],
    },
  },
  defaultNetwork: 'hardhat',
};

export default config;
```

### Install Hardhat toolbox

The above configuration uses the `@nomicfoundation/hardhat-toolbox` plugin to bundle all the commonly used packages and Hardhat plugins recommended to start developing with Hardhat.

To install `@nomicfoundation/hardhat-toolbox`, run:

```
npm install --save-dev @nomicfoundation/hardhat-toolbox
```

### Load environment variables

The above configuration also uses [dotenv](https://www.npmjs.com/package/dotenv) to load the `PRIVATE_KEY` environment variable from a `.env` file to `process.env.PRIVATE_KEY`. You should use a similar method to avoid hardcoding your private keys within your source code.

To install `dotenv`, run:

```
npm install --save-dev dotenv
```

Once you have `dotenv` installed, you can create a `.env` file with the following content:

```
PRIVATE_KEY=<YOUR_PRIVATE_KEY>
```

Substitute `<YOUR_PRIVATE_KEY>` with the private key for your wallet.

### Compile the smart contract[​](https://docs.base.org/guides/deploy-smart-contracts#compiling-the-smart-contract) <a href="#compiling-the-smart-contract" id="compiling-the-smart-contract"></a>

Below is a simple token contract (ERC20) written in the Solidity programming language:

```solidity
pragma solidity 0.8.17;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MyToken is ERC20 {
    constructor() ERC20("My Token", "MYT") {}

    function mint(address recipient, uint256 amount)
        external
        returns (uint256)
    {
        _mint(recipient, amount);
        return amount;
    }
}
```

The Solidity code above defines a smart contract named `ERC20`. The code uses the `ERC20` interface provided by the [OpenZeppelin Contracts library](https://docs.openzeppelin.com/contracts/4.x/) to create a token smart contract. OpenZeppelin allows developers to leverage battle-tested smart contract implementations that adhere to official ERC standards.

To add the OpenZeppelin Contracts library to your project, run:

```
npm install --save @openzeppelin/contracts@4.9.3
```

In your project, delete the `contracts/Lock.sol` contract that was generated with the project and add the above code in a new file called `contracts/MyToken.sol.`

To compile the contract using Hardhat, run:

```
npx hardhat compile
```

### Deploy the smart contract[​](https://docs.base.org/guides/deploy-smart-contracts#deploying-the-smart-contract) <a href="#deploying-the-smart-contract" id="deploying-the-smart-contract"></a>

Once your contract has been successfully compiled, you can deploy the contract to the Viction networks.

To deploy the contract to the Viction testnet, you'll need to modify the `scripts/deploy.ts` in your project:

```typescript
import { ethers } from 'hardhat';

async function main() {
  const gasLimit = 100_000_000;
  const myToken = await ethers.deployContract('MyToken', { gasLimit });

  await myToken.waitForDeployment();

  console.log('Token Contract Deployed at ' + myToken.target);
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});
```

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

Gas limit is required when deploying a smart contract using Hardhat in Viction
{% endhint %}

Finally, ensure your wallet has enough fund to cover gas fee and run script with command:

```
npx hardhat run scripts/deploy.ts --network tomo-testnet
```

The contract will be deployed on the Viction testnet. You can view the deployment status and contract by using [VicScan](https://scan-ui-testnet.viction.xyz/) and searching for the address returned by your deploy script. If you've deployed an exact copy of the token contract above, it will be verified, and you'll be able to read and write to the contract using the web interface.

### Verify contract on VicScan

VicScan now support contract verification via Hardhat API, you will need to change hardhat.config.ts with the following configuration:

#### Mainnet

```typescript
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";

/** @type import('hardhat/config').HardhatUserConfig */
const config: HardhatUserConfig = {
  networks: {
    Viction: {
      url: "https://rpc.viction.xyz", // for mainnet
      accounts:  ['']
    }
  },

  etherscan: {
    apiKey: {
      goerli: "",
      Viction: "tomoscan2023",
    },
    customChains: [
      {
        network: "Viction",
        chainId: 88, // for mainnet
        urls: {
          apiURL: "https://www.vicscan.xyz/api/contract/hardhat/verify", // for mainnet
          browserURL: "https://vicscan.xyz", // for mainnet

        }
      }
    ]
  }
};
```

#### Testnet

```typescript
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";

/** @type import('hardhat/config').HardhatUserConfig */
const config: HardhatUserConfig = {
  networks: {
    Viction: {
      url: "https://rpc-testnet.viction.xyz", // for testnet
      accounts:  ['']
    }
  },

  etherscan: {
    apiKey: {
      goerli: "",
      Viction: "tomoscan2023",
    },
    customChains: [
      {
        network: "victiontestnet",
        chainId: 89, // for testnet
        urls: {
          apiURL: "https://scan-api-testnet.viction.xyz/api/contract/hardhat/verify", // for testnet
          browserURL: "https://www.testnet.vicscan.xyz", // for testnet

        }
      }
    ]
  }
};
```

### Tips to verify contracts

It is recommended that the contract be deployed and verified using several files rather than a single file to let the verification process go more smoothly using the hardhat plugin.

Because verifying contracts requires compiling the source code to bytecode and comparing it to the bytecode on onchain, occasionally the source code might be a large file size, causing the compilation to take longer than usual.

It is strongly advised that those source code files be flattened into numerous files with less than 1MB each file to ensure performance and stability.

In the event the contract has previously been deployed in the single file format, but the verification procedure has failed. It is recommended that you re-deploy the contract with different file formats and continue the verification procedure.

{% hint style="info" %}
If you are still unable to verify the contract after several attempts, please upload your contract source code along with the compliation configuration to **Github** and **contact us** for assistance.
{% endhint %}


# Foundry

This section will guide smart contracts development on Viction network using Foundry tool.

### Prerequisites[​](https://docs.linea.build/build-on-linea/quickstart/deploy-smart-contract/hardhat#prerequisites) <a href="#user-content-prerequisites" id="user-content-prerequisites"></a>

Before you begin, ensure you've:

* Download [Rust](https://www.rust-lang.org/).
* An ethereum wallet.
* Funded your wallet for caring gas fee of transactions.

## Installations

You will need the [Rust](https://www.rust-lang.org/) compiler and Cargo, the Rust package manager. Install both with command:

```shell
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

Foundry generally only supports building on the latest stable Rust version. If you have an older Rust version, you can update with `rustup`:

```shell
rustup update stable
```

Install Foundryup:

```shell
curl -L https://foundry.paradigm.xyz | bash
```

Install Foundry:

```shell
foundryup
```

## Creating a Foundry Project

Run following commands:

```shell
forge init hello_foundry
cd hello_foundry
```

## Configurations

We will need some configs in the `foundry.toml` to work with Viction network.

```
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
optimizer = true
optimizer_runs = 200

[rpc_endpoints]
viction_mainnet = "https://rpc.viction.xyz/"

[etherscan]
viction_mainnet = { key="", url = "https://vicscan.xyz/api/" }

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
```

## Load environment variables

Setup `.env` file:

```
PRIVATE_KEY=<YOUR_PRIVATE_KEY>
```

Substitute **\<YOUR\_PRIVATE\_KEY>** with the private key for your wallet.

***Note:*** Requires prefixing with **`0x`**.

## Compile the smart contract

In a Foundry project, contracts will be placed at the `src/` folder. Create a simple token contract `MyToken.sol` for example:

```solidity
pragma solidity 0.8.20;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MyToken is ERC20 {
    constructor(string memory name, string memory symbol) ERC20(name, symbol) {}

    function mint(address recipient, uint256 amount)
        external
        returns (uint256)
    {
        _mint(recipient, amount);
        return amount;
    }
}
```

The Solidity code above defines a smart contract named MyToken. The code uses the ERC20 interface provided by the OpenZeppelin Contracts library to create a token smart contract. OpenZeppelin allows developers to leverage battle-tested smart contract implementations that adhere to official ERC standards.

To add the OpenZeppelin Contracts library to your project, run:

```shell
forge install OpenZeppelin/openzeppelin-contracts --no-commit
```

The Openzeppelin Contracts library is already in the `lib/openzeppelin-contracts` folder. In order to simple import contracts with alias `@openzeppelin/contracts`, add remappings to assign the library directiory with the `alias` in `foundry.toml`:

```
[profile.default]
...
remappings=[
    "@openzeppelin=lib/openzeppelin-contracts/"
]
...

```

To compile `ERC20` contract, run:

```shell
forge build
```

## Deploy the smart contract​

Once your contract has been successfully compiled, you can deploy the contract to the Viction networks.

To deploy the contract to the Viction mainnet, you'll need to add the `script/MyToken.s.sol` in the project:

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.20;

import {Script} from "forge-std/Script.sol";
import "../src/MyToken.sol";

contract MyTokenScript is Script {
    function run() public {
        uint256 privateKey = vm.envUint("PRIVATE_KEY");

        vm.startBroadcast(privateKey);
        new MyToken("My Token", "MYT");
        vm.stopBroadcast();
    }
}
```

Finally, ensure your wallet has enough fund to cover gas fee and run script with command:

```shell
forge script script/MyToken.s.sol:MyTokenScript --rpc-url viction_mainnet --legacy --broadcast
```

***Note:***

* Deployment requires flag `--legacy` because the Viction RPC currently **not supported** **EIP-1559** transactions. [Reference.](https://book.getfoundry.sh/forge/deploying)

The transaction informations will appear after running script likes this:

```
## Setting up 1 EVM.

==========================

Chain 88

Estimated gas price: 2 gwei

Estimated total gas used for script: 676986

Estimated amount required: 0.001353972 ETH

==========================
##
Sending transactions [0 - 0].
⠁ [00:00:00] [#################################################################################################################] 1/1 txes (0.0s)##
Waiting for receipts.
⠉ [00:00:07] [#############################################################################################################] 1/1 receipts (0.0s)
##### viction
✅  [Success]Hash: 0x3e2ff561e92a99e35cbd72ec707ae7642d2a87ef9c3213afbfc9544f37ee8b8f
Contract Address: 0xC9a8D9CEa9bF2450ED8082d73e8DaFC47989558E
Block: 78881479
Paid: 0.001041822 ETH (520911 gas * 2 gwei)



==========================

ONCHAIN EXECUTION COMPLETE & SUCCESSFUL.
Total Paid: 0.001041822 ETH (520911 gas * avg 2 gwei)
```

We got the success deployment with `txnHash` is `0x3e2ff561e92a99e35cbd72ec707ae7642d2a87ef9c3213afbfc9544f37ee8b8f` and the `MyToken` contract address is `0xC9a8D9CEa9bF2450ED8082d73e8DaFC47989558E`. We can check its on [VicScan](https://scan-ui-testnet.viction.xyz/).

## Verify contract on VicScan

The first, we need to create a `json` file that contains arguments of contructor when deploy contract. File path: `./script/arguments.json`:

```json
["My Token", "MYT"]
```

Run below commands to verify contract on VicScan:

* For mainnet:

```shell
forge verify-contract 0xC9a8D9CEa9bF2450ED8082d73e8DaFC47989558E MyToken --etherscan-api-key none --verifier-url https://vicscan.xyz/api/contract/foundry/verify --constructor-args-path ./script/arguments.json
```

* For testnet:

```shell
forge verify-contract 0xC9a8D9CEa9bF2450ED8082d73e8DaFC47989558E MyToken --etherscan-api-key none --verifier-url https://testnet.vicscan.xyz/api/contract/foundry/verify --constructor-args-path ./script/arguments.json
```

The successful verification will show:

```shell
Start verifying contract `0xC9a8D9CEa9bF2450ED8082d73e8DaFC47989558E` deployed on mainnet

Submitting verification for [src/MyToken.sol:MyToken] 0xC9a8D9CEa9bF2450ED8082d73e8DaFC47989558E.
Submitted contract for verification:
        Response: `OK`
        GUID: `Pass - Verified`
        URL: https://viscan.io/address/0xc9a8d9cea9bf2450ed8082d73e8dafc47989558e
```


# DApp Development

This section contains resources for Dapp development - back-end/front-end APIs, tools, and useful tutorials.

{% content-ref url="/pages/Init5nbT1y4mjd7v1BMQ" %}
[Smart Contract Development](/smart-contract-development)
{% endcontent-ref %}

{% content-ref url="/pages/Nt05RNsDzgV8X6YYTIqa" %}
[Standards & Specification](/smart-contract-development/standards-and-specification)
{% endcontent-ref %}

{% content-ref url="/pages/uypY62PPfxBc7uQJJlkd" %}
[Walkthrough: Build a Dapp on Viction](/developer-guide/build-a-dapp-on-viction)
{% endcontent-ref %}

{% content-ref url="/pages/RafbI1Q6hqs2AZ2qjAu8" %}
[Deploy on Viction](/archive/deploy-on-viction)
{% endcontent-ref %}

{% content-ref url="/pages/f05GFbCDlR8dr3u7IvDT" %}
[Integration](/developer-guide/integration)
{% endcontent-ref %}

{% content-ref url="/pages/DxTuItMNChHFQXRiIjjM" %}
[Archive](/archive)
{% endcontent-ref %}


# Integration

Viction Integration: A Step-By-Step Guide

{% content-ref url="/pages/VfHSwFn42kay0aKZBVYJ" %}
[Exchange/Wallet integration](/developer-guide/integration/exchange-wallet-integration)
{% endcontent-ref %}

{% content-ref url="/pages/qmcHGe32z0wB7k1lLDNO" %}
[Viction Staking Governance](/developer-guide/integration/viction-staking-governance)
{% endcontent-ref %}

{% content-ref url="/pages/j9IDfNKjjXiT8xcvezix" %}
[VIC ZeroGas](/developer-guide/integration/vic-zerogas-integration)
{% endcontent-ref %}

{% content-ref url="/pages/g20l1JxlbT4uSfuvp3mH" %}
[VRC25 Exchange/Wallet integration](/developer-guide/integration/vrc25-exchange-wallet-integration)
{% endcontent-ref %}


# Exchange/Wallet integration

Viction is an EVM-compatible public blockchain. So you can use [Viction JSON-RPC APIs](https://apidocs.tomochain.com/#Viction-apis-json-rpc) similar as in Ethereum.

EVM compatible libraries such as [Web3.js](/smart-contract-development/ides-and-tools/web3js) or [Ethers.js](/smart-contract-development/ides-and-tools/ethers.js) library can be fully reused in integration to create a wallet, check wallet balances, or create/send transactions. All you need is to connect to Viction's RPC public endpoint. [This tutorial](https://github.com/BuildOnViction/gitbook/blob/main/developer-guide/working-with-Viction/README.md) will guide you the steps to connect to Viction Testnet/Mainnet using Web3.js.

### Connect to Viction's public RPC endpoint <a href="#connect-to-viction-nodes" id="connect-to-viction-nodes"></a>

```javascript
import Web3 from 'web3';

const web3 = new Web3('https://rpc.viction.xyz');
```

### Create a wallet <a href="#create-wallet" id="create-wallet"></a>

Generate an account object with private key and public key.

```javascript
web3.eth.accounts.create([entropy]);
```

**Example**

```javascript
web3.eth.accounts.create();
> {
    address: "0xb8CE9ab6943e0eCED004cDe8e3bBed6568B2Fa01",
    privateKey: "0x348ce564d427a3311b6536bbcff9390d69395b06ed6c486954e971d960fe8709",
    signTransaction: function(tx){...},
    sign: function(data){...},
    encrypt: function(password){...}
}

web3.eth.accounts.create('2435@#@#@±±±±!!!!678543213456764321§34567543213456785432134567');
> {
    address: "0xF2CD2AA0c7926743B1D4310b2BC984a0a453c3d4",
    privateKey: "0xd7325de5c2c1cf0009fac77d3d04a9c004b038883446b065871bc3e831dcd098",
    signTransaction: function(tx){...},
    sign: function(data){...},
    encrypt: function(password){...}
}

web3.eth.accounts.create(web3.utils.randomHex(32));
> {
    address: "0xe78150FaCD36E8EB00291e251424a0515AA1FF05",
    privateKey: "0xcc505ee6067fba3f6fc2050643379e190e087aeffe5d958ab9f2f3ed3800fa4e",
    signTransaction: function(tx){...},
    sign: function(data){...},
    encrypt: function(password){...}
}
```

### Check wallet balances <a href="#wallet-balances" id="wallet-balances"></a>

Get account balance.

```javascript
web3.eth.getBalance(address [, defaultBlock] [, callback])
```

**Example**

```javascript
web3.eth.getBalance("0x407d73d8a49eeb85d32cf465507dd71d507100c1").then(console.log);
> "1000000000000"
```

### Create transaction <a href="#create-transaction" id="create-transaction"></a>

Send transaction to the network. You need to unlock wallet before using this function.

```javascript
web3.eth.sendTransaction(transactionObject [, callback])
```

**Parameters**

1. Object - The transaction object to send:
   * `from` - `String|Number`: The address for the sending account. Uses the web3.eth.defaultAccount property, if not specified. Or an address or index of a local wallet in web3.eth.accounts.wallet.
   * `to` - `String`: (optional) The destination address of the message, left undefined for a contract-creation transaction.
   * `value` - `Number|String|BN|BigNumber`: (optional) The value transferred for the transaction in wei, also the endowment if it’s a contract-creation transaction.
   * `gas` - `Number`: (optional, default: To-Be-Determined) The amount of gas to use for the transaction (unused gas is refunded).
   * `gasPrice` - `Number|String|BN|BigNumber`: (optional) The price of gas for this transaction in wei, defaults to web3.eth.gasPrice.
   * `data` - `String`: (optional) Either a ABI byte string containing the data of the function call on a contract, or in the case of a contract-creation transaction the initialisation code.
   * nonce - `Number`: (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce.
2. `callback` - `Function`: (optional) Optional callback, returns an error object as first parameter and the result as second.

**Example**

```javascript
const Web3 = require('web3')

// Connect to Viction nodes
const provider = new Web3.providers.HttpProvider('https://rpc.viction.xyz')
const web3 = new Web3(provider)

// Unlock wallet by private key
const account = web3.eth.accounts.privateKeyToAccount(pkey)
let coinbase = account.address
web3.eth.accounts.wallet.add(account)
web3.eth.defaultAccount = coinbase

// Make a transaction using the promise
web3.eth.sendTransaction({
    from: coinbase,
    to: '0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe',
    value: '1000000000000000'
})
.then(function(receipt){
    ...
});
```

### Sign data <a href="#sign-data" id="sign-data"></a>

After unlock a wallet, you can sign some data

```javascript
web3.eth.sign(dataToSign, address [, callback])
```

**Parameters**

1. `String` - Data to sign. If String it will be converted using `web3.utils.utf8ToHex`.
2. `String|Number` - Address to sign data with. Or an address or index of a local wallet in `web3.eth.accounts.wallet`.
3. `Function` - (optional) Optional callback, returns an error object as first parameter and the result as second.

**Example**

```javascript
const Web3 = require('web3')

// Connect to Viction nodes
const provider = new Web3.providers.HttpProvider('https://rpc.viction.xyz')
const web3 = new Web3(provider)

// Unlock wallet by private key
const account = web3.eth.accounts.privateKeyToAccount(pkey)
let coinbase = account.address
web3.eth.accounts.wallet.add(account)
web3.eth.defaultAccount = coinbase

// Make a transaction using the promise
web3.eth.sign('testdata').then(function(result){
    console.log(result)
});
```

### Check transaction status <a href="#check-transaction-status" id="check-transaction-status"></a>

```javascript
web3.eth.getTransactionReceipt(hash [, callback])
```

> The receipt is not available for pending transactions and returns null.

**Parameters**

1. String - The transaction hash.
2. Function - (optional) Optional callback, returns an error object as first parameter and the result as second.

**Returns**

Promise returns Object - A transaction receipt object, or null when no receipt was found:

* `status` - `Boolean`: `TRUE` if the transaction was successful, `FALSE`, if the EVM reverted the transaction.
* `blockHash` 32 Bytes - `String`: Hash of the block where this transaction was in.
* `blockNumber` - `Number`: Block number where this transaction was in.
* `transactionHash` 32 Bytes - `String`: Hash of the transaction.
* `transactionIndex` - `Number`: Integer of the transactions index position in the block.
* `from` - `String`: Address of the sender.
* `to` - `String`: Address of the receiver. null when its a contract creation transaction.
* `contractAddress` - `String`: The contract address created, if the transaction was a contract creation, otherwise null.
* `cumulativeGasUsed` - `Number`: The total amount of gas used when this transaction was executed in the block.
* `gasUsed` - `Number`: The amount of gas used by this specific transaction alone.
* `logs` - `Array`: Array of log objects, which this transaction generated.

### Irreversible blocks <a href="#irreversible-blocks" id="irreversible-blocks"></a>

In normal case, you can wait for 60 confirmations, then checking block finality via `eth_getBlockFinalityByNumber` or `eth_getBlockFinalityByHash` API:

* [eth\_getBlockFinalityByNumber](https://apidocs.tomochain.com/#eth_getblockfinalitybynumber)
* [eth\_getBlockFinalityByHash](https://apidocs.tomochain.com/#eth_getblockFinalitybyhash)

If `result` >= 75, it means the block with the input hash is finalized, thus irreversible.

### How does Viction smart contract work? <a href="#how-does-viction-smart-contract-work" id="how-does-viction-smart-contract-work"></a>

Viction supports Solidity compiler version <= 0.8.17

### Does Viction support multi-signature wallets? <a href="#possible-to-create-muti-signature-wallet" id="possible-to-create-muti-signature-wallet"></a>

Yes. Similar to Ethereum, you can use Gnosis MultiSigWallet.

### Run Viction node <a href="#run-viction-node" id="run-viction-node"></a>

Please check [Run Viction Fullnode](/masternode/run-a-full-node) for details how to run a Viction full node.


# VRC25 Exchange/Wallet integration

This tutorial will walk through integrating TRC2 tokens to applications (e.g., wallet, exchange)

### **Prerequisites**

Contract ABI: [IVRC25.json](https://raw.githubusercontent.com/Viction/trc25/main/metadata/IVRC25.json)

Contract Interface: [IVRC25.sol](https://github.com/BuildOnViction/trc25/raw/main/contracts/interfaces/IVRC25.sol)

```solidity
interface IVRC25 {
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
    event Fee(address indexed from, address indexed to, address indexed issuer, uint256 value);

    function decimals() external view returns (uint8);
    function totalSupply() external view returns (uint256);
    function balanceOf(address owner) external view returns (uint256);
    function issuer() external view returns (address);
    function allowance(address owner, address spender) external view returns (uint256);
    function estimateFee(uint256 value) external view returns (uint256);
    function transfer(address recipient, uint256 value) external returns (bool);
    function approve(address spender, uint256 value) external returns (bool);
    function transferFrom(address from, address to, uint256 value) external  returns (bool);
}
```

Users are recommended to refer to the [VRC25 Specification](/smart-contract-development/standards-and-specification/vrc25-specification) for more details about the VRC25 token standard.

Follow the steps below to interact with the smart contract by using the Web3 library and Node.

### Initialize Web3 provider <a href="#init-web3-provider" id="init-web3-provider"></a>

As a first step, we need to initialize a Web3 provider by connecting to Viction Full node RPC endpoint.

Look at the [Viction Networks](https://github.com/BuildOnViction/gitbook/blob/main/developer-guide/working-with-Viction/README.md) page to get more information of the Viction Testnet/Mainnet RPC network.

```javascript
const Web3 = require('web3')
const web3 = new Web3('https://rpc.viction.xyz')
const chainId = 88
```

### Unlock wallet <a href="#unlock-wallet" id="unlock-wallet"></a>

Unlock the wallet before interacting with VRC25 token contracts

**Example**

```javascript
// Unlock wallet by private key
const account = web3.eth.accounts.privateKeyToAccount(pkey)
const holder = account.address
web3.eth.accounts.wallet.add(account)
web3.eth.defaultAccount = holder
```

### Initialize Web3 VRC25 Contract <a href="#init-web3-trc21-contract" id="init-web3-trc21-contract"></a>

```javascript
const trc25Abi = require('./IVRC25.json')
const address = '[enter_your_contract_address]'
const trc25 = new web3.eth.Contract(trc25Abi,
        address, {gasPrice: 250000000, gas: 2000000 })
```

Note: Get IVRC21.json [here](https://raw.githubusercontent.com/Viction/trc25/main/metadata/IVRC25.json).

### Check balance <a href="#check-balance" id="check-balance"></a>

Call function `balanceOf()` from VRC25 contract to check the token balance for an address.

**Example**

```javascript
trc25.methods.balanceOf(holder).call()
.then((result) => {
    console.log(result)
}).catch(e => console.log(e))
```

### Estimate fee <a href="#estimate-fee" id="estimate-fee"></a>

Before sending tokens, we need to check TX fee by calling `estimateFee` function in VRC25 smart contract.

**Example**

```javascript
trc25.methods.estimateFee().call()
.then((result) => {
    console.log(result)
}).catch(e => console.log(e))
```

Note: this fee is the amount of the token that needs to be paid to send the VRC25 token applied to VIC ZeroGas

### Transfer token <a href="#transfer-token" id="transfer-token"></a>

The Token holder needs to call function `transfer` to send token to an address.

**Example**

```javascript
// send 500000000000000000000 tokens to this address (e.g decimals 18)
const to = "0xf8ac9d5022853c5847ef75aea0104eed09e5f402"
trc25.methods.transfer(to, '500000000000000000000').send({
    from: holder,
    gas: 2000000,
    gasPrice: 250000000,
    chainId: chainId
})
.then((result) => {
    console.log(result)
}).catch(e => console.log(e))
```

### Checking VIC ZeroGas <a href="#checking-vic-zerogas" id="checking-vic-zerogas"></a>

Call `getTokenCapacity` to [0x8c0faeb5c6bed2129b8674f262fd45c4e9468bee](https://vicscan.xyz/address/0x8c0faeb5c6bed2129b8674f262fd45c4e9468bee). If the return value > 0, the token has successfully been enabled by the VIC ZeroGas protocol.


# Viction Staking Governance

Masternodes and Voters' funds are locked and governed in the [Viction Validator smart contract](https://vicscan.xyz/address/0x0000000000000000000000000000000000000088):

* Smart Contract Code: [Viction Validator](https://github.com/BuildOnViction/tomomaster/blob/master/contracts/TomoValidator.sol)
* Smart Contract ABI: [TomoValidatorAbi.json](https://raw.githubusercontent.com/Viction/tomomaster/master/abis/TomoValidatorAbi.json)

Viction Validator Smart Contract Interface:

```solidity
// apply a new masternode candidate
function propose(address _candidate) external payable;

// Deposit to stake/vote for a candidate
function vote(address _candidate) external payable;

// Unstake/unvote for a candidate
function unvote(address _candidate, uint256 _cap) public;

// Resign a candidate
function resign(address _candidate) public;

// Withdraw after unvote, resign
function withdraw(uint256 _blockNumber, uint _index) public;

function getCandidates() public view returns(address[]);

function getCandidateCap(address _candidate) public view returns(uint256);

function getCandidateOwner(address _candidate) public view returns(address);

function getVoterCap(address _candidate, address _voter) public view returns(uint256);

function getVoters(address _candidate) public view returns(address[]);

function isCandidate(address _candidate) public view returns(bool);

function getWithdrawBlockNumbers() public view returns(uint256[]);

function getWithdrawCap(uint256 _blockNumber) public view returns(uint256);
```

Viction provides RPC APIs that can be used with Web3 library to directly call the functions in the smart contract.

You can follow the steps below to interact with the smart contract by using Web3 library and NodeJS.

\
**Init Web3 Provider**

At the first step, you need init Web3 provider by connecting Viction Fullnode RPC endpoint.

```javascript
const Web3 = require('web3')
const web3 = new Web3('https://rpc.viction.xyz')
const chainId = 88
```

For testnet/mainnet details, you can get network information [here](https://github.com/BuildOnViction/gitbook/blob/main/developer-guide/working-with-Viction/README.md)

### Unlock Wallet <a href="#unlock-wallet" id="unlock-wallet"></a>

Unlock the wallet must be done before staking on the nodes

**Example**

```javascript
// Unlock wallet by private key
const account = web3.eth.accounts.privateKeyToAccount(pkey)
const owner = account.address
web3.eth.accounts.wallet.add(account)
web3.eth.defaultAccount = owner
```

### Init Web3 Viction Validator Contract <a href="#init-web3-viction-validator-contract" id="init-web3-viction-validator-contract"></a>

```javascript
const validatorAbi = require('./TomoValidatorAbi.json')
const address = '0x0000000000000000000000000000000000000088'
const validator = new web3.eth.Contract(validatorAbi,
        address, {gasPrice: 250000000, gas: 2000000 })
```

Note: you can get TomoValidatorAbi.json [here](https://raw.githubusercontent.com/Viction/tomomaster/master/abis/TomoValidatorAbi.json)

### Propose/Apply a Candidate <a href="#proposeapply-a-candidate" id="proposeapply-a-candidate"></a>

Masternode owners need to have at least 50,000 VIC to apply to become a Masternode Candidate. Make sure to have > 50,000 VIC in the Masternode owner wallet in order to deposit it into the smart contract and pay the related transaction fee.

Apply to become a Masternode Candidate by calling `propose` function from the smart contract

**Example**

```javascript
// Masternode coinbase address
const coinbase = "0xf8ac9d5022853c5847ef75aea0104eed09e5f402"

validator.methods.propose(coinbase).send({
    from : owner,
    value: '50000000000000000000000', // 50000 VIC
    gas: 2000000,
    gasPrice: 250000000,
    chainId: chainId
})
.then((result) => {
    console.log(result)
}).catch(e => console.log(e))
```

Refer to [Staking Viction script](https://gist.github.com/thanhson1085/7a6471ea0d6c0d6321a0454789d6266c)

### Stake/Vote for a Candidate <a href="#stakevote-a-candidate" id="stakevote-a-candidate"></a>

Stake at least 100 VIC for a node by calling `vote` function from the smart contract.

**Example**

Stake 500 VIC to a node.

```javascript
validator.methods.vote(coinbase).send({
    from: owner,
    value: '500000000000000000000', // 500 VIC
    gas: 2000000,
    gasPrice: 250000000,
    chainId: chainId
})
.then((result) => {
    console.log(result)
}).catch(e => console.log(e))
```

### Unstake/Unvote a Candidate <a href="#unstakeunvote-a-candidate" id="unstakeunvote-a-candidate"></a>

You can unstake by calling `unvote` function from the smart contract

```javascript
const cap = '500000000000000000000' // unvote 500 VIC

validator.methods.unvote(coinbase, cap).send({
    from : owner,
    gas: 2000000,
    gasPrice: 250000000,
    chainId: chainId
})
.then((result) => {
    console.log(result)
}).catch(e => console.log(e))
```

### Resign a Candidate <a href="#resign-a-candidate" id="resign-a-candidate"></a>

```javascript
validator.methods.resign(coinbase).send({
    from : owner,
    gas: 2000000,
    gasPrice: 250000000,
    chainId: chainId
})
.then((result) => {
    console.log(result)
}).catch(e => console.log(e))
```

### Withdraw VIC <a href="#withdraw-tomo" id="withdraw-tomo"></a>

You need to wait for 96 epochs (to unvote), 30 days (to resign) to unlock your staked VIC

**Example**

```javascript
// get highest block number
web3.eth.getBlockNumber().then(blockNumber => {
    return validator.methods.getWithdrawBlockNumbers().call({
        from: owner
    }).then((result) => {
        let map = result.map(it, idx => {
            it = it.toString()
            if (parseInt(it) < blockNumber && it != "0") {
                return validator.methods.withdraw(it, idx).send({
                    from : owner,
                    gas: 2000000,
                    gasPrice: 250000000,
                    chainId: chainId
                })
            }
        })
        return Promise.all(map)
    })
}).then((result) => {
    console.log(result)
}).catch(e => console.log(e))
```

### Get list Withdrawals <a href="#get-list-withdrawals" id="get-list-withdrawals"></a>

We need to call `getWithdrawBlockNumbers` and `getWithdrawCap` functions from TomoValidator smart contract to get the data

**Example**

```javascript
let blks = await contract.getWithdrawBlockNumbers.call({ from: owner })
// remove duplicate
blks = [...new Set(blks)]
let withdraws = []

await Promise.all(blks.map(async (it, index) => {
    let blk = new BigNumber(it).toString()
    if (blk !== '0') {
        self.aw = true
    }
    let wd = {
        blockNumber: blk
    }
    wd.cap = await contract.methods.getWithdrawCap(blk).call({ from: owner })
    withdraws[index] = wd
}))
console.log(withdraws)
```

### Get list Candidates <a href="#get-list-candidates" id="get-list-candidates"></a>

You can get list Candidates from [RPC endpoint](https://apidocs.tomochain.com/?shell#eth_getcandidates):

```bash
curl https://rpc.viction.xyz \
    -X POST \
    -H "Content-Type: application/json" \
    -d '{"jsonrpc":"2.0","method":"eth_getCandidates","params": ["latest"],"id":1}'
```

Or [get list candidates from VicMaster](https://apidocs.tomochain.com/?shell#tomomaster-apis-candidates):

```bash
curl -X GET https://vicmaster.xyz/api/candidates \
  -H 'Accept: application/json'
```


# VIC ZeroGas

VIC ZeroGas is the runtime feature to perform gas-less transaction with VRC25 token

### How it works

* VIC ZeroGas enables gas-less transaction for VRC25 by requiring the owner to deposit VIC to VRC25Issuer contract. So when there is transaction call to VRC25 token, the gas fee will be paid by the owner. Please note that internal call to VRC25 token won't be gas-sponsored.
* The owner of VRC25 token must call `apply` function of `VRC25Issuer` contract at <https://www.vicscan.xyz/address/0x8c0faeb5c6bed2129b8674f262fd45c4e9468bee> after deployment in order to register for VIC ZeroGas. If a contract didn't register VIC ZeroGas yet, the transaction fee must be paid by the user who perform the transaction.
* When the VIC for the VRC25 token is exhausted, user will pay gas for it normally unless the owner deposit more VIC.

### Requirement

* Smart-contract that meet [VRC25 Specification](/smart-contract-development/standards-and-specification/vrc25-specification).
* 10 VIC for first time registration.

### How to apply (mainnet)

The owner of VRC25 token must call `apply` function of `VRC25Issuer` contract at&#x20;

<https://www.vicscan.xyz/address/0x8c0faeb5c6bed2129b8674f262fd45c4e9468bee>

### How to apply (testnet)

The owner of VRC25 token must call `apply` function of `VRC25Issuer` contract at <https://testnet.vicscan.xyz/address/0x8c0faeb5c6bed2129b8674f262fd45c4e9468bee>

The VIC testnet token can be found via faucet:  <https://faucet-testnet.viction.xyz/>

The VICIssuer testnet: <https://issuer-testnet.viction.xyz/>

The [source code](https://github.com/BuildOnViction/trc25/raw/main/contracts/tests/VRC25Issuer.sol) and [ABI](https://github.com/BuildOnViction/trc25/raw/main/metadata/VRC25Issuer.json) for VRC25Issuer contract can be found in [VRC25 repository](https://github.com/BuildOnViction/vrc25).


# VRRF

Viction VRRF, which stands for Verifiable Relatively Random Function, is a pseudo-random number generator that is both verifiable and provably fair.

## Get Started

In decentralized blockchain, random number generator (RNG) is essential recipe in developing application, especially in gaming application. Verifiable Random Function (VRF) in the recent years become a familiar concept for smart contract developers. In an effort to create a lightweight solution for smart contract developers to get random numbers, Viction Team is pleased to intro VRRF, a pseudo-random number generator.

With simplicity in mind, VRRF is designed as pseudo-random number generator, which is not perfect in term of probability distribution, but still extremely hard to be manipulated. In exchange for the absent of true random, VRRF enable calling smart-contracts to get random number with lighting fast speed and within one transaction only.

VRRF is an ideal solution for application that isn't too strict on probability distribution but still want to have a manipulation-resistant number to use as source of random number for the application itself. All the processes are fully on-chain and simple APIs make it easier to integration into any application.

## Features

VRRF creates a pseudo-random number based on mathematical and cryptographic techniques. Every request call to VRRF and its result will be processed and stored by the blockchain. Therefore, they are protected from being modified or controlled by any one party, including oracle operators, miners, users, or creators of smart contracts.

**Verifiable**: The random number created by VRRF is deterministic, with the same set of inputs, will result in the same output.

**Relatively**: This is where VRRF is different from other VRF solution. VRRF makes use of parts of previous result combined with many on-chain parameters and user inputted salt to feed into the random function. Because of this characteristic, *the order of calling VRRF in block can make the output more unpredictable*.

**Random**: The output of VRRF is presoudo-random and manipulation resistant number. With the length of 256-bit, it's sufficient for most applications' needs.

**Function**: At its heart is the function that utilized mathematical and cryptography techniques generate the random number.

## APIs

To integrate with VRRF, you will simply need to call `random(bytes32 salt)` function. Both of them return a 256-bit number, which is large enough to serve any application the developers may want.

```solidity
interface IVRRF {
  /**
   * @notice Get pseudo-random number base on provided seed
   * @param salt Random data as an additional input to harden the random
   */
  function random(bytes32 salt) external returns(bytes32);
}
```

The API is available at the following address in Viction:

* Mainnet: 0x53eDcf19e4fb242c9957CB449d2d4106fD760A7F
* Testnet: 0xDb14c007634F6589Fb542F64199821c3308A9d92

{% hint style="info" %}
For unit-testing, please implement a mock version of IVRRF in your test.
{% endhint %}

## Use cases

VRRF may be utilized to construct trustworthy smart contracts for any applications that are dependent on the possibility of unforeseen results:\
Responsibilities and resources are distributed at random. For instance, customer service members are assigned to any tickets or tele-sale support activities.

* By utilizing VRRF, it is possible to generate distinct attributes for NFTs, adding a touch of uniqueness to the minting process. Game Studio can use this to assign a unique set of characteristics through a randomized process.
* Developers have the ability to create more enjoyable blockchain games by using random results, which are unpredictable.
* Lottery system to select winners at random. With VRRF, users will be able to verify that each winner is picked using a random source that is not biased in any way.

## Cost

At Viction, we believed that the VRRF should be **free** and **accessible** to everyone. So, any user may utilize this feature to construct what they want while enjoying a frictionless journey to Web3.

## Notices

* Due to the fact that VRRF relies on the order of calling transaction, protocols who make use of VRRF must wait for a short period of time (say 8-10 seconds) before displaying random result to end-users to avoid issues related to block re-org.


# Data and analytics

## Introduction

As the network usage expands, the volume of valuable on-chain data will significantly increase. With this rapid data growth, the task of calculating and aggregating this information to generate reports or power a decentralized application (dApp) can become increasingly time-consuming and resource-intensive.

By utilizing established data providers, developers can accelerate their development processes, achieve more accurate results, and minimize the efforts required for ongoing maintenance. This approach allows development teams to focus on delivering the core functionalities of their projects, rather than getting bogged down by the complexities of data management. Leveraging these external data solutions ensures that teams can efficiently harness the wealth of on-chain data, driving innovation and enhancing the performance and reliability of their dApps.

## Prerequisites

To effectively use block explorers within the context of data analytics, it is essential to grasp their basic concepts. **Block explorers** provide a user-friendly interface for accessing and navigating blockchain data, which is crucial for extracting meaningful insights.

Additionally, gaining a solid understanding of indexing is important, as indexes significantly enhance system design by optimizing data retrieval processes. Indexes allow for faster and more efficient queries, which is particularly beneficial in handling large volumes of blockchain data.

From an architectural standpoint, it is also beneficial to understand the fundamentals of **APIs (Application Programming Interfaces)** and **REST (Representational State Transfer)**. Even a theoretical knowledge of these concepts can be invaluable. **APIs** enable different software applications to communicate with each other, while **REST** is a widely-used architectural style for designing networked applications. Together, they play a crucial role in developing robust and scalable systems for blockchain data analytics. Familiarity with these concepts will provide a solid foundation for leveraging block explorers and data indexing effectively in your projects.

## SubQuery Network <a href="#subquery-network" id="subquery-network"></a>

SubQuery is a premier data indexing service that provides developers with fast, reliable, decentralized, and customizable APIs tailored for their Web3 projects. By leveraging SubQuery, developers gain access to rich, indexed data from over 100+ ecosystems, including **Viction**. This enables them to create intuitive and immersive user experiences. The SubQuery Network ensures the resilience and decentralization of your applications by offering a robust infrastructure network. With SubQuery's comprehensive blockchain developer toolkit, you can focus on building the next generation of Web3 applications without the need to invest time and resources into developing a custom backend for data processing activities. This empowers developers to innovate and deploy unstoppable applications efficiently and effectively.

One of SubQuery's significant competitive advantages is its capability to aggregate data not only within a single blockchain but also across multiple blockchains, all within a single project. This cross-chain data aggregation enables developers to create advanced, feature-rich analytics dashboards and multi-chain block explorers. By consolidating data from various blockchains, SubQuery allows for comprehensive insights and real-time analytics, providing a unified view of blockchain activities. This functionality is particularly valuable for developers looking to build sophisticated tools and applications that require seamless integration and analysis of data from multiple blockchain networks, thereby enhancing the overall user experience and utility of their Web3 projects.

To get started, use the [Viction starter](https://github.com/subquery/ethereum-subql-starter/tree/main/Viction/viction-starter) and begin indexing Viction blockchain data in minutes. It is advised to first start with the [quick start guide](https://academy.subquery.network/indexer/quickstart/quickstart.html). Otherwise, further information may be obtained [here](https://academy.subquery.network/).

## Goldsky Subgraph

Goldsky is the go-to data indexer for web3 builders, offering high-performance subgraph hosting and realtime data replication pipelines.

Goldsky provides a completely backwards-compatible subgraph indexing solution. The core of the indexing uses exactly the same WASM processing layer, but in addition, Goldsky offers:

* a rewritten RPC layer, autoscaling query layer, and storage optimizations to improve reliability (99.9%+ uptime) and performance (up to 6x faster)
* webhooks support out-the-box to enable notifications, messaging, and other push-based use cases
* support for custom EVM chains so you can index your own rollup or private blockchain seamlessly

You can query Viction blocks easily using this endpoint

<https://api.goldsky.com/api/public/project_cld6kdj9u539w0htd50sbeqyz/subgraphs/viction-blocks/1.0/gn>

## The Graph

Getting historical data on a smart contract can be frustrating when you’re building a dApp. [The Graph](https://thegraph.com/) provides an easy way to query smart contract data through APIs known as subgraphs. The Graph’s infrastructure relies on a decentralized network of indexers, enabling your dapp to become truly decentralized.

### Quick Start[​](https://docs.fuse.io/developers/subgraphs#quick-start)

These subgraphs only take a few minutes to set up and get running. To get started, follow these three steps:

1. Initialize your subgraph project
2. Deploy & Publish
3. Query from your dapp

Pricing: All developers receive 100,000 free queries per month on the decentralized network. After these free queries, you only pay based on usage at $2 for every 100,000 queries.

Here’s a step-by-step walkthrough:

### 1. Initialize your subgraph project[​](https://docs.fuse.io/developers/subgraphs#1-initialize-your-subgraph-project)

#### Create a subgraph on Subgraph Studio⁠[​](https://docs.fuse.io/developers/subgraphs#create-a-subgraph-on-subgraph-studio)

Go to the [Subgraph Studio](https://thegraph.com/studio/) and connect your wallet. Once your wallet is connected, you can begin by clicking “Create a Subgraph”. It is recommended to use Title Case: “Subgraph Name Chain Name.”

![Create a Subgraph](https://lh7-rt.googleusercontent.com/docsz/AD_4nXec0i1XMpKLaNsJKKxKIE2CksezUDgJVNzYhte_meraAOr8YlLqG9YryTYc6dlEmEume_fhXAIdqruBUCITAZcJTzw2WwHGucq6UsotS4oIZUeIEyIGDK-UASG3Zifypzz9aM5h?key=ZR7I2qHpTceitGesCDnDjg4E)

You will then land on your subgraph’s page. All the CLI commands you need will be visible on the right side of the page:

![CLI commands](https://lh7-rt.googleusercontent.com/docsz/AD_4nXduXmDd9YeX1g3fbTxXpzc1glbPQJKxb2Weo4atzNSzidZFoTU6vQgkjGxFyNWORQ8SLeu1OoSdtqvQjpmgVFDDjZt5gbAa716isMAQRoxKbXvVJYBO9gtrPI9XbUhPmJlQRGOEhw?key=ZR7I2qHpTceitGesCDnDjg4E)

#### Install the Graph CLI⁠[​](https://docs.fuse.io/developers/subgraphs#install-the-graph-cli)

On your local machine run the following:

```
npm install -g @graphprotocol/graph-cli
```

#### Initialize your Subgraph⁠[​](https://docs.fuse.io/developers/subgraphs#initialize-your-subgraph)

You can copy this directly from your subgraph page to include your specific subgraph slug:

```
graph init <SUBGRAPH_SLUG>// Some code
```

You’ll be prompted to provide some info on your subgraph like this:

![cli sample](https://lh7-rt.googleusercontent.com/docsz/AD_4nXe_aM9tHEhv3E_IbROEt80-QVTIOn3Ei3_Hci6qywQuOztCvb1c93M_aqSVgwr2Wmst6B4o5gd_wcInMSm24j1rx0vboZblz_smTtsu3dHW06u5WP8Bo34x62U1cxfwFaoUziF2cg?key=ZR7I2qHpTceitGesCDnDjg4E)

Simply have your contract verified on the block explorer and the CLI will automatically obtain the ABI and set up your subgraph. The default settings will generate an entity for each event.

### 2. Deploy & Publish[​](https://docs.fuse.io/developers/subgraphs#2-deploy--publish)

#### Deploy to Subgraph Studio⁠[​](https://docs.fuse.io/developers/subgraphs#deploy-to-subgraph-studio)

First run these commands:

```
$ graph codegen
$ graph build
```

Then run these to authenticate and deploy your subgraph. You can copy these commands directly from your subgraph’s page in Studio to include your specific deploy key and subgraph slug:

```
$ graph auth <DEPLOY_KEY>
$ graph deploy <SUBGRAPH_SLUG>
```

You will be asked for a version label. You can enter something like v0.0.1, but you’re free to choose the format.

#### Test your subgraph⁠[​](https://docs.fuse.io/developers/subgraphs#test-your-subgraph)

You can test your subgraph by making a sample query in the playground section. The Details tab will show you an API endpoint. You can use that endpoint to test from your dapp.

![Playground](https://lh7-rt.googleusercontent.com/docsz/AD_4nXfFIngodCrLIYreEz-K-0t-HA-BpC0CN7Akomckev34aqh16nmKtkaik_5mwFF_TZoAMk5YOg-oMNiWNf4tr8Nrzvr6vZRvU2rqbk2km03ygiWYkNX8ZDUNxw0fi5gNdbdSBYKYNw?key=ZR7I2qHpTceitGesCDnDjg4E)

#### Publish Your Subgraph to The Graph’s Decentralized Network[​](https://docs.fuse.io/developers/subgraphs#publish-your-subgraph-to-the-graphs-decentralized-network)

Once your subgraph is ready to be put into production, you can publish it to the decentralized network. On your subgraph’s page in Subgraph Studio, click on the Publish button:

![publish button](https://lh7-rt.googleusercontent.com/docsz/AD_4nXf4STljAjkXLSj8XzVtP3YP8kXtQYQ1NEsB1yWMyqZsIiHpTLaLYCY07Tmp0mYRn8unKIF7WTFJAFov3VGEfULHMM6tpxKnHAlaPtPV-maRWp6hn1Nvg6FsNCfjWwDzEvJR87A2RA?key=ZR7I2qHpTceitGesCDnDjg4E)

Before you can query your subgraph, Indexers need to begin serving queries on it. In order to streamline this process, you can curate your own subgraph using GRT.

When publishing, you’ll see the option to curate your subgraph. As of May 2024, it is recommended that you curate your own subgraph with at least 3,000 GRT to ensure that it is indexed and available for querying as soon as possible.

![Publish screen](https://lh7-rt.googleusercontent.com/docsz/AD_4nXdp47H91K3_BJ7bhPzWWh8IiGSaUuN6FzW7L1yLOp8b25AgkXe8bF6x4r6qJPFHc0cMgsoViSoWicXiv6gvnqr8zapgENQGYh6AZHIlAZsyaxj-tpQ70vdxP5ke3WLoAR-X6ZWvvQ?key=ZR7I2qHpTceitGesCDnDjg4E)

Note: The Graph's smart contracts are all on Arbitrum One, even though your subgraph is indexing data from Ethereum, BSC or any other [supported chain](https://thegraph.com/docs/en/developing/supported-networks/).

### 3. Query your Subgraph[​](https://docs.fuse.io/developers/subgraphs#3-query-your-subgraph)

Congratulations! You can now query your subgraph on the decentralized network!

For any subgraph on the decentralized network, you can start querying it by passing a GraphQL query into the subgraph’s query URL which can be found at the top of its Explorer page.

Here’s an example from the [CryptoPunks Ethereum subgraph](https://thegraph.com/explorer/subgraphs/HdVdERFUe8h61vm2fDyycHgxjsde5PbB832NHgJfZNqK) by Messari:

![Query URL](https://lh7-rt.googleusercontent.com/docsz/AD_4nXcj6_nq8W5X7AoIdOXbs2Dh4nzAg0x3SNdqRuSLNqV1YloNMr2amiDk1-J7a-C0wRPLF3r0fdwkjzY2arBcwwTBswpMXJ165rx_Q00XaouaigA1eJJh9nW9yp5Bx8nVKeFITiYM?key=ZR7I2qHpTceitGesCDnDjg4E)

The query URL for this subgraph is:

[https://gateway-arbitrum.network.thegraph.com/api/\*\*\[api-key\]\*\*/subgraphs/id/HdVdERFUe8h61vm2fDyycHgxjsde5PbB832NHgJfZNqK](https://gateway-arbitrum.network.thegraph.com/api/**%5Bapi-key%5D**/subgraphs/id/HdVdERFUe8h61vm2fDyycHgxjsde5PbB832NHgJfZNqK)

Now, you simply need to  fill in your own API Key to start sending GraphQL queries to this endpoint.

#### Getting your own API Key[​](https://docs.fuse.io/developers/subgraphs#getting-your-own-api-key)

![API keys](https://lh7-rt.googleusercontent.com/docsz/AD_4nXe4LCeMfSqlCQPcJrDjxP3k459imR8knwvWxpxFrhLBs1GZbn12I4n5VWncEGnsvEzV-DaWnzGGDCNsysUB2rFsEb7UWCfAChtTN6EuY1sRgu9P0ZZpAVc2IRrywcnkA5b8oF5pCg?key=ZR7I2qHpTceitGesCDnDjg4E)

In Subgraph Studio, you’ll see the “API Keys” menu at the top of the page. Here you can create API Keys.

### Appendix[​](https://docs.fuse.io/developers/subgraphs#appendix)

#### Sample Query[​](https://docs.fuse.io/developers/subgraphs#sample-query)

This query shows the most expensive CryptoPunks sold.

```
{
 trades(orderBy: priceETH, orderDirection: desc) {
   priceETH
   tokenId
 }
}
Passing this into the query URL returns this result:
{
 "data": {
   "trades": [
     {
       "priceETH": "124457.067524886018255505",
       "tokenId": "9998"
     },
     {
       "priceETH": "8000",
       "tokenId": "5822"
     },
//      ...
```

💡 Trivia: Looking at the top sales on [CryptoPunks website](https://cryptopunks.app/cryptopunks/topsales) it looks like the top sale is Punk #5822, not #9998. Why? Because they censor the flash-loan sale that happened.

#### Sample code[​](https://docs.fuse.io/developers/subgraphs#sample-code)

```
const axios = require("axios");

const graphqlQuery = `{
 trades(orderBy: priceETH, orderDirection: desc) {
   priceETH
   tokenId
 }
}`;
const queryUrl =
 "https://gateway-arbitrum.network.thegraph.com/api/[api-key]/subgraphs/id/HdVdERFUe8h61vm2fDyycHgxjsde5PbB832NHgJfZNqK";

const graphQLRequest = {
 method: "post",
 url: queryUrl,
 data: {
   query: graphqlQuery,
 },
};

// Send the GraphQL query
axios(graphQLRequest)
 .then((response) => {
   // Handle the response here
   const data = response.data.data;
   console.log(data);
 })
 .catch((error) => {
   // Handle any errors
   console.error(error);
 });
```

#### Additional resources:[​](https://docs.fuse.io/developers/subgraphs#additional-resources)

* To explore all the ways you can optimize & customize your subgraph for a better performance, read more about [creating a subgraph here](https://thegraph.com/docs/en/developing/creating-a-subgraph/).
* For more information about querying data from your subgraph, read more [here](https://thegraph.com/docs/en/querying/querying-the-graph/).


# Embedded Wallet (MPC)

Embedded wallets are indispensable tooling for developers to go to market faster and onboard all online users to onchain.

## Context

As Viction aims to meet the scaling needs of any dapps and pave the way for mass adoption, embedded wallets are indispensable tooling for developers to go to market faster and onboard all online users to onchain.

By using embedded wallets, Viction builders can leverage the no-code wallet tooling and be inspired to build scalable onchain applications for daily use.

## About Ramper SDK

Ramper is providing an Auth & Embedded Wallet SDK that helps developers to have non-custodial MPC wallet features natively in their onchain applications at speed with no-code integration, while allowing their users to seamlessly create/restore wallet just by signing in with Email or SSO (Gmail, Facebook, Apple ID, Telegram, Twitter, etc) - No seed phrase, no wallet app/extension download required. This enables intuitive and stay-in-app user experience, eliminating current complex Web3 onboarding that causes churn, especially for Web2 users.

Ramper ensures the decentralization of onchain applications through secure underlying Embedded Multi-Party Computation (EMPC) system where users’ secret (mnemonic) are split into three encrypted parts and stored separately in trusted environments, with neither Ramper nor the dapps able to reconstruct it.

Ramper SDK also provides the In-App WalletView component, which allows various wallet-related functionalities, including but not limited to fiat on-ramp, asset management, transaction history, asset transfers, etc.

Currently, Ramper SDK supports Next Js and will soon be supporting React Native or Unity, Cocos for games on mobile, Telegram Mini Apps.

Get started on Viction: <https://docs.ramper.xyz/embedded-wallet-sdk/version-2/get-started-on-viction>


# Walkthrough: Build a Dapp on Viction

In this guide:

* Setting up Hardhat, the most popular development framework for Ethereum which also works perfectly for Viction.
* Creating a Hardhat project.
* Creating a Viction wallet.
* Requesting free tokens using Viction faucet.
* Writing a smart contract.
* Compiling and migrating the smart contract to Viction.
* Connecting Metamask to Viction Testnet.
* Creating a user interface to interact with the smart contract.

### Why should developers build Dapps on Viction? <a href="#id-8c4b" id="id-8c4b"></a>

Remember [*CryptoKitties*](https://www.cryptokitties.co/) in 2017? A single Dapp brought the whole Ethereum blockchain to its knees. The network was congested, with endless waiting times for transaction confirmation and high transaction fees. Porting to Viction would seem a good idea for the cute kitties.

Viction Mainnet can process 2,000 TPS, which is **100x faster than the Ethereum blockchain,** and for a fraction of the cost.

In this tutorial, we will see **how to build a Dapp using Solidity** and then deploy it to **Viction** blockchain.

> **Note:** Because deploying a smart contract on Mainnet is much similar to Testnet, the differences are just the configuration information, this document will explicitly mention the differences where possible.


# Setup Environment

### Prerequisites <a href="#id-7095" id="id-7095"></a>

To start building your Dapp you will need to install some programs:

* Install [**Node.js**](https://nodejs.org/en/download/) & **npm** (“Node.js Package Manager”)
* Install [**Git**](https://git-scm.com/downloads)

To check that Node is installed properly, open a console (admin PowerShell on Windows) and type `node -v`. This should print a version number, like `v10.15.0`.

To test npm, type `npm -v` and you should see the version number, like `6.4.1`.

### Install Node.js

{% hint style="info" %}
You can [skip](https://hardhat.org/tutorial/creating-a-new-hardhat-project) this section if you already have a working Node.js `>=16.0` installation. If not, here's how to install it on Ubuntu, MacOS and Windows.
{% endhint %}

#### Linux

For Ubuntu based distro, copy and paste these commands in a terminal:

```bash
sudo apt update
sudo apt install curl git
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt-get install -y nodejs
```

Check out this [link](https://nodejs.org/en/download/current) for each platform installers.

#### MacOS

Make sure you have `git` installed.

```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
nvm install 16
nvm use 16
nvm alias default 16
npm install npm --global # Upgrade npm to the latest version
```

#### Windows

If you are using Windows, we **strongly recommend** you use Windows Subsystem for Linux (also known as WSL 2). You can use Hardhat without it, but it will work better if you use it.

To install Node.js using WSL 2, please read [this guide](https://docs.microsoft.com/en-us/windows/dev-environment/javascript/nodejs-on-wsl).

### Creating a new Hardhat project

We'll install Hardhat using the Node.js package manager (`npm`), which is both a package manager and an online repository for JavaScript code.

You can use other package managers with Node.js, but we suggest you use npm 7 or higher to follow this guide. You should already have it if you followed the previous section's steps.

Open a new terminal and run these commands to create a new folder:

```bash
mkdir hardhat-tutorial
cd hardhat-tutorial
```

```bash
npm init
npm install --save-dev hardhat
npx hardhat init
```

Select `Create an empty hardhat.config.js` with your keyboard and hit enter.

```
$ npx hardhat init
888    888                      888 888               888
888    888                      888 888               888
888    888                      888 888               888
8888888888  8888b.  888d888 .d88888 88888b.   8888b.  888888
888    888     "88b 888P"  d88" 888 888 "88b     "88b 888
888    888 .d888888 888    888  888 888  888 .d888888 888
888    888 888  888 888    Y88b 888 888  888 888  888 Y88b.
888    888 "Y888888 888     "Y88888 888  888 "Y888888  "Y888

👷 Welcome to Hardhat v2.18.1 👷‍

? What do you want to do? …
  Create a JavaScript project
  Create a TypeScript project
❯ Create an empty hardhat.config.js
  Quit
```

When Hardhat is run, it searches for the closest `hardhat.config.js` file starting from the current working directory. This file normally lives in the root of your project and an empty `hardhat.config.js` is enough for Hardhat to work. The entirety of your setup is contained in this file.

### Create a VIC Wallet

**You will need a wallet address** and some tokens. We will show you how to do it on both Viction Testnet and Mainnet.

#### 1. Create a VIC wallet and save your Mnemonic

You can create a new VIC wallet using **Viction Wallet** mobile app for [iOS](https://apps.apple.com/us/app/viction-wallet-by-coin98/id1436476145), or the web version (<https://wallet.tomochain.com/#/login>). Under *Settings* go to *Advanced Settings,* here you can *Choose network* and select `Viction TestNet` or `Viction` \[mainnet].

Go to *Settings* menu, select *Backup wallet* and then **Continue**. Here you can see your wallet’s private key and the 12-word recovery phrase. **Write down the 12-word recovery phrase.**

You can also create a new [Viction wallet with MetaMask, MyEtherWallet or TrustWallet](https://docs.viction.xyz/get-started/wallet/). For instance, for mainnet you can go to [MyEtherWallet](https://www.myetherwallet.com/) and select **VIC (viction.xyz)** on the top right corner. Enter a password and then Create a new wallet. **Write down your recovery phrase.**

For this tutorial, my wallet address (testnet) is:

```
0xc9b694877acd4e2e100e095788a591249c38b9c5
```

My recovery phrase (12-word `mnemonic`) is:

```
myth ahead spin horn minute tag spirit please gospel infant clog camera
```

Write them down. This will be needed later. **Notice that your wallet address (public key) and your recovery phrase will be different than mine.**

> **Important!** Always keep your private key and recovery phrase **secret!**

#### 2. Get some VIC funds

Tokens are required for different matters, like smart contract deployment or to use in Dapps.

**Testnet:** Receive 15 free testnet VIC tokens using [Viction's Faucet](https://faucet-testnet.viction.xyz/).

**Mainnet:** You need real VIC tokens from exchanges.

Go to faucet and collect `30 VIC`. Now your wallet has enough balance to do everything in this tutorial so… let’s go ahead!

#### 3. The Block Explorer

To check the balance of a wallet address, you can use **VicScan**.

**Mainnet:** <https://vicscan.xyz/>

**Testnet:** <https://scan-ui-testnet.viction.xyz/>


# Write the Smart Contract

We’ll start our Dapp by writing the smart contract that acts as the back-end logic and storage.

{% hint style="info" %}
You might have heard about ERC-20, which is a token standard in Ethereum. Tokens such as DAI and USDC implement the ERC-20 standard which allows them all to be compatible with any software that can deal with ERC-20 tokens. For the sake of simplicity, the token we're going to build does *not* implement the ERC-20 standard.
{% endhint %}

1. Create a new file named `Token.sol` in the `contracts/` directorynote
2. Copy the following code:

```solidity
// Solidity files have to start with this pragma.
// It will be used by the Solidity compiler to validate its version.
pragma solidity ^0.8.0;


// This is the main building block for smart contracts.
contract Token {
    // Some string type variables to identify the token.
    string public name = "My Hardhat Token";
    string public symbol = "MHT";

    // The fixed amount of tokens, stored in an unsigned integer type variable.
    uint256 public totalSupply = 1000000;

    // An address type variable is used to store ethereum accounts.
    address public owner;

    // A mapping is a key/value map. Here we store each account's balance.
    mapping(address => uint256) balances;

    // The Transfer event helps off-chain applications understand
    // what happens within your contract.
    event Transfer(address indexed _from, address indexed _to, uint256 _value);

    /**
     * Contract initialization.
     */
    constructor() {
        // The totalSupply is assigned to the transaction sender, which is the
        // account that is deploying the contract.
        balances[msg.sender] = totalSupply;
        owner = msg.sender;
    }

    /**
     * A function to transfer tokens.
     *
     * The `external` modifier makes a function *only* callable from *outside*
     * the contract.
     */
    function transfer(address to, uint256 amount) external {
        // Check if the transaction sender has enough tokens.
        // If `require`'s first argument evaluates to `false` then the
        // transaction will revert.
        require(balances[msg.sender] >= amount, "Not enough tokens");

        // Transfer the amount.
        balances[msg.sender] -= amount;
        balances[to] += amount;

        // Notify off-chain applications of the transfer.
        emit Transfer(msg.sender, to, amount);
    }

    /**
     * Read only function to retrieve the token balance of a given account.
     *
     * The `view` modifier indicates that it doesn't modify the contract's
     * state, which allows us to call it without executing a transaction.
     */
    function balanceOf(address account) external view returns (uint256) {
        return balances[account];
    }
}
```

{% hint style="info" %}
The source code above is just an example to illustrate how your source code looks like. In practice, your source code may contain one or many files with complex structure.
{% endhint %}

## Compiling <a href="#df38" id="df38"></a>

Solidity is a compiled language, meaning we need to compile our Solidity to bytecode for the **Ethereum Virtual Machine (EVM)** to execute. Think of it as translating our human-readable Solidity into something the EVM understands.

> Viction is EVM-compatible, which means that every contract written in Ethereum can be seamlessly ported to Viction without effort.

To compile the contract run `npx hardhat compile` in your terminal. The `compile` task is one of the built-in tasks.

```bash
npx hardhat compile
```

You should see output similar to the following:

```bash
$ npx hardhat compile
Compiling 1 file with 0.8.17
Compilation finished successfully
```


# Interacting with the Dapp in a browser

Now we’re ready to use our Dapp!

### Install and configure MetaMask <a href="#id-4986" id="id-4986"></a>

1. Install the [MetaMask browser extension](https://metamask.io/) in Chrome or FireFox.
2. Once installed, you’ll see the MetaMask fox icon next to your address bar. Click the icon and MetaMask will open up.
3. Create a New password. Then, write down the Secret Backup Phrase and accept the terms. By default, MetaMask will create a new Ethereum address for you.

<img src="https://miro.medium.com/max/1828/1*tV2bQfZ2vVhvpOOwKY0Y5g.png" alt="" data-size="original">

*Initiating MetaMask*

4\. Now we’re connected to the Ethereum network, with a brand new wallet with 0 ETH.

5\. Let’s now connect MetaMask to Viction (testnet). Click the menu with the “Main Ethereum Network” and select **Custom RPC**. Use the [Networks data from Viction](/how-to/how-to-connect-to-viction-network/metamask) (testnet) and click **Save**

![](https://miro.medium.com/max/60/1*Dm4qhGJOjnolRwxX-VN94w.png?q=20) ![](https://miro.medium.com/max/1424/1*Dm4qhGJOjnolRwxX-VN94w.png)

*Connecting MetaMask to Viction (testnet)*

6\. The network name at the top will switch to say “Viction testnet”. Now that we are on Viction network we can import Viction wallets.

We could use the VIC wallet we created previously, but better **let’s create a new VIC wallet** and add a few VIC tokens — *you know how to do it*.

7\. Once you have created your new VIC wallet, **copy the private key**. Back to MetaMask, click on the top-right circle and select **Import Account.** Paste the private key and *voilà*! Your VIC wallet is loaded in MetaMask

![](https://miro.medium.com/max/60/1*AjEHidU-h0Ae0CXTsQUJ5Q.png?q=20) ![](https://miro.medium.com/max/1298/1*AjEHidU-h0Ae0CXTsQUJ5Q.png)

*Importing a wallet*

### Using the Dapp <a href="#id-9432" id="id-9432"></a>

If you want to get started with your dApp quickly or see what this whole project looks like with a frontend, you can use Hardhat's[ boilerplate repo](https://github.com/NomicFoundation/hardhat-boilerplate).

The first things you need to do are cloning this repository and installing its dependencies:

```bash
git clone https://github.com/NomicFoundation/hardhat-boilerplate.git
cd hardhat-boilerplate
npm install
```

### **Front End App**

In `frontend` you'll find a simple app that allows the user to do two things:

* Check the connected wallet's balance.
* Send tokens to an address.

It's a separate npm project and it was created using `create-react-app`, so this means that it uses webpack and babel.

```bash
npx hardhat node
```

Once installed, let's run Hardhat's testing network:

```bash
npx hardhat run scripts/deploy.js --network localhost
```

Then, on a new terminal, go to the repository's root folder and run this to deploy your contract:

```bash
npx hardhat run scripts/deploy.js --network localhost
```

Finally, we can run the frontend with:

```bash
cd frontend
npm install
npm start
```

Open <http://localhost:3000/> to see your Dapp. You will need to have [Coinbase Wallet](https://www.coinbase.com/wallet) or [Metamask](https://metamask.io/) installed and listening to`localhost 8545.`([Example](https://github.com/c98tristan/gitbook-Viction/blob/master/developer-guide/building-dapp-on-Viction/develop-a-simple-web3-frontend-to-interact-with-the-contract/interacting-with-the-dapp-in-a-browser.md#4986))


# Masternode

In this section we provide information on how to setup and run a Masternode on Viction.

### Masternode

| Topic                                                                | Content                                                                                                                                          |
| -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| [Requirements](/masternode/requirements)                             | The base recommendations for running a Masternode Candidate.                                                                                     |
| [Run a full node](/masternode/run-a-full-node)                       | This guide shows how to run a Viction Masternode in Testnet and Mainnet without the need of using Docker and `tmn`.                              |
| [Apply Your Node](/masternode/apply-your-node)                       | Once the full node is up and running, we walk through how to make it eligible to become a Masternode .                                           |
| [Viction Slashing Mechanism](/masternode/viction-slashing-mechanism) | If a Masternode does not sign any blocks during an entire epoch, the Masternode will be kicked out of the Masternode list for the next 5 epochs. |
| [Chain Data Snapshots](/masternode/chain-data-snapshots)             | A snapshot is a recording of the state of a blockchain at a particular block height.                                                             |


# Requirements

Hardware specification for running a Viction Mainnet node.

### General System Specs <a href="#hardware" id="hardware"></a>

Minimum requirements

* CPU: 2 cores
* RAM: 8 GB
* SSD: 1 TB
* Network: 10 Mb/s

Full node requirements

* CPU: 4 cores
* RAM: 16 GB
* SSD: 1 TB
* Network: 25 Mb/s

Masternode requirements

* CPU: 8 cores
* RAM: 16 GB
* SSD: 1 TB
* Network: 25 Mb/s

Archive node requirements

* CPU: 16-64 cores
* RAM: 32 GB
* SSD: 4 TB
* Network: 25 Mb/s

The requirements above are for typical workload and cannot cover all workloads. These are good starting points to adjust node specifications to fit with your workload.

{% hint style="info" %}
As of December 2024, the size of blockchain data is:

* Full node: 900 GB
* Archive node: 3743 GB
  {% endhint %}

### Recommendation

We recommend using popular cloud providers as their reliability and uptime are close to 100%. These servers would be a good starting point:

* **Amazon EC2**: C5 instance
* **DigitalOcean**: CPU optimized droplet 16GB/8vCPU
* **Google Cloud Engine**: n2d-standard-8

Setting up a Masternode Candidate on a low specs machine might result in poor performances, significantly impacting owner's rewards and the chain performance.

{% hint style="info" %}
Notice

A Masternode has a certain number of tasks to process (validations, block creations, etc.) over time. Your Masternode should be able to process all the tasks that are designated to it, or the rewards will be negatively impacted. However, overpowered technical specifications of the Masternode will not result in greater rewards.
{% endhint %}

### Maintenance <a href="#maintenance" id="maintenance"></a>

All IT systems require maintenance.

It is of the owner's responsibility to ensure regular maintenance, and that the node has enough:

* Disk space to store the new blockchain data.
* Processing power to keep the chain operating at optimal speed.
* Monitoring to be able to react quickly in case of a problem occurring.
* Security measures like firewalling, OS security patching, SSH via keypairs, etc.

This is a non-exhaustive list.


# Run a Full Node

This tutorial shows how to run a full node and meet the requirements to apply to become a Masternode Candidate on VicMaster. You have to run the Viction client - our Viction implement on Go

### General hardware notice <a href="#general-hardware-notice" id="general-hardware-notice"></a>

The Viction team has extensively tested performances and come up with those minimal requirements for any Viction masternode host.

**Testnet**

* Must be facing internet directly (no NAT, public IP)
* Must have at least 2 cores
* Must have at least 8GB of RAM
* Must use an IaaS ("cloud") provider of your choice (AWS, Digital Ocean, Google Cloud, etc.).
* Storage must be SSD

**Mainnet**

* Must be facing internet directly (no NAT, public IP)
* Must have at least 16 cores
* Must have at least 32GB of RAM
* Must use an IaaS ("cloud") provider of your choice (AWS, Digital Ocean, Google Cloud, etc.)
* Storage must be SSD

**Storage requirements for building a node**

It depends on how you operate the Full node. The data is now roughly 700GB (updated on Oct 1st, 2023). So there are two options for you to consider:

* If you're starting a fresh new full node, 1TB should be enough.
* If you want to restore the chain data from a Snapshot, 2TB is recommended because downloading and decompressing can take up to 1.5TB of your storage.

We recommend prioritizing CPU. For example with Digital Ocean, pick a CPU optimized droplet. On AWS EC2, a C5 type instance would be a perfect match.

The full node will serve on port `30303` udp and tcp for p2p communication with other nodes, `8545` tcp for RPC api and `8546` tcp for websocket api. You may need to edit your firewall configuration accordingly.

If you have other production grade environment than cloud provider at your displosal, please tell us more about on our [Gitter](https://gitter.im/Viction).

### tmn <a href="#tmn" id="tmn"></a>

We made a simple command line interface called [tmn](https://github.com/BuildOnViction/masternode) to easily and quickly start a Viction full node. It takes care of starting the necessary docker containers with the proper settings for you. It will really suit you if you don't already have a big infrastructure running. Spin up a machine in your favorite cloud and get your full node running in a few minutes!

#### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

To use tmn, you should meet these requirements in addition to the hardware ones:

* [Docker CE](https://docs.docker.com/install/)
* [Python](https://docs.python-guide.org/starting/install3/linux/) >= 3.5

#### Installation <a href="#installation" id="installation"></a>

Simply install it from pip.

```
pip3 install --user tmn
```

#### Update <a href="#update" id="update"></a>

Update it from pip.

```
pip3 install -U tmn
```

#### First start <a href="#first-start" id="first-start"></a>

When you first start your full node with tmn, you need to give some information.

`--name`: The name of your full node. It should be formatted as a slug string. Slug format authorize all letters and numbers, dashes ("-") and underscores ("\_"). You can name it to reflect your identity, company name, etc.

`--net`: The network your full node will connect to. You can choose here to connect it to the Viction Testnet or Mainnet (once launched).

`--pkey`: The private key of the account that your full node will use. A Viction full node uses an account to be uniquely identified and to receive transaction fee.

**Important note:** we advise for security measures to use a fresh new account for your masternode. This is not the account who will receive the rewards. The rewards are sent to the account who will make the 50k VIC initial deposit.

It could look like this:

```
tmn start --name [YOUR_NODE_NAME] \
    --net testnet \
    --pkey [YOUR_COINBASE_PRIVATE_KEY]
```

Once started, you should see your node on the [testnet stats page](https://stats.testnet.tomochain.com/) or the [mainnet stats page](https://stats.tomochain.com/), depending on which net you are connecting to!

Note: it can take up to one hour or more (depending on the blockchain data size) to properly sync the entire blockchain.

#### Usage <a href="#usage" id="usage"></a>

You can now interact with it via the other commands:

`stop`: Stop your full node.

`start`: Start your full node if it is stopped.

`status`: The current status of your full node.

`inspect`: Display the details related to your full node. Useful for applying your full node as a masternode.

`remove`: Completely remove your masternode, unique identity and data.

#### Troubleshooting <a href="#troubleshooting" id="troubleshooting"></a>

**tmn: command not found**

It might happen that your PATH is not set by default to include the default user binary directory. You can add it by adding it to your shell $PATH:

On GNU/Linux:

```
echo 'export PATH=$PATH:~/.local/bin' >> ~/.bashrc
```

On MacOS: Replace `[VERSION]` by your version of python (3.5, 3.6, 3.7)

```
echo 'export PATH=$PATH:~/Library/Python/[VERSION]/bin' >> ~/.bashrc
```

**error: could not access the docker daemon**

If you have installed Docker, you probably forgot to add your user to the docker group. Please run this, close your session and open it again.

```
usermod -aG docker $your_user_name
```


# Binary

This guide shows how to run a Viction Masternode in testnet and mainnet without the need of using Docker and tmn.

### Install Golang <a href="#install-golang" id="install-golang"></a>

* Reference: <https://golang.org/doc/install>
* Set environment variables
* Supports Go 1.19+

```
export GOROOT=$HOME/usr/local/go
export GOPATH=$HOME/go
```

### Prepare tomo client software <a href="#prepare-tomo-client-software" id="prepare-tomo-client-software"></a>

**Build from source code**

Create new directory for the project

```
mkdir -p $GOPATH/src/github.com/Viction/
cd $GOPATH/src/github.com/Viction/
```

* Download source code and build

```
git clone https://github.com/BuildOnViction/tomochain.git Viction
cd Viction
```

* Checkout the latest version (e.g v2.2.4)

```
git pull origin --tags
git checkout v2.2.4
```

* Build the project

```
make all
```

* Binary file should be generated in build folder `$GOPATH/src/github.com/Viction/Viction/build/bin`

```
alias tomo=$GOPATH/src/github.com/Viction/Viction/build/bin/tomo
```

**Download Viction binary from Github release page**

Download tomo binary from our [releases page](https://github.com/BuildOnViction/tomochain/releases)

```
alias tomo=path/to/tomo/binary
```

### Download genesis block <a href="#download-genesis-block" id="download-genesis-block"></a>

$GENESIS\_PATH : location of genesis file you would like to put

```
export GENESIS_PATH=path/to/genesis.json
```

* Testnet

```
curl -L https://raw.githubusercontent.com/buildonViction/tomochain/master/genesis/testnet.json -o $GENESIS_PATH
```

* Mainnet

```
curl -L https://raw.githubusercontent.com/buildonViction/tomochain/master/genesis/mainnet.json -o $GENESIS_PATH
```

### Create datadir <a href="#create-datadir" id="create-datadir"></a>

* create a folder to store Viction data on your machine

```
export DATA_DIR=/path/to/your/data/folder
mkdir -p $DATA_DIR/tomo
```

### Initialize the chain from genesis <a href="#initialize-the-chain-from-genesis" id="initialize-the-chain-from-genesis"></a>

```
tomo init $GENESIS_PATH --datadir $DATA_DIR
```

### Initialize / Import accounts for the nodes's keystore <a href="#initialize-import-accounts-for-the-nodess-keystore" id="initialize-import-accounts-for-the-nodess-keystore"></a>

If you already had an existing account, import it. Otherwise, please initialize new accounts

```
export KEYSTORE_DIR=path/to/keystore
```

**Initialize new accounts**

```
tomo account new \
    --password [YOUR_PASSWORD_FILE_TO_LOCK_YOUR_ACCOUNT] \
    --keystore $KEYSTORE_DIR
```

**Import accounts**

```
tomo account import [PRIVATE_KEY_FILE_OF_YOUR_ACCOUNT] \    
    --keystore $KEYSTORE_DIR \
    --password [YOUR_PASSWORD_FILE_TO_LOCK_YOUR_ACCOUNT]
```

**List all available accounts in keystore folder**

```
tomo account list --datadir $DATA_DIR  --keystore $KEYSTORE_DIR
```

### Start a node <a href="#start-a-node" id="start-a-node"></a>

**Environment variables**

* $IDENTITY: the name of your node
* $PASSWORD: the password file to unlock your account
* $YOUR\_COINBASE\_ADDRESS: address of your account which generated in the previous step
* $NETWORK\_ID: the networkId. Mainnet: 88. Testnet: 89
* $BOOTNODES: The comma separated list of bootnodes. Find them [here](https://docs.viction.xyz/developer-guide/working-with-viction/viction-mainnet#bootnodes)
* $WS\_SECRET: The password to send data to the stats website. Find them [here](https://docs.viction.xyz/developer-guide/working-with-viction/viction-mainnet#stats-websocket-secret)
* $NETSTATS\_HOST: The stats website to report to, regarding to your environment. Find them [here](https://docs.viction.xyz/developer-guide/working-with-viction/viction-mainnet#stats-websocket-secret)
* $NETSTATS\_PORT: The port used by the stats website (usually 443)

**Let's start a node**

```
tomo  --syncmode "full" \
    --announce-txs \
    --datadir $DATA_DIR --networkid $NETWORK_ID --port 30303 \
    --keystore $KEYSTORE_DIR --password $PASSWORD \
    --identity $IDENTITY \
    --mine --gasprice 250000000 \
    --bootnodes $BOOTNODES \
    --ethstats $IDENTITY:$WS_SECRET@$NETSTATS_HOST:$NETSTATS_PORT
```

If you are a dapp developer, you should open RPC and WS apis:

```
tomo  --syncmode "full" \
    --announce-txs \
    --datadir $DATA_DIR --networkid $NETWORK_ID --port 30303 \
    --keystore $KEYSTORE_DIR --password $PASSWORD \
    --rpc --rpccorsdomain "*" --rpcaddr 0.0.0.0 --rpcport 8545 --rpcvhosts "*" \
    --rpcapi "db,eth,net,web3,personal,debug" \
    --ws --wsaddr 0.0.0.0 --wsport 8546 --wsorigins "*" --unlock "$YOUR_COINBASE_ADDRESS" \
    --identity $IDENTITY \
    --mine --gasprice 250000000 \
    --bootnodes $BOOTNODES \
    --ethstats $IDENTITY:$WS_SECRET@$NETSTATS_HOST:$NETSTATS_PORT
```

If you want to run an archive node to be able to access historical data, you must add two more parameters to the command line `--gcmode archive --store-reward` , so the final command line will be:

```
tomo  --syncmode "full" \
    --announce-txs \
    --datadir $DATA_DIR --networkid $NETWORK_ID --port 30303 \
    --keystore $KEYSTORE_DIR --password $PASSWORD \
    --rpc --rpccorsdomain "*" --rpcaddr 0.0.0.0 --rpcport 8545 --rpcvhosts "*" \
    --rpcapi "db,eth,net,web3,personal,debug" \
    --ws --wsaddr 0.0.0.0 --wsport 8546 --wsorigins "*" --unlock "$YOUR_COINBASE_ADDRESS" \
    --identity $IDENTITY \
    --mine --gasprice 250000000 \
    --bootnodes $BOOTNODES \
    --ethstats $IDENTITY:$WS_SECRET@$NETSTATS_HOST:$NETSTATS_PORT
    --gcmode archive --store-reward
```

**Some explanations on the flags**

```
--verbosity: log level from 1 to 5. Here we're using 4 for debug messages

--datadir: path to your data directory created above.

--keystore: path to your account's keystore created above.

--identity: your full-node's name.

--password: your account's password.

--networkid: our network ID.

--port: your full-node's listening port (default to 30303)

--rpc, --rpccorsdomain, --rpcaddr, --rpcport, --rpcvhosts: your full-node will accept RPC requests at 8545 TCP.

--ws, --wsaddr, --wsport, --wsorigins: your full-node will accept Websocket requests at 8546 TCP.

--mine: your full-node wants to register to be a candidate for masternode selection.

--gasprice: Minimal gas price to accept for mining a transaction.

--targetgaslimit: Target gas limit sets the artificial target gas floor for the blocks to mine (default: 4712388)

--bootnode: bootnode information to help to discover other nodes in the network

--gcmode: blockchain garbage collection mode ("full", "archive")

--synmode: blockchain sync mode ("fast", "full", or "light". More detail: https://github.com/BuildOnViction/Viction/blob/master/eth/downloader/modes.go#L24)

--ethstats: send data to stats website

--tomo-testnet: required when the networkid is testnet(89)

--store-reward: store reward report
```

To see all flags usage

```
tomo --help
```

### See your node on stats page <a href="#see-your-node-on-stats-page" id="see-your-node-on-stats-page"></a>

* Testnet: <https://stats-testnet.viction.xyz/>
* Mainnet: <https://stats.viction.xyz/>

### Troubleshooting <a href="#troubleshoot" id="troubleshoot"></a>

If your node seems run smooth with no error logs but still get slash frequently. You need to check system time on your node, your system time have to be synced from NTP server

E.g:

```
$ timedatectl
Local time: Fri 2019-07-26 05:57:40 CEST
  Universal time: Fri 2019-07-26 03:57:40 UTC
        RTC time: Fri 2019-07-26 03:58:01
       Time zone: Europe/Berlin (CEST, +0200)
 Network time on: yes
NTP synchronized: no
 RTC in local TZ: no
```

`NTP synchronized: no` means your node does not use NTP, you have to enable it.


# Create a Viction Masternode

This tool aims to help beginner/intermediate Masternode owners. It acts as a terminal wizard which helps the user generate a working configuration for docker-compose to run the node.

Using create-Viction-masternode and docker-compose offers you benefits like:

* working "out of the box" docker-compose configuration
* auto-restarting your node on failure
* flexible configuration (storage, logging, ports)

### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

* Docker
* Docker-compose

#### Installation of Docker CE <a href="#installation-of-docker-ce" id="installation-of-docker-ce"></a>

To install Docker, first update the apt package index.

```
sudo apt update
```

Then install packages to allow apt to use a repository over HTTPS.

```
sudo apt install apt-transport-https ca-certificates curl software-properties-common dirmngr gnupg
```

Add Docker’s official GPG key.

```
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
```

Verify that you now have the key with the fingerprint `9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88`, by searching for the last 8 characters of the fingerprint.

```
apt-key fingerprint 0EBFCD88
```

Set up the stable Docker repository.

```
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
```

Update the apt package index, then install the latest version of Docker CE.

```
sudo apt update

sudo apt install docker-ce
```

Once installed, add your current user to the Docker group.

```
sudo usermod -aG docker $(whoami)
```

**Warning**

You need to relog into your account for this to take effect. Until then, you will not be able to access the Docker deamon.

Verify that Docker CE is installed correctly by running the hello-world image:

```
docker run hello-world
```

This command downloads a test image and runs it in a container. When the container runs, it prints an informational message starting by "Hello from Docker!" and exits.

#### Installation of Docker-compose <a href="#installation-of-docker-compose" id="installation-of-docker-compose"></a>

To install docker-compose, start by downloading the executable.

```
sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
```

Make it executable.

```
sudo chmod +x /usr/local/bin/docker-compose
```

Optional: install bash completion.

```
sudo curl -L https://raw.githubusercontent.com/docker/compose/1.23.2/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
```

Verify that docker-compose is correctly installed by running the version command.

```
docker-compose version
```

### Usage <a href="#usage" id="usage"></a>

Simply run create-Viction-masternode with the name of your Masternode as argument.

```
create-Viction-masternode mymasternode
```

Follow the wizard by replying to the following questions:

* **Coinbase private key**: Your Masternode coinbase account private key. A Viction node uses an account to be uniquely identified and to receive transaction fee.

Important note:

We advise for security measures to use a fresh new account for your Masternode. This is not the account which will receive the rewards. The rewards are sent to the account which will make the initial deposit.

* **Storage**: The storage location for your node data (chaindata). Either `docker volume` if you want to use the default docker volume location, or `host directory` if you want to define specific location on your filesystem (usefull when extending storage).
* **Chaindata**: The name of the docker volume that will be used or the path to the directory containing the chaindata, depending on your answer to the last question.
* **The volume already exists**: If you selected "docker volume", this will determine if the volume already exists or if it needs to be created.
* **Expose RPC**: If you want to expose or not port `8545`. It is the RPC api to your node. It should be only exposed if you have a specific reason to access the Viction JSON-RPC Protocol. The Masternode owner is responsible of proxing and securing the RPC api as it should not be directly exposed to the internet.
* **Expose WebSocket**: If you want to expose or not port `8546`. It is the WebSocket api to your node. It should only be exposed if you have a specific reason to access the Viction Protocol via WebSocket. The Masternode owner is responsible of proxing and securing the WebSocket api as it should not be directly exposed to the internet.
* **Logging level**: Set the logging level of the Viction container to error, info or debug. Info or Error is usually a good logging level. Only use the debug level if you have a good reason to do so, it will generate a lot of output and increase resource usage.

Once finished, you will get a folder named after your Masternode (in our case "mymasternode") with two files.

* `.env` Which contains the configuration generated from your answers to the question.
* `docker-compose.yml` Which tells docker-compose how and which container run for your node. Your specific configuration will be read from the `.env` file.

Now that we have generated the correct initial configuration for docker-compose, we just need to start our node.

```
docker-compose up -d
```

You can check that your Masternode is running with the `ps` sub-command.

```
docker-compose ps
```

For more docker-compose commands, use `docker-compose --help` or refer to their [documentation](https://docs.docker.com/compose/reference/overview/).

### Migrating from `tmn` <a href="#migrating-from-tmn" id="migrating-from-tmn"></a>

You can find a guide on migrating from `tmn` in the [wiki](https://github.com/BuildOnViction/docs/wiki/Migrate-from-tmn-to-docker-compose-with-create-Viction-masternode).

For the long time Masternode runners who started with our older tool, `tmn`, here are the commands to achieve the same actions.

**tmn start**:

```
docker-compose up -d
```

**tmn stop**:

```
docker-compose stop
```

**tmn update**:

```
docker-compose pull
docker-compose up -d
```

**tmn remove**:

```
docker-compose down
```

### Troubleshooting <a href="#troubleshooting" id="troubleshooting"></a>

#### error: could not access the docker daemon <a href="#error-could-not-access-the-docker-daemon" id="error-could-not-access-the-docker-daemon"></a>

If you have installed Docker, you probably forgot to add your user to the docker group. Please run this, close your session and open it again.

```
usermod -aG docker $your_user_name
```


# Tmn

We made a simple command line interface called tmn to easily and quickly start a Viction Masternode

It takes care of starting the necessary docker containers with the proper settings for you. It will really suit you if you don't already have a big infrastructure running. Spin up a machine in your favorite cloud and get your Masternode running in a few minutes!

### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

* [Python](https://docs.python-guide.org/starting/install3/linux/) >= 3.6
* [Docker CE](https://docs.docker.com/install/)

**Warning**

We recommnd to run your Masternode on Ubuntu 18.04 LTS. This version have python 3.6 and has been reported as working out of the box.

#### Installation of Python <a href="#installation-of-python" id="installation-of-python"></a>

To install Python under debian based distribution, run the following commands.

```
apt update

apt install python3-pip
```

To check if you have installed the right Python version (must be greater than 3.5).

```
python3 --version
```

![tmn python](https://docs.viction.xyz/assets/tmn_python.png)

#### Installation of Docker CE <a href="#installation-of-docker-ce" id="installation-of-docker-ce"></a>

To install Docker, first update the apt package index.

```
sudo apt update
```

Then Install packages to allow apt to use a repository over HTTPS.

```
sudo apt install apt-transport-https ca-certificates curl software-properties-common
```

Add Docker’s official GPG key.

```
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
```

Verify that you now have the key with the fingerprint `9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88`, by searching for the last 8 characters of the fingerprint.

```
apt-key fingerprint 0EBFCD88
```

![](/files/AGB6gPn8D6Wwk6Rqvwed)

Set up the stable Docker repository.

```
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
```

Update the apt package index. Then install the latest version of Docker CE.

```
sudo apt update

sudo apt install docker-ce
```

Once installed, add your current user to the Docker group.

```
usermod -aG docker $your_user_name
```

**Warning**

You need to relog into your account for this to take effect.

Verify that Docker CE is installed correctly by running the hello-world image:

```
docker run hello-world
```

This command downloads a test image and runs it in a container. When the container runs, it prints an informational message and exits.

### tmn <a href="#tmn" id="tmn"></a>

#### Installation <a href="#installation" id="installation"></a>

Simply install it from pip.

```
pip3 install --user tmn
```

#### Update <a href="#update" id="update"></a>

Update it from pip.

```
pip3 install -U tmn
```

#### First start <a href="#first-start" id="first-start"></a>

When you first start your full node with tmn, you need to give some information.

`--name`: The name of your full node. It should be formatted as a slug string. Slug format authorize all letters and numbers, dashes ("-") and underscores ("\_"). You can name it to reflect your identity, company name, etc.

`--net`: The network your full node will connect to. You can choose here to connect it to the Viction Testnet or Mainnet.

`--pkey`: The private key of the account that your full node will use. A Viction full node uses an account to be uniquely identified and to receive transaction fee.

**Important note:**

We advise, for security measures, to use a fresh new account for your Masternode. This is not the account who will receive the rewards. The rewards are sent to the account who will make the 50,000 VIC initial deposit.

`--api`: Expose RPC and websocket on ports `8545` and `8546`.

**Important note:**

Those ports should not be accessible directly from the internet. Please setup fire-walling accordingly if you need to access them localy. Use a reverse proxy if you want to expose them to the outside.

It could look like this:

```
tmn start --name [YOUR_NODE_NAME] --net testnet --pkey [YOUR_COINBASE_PRIVATE_KEY] --api
```

Once started, you should see your node on the [stats page](https://stats.testnet.tomochain.com/)!

Note: It can take up to one hour to properly sync the entire blockchain.

![](/files/IcfflwTeJFZGmaE6DRGU)

### Usage <a href="#usage" id="usage"></a>

You can now interact with it via the other commands:

`stop`: Stop your full node.

`start`: Start your full node if it is stopped.

`status`: The current status of your full node.

`inspect`: Display the details related to your full node. Useful for applying your full node as a Masternode.

`remove`: Completely remove your asternode, unique identity and data.

### Troubleshooting <a href="#troubleshooting" id="troubleshooting"></a>

#### tmn: command not found <a href="#tmn-command-not-found" id="tmn-command-not-found"></a>

It might happen that your PATH is not set by default to include the default user binary directory. You can add it by adding it to your shell $PATH:

On GNU/Linux:

```
echo 'export PATH=$PATH:$HOME/.local/bin' >> $HOME/.bashrc
```

On MacOS: Replace `[VERSION]` by your version of python (3.5, 3.6, 3.7)

```
echo 'export PATH=$PATH:$HOME/Library/Python/[VERSION]/bin' >> $HOME/.bashrc
```

Then reload your environment:

```
source ~/.bashrc
```

#### error: could not access the docker daemon <a href="#error-could-not-access-the-docker-daemon" id="error-could-not-access-the-docker-daemon"></a>

If you have installed Docker, you probably forgot to add your user to the docker group. Please run this, close your session and open it again.

```
usermod -aG docker $your_user_name
```

#### pip3 install fails due to not being able to build some package <a href="#pip3-install-fails-due-to-not-being-able-to-build-some-package" id="pip3-install-fails-due-to-not-being-able-to-build-some-package"></a>

Your OS might not come with build tools preinstalled.

For ubuntu, you can solve that by running:

```
sudo apt install build-essential python3-dev python3-wheel
```

#### pip3 install fails due to "No Module named Setuptools" <a href="#pip3-install-fails-due-to-no-module-named-setuptools" id="pip3-install-fails-due-to-no-module-named-setuptools"></a>

Your OS might not come with setup tools preinstalled.

For ubuntu, you can solve that by running:

```
sudo apt install python3-setuptools
```


# Docker

Alternative to using our simple tool tmn, people or companies with existing infrastructure might want to directly run our docker images for more flexibility.

To achieve that, you just need to run our `tomochain/node` docker image.

This image runs the [Viction go client](https://github.com/BuildOnViction/tomochain) with some automation added on top.

### Tags <a href="#tags" id="tags"></a>

| Environment | Tag        |
| ----------- | ---------- |
| Testnet     | `:testnet` |
| Mainnet     | `:stable`  |

### Environment variables <a href="#environment-variables" id="environment-variables"></a>

| Variable        | Required | Default         | Example                                    | Description                                                                                                     |
| --------------- | -------- | --------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------- |
| `IDENTITY`      | False    | Random name     | `my-super-node`                            | The name of your asternode                                                                                      |
| `PASSWORD`      | False    | Random password | `S5G@fS3A8+*g-)ftYc`                       | The password used by the the client to localy encrypt its account                                               |
| `PRIVATE_KEY`   | False    | Random account  | `0xa3f5195...`                             | The private key of the account who will identify the node and receive txs fees                                  |
| `BOOTNODES`     | True     | None            | `enode://4d3...@1.2.3.4:30301,enode://...` | The comma separated list of bootnodes. Find them [here](/general/network-information/viction-mainnet#bootnodes) |
| `VERBOSITY`     | False    | 3               | `4`                                        | The level of logging (default one should be enough)                                                             |
| `NETWORK_ID`    | False    | 89              | `88`                                       | The network id of the join your node is joining. Find them [here](https://docs.viction.xyz/general/networks/)   |
| `WS_SECRET`     | False    | None            | `d$M4J4\5gLAz%Zjn>%`                       | The password to send data to the stats website                                                                  |
| `NETSTATS_HOST` | False    | netstats-server | `https://stats.tomochain.com`              | The stats website to report to, regarding to your environment                                                   |
| `NETSTATS_PORT` | False    | 3000            | `443`                                      | The port used by the stats website (usually 443)                                                                |
| `ANNOUNCE_TXS`  | False    | None            | `True`                                     | Enable reporting transactions via RPC/WS                                                                        |

### Ports <a href="#ports" id="ports"></a>

| Exposed | Protocol | Description             |
| ------- | -------- | ----------------------- |
| `30303` | tcp      | Viction client p2p port |
| `30303` | udp      | Viction client p2p port |
| `8545`  | tcp      | Blockchain RPC          |
| `8546`  | tcp      | Blockchain WS           |

### Filesystem <a href="#filesystem" id="filesystem"></a>

| Path                | Content   |
| ------------------- | --------- |
| `/tomochain/data`   | Chaindata |
| `/Viction/keystore` | Accounts  |

### Examples <a href="#examples" id="examples"></a>

`docker run`

```
docker run -d --name masternode \
  -e IDENTITY=$MASTERNODE_NAME \
  -e PRIVATE_KEY=$MASTERNODE_PK \
  -e BOOTNODES=$BOOTNODES \
  -e NETSTATS_HOST=stats.viction.xyz \
  -e NETSTATS_PORT=443 \
  -e WS_SECRET=$STATS_WS_SECRET \
  -p 30303:30303 \
  -p 30303:30303/udp \
  -v chaindata:/tomochain/data \
  Viction/node:stable
```

`docker-compose.yml`

```
version: "3.4"
services:
  masternode:
    image: tomochain/node:stable
    environment:
      IDENTITY: $MASTERNODE_NAME
      PRIVATE_KEY: $MASTERNODE_PK
      BOOTNODES: $BOOTNODES
      NETSTATS_HOST: stats.viction.xyz
      NETSTATS_PORT: 443
      WS_SECRET: $STATS_WS_SECRET
    ports:
      - 30303:30303
      - 30303:30303/udp
    volumes:
      - chaindata:/tomochain/data
```


# Apply Your Node

Once your full node is up and running, you need to apply to make it eligible as a Masternode.

Masternodes will receive a significant amount of block rewards, which likely exceeds the cost for running the infrastructure. However, Masternode Candidates need to invest in Viction by depositing at least 50,000 VIC, and stake them for the long term. Furthermore, after the initial deposit to become a candidate, if the Masternode Candidate is not one of the top 150 most voted Candidates, it will not be promoted to Masternode status, and thus receive no rewards. Therefore, Candidates have an incentive to do as much as they can such as signalling their capability to support Viction to get into the top 150 most voted Candidates.

### Requirements <a href="#requirements" id="requirements"></a>

To have a Masternode Candidate, the following requirements must be satisfied:

* The token holder has an up and running node - see our [documentation.](/masternode/run-a-full-node)
* The token holder must hold a minimum required amount of tokens (50,000 VIC). These 50,000 VIC are deposited to the Voting Smart Contract.
* Must be one of the 150 most voted Masternode Candidates in the system. The voting by token holders is credited through a Voting Dapp that allows token holders to send VIC through the smart contract mechanism.

### Apply to become a Masternode <a href="#applying-to-become-a-masternode" id="applying-to-become-a-masternode"></a>

You can apply to become a Masternode by going on [VicMaster](https://vicmaster.xyz/). Connect the wallet that contains the funds you want to deposit.

{% hint style="danger" %}
Warning

The wallet who makes the initial deposit will be the one receiving block rewards.
{% endhint %}

On the top right corner, click on "Become a Candidate".

Enter the amount of VIC you want to deposit (minimum 50,000).

Enter your [coinbase address](https://docs.viction.xyz/faq/masternode-and-voting/masternode#what-is-the-coinbase-address). This is the address of the account that your Masternode is using. If your are running your node with `tmn`, you can simply run `tmn inspect` to get it.

{% hint style="warning" %}
Important note:

We advise for security measures to use a fresh new account for your Masternode or 'coinbase address'. This is not the account that will receive the rewards. The rewards are sent to the account that will make the 50,000 VIC initial deposit.
{% endhint %}

Confirm with apply and proceed to make the payment.

Your full node will now be listed on VicMaster. People can view its details and vote for it.

A Candidate becomes a Masternode when it belongs to top 150 most voted Candidates in each epoch.

{% hint style="info" %}
Info

An epoch is a period of 900 blocks (\~ 30 minutes) starting from block #1
{% endhint %}

If your node is in the top 150 most voted Candidates at the checkpoint between two epochs, it will be promoted as a Masternode and will start producing blocks at the next epoch.

### Resigning a Masternode <a href="#resigning-your-masternode" id="resigning-your-masternode"></a>

In case you want to stop your node, you need to resign it from the governance first in order to retrieve the locked funds. Access VicMaster, go to your Candidate detail page, and click the `Resign` button. Your funds will be available to withdraw 30 days after the resignation (1,296,000 blocks).

After resigning successfully, you can stop your node. If you ran it with `tmn`, simply run:

```
tmn remove
```

At this point, your Masternode is completely terminated.


# Slashing Mechanism

Slashing Masternodes to keep the network functionality efficient

With Slashing v2.0, a Masternode who doesn't create any block within an epoch and therefore delays the network by 10 seconds at each of their turns will be penalized (no rewards) for the next five epochs.

{% hint style="info" %}
Note: a slashed Masternode can still sign transactions if he’s online but receive no rewards for doing so.
{% endhint %}

After being slashed for 5 epochs, the Masternode is analysed for re-entry. If the slashed Masternode have signed any transaction during the last epoch (meaning that he's up and working again) it will come back to its Masternode status and receive rewards normally. Otherwise it will be slashed for a new round of 5 epochs. This can happen as long as the node isn't back up or kicked out of the top 150.

Some reasons for being Slashed might be that the Masternode does not have the correct Viction software, lack of memory or Masternode crashes due to the lack of e-maintenance and operation by the Masternode owner.

{% hint style="info" %}
On VicMaster, click on a candidate to open the candidate page. Scroll down to 'Masternode Rewards'. You should look at 'Sign number', 'Slashing history' under Masternode Rewards to determine a good node or not.
{% endhint %}

Masternodes will sign a maximum of 60 blocks per epoch. A good Masternode will create around 60 sign transactions in that epoch. We also calculate the reward based on sign transactions number.\
\\


# Chain Data Snapshots

## Overview

For a node to join the network and work with other nodes, it must sync data with other nodes first. Overtime, the data to be synchronized will increased and the process will take several days to weeks, even months.

## Download

Snapshots for mainnet are available for both full node and archive node:

* Full node: <https://snapshot.viction.xyz/VICTION_FULL_DATA.tar.zst>
* Full node mirror: <https://chain-snapshots.tforce.dev/viction_mainnet_full.tar.zst>
* Archive node: <https://snapshot.viction.xyz/VICTION_ARCHIVE_DATA.tar.zst>
* Archive node mirror: <https://chain-snapshots.tforce.dev/viction_mainnet_archive.tar.zst>

Snapshots for testnet are available for full node and archive node:

* Full node: <https://chain-snapshots.tforce.dev/viction_testnet_full.tar.zst>
* Archive node: <https://chain-snapshots.tforce.dev/viction_testnet_archive.tar.zst>

{% hint style="info" %}
As of January 2026, the size after extraction for full node and archive node are 1025G and 4213G respectively.
{% endhint %}

To download the file, it's recommended to use **wget** or **aria2**.

```sh
# donwload using wget
wget -P /tmp https://snapshot.viction.xyz/VICTION_FULL_DATA.tar.zst

# download using aria2
aria2c -c -d /tmp https://snapshot.viction.xyz/VICTION_FULL_DATA.tar.zst
```

## How to use

The snapshot is compressed using zstandard for balancing between speed and compression.

After downloaded the file to `/tmp/VICTION_FULL_DATA.tar.zst`, to extract the file to a directory, say `/data/victionchain`, please run this command:

<pre class="language-sh"><code class="lang-sh"><strong># create destination directory
</strong>mkdir /data/viction

# extract the archive
tar -xvf /tmp/VICTION_FULL_DATA.tar.zst -C /data/victionchain
</code></pre>

After extraction, the datadir should look like this:

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

### Notes

To download and extract the file in background, in Linux host can use `nohup` for this purpose.

```sh
# donwload using wget
wget -b -P /tmp -o /tmp/VICTION_FULL_DATA.tar.zst.txt https://snapshot.viction.xyz/VICTION_FULL_DATA.tar.zst

# download using aria2
nohup aria2c -c -d /tmp https://snapshot.viction.xyz/VICTION_FULL_DATA.tar.zst > /tmp/VICTION_FULL_DATA.tar.zst.txt 2>&1 &

# extract the file
mkdir /data/victionchain
nohup tar -xvf /tmp/VICTION_FULL_DATA.tar.zst -C /data/victionchain > nohup.txt 2>&1 &
```


# Troubleshooting

Self-help guide to resolve common issues when deploying new node

### The node has been running for a long time and couldn't connect to any peer.

#### P2P port is not opened

The common cause for this issue is usually related local machine network configuration, in particular the P2P port (default 30303) is not accessible from the internet. To check that P2P is accessible from outsite, you can use any **open port checker** to help with this. At the time of this writing, a working tool can be used is <https://www.yougetsignal.com/tools/open-ports/>.

{% hint style="info" %}
Please note that the node must be running while checking for open port.
{% endhint %}

If the port is not accessible from outsite, please verify local machine firewall and Cloud provider firewall if any.

#### NAT param is not provided

Another common cause for the issue is NAT is not provider via command line when starting the node. Somtimes the node itself cannot determine its external IPv4 address, there when it broadcast its enode to boot node, other peers don't know which IP to connect to.

For instance, the IP of VM running the node is **35.212.224.171**, the NAT param should be:

```
--nat extip:35.212.224.173
```

#### P2P port running on Docker is different from 30303

Official Viction Docker image prior to v2.4.5 doesn't support custom P2P port out of the box. If you're in this case, please use port 30303 only.

Since Viction v2.4.5, the Docker image have a new environment variable `P2P_PORT` to change the P2P for node run inside Docker image.

In Docker setup, EXTIP environment variable is strongly recommended to be provided to support NAT configuration for the node.

{% hint style="info" %}
In both cases, please map the P2P port of Docker image to same port in the host.

For instance, if you want to have P2P port to 20202, it must be mapped to port 20202 of the host. The command line argument for this example will be

docker run -e EXTIP=35.212.224.171 -e P2P\_PORT=20202 -p 20202:20202 ...
{% endhint %}

For instance, the IP of VM running the node is **35.212.224.171**, and you want P2P port to be **20202**, the Docker command to start the container should have the following params:

```
-e EXTIP=35.212.224.171 -e P2P_PORT=20202 -p 20202:20202
```

### How to verify if I extract the snapshot correctly.

A common datadir will look like this.

* keystore: where the account for masternode is stored.
* tomo/chaindata: `CHAIN_DATA.tar.zst` will be extracted to this directory.
* tomox: `TOMOX_DATA.tar.zst` will be extracted to this directory.

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

As of December 2024, the size of datadir is follow, so the extract should be like this or higher:

* Full node: 900 GB
* Archive node: 3743 GB


# Viction Wallet


# User Guide


# Authentication

### How to Setup Password? <a href="#how-to-setup-password" id="how-to-setup-password"></a>

To ensure the security and privacy of your account, when installing the Viction Wallet and launching it for the first time, you need to set up a password.

**Step 1:** Install Viction Wallet and open it.

**Step 2:** At Get Started screen, select the action you want to perform

→ You will be redirected to the setup password process

<figure><img src="/files/ypaLzAsFmcR6El69Jhut" alt="" width="286"><figcaption></figcaption></figure>

**Step 3:** Input **Password** and **Confirm Password** fields

**Step 4:** Tick ​​the checkbox to confirm that you have read, understood, and agree to abide by Viction Wallet's Terms of Service and Privacy Policy

**Step 5:** Click **Create Password** to create a password and redirect to the respective process you selected

<figure><img src="/files/ol5NbfIB6WLv68UhldWJ" alt="" width="281"><figcaption></figcaption></figure>

### How to Lock Wallet? <a href="#how-to-lock-wallet" id="how-to-lock-wallet"></a>

To increase security, you can lock the wallet when not in use, or the wallet will be automatically locked after a period of inactivity.

**Step 1:** Open Viction Wallet

**Step 2:** At the home screen, click the Lock icon&#x20;

<figure><img src="/files/RUybfswDhAzqucdE1eP9" alt="" width="360"><figcaption></figcaption></figure>

→ After the wallet is locked, you will be redirected to the Unlock Wallet screen.

### How to Unlock Wallet? <a href="#how-to-unlock-wallet" id="how-to-unlock-wallet"></a>

**Step 1:** Having created a Viction Wallet

**Step 2:** Input **Password**

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

**Step 3:** Click **Unlock Wallet** to access Viction


# How to create a new wallet

## How to create a new wallet? <a href="#how-to-create-a-new-wallet" id="how-to-create-a-new-wallet"></a>

**Step 1:** Access to Viction Wallet;

**Step 2:** Click on the Wallet section at the top left corner, then click the Add Wallet icon on the top left corner;

<div><figure><img src="/files/pX6trtBHIe0JLaI0fB9i" alt=""><figcaption></figcaption></figure> <figure><img src="/files/ivHPJevuNbQ5Pl0TVR7o" alt=""><figcaption></figcaption></figure></div>

**Step 3**: Click **Create a new wallet** to initiate a new wallet

<figure><img src="/files/zZvuTk1fMN9vWSNnjfhi" alt="" width="292"><figcaption></figcaption></figure>

**Step 4:** Tick the checkbox to confirm that you understand that if you lose your passphrase, you will not be able to access your funds, and Click **I am Ready** to go to the next step;

<figure><img src="/files/t0WfGcMcNEiObcnYJLjX" alt="" width="289"><figcaption></figcaption></figure>

**Step 5**: Backup passphrase

{% hint style="info" %}
You should store the passphrase in a safe place and never share it with anyone
{% endhint %}

* Click **Copy Passphrase** to copy the passphrase to your device's clipboard
* Click **Continue** to go to the passphrase verification step

<figure><img src="/files/nE8btnY7wPCU6zhlzMjh" alt="" width="289"><figcaption></figcaption></figure>

**Step 6**: Verify the passphrase by clicking on words to put them into the right order

* Click **Verify** and the system will verify the passphrase

<figure><img src="/files/2jcAxbwXRUsYDlsHdZq9" alt="" width="288"><figcaption></figcaption></figure>

**Step 7:** Input wallet name, select avatar, and click **Start Using** to complete the process

<figure><img src="/files/9lApO5EjdWAJtZBiLFH4" alt="" width="290"><figcaption></figcaption></figure>

## How to switch wallets? <a href="#how-to-switch-wallet" id="how-to-switch-wallet"></a>

**Viction Wallet** supports multiple wallets, therefore users can switch from one wallet to another just in a few simple steps as below:

**Step 1:** On the home screen of Viction Wallet, click on the Wallet section at the top left corner;

**Step 2:** Select a wallet that you want to switch to.


# How to restore a wallet?

Users can import their existing wallets into Viction Wallet to enjoy its features.

**Step 1:** Access Viction Wallet;

**Step 2:** Click the wallet section at the top left corner, then click the add wallet icon on the top right corner;

<div><figure><img src="/files/iZqnPEZ7oCrV7hRqbv7o" alt="" width="375"><figcaption></figcaption></figure> <figure><img src="/files/uwnsUqDRZU1MONMgqLJq" alt="" width="375"><figcaption></figcaption></figure></div>

**Step 3:** Select **Passphrase or Private key** option to restore your wallet

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

**Step 4:** Input **Passphrase/Private key** to restore then click **Restore** to import the wallet;

* **Using Passphrase:** You will need to choose the derivation standard. If your wallet uses an old derivation standard, select Old Standard. Otherwise, choose New Standard
* **Using Private key**: Viction Wallet will automatically correct the derivation standard based on the private key you provided.&#x20;

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

**Step 5:** Input wallet name, avatar and click **Start Using** to complete the process;

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


# Wallet settings

We have developed the “Wallet Settings” feature for users to change their profiles, backup passphrases, manage connections, remove their wallet or view their wallet address.

## How to Change Profile? <a href="#how-to-change-profile" id="how-to-change-profile"></a>

Allows users to change profile

**Step 1:** On the home screen, select the wallet section at the top left corner

**Step 2:** Click on the Settings icon on the right corner of the wallet for which you want to get it's detail

**Step 3:** Click **Change Profile,** then input the information you want to change:

* Wallet name
* Wallet avatar

**Step 4:** After changing the information, click **Save** to complete the process

<div><figure><img src="/files/m4OzkLcPFqZMz3YtWntw" alt=""><figcaption></figcaption></figure> <figure><img src="/files/NxVbVuGNnv1P8LkimbVk" alt=""><figcaption></figcaption></figure></div>

## How to Backup Passphrase? <a href="#how-to-backup-passphrase" id="how-to-backup-passphrase"></a>

> * If the user creates a new wallet or imports the wallet with a passphrase → The system will display both passphrase and private key
> * If the user imports the wallet with a private key → The system only shows private key

{% hint style="info" %}
**Passphrase** and **Private Key** must be saved in a safe place when users create wallets on Viction Wallet.
{% endhint %}

However, PassPhrase and Private key can be revealed by following the steps below if the user could not remember:

**Step 1:** On the home screen, select the wallet section at the top left corner

**Step 2:** Click on the Settings icon on the right corner of the wallet for which you want to get it's detail

**Step 3:** Click **Backup Passphrase**

**Step 4**: Click **Backup** to reveal the Private Key and Passphrase of the wallet

<div><figure><img src="/files/rX2SROoKiIERaKkq1vQe" alt=""><figcaption></figcaption></figure> <figure><img src="/files/oKc7epCQp4OLyDxWuMBx" alt=""><figcaption></figcaption></figure> <figure><img src="/files/3nLLy4dgTAiLLNqNWKxX" alt="" width="360"><figcaption></figcaption></figure></div>

## How to Revoke Connection? <a href="#how-to-revoke-connection" id="how-to-revoke-connection"></a>

We’ve developed the “Revoke Connection” feature to make sure that the connected website or Dapp no ​​longer has access to your wallet address.

**Step 1:** On the home screen, select the wallet section at the top left corner

**Step 2:** Click on the Settings icon on the right corner of the wallet for which you want to get it's detail

**Step 3:** Click **Manage Connections,** then select a specific connection and click **X** icon to revoke that connection

* Or click **Revoke all connections** to revoke all

**Step 4:** Click **Revoke** to complete the process

<div><figure><img src="/files/iWZ4DNuOS4lVzGuxWkap" alt=""><figcaption></figcaption></figure> <figure><img src="/files/wOJqJjS7y1hvR2gbLD1k" alt=""><figcaption></figcaption></figure></div>

## How to Remove wallet? <a href="#how-to-remove-wallet" id="how-to-remove-wallet"></a>

Allows users to remove their wallet from Viction wallet

**Step 1:** On the home screen, select the wallet section at the top left corner

**Step 2:** Click on the Settings icon on the right corner of the wallet for which you want to get it's detail

**Step 3:** Click **Remove Wallet,** then click **Remove** on confirmation popup to complete the process

<div><figure><img src="/files/IuaBf5W8uJrfmFO4FQj7" alt=""><figcaption></figcaption></figure> <figure><img src="/files/iLY8vATp9IbQQm4RLoa9" alt=""><figcaption></figcaption></figure></div>

## How to view wallet address? <a href="#how-to-view-wallet-address" id="how-to-view-wallet-address"></a>

**Step 1:** On the main screen, click the wallet section at the top left corner

**Step 2:** Click on the Settings icon on the right corner of the wallet for which you want to get it's detail

**Step 3**: Click on **QR icon** on the top left of the screen

<div><figure><img src="/files/uAGFr3mQYqOoGSQyxcb2" alt=""><figcaption></figcaption></figure> <figure><img src="/files/19vrSceYAakq47cyIQqS" alt=""><figcaption></figcaption></figure></div>


# Send & Receive Tokens

### How to Send token? <a href="#how-to-send-token" id="how-to-send-token"></a>

Allow users to send a chosen token amount to a specific wallet address.

**Step 1:** Access to Viction wallet

**Step 2:** Click **Send**, then select a specific token

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

**Step 3:** Input the token amount then click **Next**

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

*Notes*:

* If your account balance is insufficient or your address is incorrect, you will get an error message
* You can custom gas fee

**Step 4**: Input the recipient address in these ways:

* Enter recipient address
* Click on the contact icon to select the wallet available in Viction *(Show only wallets other than sending wallet)*
* Click the **Paste** button to paste the address that you have copied into the clipboard

→ Then click **Review**

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

**Step 5:** Click **Confirm** to confirm transaction

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

After the transaction has been finalized, the sender will be redirected to a transaction details page, and the recipient will get a message that they have received the assets.

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

### How to Receive a token? <a href="#how-to-receive-token" id="how-to-receive-token"></a>

The receiving address can be displayed or copied to the clipboard easily by following these steps:

**Step 1:** On the home screen, click **Receive**

**Step 2:** Select a specific token

**Step 3:** Click on the **Copy Address** or Scan the **QR code** to get the wallet address


# Add custom token

### How to add a custom token? <a href="#how-to-add-custom-token" id="how-to-add-custom-token"></a>

We have developed the “Add Custom Token“ feature for users to input some new tokens to interact with

**Step 1:** On home screen, click **Add Custom Token**

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

**Step 2:** Input information in the following fields:

* Contract Address
* Name
* Symbol
* Decimals
* Icon URL (optional)

{% hint style="info" %}
If it is in the token data file or not:

* If yes → auto-filled token name, token symbol, decimal
* If no → user inputs these fields (token name, token symbol, decimal)
  {% endhint %}

**Step 3:** Then click **Add** to complete the process

<figure><img src="/files/BkcwFpPXff0wrh0fipzy" alt="" width="360"><figcaption></figcaption></figure>


# Manage Tokens

### How to hide/show tokens? <a href="#how-to-hide-show-tokens" id="how-to-hide-show-tokens"></a>

The “Manage Tokens” feature allows users to hide or show tokens in their wallet

**Step 1:** On the home screen, click the custom icon

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

**Step 2:** Turn on the toggle to hide the token or Turn off the toggle to show the token

* You can click **Hide All** to hide all token or **Show All** to show all token

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

After hiding the token → that token at the Token tab will disappear

### How to remove token? <a href="#how-to-remove-token" id="how-to-remove-token"></a>

This feature only allows deleting custom tokens

You can remove a custom token by following the steps below:

**Step 1:** On the home screen, click the custom icon

**Step 2:** Click **X** icon on the left corner token logo to remove the custom token

<figure><img src="/files/3bxds0UkBeWVZKjtIE1j" alt="" width="360"><figcaption></figcaption></figure>

After removing the custom token → that token at the Token tab will disappear.


# Send NFT

### How to send NFT? <a href="#how-to-send-nft" id="how-to-send-nft"></a>

Viction Wallet allows users to store, send, and receive non-fungible tokens (NFTs)

**Step 1:** On the home screen, click the **NFTs tab**

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

**Step 2:** Click on a NFT to see the NFT detail, then click **Send** to make a transaction

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

**Step 3**: Input the recipient address in these ways:

* Enter recipient address
* Click on the contact icon to select the wallet available in Ninji *(Show only wallets other than sending wallet)*
* Click the **Paste** button to paste the address that you have copied into the clipboard

→ Then click **Review**

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

**Step 4**: Click **Confirm** to confirm transaction

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

After the transaction has been finalized, the sender will be redirected to a transaction details page, and the recipient will get a message that they have received the NFT.

<figure><img src="/files/oXt4iiivnU1zzMQIWLtr" alt="" width="360"><figcaption></figcaption></figure>


# General settings

We have developed the “Wallet Settings” feature for users to change themes, change passwords, and change networks.

### How to change themes? <a href="#how-to-change-themes" id="how-to-change-themes"></a>

**Step 1:** On the home screen, click the **Discover tab**

**Step 2:** Click **General** then turn on the Dark Mode toggle to change the dark theme or turn off the Dark Mode toggle to change the light theme

<div><figure><img src="/files/whgXVisOLfysBacbZ5v6" alt=""><figcaption></figcaption></figure> <figure><img src="/files/ZqREaJ0ujrvCo3fEmWv0" alt=""><figcaption></figcaption></figure> <figure><img src="/files/LpacASjmEfqVXKzfYO8g" alt=""><figcaption></figcaption></figure></div>

### How to change password? <a href="#how-to-change-password" id="how-to-change-password"></a>

**Step 1:** On the home screen, click the **Discover tab**

**Step 2:** Click **Security & Privacy** then click **Change Password**

**Step 3**: Input your current password then click **Next**

<div><figure><img src="/files/vmLanSNUtlhWxx3MXsig" alt=""><figcaption></figcaption></figure> <figure><img src="/files/fmPWPc5NpnAwEUpfOXA4" alt=""><figcaption></figcaption></figure></div>

&#x20;

**Step 4:** Input new password and confirm new password then click **Confirm** to change new password

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


# Developer Guide

Welcome to Viction Wallet Developer Guide. This documentation contains guides for developers to get started developing on Viction Wallet Extension.‌

## The easiest way to connect to Viction Wallet

Check if the provider is window\.viction, if not, please replace it with the exclusive Viction Wallet provider window\.viction.

For example, see below:

```
function getProvider() {
  const provider = window.viction;
  if (!provider) {
    return window.open('https://chrome.google.com/webstore/detail/tomo-wallet/nopnfnlbinpfoihclomelncopjiioain?hl=vi');
  }
  return provider;
  }
```

**ChainID:**

| Hex  | Decimal | Network | Hex  | Decimal | Network      |
| ---- | ------- | ------- | ---- | ------- | ------------ |
| 0x58 | 88      | Viction | 0x64 | 100     | Gnosis Chain |

Use eth\_chainId or net\_version to returns the current network/chain ID

### To detect Viction Wallet Extension

```
if(window.Viction ){
    console.log('Viction Extension is installed!');
}
```

**Notice**\
Viction Testnet is under development and not available now

## To connect Viction Wallet Extension

***

#### Access a user's accounts

We recommend providing a button to allow users to connect Viction Wallet to your dapp. Selecting this button should call eth\_requestAccounts to access the user's accounts.

```
//Alias for connection
window.viction.request({method: 'eth_requestAccounts'});​
```

#### Handle accounts[​](https://docs.metamask.io/wallet/how-to/connect/access-accounts/#handle-accounts)

Use the eth\_accounts RPC method to handle user accounts. Listen to the accountsChanged provider event to be notified when the user changes accounts.

```
// Connect & get accounts
window.viction.request({method: 'eth_accounts'});
```

#### To check if Dapp connected

```
window.viction.isConnected();
```

### To disconnect Viction Wallet Extension

To disconnect Viction Extension, please use:

```
window.viction.disconnect()
```

## To experience functions

Once your account is connected, let's start experiencing more functions.‌

### Account

#### How to get Current Account

return Promise\<Array\[String]>

* If wallet can not be found, return \[] instead of throw Error

```
window.viction.request({ method: 'eth_accounts' }).then(accounts => {
  if (accounts[0]) {
    // Do something with accounts
  } else {
    // Wallet not found
  }
})
```

### Sign Transaction

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

eth\_signTypedData\_v1, and eth\_signTypedData\_v3 are deprecated. We highly recommend user to use eth\_signTypedData\_v4 or personal\_sign.
{% endhint %}

#### Personal\_sign

personal\_sign provides a simple means to request signatures that are human-readable and don't require efficient processing on-chain. It's commonly used for signature challenges authenticated on a web server.

Viction Wallet implements both personal\_sign and eth\_sign. You might need to check what method your supported signers use for a given implementation.

```
method: 'personal_sign',
params: [msg, from],
```

#### eth\_signTypedData\_v4

eth\_signTypedData\_v4 offers highly legible signatures that can be processed efficiently on-chain. Adheres to the [EIP-712 ](https://eips.ethereum.org/EIPS/eip-712)standard, enabling users to sign sign typed structured data that can be confirmed on-chain.

```
  const msgParams = JSON.stringify({
    domain: {
      chainId: 0x58,
      name: 'Ether Mail',
      verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
      version: '1',
    },

    message: {
      contents: 'Hello, Bob!',
      attachedMoneyInEth: 4.2,
      from: {
        name: 'Cow',
        wallets: [
          '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
          '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
        ],
      },
      to: [
        {
          name: 'Bob',
          wallets: [
            '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
            '0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57',
            '0xB0B0b0b0b0b0B000000000000000000000000000',
          ],
        },
      ],
    },
    
    primaryType: 'Mail',
    types: {
      EIP712Domain: [
        { name: 'name', type: 'string' },
        { name: 'version', type: 'string' },
        { name: 'chainId', type: 'uint256' },
        { name: 'verifyingContract', type: 'address' },
      ],
      Group: [
        { name: 'name', type: 'string' },
        { name: 'members', type: 'Person[]' },
      ],
      Mail: [
        { name: 'from', type: 'Person' },
        { name: 'to', type: 'Person[]' },
        { name: 'contents', type: 'string' },
      ],
      Person: [
        { name: 'name', type: 'string' },
        { name: 'wallets', type: 'address[]' },
      ],
    },
  ;
```

{% hint style="info" %}
**Note:**

Gas limit​: is an optional parameter, since Viction Wallet automatically calculates a reasonable gas price.

chainid: The chain ID is derived from the user's current selected network at window\.Viction.net\_version.
{% endhint %}

#### personal\_ecRecover

personal\_ecRecover returns the address associated with the private key that was used to calculate a signature.

```
method: 'personal_ecRecover',
params: [message, signature],
```

### Transfer

This method requires that the user has granted permission to interact with their account first, so please make sure to call eth\_requestAccounts or wallet\_requestPermissions first.

#### eth\_sendTransaction

return Promise\<hash>

```
window.viction.request({
  method: 'eth_sendTransaction',
  params: [
    {
      from: 'string',
      to: 'string',
      gas: 'string',
      gasPrice: 'string',
      value: 'string',
      data: 'string',
      nonce: 'string'
    }
  ]
})
```

### Decrypt & Encrypt

#### eth\_decrypt

Requests that Viction Wallet decrypt the specified encrypted message.

* The message must have been encrypted using the public encryption key of the specified Ethereum address.

return Promise\<string>

```
window.viction.request({
  method: 'eth_decrypt',
  params: [encryptedMessage, accounts[0]],
  })
   .then((decryptedMessage) =>
    console.log('The decrypted message is:', decryptedMessage)
  )
  .catch((error) => console.log(error.message));
})
```

#### eth\_getEncryptionPublicKey

Requests that the user share their public encryption key. Returns a public encryption key, or rejects if the user denies the request.

return Promise\<string>- The public encryption key of the Ethereum account whose encryption key should be retrived

```
let encryptionPublicKey
window.viction.request({
  method: 'eth_getEncryptionPublicKey',
  params: [accounts[0]], // you must have access to the specified account
  })
  .then((result) => {
    encryptionPublicKey = result;
  })
  .catch((error) => {
    if (error.code === 4001) {
     
      // EIP-1193 userRejectedRequest error
      console.log("We can't encrypt anything without the key.");
    } else {
      console.error(error);
    }
  });
```

#### Encrypt

```
const ethUtil = require('ethereumjs-util');
const encryptedMessage = ethUtil.bufferToHex(

  Buffer.from(
    JSON.stringify(
      sigUtil.encrypt(
        {
          publicKey: encryptionPublicKey,
          data: 'hello world!,
          version: 'x25519-xsalsa20-poly1305',
        }
      )
    ),
    'utf8'
  )
);
```

### List of events

Currently we only support some action event from wallet extension

```
window.viction.on('event_name', callback);

​//Example

window.viction.on('close', () => window.location.reload());

window.viction.on('accountsChanged', () => window.location.reload());
```

| Events          | Trigger                                          |
| --------------- | ------------------------------------------------ |
| accountsChanged | Receive when active account changed in Extension |
| networkChanged  | Receive when active network changed in Extension |

| Method               | Description           |
| -------------------- | --------------------- |
| on(event, callback)  | Add event listener    |
| off(event, callback) | Remove event listener |


# Privacy Policy

Date Last Revised: Nov 23, 2023

This Privacy Policy describes how Viction Labs, LLC ("Viction Wallet”, "We", "Our", and "Us") collects, uses, processes, discloses, shares, transfers, and protects your personal information or data when you:&#x20;

1. access or use Viction Wallet applications (including unhosted mobile device application and browser extension) (collectively, “Applications”) provided on or in connection with Services, as described in our [Terms of Service](https://docs.viction.xyz/general/how-to-connect-to-viction-network/viction-wallet/term-and-services) (collectively, the “Services”); and
2. provide us with your personal data.&#x20;

This Privacy Policy (together with our Terms of Service and any other documents referred to herein) sets out the basis on which any personal data we collect from you, or that you provide to us, will be processed, used and/or disclosed by us. Please read the following carefully to understand our practices in processing your personal data, as well as your rights regarding your personal data and how we will treat it.

By visiting our Applications and/or submitting data to us, you are accepting and consenting to the collection, use, disclosure and processing of your personal data as described in this Privacy Policy. Please refrain from accessing the Applications and do not provide any personal data to us if you disagree with the terms of this Privacy Policy.

We may change or amend this Privacy Policy from time to time without notice to you, in compliance with applicable laws or as we update our data usage and handling processes. Any changes we may make to this Privacy Policy in the future will be made available on Viction Wallet website and any such changes will become effective upon posting of the revised Privacy Policy. The updated Privacy Policy will supersede earlier versions and will apply to personal data provided to us previously. Please check back frequently to see any updates or changes to our Privacy Policy.&#x20;

For the avoidance of doubt, this Privacy Policy forms a part of the terms and conditions governing your relationship with us. This Privacy Policy supplements but does not supersede or replace any other consents you may have provided to us, or any other agreements or arrangements that you may have with us, in respect of your personal data.

For any questions or feedback in relation to this Privacy Policy or your personal data, or if you wish to make a complaint to us, please submit your requests, feedback or complaint to <support@viction.xyz>.

&#x20;When you contact us, we may require that you submit certain forms or provide certain information, including verification of your identity, before we are able to respond.

1. Your Personal Data&#x20;

“Personal data” is data that can be used to identify a natural person. Examples of personal data include name, transactional information based on your activities on our Applications and/or Services, and any other information of a personal nature.&#x20;

We may collect and process personal data provided directly by you. We also process, insofar as necessary, personal data provided to us by third parties, including publicly accessible data, personal data legitimately provided by other group companies, personal data collected through your use of our (or our service provider’s) digital technologies and services, and personal data provided by other trusted third parties (including our service providers).&#x20;

You are responsible for ensuring that all personal data that you provide to us is true, accurate, and complete.  You are responsible for informing us of any changes to your data in writing, so that we may take all reasonable measures to keep our records of your personal data correct and up to date.&#x20;

When our collection is based on consent, you have the choice, at any time, not to provide your personal data to us or to withdraw your consent previously provided to us. However, do note that if you do so, we may be unable to fulfill the purposes for which we require the personal data, continue to provide Services to you (e.g. processing your transactions), and/or fulfill any contractual relationship which may be in place between us.

Our Applications and/or Services are not intended to be accessed or used by children, minors or persons who are not of legal age. If you are a parent or guardian and you have reason to believe your child or ward has provided us with their personal data without your consent, please contact us.

In certain circumstances, you may also provide us with personal data of persons other than yourself (such as your officers, employees, agents, customers, family members and next-of-kin). If you do so, you represent and warrant that you have brought this Privacy Policy to his/her attention, informed him/her of the purposes for which we are collecting his/her personal data and that he/she has consented to your disclosure of his/her personal data to us for those purposes and accepts this Privacy Policy. You agree to indemnify and hold us harmless from and against any and all claims by such individuals relating to our collection, use and disclosure of such personal data in accordance with the terms of this Privacy Policy.

1. Personal Data you give us

You may voluntarily give us your personal data by filling in forms on the Applications or by corresponding with us by phone, e-mail or otherwise. This includes personal data you provide when you register on the Applications, use our Services or the services provided by our service providers, or when you report a problem with the Applications. See Clause 1.4 for more information on how we collect your personal data. &#x20;

Examples of personal data you may provide to us include (depending on the nature of your interaction with us) your name, email address, and any other information relating to any individuals which you have provided to us in any forms submitted to us, or via other forms of interaction with you. See Clause 1.2 for more information on the types of personal data we may collect from you.&#x20;

2. Personal data and/or information we collect about you&#x20;

With regard to each of your visits to or use of our Applications, we may collect the following information and/or personal data that are relevant to our relationship with you, as well as copies of documents verifying such information:

1. your financial information, including but not limited to, your transaction history     , your investment details, and any other information or documents in order to comply with domestic and international industry standards, government rules and regulations, particularly Anti-Money Laundering (AML) regulations, Know Your Customer (KYC) rules, and Counter-Terrorist Financing (CTF) regulations;
2. technical information, including but not limited to the Internet protocol (IP) address used to connect your computer to the Internet, your login information, browser type and version, time zone setting, browser plug-in types and versions, and information relating to your operating system and platform;
3. information about your visit and use of our Applications, including but not limited to the full Uniform Resource Locators (URL) clickstream to, through and from our Applications (including date and time), download errors, length of visits to certain pages, page interaction information (such as scrolling, clicks, and mouse-overs), and methods used to browse away from the page; and

You hereby agree that we are entitled to collect and use the above-listed personal data and/or information you have provided on our Applications or generated through your use or access of our Applications for the purposes listed in Clause 2 of this Privacy Policy.&#x20;

Apart from personal data, we may collect other types of information which are not related to an individual and which are anonymous. For example, the number of website visitors and the number of website users using a particular service.

3. How we collect your personal data&#x20;

We may collect your personal data directly or indirectly through various channels, such as:

1. when you register an account or Wallet with us through our Applications;&#x20;
2. when you log in, visit, use, access or download our Applications and Services;
3. when you authorize us to obtain your personal data from a third party;&#x20;
4. when you enter into agreements with us;&#x20;
5. when you transact with us, contact us or request that we contact you through various communication channels, for example, through social media platforms, messenger platforms, face-to-face meetings,  emails and letters;
6. when you attend events or functions organized by us;&#x20;
7. we seek information about you and receive your personal data in connection with your relationship with us;&#x20;
8. when you submit your personal data to us for any other reason;&#x20;
9. when you voluntarily complete any user survey or provide feedback to us via emails or any other electronic channels;
10. through automated data collection technologies upon visiting our Applications; and
11. in other situations where we may collect your information as may be described in this Privacy Policy or in our terms and conditions.
12. Personal Data we receive from other sources and third parties

Depending on your relationship with us, we may also collect and receive your personal data from third party sources, for example, from:&#x20;

1. public databases, public agencies, other public sources, credit bureaus, blockchain data;&#x20;
2. third parties whom you have authorised us to obtain your personal data from;&#x20;
3. our business partners such as third parties providing services to us (including but not limited to, our ID verification partners, marketing partners, advertising partners, our sub-contractors in technical, payment and delivery services, advertising networks, analytics providers, search information providers and credit reference agencies); and/or
4. your family members or friends who provide your personal data to us on your behalf. &#x20;

We may also receive personal data about you if you use any of the other websites or platforms we operate (or operated by our affiliate or related companies), or other services we (or our affiliate or related companies) provide.&#x20;

2. Processing your personal data
3. 1. General Purposes

We collect, use, disclose and process your personal data, including data provided by you, data we collect about you and data provided by third parties, in the following ways and upon the following grounds:

1. for the fulfillment of contractual obligations and/or transactions entered into between you and us, and to provide you with the information, or Services that you request from us;
2. facilitating the use of our Applications, including verifying, authenticating and/or establishing your identify;
3. facilitating business asset transactions; &#x20;
4. to notify you about changes to our Services;
5. to comply with any legal or regulatory obligations, applicable laws, regulations, codes of practices, guidelines, industry standards (domestic or global), government requests, or rules (including but not limited to Anti-Money Laundering (AML) regulations, Know Your Customer (KYC) rules, and Counter-Terrorist Financing (CTF) regulations), or to assist in law enforcement and investigations conducted by any governmental and/or regulatory authority;&#x20;
6. where it is strictly necessary (i.e. to protect the vital interests of the users or other natural persons, to fulfil the purpose of public interest, or to pursue our reasonable interests);
7. security purposes, e.g. to monitor and detect suspicious activities, to protect users from fraudulent activities, to protect our Applications, users' accounts, and archives from unauthorised access or usage, to prevent damage to our Applications and systems, and to protect against automated abuse such as spam, and phishing;&#x20;
8. communicating with you (through messages, emails, live chats or otherwise) and assisting you with your queries, requests, applications, complaints and feedback;
9. resolving any disputes or legal claims, investigating any complaint, claim or dispute or any actual or suspected illegal or unlawful conduct;
10. administrative purposes, including finance, IT and HR purposes, quality assurance and staff training, and compliance with internal policies and procedures, including audit, accounting, risk management and record keeping;&#x20;
11. carrying out research and statistical analysis, including the development of new products and services or evaluation, and improvement of our existing Services (including but not limited to, gaining better understanding of users' needs and behaviors, diagnosing any problems with our server, and quality assurance);
12. performing data analytics and related technologies on data, to enable us to deliver relevant content and information to you, and to improve our websites and digital platforms (e.g. ensuring that content from our Applications are presented in the most effective manner for you and for your computer);
13. managing and engaging third parties, data processors or subcontractors that provide services to us, e.g. IT services, technological services, delivery services, and other professional services (e.g. accountants, lawyers and auditors);&#x20;
14. such purposes that may be informed to you when your personal data is collected; and/or
15. any other reasonable purposes related to the aforesaid.&#x20;

Subject to the terms of this Privacy Policy, we shall not use or process your personal data for purposes other than the purposes stipulated in this Privacy Policy without your prior consent. Where your personal data is used for a new purpose and where required under applicable law, we shall obtain your consent. We may collect, use, disclose and process your personal data for other purposes, without your knowledge or consent, only where this is required or permitted by law.&#x20;

We may, if necessary or required by law, provide your personal data to law enforcement agencies, regulatory organizations, courts or other public authorities. Where appropriate, we will attempt to notify our customers about legal demands for their personal data. You agree that we may not be able to do so if such notification is prohibited by law or court order, when the request is an emergency, or when the burden or expense of notifying the customers would be unreasonable to us. We may dispute such demands when we believe that the requests are disproportionate, vague or lack proper authority, but we do not promise or undertake to challenge every demand.

2. Marketing purposes

In order for us, or for authorized third parties permitted by us, to market or advertise products, events, and/or services that are of specific interest and relevance to you, we may analyze, use, process and/or rely on your personal data provided to us, or data collected from your interactions with us. However, no marketing or advertising, using your personal data in non-aggregated and/or identifiable form would be carried out unless you have provided us with your consent to use your personal data for such marketing or advertising purposes. If you do not want us to use or process your personal data for the purposes of marketing or advertising, you can withdraw your consent at any time by contacting us. You can exercise your right to prevent such use or processing by checking certain boxes on the forms we use to collect your personal data. If you are an existing customer, we will only contact you by electronic means (e-mail or SMS or other means) with information about goods and services similar to those which were the subject of a previous sale or negotiations of a sale to you, subject to your consent. If you are a new customer, and where we permit selected third parties to use your data for marketing or advertising purposes, we (or they) will contact you by electronic means only, subject to your consent.&#x20;

3. Legitimate business interests

We may also collect, use, disclose and process your personal data for the following purposes to safeguard, support and/or carry out our company’s legitimate business interests such as:

1. processing of personal data for the purposes of our daily operations including billing and debt collecting;
2. managing our business and relationship with you (e.g. accurately carrying out and confirming your instructions, or for the purposes of providing you with rebates and other benefits), and providing services to our customers;
3. assistance of carrying out corporate restructuring plans;&#x20;
4. protecting our rights and interests, and those of our customers (e.g. processing of your data for the protection of the company’s legal position in the event of legal proceedings);&#x20;
5. processing for the purpose of reporting possible criminal acts (e.g. fraud) or threats to public security to competent authorities;
6. enforcing our terms and conditions, and obligations owed to us, or protecting ourselves from legal liability;&#x20;
7. managing our investor and shareholder relations;
8. complying with internal policies, procedures, and operations, including troubleshooting, data analysis, testing, research, statistical and survey purposes; and/or
9. process or share your personal data to facilitate acquisitions, mergers, or transfers of our business.
10. Storing of data
11. 1. Where we store your personal data

The security of your personal data is our top priority. We shall take care in implementing and maintaining the security of our services and Applications, as well as that of your personal data. We employ procedures and policies that incorporate industry best practices to ensure the integrity of your personal data and to prevent instances of unauthorized use.&#x20;

Please note that it is impossible to fully guarantee the security of your personal data. While we take reasonable steps to safeguard your personal data in our possession or under our control, you agree not to hold us liable or responsible for any loss or damage resulting from any unauthorized or unintended access that is beyond our control (e.g. hacking or cybercrimes), or abuse of your information. We recommend that you take independent safety precautions to protect your personal data, particularly your credential information such as your username and password. You hereby agree that we shall not be liable for any information leakage and other losses not caused intentionally or otherwise by our gross negligence, including, but not limited to, hacker attacks, power interruptions, or unavoidable technical failures. For the avoidance of doubt, we do not make any warranty, guarantee, or representation that your use of our systems or applications is safe and protected from malware, and other vulnerabilities. We also do not guarantee the security of data that you choose to send us electronically. Sending such data is entirely at your own risk.&#x20;

2. For how long will your data be stored?&#x20;

We will process and store your personal data for as long as it is necessary in order to fulfill the purposes we collected it for, and to satisfy our business, contractual, legal, regulatory and/or statutory obligations (including audit, accounting or reporting purposes). We may thus be required to retain certain information, including personal data or information of users, users' profiles, identification verification materials, information relevant to AML/KYC/CTF procedures, account information, account agreements, and other agreements between us and third parties, account statements, and other records, for an extended period of time.&#x20;

We will assess and respond to requests to delete personal data and we shall accordingly delete personal data provided that the personal data is no longer required in order to fulfill our business, contractual, legal, regulatory and/or statutory obligations, or the fulfillment of any obligations to preserve records according to applicable laws and regulations.&#x20;

In general, how long we keep your personal data depends on the nature of the data, e.g. we keep personal data for at least the duration of the limitation period for bringing claims if the personal data may be required to commence or defend legal proceedings. Some information may also be retained for longer e.g. where we are required to do so by law.

3. Anonymized data

In some circumstances we may anonymize and/or aggregate your personal data so that it can no longer be associated with you, in which case we are entitled to retain and use such data without restriction.

4. Disclosure of your personal data&#x20;

Your personal data may be made available, disclosed or shared to our related parties and/or within our group of companies in order to provide our Services or Applications to you, for management and compliance purposes, and to utilize shared group IT functions.&#x20;

We may share, transfer, disclose, or allow access to your personal data to third parties in connection with the purposes described in Clause 2, including without limitation the purposes described below:

1. to administer or process a transaction, or services you have authorized or requested, or in the context of facilitating the execution of a transaction;
2. to facilitate or otherwise enable the sale of tokens (or other products) or any other activity on the Applications which you choose to participate in, including the provision of your personal data to the third party entities to comply with applicable legal, regulatory, compliance or statutory requirements (e.g. AML/KYC/CTF procedures);
3. to carry out or aid in certain functions during the account opening, updating      and/or maintenance process, such as, but not limited to, account processing, surveillance, reconciliation, execution, document retention requirements, and document dissemination;
4. to process payments which you have authorized (e.g. disclosure to financial institutions that we have partnered with);
5. to operate and/or improve our Services;
6. if we are discussing selling or transferring part or all of our business, to a purchaser of our business. The information may be transferred to prospective purchasers under suitable terms as to confidentiality;
7. if we are reorganised or sold, information may be transferred to a buyer who can continue to provide the Applications and related services to you;&#x20;
8. to facilitate account closing where you have a deficient balance, or upon excessive instances where you do not have sufficient funds in your account;
9. to third parties that provide services to us, such as, but not limited to, data providers, technology providers, consulting, sales, client support operations, payment processing, authentication services, professional services (including accountants, lawyers and auditors), and technical support or services;
10. to third parties in order to fulfil such third party products and/or services as may be requested or directed by you;
11. if we are defending a legal claim your information may be transferred as required in connection with defending such claim;
12. to law enforcement agencies, authorities, public agencies and government officials, or other third parties when we are compelled to do so by a subpoena, court order, or similar legal procedure, or when we believe in good faith that the disclosure of personal data is necessary to prevent physical harm or financial loss, to report suspected illegal activity or to investigate violations of any of our terms and conditions, or any other applicable policies; and&#x20;
13. other circumstances under which we may disclose your personal data such as:
14. 1. to comply, as necessary, with applicable laws and regulatory requirements;
    2. respond to mandatory legal or governmental requests or demands for information;
    3. meet national security requirements;
    4. enforce our agreements, policies, procedures and/or Terms of Service;
    5. protect ourselves, our affiliates, our users, our counterparties or the general public from illegal activities; and
    6. to respond to an emergency that requires disclosure of your personal data.&#x20;

You may freely opt-out of having your personal data shared with third parties (or for any of the above listed purposes), or from allowing us to use your personal data for any purpose that is incompatible with the purposes for which we originally collected or subsequently obtained your authorization as stipulated in this Privacy Policy. Please contact us if you wish to opt-out.&#x20;

We will ensure that all companies and/or third parties to whom we disclose your personal data will only process it in accordance with our instructions and on our behalf. We will, where appropriate and permissible, enter into contracts with these third parties to protect your personal data in a manner that is consistent with all applicable laws. All such companies and third parties will be required by us to meet the requirements of applicable data protection legislation and our strict privacy and retention policies to keep your personal data secure at all times.

5. Transfer of Personal Data to other countries

You agree and acknowledge that we may transfer your personal data to different jurisdictions in connection with the purposes described in this Privacy Policy:&#x20;

1. from the jurisdiction where it is collected (or where you are located) to any other jurisdictions that we operate in; and
2. to third parties in other jurisdictions.&#x20;

When we transfer your personal data internationally and where required by applicable law, we will put in place appropriate safeguards. You may obtain details of these safeguards by contacting us.

6. Third-Party Collection of Personal Information

Our Applications may contain links to other websites or platforms that are not owned or maintained by us. These links are provided only for your convenience. You may also be accessing our Applications through third party websites and/or platforms. This Privacy Policy only applies to our Applications. When visiting third party websites or using their platforms, their privacy policies apply to their collection, use or disclosure of the personal data you disclose to them. For each token project listed on the Applications, the privacy policy of the respective third party behind each token project will apply. You must confirm that you are agreeable to the privacy policy of the relevant third party before proceeding further with any token project.

You hereby acknowledge that we shall not be responsible for the products, services, or descriptions of products or services that you receive from these third-party websites or platforms, token projects listed on the Applications or to the content or privacy practices of those websites, platforms or token projects. This Privacy Policy shall not be applied to any such third-party products and services that you access through our Applications. You knowingly and voluntarily assume all risks of using such third-party websites or platforms to purchase products and services, and you agree that we shall have no liability whatsoever concerning such third-party websites or platforms and your usage of them.

7. Your rights

Depending on the jurisdiction that you are in or where we operate, you may enjoy certain rights under applicable law in relation to our collection, use, disclosure and processing of your personal data. Such rights may include:

1. Access: you may ask us if we hold your personal data and, if we are, you can request access to your personal data free of charge. This enables you to receive a copy of and information on the personal data we hold about you;
2. Correction: you may request for the rectification or correction of your personal data that is incomplete or inaccurate;
3. Restriction: you may withdraw consent for our use or process of your personal data, or ask us to suspend the process of your personal data (e.g. if you want us to establish its accuracy);
4. Objection: where we are processing your personal data based on a legitimate interest (or those of a third party), you may object to processing on this ground;
5. Portability: you may request for the transfer of your personal data to another party under certain circumstances; and
6. Erasure: you may request the erasure, deletion or removal of your personal data that we hold about you in certain circumstances.&#x20;

If you wish to exercise any of your rights, you may contact us at <support@viction.xyz> . We may require that you submit certain forms or provide certain information to process your request. Where permitted by law, we may also charge you a fee to process your request.

We may be permitted under applicable laws to refuse a request, for example, we may refuse (a) a request for erasure where the personal data is required for in connection with claims; or (b) an objection request and continue processing your personal data based on compelling legitimate grounds for the processing.

<br>


# Term and Services

Date Last Revised: Nov 23, 2023

1. Introduction

These Terms of Service (“Terms”), which can be viewed as an agreement between an individual or entity user or authorized representative of such user (“you”, “your”, “user”) and Viction Labs, LLC (“Viction      Wallet”, “we”, “us”, “our”), govern your access and use of all versions of the App (as defined below) and the Services (as defined below).  The App makes certain software services accessible to users via an unhosted mobile device application and browser extension marketed, advertised, or marked by us with the name “Viction Wallet” from time to time (the “App”).

By accessing the App and/or using any or all the Services, you accept and agree to be legally bound by these Terms and all the terms incorporated herein by reference.

Viction Wallet reserves the right to modify or replace any of these Terms in its sole discretion from time to time. The “Date Last Revised” specified on these Terms indicates the date on which the Terms were last modified. Please check these Terms periodically to ensure that you are aware of and in compliance with the most current version of these Terms. Any revision to the Terms shall take effect immediately upon such revised Terms being made accessible via the Services. Such revised Terms shall be binding on you, and by your continued access and/or use of the App for purposes of participating in the Services, you shall be deemed to agree to and accept the Terms as revised.&#x20;

THE APP IS DEVELOPED AND PROVIDED ON AN “AS-IS” AND “AS AVAILABLE” BASIS BY VICTION WALLET AND/OR ITS AFFILIATES, AND VICTION WALLET AND ITS AFFILIATES (SAVE TO THE EXTENT PROHIBITED BY APPLICABLE LAWS) EXPRESSLY DISCLAIM ANY AND ALL REPRESENTATIONS, WARRANTIES AND/OR CONDITIONS OF ANY KIND IN RESPECT THEREOF. IF YOU ARE IN ANY DOUBT AS TO THE ACTION YOU SHOULD TAKE, YOU SHOULD CONSULT YOUR LEGAL, FINANCIAL, TAX AND/OR OTHER PROFESSIONAL ADVISOR(S). IF YOU DO NOT AGREE TO THESE TERMS, PLEASE DO NOT ACCEPT THESE TERMS, OR PARTICIPATE IN THE SERVICES, AND MUST CANCEL YOUR ACCESS IMMEDIATELY.

1. In these Terms, the following words, and expressions, whenever used in this Agreement shall have the respective meanings indicated below:

“Digital Asset” means any digital asset (including a virtual currency or virtual commodity) which is a digital representation of value based on (or built on top of) a cryptographic protocol of a computer network.

“Law” means the laws, statutes, ordinances, rules, regulations, judgments, injunctions, orders, and decrees of any governmental authority.

“Viction” (formerly “Tomochain") is a scalable blockchain powered via Proof-of-Stake Voting (PoSV) consensus, in mainnet since 2018, taking a community-driven approach to accelerate the mass adoption of web3 applications. Information about Viction is available on its official website <<https://viction.xyz/>>.

“Services” means the services that may be provided by us as defined in Section 4.

“Wallet” means a digital storage component provided by the App, encompassing both the native wallets generated by the App and third-party wallets that can be imported and accessed within the App, for storing, managing, and facilitating transactions involving your Digital Assets stored on the blockchain(s) supported by the App.&#x20;

2. Acknowledgement of Risk: As with any asset, the value of Digital Assets can increase or decrease and there can be a substantial risk that you lose money buying, selling, holding, or investing in Digital Assets. You should consult your financial advisor, legal or tax professional regarding your specific situation and financial condition and carefully consider whether trading or holding Digital Assets is suitable for you. &#x20;

Viction Wallet is not registered with the U.S. Securities and Exchange Commission and does not offer securities services in the United States or to U.S. persons.  You acknowledge that Digital Assets are not subject to protections or insurance provided by the Federal Deposit Insurance Corporation or the Securities Investor Protection Corporation.

3. NOT FINANCIAL ADVICE: WE DO NOT PROVIDE INVESTMENT OR FINANCIAL ADVICE OR CONSULTING SERVICES. WE ARE SOLELY THE PROVIDER OF VICTION WALLET AND WE DO NOT ADVISE OR MAKE RECOMMENDATIONS ABOUT ENGAGING IN DIGITAL ASSET TRANSACTIONS OR OPERATIONS. DECISIONS TO ENGAGE IN TRANSACTIONS OR PERFORM OPERATIONS INVOLVING DIGITAL ASSETS SHOULD BE TAKEN ON YOUR OWN ACCORD.
4. Wallet Registration and Security

You must either import or create a Wallet in order to use Viction Wallet. When you create a Wallet, you will be assigned a private key. You agree to immediately notify us of any unauthorized use of your private key or any other breach of security of your Wallet. Notwithstanding the foregoing, you acknowledge and agree that you shall assume all risks related to the use of the Services and you shall be solely responsible for maintaining the confidentiality and security of your private key. When you create a Wallet, you are strongly advised to take precautions in order to avoid loss of access to and/or control over your Wallet. Suggested measures include, but are not limited to, the following: (a) creating a strong unique password that you do not use for any other purpose (i.e. different to your phone password or any other passwords you use for websites, online services, etc.) and leveraging biometric authentication if available; (b) do not store the private key and Secret Phrase in plain text online or in an unsecured physical location; (c) limiting access to your devices and your Wallet; (d) taking all necessary precautions against malware on your devices and networks; and (e) promptly notifying us if you discover or otherwise suspect any security breaches related to your Wallet. Notwithstanding anything to the contrary herein, we shall have no liability whatsoever in connection with activities that occur on your Wallet with or without your authorization.

2. Payment and Fees&#x20;

We may charge fees for some or part of the Services we make available to you. We reserve the right to change those fees at our discretion. Fees applicable to the Services or any component of the Services, if any, shall be set forth or displayed in the App from time to time.

You may incur charges from third parties for use of linked services. For example, you may be charged fees via the DApps and/or DEXs that you may access via the App.&#x20;

3. Transaction Fees

There may be transaction fees (e.g. mining fees) associated with your virtual currency transactions that are required by Viction or any other blockchain network with which the Services are compatible. You must ensure that you have an adequate balance in your Wallet and/or “gas” to complete transactions before initiating a transaction. You acknowledge and agree that we will not be liable for any failed transactions or losses you incur due to incorrectly set transaction fees (i.e. too low or too high) or due to insufficient funds or gas associated with your Wallet address. You further acknowledge and agree that we do not have access to your or anyone else’s transactions.

4. Taxes

It is your responsibility to determine what, if any, taxes apply to the transactions that you have submitted transaction details for via the Services, and it is your responsibility to report and remit the correct tax to the appropriate tax authority. You agree that we are not responsible for determining whether taxes apply to your transactions or for collecting, reporting, withholding, or remitting any taxes arising from any Digital Asset-related transactions.

5. Ownership and Control

You own and control Digital Assets held in your Wallet. As the sole owner of digital assets in your Wallet, you shall bear all risk of loss of such digital assets. Viction Wallet shall have no liability for digital asset fluctuations or loss associated with your use of the App. At any time, subject to outages, downtime, and other applicable policies, you may withdraw your Digital Assets by sending it to a different blockchain address.

3. Authority/Terms of Service

Viction Wallet retains all authority over the issuing, maintenance, and closing of the Services. The decision of Viction Wallet’s management, concerning any use of the Services, or dispute resolution, is final and shall not be open to review or appeal.

4. Services
5. Our Services. The App allows you to:

<br>

2. Wallet Address, Private Key, and Backup Capabilities

An encrypted backup of certain information associated with your Wallet can be stored on eligible devices. The private key is associated with the Wallet address and, together, they can be used to authorize the transfer of Digital Assets to and from that Wallet address. You are solely responsible for the retention and security of your private key and any mnemonic phrase (“Secret Phrase”) associated with your Wallet. Your Secret Phrase is the only way to access the Digital Assets associated with your Wallet. Anyone that has access to your Secret Phrase can access your Digital Assets. You must keep your Wallet address, Secret Phrase, and private key access information secure. It is very important that you backup your private keys, backup phrases or passwords. Failure to do so may result in the loss of control of Digital Assets associated with your Wallet. You acknowledge and agree that we do not receive or store your Wallet password, encrypted private key, unencrypted private key, or Secret Phrase associated with your Wallet. We cannot generate a new password for your Wallet if you fail to remember your original password. If you have not safely stored a backup of any Wallet address and private key pairs maintained in your Wallet, you accept and acknowledge that any Digital Assets you have associated with such Wallet address will become inaccessible. You agree that Viction Wallet and its affiliates shall have no responsibility or liability whatsoever in the event you are unable to access your Wallet for any reason including without limitation your failure to keep your Wallet address, Secret Phrase and private key information secure.

3. Use of Third Party Materials

If you access or use DApps or DEX, including, without limitation, DApp functionality embedded within the Services such as the trade/swap Digital Assets function (“Third Party Materials”), you acknowledge and agree that:

1. Viction Wallet makes no warranties or representations, express or implied, about such linked Third Party Materials, the third parties they are owned and operated by, the information contained on them, the suitability of their products or services, or the assets they make accessible;
2. Viction Wallet is not responsible for your access or use of Third Party Materials and shall have no liability whatsoever in connection with your use of Third Party Materials, including, without limitation, any transactions you dispute;&#x20;
3. the limits of amounts that you may exchange via Third Party Materials per day shall be subject to any requirements of the third-party developed smart contracts;
4. blockchain operations are irrevocable meaning when you conduct any transactions via Third Party Materials, you shall be solely responsible for the consequences of any issues associated with such transactions, including, without limitation, your transfer to an incorrect address or problems associated with the node servers selected by you;
5. when you use Third Party Materials, third-party developed smart contracts may charge you handling fees and/or service fees and any information displayed on Viction      Wallet relating to such fees are for your reference only as Viction Wallet cannot and does not guarantee its accuracy, applicability, reliability, integrity or appropriateness, nor shall Viction Wallet be liable for any loss or damage that may be caused directly or indirectly by your use of these contents; and&#x20;
6. Viction Wallet may, in its discretion, charge such fees at any time in the future. Any updated fees will apply to any transaction that occurs following the effective date of the updated fees.
7. Use of Staking Service

If you access or use the Staking Service, a third party may stake certain Digital Assets on your behalf (“Staked Digital Assets”), acting as a transaction validator on Viction or any other blockchain network supported by the App. If a block of transactions is successfully validated using such Staked Digital Assets, a reward is granted by that network (“Staking Reward”). You acknowledge and agree that Viction Wallet is not responsible for: (i) your use of the Staking Service and shall have no liability whatsoever in connection with your use of the Staking Service; (ii) ensuring Staking will occur continuously; and (iii) ensuring any particular Digital Asset will be staked or will continue to be staked.

5. Digital Asset Transactions

In order for all proposed Digital Asset transactions to be completed, they must be confirmed and recorded in Viction or Digital Asset’ associated public blockchain. Such networks are decentralized, peer-to-peer networks supported by independent third parties, which we do not own, control, or operate. We have no control over the blockchain networks and, therefore, cannot and do not ensure that any transaction details that you submit via our Services will be confirmed and processed. By using the App, you acknowledge and agree that: (i) we do not have the ability to cancel or otherwise modify your transaction; (ii) the transaction details you submit may not be completed, or may be substantially delayed, by the applicable blockchain networks; (iii) we do not store, send, or receive Digital Assets; and (iv) any transfer that occurs in relation to any Digital Asset occurs on the relevant blockchain network and not on a network owned by us and therefore we do not guarantee the transfer of title or right in any Digital Asset.

6. Accuracy of Information Provided by User

You represent and warrant that any information you provide via the Services is accurate and complete. You accept and acknowledge that we are not responsible for any errors or omissions that you make in connection with any Digital Asset transaction initiated via the Services. We strongly encourage you to review your transaction details carefully before attempting to transfer a Digital Asset.

5. You accept and acknowledge
6. The prices and liquidity of cryptocurrency assets are extremely volatile. Fluctuations in the price of other digital assets could materially and adversely affect the Digital Assets made available through the Services, which may also be subject to significant price volatility. We cannot guarantee that you will not lose money and have no responsibility to you for any such loss.
7. There are risks associated with using an internet-based currency, including but not limited to, the risk of hardware, software and Internet connections, the risk of malicious software introduction, and the risk that third parties may obtain unauthorized access to information stored within your Wallet. You accept and acknowledge that Viction Wallet will not be responsible for any communication failures, disruptions, errors, distortions or delays you may experience when using the Services for transactions, however caused.
8. The regulatory regime governing blockchain technologies, cryptocurrencies, and digital assets is uncertain, and new regulations or policies may materially adversely affect the development of the Services.
9. The Services may rely on third-party apps to perform transactions with respect to any digital assets. If we are unable to maintain a good relationship with such app providers; if the terms and conditions or pricing of such app providers change; if we violate or cannot comply with the terms and conditions of such apps; or if any of such apps loses market share or falls out of favor or is unavailable for a prolonged period of time, access to and use of the Services will suffer.
10. You further acknowledge and accept the risk that your Digital Assets, or any Digital Assets you acquire, including through a third-party exchange may lose some or all of their value and you may suffer loss due to the fluctuation of prices of Digital Assets and/or significant price slippage and cost. You understand that anyone can create a Digital Asset, including fake versions of existing Digital Assets and Digital Asset that falsely claim to represent projects, and acknowledge and accept the risk that you may mistakenly trade those or other Digital Asset. You further acknowledge that we are not responsible for any of these variables or risks and that we cannot be held liable for any resulting losses that you experience while accessing or using the Services.

If the Signatory asserts that there is a Principal but the individual or entity identified as the Principal (i) does not fully satisfy the Eligibility Conditions under Section 6(b) below or (ii) is for any reason not legally bound to these Terms, then the Signatory will be bound to these Terms in his or her personal capacity.

2. To be eligible to access and/or use the Services, you must satisfy each of the following conditions (the “Eligibility Conditions”):

If you are an individual:&#x20;

1. you must be at least 18 years old or above the minimum age in your jurisdiction to have the legal capacity to enter into contracts and to use the Services;
2. you are not a citizen or permanent resident of, you do not have a primary residence in, and you are not physically located in (i) North Korea, Iran, Syria, Cuba, People’s Republic of China, United States of America or its territories or possessions; or (ii) any country (A) where participation in the Services is prohibited, restricted or unauthorized in any form and/or manner whether in full or in part under the laws, regulatory requirements, or rules in such jurisdiction or (B) where it is likely that the Digital Asset transactions would be construed as the transactions of a security (howsoever named), financial services or investment products under the laws, regulatory requirements, or rules of such jurisdiction; and
3. You are not a Specially Designated National as identified by the Office of Foreign Assets Control of the U.S. Treasury Department; or on the Consolidated List of Targets maintained by the U.K. Office of Financial Sanctions Implementation of HM Treasury; or on the consolidated list of persons, groups, and entities subject to economic, financial sanctions, trade embargoes or export controls administered, enacted or enforced from time to time by the United States of America (“U.S.”), the United Nations Security Council, the European Union (“EU”), any EU member state, or the United Kingdom (regardless of its status vis-a-vis the EU), or any other jurisdiction.

If you are an entity:

1. you are duly organized and validly existing under the applicable laws of the jurisdiction of your organization;&#x20;
2. you have authorized your Signatory to accept these Terms on your behalf;
3. you are not a resident for tax purposes of, you do not have a domicile in, and you are not physically located in (i) North Korea, Iran, Syria, Cuba, People’s Republic of China, United States of America or its territories or possessions; or (ii) any country or jurisdiction (A) where participation in the Services is prohibited, restricted or unauthorized in any form and/or manner whether in full or in part under the Laws, regulatory requirements, or rules in such jurisdiction or (B) where it is likely that the Digital Asset transactions would be construed as the transactions of a security (howsoever named), financial services or investment products under the laws, regulatory requirements, or rules of such jurisdiction; and
4. You are not a Specially Designated National as identified by the Office of Foreign Assets Control of the U.S. Treasury Department; or on the Consolidated List of Targets maintained by the U.K. Office of Financial Sanctions Implementation of HM Treasury; or on the consolidated list of persons, groups, and entities subject to economic, financial sanctions, trade embargoes or export controls administered, enacted or enforced from time to time by the United States of America (“U.S.”), the United Nations Security Council, the European Union (“EU”), any EU member state, or the United Kingdom (regardless of its status vis-a-vis the EU), or any other jurisdiction.

You can only use our Services if permitted under the Laws of your jurisdiction. For the avoidance of doubt, you may not use our Services if you are located in, or a citizen or resident of any state, country, territory or other jurisdiction where your use of our Services would be illegal or otherwise violate any applicable laws. Please make sure that your accessing, using the Services are not prohibited, restricted, or regulated by any law or regulation applicable to you. You are solely responsible (i) to determine if there are any such laws or regulations (including foreign exchange restrictions) applicable to you and to comply with them and (ii) to determine if there are any governmental or other consents or approvals which you need to obtain, and to obtain and maintain them.

You are accessing and/or using the Services as principal and for your own account, and not as nominee or agent for, or for the account of, any other person.

3. If you do not fully satisfy each of the Eligibility Conditions at all times from the time that you accept these Terms, then you may not, and you agree not to, access to and/or use the Services. If you access to and/or use the Services notwithstanding that you do not meet each of the Eligibility Conditions, you acknowledge that (a) your access to and/or use the Services is a breach of these Terms, and (b) you access to and/or use the Services at your own risk. You acknowledge and agree that Viction Wallet will not be liable to you or any other party arising from or in connection with your access to and/or use the Services if you do not meet each of the Eligibility Conditions.
4. Viction Wallet may require you to provide certain information to confirm your satisfaction of the Eligibility Conditions and to complete the transactions related to the Services. If you do not provide the required information, then you may be unable to use the Services. Viction Wallet’s request for, and your provision of, any information from you, and any actions or decisions Viction Wallet may take based on that information, do not affect your obligations under this Section 6.
5. Intellectual Property

The Services, including its “look and feel” (e.g., text, graphics, images, logos, page headers, button icons, and scripts), proprietary content, information and other materials, and all content and other materials contained therein, including, without limitation, the Viction Wallet logo and all designs, layouts, displayed, technical information, text, graphics, pictures, data, software, sound files, other files, and the selection and arrangement thereof are the proprietary property of Viction Wallet or our affiliates, licensors, or users, as applicable, and you agree not to take any action(s) inconsistent with such ownership interests. We and our affiliates, licensors, and users, as applicable, reserve all rights in connection with the Services and its content, including, without limitation, the exclusive right to create derivative works.

“Viction Wallet” name, logo, trademarks, and any Viction Wallet product or Services names, designs, logos, and slogans are the intellectual property of Viction Wallet or our affiliates or licensors and may not be copied, imitated, or used, in whole or in part, without our prior written permission in each instance. You may not use any metatags or other “hidden text” utilizing “Viction Wallet” or any other name, trademark, or product or Services name of Viction Wallet or our affiliates or licensors without our prior written permission. In addition, the “look and feel” of the Services constitutes the Services mark, trademark, or trade dress of Viction Wallet and may not be copied, imitated, or used, in whole or in part, without our prior written permission.

All other third-party trademarks, registered trademarks, and product names mentioned on the Services or displayed on the Services are the property of their respective owners and may not be copied, imitated, or used, in whole or in part, without the permission of the applicable intellectual property rights holder. Reference to any products, services, processes or other information by name, trademark, manufacturer, supplier or otherwise does not constitute or imply endorsement, sponsorship, or recommendation by Viction Wallet.

2. License

As long as you agree to and comply with the present Terms, we grant you a non-exclusive, non-sublicensable and non-transferable license to use the App for your personal use or internal business use only. Except as otherwise expressly permitted in these Terms, you will not: (a) reproduce, modify, adapt or create derivative works of any part of the App; (b) rent, lease, distribute, sell, sublicense, transfer, or provide access to the App; (c) use the App for the benefit of any third party; (d) incorporate the App into a product or service you provide to a third party without our prior written consent; (d) circumvent mechanisms in the App intended to limit your use; (f) reverse engineer, disassemble, decompile, translate, or otherwise seek to obtain or derive the source code, including images and texts, underlying ideas, algorithms, file formats or non-public APIs to the App, except to the extent expressly permitted by applicable law (and then only upon advance notice to us); (g) remove or obscure any proprietary or other notices contained in the App (h) use the App for competitive analysis, as part of any other software or project of any kind or to build competitive products.

3. License to NFT Content

You may be able to store non-fungible tokens (“NFTs”) on your Wallet. You hereby represent and warrant that you own all legal right, title in and interest to, including all intellectual property rights to the content associated with the NFT (“NFT Content”), or you are legally authorized by the owner of the intellectual property in the NFT Content to store the NFTs on your Wallet. You retain all rights to the NFT Content except for rights expressly granted herein. By using the App, you grant us a license to access, use, host, cache, store, copy, reproduce, transmit, display, publish, distribute, adapt and modify (for technical purposes, e.g., making sure content is viewable on smartphones as well as computers and other devices) the NFT Content in any and all media or distribution methods (now know or later developed) solely as required to be able to operate and provide services of Viction Wallet. We do not monitor the NFTs and NFT Content stored on your Wallet for any infringement of a third party’s intellectual property rights. Accordingly, we assume no liability for any action regarding any content provided by you. You further acknowledge and agree it is your sole responsibility to carry out all necessary due diligence for all your activities relating to NFTs, and you represent and warrant that you have not and are not relying on, and shall have no remedies, in respect of any statement or representation made by us in relation to any transfer or interaction otherwise with any NFTs. If you have a dispute in relation to the NFTs and/or NFT Content, you release us from claims, demands, and damages of every kind and nature, known and unknown, arising out of or in any way connected with such disputes. In entering into this release, you expressly waive any protections (whether statutory or otherwise) that would otherwise limit the coverage of this release to include those claims which you may know or suspect to exist in your favor at the time of agreeing to this release.

8. Your responsibilities

You agree not to do any of the following:

1. Impersonate someone or use or attempt to use another user’s Wallet without authorization or use our Services in any manner that could interfere, disrupt, negatively affect, or inhibit other users from fully enjoying it;
2. Take any action that may impose an unreasonable or disproportionately large load on our or any of our third party providers’ infrastructure;
3. Access or use the Services to copy, modify, or create derivative works of the Services or any related software or code, or reverse engineer, disassemble, decompile, decode, adapt, or do anything that might discover source code or bypass or circumvent measures employed to prevent or limit access to the Services, or otherwise attempt to derive or gain access to any software component of the Services, including those of third parties.
4. Collect or store any personally identifiable information from the Services from other users of the Services without their express permission.
5. Impersonate or misrepresent your affiliation with any person or entity.
6. Engage or assist in any activity that violates any law, statute, ordinance, regulation, or sanctions program, or that involves proceeds of any criminal or fraudulent activity (including but not limited to money laundering, terrorist financing or deliberately engaging in activities designed to adversely affect the performance of the Services).
7. Use the Services in any manner that could interfere with, disrupt, negatively affect, or inhibit other users from fully enjoying the Services.
8. Violate, misappropriate or infringe the rights of Viction Wallet, our users, or others, including privacy, publicity, intellectual property, or other proprietary rights.&#x20;
9. Facilitate or assist another person to do any of the above acts.
10. Your representations, warranties and covenants

By using the Services, you further represent, warrant and covenant that:

1. Any Digital Assets you transfer via the Services have been legally obtained by, and belong to, you;
2. You will not provide any false, inaccurate or misleading information while using the Services, or engage in any activity that operates to defraud Viction Wallet, other users of the Services, or any other person or entity;
3. You will not use the Services to transmit or exchange Digital Assets that are the direct or indirect proceeds of any criminal or fraudulent activity, including, without limitation, terrorism or tax evasion;
4. Any Digital Assets you use in connection with the Services are either owned by you or you are validly authorized to carry out actions using such assets;
5. You will pay all fees necessary for interacting with Viction, or any other network with which the Services are compatible, including "gas" costs, as well as all fees charged by us for your use of the Services; and
6. You agree to comply with all applicable U.S. and non-U.S. export control and trade sanctions laws ("Export Laws"). Without limiting the foregoing, you may not download the App or use the Services if (i) you are in, under the control of, or a national or resident of Cuba, Iran, North Korea, Sudan, or Syria or any other country subject to United States embargo, UN Security Council Resolutions, HM Treasury's financial sanctions regime, or if you are on the U.S. Treasury Department's Specially Designated Nationals List or the U.S. Commerce Department's Denied Persons List, Unverified List, Entity List HM Treasury's financial sanctions regime; or (ii) you intend to supply any Services to Cuba, Iran, North Korea, Sudan or Syria or any other country subject to United States embargo or HM Treasury's financial sanctions regime (or a national or resident of one of these countries), or to a person on the Specially Designated Nationals List, Denied Persons List, Unverified List, Entity List, or HM Treasury's financial sanctions regime.
7. Indemnity

To the fullest extent permitted by applicable law, you will indemnify, defend and hold harmless Viction Wallet, and our affiliates, officers, directors, agents, partners and employees (individually and collectively, the “Viction Wallet Parties”) from and against all actual or alleged claims, damages, awards, judgments, losses, liabilities, obligations, taxes, penalties, interest, fees, expenses (including, without limitation, attorneys’ fees and expenses), and costs (including, without limitation, court costs, costs of settlement, and costs of pursuing indemnification and insurance), of every kind and nature whatsoever, whether known or unknown, foreseen or unforeseen, matured or unmatured, or suspected or unsuspected, in law or equity, whether in tort, contract, or otherwise (collectively, “Claims”) arising out of or related to (a) your use of misuse of the Services, (b) your violation, misappropriation or infringement of any rights of another (including intellectual property rights or privacy rights), (c) your violation or breach of any term of these Terms or applicable law, (d) your violation of the rights of or obligations to a third party, including another user or third-party, and (e) your negligence or willful misconduct. You agree to promptly notify Viction Wallet Parties of any third-party Claims, cooperate with Viction Wallet Parties in defending such Claims and pay all fees, costs and expenses associated with defending such Claims (including attorneys’ fees). You also agree that the Viction Wallet Parties will have control of the defense or settlement, at Viction Wallet’s sole option, of any third-party Claims. This indemnity is in addition to, and not in lieu of, any other indemnities set forth in a written agreement between you and Viction Wallet.&#x20;

If Viction Wallet is obligated to respond to a subpoena or other compulsory legal or court order or process relating to subject matter that is within the scope of your indemnity under this Section 10, you agree to reimburse Viction Wallet its legal fees, as well as its employees’ and contractors’ time and materials spent responding to the subpoena or other compulsory legal or court order or process at reasonable hourly rates.

11. Warranty Disclaimers

THE SERVICES LISTED THEREIN ARE PROVIDED “AS IS” AND “AS AVAILABLE”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. VICTION WALLET EXPRESSLY DISCLAIMS ALL WARRANTIES ARISING FROM COURSE OF DEALING, USAGE, OR TRADE PRACTICE. VICTION WALLET MAKES NO WARRANTY OF ANY KIND THAT THE SERVICES, OR ANY PRODUCTS OR RESULTS OF THE USE THEREOF, WILL MEET USERS’ OR ANY OTHER PERSON’S REQUIREMENTS, OPERATE WITHOUT INTERRUPTION, BE AVAILABLE AT ANY TIME OR IN ANY GEOGRAPHIC LOCATION, ACHIEVE ANY INTENDED RESULT, BE COMPATIBLE OR WORK WITH ANY SOFTWARE, SYSTEM, OR OTHER SERVICES, OR BE SECURE, ACCURATE, COMPLETE, FREE OF HARMFUL CODE, OR ERROR FREE. VICTION WALLET MAKES NO WARRANTY OR REPRESENTATION THAT THE SERVICES DO NOT INFRINGE UPON THE INTELLECTUAL PROPERTY RIGHTS OF OTHERS, THAT THE SERVICES WILL NOT INCIDENTALLY INFRINGE UPON THE INTELLECTUAL PROPERTY RIGHTS OF OTHERS BY NATURE OF ITS OPERATION. VICTION WALLET CANNOT GUARANTEE THE SECURITY OF ANY DATA THAT USERS DISCLOSE ONLINE. NO ADVICE OR INFORMATION, WHETHER ORAL OR OBTAINED FROM THE SERVICE, WILL CREATE ANY WARRANTY OR REPRESENTATION NOT EXPRESSLY MADE HEREIN. YOU ACCEPT THE INHERENT SECURITY RISKS OF PROVIDING INFORMATION AND DEALING ONLINE OVER THE INTERNET AND WILL NOT HOLD VICTION WALLET RESPONSIBLE FOR ANY BREACH OF SECURITY.&#x20;

VICTION WALLET MAKES NO REPRESENTATIONS OR WARRANTIES AS TO THE FUNCTIONALITY OF Viction, OR THAT Viction WILL OPERATE FREE FROM INTERRUPTIONS, DELAYS, DEFECTS AND/OR ERRORS THAT MAY DELAY, HINDER OR PREVENT THE TRANSMISSION OF TRANSACTIONS OR MESSAGES TO OR ON Viction, OR ANY OTHER NETWORK. THE DURATION OF ANY IMPLIED WARRANTY THAT IS NOT EFFECTIVELY DISCLAIMED WILL BE LIMITED TO THE LONGER OF (I) THIRTY (30) DAYS FROM THE DATE THAT YOU FIRST USE THE APPLICABLE SERVICE AND (II) THE SHORTEST PERIOD ALLOWED UNDER APPLICABLE LAW. SOME STATES/JURISDICTIONS DO NOT ALLOW LIMITATIONS ON HOW LONG AN IMPLIED WARRANTY LASTS, SO THE ABOVE LIMITATION MAY NOT APPLY TO YOU.

OUR SERVICES RELY ON EMERGING TECHNOLOGIES, SUCH AS Viction AND THIRD PARTY DECENTRALIZED EXCHANGES. SOME SERVICES ARE SUBJECT TO INCREASED RISK THROUGH YOUR POTENTIAL MISUSE OF THINGS SUCH AS PUBLIC/PRIVATE KEY CRYPTOGRAPHY. BY USING THE SERVICES YOU EXPLICITLY ACKNOWLEDGE AND ACCEPT THESE HEIGHTENED RISKS. VICTION WALLET SHALL NOT BE LIABLE FOR THE FAILURE OF ANY MESSAGE TO SEND TO OR BE RECEIVED BY THE INTENDED RECIPIENT IN THE INTENDED FORM, OR FOR DIMINUTION OF VALUE OF ANY DIGITAL TOKEN OR DIGITAL ASSET ON Viction OR ANY OTHER NETWORK, AND VICTION WALLET MAKES NO REPRESENTATIONS OR WARRANTIES WITH RESPECT TO THE SAME.

12. Acknowledgment of Certain Risks; Other Disclaimers; Release of Claims

YOU ACKNOWLEDGE AND AGREE THAT WE HAVE NO CONTROL OVER, AND NO DUTY TO TAKE ANY ACTION REGARDING: (I) FAILURES, DISRUPTIONS, ERRORS, OR DELAYS IN THE PROCESSING OF DIGITAL ASSETS THAT YOU MAY EXPERIENCE WHILE USING THE SERVICES; (II) THE RISK OF FAILURE OF HARDWARE, SOFTWARE, AND INTERNET CONNECTIONS; (III) THE RISK OF MALICIOUS SOFTWARE BEING INTRODUCED OR FOUND IN THE SOFTWARE UNDERLYING VICTION WALLET; (IV) THE RISK THAT THIRD PARTIES MAY OBTAIN UNAUTHORIZED ACCESS TO INFORMATION STORED WITHIN YOUR WALLET, INCLUDING, BUT NOT LIMITED TO YOUR WALLET ADDRESS, PRIVATE KEY, AND SECRET PHRASE; AND (V) THE RISK OF UNKNOWN VULNERABILITIES IN OR UNANTICIPATED CHANGES TO THE APPLICABLE BLOCKCHAIN NETWORKS.

YOU UNDERSTAND THAT Viction (AND ALL OTHER NETWORKS WITH WHICH THE SERVICES MAY BE COMPATIBLE) REMAINS UNDER DEVELOPMENT, WHICH CREATES TECHNOLOGICAL AND SECURITY RISKS WHEN USING THE SERVICES IN ADDITION TO UNCERTAINTY RELATING TO DIGITAL ASSETS AND TRANSACTIONS THEREIN. YOU ACKNOWLEDGE THAT THE COST OF TRANSACTING ON Viction IS VARIABLE AND MAY INCREASE AT ANY TIME, THEREBY IMPACTING ANY ACTIVITIES TAKING PLACE ON Viction, WHICH MAY RESULT IN PRICE FLUCTUATIONS OR INCREASED PRICES FOR USING THE SERVICES.

USE OF THE SERVICES, IN PARTICULAR FOR TRADING DIGITAL ASSETS, MAY CARRY FINANCIAL RISK. DIGITAL ASSETS ARE, BY THEIR NATURE, HIGHLY EXPERIMENTAL, RISKY, AND VOLATILE. TRANSACTIONS ENTERED INTO IN CONNECTION WITH THE SERVICES ARE IRREVERSIBLE, FINAL AND THERE ARE NO REFUNDS. YOU ACKNOWLEDGE AND AGREE THAT YOU WILL ACCESS AND USE THE SERVICES AT YOUR OWN RISK. THE RISK OF LOSS IN TRADING DIGITAL ASSETS CAN BE SUBSTANTIAL. YOU SHOULD, THEREFORE, CAREFULLY CONSIDER WHETHER SUCH TRADING IS SUITABLE FOR YOU IN LIGHT OF YOUR CIRCUMSTANCES AND FINANCIAL RESOURCES. BY USING THE SERVICES, YOU REPRESENT AND WARRANT THAT YOU HAVE BEEN, ARE, AND WILL BE SOLELY RESPONSIBLE FOR MAKING YOUR INDEPENDENT APPRAISAL AND INVESTIGATIONS INTO THE RISKS OF A GIVEN TRANSACTION AND THE UNDERLYING DIGITAL ASSETS. YOU REPRESENT THAT YOU HAVE SUFFICIENT KNOWLEDGE, MARKET SOPHISTICATION, PROFESSIONAL ADVICE, AND EXPERIENCE TO MAKE YOUR EVALUATION OF THE MERITS AND RISKS OF ANY TRANSACTION CONDUCTED IN CONNECTION WITH THE SERVICES OR ANY DIGITAL ASSET. YOU ACCEPT ALL CONSEQUENCES OF USING THE SERVICES, INCLUDING THE RISK THAT YOU MAY LOSE ACCESS TO YOUR DIGITAL ASSETS INDEFINITELY. ALL TRANSACTION DECISIONS ARE MADE SOLELY BY YOU. NOTWITHSTANDING ANYTHING IN THESE TERMS, WE ACCEPT NO RESPONSIBILITY WHATSOEVER FOR, AND WILL IN NO CIRCUMSTANCES BE LIABLE TO YOU IN CONNECTION WITH, YOUR USE OF THE SERVICES FOR PERFORMING DIGITAL ASSET TRANSACTIONS.

THE SERVICES MAY NOT BE AVAILABLE DUE TO ANY NUMBER OF FACTORS INCLUDING, BUT NOT LIMITED TO, PERIODIC SYSTEM MAINTENANCE, SCHEDULED OR UNSCHEDULED, ACTS OF GOD, UNAUTHORIZED ACCESS, VIRUSES, DENIAL OF SERVICES OR OTHER ATTACKS, TECHNICAL FAILURE OF THE SERVICES AND/OR TELECOMMUNICATIONS INFRASTRUCTURE OR DISRUPTION, AND THEREFORE WE EXPRESSLY DISCLAIM ANY EXPRESS OR IMPLIED WARRANTY REGARDING THE USE AND/OR AVAILABILITY, ACCESSIBILITY, SECURITY OR PERFORMANCE OF THE SERVICES CAUSED BY SUCH FACTORS. WE DO NOT MAKE ANY REPRESENTATIONS OR WARRANTIES AGAINST THE POSSIBILITY OF DELETION, MISDELIVERY OR FAILURE TO STORE COMMUNICATIONS, PERSONALIZED SETTINGS, OR OTHER DATA. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF CERTAIN WARRANTIES. ACCORDINGLY, SOME OF THE ABOVE DISCLAIMERS OF WARRANTIES MAY NOT APPLY TO YOU.

TO THE MAXIMUM EXTENT PERMITTED BY ALL APPLICABLE LAWS AND REGULATIONS, YOU, FOR AND ON BEHALF OF ALL NATURAL AND LEGAL PERSONS WHO MAY CLAIM THROUGH OR UNDER YOU, ON YOUR BEHALF, OR OTHERWISE IN RESPECT OF YOU, RELEASE AND FOREVER DISCHARGE VICTION WALLET AND ITS AFFILIATES, AND ITS AND THEIR RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AGENTS, REPRESENTATIVES, SUPPLIERS, ATTORNEYS, AND ADVISERS, AND ALL OF ITS AND THEIR RESPECTIVE PREDECESSORS, SUCCESSORS, AND ASSIGNS, FROM ALL CLAIMS AND CAUSES OF ACTION OF ANY KIND WHATSOEVER, WHETHER UNDER COMMON LAW, STATUTORY, CONTRACTUAL, TORTIOUS, EQUITABLE, OR OTHERWISE, AND ALL LOSSES, DAMAGES, TAXES, LIABILITIES, COSTS, AND EXPENSES, WHICH YOU HAVE, EVER HAD, MAY HAVE, OR HEREAFTER MIGHT HAVE, WHETHER KNOWN OR UNKNOWN, NOW EXISTING OR WHICH MIGHT ARISE OR ACCRUE HEREAFTER, RELATING TO OR ARISING FROM THE MATTERS LISTED IN THIS SECTION.

13. Limitation of liability

IN NO EVENT SHALL VICTION WALLET BE LIABLE FOR ANY LOSSES REALIZED OR DEMANDED OF USERS RELATED TO USERS’ ACCESS TO OR USE OF THE SERVICES, INCLUDING ANY LOSSES FOR INTELLECTUAL PROPERTY INFRINGEMENT. NOTWITHSTANDING THE FOREGOING, IN NO EVENT SHALL THE MAXIMUM AGGREGATE LIABILITY OF VICTION WALLET FOR DAMAGES EXCEED THE AMOUNTS YOU HAVE PAID OR ARE PAYABLE BY YOU TO VICTION WALLET FOR USE OF THE SERVICES OR ONE HUNDRED U.S. DOLLARS ($100), IF YOU HAVE NOT HAD ANY PAYMENT OBLIGATIONS TO VICTION WALLET, AS APPLICABLE.

IN NO EVENT SHALL VICTION WALLET NOR ITS DIRECTORS, EMPLOYEES, PARTNERS, AGENTS, SUPPLIERS, OR AFFILIATES, BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES, INCLUDING WITHOUT LIMITATION, LOSS OF PROFITS, DATA, USE, GOODWILL, OR OTHER INTANGIBLE LOSSES, RESULTING FROM: (I) YOUR ACCESS TO OR USE OF OR INABILITY TO ACCESS OR USE THE SERVICES, INCLUDING, BUT NOT LIMITED TO: ANY UNAUTHORIZED USE OF YOUR WALLET ADDRESS AND/OR PRIVATE KEY DUE TO YOUR FAILURE TO MAINTAIN THE CONFIDENTIALITY OF YOUR WALLET, ANY INTERRUPTION OR CESSATION OF TRANSMISSION TO OR FROM THE SERVICES OR ANY BUGS, VIRUSES, TROJAN HORSES, OR THE LIKE THAT ARE FOUND IN VICTION WALLET SOFTWARE OR THAT MAY BE TRANSMITTED TO OR THROUGH OUR SERVICES BY ANY THIRD PARTY (REGARDLESS OF THE SOURCE OF ORIGINATION); (II) ANY CONDUCT OR CONTENT OF ANY THIRD PARTY; AND (III) UNAUTHORIZED ACCESS, USE, OR ALTERATION OF YOUR TRANSMISSIONS OR CONTENT, WHETHER BASED ON WARRANTY, CONTRACT, TORT (INCLUDING NEGLIGENCE), OR ANY OTHER LEGAL THEORY, WHETHER OR NOT WE HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGE, AND EVEN IF A REMEDY SET FORTH HEREIN IS FOUND TO HAVE FAILED OF ITS ESSENTIAL PURPOSE.

THE LIMITATIONS OF LIABILITY IN THIS SECTION PROTECT VICTION WALLET’S AFFILIATES, AND THE DIRECTORS, OFFICERS, EMPLOYEES, AGENTS, ADVISERS, AND REPRESENTATIVES OF VICTION WALLET AND ITS AFFILIATES, AND ALL OF THEIR RESPECTIVE PREDECESSORS, SUCCESSORS, AND ASSIGNS, TO THE SAME EXTENT THAT VICTION WALLET IS PROTECTED.

SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF CERTAIN WARRANTIES OR THE LIMITATION OF LIABILITY FOR SOME TYPES OF DAMAGES. TO THAT END, THE EXCLUSIONS OF WARRANTIES AND THE LIMITATIONS OF LIABILITY ARE TO THE FULLEST EXTENT PERMITTED BY LAW.

YOU AGREE TO WAIVE ALL RIGHTS TO ASSERT ANY CLAIMS UNDER APPLICABLE LAWS AND REGULATIONS AND YOU AGREE THAT YOU MAY MAKE CLAIMS BASED ONLY ON THESE TERMS.

YOU ACKNOWLEDGE THAT VICTION WALLET HAS ENTERED INTO THESE TERMS IN RELIANCE UPON THE DISCLAIMERS AND LIMITATIONS OF LIABILITY IN THESE TERMS, AND THAT THE SAME FORM AN ESSENTIAL BASIS OF THE BARGAIN BETWEEN YOU AND VICTION WALLET.

14. Privacy Policy

Please refer to our [Privacy Policy ](https://docs.viction.xyz/general/how-to-connect-to-viction-network/viction-wallet/privacy-policy)for information about how we collect, use, and disclose information from our App users. By submitting personal data through our Services, you agree to the terms of our [Privacy Policy](https://docs.viction.xyz/general/how-to-connect-to-viction-network/viction-wallet/privacy-policy) and you expressly consent to the collection, use, and disclosure of your personal data in accordance with the [Privacy Policy](https://docs.viction.xyz/general/how-to-connect-to-viction-network/viction-wallet/privacy-policy).

15. Future changes to the App

We are always working to improve the App, so our products and Services may change over time. We may suspend or discontinue any part of Viction Wallet, or we may introduce new features or impose limitations on certain features or restrict access to part or all the App.

16. Resolving Disputes; Binding Arbitration

We want to address your concerns without needing a formal legal case. Before filing a claim against Viction Wallet, you agree to contact us and attempt to resolve the claim informally by sending a written notice of your claim by email at <<support@viction.xyz>>. The notice must (a) include your name, residence address, email address, and telephone number; (b) describe the nature and basis of the claim; and (c) set forth the specific relief sought. Our notice to you will be sent to the email address associated with your online account and will contain the information described above. If we can’t resolve matters within thirty (30) days after any notice is sent, either party may initiate a formal proceeding.

Please read the following section carefully because it requires you to arbitrate certain disputes and claims with Viction Wallet and limits the manner in which you can seek relief from us, unless you opt out of arbitration by following the instructions set forth below. No class or representative actions or arbitrations are allowed under this arbitration provision. In addition, arbitration precludes you from suing in court or having a jury trial.

1. No Representative Actions. You and Viction Wallet agree that any dispute arising out of or related to these Terms, or our Services is personal to you and Viction Wallet and that any dispute will be resolved solely through individual action, and will not be brought as a class arbitration, class action or any other type of representative proceeding.
2. Arbitration of Disputes. Except for claims disputes in which you or Viction Wallet seeks injunctive or other equitable relief for the alleged infringement or misappropriation of intellectual property, you and Viction Wallet waive your rights to a jury trial and to have any other dispute arising out of or related to these Terms or our Services, including claims related to privacy and data security, (collectively, “Disputes”) resolved in court. All Disputes shall be submitted to the Singapore International Arbitration Centre (“SIAC”) to be resolved through confidential, binding arbitration before one arbitrator. Arbitration proceedings shall be conducted virtually. You and Viction Wallet agree that Disputes will be held in accordance with the SIAC Arbitration Rules and Procedures (“SIAC Rules”). The most recent version of the SIAC Rules is incorporated into these Terms by reference. You either acknowledge and agree that you have read and understand the SIAC Rules or waive your opportunity to read the SIAC Rules and waive any claim that the SIAC Rules are unfair or should not apply for any reason.
3. The arbitration will allow for the discovery or exchange of non-privileged information relevant to the Dispute. The arbitrator, Viction Wallet, and you will maintain the confidentiality of any arbitration proceedings, judgments, and awards, including information gathered, prepared and presented for purposes of the arbitration or related to the Dispute(s) therein. The arbitrator will have the authority to make appropriate rulings to safeguard confidentiality unless the law provides to the contrary. The duty of confidentiality doesn’t apply to the extent that disclosure is necessary to prepare for or conduct the arbitration hearing on the merits, in connection with a court application for a preliminary remedy, or in connection with a judicial challenge to an arbitration award or its enforcement, or to the extent that disclosure is otherwise required by law or judicial decision.
4. Any Dispute must be filed within one year after the relevant claim arose; otherwise, the Dispute is permanently barred, which means that you and Viction Wallet will not have the right to assert the claim.
5. If any portion of this section is found to be unenforceable or unlawful for any reason, (1) the unenforceable or unlawful provision shall be severed from these Terms; (2) severance of the unenforceable or unlawful provision shall have no impact whatsoever on the remainder of this section or the parties’ ability to compel arbitration of any remaining claims on an individual basis pursuant to this section; and (3) to the extent that any claims must therefore proceed on a class, collective, consolidated, or representative basis, such claims must be litigated in a civil court of competent jurisdiction and not in arbitration, and the parties agree that litigation of those claims shall stay pending the outcome of any individual claims in arbitration. Further, if any part of this section is found to prohibit an individual claim seeking public injunctive relief, that provision will have no effect to the extent such relief is allowed to be sought out of arbitration, and the remainder of this section will be enforceable.
6. Governing Law

These Terms and your access to and use of the Services shall be governed by and construed and enforced in accordance with the laws of Saint Vincent and the Grenadines without [giving](https://www.lawinsider.com/clause/giving) [effect](https://www.lawinsider.com/clause/effect) to the [conflict of laws](https://www.lawinsider.com/clause/conflict-of-laws) [principles](https://www.lawinsider.com/clause/principles) thereof.

18. Termination

Notwithstanding the foregoing, we may suspend or terminate your access to the Services at any time in connection with any transaction as required by applicable law, any governmental authority, or if we in our sole and reasonable discretion determine you are violating these Terms or the terms of any third-party Services provider at our sole discretion, at any time and without notice to you. Such suspension or termination shall not constitute a breach of these Terms by Viction Wallet. In accordance with its anti-money laundering, anti-terrorism, anti-fraud, and other compliance policies and practices, we may impose reasonable limitations and controls on the ability of you or any beneficiary to utilize the Services. Such limitations may include where good cause exists, rejecting transaction requests, freezing funds, or otherwise restricting you from using the Services.

You may disconnect your Wallet at any time. You acknowledge and agree that we shall have no liability or obligation to you in such an event and that you will not be entitled to a refund of any amounts that you have already paid to us or any third party, to the fullest extent permitted by applicable law. Upon any termination, discontinuation, or cancellation of the Services, the following Sections will survive: 1, 5, 6, 7, 8, 9, 10, 11, 13, 14, 16, 17, 18, 19, 20, and 21.&#x20;

19. Severability

If any term, clause, or provision of these Terms is held invalid or unenforceable, then that term, clause, or provision will be severable from these Terms and will not affect the validity or enforceability of any remaining part of that term, clause, or provision, or any other term, clause, or provision of these Terms.

20. Injunctive Relief

You agree that a breach of these Terms will cause irreparable injury to Viction Wallet for which monetary damages would not be an adequate remedy and Viction Wallet shall be entitled to equitable relief in addition to any remedies it may have hereunder or at law without a bond, other security, or proof of damages.

21. Miscellaneous

These Terms constitute the entire agreement between you and Viction Wallet relating to your access to and use of the Service. These Terms, and any rights and licenses granted hereunder, may not be transferred or assigned by you without the prior written consent of Viction Wallet, and Viction Wallet’s failure to assert any right or provision under these Terms shall not constitute a waiver of such right or provision. No waiver by either party of any breach or default hereunder shall be deemed to be a waiver of any preceding or subsequent breach or default. The section headings used herein are for reference only and shall not be read to have any legal effect.

Except as otherwise provided herein, these Terms are intended solely for the benefit of the parties and are not intended to confer third-party beneficiary rights upon any other person or entity.

<br>

&#x20;

<br>


# Viction Bridge

Users can bridge token from different blockchains to Viction to explore and enjoy different utilities on Viction network. Supported tokens are VIC, ETH, C98, USDT, USDC,... just to name a few.

We're constantly expanding the bridge options, stay tuned for more.


# Spacegate

SpaceGate supports users in converting token assets across blockchains. Especially from **TOMOE (Ethereum) -> VIC (Viction)**. You can read about TOMOE in the section below.

Besides TOMOE, other tokens that are also supported on Spacegate are C98 (Coin98), and SAROS (Saros), offering the following routes:

* TOMOE (Ethereum) -> VIC(Viction)
* C98 (BEP20) <> C98 (VRC25) <> C98 (ERC20)
* SAROS (VRC25) <> SAROS (SPL)

## **How to convert tokens on SpaceGate?** <a href="#f27w4dkreqca" id="f27w4dkreqca"></a>

{% hint style="info" %}

* To use the cross-chain bridges, you need to pay several types of fees as follows: protocol fees, bridging fees (withdraw fee), and network fees (which are charged in the father token of each blockchain such as BNB for converting C98 Bep20 to others, ETH for C98 ERC20, SOL for C98 SPL, and MATIC for C98 PRC20). Please check further details on the fees [here](https://docs.coin98.com/products/coin98-super-wallet/mobile/spacegate/faqs).
* Each asset will have a limit on the number of tokens in a single conversion transaction\
  \- For C98, you can convert a minimum of **10 C98** and a maximum of **50,000 C98** per transaction\
  \- For VIC, you can convert a minimum of **10 VIC** and a maximum of **5,000** per transaction
  {% endhint %}

Kindly refer to the detailed guide on how to swap on Spacegate below:

{% embed url="<https://docs.coin98.com/products/spacegate/convert-tokens>" %}

## What is TOMOE?

VIC-wrapped ETH, called TOMOE, is an ERC20 token hosted on the Ethereum blockchain and backed by an equal amount of native VIC (on the Viction blockchain). One TOMOE is worth the same as one native VIC at any given moment.

{% hint style="info" %}
TOMOE Contract Address

[0x05d3606d5c81eb9b7b18530995ec9b29da05faba](https://etherscan.io/address/0x05d3606d5c81eb9b7b18530995ec9b29da05faba)
{% endhint %}

**What’s the difference between TOMOE & VIC?**

* VIC is the native token used on the Viction network.
* TOMOE is an ERC20 token hosted on the Ethereum network. TOMOE represents a 1:1 value with VIC.
* To have a well-rounded DeFi experience on Viction, you are highly recommended to convert TOMOE > VIC.


# Hyperlane

## **How to Bridge your Assets to Viction using Hyperlane NEXUS**

{% hint style="info" %}
**Prerequisites:**

\- **A crypto wallet** compatible with Ethereum and Viction networks (e.g., MetaMask, WalletConnect).

\- **Tokens in your Ethereum wallet** to cover bridging fees and transaction costs on Viction.
{% endhint %}

**Step 1:** Access [Hyperlane Nexus](https://www.usenexus.org/)

<figure><img src="/files/VlLefRx9BzSpBU0OHlke" alt="Hyperlane main page"><figcaption></figcaption></figure>

**Step 2:** Connect Your Wallet

Click on the **Connect Wallet** button and choose your preferred wallet provider from the available options. Follow the on-screen instructions to complete the connection.

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

**Step 3:** Select Transfer Options

* **Source Chain**: This should be pre-filled as **Ethereum** since you're bridging from the Ethereum mainnet.
* **Destination Chain**: Select **Viction** from the dropdown menu.

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

**Step 4:** Choose Your Token

In the **Token** section, choose the specific token you want to bridge to Viction (e.g., ETH, USDC, USDT).

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

**Step 5:** Enter Transfer Amount Enter the amount of the chosen token you want to transfer to Viction.

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

**Step 6:** Initiate the Bridge Transaction

* Review the transaction details carefully, including the bridging fees and estimated transfer time.
* Once confirmed, click on the **Bridge** button to initiate the transfer.

**Step 7:** Approve the Transaction in Your Wallet

* A pop-up window will appear in your connected wallet, requesting your approval for the transaction.
* Review the details again, including gas fees on the Ethereum network, and confirm the transaction.

**Step 8:** Monitor the Transfer Process

You can monitor the progress of your bridge transaction on the Hyperlane Nexus interface or through your wallet provider's transaction history.

**Step 9:** Access Your Bridged Tokens on Viction

Once the transaction is complete, your chosen token will be available in your Viction wallet address. You might need to add the token address to your wallet manually if it's not automatically displayed.

{% hint style="info" %}
**Important Considerations:**

* **Network Fees:** You'll incur gas fees on the Ethereum network for initiating the bridge transaction. Additionally, there might be minimal fees on the Viction network upon receiving the tokens.
* **Bridge Fees:** Although the gas fee of Viction is relatively small, the bridge fee (charged by Hyperlane) could be significant.
* **Supported Tokens:** Currently, Hyperlane Nexus on Viction supports ETH, USDC, and USDT. Double-check if the token you desire is included before proceeding.
* **Transaction Approval:** Always review the transaction details thoroughly before approving it in your wallet.
* **Token Utilities:** The utility of bridged tokens (ETH, USDT, USDC,...) are still under development, ensure you have researched and a clear usage purpose of the bridged tokens in mind before doing bridge.
  {% endhint %}

By following these steps, you can leverage Hyperlane Nexus to seamlessly bridge your assets from Ethereum to the Viction blockchain and explore the exciting opportunities it offers.


# Viction Data Availability

Viction's Data Availability (DA) represents a groundbreaking initiative to enhance this aspect of blockchain technology.

## Introduction

Every monolithic blockchain, which is a blockchain where all functions—such as consensus, data availability, and transaction execution—are integrated within a single protocol, includes a data availability layer. This layer ensures that all the necessary data for validating and verifying transactions is accessible to all network participants.

Viction's Data Availability (DA) represents a groundbreaking initiative to enhance this aspect of blockchain technology. By modularizing the data availability layer, Viction decouples it from the core Viction blockchain. This means that instead of being an inseparable part of the Viction blockchain, the DA layer is designed as a separate, standalone module.

This modular DA layer can be utilized as a roll-up solution by developers building on other blockchain networks. Roll-ups are a scalability technique that processes transactions off the main blockchain (off-chain) and then posts the transaction data back to the main blockchain. This reduces the computational load on the main blockchain while still benefiting from its security features.

By offering its DA layer as a modular component, Viction provides an efficient, scalable, and secure way for other blockchains to manage their data availability needs. This pioneering approach not only enhances the scalability of individual blockchains but also promotes interoperability and flexibility across the broader blockchain ecosystem.

## Viction DA Infrastructure diagram

<figure><img src="/files/uGeE8vNWeu5w9vf4TaMx" alt=""><figcaption><p>Viction DA infrastructure diagram</p></figcaption></figure>

**Viction DA** takes advantage of AWS CloudFormation, a powerful service specifically designed to manage and provision AWS infrastructure using code. This approach allows us to define their cloud resources in simple text files, which can then be used to automatically and consistently create and manage those resources.&#x20;

By utilizing AWS CloudFormation, **Viction DA** ensures a deployment model that is highly scalable, meaning it can handle increased load without performance issues. It is also highly reliable, providing a stable and consistent environment, and automated, reducing the need for manual intervention and minimizing the risk of human error. This results in an efficient and effective way to manage cloud resources, ensuring that the infrastructure can grow and adapt as needed.

## System components context diagram

<figure><img src="/files/ODYwQwlRwmipMyopGbBf" alt=""><figcaption><p>Viction DA - System component context diagram</p></figcaption></figure>

This describes the system components that we develop and how it connects to external components.

1. Users initiate transactions on the Layer 2 (L2) blockchain.
2. The L2 blockchain/ DA client submits the block data to the Viction DA service.
3. Viction DA compresses the data, generates unique commitments and IDs, and returns these IDs. These IDs are used to retrieve the original data and associated proofs.
4. The L2 blockchain sends the IDs back to Viction (Rollup Tx).
5. Light nodes/ users can use these IDs to fetch the corresponding commitments and proofs from Viction DA.
6. Light nodes/ users utilize the commitments and proofs to validate the data.


# Viction DA RPC API

Viction DA, the interconnecting data layer for Web3, breaking down communication barriers between blockchain platforms.

You can make JSON RPC calls to Viction via those following URLs:

**DA-Testnet:** <https://da-testnet.viction.xyz>

**DA-Mainnet:** <https://da.viction.xyz>

## Postman collection

{% file src="/files/a5C8S1Hgekw2mNcgkHLD" %}

## Commit data

<mark style="color:yellow;">`POST`</mark> `/commit`

Commit data to the DA Layer & returns Commitment for each given Blob

**RequestBody:** The argument is byte array

{% tabs %}
{% tab title="Body" %}

```json
{
    "jsonrpc": "2.0",
    "id": 128,
    "method": "commit",
    "params": [
        [
            [
                104,
                101,
                108,
                108,
                111
            ]
        ],
        "namespace"
    ]
}
```

{% endtab %}
{% endtabs %}

**Response**

Success response should return an array of commitments of the byte array

{% tabs %}
{% tab title="200" %}

```json
{
    "jsonrpc": "2.0",
    "result": [
        [
            179,
            75,
            83,
            34,
            165,
            175,
            249,
            223,
            47,
            197,
            64,
            246,
            39,
            144,
            246,
            178,
            41,
            129,
            180,
            213,
            74,
            140,
            54,
            81,
            194,
            150,
            87,
            48,
            172,
            66,
            114,
            200,
            132,
            185,
            173,
            238,
            171,
            189,
            233,
            151,
            60,
            138,
            111,
            177,
            2,
            96,
            22,
            134
        ]
    ],
    "id": 128
}
```

{% endtab %}

{% tab title="400" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

## Get Blob

<mark style="color:green;">`GET`</mark> `/get`

Return Blob for each given ID

**RequestBody**

{% tabs %}
{% tab title="Body" %}

```json
{
    "jsonrpc":"2.0",
    "id": 128,
        "method": "get",
    "params": [
        [
            [1,97,54,102,57,50,55,97,102,51,53,100,98,50,50,100,49,55,98,53,51,100,55,102,54,51,97,52,98,52,97,102,102,99,55,48,49,48,55,100,54,56,49,97,98,101,98,48,102,97,53,50,53,57,57,101,56,57,50,57,49,54,99,97]
        ],
        "namespace"
    ]
}
```

{% endtab %}
{% endtabs %}

**Response**

{% tabs %}
{% tab title="200" %}

```json
{
    "jsonrpc": "2.0",
    "result": [
        [
            104,
            101,
            108,
            108,
            111
        ]
    ],
    "id": 128
}
```

{% endtab %}

{% tab title="400" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

!!! In case there is no data in storage(means nothing was submitted before) it returns `empty bytes array`

## Get Proof

<mark style="color:green;">`GET`</mark> `/get_proofs`

Return Proofs for each given ID

**RequestBody**

{% tabs %}
{% tab title="Body" %}

```json
{
    "jsonrpc":"2.0",
    "id": 128,
    "method": "get_proofs",
    "params": [
        [
            [1,97,54,102,57,50,55,97,102,51,53,100,98,50,50,100,49,55,98,53,51,100,55,102,54,51,97,52,98,52,97,102,102,99,55,48,49,48,55,100,54,56,49,97,98,101,98,48,102,97,53,50,53,57,57,101,56,57,50,57,49,54,99,97]
        ],
        "namespace"
    ]
}
```

{% endtab %}
{% endtabs %}

**Response**

{% tabs %}
{% tab title="200" %}

```json
{
    "jsonrpc": "2.0",
    "result": [
        [
            166,
            226,
            152,
            3,
            148,
            197,
            142,
            68,
            37,
            3,
            30,
            235,
            83,
            168,
            156,
            244,
            25,
            94,
            85,
            95,
            38,
            18,
            205,
            209,
            242,
            109,
            0,
            45,
            121,
            48,
            13,
            160,
            133,
            205,
            96,
            223,
            139,
            179,
            76,
            141,
            151,
            183,
            74,
            156,
            153,
            101,
            48,
            136
        ]
    ],
    "id": 128
}
```

{% endtab %}

{% tab title="400" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

## Submit

<mark style="color:yellow;">`POST`</mark> `/submit`

Submit data to Data layer & returns tuple of ID and Commitment for each given Blob

**RequestBody**

{% tabs %}
{% tab title="Body" %}

```json
{
    "jsonrpc":"2.0",
    "id": 128,
    "method": "submit",
    "params": [
        [[104,101,108,108,111]],
        "namespace"
    ]
}
```

{% endtab %}
{% endtabs %}

**Response**

{% tabs %}
{% tab title="200" %}

```json
{
    "jsonrpc":"2.0",
    "result":[
        [
            [50,99,102,50,52,100,98,97,53,102,98,48,97,51,48,101,50,54,101,56,51,98,50,97,99,53,98,57,101,50,57,101,49,98,49,54,49,101,53,99,49,102,97,55,52,50,53,101,55,51,48,52,51,51,54,50,57,51,56,98,57,56,50,52],
            [166,54,159,144,72,207,81,43,3,233,138,181,14,56,147,45,171,85,142,173,92,28,238,112,164,213,203,130,110,6,33,97,93,73,204,147,28,226,140,248,191,103,232,253,200,84,209,89]
        ]
    ],
    "id":128
}
```

{% endtab %}

{% tab title="400" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

## Validate

<mark style="color:yellow;">`POST`</mark> `/validate`

Request body 1st params argument is a "hello" string Id and Commitmen&#x74;**("${Id}-{Commitment}")**

Kindly view `Submit` example 2nd onw is a data with corrupted proof byte array

**RequestBody**

`ERROR RESPONSE` In case the request has invalid params

{% tabs %}
{% tab title="Body" %}

```json
   {
    "jsonrpc":"2.0",
    "id": 128,
    "method": "validate",
    "params": [
        [
            [1,97,54,102,57,50,55,97,102,51,53,100,98,50,50,100,49,55,98,53,51,100,55,102,54,51,97,52,98,52,97,102,102,99,55,48,49,48,55,100,54,56,49,97,98,101,98,48,102,97,53,50,53,57,57,101,56,57,50,57,49,54,99,97]
        ],
        [
            [179,75,83,34,165,175,249,223,47,197,64,246,39,144,246,178,41,129,180,213,74,140,54,81,194,150,87,48,172,66,114,200,132,185,173,238,171,189,233,151,60,138,111,177,2,96,22,134]
        ],
        [
            [166,226,152,3,148,197,142,68,37,3,30,235,83,168,156,244,25,94,85,95,38,18,205,209,242,109,0,45,121,48,13,160,133,205,96,223,139,179,76,141,151,183,74,156,153,101,48,136]
        ],
        "namespace"
    ]
}
```

{% endtab %}

{% tab title="Invalid Body" %}

```json
{
    "jsonrpc":"2.0",
    "id": 128,
    "method": "submit",
    "params": [22]
}
```

{% endtab %}
{% endtabs %}

**Response**

Success response should return **true** and **false**

{% tabs %}
{% tab title="200" %}

```json
{
    "jsonrpc": "2.0",
    "result": [
        true
    ],
    "id": 128
}
```

{% endtab %}

{% tab title="200 with Error response" %}

```json
{
    "jsonrpc": "2.0",
    "error": {
        "code": -32602,
        "message": "Invalid params",
        "data": "invalid type: integer `22`, expected byte array at line 1 column 3"
    },
    "id": 128
}
```

{% endtab %}

{% tab title="400" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

!!! In case there is no data in storage(means nothing was submitted before) it returns `false` validation result


# DA Integration Use cases

This section provides an overview of how the Viction Data Availability (DA) Layer integrates with Layer 2 (L2) rollups. The integration involves implementing a Light Client as an intermediary component. This Light Client encapsulates the necessary logic to enable rollups to maintain IDs (commitments to the transaction blob data) on the Viction network while storing the full transaction data on the DA Layer. The diagram below outlines each step of this workflow, offering a high-level understanding of the integration process.

The Light Client plays a crucial role in this architecture by ensuring the integrity and availability of transaction data. It achieves this by:

* **Storing IDs on Viction(L1)**: Preserving the cryptographic commitment to the transaction data, which allows for verification and auditing on the Viction network.
* **Managing Data Storage on the DA Layer**: Offloading the actual transaction data to the Viction DA Layer, thereby optimizing storage efficiency and scalability.

By providing this intermediary layer, the integration facilitates a seamless connection between L2 rollups and the Viction DA Layer, enhancing scalability without compromising data integrity or availability.

<figure><img src="/files/bzrpBOQCMI4k61H91WZk" alt=""><figcaption><p>Viction - Data Availability (DA) Layer Architecture</p></figcaption></figure>

**Note**: The current version of the Light Client is undergoing active testing and will be updated soon with new improvements.

<br>


# Simple Guide for Integrating OP Stack Rollup with Viction DA Layer

This guide explains how to connect OP Stack rollups with the Viction Data Availability (DA) Layer using the testnet on Viction as settlement.

## Prerequisites and Initial Configuration

To initiate an OP Stack rollup, follow the steps provided in the [official documentation](https://docs.optimism.io/builders/chain-operators/tutorials/create-l2-rollup). OP Stack documentation covers all procedures necessary for deploying the rollup, however, please note that the following adjustments are necessary for switching the network to Viction testnet:

* **Change the Network Chain ID**: Modify the chain ID from Viction testnet
* Modify the Batcher’s Destination Viction Address: Update the batcher’s destination Viction address to separate transactions from the default destination address on the Viction network.

The above two updates can be made after creating the `getting-started.json` file.

## Service Configuration for DA Layer Integration <a href="#service-configuration-for-da-layer-integration" id="service-configuration-for-da-layer-integration"></a>

Once all OP services are started, proceed with the following steps:

**1. Start the Light Client:** Initialize the light client service, which will handle storing L2 transaction batch data to the DA Layer.

**2. Stop the Batcher Service:** Temporarily halt the batcher service to apply the necessary configuration changes.

**3. Update the Batcher Configuration:** Modify the `--l1-eth-rpc` parameter in the batcher’s configuration to point to the light client’s RPC URL.

**4. Resume the Batcher Service:** Resume the batcher service to continue processing transactions.

[As illustrated in the Light Client diagram](https://docs.viction.xyz/viction-data-availability/da-integration-use-cases), the light client performs the following functions:

* Stores L2 transaction batch data to the DA Layer.
* Saves versioned hashes on Viction.
* Returns the versioned hashes to the batcher.

## Testing the Integration <a href="#testing-the-integration" id="testing-the-integration"></a>

A test OP Stack L2 network is available for experimentation:

* **Chain ID:** 42444
* **L2 RPC Node:** <http://geth-l2-op-stack-rollup-dev-1161098553.eu-central-1.elb.amazonaws.com:8545/>
* **Batcher transactions on the Viction network can be found at the following link:**

By comparing the initial transactions with subsequent ones, particularly focusing on the input size, it becomes evident that the input size is significantly smaller in later transactions. This reduction occurs because the transactions contain only the versioned hashes of the data stored on the DA layer.

By adhering to these steps and configurations, the integration of the DA Layer solution with an OP Stack rollup can be successfully accomplished. For any questions or issues, please consult the documentation or contact our team.


# How to


# How to Connect to Viction Blockchain

This guide will show you how to connect to the Viction Mainnet to check your balance, move tokens, and start staking via MEW, Ledger Nano S, Metamask, and Viction Wallet.


# Coin98 Super Wallet

Coin98 is the #1 crypto super app designed to seamlessly connect a billion users to the crypto world safely and securely.This guide shows detailed steps on how to use and connect Coin98 Super Wallet t

## I. How to install Coin98 Super Wallet

Coin98 Super Wallet is available for download at:

* iOS: [ios.coin98.com](https://ios.coin98.com/)
* Android: [android.coin98.com](https://android.coin98.com/)

## II. How to create and restore a wallet on the Coin98 Super Wallet

### Create a wallet for Viction on the Coin98 Super Wallet

**Step 1**: At the top right corner of the home page, choose **Add Wallet** icon

**Step 2:** Click **Create a New Wallet**, then select your desired wallet type

If you're unclear about these wallet types, you can refer to a wallet comparison by clicking the icon in the top right corner.

<figure><img src="https://docs.coin98.com/~gitbook/image?url=https%3A%2F%2F2549780185-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FirKWZRA5WMZ5uBeDGB96%252Fuploads%252FNq0HqjYmXwp99uiIXrAQ%252FScreenshot%25202025-06-09%2520at%25204.13.20%25E2%2580%25AFPM.png%3Falt%3Dmedia%26token%3Da8f0b104-f552-4aec-9ed6-c7c682d62053&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=fe6a33c0&#x26;sv=2" alt=""><figcaption></figcaption></figure>

**Step 3**: Select the blockchain you'd like to create, and choose Seed Phrase Type. As this guide focuses on creating a Multichain wallet, choose **Multichain** and click **Continue**

Coin98 supports generating 2 types of Seed Phrases: 12 words and 24 words. The 12-word seed phrase is set as default.

**Step 4:** Name the wallet, backup Seed phrase/Private Keys, and read the warnings carefully.

**Important note:**

Please pay attention to every word and make sure you back up the Seed Phrase correctly and in a safe place.

**Step 5:** Tick three checkboxes to confirm your awareness of the risks when losing keys and click **Create** to complete

<figure><img src="https://docs.coin98.com/~gitbook/image?url=https%3A%2F%2F2549780185-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FirKWZRA5WMZ5uBeDGB96%252Fuploads%252F0bZ3rng6YCvhwj28UIwB%252FScreenshot%25202025-06-09%2520at%25204.33.19%25E2%2580%25AFPM.png%3Falt%3Dmedia%26token%3D5fd66ced-51ab-4f70-8fba-e5e6f0d60efb&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=4069900a&#x26;sv=2" alt=""><figcaption></figcaption></figure>

After having been created successfully, your wallet will be shown automatically in the All Wallets section.

* Once your wallet has been successfully created, a pop-up will appear prompting you to back up its seed phrase via Cloud.
* This provides an additional layer of protection in case your seed phrase is lost, enabling you to recover your wallet using the Cloud backup feature.

<figure><img src="https://docs.coin98.com/~gitbook/image?url=https%3A%2F%2F2549780185-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FirKWZRA5WMZ5uBeDGB96%252Fuploads%252FHbmFNa7Cx6jfZ6htfnNZ%252Fimage.png%3Falt%3Dmedia%26token%3Dd541b073-8270-499e-9291-c7f57cb5deec&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=c5e72683&#x26;sv=2" alt="" width="375"><figcaption></figcaption></figure>

Once completed, the wallet will be displayed on the main interface. You can also access diverse features of Coin98 Super Wallet.

### Restore a wallet on the Coin98 Super Wallet

If you already have a wallet, you can simply import it to Coin98 Super Wallet to store coins/tokens as well as experience multiple AMMs and the Web3 Dapp Browser directly on the Mobile App.

To import a wallet to Coin98 Super Wallet, you need its **Seed phrase**. Therefore, you should store the Seed phrase carefully from the moment of creating the wallet.

Seed phrase and Private Key are security keys that can be understood as a type of password in which the Seed phrase consists of 12 random English keywords, while the Private Key consists of a string of letters and numbers.

If you want to restore access to your wallets, you must have ownership of the Seed phrases (used for restoring both Single Chain Wallet and Multichain Wallet) or Private Key (only used for restoring Single Chain Wallet).

**Step 1**: At the top right corner of the home page, choose **Add Wallet** icon

**Step 2:** Click **Add an Existing Wallet**, then select your desired wallet type

If you're unclear about these wallet types, you can refer to a wallet comparison by clicking the icon in the top right corner.

<figure><img src="https://docs.coin98.com/~gitbook/image?url=https%3A%2F%2F2549780185-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FirKWZRA5WMZ5uBeDGB96%252Fuploads%252FugS83h3f6RUda5OsypT4%252FScreenshot%25202025-06-09%2520at%25204.56.26%25E2%2580%25AFPM.png%3Falt%3Dmedia%26token%3Da2c1b22a-b65d-42ea-b885-4edecc10ec40&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=8dab22cb&#x26;sv=2" alt=""><figcaption></figcaption></figure>

**Step 3:** Name the walle and choose **Multi-Chain**

**Step 4:** Paste Seed Phrase into the Seed Phrase box and click **Restore** to complete.

<figure><img src="https://docs.coin98.com/~gitbook/image?url=https%3A%2F%2F2549780185-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FirKWZRA5WMZ5uBeDGB96%252Fuploads%252F9vU52kpFak1BBjHFQPTN%252FScreenshot%25202025-06-09%2520at%25204.57.49%25E2%2580%25AFPM.png%3Falt%3Dmedia%26token%3Da0bb776d-8c69-4351-9d38-13bb75927d81&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=8fd1b060&#x26;sv=2" alt=""><figcaption></figcaption></figure>

**Note:**

Coin98 supports 2 import options (New Standard or Old Standard) for each wallet on some blockchains such as Bitcoin, Solana, Avalanche C-chain, Viction (formerly Tomochain), Celo, Injective, The Open Network, Tron, Persistence and Aptos (including Aptos Testnet, Aptos Devnet and Aptos mainnet). If the correct standard is not selected, the wallet cannot be properly recovered.

<figure><img src="https://docs.coin98.com/~gitbook/image?url=https%3A%2F%2F2549780185-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FirKWZRA5WMZ5uBeDGB96%252Fuploads%252FYFjc91kLSazFop2R4GcG%252FScreenshot%25202025-06-09%2520at%25204.59.37%25E2%2580%25AFPM.png%3Falt%3Dmedia%26token%3Da655ae39-868b-4fcd-ae93-d05f5a5943c8&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=db38e4e0&#x26;sv=2" alt=""><figcaption></figcaption></figure>

## III. How to add a custom Network on Coin98 Super Wallet

**Step 1:** Click the More icon **"..."** on the main screen;

**Step 2:** Click on the **"V"** icon next to the More Wallet Features to show additional features supported on Coin98 Super Wallet;

**Step 3:** Choose **Custom B**

**Step 4:** Click on the Add icon **"+"** at the top right corner;

**Step 5:** You can select from a predefined Custom Blockchain Profile list in the **Profile** section. If the network you want to add is not available in the Profile list, you can manually input the following information about the Network:

1. Network
2. Chain Name
3. RPC URL
4. Chain ID
5. Symbol
6. Block Explorer URL (Optional)

**Step 6**: After filling in the required fields, select **Create**

<figure><img src="https://docs.coin98.com/~gitbook/image?url=https%3A%2F%2F2549780185-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FirKWZRA5WMZ5uBeDGB96%252Fuploads%252Fc6v7PfWTBhPIYzdp0siZ%252FScreenshot%25202025-06-11%2520at%252010.32.32%25E2%2580%25AFAM.png%3Falt%3Dmedia%26token%3Df0ebe41d-d1ac-48f7-af72-b9a681badfac&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=19e30da1&#x26;sv=2" alt=""><figcaption></figcaption></figure>

**Step 7:** Back to your All Wallets section, then [create](https://docs.coin98.com/products/coin98-super-wallet/mobile/getting-started/v15-how-to-create-or-import-a-multichain-wallet) or[ import](https://docs.coin98.com/products/coin98-super-wallet/mobile/wallet-management/v15-how-to-import-multi-chain-wallets-to-coin98-super-wallet) the new wallet for the newly created Custom Blockchain.

<figure><img src="https://docs.coin98.com/~gitbook/image?url=https%3A%2F%2F2549780185-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FirKWZRA5WMZ5uBeDGB96%252Fuploads%252Fxost9TNaL07F6gIG1qEd%252Fcoin98-app-custom-network-2.png%3Falt%3Dmedia%26token%3Dc7665580-5c82-40f7-a62c-20bef20e99cd&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=17878b2d&#x26;sv=2" alt="" width="375"><figcaption></figcaption></figure>

## III. How to send/ receive a token

### **How to send a token**

**Step 1:** Select the token you want to send

*Option 1:* Click on **Send** from the Home page => select or search for the token you want to send

<figure><img src="https://docs.coin98.com/~gitbook/image?url=https%3A%2F%2F2549780185-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FirKWZRA5WMZ5uBeDGB96%252Fuploads%252FQk3Jn9BRB4tjGpsrTTop%252FScreenshot%25202025-06-07%2520at%252011.50.33%25E2%2580%25AFPM.png%3Falt%3Dmedia%26token%3D661d4350-5680-447b-8756-556b94704b9b&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=c2f87150&#x26;sv=2" alt="" width="563"><figcaption></figcaption></figure>

*Option 2:* Choose the token on the Home page => click the **Send** button

<figure><img src="https://docs.coin98.com/~gitbook/image?url=https%3A%2F%2F2549780185-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FirKWZRA5WMZ5uBeDGB96%252Fuploads%252F95v6DySSXghHTvLG5BfR%252FApp-V16-%2520Send-1.png%3Falt%3Dmedia%26token%3D633d117c-f396-4882-ab22-97d046e893ed&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=e3d5f252&#x26;sv=2" alt="" width="563"><figcaption></figcaption></figure>

**Step 2:** Input the Recipient's Wallet Address => Click the **Continue** button

Once you enter the recipient address, Coin98 will automatically verify it and generate an anomaly report to alert you of any potential risks before you proceed with the transaction. Anomaly scan is currently supported on BSC, BTC, SOL and ETH.

Note:

The recipient’s wallet address can be:

* a wallet address (e.g: 0x3350beB9Fc5a8E5f3f998aA98Ab3Fdb250C3dA64)
* a OneID (e.g: csteam.c98)

**Step 3:** Review the information, then press and hold the **Hold To Send** button

<figure><img src="https://docs.coin98.com/~gitbook/image?url=https%3A%2F%2F2549780185-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FirKWZRA5WMZ5uBeDGB96%252Fuploads%252FbbdA9ceZDL11EuWdjVvr%252FScreenshot%25202025-06-07%2520at%252011.55.59%25E2%2580%25AFPM.png%3Falt%3Dmedia%26token%3D09ff45a4-791d-4828-a7d3-e797f224ce69&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=1832d7a7&#x26;sv=2" alt=""><figcaption></figcaption></figure>

**Note**: Here you can check the Gas Fee and adjust the Custom gas. Make sure to prepare a small amount of father token for the gas fee.

### **How to receive a token**

***Option 1**:*

**Step 1:** Click on **Receive** from the Home page => select or search for the token you want to receive

**Step 2:** If the wallet you want to receive the token to is not the currently active one, tap the expand icon to switch to your desired wallet.

**Step 3**: Copy the wallet address

<figure><img src="https://docs.coin98.com/~gitbook/image?url=https%3A%2F%2F2549780185-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FirKWZRA5WMZ5uBeDGB96%252Fuploads%252FhkdTAnhwVp39HjrVNjAl%252FScreenshot%25202025-06-11%2520at%25203.42.38%25E2%2580%25AFPM.png%3Falt%3Dmedia%26token%3D4090b4cc-63e6-489b-84ed-1e460255343d&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=8c3929c6&#x26;sv=2" alt=""><figcaption></figcaption></figure>

***Option 2**:*

If you want to receive the token to the currently active wallet, simply select the token from the Home page and click **Receive**.

<figure><img src="https://docs.coin98.com/~gitbook/image?url=https%3A%2F%2F2549780185-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FirKWZRA5WMZ5uBeDGB96%252Fuploads%252FjAjE97l3GupJiFZT0As0%252FScreenshot%25202025-06-11%2520at%25203.22.23%25E2%2580%25AFPM.png%3Falt%3Dmedia%26token%3De6193de6-a4e4-4cf2-aeb0-0d03d99e481f&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=43c6af8e&#x26;sv=2" alt=""><figcaption></figcaption></figure>

***Option 3**:*

Note that the tokens on the same network have the same wallet address. In other words, a wallet address can receive different tokens that are supported on that network. So you can also get the wallet address of the token in the Manage Wallet section. Make sure that you choose the correct network of the token you want to receive.

**Step 1**: On the Home screen, click on the OneID logo at the top left corner.

**Step 2**: Click on **My Wallets** => Choose the wallet that you want to receive the tokens

**Step 3**: Click **View all wallet addresses** => Click on Copy icon next to the wallet whose address you want to get

<figure><img src="https://docs.coin98.com/~gitbook/image?url=https%3A%2F%2F2549780185-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FirKWZRA5WMZ5uBeDGB96%252Fuploads%252FlwasFlYzcpVnVwjMNoO6%252FScreenshot%25202025-06-11%2520at%25204.04.37%25E2%2580%25AFPM.png%3Falt%3Dmedia%26token%3D79009111-3fe9-4ff7-9cf1-67459f3c5267&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=b99a6758&#x26;sv=2" alt=""><figcaption></figcaption></figure>

And that’s it! You should now see your wallet, ready to send and receive funds.


# Metamask

This guide shows how to connect Metamask to the Viction Mainnet.

First install the[ MetaMask Extension](https://metamask.io/) on Chrome or Brave browsers. Once you agree to the Metamask Terms of Use and create an account successfully, follow instructions:

**Step 1:** Click the MetaMask logo on the browser to open the Extension -> select Network -> select Custom RPC as shown below:

![](https://lh4.googleusercontent.com/kOi0vanOKwQxRi_08zptnbXkrgb5I9RiniQZITS_yq_jzyInfPFUi8eQncrGfwansA0JoegI_BbXvKqJzW6ye-59nIPQLYoeA_thq84iaMHQcTfyztJ83mCiCpWH6ns7bL1b97N5LcYqwP2ZsBvh3pI)

**Step 2:** When the Settings screen pops up, scroll down to New Network and click Show Advanced Options. Enter the following information, then Save:

| <p><br></p>        | Mainnet                   | Testnet                           |
| ------------------ | ------------------------- | --------------------------------- |
| New RPC URL        | <https://rpc.viction.xyz> | <https://rpc-testnet.viction.xyz> |
| ChainID            | 88 or 0x58                | 89                                |
| Symbol             | VIC                       | VIC                               |
| Nickname           | Viction                   | Viction Testnet                   |
| Block Explorer URL | https\:/vicscan.xyz       | <https://testnet.vicscan.xyz>     |


# Ledger

VIC and tokens issued on Viction are officially supported by the Ledger Nano S hardware wallet. The following describes how to use Ledger Nano S to connect to and use Viction Labs' services.

This guide will show how to

* Install the Viction App on the Ledger Nano S
* Access the VIC Wallet with the Ledger Nano S through MetaMask and MyEtherWallet.
* Receive VIC
* Send VIC
* Check account balance on the Viction Explorer (VicScan)

### Requirements

* A [Ledger Nano S hardware wallet](https://www.ledger.com/collections/all-products) with latest firmware.
* Latest version of VIC app installed
* A computer with at least macOS 10.9, Windows 8 (64-bit) or Linux Ubuntu 16.10
* An internet connection and an available USB port. Use an [adapter](https://www.ledger.com/products/ledger-otg-kit) for USB-C ports
* A U2F compatible browser (Google Chrome, Opera, FireFox, Brave)

For instructions on how to install Ledger Live, please refer [here](https://support.ledger.com/hc/en-us/articles/360006395553/).

### Installing the VIC Ledger Nano S Application

Using the Ledger Live application, follow these instructions:

* Open the Manager in Ledger Live
* Connect and unlock the Ledger Nano S
* Allow the Manager on the Ledger Nano S device by pressing the right button if asked
* Search the App catalog for VIC, and click the Install button next to the VIC app
* An installation window will appear, and the device will display Processing…
* The VIC App installation is complete and ready to use

### Connect with MyEtherWallet

Users can use [MyEtherWallet vintage](http://vintage.myetherwallet.com/) for Ledger Nano S to connect to Viction. We recommend checking and following [this clear tutorial](https://support.ledger.com/hc/en-us/articles/115005200009) with the following information:

**Note:** Select **VIC (viction.xyz)** the crypto asset network in the top-right corner. Select m/44'/60'/0'/0 as the derivation path

### Connect to VicMaster

VicMaster is the decentralized governance Dapp of Viction, allowing users to vote/unvote for masternodes and apply to become a Masternode Candidate.

* Make sure the Ledger Nano S device is powered on, unlocked and the Viction Dapp is open
* Plug the Ledger Nano S into your PC/Laptop
* Go to [VicMaster](https://vicmaster.xyz/) using a U2F-compatible browser
* Click on the Login button (top right)
* Select Ledger Wallet from the dropdown list
* Choose the m/44’/60’/0’/0 path if the Ledger Nano S has the latest firmware. Otherwise, use m/44’/889’/0’/0 path

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

* Click on Save
* Choose one of the addresses that you want to use
* VIC Balance (right column) should show next to addresses (the first address has 2 VIC as in the figure)
* Click on Unlock your wallet

**Note:** Now you can use Ledger Nano S and VicMaster to vote and/or apply to become a Masternode Candidate (please refer to [here](https://docs.viction.xyz/get-started/voting/) and [here](https://docs.viction.xyz/get-started/apply-node/) for how to vote and apply to become a Masternode).


# How to troubleshoot when the node is up but couldn't begin to sync block

In general, as long as the node is operational, it will begin to sync new blocks. However, there were a few unknown behaviors that prevented the block from synchronizing. As a result, this instruction will be helpful in resolving the issue of blocks not synchronizing once the node has been powered up.

<figure><img src="/files/tPYlYaGDWoXjJPCvQCaX" alt=""><figcaption><p>Node is Up but unable to sync new blocks</p></figcaption></figure>

The reason can come from the P2P port (default **30303**) from the node had been blocked by the Firewall. &#x20;

* **Solution**:  Rectify  & Unblocked the port.
* If the case that the firewall had been opened for the port. Then please try to run the node with the add-on command  `--nat extip:111.111.111.111` with `111.111.111.111` is the IP address to connect with internet (external network) of that node.

{% hint style="info" %}
Tips: If you are unsure whether your the port **30303** is **opened** or **not**, hence you can check it via port-checker online tools. For example: <https://www.yougetsignal.com/tools/open-ports/>
{% endhint %}

<figure><img src="/files/eyyiJGBEU6KIDYdtNZqO" alt="" width="375"><figcaption><p>Example for Port <strong>30303</strong> <strong>opened</strong></p></figcaption></figure>

<figure><img src="/files/nF5Hifw1hZlPZghiUeAF" alt="" width="375"><figcaption><p>Example for Port <strong>30303</strong> <strong>closed</strong></p></figcaption></figure>

In case you are running the node via Docker, then you need to:

* Open the port **30303** to internet for **TCP/UDP**
* Docker should use the network mode `host` instead of `bridge`

&#x20;**Incorrect** mapping port

```
      - "30343:30303"
      - "30343:30303/udp"
```

**Correct** mapping port

```
  - "30303:30303"
  - "30303:30303/udp"
```

{% hint style="success" %}
The explanation for the network mode host is that Docker may use the port as long as it starts the container; it does not need to map to another port. This will result in improved performance as docker will no longer need to proxy traffic.
{% endhint %}

Example of the `docker start command`

```
networks:
  viction:
    ipam:
      driver: default
      config:
        - subnet: 10.0.155.0/24

services:
  geth:
    image: *****.example-vic-repo.amazonaws.com/vic:1ef45erd
    restart: unless-stopped
    stop_signal: SIGTERM
    stop_grace_period: 300s
    volumes:
      - /viction:/var/data
      - ./password:/app/password
    networks:
      - viction
    ports:
      - "8595:8545"
      - "30303:30303"
      - "30303:30303/udp"
    entrypoint:
      - /app/geth
      - --datadir=/var/data
      - --syncmode=full
      - --gcmode=full
      - --networkid=88
      - --announce-txs
      - --rpc
      - --rpccorsdomain=*
      - --rpcaddr=0.0.0.0
      - --rpcport=8545
      - --rpcvhosts=*
      - --rpcapi=db,eth,net,web3,personal,debug
      - --ws
      - --wsaddr=0.0.0.0
      - --wsport=8546
      - --wsorigins=*
      - --gasprice=250000000
      - --bootnodes=enode://fd3da177f9492a39d1e7ce036b05745512894df251399cb3ec565081cb8c6dfa1092af8fac27991e66b6af47e9cb42e02420cc89f8549de0ce513ee25ebffc3a@3.212.20.0:30303,enode://97f0ca95a653e3c44d5df2674e19e9324ea4bf4d47a46b1d8560f3ed4ea328f725acec3fcfcb37eb11706cf07da669e9688b091f1543f89b2425700a68bc8876@3.212.20.0:30301,enode://b72927f349f3a27b789d0ca615ffe3526f361665b496c80e7cc19dace78bd94785fdadc270054ab727dbb172d9e3113694600dd31b2558dd77ad85a869032dea@188.166.207.189:30301,enode://c8f2f0643527d4efffb8cb10ef9b6da4310c5ac9f2e988a7f85363e81d42f1793f64a9aa127dbaff56b1e8011f90fe9ff57fa02a36f73220da5ff81d8b8df351@104.248.98.60:30301
      - --mine
      - --keystore=/var/data/keystore
      - --password=/app/password
      - --unlock=*****
      - --verbosity=5
```

If you are looking for other bootnodes, please refer to this [link](https://docs.viction.xyz/developer-guide/deploy-on-viction/viction-mainnet#bootnodes)

More detail for using the docker to run a node in mainnet can be found at the readme file [here](https://github.com/BuildOnViction/victionchain?tab=readme-ov-file#run-docker)


# How to Vote for Viction Saigon Network Upgrade Proposal

Below are the instructions for participating in the voting process for the Viction Saigon Network Upgrade Proposal.

## I. Vote guidance

### For those using Mobile to vote

Here, we will utilize the Coin98 Super Wallet for voting. If you don't have the wallet used for voting on Coin98 Super Wallet, you can follow these steps:

**Step 1:** Download and set up your Coin98 Super Wallet [here](https://docs.coin98.com/products/coin98-super-wallet/mobile/beginners-guide/how-to-download-install)

**Step 2**: Restore your wallet using the Seed Phrase or Private Key. You can refer to the detailed instructions[ here](https://docs.coin98.com/products/coin98-super-wallet/switch-to-coin98-wallet/multi-chain-wallet)

<figure><img src="https://lh7-us.googleusercontent.com/PrVUGmhVTwtcAVZrB25sJ7CLCsH443Nx7pNaJYgvqw3DVV_WAYPaoyvXUGxZOlREhpRPsPPsY_WpuOqdLyrGzhuKGW-Kq-xJ8_GQjMrjLhmivzi_QdEVZ9duFnX17zaeoVaCBYCJEawy0QCqVASAUZ4" alt=""><figcaption></figcaption></figure>

After you already have your wallet on Coin98 Super Wallet, you can access the proposal via the Dapp Browser feature on Coin98 Super Wallet.\
**Step 3:** Access the Dapp Browser section and search for **gov.viction.xyz** or directly click the Viction Governance shown on the interface.

<figure><img src="https://lh7-us.googleusercontent.com/VRWb2nFTEkFc4Z9bBbNw2GVWQKZ4O-bFhybEYshNKcBNhIrBESP3MVToDWpMTBsJdy-cd5hkuHB4GDbTq0_vbabw-VPM1sQhL4r1ehCGbjcgspAoplBPlXsVRL3ojKvn23lEPoCcP82-250SUAcDXoE" alt=""><figcaption></figcaption></figure>

**Step 4:** Select the chain (Viction) and your desired wallet.

**Step 5:** Click on **Connect Wallet** and select **Coin98**

<figure><img src="https://lh7-us.googleusercontent.com/Naoydtzinu0xhuLi9OnSmyH-0ZFizNeb6C1WDiGn85pBHc9D37189TJ4xxHNNhMAXSX7UI1VrrT1en05zxN1PNdplq3R-DtQtfqPpN5RMiDttPtcV8JuwIT0pzedVSp0xWdPbyLBES6zXkQkYq-zSVs" alt=""><figcaption></figcaption></figure>

**Step 6**: Read the proposal carefully and check your voting rights.

**Step 7:** Scroll down to the **Cast Your Vote** section. Give your vote by clicking **Agree** or **Disagree** according to your preference.

* Agree:  means saying “Yes" to the proposal&#x20;
* Disagree: means saying “No" to the proposal

**Step 8**: Click **Vote** and wait a moment for the process to complete.

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

### For those using PC to vote

**Step 1:** Access <https://gov.viction.xyz/>

**Step 2**: Click on **Connect Wallet** at the top right corner.

<figure><img src="https://lh7-us.googleusercontent.com/i1sw_afhbZc9PUPEzBhdzIzmIIqZbQIbS_rAgCakKlMm97fuFMUJyfn440TVE4LD_jjKNY7Ti-Xz1zPPHqh_NvRbQdWY3NyyRQOjgxzX236Fo0k9Q1obzRpUipKybwCv7cGtLGiNQagFVz-11DdRqI8" alt=""><figcaption></figcaption></figure>

**Step 3:** Choose the wallet you want to connect with.

<figure><img src="https://lh7-us.googleusercontent.com/R9f9DE7MYK92YiVjlowRUjDfUJviez1lChyBLPLFTf95_I4tAmT_HrNZeEUnI0uzsFm62kFcH8bLAzKaL-KQxMB24_HL8IUmhIatcyEWh8ZLe1bVbQW7nnniJz6kVQZX1SEmI0CP4D0hdkP0xpf7Z3w" alt=""><figcaption></figcaption></figure>

After connecting successfully, read the proposal carefully and check your voting rights.

**Step 4:** Give your vote by clicking **Agree** or **Disagree** according to your preference.

* Agree:  means saying “Yes" to the proposal&#x20;
* Disagree: means saying “No" to the proposal

**Step 6:** Click **Vote** and wait a moment for the process to complete

<figure><img src="https://lh7-us.googleusercontent.com/AzfwOra-uJ7sn7UtD_C31zU0frv2EVA1xmGtNkxKP2fteXWBnLVEj7nBi3R-bMbWJhUdgzGs3BoPhr6Rc_e8yS-sQhyl7TrKRxMOja9Ki0ENjJ53IeFitb9NCKoXQaPi9DyJ0ayWj8D7F_1zJMEF87U" alt=""><figcaption></figcaption></figure>

## II. Retract vote guidance

If you want to change your vote and wish to retract it, you can follow these steps:

**Step 1**: Move to the Cast Your Vote section

**Step 2:** Click **Retract vote** & Confirm the Signature request

Now you’ve retracted the vote successfully.

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


# How to issue a token via VICIssuer

In this article, we are stimulate the process to issue a token via VicIssuer

## Issue a token on Vic Issuer <a href="#issue-a-token-on-vic-issuer" id="issue-a-token-on-vic-issuer"></a>

* VICIssuer on Testnet: <https://issuer-testnet.viction.xyz/>
* VICIssuer on Mainnet:<https://issuer.viction.xyz/>

The user is required to declare the Token Name, Symbol & Total Supply in order to issue the new token.

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

Ensure that all detail is correct then click on the **Issue Token** button. The code here is only displayed in this step. Hence It is recommended that you copy & store it to your file. So you can use it to perform the contract verification later on.

{% hint style="warning" %}
If you didn't copy the source code here, there is no way for you to go back to copy it again.
{% endhint %}

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

Allow the connection to the site & Confirm to deploy a new contract via wallet pop-up

<div><figure><img src="/files/fFMZHmbaNCsrrpBmbZW4" alt=""><figcaption></figcaption></figure> <figure><img src="/files/Z4WXZM9jXRy0vBZWaVri" alt=""><figcaption></figcaption></figure></div>

The token has been issued successfully

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

**View** the contract at the dashboard of **VicIssuer**. Click on the contract address to view on explorer

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


# How to verify if a contract has been issued via VICIssuer

In this article, we will cover for how to verify the token contract had been issued by VICIssuer

## Prerequisites

A token cantract is issued by VICIssuer (Guide: <https://docs.viction.xyz/how-to/how-to-issue-a-token-via-vicissuer>)

* VICIssuer on Testnet: <https://issuer-testnet.viction.xyz/>
* VICIssuer on Mainnet:<https://issuer.viction.xyz/>

## Verify the token contract

Open the contract detail URL on the **Vicscan** or **VICIssuer** UI

<div><figure><img src="/files/JKZDpRZs7Ofeopi6sSII" alt=""><figcaption></figcaption></figure> <figure><img src="/files/hisbhG5PTzVD8RnRPabM" alt=""><figcaption></figcaption></figure></div>

Click on the **Contract** tab & click on **Verify & Publish** button

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

Fulfill the details for:

* **Contract Address**: **Fetched** the contract address **automatically**
* **Contract Name**: If you create a **token** via **Viction Issuer** then the name should be
  * **MyVRC25Mintable** for **Reissueable** token (selected when issuing)
  * **MyVRC25** for **Non-reissueable** token
* **Complier:** Select the compiler version **v0.7.6** for verifying the **contract is issued** from **VicIssuer**
* **Optimization:** Default is **No**. Refer: [![](https://cdn.sstatic.net/Sites/ethereum/Img/favicon.ico?v=40dede55262c)'Runs (Optimizer) ' and 'Optimization' while verifying source code on Etherscan](https://ethereum.stackexchange.com/questions/64172/runs-optimizer-and-optimization-while-verifying-source-code-on-etherscan)
* Click on the “**Add Solidity Source Code**“ to input the source code.
  * **File name** can be any thing without **space** or **special characters**.
  * **Solidity Source Code**: copy & paste your source code from the VicIssuer screen. If you forget about it, Please view the token info to get it again.

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

The Contract is verified successfully

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


# How to deploy the VRC725 contract

This is the step by step guide to deploy the VRC725 contract

## Deploy a VRC725 contract

Open Remix IDE at: <https://remix.ethereum.org/#lang=en&optimize=false&runs=200&evmVersion=null&version=soljson-v0.8.26+commit.8a97fa7a.js>

Cloning the VRC25 from the Repo URL: <https://github.com/BuildOnViction/vrc725.git>

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

The source code struture will be displayed as image

<figure><img src="/files/pXU7RROcyciktYCDsUdG" alt="" width="335"><figcaption></figcaption></figure>

Under the contracts folder there will be an example for **VRC725 Contract**

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

Now, we would like to compile the contract as image. Please ensure that the compiler version is **0.8.17+commit.8df45f5f**

<figure><img src="/files/t5aGM4Z1iKr4apyZosze" alt="" width="371"><figcaption></figcaption></figure>

Next, we would like to deploy the contract which had been built & compiled above. In this scenario, we are using the **Injected Provider - Coin98 Wallet**. Hence the following pop-up will be displayed.

Since we are using the **C98 Wallet**, hence the **Gas Limit** option can be ticked on **Estimated Gas** per default. However, if you are using the **Metamask**, it is recommended that you would increase it a bit to avoid the failure. The suitable number should be **5000000** wie

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

After that, we need to fulfill the **Name**, **Symbol** & the **Issuer** (The connected wallet: **0x4bCfFA4D24f774486399230924b2545ee7134bFe**) for the contract. Once all detail is filled up, you can click on the transact button. The pop-up will be displayed to confirm for further process.

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

If the contract is successfully deployed, the following message will be displayed.

<figure><img src="/files/3Xsil0TVzoiftKpSlzv7" alt=""><figcaption></figcaption></figure>

The onchain TX can be found at: <https://testnet.vicscan.xyz/tx/0xfb7c50988b780d501348cb22d0eb4076d031e53061f35a3d0adc2e8dca346dd3>

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

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

After we had the VRC725 contract, the next step is to apply the Viction ZeroGas for it.


# How to apply ZeroGas for VRC725 contract

This is the step by step guide to apply the ZeroGas protocol for any  VRC725 contract

## Prerequisites

The VRC725 contract had been deployed (Guide: <https://docs.viction.xyz/how-to/how-to-deploy-the-vrc725-contract>)

## Applying Vic ZeroGas Protocol

This step can be achieved by following step:

* Navigate to the **VRC25Issuer Contract** on **Vicscan**
  * Testnet: [https://testnet.vicscan.xyz/address/0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee](https://testnet.vicscan.xyz/address/0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee#code)
  * Mainnet:<https://www.vicscan.xyz/address/0x8c0faeb5c6bed2129b8674f262fd45c4e9468bee>

{% hint style="info" %}
**Hint**: Please **ensure** that the address to call **apply** function must be current **owner of your token**.
{% endhint %}

* Access to Contract tab & **connect** the wallet

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

* Input **10 VIC** for the deposit & the **VRC725 contract address** (**0x4d76D1eBe3E95Ad0b8B4Ce59ABedE9cF1A7Bc593**) to apply the ZeroGas.

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

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

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

Then your **VRC725 contract** is now **ZeroGas** with the following transactio&#x6E;**:** <https://testnet.vicscan.xyz/tx/0x66c39ec3474366a6eae64d37c0d4c72796af7fb967a4cba4ea1690bc75349b89>


# How to Migrate Dapps from Ethereum

Now that we’ve successfully compiled, it’s time to migrate your smart contracts to Viction’s blockchain!

Work In-Progress


# How to register Token or NFT logo on Vicscan

This guide will show you how to register your Token of NFT logo, so that they are displayed on Vicscan

&#x20;Follow the steps in this [guide](https://github.com/BuildOnViction/tokens/blob/master/README.md) to register your Token or NFT logo on [Vicscan](https://www.vicscan.xyz/).


# How to verify a contract on Vicscan

This guide will show you how to verify a contract on Vicscan

**Outcome:**&#x20;

* Verifying a smart contract on Viction is a crucial process that ensures transparency and builds trust in blockchain applications
* The contract will be verified with the status “**Contract Verified**” <img src="/files/bkjDqkOunaefbgBMlyuB" alt="" data-size="line"> on [Vicscan](https://www.vicscan.xyz/). Allowing **the source code to be publicly visible to view, read on VicScan**.
* If both the contract is verified and the [project is confirmed](/how-to/how-to-confirm-a-project-on-vicscan), the contract status will be updated to <img src="/files/MMc97RKxoHDaOWIS62ez" alt="" data-size="line">

**How to verify your contract:**

* **Approach 1**: Manual Contract Verification [Vicscan](https://www.vicscan.xyz/)
  * **Action Required**: Partners manually verify the contract on [Vicscan](https://www.vicscan.xyz/).
  * **Steps**:
    * Go to the VicScan explorer and search for the contract.
    * Click on **Contract/Verify & Publish** to initiate the verification process.

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

* **Approach 2**:
  * **Action Required**: Alternatively, partners can use the Hardhat plugin to verify the contract. A detailed guide is available to assist with this process.
  * **Guidance**: [Hardhat | Viction](https://docs.viction.xyz/smart-contract-development/smart-contract-verification/hardhat).


# How to confirm a project on Vicscan

This guide will show you how to confirm a project on Vicscan

To officially **confirm that the contract belongs to the recognized project**. This provides validation to users that the project is legitimate and officially associated with the contract on [Vicscan](https://www.vicscan.xyz/).

**Outcome:**&#x20;

* The contract will be confirmed with the status “**Project Confirmed**” <img src="/files/KauHoWfrvQ16ERq2s1gr" alt="" data-size="line"> on [Vicscan](https://www.vicscan.xyz/), verifying that the contract belongs to the officially recognized project.
* If both the project is confirmed and the [contract is verified](/how-to/how-to-verify-a-contract-on-vicscan), the contract status will be updated to <img src="/files/MMc97RKxoHDaOWIS62ez" alt="" data-size="line">

**How to confirm a project on Vicscan:**

Send a confirmation email to `support@viction.xyz`. Use your official organization email domain to make this request, and include the token contract address.

**Email template:**

`From: user1@victiny.xyz`

`Subject: Confirm Project's Address on Viction`

`Dear Viction Support Team, I confirmed that the [token_address] was belong to our project.`

`Regards,`&#x20;

`User1's Name`


# How to check if a token is gas sponsored on Viction

This guide will show you how to check if a token is gas sponsored on Viction

### **Step 1: Check if the Token is in the Sponsor List** <a href="#step-1-check-if-the-token-is-in-the-sponsor-list" id="step-1-check-if-the-token-is-in-the-sponsor-list"></a>

* **Objective:** Verify if the token is eligible for gas sponsorship.
* **Function:** Use the `tokens` function from the [Issuer Contract](https://www.vicscan.xyz/address/0x8c0faeb5c6bed2129b8674f262fd45c4e9468bee#code).

**Steps:**

1. Call the `tokens` function with the token address or identifier.
2. If the token exists in the sponsor list, proceed to Step 2. Otherwise, it is **not sponsored**.

### **Step 2: Check Token Capacity** <a href="#step-2-check-token-capacity" id="step-2-check-token-capacity"></a>

* **Objective:** Determine if the token has remaining gas sponsorship capacity.
* **Function:** Use the `getTokenCapacity` function.

**Steps:**

1. Call `getTokenCapacity` with the token address or identifier.
2. Interpret the response:
   * **If > 0:** Token can sponsor gas.
   * **If = 0:** Token sponsorship is exhausted. Transactions will be failed.

#### **Key Functions:** <a href="#key-functions" id="key-functions"></a>

Simple flow:

1. Call `tokens` to check sponsorship eligibility.
2. If eligible, call `getTokenCapacity` to validate capacity:
   * 0: Sponsored.
   * \= 0: Not sponsored.
3. Cache results for faster future checks.


# How to verify gas sponsored transactions

This guide will show you how to verify gas sponsored transactions

## Background <a href="#background" id="background"></a>

As the current status of VRC25 standard, a few partner or users had been issued the token successfully. However, they are unable to regconize whether their transactions had been applied for ZeroGas or not. Hence this article is a guidance for how can they ensure that they applied the ZeroGas successfully.

## Prerequisite <a href="#prerequisite" id="prerequisite"></a>

* Assumed that the Token had been applied succesfully. If the token had not been created or not event apply it. Then kindly follow the guidance as here: <https://docs.viction.xyz/developer-guide/integration/vic-zerogas-integration>
* If the token had been issue via **VicIssuer**, then you can follow this guidance:[How to issue token, apply ZeroGas & testing on Viction Blockchain Testnet](https://coin98.atlassian.net/wiki/spaces/TT/pages/268075011)

## Getting Started <a href="#getting-started" id="getting-started"></a>

As the following image, the. user issued the token successfully. However, they know how to rectify whether the transaction is zero gas or not.

New Issued Token contract: <https://testnet.vicscan.xyz/address/0x4ff96908a19a2AF0E70404eF6Bc0925C0e43700A#code>

VicIssuer Apply Tx: <https://testnet.vicscan.xyz/tx/0xde1aa5624aa5ab025b2b65c0a5c278b3791e930d79aaa3fedfb74d01aa133cba>

Step to verify with the example Tx:  [![](https://testnet.vicscan.xyz/favicon-dark.svg)VIC Scan - The most intuitive Viction explorer](https://testnet.vicscan.xyz/tx/0xf0ea48e8f8e0d02595ccb64821e0fc89ce06c284c976ea552490fc326483c19b)

In the example Tx we would notice a few following detail:

* **Tx Type**: Gas Sponsored
* **Sender** : 0xCc48C437020B17D881C719Ff53DF4e56022Fb61A&#x20;
* **Receiver**: 0xaa3984428fe62211c6485165c30584507175B3fb
* **Fee Payer (Token contract address)**: 0x4ff96908a19a2AF0E70404eF6Bc0925C0e43700A

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

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

As we can see, The Fee payer now is neither **Sender** or **recepient.** It is the token contract address, which means that the token had been **registered** for ZeroGas successfully.

For further testing, you can vist the **VRCIssuer** **contract** to figure whether the token is registered or not & the amout of sponsored fund is remaining by querying the token address.

**Testnet**: <https://testnet.vicscan.xyz/address/0x8c0faeb5c6bed2129b8674f262fd45c4e9468bee>

**Mainnet**: <https://www.vicscan.xyz/address/0x8c0faeb5c6bed2129b8674f262fd45c4e9468bee>

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


# How to create Telegram Mini Apps

This guide will show you how to create Telegram Mini Apps on Viction

## **What are Telegram Mini Apps?**

**Telegram Mini Apps** are lightweight web apps that run inside Telegram chats. They allow developers to create social experiences, games, marketplaces, and other services that tap into Telegram’s features and \~1B audience globally.

### Mini App type

There are two main types of Mini Apps:

#### **Inline Apps**

Inline Apps show up as results when a user types the bot’s username followed by a query. The user taps an app result to launch the Mini App. Inline Apps are great for:

* Search experiences
* Quick interactions
* Discovering new content

#### **Direct Link Apps**

Users can open a Direct Link App just by tapping a link. Direct Link Apps are aware of the current chat context and support shared, collaborative experiences. Direct Link Apps are ideal for:

* Social experiences
* Games
* Productivity tools
* And more

### Core Infrastructure

1. A Telegram-supported wallet: which allows developers to embed web3 wallet into their games. You might refer to the following that support Viction

* Particle Network
* Ramper
* Wallet Connect

\*\* Wallet bot could serve managing your assets without switching between apps outside of Telegram:\*

* WalletX
* Coin98 (coming soon)

1. A Webapp to link to Telegram
2. A Telegram Bot to redirect users to the Webapp
3. Payments - via crypto/Telegram Stars

## Integration

### 1. Create a Telegram Bot

#### Generate a private Telegram Bot

Visit the **@BotFather** bot (developed by Telegram’s core team) and enter **/newbot** to create a new bot. You will receive an API token for your bot. Keep this token private as it will allow you to control your bot.

#### Connect the Webapp to your Bot

Use the **/newapp** command in the **@BotFather** bot by selecting your bot. Provide details such as the app name, description, photo, etc. Finally, enter the URL of your webapp. Your mini app will now appear in the Telegram app and can be launched by users.

#### **Additional Capabilities**

Mini apps opened from a direct link have limited capabilities. They cannot read or send messages on behalf of the user. However, they support cooperative and multiplayer features within the current chat context. Users must redirect to inline mode to actively pick a result in order to send messages.

Mini apps are powerful tools for creating fully-fledged web services, team collaborations, multiplayer games, and more. The possibilities are endless.

### 2. **Register a Game with @GameBot**

The first step is to register your game with @BotFather. Send the /newgame command to @BotFather, and provide the required details including:

* The title and description of your game
* A cover photo
* The message text a user will see when starting a game
* The URL of your Mini App

### 3. Deploy your smart contracts and assets

Viction provide a all-in-one development platform for web3 telegram games to enable seamless game deployment with ease

1. Web3 wallet
2. Management dashboard
3. Audited contract templates for games
4. Game Engine SDK
5. Embedded Marketplace
6. In-game purchase

…Guide by steps from Sequence/Thirdweb/Elympics…

### 4. Using Telegram Stars for in-game purchase

Stars can ONLY be acquired through **in-app purchases** via Apple and Google or [PremiumBot](https://t.me/premiumbot), then spent on **digital products** offered by bots – from **e-books** and **online courses** to items in [Telegram games](https://core.telegram.org/bots#host-games).

Walkthrough [**Bot Payments API for Digital Goods and Services**](https://core.telegram.org/bots/payments-stars)

\*\* There is no current option to enable purchasing Stars using $VIC or other assets on Viction\*

You will find the necessary methods for building your payment implementation in the [Payments Section of the Bot API Manual](https://core.telegram.org/bots/api#payments).

In short, you must:

* Send an invoice via [sendInvoice](https://core.telegram.org/bots/api#sendinvoice) (`currency`: “XTR”)
* Await an [Update](https://core.telegram.org/bots/api#update) with the field `pre_checkout_query`
* Approve or cancel the order via [answerPreCheckoutQuery](https://core.telegram.org/bots/api#answerprecheckoutquery)
* Await an [Update](https://core.telegram.org/bots/api#update) with the field `successful_payment`
* Store the [SuccessfulPayment](https://core.telegram.org/bots/api#successfulpayment)’s `telegram_payment_charge_id` – it may be needed to issue a refund in the future
* Deliver the goods and services purchased by the user

> You may find that some API methods for Payments request a provider\_token. This parameter is only needed for sales of physical goods and services – for digital ones, you can leave it empty.

#### **Step-by-Step Process**

> See Bot API: Payments for the complete list of available methods and objects. Be sure to provide the proper set of parameters to account for the type of goods you are selling, differentiating between digital and physical orders.

#### **1. Create Invoice**

The user contacts `@merchantbot` and requests to purchase something. The bot forms an invoice message with a description of the goods or service and amount to be paid (expressed in Telegram Stars). There are two ways of creating an invoice:

#### **A. Bot Invoice**

Use the [sendInvoice](https://core.telegram.org/bots/api#sendinvoice) method to generate an invoice and send it to a chat. You can pass an empty string as the *provider\_token* parameter, since the invoice is for digital goods and services.

Remember to specify `XTR` in the `currency` field, since all sales of **digital goods and services** are carried out exclusively in Telegram Stars.

#### **B. Inline Invoice**

If `@merchantbot` supports [inline mode](https://core.telegram.org/bots/inline), you can use [inputInvoiceMessageContent](https://core.telegram.org/bots/api#inputinvoicemessagecontent) to allow users to share invoices for your goods and services to their one-on-one chats with friends, or to their groups and channels. These invoices will have a **Pay button** that can be used multiple times.

#### **2. Choose Forwarding Behavior**

There are two ways for handling **forwarded copies** of your invoices, controlled by the parameter *start\_parameter* in the [sendInvoice](https://core.telegram.org/bots/api#sendinvoice) method.

* **A. Multi-chat invoice.** Forwarded copies show a **Pay button**, which multiple users can press and attempt to pay for the goods or services. [Inline invoices](https://core.telegram.org/bots/payments-stars#b-inline-invoice) are always multi-chat invoices.
* **B. Single-chat invoice.** Invoice can only be paid from the chat to which it was sent, *forwarded copies* show a **URL button** with a deep link to the bot. The deep link can be used to generate a similar invoice in the chat with the bot, to show an error message, or for other purposes. [More info on Deep Linking »](https://core.telegram.org/bots#deep-linking)

If a *single-chat invoice* is sent to the chat with `@merchantbot`, it can only be paid **once**. If a *single-chat invoice* is sent to any other chat, it can be paid **many times** by many users.

> To get a better understanding of how this works, try toggling the “Pay from Forwards” parameter when creating invoices with our demo @ShopBot.

Regardless of whether or not the **Pay** button is available in an invoice, the merchant bot always has the power to decide whether or not to accept new payments for a particular invoice.

#### **3. Pre-Checkout**

The user purchases Stars from Telegram (if necessary), then presses the pay button. At this moment the Bot API sends an [Update](https://core.telegram.org/bots/api#update) with the field *pre\_checkout\_query* that contains all the available information about the order to the bot.

Your bot must reply using [answerPrecheckoutQuery](https://core.telegram.org/bots/api#answerprecheckoutquery) within **10 seconds** after receiving this update or the transaction is canceled.

The bot may return an error if it can't process the order for any reason. We highly recommend specifying a reason for failure to complete the order in human readable form (e.g. *"Sorry, we're all out of rubber duck digital posters! Would you be interested in a cast iron bear digital poster instead?"*). Telegram will display this reason to the user.

> Warning: It is critical to make sure your bot only accepts multiple payments when the order can be processed correctly. This is especially important if you are using multi-chat, inline or single-chat, multi-use invoices.

#### **4. Checkout**

If the bot confirms the order and the payment is successful, the API will send a receipt message of the type [*successful\_payment*](https://core.telegram.org/bots/api#message) from the user. Once your bot receives this message, it should proceed with sending the digital goods or services purchased by the user.

> Warning: You must always check that you received a successful\_payment update before delivering the goods or services purchased by the user – simply answering a pre\_checkout\_query does not guarantee a successful order or payment.

If the message was sent to any other chat, the **Pay button** remains and can be used again. It is up to the merchant bot whether to actually accept multiple payments.

### 5. Share your game

Once registered, your game will receive a shareable game URL and a game code which players can enter to launch the game. You can share this URL and code on your website, social media, and within Telegram chats to spread your game to other players.


# How to use VictionSafe (Multisig)

This page will show you how to use Viction Safe (Multisig)

Viction Safe (Multisig) is a secure and user-friendly wallet designed to safeguard digital assets through multi-signature functionality. Supported by RabbitSwap, it offers enhanced security, intuitive interfaces, and seamless compatibility with the Viction ecosystem. Whether you’re managing tokens, interacting with decentralized applications, or exploring DeFi opportunities, Viction Safe (Multisig) ensures a reliable and secure experience.

&#x20;

For developers looking to integrate full support for Viction Safe (Multisig), please contact us on Telegram at[ ](https://t.me/rabbitswap_xyz)[![](https://telegram.org/img/favicon-16x16.png)Snowball | RabbitSwap](https://t.me/rabbitswap_xyz).

&#x20;

To learn more and get started, explore our comprehensive documentation [here](https://docs.rabbitswap.xyz/rabbitswap/viction-ecosystem-tools/viction-safe-multisig).


# FAQ

The most frequently asked questions about Viction products and its ecosystem.

{% content-ref url="/pages/aIA3vTOCvbRJvFcbItfD" %}
[General](/general)
{% endcontent-ref %}

{% content-ref url="/pages/A4fhHnGFokIjvmgb5Drs" %}
[Masternodes and Voting](/faq/masternode-and-voting)
{% endcontent-ref %}

{% content-ref url="/pages/DCWXC8JkQRFYF7rRMKPT" %}
[Products](/faq/products)
{% endcontent-ref %}


# General

{% content-ref url="<https://github.com/BuildOnViction/gitbook/blob/main/faq/general/Viction.md>" %}
<https://github.com/BuildOnViction/gitbook/blob/main/faq/general/Viction.md>
{% endcontent-ref %}

{% content-ref url="/pages/UcDxQBwjIi0gH2dNvKGb" %}
[Ecosystem](/faq/general/ecosystem)
{% endcontent-ref %}

{% content-ref url="/pages/0WXApjnhlzYV1FFidJ1P" %}
[VIC - Economics](/faq/general/vic-economic)
{% endcontent-ref %}

{% content-ref url="/pages/dmLvRTxhv1CYSKjVjYY6" %}
[Contact & Support](/faq/general/company)
{% endcontent-ref %}


# Viction

Viction is a people-centric blockchain, offering zero-gas transactions and enhanced security to make Web3 easy and safe for everyone. Now with Viction World Wide Chain, we provide a novel solution representing a network of app chains that operate concurrently, anchored by a common settlement on Viction. Build, own, win, and be part of Viction World Wide Chain where everyone scales beyond limits.

With a network of 150 masternodes utilizing Proof-of-Stake (PoS) consensus, Viction touts its scalability and stability. It employs advanced techniques like double validation, smart contract staking, and proper randomization to enhance security and chain finality. Viction supports all EVM-compatible smart contracts, protocols, and atomic cross-chain token transfers.

Viction is driven by a mission to build a decentralized platform that empowers humanity to connect, collaborate, and create without limitations, envisioning a world where transparency, accessibility, and growth thrive. That’s why we introduced Viction World Wide Chain.&#x20;

Viction World Wide Chain provides a novel solution, representing a network of app chains that operate concurrently, anchored by a common settlement on Viction. These fractal-like chains are interconnected through Viction World Wide Chain Protocol (WWCP), allowing for fluid asset and data transfer within these chains, and establishing a foundation for extensive scalability and a myriad of decentralized applications

And Viction Data Availability (Viction DA), a component of the Viction World Wide Chain. This innovation promises to revolutionize the blockchain space by boosting scalability, flexibility, and interoperability, paving the way for Web3 builders to build blockchain applications primed for global uptake.

The seamless integration of Viction DA with other rollup stacks facilitates fluid data communications and transfers, boosting shared liquidity and empowering developers with the confidence to innovate within the Viction World Wide Chain network. This strong infrastructure not only propels the growth of the Viction World Wide Chain but also cultivates a dynamic ecosystem where developers can innovate confidently and users benefit from a broader range of secure, interconnected applications.


# Ecosystem

## **What are the incentives for partners and Dapp developers to build on Viction?**

Building on Viction isn't just about leveraging advanced blockchain technology—it's about thriving in a supportive and vibrant ecosystem. Here’s how we empower our partners and developers with our holistic support:

### The win-for-all technical core

* **Scalability and Performance:** Viction's technical infrastructure, powered by the Proof of Staked Vote (PoSV) mechanism, supports up to 150 masternodes, ensuring high throughput and reliable performance. This structure allows for a fair distribution of block rewards and a double-validation process that enhances the security and consistency of block production​&#x20;
* **Innovative Features and Integration Capabilities:** With cross-chain interoperability through the Viction World Wide Chain, developers can create more flexible and interconnected applications. This integration capability allows applications on Viction to seamlessly interact with other blockchains, expanding the potential use cases and user reach.
* **Zero Gas Fee Transactions:** A standout feature of Viction is the elimination of gas fees through the VRC25 token standard. This approach not only lowers the barrier for new users and developers but also significantly reduces the operational cost of running applications on the blockchain
* **Data Availability Powered by Viction DA:** This will support the scalability of the blockchain. By ensuring data is readily available and accessible, Viction helps maintain the efficiency and speed of transactions across the network, which is critical for applications that require high throughput and rapid processing times.
* **Security and Decentralization:** Viction prioritizes a secure and decentralized network. This focus not only enhances the safety of deployed applications but also aligns with the ethos of blockchain technology—promoting a decentralized and user-empowered framework.
* **Developer-Friendly Tools:** Viction provides a range of tools and resources that simplify the development process. From comprehensive documentation to active community support and developer incentives, Viction aims to lower the barrier to entry for new developers and support the ongoing projects of experienced developers.
* **Supportive Community and Ecosystem:** The Viction community offers a supportive network for developers, including forums, technical support, and regular updates. This community-driven approach helps foster innovation and collaboration among developers, enhancing the overall ecosystem.

### Network opportunity

Viction receives support from the Ninety Eight Ecosystem, as well as numerous close\
partners and projects.

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

### Marketing Amplification

Visibility is vital in the crowded blockchain space. That’s why we support you to amplify your project through our dynamic marketing channels. Whether it’s spotlighting your work on our influential social media platforms, or featuring you in our widely-read community updates,  we're passionate about telling your story, highlighting your progress, and celebrating your milestones as part of the broader Viction journey.

Also, our marketing grants are crafted to maximize your visibility and impact:

* **Marketing Grants on Quest Platform**
* **Influencer Outreach**
* **Coin98 Network support**

Besides, communication is the cornerstone of collaboration. Viction provides unparalleled access to communication channels that connect you with a global audience.

### Financial Empowerment

At Viction, we believe in nurturing potential and fueling innovation. That's why we offer diversified financial incentives, including development grants and funding to reduce barriers and foster innovation across our platform.

* **Milestone-Based and KPI-Based Grants:** We support your journey through targeted grants that reward achieving specific milestones and KPIs, such as user acquisition. These grants are renewable, ensuring continued support as you meet new milestones.
* **Lifetime Gas Grants:** For ecosystem projects applying our VRC25 token standard, we provide lifetime gas grants to eliminate the cost barriers associated with transaction fees, allowing you to scale smoothly and efficiently.
* **Pitching Opportunities:** Gain exclusive access to pitch your project to Arche Fund (Ventures) and Kompass (Accelerator program) within the Ninety Eight Ecosystem, opening doors to potential investment and accelerated growth.

At Viction, your journey is supported every step of the way—from inception to launch and beyond. We're more than a platform; we're your partner in the blockchain space. Ready to start building? Connect with us at[ ](https://viction.xyz/)**<hi@viction.xyz>** and join a community where innovation meets opportunity.

## **Where can I check the actual product ecosystem and partnerships?**

All partnership and ecosystem announcements can be found on[ ](https://medium.com/Viction)our [blog](https://blog.viction.xyz/) and our official [Twitter account ](https://twitter.com/BuildOnViction)for partnership announcements.

Follow us on [Viction Announcement Channel](https://t.me/buildonviction) | [Twitter](https://twitter.com/BuildOnViction) |[ ](https://www.linkedin.com/company/Viction/?source=post_page---------------------------)[LinkedIn](https://www.linkedin.com/company/buildonviction/) |[ Github](https://github.com/BuildOnViction?source=post_page---------------------------) | [Discord](http://viction.link/discord)


# VIC - Economics

### **What is VIC? Can you describe the functions and purposes of VIC?**

VIC is the native cryptocurrency of Viction and will be the reserve cryptocurrency for all third-party apps running on Viction. Being the protocol token for the Viction infrastructure, VIC will be needed by all parties utilising Viction to build apps or issue and integrate cryptographic tokens into their apps.

The supply of VIC is fixed, long-term and non-inflationary.

In addition to the above, VIC is an integral part of the Viction network for a number of reasons.

* VIC will be used to fund the development of Viction and its ecosystem (VicScan, VicMaster, Vic Wallet, etc.).
* VIC will be used as a reward to incentivise the building of the Viction engine/ecosystem.
* VIC will be used as a long-term, decentralized governance instrument of the Viction network.

You can check our [technical whitepaper](https://docs.viction.xyz/whitepaper-and-research) for more details.

### **Can I mine VIC?**

VIC is not `mineable` but `mintable` by Masternodes. Masternodes are responsible for creating, verifying and finalizing the blocks created within a period, called an epoch. Masternodes and Stakers will receive block rewards.

### **What is the VIC circulating supply and total supply?**

The initial circulating supply at the genesis block was 55,000,000 but the current circulating supply is increasing every epoch.

After 8 years, VIC total supply is fixed at 100,000,000 VIC.

### **How is VIC distributed?**

The token allocation is split as follows:

* 55 millions VIC was already allocated after the token sale period;
* 12 millions VIC are reserved for the team vested over 4 years;
* 16 millions VIC are reserved for strategic partners and an ecosystem building fund;
* 17 millions VIC are reserved as block rewards for 8 years

### **How are block rewards distributed?**

17 millions VIC are reserved as block rewards with a halving schedule over 8 years.

* 1st and 2nd year: 4 million VIC annually
* 3rd, 4th and 5th year: 2 million VIC annually
* 6th, 7th and 8th year: 1 million VIC annually

**Will Viction have inflation?**

The total supply is fixed at 100 million VIC in the first 8 years (non-inflationary). 17 million VIC which are reserved as block rewards will have been all distributed after 8 years. At that time, we are expecting that block rewards will come from the exchange fees. But the Masternode Council can decide to increase the total supply by 0.5-1 million VIC per year (which will be used as block rewards) (\~small inflation, 0.5%-1% annually).

**How often are block rewards paid out?**

Block rewards will be awarded every epoch, which lasts for 900 blocks at roughly a two-second-block time rate (\~30 minutes). Both Masternode operators and Stakers will be rewarded.

**If Viction has near zero fees, how can Masternodes get rewards?**

The block rewards will be emitted from a reserved fund of 17 million VIC for the first 8 years. The block rewards are as follows:

* 1st and 2nd year: 4 million VIC annually
* 3rd, 4th and 5th year: 2 million VIC annually
* 6th, 7th and 8th year: 1 million VIC annually

We plan to have a built-in DEX, the revenues from the DEX will go to the Masternodes as well.

After 8 years, the block rewards will come from exchange fees. Also, the Masternode Council can decide to increase the total supply by 0.5-1 million VIC per year (which will be used as block rewards).

### **What was the price in presale and ICO?**

Presale Price: `$0.20`

ICO Price: `$0.25` (`0.0003125 ETH`)

### **Is VIC an ERC-20 token?**

No. Since Mainnet, VIC has become the native coin of the Viction blockchain.

**Where can I store VIC? How can I send VIC to my wallet?**

You can store VIC in Viction Wallet, TrustWallet, MetaMask, MyEtherWallet, Ledger and Trezor and more wallets

We recommend to store VIC in Viction Wallet.

Please, read more details [here](/viction-wallet)

### **How do I connect Metamask with Viction mainnet?**

The following is information used for configuring Metamask to connect to Viction Mainnet.

* RPC endpoint: `https://rpc.viction.xyz`
* Chain ID: `88`
* Symbol: `VIC`
* Network Name: `Viction Mainnet`

If you're unable to add the Viction Mainnet using the previous instructions, you can try an alternative method by connecting through <https://chainlist.org/?search=viction>.

You can find the info about our Mainnet or Testnet [here](/archive/deploy-on-viction).&#x20;

Also, you can find out more detailed information about how to use different wallet types to connect to Viction Mainnet on [Connect your wallet](/how-to/how-to-connect-to-viction-network)

### **Where can I buy VIC?**

You can trade VIC on various exchanges. Please refer to the information below:

| Exchanges                  | Trading Pair                                                                                   |
| -------------------------- | ---------------------------------------------------------------------------------------------- |
| Binance                    | [VIC/USDT](https://www.binance.com/en/trade/VIC_USDT)                                          |
| Binance                    | [VIC/BTC](https://www.binance.com/en/trade/VIC_BTC)                                            |
| HTX                        | [VIC/USDT](https://www.huobi.com/en-us/exchange/vic_usdt)                                      |
| Biconomy                   | [VIC/USDT](https://www.biconomy.com/exchange/VIC_USDT)                                         |
| MEXC                       | [VIC/USDT](https://www.mexc.com/exchange/VIC_USDT)                                             |
| BingX                      | [VIC/USDT](https://bingx.com/en-us/spot/VICUSDT?ch=cgk_organic)                                |
| Bitget                     | [VIC/USDT](https://www.bitget.com/spot/VICUSDT?channelCode=42xn\&vipCode=sq59\&languageType=0) |
| BTSE                       | [VIC/USDT](https://www.btse.com/en/trading/VIC-USDT)                                           |
| [Gate.io](http://gate.io/) | [VIC/USDT](https://gate.io/trade/VIC_USDT)                                                     |
| Bitmart                    | [VIC/USDT](https://www.bitmart.com/trade/en?symbol=$VIC_USDT\&r=PjkAFy)                        |
| Bybit                      | [VIC/USDT](https://www.bybit.com/trade/spot/VIC/USDT/)                                         |
| StealthEX                  | [VIC/USDT](https://stealthex.io/exchange/new/)                                                 |
| Aliniex                    | [VIC/VND](https://aliniex.com/mua-ban/vic)                                                     |
| Giottus                    | [VIC/USDT](https://www.giottus.com/)                                                           |
| Lbank                      | [VIC/USDT](https://www.lbank.com/trade/viction_usdt)                                           |
| SimpleSwap                 | [VIC/USDT](https://simpleswap.io/)                                                             |


# Contact & Support

### **Where can I take a look at Viction code? Is there a GitHub repository?**

All the code regarding Viction is free to access on our [GitHub](https://github.com/BuildOnViction). This includes the code for the Viction blockchain client, governance Dapp, block explorer, tools, docker images, documentation, etc.

We like to publish code publicly when it reaches a certain level of development and/or when we think auditing and contributions are beneficial to the codebase. Keeping early projects private is probably more responsible for now due to our scale. It might change in the future.

We are also working with some third parties with which we signed a non-disclosure-agreements for code development.

### **Where can I contact you to get support?**

If you need support, please contact us on one of these platforms:

* Bugs or technical contributions: [GitHub (https://github.com/BuildOnViction)](https://github.com/BuildOnViction)
* General discussion regarding our blockchain: [Discord (viction.link/discord)](https://viction.link/discord)

### **Which are Viction's official channels for communication and information?**

You can keep in touch with our latest news here:

1. Twitter: [https://twitter.com/BuildOnViction ](<https://twitter.com/BuildOnViction >)
2. Telegram Announcements: [https://t.me/buildonviction ](<https://t.me/buildonviction >)
3. Blog: [https://blog.viction.xyz/ ](<https://blog.viction.xyz/ >)
4. Website: [https://viction.xyz](https://viction.xyz/)
5. LinkedIn: [https://www.linkedin.com/company/buildonviction/ ](<https://www.linkedin.com/company/buildonviction/ >)


# Masternodes and Voting

{% content-ref url="/pages/09lazRAlNRLGB4luS5Q6" %}
[Masternodes](/faq/masternode-and-voting/masternode)
{% endcontent-ref %}

{% content-ref url="/pages/TGRUPromc7V1D2ROFdHZ" %}
[Voter](/faq/masternode-and-voting/voter)
{% endcontent-ref %}




---

[Next Page](/llms-full.txt/1)

