info@cyberlawacademy.com | +91-XXXXXXXXXX
Part 2 of 7

Solidity Programming Basics

Learn essential Solidity syntax and concepts enabling legal professionals to read smart contract code, conduct due diligence, and understand technical specifications in audit reports.

[T] ~120 minutes [S] 5 Sections [C] 12 Code Examples

2.1 Solidity Overview

Solidity is the dominant programming language for Ethereum smart contracts. As a legal professional, understanding Solidity enables you to read contract code, identify potential issues during due diligence, and communicate effectively with technical teams.

Solidity
A statically-typed, contract-oriented programming language designed for implementing smart contracts on Ethereum and EVM-compatible blockchains. Influenced by JavaScript, Python, and C++.

Why Legal Professionals Should Learn Solidity

  • Due Diligence: Review code to verify it matches documentation and legal agreements
  • Risk Assessment: Identify potential vulnerabilities or problematic patterns
  • Dispute Resolution: Understand what the code actually does vs. what parties expected
  • Client Communication: Bridge the gap between technical and legal teams
  • Regulatory Compliance: Assess whether code behavior complies with regulations

Basic Contract Structure

Solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

/// @title Simple Storage Contract
/// @notice Demonstrates basic Solidity structure
contract SimpleStorage {

    // State variable - stored on blockchain
    uint256 private storedValue;

    // Event - logs activity for off-chain monitoring
    event ValueChanged(uint256 newValue, address changedBy);

    // Function - modifies state (costs gas)
    function setValue(uint256 _value) external {
        storedValue = _value;
        emit ValueChanged(_value, msg.sender);
    }

    // View function - reads state (free when called externally)
    function getValue() external view returns (uint256) {
        return storedValue;
    }
}
Key Structure Elements

SPDX License: Required license identifier
Pragma: Specifies compiler version
Contract: Similar to a class in OOP
State Variables: Data stored on blockchain
Events: Logging mechanism for off-chain applications
Functions: Executable code units

2.2 Data Types

Value Types

TypeDescriptionExampleLegal Relevance
uint256Unsigned integer (0 to 2^256-1)uint256 balance = 1000;Token amounts, timestamps
int256Signed integerint256 change = -50;Price changes, adjustments
boolTrue or falsebool isActive = true;Status flags, permissions
address20-byte Ethereum addressaddress owner;User identity, ownership
bytes32Fixed-size byte arraybytes32 hash;Document hashes, IDs
Critical: Integer Overflow

Prior to Solidity 0.8.0, integers could overflow silently (e.g., 255 + 1 = 0 for uint8). This caused numerous exploits. Always verify contracts use Solidity 0.8+ or SafeMath library.

Reference Types

Solidity
// Arrays - ordered collections
uint256[] public dynamicArray;
uint256[10] public fixedArray;

// Mappings - key-value storage (like dictionaries)
mapping(address => uint256) public balances;
mapping(address => mapping(address => uint256)) public allowances;

// Structs - custom data structures
struct Agreement {
    address partyA;
    address partyB;
    uint256 amount;
    uint256 deadline;
    bool executed;
}

Agreement[] public agreements;
Legal Due Diligence: Data Structures

When reviewing contracts, examine how data is stored. Mappings cannot be iterated - if a contract needs to enumerate all users, it must maintain a separate array. This affects functionalities like airdrops, refunds, or mass distributions.

Special Variables

VariableTypeDescription
msg.senderaddressAddress that called the function
msg.valueuint256ETH sent with the transaction (in wei)
block.timestampuint256Current block timestamp (can be manipulated +/- 15 seconds)
block.numberuint256Current block number
tx.originaddressOriginal transaction sender (avoid using!)

2.3 Functions and Modifiers

Function Visibility

VisibilityWho Can CallUse Case
publicAnyone (internal + external)General access functions
externalOnly from outside the contractAPI endpoints
internalThis contract + derived contractsShared logic in inheritance
privateOnly this contractImplementation details
Private Does Not Mean Secret

All blockchain data is public. "Private" only restricts which contracts can call a function - the data is still visible to anyone reading the blockchain. Never store sensitive information on-chain.

Function Modifiers

Solidity
contract AccessControl {
    address public owner;
    bool public paused;

    // Custom modifier - reusable access control
    modifier onlyOwner() {
        require(msg.sender == owner, "Not authorized");
        _; // Placeholder for function body
    }

    modifier whenNotPaused() {
        require(!paused, "Contract is paused");
        _;
    }

    // Function with multiple modifiers
    function sensitiveAction() external onlyOwner whenNotPaused {
        // Only executes if both modifiers pass
    }

    function pause() external onlyOwner {
        paused = true;
    }
}

State Mutability

  • No keyword (default): Can read and write state, costs gas
  • view: Can only read state, free when called externally
  • pure: Cannot read or write state, only uses inputs
  • payable: Can receive ETH with the transaction
Solidity
function transfer(address to, uint256 amount) external {
    // Modifies state - costs gas
    balances[msg.sender] -= amount;
    balances[to] += amount;
}

function getBalance(address account) external view returns (uint256) {
    // Only reads - free when called externally
    return balances[account];
}

function calculateFee(uint256 amount) external pure returns (uint256) {
    // No state access - pure computation
    return amount * 3 / 100; // 3% fee
}

function deposit() external payable {
    // Can receive ETH - msg.value contains amount
    balances[msg.sender] += msg.value;
}

2.4 Common Patterns for Legal Review

Ownership Pattern

Most contracts implement ownership for administrative control. Review who can change ownership and what powers the owner has.

Solidity
contract Ownable {
    address public owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor() {
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Ownable: caller is not the owner");
        _;
    }

    function transferOwnership(address newOwner) public onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }

    // DANGEROUS: Owner can renounce ownership permanently
    function renounceOwnership() public onlyOwner {
        emit OwnershipTransferred(owner, address(0));
        owner = address(0);
    }
}
Due Diligence Checklist: Ownership

1. Who is the initial owner?
2. What functions are restricted to the owner?
3. Can ownership be transferred? To whom?
4. Is there a renounceOwnership function? What happens if used?
5. Is there a timelock on ownership changes?

Pausable Pattern

Solidity
contract Pausable is Ownable {
    bool public paused;

    event Paused(address account);
    event Unpaused(address account);

    modifier whenNotPaused() {
        require(!paused, "Pausable: paused");
        _;
    }

    modifier whenPaused() {
        require(paused, "Pausable: not paused");
        _;
    }

    function pause() external onlyOwner whenNotPaused {
        paused = true;
        emit Paused(msg.sender);
    }

    function unpause() external onlyOwner whenPaused {
        paused = false;
        emit Unpaused(msg.sender);
    }
}
Legal Risk: Pause Functions

Pause functions give owners the power to freeze user funds or prevent withdrawals. This creates significant counterparty risk. In legal terms, this may constitute potential breach of fiduciary duty if misused.

ERC-20 Token Standard

The most common smart contract standard. Understanding ERC-20 is essential for token-related legal work.

Solidity - ERC-20 Interface
interface IERC20 {
    // Returns total token supply
    function totalSupply() external view returns (uint256);

    // Returns account balance
    function balanceOf(address account) external view returns (uint256);

    // Transfer tokens to recipient
    function transfer(address to, uint256 amount) external returns (bool);

    // Check spending allowance
    function allowance(address owner, address spender) external view returns (uint256);

    // Approve spender to use tokens
    function approve(address spender, uint256 amount) external returns (bool);

    // Transfer from another account (requires allowance)
    function transferFrom(address from, address to, uint256 amount) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

2.5 Gas Optimization

Gas costs directly affect usability and economics of smart contracts. Understanding gas optimization helps identify efficient vs. wasteful contract designs.

Storage vs. Memory vs. Calldata

LocationPersistenceGas CostUse Case
storagePermanent (on-chain)Very High (20,000 gas for new slot)State variables
memoryFunction execution onlyLow (3 gas per word)Local computations
calldataFunction execution onlyLowest (read-only)External function parameters

Gas Optimization Techniques

Solidity - Before Optimization
// INEFFICIENT: Multiple storage reads
function inefficientSum() external view returns (uint256) {
    uint256 total = 0;
    for (uint256 i = 0; i < values.length; i++) {
        total += values[i]; // Storage read each iteration!
    }
    return total;
}
Solidity - After Optimization
// EFFICIENT: Cache in memory
function efficientSum() external view returns (uint256) {
    uint256[] memory _values = values; // Single storage read
    uint256 total = 0;
    uint256 length = _values.length; // Cache length
    for (uint256 i = 0; i < length; ) {
        total += _values[i];
        unchecked { ++i; } // Skip overflow check (safe here)
    }
    return total;
}
Red Flags for Inefficiency

Watch for: loops over storage arrays, repeated storage reads of the same variable, string comparisons, unnecessary state variables. High gas costs may indicate poor design or intentional barriers to user actions.

Key Takeaways

  • Solidity knowledge enables legal professionals to conduct meaningful technical due diligence
  • Private does not mean secret - all blockchain data is publicly readable
  • Review ownership patterns and pause functions for centralization risks
  • Understand ERC-20 standard for token-related legal work
  • Gas costs affect contract usability - high costs may be intentional barriers
  • Always verify Solidity version (0.8+ has built-in overflow protection)