Session 02.3
ImplementationCONTRACT
DEVELOPMENT.
From architecture to deployment. A technical walkthrough of writing, compiling, and interacting with production-grade Ethereum smart contracts.
LIFECYCLE_INIT
Contract Deployment Cycle
Ethereum smart contracts are immutable programs. Once deployed, their logic cannot be altered, only interacted with.
Deployment Sequence:
1. Development: Write Solidity in an IDE (Remix/Hardhat).
2. Compilation: Convert high-level code to EVM Bytecode & ABI.
3. Signing: Sign the deployment transaction with a wallet (EOA).
4. Broadcast: Send to the network; miners/validators verify.
Counter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Counter {
uint256 public count;
event Incremented(uint256 newCount);
// Initializer
constructor() {
count = 0;
}
// State Modifier
function increment() external {
count += 1;
emit Incremented(count);
}
}INTERFACE_LAYER
Remix & Web3.js Interaction
Remix IDE is the standard playground for testing. For production apps, we use libraries like Web3.js or Ethers.js to bridge the frontend with the blockchain.
Key Interfaces:
- ABI (Application Binary Interface): JSON that tells your app how to talk to the contract.
- Provider: Connection to an Ethereum node (e.g., Infura, Alchemy).
- Signer: The account paying gas for write operations.
dapp.js
const Web3 = require('web3');
const contractABI = require('./CounterABI.json');
// Initialize Contract Instance
const contract = new web3.eth.Contract(
contractABI,
'0x123...abc' // Deployed Address
);
// Call: Read Data (Free)
const value = await contract.methods.count().call();
// Send: Write Data (Costs Gas)
await contract.methods.increment().send({
from: userAddress
});DATA_STRUCTURES
Complex Logic: Registry Pattern
A practical example demonstrating standard Solidity patterns: Mappings for O(1) lookups, Structs for data grouping, and Events for indexing data off-chain.
This pattern is foundational for Identity Systems, Token Registries, and DAOs.
StudentRegistry.sol
contract Registry {
struct Record {
string name;
bool isActive;
}
// O(1) Lookup Table
mapping(address => Record) public records;
address public admin;
modifier onlyAdmin() {
require(msg.sender == admin, "ACCESS_DENIED");
_;
}
function register(address user, string memory name) external onlyAdmin {
records[user] = Record(name, true);
}
}RISK_MANAGEMENT
Security Architecture
Security is not an add-on; it is architectural. A single reentrancy bug can drain millions.
Defense Strategy:
- Checks-Effects-Interactions: Update state *before* making external calls.
- Reentrancy Guards: Mutex locks for critical functions.
- Access Control: Strict ownership models.
Security.sol
// Prevents recursive calling attacks
bool internal locked;
modifier nonReentrant() {
require(!locked, "REENTRANCY_DETECTED");
locked = true;
_;
locked = false;
}Deployment Checklist
Compile contracts to check for syntax errors (ABI generation).
Ensure all state variables are packed to optimize gas.
Verify modifiers are applied to restricted functions.
Use Reentrancy Guards on all functions handling ETH transfer.
Test interaction scripts on a local fork before mainnet.