BTA CBDE cheat sheet
BTA CBDE · Keep the key ideas within reach.
Ethereum Blockchain Development Fundamentals
Account types: EOAs are controlled by a private key and have no code; contract accounts hold code and storage and are driven only by messages they receive.
Transaction cost formula: total fee = gasUsed × effectiveGasPrice, where effectiveGasPrice = baseFee + priorityFee (tip) after EIP-1559.
Block gas limit caps the sum of gas consumed by all transactions in a block; baseFee adjusts per block toward a 50% full target block.
Nonce rules: an EOA nonce increments once per sent transaction and enforces ordering; a contract nonce counts contracts it created (EIP-161 starts at 1).
State is a Merkle-Patricia trie keyed by keccak256(address) and storage slot; the world state root commits to all account balances, nonces, code hashes, and storage roots.
Logs (LOG0–LOG4) are not readable by contracts; topics hold indexed values and data holds non-indexed ABI-encoded values, used for off-chain filtering.
Finality: PoS Ethereum checkpoints justify and finalize epochs (32 slots of 12 s each); a finalized block is reverted only under a slashing-level fault.
EVM execution is deterministic and metered: opcodes cost gas, memory expands quadratically, and a revert undoes state changes but still consumes gas spent.
Smart Contract Development with Solidity
Data location rules: storage persists, memory is per-call and copyable, calldata is read-only call data; reference-type parameters need explicit location (external functions default to calldata).
Visibility: public, external, internal, private. external is cheapest for functions taking calldata arrays; private is not hidden on-chain, only inaccessible to derived contracts.
Payable is required to receive ETH; receive() handles empty calldata, fallback() handles everything else, and a contract without either rejects plain transfers.
Function modifiers run code before and/or after the body via the underscore placeholder; multiple modifiers wrap in declaration order.
Custom errors (error X(); revert X();) are cheaper than require strings and are ABI-encoded as a 4-byte selector plus arguments.
Storage packing: adjacent state variables smaller than 32 bytes share a slot; structs and arrays always start a new slot and cannot be packed across.
Signature checks: ecrecover returns address(0) on failure, so verify the recovered address is nonzero and matches the expected signer; use EIP-191/EIP-712 prefixes to avoid replay.
Arithmetic is checked by default since Solidity 0.8.0; unchecked { } blocks restore wrapping behavior and save gas where overflow is provably impossible.
Ethereum Development Tools and Frameworks
Hardhat runs a local in-process EVM (Hardhat Network) with console.log in Solidity, stack traces, and mainnet forking via forking.url.
Foundry uses forge (build/test), cast (chain interaction), and anvil (local node); tests are written in Solidity and use cheatcodes such as vm.prank and vm.deal.
Truffle is legacy; migrations run in numbered order, and truffle-config.js or hardhat.config.js set networks, compiler versions, and optimizer settings.
Ethers.js v6 providers are read-only (JsonRpcProvider, BrowserProvider) while signers write; Contract objects bind an ABI plus address to a runner.
web3.js and ethers both ABI-encode calls; viem is a typed alternative with tree-shakeable actions and is the default client in modern scaffolds.
solc compiler settings that change bytecode: optimizer runs (lower = smaller deploy, higher = cheaper runtime), viaIR, evmVersion, and metadata bytecodeHash.
Environment variables for keys belong in .env excluded from git; dotenv loads them, and hardhat.config reads process.env with explicit chainId per network.
OpenZeppelin Contracts provides audited primitives (ERC20, ERC721, Ownable, AccessControl, ReentrancyGuard) installed via npm and imported by path.
Decentralized Application (DApp) Architecture and Integration
Layers: wallet (key custody and signing) → provider/RPC (read and broadcast) → contract ABI + address (encode calls) → UI state.
window.ethereum is injected by wallets; eth_requestAccounts triggers connection, eth_chainId identifies the network, and chainChanged/accountsChanged events must be handled.
Reads use eth_call (no gas, no state change); writes use eth_sendTransaction, which returns a tx hash immediately and requires receipt polling for status.
Signer flow: getSigner() resolves the account, contract.connect(signer) binds it; without a signer, state-changing calls throw.
EIP-712 typed data signing (eth_signTypedData_v4) lets users see structured fields; verify on-chain with ecrecover over the domain-separated hash.
Event indexing strategy: subscribe with contract.on(filter) for live UI, and backfill history with queryFilter over bounded block ranges because RPCs cap ranges.
Decimals: ERC-20 amounts are integers scaled by 10**decimals; format with formatUnits for display and parseUnits before sending.
Chain mismatch handling: compare the wallet chainId to the deployed chainId and prompt wallet_switchEthereumChain rather than sending a transaction on the wrong network.
Testing, Security, and Deployment Practices
Reentrancy defense: checks-effects-interactions ordering plus ReentrancyGuard; update balances before external calls and avoid state reads after a call.
Oracle and price risk: never use spot AMM reserves as a price source without manipulation resistance; prefer TWAP or Chainlink with staleness and decimals checks.
Access control: Ownable for a single admin, AccessControl for roles; never leave initializers unguarded - call _disableInitializers() in the constructor of upgradeable implementations.
Test pyramid for contracts: unit tests per function, fork tests against real mainnet state, fuzz/invariant tests for arithmetic and accounting, and gas snapshots for regressions.
Deployment patterns: CREATE address = keccak256(rlp(sender, nonce))[12:]; CREATE2 address = keccak256(0xff ++ deployer ++ salt ++ keccak256(initCode))[12:], enabling deterministic addresses.
Upgradeability: proxy storage layout must be append-only; use ERC-1967 slots and OpenZeppelin upgrades tooling to detect storage collisions before deploying.
Pre-deploy checklist: pinned compiler version, optimizer settings recorded, constructor args verified, ownership transferred to a multisig, and source verified on a block explorer.
Front-running and MEV: commit-reveal schemes and slippage/deadline parameters on swaps mitigate sandwiching; private mempools reduce exposure but do not eliminate it.