Smart contracts are self-executing agreements written in code, operating on blockchain networks like Ethereum. They automatically enforce rules and execute actions when predefined conditions are met—without intermediaries. This guide explores the fundamentals of smart contracts using Solidity, the most widely used language for Ethereum-based development.
A Simple Smart Contract
Let’s begin with a basic example that demonstrates how to store and retrieve a value through a smart contract. Don’t worry if every detail isn’t clear yet—we’ll break it down step by step.
Storage Example
// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.4.16 < 0.9.0;
contract SimpleStorage {
uint storedData;
function set(uint x) public {
storedData = x;
}
function get() public view returns (uint) {
return storedData;
}
}The first line specifies the license under which this code is released—GPL-3.0. Including a machine-readable license identifier is essential when sharing source code publicly.
The pragma directive defines the compatible Solidity compiler version range: from 0.4.16 up to (but not including) 0.9.0. This prevents unexpected behavior due to breaking changes in future compiler versions.
In blockchain terms, a smart contract is a collection of code (functions) and data (state) located at a specific address on the Ethereum network.
uint storedData;declares a state variable of type unsigned integer (uint), which stores values persistently on the blockchain.- The
set()function allows anyone to update the value ofstoredData. - The
get()function retrieves the current value.
These functions make the variable accessible to external users and other contracts. Since state variables are globally visible within the contract, you can access them directly without prefixes like this..
👉 Discover how developers deploy real-world smart contracts securely.
Note: While this contract lets anyone store a number, it currently has no access restrictions—anyone can overwrite the stored value. Later, we’ll explore ways to restrict permissions so only authorized users can modify data.
Building a Custom Cryptocurrency
Now let’s look at a more advanced use case: creating a simple cryptocurrency.
Sub-Currency Example
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.26;
contract Coin {
address public minter;
mapping(address => uint) public balances;
event Sent(address from, address to, uint amount);
constructor() {
minter = msg.sender;
}
function mint(address receiver, uint amount) public {
require(msg.sender == minter);
balances[receiver] += amount;
}
error InsufficientBalance(uint requested, uint available);
function send(address receiver, uint amount) public {
require(amount <= balances[msg.sender], InsufficientBalance(amount, balances[msg.sender]));
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
}This contract introduces several core concepts in smart contract development:
State Variables and Access Control
address public minter;stores the creator’s Ethereum address. Thepublickeyword automatically generates a getter function, allowing others to query this value.mapping(address => uint) public balances;creates a dynamic lookup table that maps user addresses to their token balances.
Mappings behave like virtual hash tables—every possible key exists from the start, initialized to zero. However, you cannot iterate over keys or values directly. You must track them separately if needed.
Events for Real-Time Monitoring
event Sent(...);defines an event that logs transactions. External applications (e.g., web dashboards) can listen for these events efficiently using tools likeweb3.js.
Example JavaScript listener:
Coin.Sent().watch({}, '', function(error, result) {
if (!error) {
console.log("Transfer: " + result.args.amount + " tokens from " + result.args.from);
}
});Function Security with Require and Errors
require(msg.sender == minter);ensures only the contract creator can mint new tokens.error InsufficientBalance(...);provides detailed feedback when users try to send more than they hold.- Arithmetic operations are checked by default in Solidity 0.8+, meaning overflows will revert the transaction automatically.
👉 Learn how blockchain platforms validate smart contract logic before execution.
Note: Even though tokens appear transferred, standard blockchain explorers won’t display them unless they recognize your custom contract. To track balances, users must query the contract directly or use specialized tools.
Blockchain Fundamentals
Understanding smart contracts requires grasping how blockchains work at a foundational level.
Transactions: Atomic and Secure
A blockchain acts as a globally shared transactional database. Changes occur via transactions, which are atomic—either fully completed or entirely reverted.
For example, transferring digital assets deducts funds from one account and credits another simultaneously. If any part fails (e.g., insufficient balance), the entire operation rolls back.
All transactions are cryptographically signed by the sender, ensuring only authorized parties can initiate changes.
Blocks and Consensus
Transactions are grouped into blocks, added to the chain approximately every 12 seconds on Ethereum. A decentralized consensus mechanism resolves conflicts—for instance, preventing double-spending—by agreeing on a single valid transaction order.
While blocks are generally permanent, recent ones may be reorganized under rare network conditions. The deeper a block is in the chain, the more secure it becomes.
Tip: Transactions aren’t guaranteed immediate inclusion in a block—they depend on gas fees and miner preferences. For scheduled future executions, consider automation tools or oracle services.
Ethereum Virtual Machine (EVM)
The EVM is the runtime environment for all smart contracts on Ethereum. It operates as a sandboxed, isolated system with strict rules.
Account Types
Ethereum supports two account types:
- Externally Owned Accounts (EOAs): Controlled by private keys (typically users).
- Contract Accounts: Governed by code stored at their address.
Both share the same namespace and support balance storage (in wei, where 1 ether = 10¹⁸ wei).
Data Storage Models
The EVM provides four primary data areas:
- Storage: Persistent key-value store (256-bit to 256-bit). Expensive to read/write.
- Memory: Temporary linear memory cleared after each call.
- Calldata: Immutable space for input parameters (cost-efficient for reading).
- Stack: Holds up to 1024 items; used for computation.
Use storage sparingly—store only essential state data.
Gas: The Fuel of Computation
Every operation consumes gas, paid in ether by the transaction initiator. Gas limits prevent infinite loops and ensure fair compensation for validators.
- High gas usage increases costs but improves execution priority.
- Unused gas is refunded; failed transactions still pay for consumed resources.
👉 Explore how gas optimization boosts smart contract efficiency.
Message Calls and Delegation
Contracts interact via message calls, which can transfer value or trigger function execution in other contracts.
- Delegatecall enables code reuse by executing external logic in the caller’s context—key for building libraries.
- Call depth is limited to 1024 to prevent stack overflows.
Logs and Events
Logs allow efficient indexing of blockchain activity without bloating state size. They power event systems in Solidity and support lightweight clients via bloom filters.
Contract Creation and Self-Destruct
New contracts are deployed via special creation transactions. Once deployed, they persist unless explicitly destroyed using selfdestruct.
Warning: As of the Cancun upgrade (EVM >= Cancun),selfdestructno longer removes contract code unless called during the same transaction as deployment. Additionally, this opcode is deprecated in Solidity 0.8.18+ and should be avoided in new projects.
Even after self-destruction, historical records remain part of the blockchain ledger.
Frequently Asked Questions
Q: What is a smart contract?
A: A smart contract is a program deployed on a blockchain that executes automatically when predefined conditions are met—enabling trustless, transparent interactions.
Q: Can smart contracts be changed after deployment?
A: No—once deployed, code is immutable unless designed with upgradeability patterns (e.g., proxy contracts).
Q: How do I test a smart contract before launch?
A: Use development environments like Remix or Hardhat to simulate behavior on local or test networks before mainnet deployment.
Q: Are all variables in Solidity public by default?
A: No—visibility must be explicitly set (public, private, internal, external). Public variables generate automatic getter functions.
Q: What happens if a transaction runs out of gas?
A: The transaction reverts—all state changes are undone, but gas fees are still charged for computation performed.
Q: Can one contract call another?
A: Yes—contracts can interact via message calls or delegatecalls, enabling modular design and shared logic libraries.
Core Keywords
- Smart contract
- Solidity
- Ethereum Virtual Machine (EVM)
- Blockchain
- Gas
- State variable
- Event logging
- Decentralized application (dApp)
This comprehensive overview equips you with foundational knowledge to start writing secure, functional smart contracts using Solidity and interacting with the broader Ethereum ecosystem.