What Is a Smart Contract?

A smart contract is a program stored on a blockchain that automatically executes predefined actions when certain conditions are fulfilled. Unlike traditional contracts, which rely on people or institutions to enforce them, a smart contract is self-enforcing — once it’s deployed, it runs exactly as programmed without human intervention.

Think of it as:

“If this happens, then do that” — enforced by code and trustless infrastructure.

Smart contracts are important because they eliminate the need for intermediaries, reduce the risk of fraud, and ensure agreements are executed exactly as written — with transparency and automation. This makes them a foundational building block for decentralized applications (dApps), enabling trustless interactions in finance, governance, identity, and beyond.

Analogy: A Digital Vending Machine

Imagine a vending machine:

  1. You insert $1 and select a soda.
  2. The machine checks your input.
  3. If the condition (enough money + valid selection) is true, it dispenses the soda.
  4. If not, it does nothing or gives your money back.

A smart contract works similarly:

  • Input: A user sends funds or data to the contract.
  • Condition: The contract checks the terms (e.g., “Has the payment been made?”).
  • Action: If conditions are met, it executes the logic (e.g., transfers ownership, sends tokens).

All of this happens automatically and irreversibly once deployed.

How It Works (Technically)

  • Written in code (like Solidity for Ethereum).
  • Deployed to a blockchain, where it gets an address.
  • Interacts with users or other contracts via transactions that other users send to its address.
  • Immutable: Once deployed, you can’t alter it (unless you build upgradeable patterns).
  • Transparent: Anyone can read the code and verify what it does.

Key Components of a Smart Contract

Let’s break down a simple smart contract to understand its parts:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SimpleStorage {
    // State Variables
    uint256 private storedData;
    
    // Events
    event DataStored(uint256 newValue);
    
    // Constructor
    constructor() {
        storedData = 0;
    }
    
    // Functions
    function set(uint256 x) public {
        storedData = x;
        emit DataStored(x);
    }
    
    function get() public view returns (uint256) {
        return storedData;
    }
}

Examining each component:

  1. License and Version

    • // SPDX-License-Identifier: MIT: Specifies the license
    • pragma solidity ^0.8.0: Specifies the Solidity version
  2. State Variables

    • Variables that are permanently stored in contract storage
    • Example: uint256 private storedData
    • Can be marked as public, private, or internal
  3. Events

    • Used to log important actions on the blockchain
    • Example: event DataStored(uint256 newValue)
    • Help frontend applications track contract state changes
  4. Constructor

    • Runs once when the contract is deployed
    • Used for initial setup
    • Example: constructor() { storedData = 0; }
  5. Functions

Setting Up Your Development Environment

1. Install Required Tools

# Install Node.js and npm if not already installed
# Then install Hardhat
npm install --save-dev hardhat

Hardhat is a development environment and task runner for Ethereum that helps developers compile, deploy, test, and debug smart contracts. The —save-dev flag ensures Hardhat is installed as a development-only dependency, keeping it separate from production dependencies.

2. Create a New Project

# Create a new directory
mkdir my-first-contract
cd my-first-contract

# Initialize a Node.js project with package.json
npm init -y

# Initialize a new Hardhat project
npx hardhat

3. Configure Hardhat for Nexus

Within your project directory, create/update your config file hardhat.config.js which will define the network configuration, RPC endpoint for Hardhat to connect to, and chainID for signature verification:

require("dotenv").config();
require("@nomicfoundation/hardhat-toolbox");

module.exports = {
  solidity: "0.8.20",
  networks: {
    nexus: {
      url: "https://rpc.nexus.xyz/http",
      chainId: 393,
      accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : []
    }
  }
};

4. Configure your private key in .env file

  1. Get your private key from Nexus

    • Go to the Nexus Web App
    • Sign in to your account in the top right corner
    • Click the “Settings” tab
    • Navigate to “Account & Security”
    • Click on “Private Key”
    • Click “Reveal” to view your private key
  2. Create your .env file

    • Create a new file named .env in your project root directory
    • Add your private key in this format:
    PRIVATE_KEY=your_private_key_here
    
  3. Install dotenv package

    npm install dotenv
    
  4. Update hardhat.config.js

    • Add this line at the top of your hardhat.config.js if not already present:
    require("dotenv").config();
    

Important Security Notes:

  • Never share your private key
  • Never commit it to version control
  • Keep it secure and backed up
  • Use a test account for development

5. Receive test NEX from a faucet for contract deployment

To deploy your contract on Nexus Layer 1, you’ll need NEX tokens to pay for gas fees. Gas fees are the cost of executing transactions on the blockchain, similar to how you need fuel to drive a car.

There are two ways to receive NEX for testing:

  1. Earn NEX through Proving

    • Submit proofs to earn points and NEX in real-time
    • This is the recommended way as it helps secure the network
    • For detailed instructions on proving, visit our Proving Guide
  2. Use the Nexus Faucet

    • A faucet is a service that provides small amounts of cryptocurrency for testing.
    • It’s like a water faucet, but instead of water, it dispenses test tokens
    • Visit our Faucet to receive test NEX

Note: The amount of NEX you receive from the faucet is sufficient for deploying and testing basic contracts. For more extensive testing, consider earning NEX through proving.

Writing and Deploying Your First Contract

1. Create a Contract File

Create contracts/Lock.sol:

This contract is the default Solidity example included when you scaffold a new Hardhat project. It demonstrates core Ethereum concepts like sending and holding ETH, working with block.timestamp, using events, and enforcing access control with msg.sender.

The contract implements a simple timelock wallet. When deployed, it requires:

  • A future unlockTime (timestamp),
  • And an ETH payment (payable constructor).

The contract locks the ETH until the specified unlock time. After that time has passed, only the deploying address (the owner) can withdraw the funds. The withdraw() function will revert if called too early or by anyone other than the owner.

This type of contract is useful for:

  • Time-based escrow
  • Delayed disbursements or vesting
  • Testing ETH flow logic with time-based constraints
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);
    }
}

2. Create a Deployment Script

Create scripts/deploy.js:

A deployment script is a programmatic way to deploy your smart contracts to a blockchain using Hardhat. Instead of manually interacting with the network through a UI or console, deployment scripts allow you to:

  • Automate contract deployment
  • Set constructor arguments dynamically
  • Log or save deployed addresses
  • Chain deployments in a predictable order
  • Integrate easily into testing, development, or CI/CD pipelines

Here we create a new folder entitled scripts and create a file entitled deploy.js, which will deploy our code to the Layer 1:

const hre = require("hardhat");

async function main() {
  console.log("Deploying Lock contract...");

  // Get the contract factory
  const Lock = await hre.ethers.getContractFactory("Lock");
  
  // Deploy the contract
  // The constructor requires a timestamp for the unlock time
  const unlockTime = Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 365; // 1 year from now
  const lock = await Lock.deploy(unlockTime);

  // Wait for deployment to finish
  await lock.waitForDeployment();

  const lockAddress = await lock.getAddress();
  console.log(`Lock contract deployed to: ${lockAddress}`);

  // Wait for a few block confirmations before verifying
  console.log("Waiting for block confirmations...");
  await new Promise(resolve => setTimeout(resolve, 30000)); // Wait 30 seconds

  // Verify the contract
  console.log("Verifying contract...");
  try {
    await hre.run("verify:verify", {
      address: lockAddress,
      constructorArguments: [unlockTime],
    });
    console.log("Contract verified successfully");
  } catch (error) {
    if (error.message.includes("Already Verified")) {
      console.log("Contract is already verified!");
    } else {
      console.error("Error verifying contract:", error);
    }
  }
}

// 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;
}); 

This script demonstrates a complete, real-world deployment pattern:

  • It handles constructor parameters (unlockTime)
  • Manages asynchronous deployment logic with await
  • Provides helpful logs to track progress
  • Prepares for contract verification (though it may be disabled or optional in some cases)

Deploying Your Contract

1. Deploy to Nexus

Run the following command to deploy your contract to the Nexus network:

npx hardhat run scripts/deploy.js --network nexus

You should see the following output in your terminal:

Deploying Lock contract...
Lock contract deployed to: 0x...  # Your contract's address will appear here

This means your contract has been successfully deployed to the Nexus network. Save the contract address - you’ll need it to interact with your contract later.

2. Examine Lock contract on the Nexus Explorer

Visit the Nexus Explorer to view your deployed contract. The block explorer is a search engine for the blockchain that lets you:

  • View all transactions
  • Check contract code
  • Monitor contract interactions
  • Track token transfers
  • View account balances

To find your contract:

  1. Copy your contract’s address from the deployment output
  2. Paste it into the search bar at the top of the explorer
  3. Click on your contract to view its details

You’ll see:

  • Contract code (verified)
  • Transaction history
  • Contract balance
  • Recent interactions
  • Event logs

This is where you can verify that your contract was deployed correctly and monitor its activity on the network.

Project Structure

Your project directory should look like this:

my-first-contract/
├── contracts/
   └── Lock.sol
├── scripts/
   └── deploy.js
├── .env
├── hardhat.config.js
└── package.json

Each directory and file serves a specific purpose:

  • contracts/: Contains your Solidity smart contracts
  • scripts/: Contains deployment and interaction scripts
  • .env: Stores your private key and other sensitive data
  • hardhat.config.js: Configures your development environment
  • package.json: Manages your project dependencies

Conclusion and Next Steps

Congratulations! You’ve successfully:

  • Set up your development environment
  • Created and deployed your first smart contract
  • Verified your contract on the Nexus Explorer

This is just the beginning of your smart contract development journey with Nexus. Here are some recommended next steps to continue learning:

  1. Learn More

  2. Build More

    • Try deploying more complex contracts (see additional guides)
    • Build a full-stack dApp

Remember: Smart contract development is a journey. Start simple, test thoroughly, and gradually build up to more complex applications. The Nexus community is here to support you every step of the way.