A smart contract is a program that runs on a blockchain. Once deployed, it executes exactly as written — no one can alter it, censor it, or shut it down. Smart contracts power everything from decentralized exchanges and lending protocols to NFTs and DAOs. This guide explains what smart contracts are, how they work, and how to build and interact with them.
What is a Smart Contract?
A smart contract is self-executing code stored on a blockchain that automatically enforces the terms of an agreement. Think of it as a vending machine: you insert the right input (coins + selection), and it automatically produces the output (your snack). No human intermediary is needed.
In technical terms, a smart contract is a program deployed at a specific address on the blockchain. It has its own storage (persistent state), can hold ETH and tokens, and exposes functions that anyone can call by sending a transaction. The code is executed by every node in the network, and the results are verified through consensus.
Key properties of smart contracts:
- Immutable: Once deployed, the code cannot be changed (unless using proxy patterns).
- Deterministic: Given the same input and state, the output is always identical.
- Transparent: The code is publicly visible and verifiable by anyone.
- Trustless: No central authority controls execution; the blockchain enforces the rules.
- Composable: Contracts can call other contracts, enabling complex applications built from simple building blocks.
A Brief History
The concept of smart contracts was first described by computer scientist and cryptographer Nick Szabo in 1994. Szabo envisioned digital protocols that could automatically execute the terms of a contract, reducing the need for trusted intermediaries.
However, Szabo's vision could not be fully realized until blockchain technology provided a decentralized, tamper-proof execution environment. Bitcoin (2009) introduced limited scripting capabilities, but it was Ethereum (2015), created by Vitalik Buterin, that brought Turing-complete smart contracts to life. Ethereum's Ethereum Virtual Machine (EVM) can execute arbitrary programs, making it a "world computer" capable of running any logic.
How Smart Contracts Work
Under the hood, smart contracts work through a cycle of compilation, deployment, and interaction:
1. Write the Code
Developers write smart contract logic in a high-level language (usually Solidity). The code defines state variables (storage), functions (logic), and events (logs).
2. Compile to Bytecode
The Solidity compiler (solc) converts the source code into EVM bytecode — the low-level instruction set that the Ethereum Virtual Machine understands. The compiler also generates the ABI (Application Binary Interface), which describes the contract's functions and how to encode/decode calls. See our ABI Encoding guide for a deep dive into how ABI encoding works.
Solidity Source Code (.sol)
|
v [solc compiler]
|
+-- Bytecode (deployed on-chain)
+-- ABI (JSON interface for interaction)3. Deploy to the Blockchain
Deployment is a special transaction with no "to" address. The transaction data contains the contract bytecode and any constructor arguments. When processed, the EVM creates a new contract account at a deterministic address and stores the bytecode.
4. Interact via Transactions
Users and other contracts interact by sending transactions to the contract's address. The transaction includes calldata that specifies which function to call and what arguments to pass. The EVM executes the function, updates state, emits events, and returns results.
Transaction Calldata:
0xa9059cbb <- function selector
0000000000000000000000001234567890abcdef1234567890abcdef12345678 <- address parameter
0000000000000000000000000000000000000000000000000000000000000064 <- uint256 parameter (100)
This calls: transfer(0x1234...5678, 100)Smart Contract Languages
Several programming languages can be used to write smart contracts for the EVM:
| Language | Style | Use Case | Adoption |
|---|---|---|---|
| Solidity | C++/JavaScript-like | General purpose | ~90% of contracts |
| Vyper | Python-like | Security-focused | ~5% of contracts |
| Huff | Assembly-like | Gas optimization | Niche |
| Yul | Intermediate language | Inline assembly in Solidity | Used within Solidity |
A Simple Smart Contract
Here is a basic Solidity smart contract that stores and retrieves a number. It demonstrates the essential components of every contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/// @title SimpleStorage - A minimal smart contract example
contract SimpleStorage {
// State variable - stored permanently on the blockchain
uint256 private storedValue;
// Event - emitted when the value changes (for off-chain tracking)
event ValueChanged(uint256 oldValue, uint256 newValue);
// Write function - costs gas (modifies state)
function set(uint256 newValue) external {
uint256 oldValue = storedValue;
storedValue = newValue;
emit ValueChanged(oldValue, newValue);
}
// Read function - free to call (does not modify state)
function get() external view returns (uint256) {
return storedValue;
}
}This contract has three key elements:
- State variable (
storedValue): Persistent data stored on the blockchain. - Event (
ValueChanged): A log entry that off-chain applications can listen to. - Functions (
setandget): Entry points for interaction. Write functions cost gas; read functions are free.
Interacting with Smart Contracts
Developers interact with smart contracts through JavaScript libraries. The two most popular are ethers.js and viem:
// Using ethers.js v6
import { ethers } from 'ethers';
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const contract = new ethers.Contract(
'0xContractAddress...',
['function set(uint256)', 'function get() view returns (uint256)'],
signer
);
// Read (free - no gas)
const value = await contract.get();
console.log('Current value:', value);
// Write (costs gas)
const tx = await contract.set(42);
await tx.wait();
console.log('Value updated!');// Using viem
import { createPublicClient, http } from 'viem';
import { mainnet } from 'viem/chains';
const client = createPublicClient({
chain: mainnet,
transport: http(),
});
// Read a contract value
const value = await client.readContract({
address: '0xContractAddress...',
abi: contractABI,
functionName: 'get',
});Real-World Use Cases
Smart contracts enable a wide range of applications that were previously impossible without trusted intermediaries:
Decentralized Finance (DeFi)
Smart contracts power lending protocols (Aave, Compound), decentralized exchanges (Uniswap, Curve), and stablecoins (DAI). This entire ecosystem is known as DeFi (Decentralized Finance), which replaces banks, brokers, and clearinghouses with transparent, auditable code.
NFTs and Digital Ownership
ERC-20, ERC-721, and ERC-1155 smart contracts enable verifiable ownership of fungible tokens and unique digital assets, from art and music to real estate deeds and academic credentials.
DAOs (Decentralized Autonomous Organizations)
Smart contracts enable governance systems where token holders vote on proposals that are automatically executed when approved. No board of directors or legal entity is required.
Gaming and Metaverse
In-game items, characters, and currencies can be represented as tokens on the blockchain, giving players true ownership of their digital assets that can be traded or used across games.
Supply Chain and Identity
Smart contracts can track goods from manufacturer to consumer, verify product authenticity, and manage digital identity credentials without centralized authorities.
Gas Costs and Optimization
Every operation in a smart contract costs gas. Understanding gas is essential for writing efficient contracts:
| Operation | Gas Cost | Notes |
|---|---|---|
| Addition/Subtraction | 3 gas | Cheapest operations |
| Keccak256 | 30 + 6/word | Common for hashing |
| Storage read (cold) | 2,100 gas | First read of a slot |
| Storage write (new) | 20,000 gas | Most expensive operation |
| ETH transfer | 21,000 gas | Base transaction cost |
| Contract deployment | 32,000 + bytecode | 200 gas per byte |
Common optimization techniques include packing multiple variables into single storage slots, using calldata instead of memory for read-only function parameters, minimizing storage writes, and using events instead of storage for data that only needs to be read off-chain. Use our Gas Fee Calculator to estimate costs.
Security Considerations
Smart contract security is critical because bugs can lead to permanent loss of funds. Billions of dollars have been lost to smart contract exploits. Here are the key areas to consider:
- Reentrancy attacks: When a contract makes an external call before updating its state, the called contract can re-enter the original function. The infamous DAO hack (2016) exploited this, leading to the Ethereum/Ethereum Classic fork.
- Integer overflow/underflow: Before Solidity 0.8.0, arithmetic could silently wrap around. Solidity 0.8+ includes built-in overflow checks.
- Access control: Ensure that sensitive functions (like minting, pausing, or upgrading) can only be called by authorized addresses.
- Oracle manipulation: Contracts that rely on external price feeds can be exploited if the oracle data is manipulated (common in flash loan attacks).
- Front-running: Miners and MEV bots can see pending transactions and insert their own transactions before or after yours to extract profit.
Best practices: Always have your contracts audited by reputable firms before deploying with significant funds. Use established libraries like OpenZeppelin. Write comprehensive tests. Consider formal verification for critical contracts. Run a bug bounty program.
Development Tools and Frameworks
The smart contract development ecosystem has mature tooling:
- Foundry: A fast, Rust-based framework for compiling, testing, and deploying Solidity contracts. Tests are written in Solidity.
- Hardhat: A JavaScript-based development environment with extensive plugin ecosystem. Tests are written in JavaScript/TypeScript.
- Remix IDE: A browser-based IDE ideal for learning and quick prototyping. No installation required.
- OpenZeppelin: A library of audited, reusable smart contract components (ERC-20, ERC-721, access control, etc.).
- Tenderly: A debugging and monitoring platform that provides transaction simulation, gas profiling, and alerting.
Frequently Asked Questions
Can a smart contract be changed after deployment?
Standard smart contracts are immutable once deployed. The bytecode on the blockchain cannot be modified. However, developers can use proxy patterns (like UUPS or Transparent Proxy) to create upgradeable contracts, where the logic can be swapped while preserving the contract's address and state. This adds complexity and trust assumptions.
How much does it cost to deploy a smart contract?
Deployment cost depends on the contract size (bytecode length) and network gas prices. On Ethereum mainnet, deploying a simple contract might cost $10-50, while complex contracts can cost hundreds of dollars. Layer 2 networks like Arbitrum and Optimism reduce costs by 10-100x.
What programming language are smart contracts written in?
The most popular language is Solidity, used by the vast majority of Ethereum smart contracts. Vyper is an alternative that prioritizes simplicity and security. Huff is a low-level language for maximum gas optimization. All compile to EVM bytecode, which is what actually runs on the blockchain.
Are smart contracts legally binding?
Smart contracts are not legal contracts in the traditional sense. They are self-executing programs, not legal agreements. However, some jurisdictions are beginning to recognize smart contracts as enforceable agreements, and they can be used alongside traditional legal contracts to automate enforcement.
What happens if there is a bug in a smart contract?
Because smart contracts are immutable, bugs cannot be patched like traditional software. If a vulnerability is exploited, funds can be permanently lost. This is why security audits, formal verification, extensive testing, and bug bounty programs are critical before deploying contracts that handle significant value.
Try It Yourself
Ready to work with smart contract data? Use our ABI Encoder / Decoder to encode function calls, or compute function selectors with the Keccak256 Hash Generator.
Related Tools
- ABI Encoder / Decoder — Encode and decode smart contract function calls
- Keccak256 Hash Generator — Compute Keccak256 hashes and function selectors
- Calldata Decoder — Decode raw transaction calldata
- Gas Fee Calculator — Estimate Ethereum transaction costs
- Storage Slot Calculator — Calculate storage layout for smart contracts