Skip to main content

Smart Contract Templates

This page offers ready-to-use, copy/paste contract templates designed for gasless transactions and full Stability platform compatibility. For each template, you'll find the full contract code, a concise explanation of how it works, and deployment / interaction examples.

  • All examples target Solidity compiler version ≤ 0.8.24 and are compatible with the Shanghai EVM or earlier.

  • For a deeper dive into platform-specific EVM limitations and Solidity best practices, visit EVM Compatibility & Solidity Development.

Getting Started

These templates assume you're familiar with either:

  • Deploying contracts using Remix or reading contract data with ethers.js, or
  • Understanding the ZKT API for Web2-friendly interactions via ZKT API Reference

If you're new to smart contracts, we recommend starting with these templates below.


Templates

Overview

BasicStorage is the simplest read/write contract: it stores a string and a uint256, exposes read access, and emits events whenever values change. It is a clean starting point for understanding how state is persisted on-chain without any token or value transfer logic.

How It Works

On deployment, the state starts with Solidity defaults (empty string and 0). Reads (getMessage(), getValue()) are view and cost no state changes; writes (setMessage(), setValue()) update storage and emit events so indexers and frontends can react.

The contract uses two private state variables (message and value) that persist in contract storage. Read functions (getMessage(), getValue()) are pure queries with no storage writes, while write functions (setMessage(), setValue()) mutate storage and emit MessageUpdated/ValueUpdated events so off-chain systems can track updates.

Contract Code

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

contract BasicStorage {
string private message;
uint256 private value;

event MessageUpdated(string oldMessage, string newMessage);
event ValueUpdated(uint256 oldValue, uint256 newValue);

function getMessage() external view returns (string memory) {
return message;
}

function setMessage(string calldata newMessage) external {
string memory oldMessage = message;
message = newMessage;
emit MessageUpdated(oldMessage, newMessage);
}

function getValue() external view returns (uint256) {
return value;
}

function setValue(uint256 newValue) external {
uint256 oldValue = value;
value = newValue;
emit ValueUpdated(oldValue, newValue);
}
}

Functions

Write Functions

setMessage(): Updates the stored message and emits an event containing both the old and new values (useful for UI updates and indexing).

function setMessage(string calldata newMessage) external {
string memory oldMessage = message;
message = newMessage;
emit MessageUpdated(oldMessage, newMessage);
}

Read Functions

getMessage(): view reads do not modify state. Typically you call these via RPC (eth_call) without sending a transaction.

function getMessage() external view returns (string memory) {
return message;
}

Events

Events are emitted to notify off-chain systems of state changes. They are indexed and searchable, making them ideal for frontends and indexers.

  • MessageUpdated(string oldMessage, string newMessage) - Emitted when setMessage() is called. Includes both the previous and new message values for tracking changes.
  • ValueUpdated(uint256 oldValue, uint256 newValue) - Emitted when setValue() is called. Records the old and new numeric values for audit purposes.

How to Deploy/Interact

Replace placeholders like YOUR_RPC_URL, CONTRACT_ADDRESS, and YOUR_PRIVATE_KEY with your own values.

  • Deploy with no constructor args.
  • Call getMessage() / getValue() to read.
  • Call setMessage() / setValue() to write.