Builder Guide

Gas

Gas Token

DuckChain uses native TON as its gas token for transaction costs. TON on DuckChain has 18 decimals, different from the 9-decimal precision on The Open Network to align with EVM-compatible chains' standards.

How to Get Gas Token

Gas Price

The minimum allowable Gas Price for nodes on DuckChain is 0.1 Gwei(Testnet)/10 Gwei(Mainnet). Transactions with gas prices below this threshold will be automatically rejected.

Developer Tools

EVM Wallet

DuckChain is EVM compatible. You can connect to DuckChain using familiar EVM wallets like MetaMask.

MetaMask Setup

  1. Open the MetaMask browser extension.

  2. Click the network selection dropdown.

  3. Select "Add Network Manually."

  4. Enter the DuckChain network details.

Deploying Smart Contracts

Using Hardhat

Guide on deploying a smart contract on DuckChain using Hardhat, a popular framework for deploying and verifying smart contracts.

Initial Setup:

  1. Get some test TON from the DuckChain testnet faucet.

  2. Install Hardhat and its dependencies:

    Copy

    npm install --save-dev ethers hardhat @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers dotenv
  3. Initialize the project:

    Copy

    npx hardhat init
  4. Open hardhat.config.js and add the following:

    Copy

    require("dotenv").config();
    require("@nomicfoundation/hardhat-toolbox");
    
    module.exports = {
      solidity: "0.8.9",
      paths: {
        artifacts: "./src",
      },
      networks: {
        DuckChainTestnet: {
          url: `https://testnet-rpc.duckchain.io`,
          accounts: [process.env.ACCOUNT_PRIVATE_KEY],
        },
      },
    };

Add Contract Code and Deployment Script

  1. Create Storage.sol in the contracts folder with the following code:

    Copy

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.9;
    
    contract Storage {
        uint256 _count = 0;
    
        function set(uint256 count) public {
            _count = count;
        }
    
        function get() public view returns (uint256){
            return _count;
        }
    }
  2. Create a deployment script deploy-storage.js:

    Copy

    const hre = require("hardhat");
    
    async function main() {
        const deployedContract = await hre.ethers.deployContract("Storage");
        await deployedContract.waitForDeployment();
        console.log(
            `Storage contract deployed to https://testnet-scan.duckchain.io/address/${deployedContract.target}`
        );
    }
    
    main().catch((error) => {
        console.error(error);
        process.exitCode = 1;
    });
  3. Install Hardhat toolbox if not already installed:

    Copy

    npm install --save-dev @nomicfoundation/hardhat-toolbox
  4. Compile and deploy the contract:

    Copy

    npx hardhat compile
    npx hardhat run scripts/deploy-storage.js --network DuckChainTestnet

Using Foundry

Setting up the environment

Foundry is a smart contract development toolchain. It can be used to manage dependencies, compile a project, run tests and deploy smart contracts. It also lets one interact with blockchain from the CLI or via Solidity scripts.

Install Foundry

If you have not installed Foundry, go to book.getfoundry and select Installation from the side menu. Follow the instructions to download Using Foundryup.

Next, select Creating a New Project from the sidebar. Initialize and give your new project a name: forge init zkevm-sbtIn case of a library not loaded error, you should run the below command and then repeat the above process again:

Copy

brew install libusb

If you have never installed Rust or need an update, visit the website here.

Build a project and test

Run the command forge build to build the project. The output should look something like this:Successful forge build commandNow, test the build with forge testTesting Forge BuildYou can check out the contents of the newly built project by switching to your IDE. In case of VSCode, just type: code .

Writing the smart contract

  1. Find the OpenZeppelin Wizard in your browser, and use the wizard to create an out-of-the-box NFT contract.

    1. Select the ERC721 tab for an NFT smart contract.

    2. Name the NFT and give it an appropriate symbol. Example: Name SoEarly and Symbol SOE.

    3. Go ahead and select features for your token. Simply tick the relevant boxes.

    4. You can tick the URI Storage box if you wish to attach some image or special text to the token.

  2. Open your CLI and install dependencies with this command:

  3. Copy

Copy

npm install @openzeppelin/contracts-upgradeable
  1. Remap dependencies to easy-to-read filenames with the command:

  2. Copy

Copy

forge remappings > remappings.txt
  1. Inside the new remapping.txt file, rename the referencing openzeppelin-contracts to openzeppelin, which is the name used when importing. That is, change openzeppelin-contracts/=lib/openzeppelin-contractsopenzeppelin/=lib/openzeppelin-contracts.

  2. Copy the smart contract code in OpenZeppelin: Copy to Clipboard

  3. In the IDE, open a new .sol file, name it and paste the copied code to this file. This is in fact the actual smart contract for the NFT.

Add control on token transfers

The aim here is to put rules in place stipulating that the token cannot be transferred without burning it.

  • Look up the signature by searching for _beforetokentransfererc721.

  • Scroll down to ERC 721 and copy the corresponding text on the right side:

  • Copy

Copy

_beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal
  • Create a new function in the code for the smart contract token called _beforeTokenTransfer

  • Copy

Copy

function _beforeTokenTransfer (address from, address to, uint256 firstTokenId, uint256 batchSize) internal override {
    require(from==address(0) || to==address(0), "Soulbound: cannot transfer");
    super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
}

Set a token URI (optional)

A token URI is a function that returns the address where the metadata of a specific token is stored. The metadata is a . json file where all the data associated with the NFT is stored. Our aim here is to attach some images to the created token.The stored data typically consists of the name of the token, brief description and URL where the image is stored.

  • Choose an image and give it a name relatable to the token

  • Find some free of charge IPFS storage for the image, like NFT.STORAGE

  • Upload the image to the storage using your GitHub account

Add URI json file

This is the file that contains the metadata for the token which includes the image address (i.e., the IPFS address of the image).

  • In the IDE, create a new .json file which you can call tokenuri.json

  • Populate the tokenuri.json file with the token-name, description and URL where the image is stored:

  • Copy

Copy

{
    "title": "So Early",
    "description": "I was super duper early to the Duck Chain",
    "image": "<IPFS address>" /* remove the forward-slash at the end of the URL, if any */
}
  • Upload the tokenuri.json file to the same storage where the image was uploaded

  • Copy the address to the Sbt.sol inside the safeMint function

  • Remove the uri parameter so as to hardcode it. This makes all tokens have the same uri image, but every consecutively minted pair of tokens will differ by 1 in numerical value of their tokenId.

Populate the .env file

In order to deploy on the DuckChain Testnet, populate the .env file in the usual way. That is,

  • Create a .env.sample file within the src folder

  • Populate .env.sample file with your ACCOUNT_PRIVATE_KEY and the DuckChain Testnet’s RPC URL found here. So the .env.sample file will look like this:

  • Copy

Copy

RPC_URL="https://testnet-rpc.duckchain.io"
PVTKEY="<insert private key here>"
  • Copy the contents of the .env.sample file to the .env file,

  • Copy

Copy

cp .env.sample .env

Warning

Make sure .env is in the .gitignore file to avoid uploading your ACCOUNT_PRIVATE_KEY.

Deploy your contract

  1. In the CLI, use the following command to ensure grabbing variables from .env:

  2. Copy

Copy

source .env
  1. Check if the correct RPC URL is read from the .env file:

  2. Copy

Copy

echo $RPC_URL
  1. You can now use the next command:

  2. Copy

Copy

forge create --rpc-url $RPC_URL --private-key $PRIVATE_KEY src/{ContractFile.sol}:{ContractName} --legacy
  1. which executes the following:

    1. Does a forge create.

    2. Passes the RPC_URL and PVTKEY.

    3. References the actual smart contract.

  2. For example, when deploying the Sbt.sol contract, the command will look like this:

  3. Copy

Copy

forge create --rpc-url $RPC_URL --private-key $PRIVATE_KEY src/Sbt.sol:SoEarly --legacy

The above command compiles and deploys the contract to the DuckChain Testnet. The output on the CLI looks like this one below.Successful Deploy Sbt.sol

Check deployed contract in explorer

  • Copy the address of your newly deployed contract (i.e. the Deployed to: address as in the above example output).

  • Go to DuckChain Testnet Explorer, and paste the address in the Search by address field.

  • Check Transaction Details reflecting the From address, which is the owner’s address and the To address, which is the same Deployed to: address seen in the CLI.

Run a DuckChain Node

Prerequisites

Minimum hardware requirements:

  • RAM: 16 GB

  • CPU: 8 core

  • Storage: 1T for pruned nodes, 2T for archived nodes

Dependencies

  • docker version 27+

  • docker-compose v2.15.0+

Online Installation

To install a DuckChain node:

Copy

wget -c https://download.duckchain.io/duckchain/install.sh && chmod +x ./install.sh && ./install.sh

Select the Corresponding Network:

  1. DuckChain Mainnet

  2. DuckChain Testnet

Choose the appropriate index when prompted.

Enter index: 1

Last updated