1/113
Looks like no tags are added yet.
Name | Mastery | Learn | Test | Matching | Spaced |
|---|
No study sessions yet.
Characteristics of Bitcoin Script
stack-based, simple isntruction set, non-Turing complete (no loops), deterministic
Pay-to-Public-Key-Hash (P2PKH) script pattern
single signature spending requiring a private key
crypto building blocks
hash functions
deterministic, fixed output size, avalanche effect, collision resistance
data integrity verification, digital commitments, proof-of-work puzzles, merkle tree construction
SHA-256 for bitcoin block hashing and transaction verification
digital signitures
identity=public key ownership, unforgeable mathematical proofs of authorization
ECDSA alg: elliptic curve signatures created from private keys providing strong security with small key sizes
control spending authority for utxos
merkle trees
binary tree of hashes enabling efficient inclusion proofs
verify transaction inclusion without downloading entire block
lightweight verification for mobile and constrained devices
Multi-signature (Multisig) script pattern
Requires M out of N signatures for shared custody/governance
Pay-to-Script-Hash (P2SH) script pattern
Complex conditions through referencing a script hash
allow transaction output to be locked by hash of a script instead of a script itself
bitcoin pseudonymous model + transparency-privacy trade-off
public keys serve as pseudonms and all transactions are recorded publicly on the ledger
global verification + audit ability
fundamental trade-off
transparency enables trustless verification
privacy loss from transaction patters\
regulatory implications with public ledges which aid compliance but complicate privacy
Zero-Knowledge proofs
verifies transaction without revealing underlying data
privacy in public
zk-snarks and zk-starks
distributed consensus challenge
network latency - messages between nodes can be delayed unpredictably - difficult to establish consistent global ordering of events and transactions
node failures - individual nodes can fail. overal system needs to stay functional
byzantine adversaries - malicious nodes can send arbitrary or contradictory messages to disrupt consensus or double-spend
no trusted coordinator - no central authority to resolve conflicts and establish canon
core problem - how do thousands of individual nodes connected by unreliable network establish a single consistent view of transaction history without trusted intermediary
Proof of work
get reward through computing valid nonce value
valid nonce when combined with previous block data and hashed should produce a result with a specific number of leading zeros
success probability is proportional to computational power
network accepts chain with most accumulated proof-of-work as canon (longest chain)
easy verification - hard to find nonce, easy to verify
attacking network is not worth the effort. if you have that power it is more profitable to just mine honestly
Halving of block reward
Starting in 2008, starts at 50 btc, divides by half every 4 years. Currently at 3.125
21 million btc cap for scarcity
Difficulty Adjustment Alg
every 2016 blocks (2 weeks at 10-minute intervals), maximum 4x change per adjustment
difficulty adjusts as more computers mine for consistent block times
UTXO Model
transaction inputs consume existing utxos and creates fresh utxos for recipients, returning excess funds as change
each transaction output (utxo) is an indivisible unit. to use portion, need to consume whole amount to create smaller utxos and give change back to yourself
verify signatures and detect double-spending of utxos
bitcoin ledger is just complete set of all unspent transaction outputs (UTXOs)
stateless, new address for each transaction, high parallelization, limited scripting, simple
bitcoin architecture limitations
no global state/account balances
script language without loops or storage
limited to payment-focused applications
secure peer-to-peer payments
multi-signature transactions
time-locked payments
basic escrow conditions
cannot build complex decentralized applications
ethereum’s vision
world computer concept
blockchain is global decentralized computing platform where anyone can deploy and run apps without central control
ethereum virtual machine (EVM)
turing-complete vm unlike bitcoin script
smart contracts and dApps
self-executing programs that run exactly as programmed, enabling decentralized applications
ethereum as a global state machine
current state (complete snapshot of all accounts, balances, and smart contract storage at block N)
V
transaction processing (transactions modify global state according to predefined rules and smart contract logic)
V
new state (updated global state at block N+1 reflecting all processed transactions)
each ethereum node maintains identical copy of the state machine
deterministic state transitions
Account Model
maintains account balances, reused addresses for transactions so lower privacy, limited parallelization, full programmability, complex and flexible
Externally Owned Accounts (EOAs)
controlled by private keys, initiates transactions, no code execution capabilities, used by human users and wallets, has nonce and balance
Contract Accounts
controlled by smart contract code, cannot initiate transactions, only responds to calls, contains executable bytecodes, has storage for persistent data
Nonce
for EOA, transaction counter preventing replay attacks
also a field in transactions
for contracts, number of contracts created
Balance
amount of Ether (in wei) owned by account, contracts can hold Ether
CodeHash
hash of the account’s code, points to executable bytecode, only for contracts
StorageRoot
root hash of the account’s storage trie, contains persistent data for smart contracts
what is ethereum transaction
cryptographically signed instruction from EOA that triggers a state change in ethereum network
transaction creation
eoa creates and signs transaction with private key
network propagation
signed transaction broadcast to ethereum network and enters mempool waiting for inclusion
validation/execution
miners/validators verify transaction signature and execute it, updating global state accordingly
3 main purposes of ethereum transaction
Transfer Ether - sends ETH from one account to another
Call Contract Functions - executes code in existing smart contracts
deploy contracts - create new smart contracts on the network
to (transaction field)
Destination address or recipient (empty for contract creation)
value (transaction field)
amount of ether to transfer
data (transaction field)
contract bytecode or function call data
gasLimit (transaction field)
maximum gas willing to spend
maxFeePerGas (transaction field)
maximum total fee per gas unit
maxPriorityFeePerGas (transaction field)
tip to minors for priority inclusion
Simple Transfer
to: recipient address
value: ETH amount
data: empty
Contract Call
to: contract address
value: ETH (optional)
data: function call
Contract Deployment
to: empty (null)
value: ETH (optional)
data: bytecode
why gas
prevent infinite loops
computation is constly, only valuable operations are executed on global computer
gas overview - metering execution
transaction starts
user pays upfront for gas budget
operations execute
each operation consumes predetermined gas
if gas exhausted
transaction reverts but gas fees still consumed
Upfront payment of gas
gasLimit * maxFeePerGas
Common gas costs
basic operations (add, mul, etc.): 3-5 gas
memory operations: 3-200 gas
storage write: 20000 gas
contract creation: 32000 gas
Total Fee in EIP-1559
GasUsed * (BaseFee + PriorityFee)
max fee = gas limit * max fee per gas
Base Fee
burned by admin to reduce ETH supply and prevent inflation
Priority Fee (Tip)
user-set tip to incentivize minors/validators to include the transaction quickly
EVM Stack
LIFO with maximum of 1024 items, each item is max 256-bits
evm Memory
temporary byte-addressed storage that expands dynamically during execution, cleared after each call completes
evm Calldata
read-only input bytes passed to contract during transaction or call, contains function identifiers and encoded parameters, must be loaded onto stack for processing
Storage
persistent key value map from 256 bit keys to 256 bit values, survives after the call finishes, all slots initially zero
PUSH(1-16)
adds value to ith spot
DUP(1-16)
duplicates ith value to top
SWAP(1-16)
swaps top value with ith value after it
POP
removes top item
Arithmetic OPcodes (add, sub, mul, div, mod, addmod, mulmod)
256-bit modular arithmetic operations wraps at 2^256 on top two values of stack
pops inputs, pushes output
Comparison opcodes (LT, GT, EQ, ISZERO)
compares top two values and produces boolean results
pops inputs, pushes output
Control Flow OPcodes (JUMP, JUMPI, JUMPDEST, REVERT, STOP)
implements conditional and unconditional branching, JUMPDEST marks valid targets
Return OPcodes (RETURN, REVERT)
halts execution and return data (RETURN) or revert state changes (REVERT)
memory, storage, calldata opcodes (mload, mstore, mstore8, sload, sstore, calldataload, calldatasize, calldatacopy)
read and writes to top of stack, store expects key at top, value at 2nd, copy expects destoffset, offset, length
evm data flow
calldata > memory > return
load input from calldata to stack or memory
perform computations using stack operations
store 32-byte words to memory
return results from memory
evm storage (persistent layer)
structure:
key-value store (all 256-bit words)
each contract gets 2²56 storage slots
persistance:
only storage changes persists across transactions
cost
storage operations are most expensive because every node needs to verify and store it
evm data location comparisons
stack
lifetime within call
local scope
low cost (~3 gas)
memory
lifetime within call
local scope
low cost + expansion cost
storage
persistent lifetime
contract-global scope
high cost (2100-22100 gas)
PUSH, DUP, SWAP cost
3 gas
POP cost
2 gas
ADD, SUB, MUL cost
3-5 gas
DIV, MOD cost
5 gas
LT, GT, EQ cost
3 gas
MLOAD, MSTORE cost
3 gas + expansion
SLOAD (warm) cost
100 gas
SLOAD (cold) cost
2100 gas
SSTORE (warm) cost
2900 gas
SSTORE (cold, new) cost
22100 gas
JUMP, JUMPI cost
8 gas
CALL cost
100+ gas (base)
Cold Access
first time accessing a storage slot in a transaction, first time calling a contract address, very high costs, compensates for loading data from disk
Warm Access
subsequent access to same slot/address within transaction, data already cached in memory, lower gas costs (than cold access), rewards batching operations
Read Batching
batch multiple reads from the same storage slot to reduce gas cost by turning cold reads into warm reads
Write Batching
accumulate changes in memory, commit once to storage, minimizes number of SSTORE operations
Cold to warm cost ratio
7.6x
why solidity
bridge to EVM bytecode
solidity source code > compiler translation > bytecode > evm execution
solidity enables the following 3 core capabilities which make ethereum programmable
persistent state management across transactions
programmatic rules that execute automatically
secure value transfer without intermediaries
how is solidity designed with blockchain constraints in mind
determnism
transparency
cost-awareness
what is a smart contract
combo of executable bytecode and persistent data stored at a specific blockchain address
what happens when a smart contract is deployed to the blockchain
bytecode becomes immutable
every interaction with it is transparent and recorded on the blockchain for anyone to audit
its state is persistently stored on the blockchain
how does persistent storage for smart contract states work
state variables are stored in the contract’s dedicated storage root within the Ethereum state trie and is maintained across blocks
describe the proxy pattern where developers can implement upgradability
while the code is immutable, you can use delegatecall to route execution to new logic contracts while preserving the original storage
3 essential components of the standard structure for a Solidity contract
SPDX License Identifier (software license)
Pragma directive (what compiler versions that can compile the code)
Contract block (main container for smart contract code)
example:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
contract SimpleStorage {
// state variables and functions here
}
state variables
stored permanently in blockchain. state maintained across all transactions
cheap to read on chain
very expensive to write
free to read off-chain
public keyword automatically generates a getter function (better transparency)
size of each storage slot
32 bytes, 256 bits
what are the different data locations
storage:
persistent
can read/write
high cost (5k-20k gas per write)
ex: state vars, permanent data
memory:
temporary during function call
mutable within function
low cost (3 gas per word)
ex: local variables, function parameters
calldata:
temporary during external call
read-only
lowest cost (0 copy overhead)
ex: external function inputs, the data field when someone calls a function on your contract, similar to passing by reference?
copy vs reference
storage to memory copies the data in temporary memory and costs high gas
storage reference creates pointer to on-chain data and is more efficient for updates
calldata has no copy.
ex:
function setAge(uint256 newAge) public {
// Creates a storage reference - modifies on-chain state
Profile storage ref = profiles[msg.sender];
ref.age = newAge;
// Creates a memory copy - changes lost after function ends
Profile memory copy = profiles[msg.sender];
copy.age = newAge; // This change is NOT persisted!
}
storage/memory/calldata best practices
storage reference to modify state variables
memory for temporary computations
calldata for external function parameters (especially large arrays)
value vs reference types
value types (copied by value, stored directly in their location)
uint256 (matches EVM native 256 bit word size, most gas-efficient for most operations)
uint8
bool
address (160 bits, 20 byte; used to identify both user and contract accounts)
reference types (passed by reference)
structs
arrays (also strings)
mapping (O(1) key-value lookup but non-iterable (can’t list all keys))
execution context
transactions execute within a context that has info about the caller, transaction, and current blockchain state
solodity shows context with global variables:
msg.sender (address which directly called the current function. used for access control. remains the original caller, not intermediate contract, for delegatecall)
msg.value (amount of wei (1 ether = 10^18 wei) sent with transaction. only accessible in payable functions)
block.timestamp (unix timestamp of current block used for implementing deadlines and time-based logic. miners can manipulate +-15 seconds so not good for precise timing)
function visibility specifiers
modify who can call a function and how
internal:
only callable within contract or derived contracts
helper functions, code reuse with inheritance
external:
only callable from other contracts or EOAs (externally owned accounts)
more gas efficient for functions with large calldata parameters
public
callable from anywhere (both internal and external)
default
private
only callable within defining contract
sensitive helper functions, shouldn’t be inherited
function mutability and payability modifiers
default(modifying)
can read/write state variables
view
can read state but not modify
free when called externally via RPC (off-chain)
pure
cannot read or write
math only
also free when called externally
payable
special modifier for function, address, or constructor to be able to recieve Ether
required for any function where msg.value>0
modifiers and errors
modifiers are reusable code blocks that execute before or after a function.
use require() to validate. if condition is false, transaction reverts, state changes undone, and unused gas is refunded
revert() for manual rollbacks
ex:
modifier onlyOwner() {
require(
msg.sender == owner,
"caller is not owner"
);
_; // Function body executes here
}
function withdraw() public onlyOwner {
// This function can only be called by owner
// The modifier check runs first
}withdraw pattern
checks-effects-interactions principle to prevent reentrancy attacks
always update state before transferring ether
validate preconditions > update state variables > make external calls last
transfer Ether with the call() function
recieve and fallback functions
special for handling ether transfers and unknown function calls
no function keyword
keep simple, limited 2300 gas when called via transfer or send
receive()
triggered when someone sends Ether with no function selector (plain transfer)
must be external payable and no parameters/return
fallback()
triggers when function doesn’t exist or Ether is sent without a receive() function
can be payable or non-payable
how to build modula defi-scale systems beyond single-contract logic
best practices
inheritance - reuse code and create policy layers
events - connect on and off-chain systems, transparency
libraries+guards - enable safe code reuse. use nonReentrant to protect against reentrancy attacks and value transfers
interfaces - build protocol composability. cross-protocol calls
avoid loops over user lists - can exceed gas limits
fork-test mainnet integrations - test on real protocol state before deployment
why inheritance
encapsulate reusable behavior (ownable, erc20)
define clear hierarchies
reduce duplication, redundant code
Ownable
inherit from Ownable base contract which has modifier that checks only the owner can access the function
inheritance keywords
virtual - allow override
override - replace parent implementation
super - extend, not rewrite (use parent’s implementation)
why events
smart contracts ahve no way to proactively notify external systems of state changes
emit events to create on-chain logs that are cheap and queryable
use for frontend updates, indexers, analytics dashboards, etc
always emit after state change. ensure events reflect actual final state to maintain data integrity
events example
event Deposit(address from, uint amount);
function deposit() external payable {
emit Deposit(msg.sender, msg.value);
}vault.on("Deposit", (from, amount) => {
console.log(`${from} deposited ${ethers.formatEther(amount)} ETH`);
});why libraries
reuse common logic with stateless helper functions
cleaner than inheritance. don’t add to contract size
trusted
examples:
SafeMath - prevent overflow
ReentrancyGuard - nonReentrant modifier for mutex, atomic functions