Using Truffle with Quai Network

Introduction

Truffle suite is a powerful tool built for testing and deploying smart contracts, which can be utilized on any of Quai Network's thirteen chains. Using Truffle you can compile smart contracts, build artifacts, run migrations and interact with deployed contracts using a custom inbuilt console.

Requirements

  • Have a Quai Full Node running.
  • Have the Quai Manager running if you are testing locally.
  • Sufficient balance in the address that you are deploying with.

Dependencies

  • NodeJS v8.9.4 or later.
  • Truffle Development Suite
  • Running Node

Create a truffle directory and install dependencies

1.) Install Truffle Suite
1
npm install -g truffle
Copied!
2.) Create a new truffle directory and navigate there
1
cd path/to/directory
Copied!
3.) Install required dependencies
1
npm install web3
2
npm install @truffle/hdwallet-provider
Copied!
4.) Initialize Truffle
1
truffle init
Copied!

List of HTTP Port, Network Id for each chain

Chain
HTTP Port
Network ID (Mainnet)
Network ID (Testnet)
Prime
8546
9000
12000
Cyprus
8578
9100
12100
Paxos
8580
9200
12200
Hydra
8582
9300
12300
Cyprus1
8610
9101
12101
Cyprus2
8642
9102
12102
Cyprus3
8674
9103
12103
Paxos1
8612
9201
12201
Paxos2
8644
9202
12202
Paxos3
8676
9203
12203
Hydra1
8614
9301
12301
Hydra2
8646
9302
12302
Hydra3
8678
9303
12303

Update truffle-config.js

One of the files created upon running truffle init is truffle-config.js. Paste the code below into truffle-config.js. The port and network_Id information can be found in the table above for each chain in Quai Network.
truffle-config.js
1
var PrivateKeyProvider = require("@truffle/hdwallet-provider");
2
3
var privateKey = "insert private key here"; // private key of the account being used to deploy contract, must be valid address in deployment chain
4
var protocol = "https" // http or https
5
var port = 8610 // Cyprus1 http port
6
7
module.exports = {
8
networks: {
9
quaitestnet: {
10
provider: () => new PrivateKeyProvider(privateKey, `${protocol}://cyprus1.rpc.quaiscan.io`),
11
network_id: 9101, // Set to valid mainnet network id, more info can be found at (https://docs.quai.network/build/truffle)
12
gas: 500000, // Arbitrary gas limit. Gas limits change, so make sure to update this based on the gas limit for the chain you are deploying to
13
from: "0x...", // Valid mainnet account to send txs from
14
websocket: true
15
},
16
17
ropsten: {
18
provider: () => new PrivateKeyProvider(privateKey, `${protocol}://127.0.0.1:${port}`),
19
network_id: 12101, // Set to valid ropsten testnet network id, more info can be found at (https://docs.quai.network/build/truffle)
20
gas: 749800, // Arbitrary gas limit. Gas limits change, so make sure to update this based on the gas limit for the chain you are deploying to
21
from: "0x...", // Valid ropsten account to send txs from
22
websocket: true
23
},
24
},
25
compilers: {
26
solc: {
27
version: "0.8.0", // Set version of solc to use based on your smart contract's version
28
}
29
},
30
31
// Set default mocha options here, use special reporters etc.
32
mocha: {
33
// timeout: 100000
34
},
35
};
36
Copied!
The changes that must to be made to truffle-config.js are as follows:
  • To decrypt your private key from the Keystore, create a new javascript file and copy the content below. Provide your keystore and provider_url.Run the script using node getPrivateKey.js.
getPrivateKey.js
1
async function main() {
2
// keystore - Paste the keystore associated with the account below
3
var keystore = ''
4
5
// provider_url - URL to the node in which you want to deploy along with the right port associated
6
var provider_url = "" // For Ex: http://localhost:8610 for a local cyprus1 node
7
8
var Web3 = require("@quainetwork/web3");
9
var web3 = new Web3(provider_url);
10
11
const PRIVATE_KEY = web3.eth.accounts.decrypt(keystore, "").privateKey;
12
console.log("Private Key", PRIVATE_KEY);
13
}
14
main();
Copied!
  • Once you have your private key and address, update the truffle-config.js. Note that you can change the protocol, host, port, address, privateKey, gas and network_id variables.

Add a simple Smart Contract inside the contracts folder

MyStatus.sol is a smart contract that stores a status. Status is initialized to be "Busy" below.
MyStatus.sol
1
// SPDX-License-Identifier: Apache-2.0
2
pragma solidity >0.5.0;
3
4
contract MyStatus {
5
string status;
6
7
constructor() public {
8
status = "Busy";
9
}
10
11
function getStatus() external view returns (string memory) {
12
return status;
13
}
14
15
function setStatus(string calldata _status) external {
16
status = _status;
17
}
18
}
Copied!

Add new migration

Create a new file in the migrations directory named, 2_deploy_contracts.js, and add the following block of code. This handles deploying the MyStatus smart contract to the blockchain.
2_deploy_contracts.js
1
const MyStatus = artifacts.require("./MyStatus.sol");
2
3
module.exports = function (deployer) {
4
deployer.deploy(MyStatus);
5
};
Copied!

Compile the Contract with Truffle

1
truffle compile
Copied!
You should see the successful compilation
1
Compiling your contracts...
2
===========================
3
> Compiling ./contracts/Mystatus.sol
4
> Artifacts written to /path/to/build/contracts
5
> Compiled successfully using:
6
- solc: 0.5.16+commit.9c3226ce.Emscripten.clang
Copied!

Migrate and Deploy the Contract

In truffle-config.js, we specified two networks: quaitestnet and ropsten. quaitestnet deploys to the live chain, and ropsten deploys to a Localhost. Below, we'll deploy to the live chain using the --network quaitestnet flag.
1
truffle migrate --network quaitestnet
Copied!
Truffle should output this after the successful deployment:
1
Compiling your contracts...
2
===========================
3
> Everything is up to date, there is nothing to compile.
4
5
6
7
Starting migrations...
8
======================
9
> Network name: 'quaitestnet'
10
> Network id: 12101
11
> Block gas limit: 4990346 (0x4c258a)
12
13
14
2_deploy_contracts.js
15
=====================
16
17
Deploying 'MyStatus'
18
--------------------
19
> transaction hash: 0x5b68feffceb0bf4a820eab7e4638bbadc4c58ccebe5168eaa99855fde9410f08
20
> Blocks: 0 Seconds: 0
21
> contract address: 0x76C3a4c3A6e2523c62E01163b19B14cF90a1A84c
22
> block number: 3401
23
> block timestamp: 1648346192
24
> account: 0x1930E0b28D3766e895dF661de871A9b8aB70a4da
25
> balance: 6.29814814814605221
26
> gas used: 233060 (0x38e64)
27
> gas price: 2.500000001 gwei
28
> value sent: 0 ETH
29
> total cost: 0.00058265000023306 ETH
30
31
32
> Saving migration to chain.
33
> Saving artifacts
34
-------------------------------------
35
> Total cost: 0.00058265000023306 ETH
36
37
38
Summary
39
=======
40
> Total deployments: 1
41
> Final cost: 0.00058265000023306 ETH
Copied!

Interacting with your contract

The MyStatus contract is now deployed at the address above. You can now interact with the contract using the built-in truffle console.
The Truffle console can be spun using truffle console --network quaitestnet. The console is similar to the chain IPC consoles and supports all web3 functions.
Setting the contract status to "Free" can be done by:
1) Starting the truffle console:
1
truffle console --network quaitestnet
Copied!
2) Accessing the contract by the name:
1
truffle(quaitestnet)> let instance = await MyStatus.deployed()
Copied!
It should return:
1
undefined
Copied!
3) Setting the status to "Free":
1
truffle(quaitestnet)> instance.setStatus("Free")
Copied!
It should return:
1
{
2
tx: '0x7d824c725bf48b3e09a1292d30c45abe8b92016d4c7cfcc29812d629cc65c660',
3
receipt: {
4
blockHash: '0x1a753e031f917ee3d186ef8669210c62de9f068e7fc1870c2bd988e8425d0d05',
5
blockNumber: 3413,
6
contractAddress: null,
7
cumulativeGasUsed: 29491,
8
effectiveGasPrice: '0x9502f901',
9
from: '0x1930e0b28d3766e895df661de871a9b8ab70a4da',
10
gasUsed: 29491,
11
logs: [],
12
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
13
status: true,
14
to: '0x76c3a4c3a6e2523c62e01163b19b14cf90a1a84c',
15
transactionHash: '0x7d824c725bf48b3e09a1292d30c45abe8b92016d4c7cfcc29812d629cc65c660',
16
transactionIndex: 0,
17
type: '0x2',
18
rawLogs: []
19
},
20
logs: []
21
}
Copied!
4) Accessing the newly set status:
1
truffle(quaitestnet)> let status = await instance.getStatus()
Copied!
It should return:
1
undefined
Copied!
5) Print the status. It should return "Free" as the new status.
1
truffle(quaitestnet)> status
2
'Free'
Copied!

Summary

Now you have all the tools to compile, deploy, interact with a smart contract on any of Quai Network's thirteen chains.