id | title | keywords | description | |||||
---|---|---|---|---|---|---|---|---|
flatten-contract-truffle |
Flatten a Smart Contract Using Truffle |
|
Use Truffle to deploy and verify smart contract |
- π§ Table of contents
- π° Overview
- π Setting up the development environment
- π΅ Writing Smart Contract
- π Veryfing Contracts on the Block Explorer
Truffle is a blockchain development environment, which you can use to create and test smart contracts by levering an Ethereum Virtual Machine.
In this tutorial, you will learn how to set up Truffle and use it to build, test and deploy smart contract on both the XDC Network mainnet and XDC Apothem testnet and verify it on Block Explorer.
- Install and set up Truffle
- Create a complex smart contract with dependencies (like OpenZeppelin)
- Compile the smart contract
- Test the smart contract
- Deploy the smart contract
- Flatten the smart contract
- Verify the smart contract
There are a few technical requirements before we start. Please install the following:
- Node.js v8+ LTS and npm (comes with Node)
- Git
Once we have those installed, we only need one command to install Truffle:
npm install -g truffle
To verify that Truffle is installed properly, type truffle version
on a terminal. You should see something like:
Truffle v5.5.27 (core: 5.5.27)
Ganache v7.4.0
Solidity v0.5.16 (solc-js)
Node v16.16.0
Web3.js v1.7.4
If you see an error instead, make sure that your npm modules are added to your path.
Lets start by setting up our folder, we are creating a project called MyCounter
, create a new MyCounter
folder by running on terminal
mkdir MyCounter && cd MyCounter
And running truffle init
. If truffle is correctly installed on your local environment, you should see the following message:
Starting init...
================
> Copying project files to /home/your/path/to/MyCounter
Init successful, sweet!
Try our scaffold commands to get started:
$ truffle create contract YourContractName # scaffold a contract
$ truffle create test YourTestName # scaffold a test
http://trufflesuite.com/docs
And your folder files will look like this:
In order to get started deploying new contracts on XDC Mainnet and/or Apothem, we need to install two new dependencies that will be used in the truffle-config.js
file. These dependencies are @truffle/hdwallet-provider
and dotenv
. First choose your preferred package manager. In this example we are using yarn
but you can also use npm
.
If you never used yarn
before, you might need to install it first.
npm install --global yarn
Initialize your package manager on your folder and install the required dependencies:
yarn init -y
yarn add @truffle/hdwallet-provider dotenv
You will also need a 24-Word Mnemonic Phrase. To configure your wallet, create a new .env
file and write your mnemonic by running:
touch .env
echo MNEMONIC=arm derive cupboard decade course garlic journey blast tribe describe curve obey >> .env
Remember to change the 24-Word Mnemonic above for your own mnemonic. The contents of your .env
file should read as follow:
MNEMONIC=arm derive cupboard decade course garlic journey blast tribe describe curve obey
π¨ Do not use the mnemonic in the example above in production or you can risk losing your assets and/or the ownership of your smart contracts! π¨
And finally, we can configure the truffle-config.js
file for both Apothem and XinFin Networks by writting:
require('dotenv').config();
const { MNEMONIC } = process.env;
const HDWalletProvider = require('@truffle/hdwallet-provider');
module.exports = {
networks: {
xinfin: {
provider: () => new HDWalletProvider(
MNEMONIC,
'https://erpc.xinfin.network'),
network_id: 50,
gasLimit: 6721975,
confirmation: 2,
},
apothem: {
provider: () => new HDWalletProvider(
MNEMONIC,
'https://erpc.apothem.network'),
network_id: 51,
gasLimit: 6721975,
confirmation: 2,
}
},
mocha: {
},
compilers: {
solc: {
version: "0.8.16",
}
},
};
It is possible to list all XDC addresses bound to your mnemonic on truffle by accessing the truffle console:
truffle console --network xinfin
Once the truffle console CLI opens, you can run:
truffle(xinfin)> accounts
And the console should log all accounts bound to your mnemonic phrase as follow:
[
'0xA4e66f4Cc17752f331eaC6A20C00756156719519',
'0x0431d52FE37F3839895018272dfa3bA189fcE07E',
'0x11A6D9727c16064950473a4c8A92dC294190f7fF',
'0x4464DDF9969E9a8e5CfF02E3706AEB4ccA92A314',
'0xFa73bE6AA126DEC47ce14a22B7BAaF8BAFaB59Fb',
'0xEdFFc4e7476f05f43cA3e6f5784349dE6E6373D5',
'0x07795c732Bb013165FADCE64B884bf9971Bf9636',
'0x5dF551A53bEaAB8bb2307eF459aA5AAFbb5F73cc',
'0x910435b01e6Aa66dE22769062998F6AE98566f23',
'0x573b009b2dE9A95531f82DA10BB0D793050329d2'
]
These accounts are on the Ethereum standard format starting with 0x
, but we can simply switch 0x
for xdc
. By default, the deployment account is the first account from the list above: xdcA4e66f4Cc17752f331eaC6A20C00756156719519
.
With this account in hand, we can head to the Apothem Faucet and claim some TXDC for development purposes:
We will be using OpenZeppelin for this guide so lets install it first:
yarn add @openzeppelin/contracts
or using npm
npm install @openzeppelin/contracts
Now lets create simple smart contract called MyCounter.sol
in contracts
folder:
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "@openzeppelin/contracts/utils/Counters.sol";
contract MyCounter {
using Counters for Counters.Counter;
Counters.Counter private _counter;
function current() public view returns (uint256) {
return _counter.current();
}
function increment() public returns (uint256) {
_counter.increment();
return _counter.current();
}
function decrement() public returns (uint256) {
_counter.decrement();
return _counter.current();
}
}
We can compile our MyCounter.sol
by running:
truffle compile
If everything is correctly configured and there is no errors, you should see the following message on your console:
Compiling your contracts...
===========================
> Compiling ./contracts/MyCounter.sol
> Compiling @openzeppelin/contracts/utils/Counters.sol
> Artifacts written to /home/your/path/to/build/contracts
> Compiled successfully using:
- solc: 0.8.16+commit.07a7930e.Emscripten.clang
And your folder should look like this:
Now lets create a simple test to see everything works as intended before we deploy our contract to live network. This will save us time and gas fees, so it is recommended you do as much as possible tests for your smart contracts before deploying.
Create file MyCounter.js
under test
directory:
const MyCounter = artifacts.require("MyCounter");
contract("MyCounter", (accounts) => {
it("should deploy MyCounter", async () => {
const myCounterInstance = await MyCounter.deployed();
const current = await myCounterInstance.current();
assert.equal(current.valueOf(), 0, "0 is not the current count");
});
it("should increment and decrement MyCounter and show current count", async () => {
const myCounterInstance = await MyCounter.deployed();
await myCounterInstance.increment()
await myCounterInstance.increment()
await myCounterInstance.decrement()
const current = await myCounterInstance.current();
assert.equal(
current.valueOf(),
1,
"1 is not the current count"
);
});
});
Then run
truffle test
Your output should look like this:
Contract: MyCounter
β should deploy MyCounter
β should increment and decrement MyCounter and show current count (131ms)
2 passing (197ms)
In order to deploy our newly compiled contract artifacts to the blockchain, we need to create a deployment script into the migrations folder:
touch ./migrations/1_token_migration.js
And write the following migration script to the 1_token_migration.js
file:
const MyCounter = artifacts.require("MyCounter");
module.exports = function (deployer) {
deployer.deploy(MyCounter);
}
If the migration script have no errors, we can go ahead and run the command:
truffle migrate --network xinfin
For deployment on XDC mainet, or:
truffle migrate --network apothem
For deployment on the XDC Apothem Testnet. In either case, you need to have enough funds to pay for gas fees on the address that is being used for development.
If the deployment is sucessful, the console should log the following message after migrations complete processing:
1_counter_migration.js
======================
Deploying 'MyCounter'
---------------------
> transaction hash: 0x128fdda5a1897e373259bd0a614f4b72c6d1f397696a7df4ddc55a863fb75620
> Blocks: 0 Seconds: 0
> contract address: 0x11d73188a9976FB32B53FFD7040030e0667CeBFa
> block number: 9
> block timestamp: 1665052811
> account: 0x7EF6aCFd4F0B8B6828Bf25D440Bf46f1Eb28c6A6
> balance: 99.92708386
> gas used: 164965 (0x28465)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.0032993 ETH
> Saving artifacts
-------------------------------------
> Total cost: 0.0032993 ETH
Summary
=======
> Total deployments: 1
> Final cost: 0.0032993 ETH
If smart contract imports external files like our, we need to flatten it before verifying on Block Explorer.
For that, install truffle-flattener
.
yarn add truffle-flattener -g
Or using npm
npm install truffle-flattener -g
Now lets flatten our contract:
truffle-flattener contracts/MyCounter.sol > MyCounterFlatten.sol
Then open MyCounterFlatten.sol
and remove every line which starts with // SPDX-License-Identifier
except the first one. We do this because Block Explorer does not accepts contracts with mutliple license definition.
Once you have successfully deployed your smart contract to the blockchain, it might be interesting to verify you contract on XinFin Block Explorer.
First lets check the address our contract is deployed to by running:
truffle networks
If you have a contract already deployed, the console should log something like this:
Network: apothem (id: 51)
No contracts deployed.
Network: xinfin (id: 50)
MyCounter: 0x53bA8Cb12EaF09E6B0b671F39ac4798A6DA7d660
Here we have a MyCounter
contract deployed on XDC Mainnet at the 0x53bA8Cb12EaF09E6B0b671F39ac4798A6DA7d660
. This address is in the Ethereum standard but we can simply swap the 0x
prefix for xdc
and search for our newly deployed contract on XinFin Block Explorer:
And click in the Verify And Publish
Option.
We will be redirected to the Contract verification page where we need to fill out:
- Contract Name: MyCounter
- Compiler: Check your
truffle-config.js
file for Compiler Version - Contract Code: Just paste everything from your
MyCounterFlatten.sol
file
β Keep in mind that Contract Code
should be MyCounterFlatten.sol
, not MyCounter.sol
. β
Once everything is filled out, press Submit!
If everything is correctly filled out, your contract page on the block explorer should display a new tab called Contract
:
For more information about Truffle Suite, Please Visit Truffle Suite Documentation.
For more information about XinFin Network, Please Visit XDC Network Documentation on GitBook.
Resources used during the deployment of the MyCounter can be found at MyCounter Contract Folder.