Smart Contract Development with Solidity on ChainMaker

·

Developing smart contracts using Solidity on ChainMaker offers a powerful way to build secure, scalable, and interoperable blockchain applications. This guide walks developers through the complete process of writing, compiling, and testing Solidity-based smart contracts tailored for the ChainMaker blockchain framework. Whether you're building enterprise-grade decentralized applications or exploring blockchain innovation, this resource delivers essential insights into leveraging Solidity in a non-currency (tokenless) chain environment.

👉 Discover how to deploy your first smart contract with ease

Environment Setup

Before diving into contract development, ensure your environment is properly configured. ChainMaker supports cross-platform development, making it accessible across operating systems.

Supported Platforms

ChainMaker has no strict OS requirements—development can be performed seamlessly on:

No additional software dependencies are required at the system level, simplifying the setup process.

Preparing the ChainMaker Environment

To test and deploy contracts, you must have:

The CMC tool enables interaction with the blockchain, including contract deployment and invocation. For detailed installation steps, refer to official documentation covering node setup and command-line tool configuration.

Writing Smart Contracts in Solidity

Solidity is a high-level, contract-oriented programming language influenced by C++, Python, and JavaScript. It's statically typed and supports advanced features like inheritance, libraries, and custom data types—ideal for writing robust smart contracts.

Development Environment Options

Developers don't need to set up local tooling from scratch. Instead, use Remix, an online IDE widely adopted in the Ethereum ecosystem:

👉 Start coding your smart contract instantly in-browser

Remix provides syntax highlighting, debugging tools, and built-in compiler support. Importantly, ChainMaker is fully compatible with Solidity code developed in Remix, meaning Ethereum-originated contracts can often be deployed on ChainMaker with minimal or no modifications.

Key Differences Between ChainMaker and Ethereum Solidity

While ChainMaker maintains strong compatibility with Ethereum’s EVM model, there are critical distinctions due to its tokenless architecture and enterprise focus.

Built-in Global Variables and Functions

Because ChainMaker does not issue native tokens, certain Ethereum-specific values default to zero or fixed constants:

FeatureValue / Behavior
msg.valueFixed at 0 (no native token transfers)
block.difficultyAlways returns 0
tx.gaspriceFixed at 1
block.coinbaseReturns proposer address of current block

Other standard variables such as block.number, block.timestamp, msg.sender, and gasleft() function as expected and can be safely used in logic.

Precompiled Contracts

Precompiled contracts optimize performance for computationally intensive operations like cryptographic hashing and elliptic curve calculations. However, ChainMaker currently does not support all Ethereum precompiles.

Unsupported precompiled functions (under development):

Supported precompiles include:

Ensure your contract avoids reliance on unsupported precompiles unless they are conditionally handled.

Cross-Contract Invocation

ChainMaker extends standard EVM capabilities by allowing cross-virtual machine contract calls. In addition to calling other Solidity contracts, developers can invoke contracts written in other supported languages (e.g., Go or Rust-based Wasm contracts).

This feature enhances modularity and promotes reuse across heterogeneous smart contract systems within the same network.

For implementation details, consult the official guide on cross-contract invocation patterns.

Sample Contract: ERC20-Compatible Token

Despite being a tokenless chain, ChainMaker supports token-like logic for asset tracking and permissions management. Below is a simplified ERC20-compliant token implementation:

pragma solidity >0.5.11;

contract Token {
    string public name = "token";
    string public symbol = "TK";
    uint256 public decimals = 6;
    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(address => uint256)) public allowance;
    uint256 public totalSupply = 0;
    bool public stopped = false;

    address owner = address(0x0);

    modifier isOwner {
        assert(owner == msg.sender);
        _;
    }

    modifier isRunning {
        assert(!stopped);
        _;
    }

    modifier validAddress {
        assert(address(0x0) != msg.sender);
        _;
    }

    constructor(address _addressFounder) {
        owner = msg.sender;
        totalSupply = 100000000000000000;
        balanceOf[_addressFounder] = totalSupply;
        emit Transfer(address(0x0), _addressFounder, totalSupply);
    }

    function transfer(address _to, uint256 _value)
        public
        isRunning
        validAddress
        returns (bool success)
    {
        require(balanceOf[msg.sender] >= _value);
        balanceOf[msg.sender] -= _value;
        balanceOf[_to] += _value;
        emit Transfer(msg.sender, _to, _value);
        return true;
    }

    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

This example demonstrates common patterns: ownership control, modifiers for access restriction, event emission, and balance management—all fully compatible with ChainMaker’s runtime.

Compiling Contracts

Compilation transforms human-readable Solidity code into EVM-executable bytecode.

Using Docker for Compilation

ChainMaker provides an official Docker image for consistent compilation:

docker pull chainmakerofficial/chainmaker-solidity-contract:2.0.0

Launch the container with volume mapping to access local files:

docker run -it --name chainmaker-solidity-contract -v $WORK_DIR:/home chainmakerofficial/chainmaker-solidity-contract:2.0.0 bash

Inside the container, compile using solc:

solc --abi --bin --hashes --overwrite -o . token.sol

Output includes:

Compiler Version Note

The Docker image uses Solidity compiler version 0.8.4. Contracts must specify a compatible version (>=0.8.4) to prevent compilation errors.

Alternatively, use Remix to compile without version conflicts and export artifacts directly.

Testing and Simulation

Before deploying on a live network, simulate contract behavior locally.

Simulated Deployment

Use the evm command-line tool to deploy:

evm Token.bin init_contract data 00000000000000000000000013f0c1639a9931b0ce17e14c83f96d4732865b58

Here:

Calldata can be generated programmatically using ChainMaker’s ABI utility package:

import "chainmaker.org/chainmaker/common/v2/evmutils/abi"
abiObj, _ := abi.JSON(strings.NewReader(string(abiBytes)))
calldata, _ := abiObj.Pack("constructorMethod", parameter)

Simulated Invocation

After deployment, interact with the contract:

evm DeployedToken.bin 0x70a08231 data 0x70a08231... // balanceOf(address)

Function selectors (like 0x70a08231) are derived from Keccak-256 hashes of method signatures and listed in the .signatures output file.


FAQ

Q: Can I use any version of Solidity?
A: It's recommended to use Solidity 0.8.4 or higher to match the compiler version in ChainMaker's Docker image and avoid compatibility issues.

Q: Is native token transfer supported?
A: No. ChainMaker is a tokenless chain; msg.value always returns 0 and cannot be used for fund transfers.

Q: Are all Ethereum precompiled contracts available?
A: Not all. Functions like ecrecover and BN256 operations are not yet supported but are planned for future releases.

Q: How do I generate calldata for constructor parameters?
A: Use ChainMaker’s ABI package in Go or leverage Remix IDE to encode parameters based on the contract ABI.

Q: Can I call non-Solidity contracts from my Solidity code?
A: Yes. ChainMaker supports cross-VM calls, allowing interaction between Solidity (EVM) and Wasm-based contracts.

Q: Do I need to run a full node to test contracts?
A: While a local node enables full integration testing, simulation tools like evm allow early-stage logic validation without full infrastructure.

👉 Unlock advanced tools for blockchain development today