Solidity
Solidity is the primary programming language for writing smart contracts on Ethereum and EVM-compatible blockchains.
Key Takeaways
- Solidity is a statically-typed, contract-oriented programming language designed specifically for the Ethereum Virtual Machine (EVM). It is the dominant language for writing smart contracts across Ethereum and dozens of EVM-compatible chains.
- The language introduced built-in overflow checks in version 0.8, eliminating an entire class of vulnerabilities. Combined with mature tooling like Hardhat, Foundry, and OpenZeppelin, Solidity offers the largest developer ecosystem in blockchain.
- Bitcoin uses a fundamentally different approach: Bitcoin Script is intentionally non-Turing-complete, and Bitcoin Layer 2s like Spark use key rotation and threshold signatures rather than virtual machine execution.
What Is Solidity?
Solidity is a high-level programming language created for writing smart contracts that run on the Ethereum Virtual Machine. Proposed by Gavin Wood in August 2014 and developed primarily by Christian Reitwiessner, the language launched alongside Ethereum in 2015. Its syntax draws from JavaScript, C++, and Python, making it approachable for developers with experience in any of those languages.
Solidity compiles to EVM bytecode: low-level instructions that every Ethereum node executes when processing transactions. Because the EVM has been adopted by numerous other blockchains (Polygon, Arbitrum, BNB Smart Chain, Avalanche, Optimism, Base), Solidity code is portable across a large portion of the blockchain ecosystem. A contract written for Ethereum can typically deploy to any EVM-compatible chain with minimal or no modification.
As of September 2026, the latest stable release is Solidity 0.8.36 (released July 2026). The language is open-source under the GNU General Public License v3.0.
How It Works
Solidity is a contract-oriented language, meaning the fundamental unit of code is the contract: a collection of state variables, functions, events, and modifiers that lives at a specific address on the blockchain. Contracts behave similarly to classes in object-oriented programming, supporting inheritance and polymorphism.
Core Language Features
Solidity provides several types and constructs purpose-built for blockchain development:
address: a 20-byte type representing an Ethereum account. Theaddress payablevariant can receive Ether viatransfer()orsend().mapping: a key-value hash table for on-chain storage. Mappings do not support iteration, so developers often pair them with arrays to track keys.uint/int: unsigned and signed integers from 8 to 256 bits.uint256is the default and most commonly used size.- Events: logged data that smart contracts emit during execution. Off-chain applications and indexers (like The Graph) subscribe to events to track contract activity.
- Modifiers: reusable conditions that wrap function logic. The classic example is
onlyOwner, which restricts a function to the contract deployer. - Inheritance: contracts can inherit from one or more parent contracts using C3 linearization (the same resolution order Python uses for multiple inheritance).
A Simple Contract
The following example demonstrates core Solidity patterns: state variables, a modifier, an event, and public functions:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SimpleVault {
address public owner;
mapping(address => uint256) public balances;
event Deposit(address indexed user, uint256 amount);
event Withdrawal(address indexed user, uint256 amount);
modifier onlyOwner() {
require(msg.sender == owner, "Not authorized");
_;
}
constructor() {
owner = msg.sender;
}
function deposit() external payable {
balances[msg.sender] += msg.value;
emit Deposit(msg.sender, msg.value);
}
function withdraw(uint256 amount) external {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
emit Withdrawal(msg.sender, amount);
}
}The pragma directive pins the compiler version. The constructor runs once at deployment. Functions marked external can only be called from outside the contract, while payable allows a function to receive Ether.
Compilation and Deployment
The development workflow follows a consistent pattern across tooling:
- Write
.solsource files with the contract logic - Compile to EVM bytecode and an ABI (Application Binary Interface) using
solc, Hardhat, or Foundry - Deploy by sending a transaction containing the bytecode to the network
- Interact via the ABI, which defines the contract's callable functions and their parameter types
Tooling Ecosystem
One of Solidity's strongest advantages is its mature developer ecosystem. The major frameworks include:
- Hardhat: the most widely used development environment. JavaScript/TypeScript-based with superior debugging (exact Solidity line numbers on failure, full stack traces). Used by Uniswap, Aave, and Compound.
- Foundry: a Rust-based framework gaining rapid adoption. Tests are written in Solidity itself, eliminating JavaScript context-switching. Includes
forge(build/test),cast(CLI interactions), andanvil(local node). - Remix IDE: a browser-based environment requiring zero installation. Ideal for learning, prototyping, and quick contract interactions.
- OpenZeppelin: a standard library of audited, reusable contract templates for ERC-20 tokens, ERC-721 NFTs, access control, and more. Integrates with both Hardhat and Foundry.
Static analysis tools like Slither help catch vulnerabilities before deployment, and formal verification tools can mathematically prove contract properties. This deep dive on account abstraction illustrates the kind of sophisticated contract logic these tools support.
Alternatives to Solidity
While Solidity dominates EVM development, other smart contract languages serve different chains and design philosophies:
| Language | Chain(s) | Key Characteristics |
|---|---|---|
| Vyper | Ethereum / EVM | Python-like syntax, intentionally simpler than Solidity. No class inheritance by design, improving auditability. |
| Cairo | StarkNet | Rust-inspired language that compiles to STARK-provable programs. Powers dYdX and ImmutableX. |
| Move | Sui, Aptos | Resource-oriented language with a linear type system. Assets cannot be duplicated or accidentally destroyed. |
| Clarity | Stacks (Bitcoin L2) | Lisp-like, non-Turing-complete, interpreted language. Can read Bitcoin state directly. Prevents reentrancy by construction. |
| Rust | Solana, Polkadot, NEAR | General-purpose systems language adapted for smart contracts. Memory safety without garbage collection. |
Even within the EVM world, Vyper serves as the main alternative for teams that prefer simplicity and reduced attack surface over Solidity's richer feature set.
Bitcoin's Different Approach
Bitcoin does not use Solidity or any Turing-complete language. Bitcoin Script is a deliberately limited, stack-based language that handles transaction validation logic: multisig conditions, timelocks, and hash locks. It cannot create loops, store persistent state, or express complex application logic. This constraint is a feature: it minimizes the attack surface and keeps Bitcoin's base layer focused on secure value transfer.
Bitcoin Layer 2 solutions reflect this philosophy. The Lightning Network uses payment channels and HTLCs for instant payments. Spark uses statechains and FROST threshold signatures to enable instant, self-custodial Bitcoin and stablecoin transfers. Neither relies on a virtual machine or smart contract language. Instead, they achieve speed and functionality through cryptographic protocols and key rotation, not bytecode execution.
This fundamental design difference means developers building on Bitcoin work with a different mental model than Solidity developers. Where Solidity developers write persistent on-chain programs, Bitcoin developers compose transaction conditions from a fixed set of opcodes.
Use Cases
Solidity powers the vast majority of decentralized applications across the EVM ecosystem:
- DeFi protocols: lending platforms (Aave, Compound), decentralized exchanges (Uniswap, Curve), and yield aggregators all run on Solidity contracts that manage billions of dollars in value.
- Token standards: ERC-20 (fungible tokens), ERC-721 (NFTs), and ERC-1155 (multi-token) are all defined as Solidity interfaces.
- DAOs: governance contracts that manage treasuries, voting, and proposal execution for decentralized organizations.
- Stablecoins: contracts for minting, burning, blacklisting, and managing reserves for tokens like USDC and DAI.
- Cross-chain bridges: contracts that lock assets on one chain and coordinate with counterparts on another.
- Layer 2 rollups: the on-chain verification and dispute resolution contracts for optimistic and ZK rollups are written in Solidity.
Risks and Considerations
Reentrancy Attacks
The most notorious Solidity vulnerability. In a reentrancy attack, a malicious contract repeatedly calls back into the victim contract before prior execution completes. The DAO hack of June 2016 exploited this pattern, draining 3.6 million ETH (roughly $60 million at the time) and ultimately causing the Ethereum/Ethereum Classic hard fork.
The standard mitigation is the checks-effects-interactions pattern: validate conditions, update state, then make external calls. OpenZeppelin's ReentrancyGuard modifier provides an additional safety layer.
Integer Overflow and Underflow
Before Solidity 0.8.0 (released December 2020), arithmetic operations silently wrapped around on overflow. For example, adding 1 to the maximum uint8 value of 255 would produce 0 instead of reverting. Developers relied on OpenZeppelin's SafeMath library to catch these errors.
Solidity 0.8.0 made overflow and underflow checks built-in: arithmetic that would overflow now automatically reverts. Developers who need unchecked math for gas optimization can use explicit unchecked blocks.
Access Control Issues
Missing or improper authorization checks on sensitive functions remain a common source of exploits. An unprotected initialize() function, a missing onlyOwner modifier, or an overly permissive role assignment can give attackers full control of a contract. Auditing tools and established patterns (like OpenZeppelin's AccessControl library) help mitigate this risk.
Immutability
Deployed Solidity contracts cannot be modified. If a bug is discovered after deployment, the team must deploy a new contract and migrate users. Upgradeable proxy patterns exist but introduce their own complexity and trust assumptions. This immutability makes thorough auditing and testing before deployment critical.
Front-Running
Because pending transactions are visible in the mempool, attackers can observe contract interactions and submit competing transactions with higher gas fees to manipulate execution order. This is particularly relevant for DEX trades and NFT mints, and it feeds into the broader problem of maximal extractable value (MEV).
This glossary entry is for informational purposes only and does not constitute financial or investment advice. Always do your own research before using any protocol or technology.