U2U Network Documentations
  • Introduction
    • Our Vision
    • Litepaper
      • Overview
        • U2U Network Diagram
        • U2U Network with DEPIN and Web3 Eco System
      • Consensus
  • Services
    • RPC
      • RPC Endpoints
      • Ethereum API Methods
        • eth_blockNumber
        • eth_call
        • eth_chainId
        • eth_estimateGas
        • eth_feeHistory
        • eth_gasPrice
        • eth_getBalance
        • eth_getBlockByHash
        • eth_getBlockByNumber
        • eth_getBlockTransactionCountByHash
        • eth_getBlockTransactionCountByNumber
        • eth_getCode
        • eth_getLogs
        • eth_getProof
        • eth_getStorageAt
        • eth_getTransactionByBlockHashAndIndex
        • eth_getTransactionByBlockNumberAndIndex
        • eth_getTransactionByHash
        • eth_getTransactionCount
        • eth_getTransactionReceipt
        • eth_getUncleByBlockHashAndIndex
        • eth_getUncleByBlockNumberAndIndex
        • eth_getUncleCountByBlockHash
        • eth_getUncleCountByBlockNumber
        • eth_maxPriorityFeePerGas
        • eth_sendRawTransaction
        • eth_subscribe
        • eth_unsubscribe
        • net_version
        • net_listening
        • net_peerCount
        • web3_clientVersion
        • web3_sha3
        • debug_traceTransaction
      • DAG API Methods
        • dag_getEvent
        • dag_getEventPayload
        • dag_getHeads
        • eth_currentEpoch
      • Trace API Methods
        • trace_block
        • trace_get
        • trace_transaction
        • trace_filter
    • Explorer
      • Explorer URLs
      • Explorer API
        • Account
        • Block
        • Contract
        • Logs
        • Stats
        • Token
        • Transaction
      • GraphQL
      • Explorer RPC API
      • Smart Contract Verification
        • Via explorer
        • Via hardhat plugin
      • Testnet Faucet
    • Wallets
      • Metamask
      • Wallet Connect
      • Coinbase Wallet
      • U2U Super App
        • Policy
    • Staking
      • How To Stake?
      • FAQ
    • The Graph
      • Deploy a Graph Node
      • Deploy a Subgraph
    • Bridge
      • Smart Contracts & EOA
    • Oracle
      • Smart Contracts & EOA
  • Network
    • Node Types
    • Requirements
    • Build Dependencies
    • Run Normal Node
      • Mainnet Normal Node
      • Testnet Normal Node
      • Run via Docker
    • Run Validator Node
      • Mainnet Validator Node
      • Testnet Validator Node
    • Run A Local Test Network
    • Troubleshooting
  • SUBNET
    • Overview
    • Subnet Node Type
    • Requirements
    • NFT Digital License
    • Subnet Node Setup
      • Master Node
      • Verifier Node
      • Edge Node CLI
  • For Developers
    • SDK
    • Smart Contract Development
      • What are smart contracts?
      • What is gas?
      • Structure of a smart contract
      • Your first smart contract
      • Test your smart contract
      • Deploy your smart contract
      • Submit your contract to explorer
      • Interact With Your Smart Contract
      • Integrate Your Smart Contract With a Frontend
      • Additional Resources
    • Smart Contract Deployment
      • Deploy with Remix
      • Deploy with Hardhat
Powered by GitBook
On this page
  • Initialization
  • Write your first smart contract
  • What's next?
  1. For Developers
  2. Smart Contract Development

Your first smart contract

In this tutorial, you'll learn to create your first smart contract with Hardhat – a full-featured development environment for contract compilation, deployment and verification.

PreviousStructure of a smart contractNextTest your smart contract

Last updated 10 months ago

In this tutorial we'll guide you:

  • Setting up your Node.js environment for U2U smart contract development

  • Creating and configuring a Hardhat project

  • The basics of a Solidity smart contract that implements a time-locked wallet

  • Writing automated tests for your contract using Hardhat

  • ...

You should get familiar to:

  • Write code in Javascript

  • Operate a terminal

  • Use git

  • Understand the basics of how smart contracts work

Initialization

First, we’ll need to create a folder for our project. Navigate to your and type:

mkdir first-contract
cd first-contract

Create an empty Node.js project:

npm init -y

Add Hardhat as a dependency to the project:

npm install --save-dev hardhat

Then use Hardhat to initialize your project:

npx hardhat init

Then it will appear as follow, please select Create a Typescript project:

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.17.4 👷‍

? What do you want to do? … 
  Create a JavaScript project
❯ Create a TypeScript project
  Create an empty hardhat.config.js
  Quit

It will ask more questions, just follow them and finish setting up your sample project, below are example:

✔ What do you want to do? · Create a TypeScript project
✔ Hardhat project root: · /Users/steven/codekeeper/u2u/sample_project
✔ Do you want to add a .gitignore? (Y/n) · y
✔ Do you want to install this sample project's dependencies with npm (@nomicfoundation/hardhat-toolbox)? (Y/n) · y

Hardhat has scaffolded a project contains Lock contract. Our sample project should contain these folders and files:

contracts/
scripts/
test/
hardhat.config.ts

These are the default paths for a Hardhat project.

  • contracts/ is where the source files for your contracts should be.

  • test/ is where your tests should go.

  • scripts/ is where simple automation scripts go.

Write your first smart contract

Open up contracts folder, you'll see sample contract file Lock.sol that Hardhat has initialized:

contracts/
    Lock.sol

Now let's take a glance at Lock.sol:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

// Uncomment this line to use console.log
// import "hardhat/console.sol";

contract Lock {
    uint public unlockTime;
    address payable public owner;

    event Withdrawal(uint amount, uint when);

    constructor(uint _unlockTime) payable {
        require(
            block.timestamp < _unlockTime,
            "Unlock time should be in the future"
        );

        unlockTime = _unlockTime;
        owner = payable(msg.sender);
    }

    function withdraw() public {
        // Uncomment this line, and the import of "hardhat/console.sol", to print a log in your terminal
        // console.log("Unlock time is %o and block timestamp is %o", unlockTime, block.timestamp);

        require(block.timestamp >= unlockTime, "You can't withdraw yet");
        require(msg.sender == owner, "You aren't the owner");

        emit Withdrawal(address(this).balance, block.timestamp);

        owner.transfer(address(this).balance);
    }
}

This Solidity smart contract is called "Lock" and is designed to hold and manage funds until a specified unlock time has passed. Let's break down the key components and functionality of this contract:

  1. State Variables:

    • uint public unlockTime: This variable stores the timestamp when the contract will allow funds to be withdrawn. It's publicly accessible, so anyone can check when the funds will become available.

    • address payable public owner: This variable holds the Ethereum address of the owner of the contract, who has the authority to withdraw funds.

  2. Events:

    • event Withdrawal(uint amount, uint when): This event is emitted when a withdrawal is made. It logs the amount withdrawn and the timestamp at which the withdrawal occurred.

  3. Constructor:

    • constructor(uint _unlockTime) payable: This constructor is executed when the contract is deployed. It takes a single argument, _unlockTime, which represents the timestamp in the future when the funds can be withdrawn. The require statement ensures that the unlock time is indeed in the future. The msg.sender is set as the owner of the contract, and the constructor can receive an initial amount of Ether.

  4. Function - withdraw:

    • function withdraw() public: This function allows the owner to withdraw the funds held in the contract. It enforces the following conditions:

      • The current block timestamp (block.timestamp) must be greater than or equal to the unlockTime, ensuring that funds can only be withdrawn after the specified unlock time.

      • The sender (i.e., msg.sender) must be the owner of the contract.

    If these conditions are met, the function emits the Withdrawal event to log the withdrawal details, and it transfers the entire balance of the contract to the owner's address using owner.transfer(address(this).balance).

Additionally, there is a commented-out line (console.log) that can be used for debugging purposes when working with a development environment like Hardhat. It's used to print information to the console but is typically commented out in production code.

What's next?

Finally you have your own smart contract. The next step is to test it carefully before deploy it to blockchain. Please refer to next section at .

command line
Test your smart contract