Your First Contract & Deployment

Never paste a real private key on the command line; use cast wallet import (encrypted keystore) with --account, or a hardware wallet (--ledger).

5.1 Hello World

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/// @title A simple greeting contract
/// @notice Stores a greeting that anyone can read and the owner can update
contract HelloWorld {
    string public greeting;          // `public` auto-generates a getter greeting()
    address public immutable owner;

    event GreetingChanged(address indexed by, string newGreeting);

    error NotOwner();

    constructor(string memory initialGreeting) {
        greeting = initialGreeting;
        owner = msg.sender;           // the deployer
    }

    function setGreeting(string calldata newGreeting) external {
        if (msg.sender != owner) revert NotOwner();
        greeting = newGreeting;
        emit GreetingChanged(msg.sender, newGreeting);
    }
}

5.2 Deploy in Remix

Create HelloWorld.sol, paste the code.

Solidity Compiler tab → choose 0.8.x → Compile.

Deploy & Run tab → Environment "Remix VM" → enter "Hello" next to Deploy → click Deploy.

Expand the deployed contract: click greeting (free call), call setGreeting (a transaction — note the gas used in the console).

Switch Environment to "Injected Provider - MetaMask" with Sepolia selected to deploy to a real testnet.

5.3 Deploy with Foundry

Never paste a real private key on the command line; use cast wallet import (encrypted keystore) with --account, or a hardware wallet (--ledger).

anvil &                                   # local node
forge create src/HelloWorld.sol:HelloWorld \
  --rpc-url http://127.0.0.1:8545 \
  --private-key $ANVIL_KEY \
  --broadcast \
  --constructor-args "Hello"
cast call $ADDR "greeting()(string)" --rpc-url http://127.0.0.1:8545
cast send $ADDR "setGreeting(string)" "Hi!" --private-key $ANVIL_KEY --rpc-url http://127.0.0.1:8545

5.4 What the compiler produces

Creation (init) bytecode runs once at deployment: executes the constructor and returns the runtime code stored on-chain at the contract address describes functions, events, errors — used by wallets, frontends, other tools compiler version, settings, source hashes (used for verification) slots and offsets of state variables

5.5 How a function call works

Calldata = 4-byte selector (first 4 bytes of keccak256("setGreeting(string)")) + ABI-encoded arguments. The compiled contract's dispatcher compares the selector against each external function and jumps to the matching code; if none matches it runs fallback (or reverts).