Using C code on EVM and Non-EVM Blockchains

ChainsAtlas enables developers to seamlessly run C code on both EVM and non-EVM blockchains. The examples below showcase some potential use cases.

Overview

The following documentation explains the features of C supported by the ChainsAtlas development framework.

QuickStart - Example 1: Passing Arguments to a Smart Contract

In this example, the user passes two arguments to a deployed smart contract. The function __chainsatlas_evm_sload is lowered to sload an EVM native operation that loads stored information via a key. (will be soon replaced by mload as the default argument passing mechanism)

long sum(long x, long y) {
    return x + y;
}

long main() {
    long x, y, z;
    x = __chainsatlas_evm_sload(1);
    y = __chainsatlas_evm_sload(2);
    // z = __chainsatlas_evm_sload(3); if you have more arguments ...
    z = sum(x, y);
    return z;
}

Explanation:

The main function first fetches two stored values from keys 1 and 2 using the __chainsatlas_evm_sload function. It then calculates their sum by calling the sum function and finally returns the result.

QuickStart - Example 2: Running the 2048 Game Logic On-Chain

This example demonstrates how one can run the logic of the popular 2048 game fully on a blockchain.

long pseudo_rand(long *seed) {
    *seed = 1103515245 * (*seed) + 12345;
    return (long)((*seed >> 16) & 0x7FFF);
}

void addRandom(long *board, long *seed) {
    long r;
    do {
        r = pseudo_rand(seed) % 16;
    } while(board[r] != 0);

    board[r] = ((pseudo_rand(seed) % 2) + 1) * 2;
}

void shiftGrid(long* grid) {
    long x, y;
    long line[4], count;

    for (y = 0; y < 4; y++) {
        count = 0;
        for (x = 0; x < 4; x++) {
            if (grid[x*4 + y] != 0) {
                if (count > 0 && line[count-1] == grid[x*4 + y]) {
                    line[count-1] *= 2;
                    grid[x*4 + y] = 0;
                } else {
                    line[count] = grid[x*4 + y];
                    count++;
                }
            }
        }
        for (x = count; x < 4; x++) {
            line[x] = 0;
        }
        for (x = 0; x < 4; x++) {
            grid[x*4 + y] = line[x];
        }
    }
}

long computeScore(long* grid) {
    long i, score = 0;
    for (i = 0; i < 16; i++)
        score += grid[i];
    return score;
}

long main() {
    long seed = 12345;
    long moves = 0b0101010101010101010101;
    long i;
    long grid[16];

    for (i = 0; i < 16; i++) {
        grid[i] = 0;
    }
    // skipping the first non null 2-bits allowing the distinction between moves and type promotion
    moves = moves >> 2;
    long len = 0;
    while(moves != 0) {
        moves = moves >> 2;
        len++;
    }

    addRandom(grid, &seed);
    for (i = 0; i < len; i++) {
        shiftGrid(grid);
        addRandom(grid, &seed);
    }

    long score = computeScore(grid);
    return score;
}

Explanation:

This code replicates the game logic of 2048. It starts by initializing a grid with random numbers using the addRandom function. The shiftGrid function is used to combine and shift the tiles, as in the actual game. The final score is then computed using the computeScore function, taking the sum of all the grid values.

Basic Data Types

  • long (Recommended): While we support a rich variety of data types, long is the most stable across different chains, thus, used as the primary data type for the examples.

    long number = 100;
    

Pointers

  • Utilized for array handling and direct variable modifications.

    long value = 10;
    long *pointer = &value;
    

Arrays

  • Single-dimensional arrays:

    long array[10];
    
  • Two-dimensional arrays interpreted via single-dimensional arrays:

    long grid[16]; // Example of a 4x4 grid
    

Loop Constructs

  • for loops:

    for(long i = 0; i < 10; i++) {
        // iteration logic
    }
    
  • while loops:

    long count = 0;
    while(count < 10) {
        count++;
    }
    

Conditional Statements

  • if:

    if(x == 10) {
        // logic if condition is true
    }
    
  • if-else:

    if(x > 10) {
        // logic if x is greater than 10
    } else {
        // logic if x is not greater than 10
    }
    

Functions

  • User-defined functions:

    void display() {
        // function logic
    }
    
  • Function Calls:

    display();
    
  • Recursive Function Calls:

    long factorial(long n) {
        if(n <= 1) return 1;
        return n * factorial(n-1);
    }
    

Arithmetic Operations

Basic operations:

long addition = a + b;
long multiplication = a * b;
long subtraction = a - b;
long division = a / b;

Bitwise Operations

long shiftedValue = a >> 2;
long bitwiseAnd = a & b;

Assignment Operations

long x = 10;
x *= 2; // Compound assignment

Relational Operators

if(a == b) { /* logic */ }
if(a > b) { /* logic */ }
if(a >= b) { /* logic */ }

Pointer Operators

long value = 10;
long *ptr = &value;
long dereferencedValue = *ptr;

Comments

// This is an inline comment

Blockchain-specific Features

__chainsatlas_evm_sstore(1, 12);
long valueFromBlockchain = __chainsatlas_evm_sload(1);