Solidity

The primary programming language for writing smart contracts on Ethereum and EVM-compatible blockchains.

Solidity is a statically-typed, contract-oriented programming language designed for implementing smart contracts on the EVM. Created by the Ethereum Foundation, it has become the dominant language for blockchain development, powering the vast majority of DeFi protocols, NFT platforms, and decentralized applications. Solidity's syntax draws from JavaScript, Python, and C++, making it accessible to developers from various backgrounds while incorporating blockchain-specific features like native cryptocurrency handling and gas optimization.

Basic Contract Structure

1// SPDX-License-Identifier: MIT
2pragma solidity ^0.8.19;
3
4contract SimpleStorage {
5 // State variables (stored on-chain)
6 uint256 private value;
7 address public owner;
8
9 // Events (for off-chain indexing)
10 event ValueChanged(uint256 newValue, address changedBy);
11
12 // Modifiers (reusable access control)
13 modifier onlyOwner() {
14 require(msg.sender == owner, "Not owner");
15 _;
16 }
17
18 // Constructor (runs once at deployment)
19 constructor() {
20 owner = msg.sender;
21 }
22
23 // External function (callable from outside)
24 function setValue(uint256 _value) external onlyOwner {
25 value = _value;
26 emit ValueChanged(_value, msg.sender);
27 }
28
29 // View function (reads state, no gas when called externally)
30 function getValue() external view returns (uint256) {
31 return value;
32 }
33}

Key Language Features

Data Types

1// Value types
2uint256 number = 42; // Unsigned integer (256 bits)
3int256 signed = -100; // Signed integer
4bool flag = true; // Boolean
5address wallet = msg.sender; // 20-byte Ethereum address
6bytes32 hash = keccak256("x"); // Fixed-size byte array
7
8// Reference types
9string name = "Token"; // Dynamic string
10bytes data = hex"1234"; // Dynamic byte array
11uint256[] numbers; // Dynamic array
12mapping(address => uint256) balances; // Key-value mapping

Visibility Specifiers

VisibilityContractDerivedExternal
private
internal
public
external

Function Modifiers

1// State mutability
2function read() external view returns (uint256) { } // Reads state
3function calc() external pure returns (uint256) { } // No state access
4function write() external { } // Modifies state
5function deposit() external payable { } // Accepts ETH

Security Features (0.8.0+)

Solidity 0.8.0 introduced built-in safety features:

1// Automatic overflow/underflow checks
2uint256 x = type(uint256).max;
3x += 1; // Reverts instead of wrapping to 0
4
5// Custom errors (gas efficient)
6error InsufficientBalance(uint256 available, uint256 required);
7
8function withdraw(uint256 amount) external {
9 if (balances[msg.sender] < amount) {
10 revert InsufficientBalance(balances[msg.sender], amount);
11 }
12}

Common Vulnerabilities

Reentrancy

1// VULNERABLE
2function withdraw() external {
3 uint256 amount = balances[msg.sender];
4 (bool success,) = msg.sender.call{value: amount}("");
5 balances[msg.sender] = 0; // Updated AFTER external call
6}
7
8// SECURE (Checks-Effects-Interactions)
9function withdraw() external {
10 uint256 amount = balances[msg.sender];
11 balances[msg.sender] = 0; // Update BEFORE external call
12 (bool success,) = msg.sender.call{value: amount}("");
13 require(success, "Transfer failed");
14}

Access Control

1// VULNERABLE - missing access control
2function mint(address to, uint256 amount) external {
3 _mint(to, amount); // Anyone can mint!
4}
5
6// SECURE
7function mint(address to, uint256 amount) external onlyOwner {
8 _mint(to, amount);
9}

Unchecked Return Values

1// VULNERABLE - ignoring return value
2token.transfer(recipient, amount); // May silently fail
3
4// SECURE - check return or use SafeERC20
5require(token.transfer(recipient, amount), "Transfer failed");
6// Or: SafeERC20.safeTransfer(token, recipient, amount);

Gas Optimization Patterns

1// Use calldata for read-only arrays
2function process(uint256[] calldata data) external { } // Cheaper
3
4// Pack storage variables
5struct User {
6 uint128 balance; // Slot 0 (first half)
7 uint128 lastUpdate; // Slot 0 (second half) - PACKED!
8}
9
10// Cache storage reads
11function sum() external view returns (uint256 total) {
12 uint256 len = array.length; // Cache length
13 for (uint256 i = 0; i < len; ++i) { // ++i cheaper than i++
14 total += array[i];
15 }
16}
17
18// Use unchecked for safe math
19function increment(uint256 x) external pure returns (uint256) {
20 unchecked { return x + 1; } // Skip overflow check when safe
21}

Development Tools

ToolPurpose
FoundryTesting, deployment, scripting
HardhatDevelopment environment
RemixBrowser-based IDE
SlitherStatic analysis
MythrilSecurity analysis

Version Considerations

1// Floating pragma (risky for production)
2pragma solidity ^0.8.0; // Any 0.8.x version
3
4// Pinned pragma (recommended)
5pragma solidity 0.8.19; // Exact version

Pinned pragmas ensure the deployed bytecode matches what was audited.

Solidity vs Alternatives

LanguageChainParadigmMaturity
SolidityEVMContract-orientedHigh
VyperEVMPythonic, simplerMedium
RustSolanaSystems languageHigh
CairoStarkNetZK-focusedGrowing

Solidity remains the most widely used smart contract language, with the largest ecosystem of tools, auditors, and documentation. Mastering its security patterns is essential for any blockchain developer or auditor.

Need expert guidance on Solidity?

Our team at Zealynx has deep expertise in blockchain security and DeFi protocols. Whether you need an audit or consultation, we're here to help.

Get a Quote

oog
zealynx

Subscribe to Our Newsletter

Stay updated with our latest security insights and blog posts

© 2024 Zealynx