Skip to content

Instantly share code, notes, and snippets.

@aquaflamingo
Last active May 15, 2019 17:06
Show Gist options
  • Save aquaflamingo/9dec538df64cc64bb4944cba78be76b8 to your computer and use it in GitHub Desktop.
Save aquaflamingo/9dec538df64cc64bb4944cba78be76b8 to your computer and use it in GitHub Desktop.
Notes from Mastering Ethereum

Mastering Ethereum

By Andreas M. Antonopoulos, Dr. Gavin Wood

Available under at Creative Commons CC-BY-NC-ND license and readable at Mastering Ethereum

Mastering Ethereum - Chapter 1

Ethereum is:

  • unbounded (turing complete)
  • determinisic
  • a state machine
  • globally accessible singleton Smart contracts are computer programs that provide:
  1. highly availability
  2. auditability
  3. transparency
  4. neutrality
  5. reduced counter party risk
  6. censorship resitance

Blockchain components:

  • P2P network that propegates transactions and blocks
  • Messages that represent state transitions
  • Consensus rules governing valitiy of state transitions
  • A state machine processing the transactions
  • Chain of cryptgrapphically secure blocks
  • Consensus algorithm with decentralized control
  • Game theoretic incentive scheme to maintain the ledger
  • Multiple open source client implementations

Ethereum's Blockchain

  • Ethereum is general purpose it tracks the changes in code and data overtime
  • Ethereum runs a virtual machine to execute code called the Ethereum Virtual Machine
  • The state data for etheruem is tored in a serialized hashed data structure called a Merkle Patricia Tree
  • Ethereum uses a metered resource called gas to avoid infinite loops
    • Each instruction has a cost in gas
    • transactions specify the max gas limit which if the EVM reaches

Mastering Ethereum - Chp 10

  • Tokens can represent:
    • Currency
    • Resource Claims
    • Equity
    • Voting
    • Access
    • Collectibles
    • Identity
    • Attestation (Signatures)
    • Utility (Payment)
  • Can be fungible (non-unique) or non-fungible (unique)
  • Some tokens are native to the blockchain and therefore have the lowest counter party risk
    • e.g. Purely blockchain based tokens, opposed to tokens which bridge chain to real world
  • One critica role of token is converting extrinsic assets into intrinisc (native) assets
  • ETH transactions are handled at the protocol level whereas Tokens are processed at the contract level

Types of Tokens

  • Utility Tokens: Use of token is required to access a resource
  • Equity Tokens: Represents a control or ownership of something

ERC20 Tokens

  • A fungible token standard
  • Is a common interface for tokens
    • (functions): totalSupply, balanceOf, transfer, transferFrom, approve,allowance
    • (events): Transfer, Approve
  • A token contract is essentially two internal mappings:
    • Balances: `address=>int)
    • Allowances: address=>(address=>int)) // used for delegation
  • Developers should be mindful in programming to accept ERC20 tokens, because if the contract does not have ERC20 functionality the tokens will be lost forever -- approx ~$2.5 USD lost this way so far
  • Nuances:
    • Unlike ETH, there are no receipient addresses
      • The token contract manages all the mappings and state of accounts
    • Tokens are send via the TokenContract.transfer, not send
    • Sending tokens requires ETH

ERC223

  • Another standard to prevent sending tokens to ERC20 incompatible contracts
    • A check to determine whether the destination address is a contract or not
      • e.g. does it have a tokenFallback function

ERC777

  • Support for an extended ERC20 interface, with support for ERC820 token registraries
  • Includes
    • various "hooks" for receiving notifications
    • proxy support
    • Metadata

ERC721 (deeds)

  • "Deed" contracts representing ownership of a unique thing
  • Mapping has an "owner" rather than a balance
  • Optional: MetaDataInterface (indexable interface)

Final thoughts

  • Standards exists to promote interopeability
  • Additional extensions include:
    • Burning
    • Minting
    • White / Black listing
    • Ownership
    • Crowd funding
    • Caps
    • Recovery

Mastering Ethereum - Chp 11

  • Oracles Provide external data source to smart contracts
  • Oracles are needed becasue the EVM execution must be deterministic
    • There is no randomness interally
    • External data can only be included in the data payload
  • Oracles "act as a bridge" to extend the real world or chain world
  • Data uses include:
    • Randomness
    • Exchange Rates
    • Political Events
    • Geolocations
    • Flights Stats

Design patterns

  • Functionally:
    • Collecting data from an offchain source
    • Transfering data on chain
    • Making data available by placing in storage for contracts to access

Types

  • Immediate Request: a one time query for a value (e.g. is over 21?)
  • Pub-Sub: An RSS feed type that pulls data from offchain
  • Request Response:
    • Data set is too large to be stored on chain
    • Can world via requesting the oracle and observing result as an EVM state change

Authentication

There are a few ways to prove authenticity of an oracle's data

  • Authenticity Proofs: Cryptographic guarantees that data has not been tampered with
    • Oracalize's TLSNotary Proof (proof of HTTPs communication between client and server

Computation

  • Oracles that perform infeasible on chain computation
  • e.g. Oracalize deploys a user configred docker container to AWS which performs computation and writes values to stdout to return to the requesting dapp
    • Centralized by auditable
  • Cryptlets are a standard

Mastering Ethereum - Chp 12

  • Web3 encompasses and attempts to decentralize: messaging, storage and naming
  • Core benefits of DApps
    • Resiliency
    • Transparency
    • Censorship Resistance

DApp Stack

  • Business Logic = Smart contracts
  • Messaging = Whisper
  • Storage = IPFS/Swarm

Ethereum Name Service

  • Domain Name System

Bottom Layer (Nodes)

  • Operates nodes creating by the namehash algorithm
  • EIP137
    • Only nodes can set their names and subdomains
    • Nodes are traversed by recursively hashing and resolving the higher domain:
keccack(keccack(0x00 + keccack("eth")+keccack("example"))
  • Currently the root TLD (which is required to resolve anything is owned by a 4-7 multisig
  • Resolver contracts are user-controlled and set-able by domain owners to resolve metadata an information about domain

Middle Layer (.eth Nodes)

  • Names are distributed through a vickory auction (Sealed bids)
  • Winner pays second highest big
  • In ENS:
    1. User's lock funds
    2. Must submit two transactions (submit bid + commit/reveal)
    3. Reveal bid or risk fund loss

Top Layer

  • Domain names lock an amount of ETH as a commitment for one year

ENS Resolvers

  • Resolver contract addresses are returned after ENS hashes the node (if it exists)
  • There is a default resolve if none is supplied which can point to wallets or swarn addressess

Mastering Ethereum - Chp 13

EVM

  • EVM is a "quasi" turning complete state machine
  • Stack Based
  • 256 bit words
  • ROM for code storage
  • Has no scheduling capacity (single threaded)
  • Role of EVM is to update state by valid state transitions

Ethereum State

  • Ethereum World State is a mapping of 160bit address to accounts
  • Accounts represent:
    • Balance (ETH)
    • Nonce
    • (Contracts) Storage
    • (Contracts) Code

Deployment

  • When a contract is executed a "sandboxed" EVM is instantiated and performs the computation
    • In the event of a reversion, the EVM is destructed and no state change occurs to the global state
    • If the code complete, the global state machine copies the state change occuring from the sandboxed EVM
  • When creating a new contract the code in the data field is used to instantiate an EVM instance with the data loaded into program ROM

Contract Execution

  • When a transaction is sent to an ABI compatible contract
    • Dispatcher is called to read the data field
    • The first 4 bytes are extracted
    • The stack machine then evaluates each function signature (4 bytes of keccak hash) searching for prototype
    • jumps to that execution if it exists otherwise exits with STOP

Gas

  • Ethereum gees are calculated based on computation
  • Gas PRICE: is exchange rate in units of gas per ETH
  • Gas COST: is the total amount of units consumer for the operation
  • Deleting stored values is encouraged and therefore gas is refunded for doing so
  • The Block gas limit is the maximum number of gas that can be consumer in a single block
    • ~ 8 million or 380 send transactions (21k gas)
    • Miners can vote to increase or decrease the gas limit based on network demands

Mastering Ethereum - Chp 14

  • Proof of Work (POW): ETHash
    • Hashimoto-Dagger algorithm
    • Generates a larger DAG structure to make hashing memory hard (ASIC resistance)
  • Proof of Stake (POS): Casper
    • Small deposit of ETH is made to become a validator and propose blocks
    • Lose stake if block is rejected
    • Earn rewards proptional to stake if block accepted

Mastering Ethereum - Chapter 2

  • Ethereum has a native currency called ether, ETH, Ξ, (greek Xi)
    • The smallest unit is Wei 1018 which is used everywhere interally
    • gwei = gigawei = 109
  • Ethereum is account based rather than UTXO based (Bitcoin)
  • Two types of accounts in Ethereum:
    • Externally Owned Accounts: Does not have contract code, has a private key
    • Contract Accounts: Contain executable code, does not have a private key
      • Contracts are owned by their logic (e.g. they can set whoever is the owner)
      • They have no private key so they cannot initiate state transitions, but can react to them
  • When a transaction is sent to a contract account, the EVM is run using the transactions *data payload.
    • transaction objects specify function names in their data field that is used to run the contract

Simple Contract: Faucet

  • msg object is one of the input accessible by a smart contract
    • it is part of the transaction that triggers execution of the contract
  • fallback function
    • this function is executed when a transaction is made without specifying the function to be called
    • it acts as the "fallback" and is used to accept ether deposits (as long as it's marked payable)

Creating a Contract on Chain

  • Contract creation is registered by creating a transaction with destination address to the zero address. (0x0).
  • When a contract sends some of it's balance to an EoA it is considered an "internal transaction" message (you can see the difference on Etherscan)

Mastering Ethereum - Chapter 3

  • Ethereum clients are interoprable so long as they follow the same reference specification (e.g. Yellow paper)
  • Remote Clients: MyCrypto, MetaMask communicate with existing networks
  • Light Clients: Simple Payment Verification (SPV), validate block headers and merkle proofs to verify a transaction is included in a block
  • Fullnodes: Download and validate the entire blockchain
    • The fullnode is set to prune in default mode and is therefore ~80-100GB
    • A fuly archival node is 1TB
    • Clients include: Parity (Rust), Geth (Go)
    • DDue to a DoS attack @ block 2283397 fullnode syncing will stall until block 2700000
    • Fast syncing is available via --fast

JSON RPC

  • HTTP Service offered on port 8545
  • Client libraries essentially stub and construct RPC calls in JSON format under the hood
  • RPC Calls include
jsonrpc: version (usually 2.0)
method: method to call
params: arguments to pass along
id: used to correlate calls (usually for batching calls)

Mastering Ethereum - Chapter 4

  • Ethereum uses digital signatures to authorize the movements of funds - the "crypto" in cryptocurrencies
  • Fundamental property of cryptography: easy to go one way, hard to compute the inverse
    • This enables digital signatures and secrets
  • Trap door functions: crypto functions that are hard to invert unless one has a secret piece of information
  • Discrete logrithm problem: is a difficult problem and is needed to undo elliptic curve multiplication in Elliptic Curve Cryptography (ECC)
    • Results a good property which is elliptic curve multiplication is easy but opposite is hard

Creating Private Keys

  • The search space of Ethereum private keys is 1 - 2<sup>256></sup> (256 bits or 64 hexadecimal digits)

  • To create a privKey we feed a large random number (entropy) into the keccak256 hashing function

    • Aside: keccak256 preceeded sha3 but the NIST did not finish standardizing sha3 during Ethereum's development, which is why keccak256 is used
  • Creating a Public key:

K (pubKey) = k (privKey) * G (generator point constant) 

Note *: denotes elliptic curve multiplication not arithmatic, it is only one way The reverse action is to find the discrete logirithm

  • Ethereum uses the secp256k1 curve (generator point G)

    • Note that G is constant in Ethereum therefore the same pubKey is always generated
  • ECC Addition:

    • P3 = P1 + P2
    • Geometrically is the line drawn through P1, P2 that intersects the curve at exactly one point P3', then the reflection accross the x-axis resulting in P3 ECC Addition
  • ECC Multiplication:

    • Arithmatically: d x P = P1 + P2 + P3 ... + Pd-1 + Pd (e.g. addition d times)
  • The Public Key (K) and Private Key (k) are just points on the curve: e.g. K = (01234567,09876542)

  • Ethereum only uses uncompressed keys (0x04 prefix)

Addresses

  • Addressess are unique identifiers derived from public keys using the keccak256 hasing function and then taking the last 20 bytes
    • pubKey: (x,y) -> concatenated xy -> keccak256 -> last 20bytes
  • By default addresses are not check sumed
    • EIP55 introducing check sums
  • Addressess are compatible with ICAP protocol (which is compatible with IBAN, bank name protocol)

Mastering Ethereum - Chapter 5

  • Wallets are a basic data structure to manage a user's keys
    • ! Wallets only hold keys not tokens

Non-deterministic Wallets

  • Just a bunch of keys (JBOK)s in a store
  • geth generates a keystore.json file: a JSON payload of the private key
    • uses a password stretching function ("KDF", Key derivation function)
    • repeatedly hashes to stretch thereby preventing brute force/ rainbow table attacks
    • (e.g need to hash n times for each password attempt)

Deterministic Wallets:

  • Keys are related from a common seed.
    • Use a key derivation algorithm to derive, the most common being BIP32/44
  • HD Wallet (BIP32)
    • A tree datastructure where parents derive child keys using an key derivation algorith,
      1. Allows an organized structure for keys
      2. Allows child public keys to be generated from children (creating watch only addresses from xpub keys)
  • BIP39: Mnemonics
    • Mnemonic words are used to generate a seed
    • A word represents a random number used to construct a seed (entropy mapped to 11 bit map to words)

Ex. (not accurate)

   00000000000    army
   00000000001    abandon
  • Entropy of mnemonic (128-256 bits) is stretched to 512 bits via PBKDF2 using arguments mneonmic and salt
    • Seed is completed after 2048 rounds of hashing with HMA-SHA512 to prevent brute forcing
    • the salt is an optional passphrase which if incorrect (frmo the original) leads to a different set of keys
      1. Good for a second factor security
      2. An "under durress" walet
  • BIP43
    • A standard to include a "purpose" as the first child hardened key for the derivation paths
    • Allowing orginzation and specific types of HD wallet trees
    • e.g. m/43' is a different tree structure from an m/44'
  • BIP44
    • Extension pf BIP43"
 m / purpose' / coin' / account' / is_change / address_index
  • m = master private key
  • M = master public key
  • Ethereum is m/44'/60'/0/0*/index (* Ethereum is always receiving)
  • The structure let's us create extended public keys too, allowing downstream derivation of child keys
   Parent Pub -
                \
   Child Priv --> Child public 
  • Great for Cold Storage

Mastering Ethereum - Chapter 6

  • Transaction are signed messages originating from an Externally Owned Account (EoA)
    • They are the only way to mutate state of Ethereum
  • Structure
    • Nonce: A sequence number by the original EoA (for replay protection)
    • Gas Price: The price in (ETH) willing to pay for gas
    • Gas Limit: The maximum gas to buy for this transaction
    • Recipient: The destination of the transaction
    • Value: The value contained
    • Data: A bytecode payload
    • v, r , s: ECDSA Signatures used to derive the public key
  • Transaction are serialized with Reverse Length Prefix (RLP) format, which has no delimiters or labels.

Nonce

Nonce is a dynamically calculated value of the number of confirmed transactions from the originating EoA

  1. Allows proper transaction ordering → Nonce too high is stuck in mempool ignored
  2. Prevents replay attacks on transactions
  • You can fetch the transaction count via getTransactionCount
  • Beware of nonce gaps:
    • e.g. Two transactions Txnonce 0 & Txnonce 2.
    • Txnonce 2 is stuck in mempool until node receives the preceding Txnonce 1.

Transaction Gas

gas is a separate virtual currency that is NOT Ether that is paid for computation in fees to miners

  • Gas has it's own exchange rate per Ether
  • It allows separation from the volatility of ether value
  • Gas Limit: is the gas unit order size
  • Gas Price: Wei per gas unit
  • Simple payment transactions require 21,000 gas
    • Contract executions are variable and not preset
  • A good analogy:
    • A credit account for the gas station with payment only sent on completion

Transaction Value and Data

There are three basic types of transactions:

  1. Value only (Payment)
  2. Data only (Invocation)
  3. Value & Data (Payment and Invocation)

Value Sending Paths

  • value to EoA: Updates the state of destination address with value sent
  • value to Contract:
    1. Calls function in data payload
    2. Fallback function if no function specified in data payload
    3. Increase the contract balance if no fallback function is defined

Data Sending Paths

  • data to EoA: Usually not interpreted
  • data to Contract: calls function specified in data payload.
    • data transactions are subject to consensus rules

Data Payload

  • The data payload of a transaction is a hex serialization of:
    1. Function selection → first 4 bytes of keccack256 hash of function prototype [e.g. withdraw(uint amount)]
    2. Arguments → hex encoded to Application Binary Interface (ABI) spec e.g.
  |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ ... _ _|
       8 bytes.                              32 bytes                                variable
         1.                                  Padding                                    2.
  • Contract creation is a special kind of transaction at destination address 0x0 (zero address)
    • The transaction contains the compiled bytecode as data

Transaction Data Signatures

Digital signatures perform three functions:

  1. proves owner of private keys (and as a result he autorization to spend or execute functions)
  2. Proof of authorization is undeniable
  3. Proof that data has not / cannot be modified
  • The signature in Ethereum is:

    • the keccak256 hash of RLP encoded data for the transaction

    Sig = Fsig(Fkeccack256(m),k) = (r,s) where Fsig is the signature algorithm Fkeccack256 is keccack256 hashing function m is the message to hash (transaction) k is the private key r is the resulting x coordinate of the ephemeral private key created during the signature process

  • To verify signatures one needs:

    1. The public key that "signed" the message
    2. The serialized transaction to verify
    3. The signature parameters (r,s)
Algorithm::create_ethereum_signed_tx

1. Construct a transaction, tx, with:
  data
  gasLimit
  gasPrice
  nonce
  to
  value
  chainID
  0,0

2. Serialize the transaction in RLP format:
   rlp_encoded_tx = rlp_encode(tx)
   
3. Take the keccack256 hash of the payload in (2):
   hash = keccack256(rlp_encoded_tx)
 
4. Sign the hash with an EoA private key
   sig = sign(hash, privKey)
   
5. Append the v, r, and s values to tx

(The tx is now signed)
  • EIP155: Replay Protection

    • The parameters chainID, 0, 0 included in the original unsigned tx prevents chainID tampering and attestation as to the network which the transaction was broadcast and intended
  • Public Key Recovery (v) Parameter

    • When we compute the recovery of a signers public key, the curve is symmetric, so we can compute two possible keys R, and R'
    • So avoid this duplicate work, the signing algorithm returns v where:
      • if v is odd, use R'
      • else use R

Mastering Ethereum - Chp 7

  • A *smart contract was originally defined by Nick Szabo to be

A set of promises specified in digital form in which the parties perform on eachother's promises

  • In Ethereum:

Immutable deterministic computer programs that run in a limited context of the Ethereum Virtual Machine (EVM) on a world computer (e.g. propegated to a global state)

  • Unlike EoAs, contracts do not have private keys and can only run when invoked by a transaction.
  • Contracts cannot run in parallel since Ethereum s a single threaded state machine
  • Transactions are atomic with state changes recorded only if execution is successful (e.g. there is no error)
    • Errors trigger state rollbacks reverting all state changes in value except for gas fees
  • Contracts cannot be modfied but can be deleted via op code: SELFDESTRUCT
    • The original program must have this functionality programmed in however.

Ethereum Languages

  • The EVM runs EVM Bytecode
  • Coding in ethereum should prefer functional (declarative) programming over imparative (procedural)
  • Solidity is procedural and the de facto language today

Ethereum ABI

  • Application Binary Interface: defined the contract for how data structures and function are accessed by machine code
    • Defines the functions in a contract that can be invoked
  • Compiler directive: pragma 0.4.24 tells what the acceptable compiler is
    • ^0.4.24 indicates that any minor version is accesible but no major versions (e.g. 0.5 is disallowed)

Global Solidity Variables

  • msg.sender: Originating caller

  • msg.data: data payload

  • msg.value: Ether sent in Wei

  • msg.sig: first 4 bytes of data

  • msg.gasLeft: gas remaining

  • tx.gasPrice: Gas price for the transaction

  • tx.origin: Originating EoA

  • block.blockhash: Originating caller

  • block.coinbase: Coinbase address for fees and rewards

  • block.difficulity: Current PoW of block

  • block.gasLimit: Max gas for all transactions to fit in block

  • block.number: Current block height

  • block.timestamp: Unix epoch timestamp in seconds

  • address.balance: Gets balance of address in wei

  • address.transfer: Attempts to transfer value passed, throws error if fails

  • address.call: Low level CALL, arbitrary msg with data payload

  • address.delegatecall: Like call code but with msg context (libraries)

  • address.send: Attempts to send value passed in, returns false if failed

  • address.callcode: CALLCODE function replacing this addresses' contract code

Visibility

  • public: Callable from any EoA or contract
  • private: Not collable from derived contracts
  • external: Only callable with explicit this
  • internal: Only callable from derived contracts (protected)

Behaviours

  • constant/view: Promises not to write (modify) state but can read
  • payable: Function can accept incoming payments
  • pure: Function cannot read or write to state (declarative)

Constructors

  • Created via construtor keyword
  • Destruction with SELFDESTRUCT

Modifiers

  • Modifiers place constraints on the function execution
  • They substitude code before execution of a function body:
  onlyOwner {
    require(msg.sender == owner)
    _; // This placeholder is replaced with code by owner
  }

Error Handling

  • Errors revert all state changes
  • require is used as a gateway condition
  • assert/throw is used to halt execution and state changed
  • transfer will automatically throw if not enough ETH is present

Events

  • A transaction receipt is given when a tx completes
    • these contain logs which can be watched

Callling other contracts

  • Can create contracts via new operator which returns an object
  • Specify value of the contract on creation:
    • faucet = (new Faucet).value(0.5 ether)
  • You can cast an address as a contract
    • `faucet = Faucet(_f)
  • Can directly call methods via call
    • Uses direct opcodes of EVM
    • _faucet.call("withdraw", 0.1 eth)
    • Risk of re-entrancy attack
  • delegatecall keeps the msg context constant so that msg.sender is the same - for libraries
    • call in comparison modifies the msg.sender (e.g. different execution context)

Mastering Ethereum - Chp 8

  • Vyper takes one step closer to declaritive programming than solidity
  • Types of Problematic Contracts Vyper tries to address
    • Suicidal Contracts: Contracts can at times be arbitrarily destroyed
    • Greegy Contracts: Contracts that can get into "unreleasable" or "unusable" states
    • Prodigal Contracts: Contracts that can release funds to arbitrary addressess
  • Vyper removes modifiers as it changes the context of code execution
    • Uses inline confirmation and assertion checks instead
    • Also forces state modifications to be explicit in the contracts
  • Vyper has no inheritance
  • Vyper has no inline assembly
  • Vyper allows explicit type casting via convert() which calls through a conversion table but no implicit casting
  • Vyper outputs LLL (Low Level Lisp Language) code to be compiled into bytecode for the EVM

Mastering Ethereum - Chp 9

Best Practices

  • Defensive programming
  • Use well tested code libraries
  • Prefer minimalistic and simple implementations
  • There is a high quality bar due to immutability
  • Write in a readable and auditable way
  • Focus on extensive test coverage

Contract Anti-Patterns

Re-Entrancy

Occurs When:

  • Sending Ether to an unknown address.
  • a payable fallback function from a malicious contract address can execute a vulnerable execution path causing it to "re-enter" the contract

Prevent With:

  1. Use the Check-Effect_Interaction pattern
  2. Use Mutex's to lock state
  3. Prefer the transfer function over send

Arithmatic Overflow

Occurs When:

  • a fixed size variable is used to store data but the value is outside the range causing wrap arounds for numbers and unexpected behaviour
  • Underflow: Value is under the storage range
uint my_var = 0 
my_var - 1 // = 255
  • Overflow: Value is over the storage range

Prevent With:

  1. Using SafeMath

Unexpected Ether

Occurs When:

  • SELFDESTRUCT opcode forcibly sends ethere to a contract (e.g. malicious contract destruction sends ether to target)
  • Contract relies on "in-variant" values like this.balance

Prevent With:

  1. Self defined variable to track balance rather than relying on this.balance

Delegatecall

Occurs When:

  • Context perserving delegatecall is misused -- particularly to exploit how Ethereum manages storage with slots.
    • Contracts store data in slot, e.g. library's first variable is slot[0]
  • Malicious contract sets it's address as a receiving address or library address for a critical point of business logic.
    • Because delegatecall perserves context, slot values can be overwritten

Prevent With:

  1. Using library keyword explicitly for contracts
  2. Avoiding state bearing contracts, and non self-destructing

Floating Point Precision

Occurs When:

  • Performing floating point arithematic with integers causing issues like under or overflows, or lack of precision

Prevent With:

  1. Allow large numerators in fractions
  2. Be mindful of order of operations
  3. Convert to higher precision, do the math, then convert down

Default Visibility

Occurs When:

  • Visibility is not specified resulting in default public and accesible functions

Prevent With:

  1. Explicity setting modifiers in code

Entropy Illusion

Occurs When:

  • Contracts require some sort of randomness to function and mistakeningly use psuedo random values like block hashes or numbers
    • There is no uncertainty in Ethereum since execution is deterministic

Prevent With:

  1. External sources of randomness (like oracles)

Externally Referenced Contracts

Occurs When:

  • Solidity contracts are casted to an address but the address might not contain the intended functions implemented correctly
  • Malicious contracts could implement the same interface and inject themselves through constructor

Prevent With:

  1. Initializing contracts with new at deployment time
  2. Hardcoding contract addressess

Short Address Parameter

Occurs When:

  • Third party apps do not validate input to the contracts
  • EVM fills short addresses with zeros which can multiply the trailing value, e.g.:
|<-- address -->|<-- value -->|

|<-- addr -->|<-- value -->000| // zero's filled in resulting in much larger value

Prevent With:

  1. Validating input parameters

Unchecked Call Values

Occurs When:

  • Developer does not revert execution based on failed send call
    • send returns false if it fails and does not revert, unlike transfer

Prevent With:

  1. Prefer transfer function where possible
  2. Use the withdraw pattern
  • User's must call the withdraw function that handles sending, and reversions on failure

Race Conditions

Occurs When:

  • A malicious user duplicate a transaction payload with a higher gasPrice to "front-run" existing transactions
    • Think exchanges, lottery guessing games, etc
    • Be wary of both malicious users and miners

Prevent With:

  1. Add explicit upper bounds to gasLimit
  2. Implement "commit-reveal schemes"
  • Send a hidden data value and only reveal once included in a block
  1. Use "submarine sends" via CREATE2 opcode

Denial of Service

Occurs When:

  1. A contract loops through a large mapping or array, or a malicious user intentionally creates a huge array (can sometimes exceed block's gasLimit)
  2. Keys are lost to priviledged account (e.g. EoA of owner account is lost)

Prevent With:

  1. Provide "pull" rather than "push" operations to withdraw funds (e.g. withdraw vs. distribute)
  2. Add lock times or multi sig so funds are not lost forever

Block Timestamp Tampering

Occurs When:

  • Malicious miners change the timestamp to exploit a contract depending on it

Prevent With:

  1. Use block numbers instead of timestamps for entropy

Constructor's with Care

Occurs When:

  • Old constructor left from Solidity 0.4.22 which use the contract name instead of keyword are publically accessible and invokable functions

Prevent With:

  1. Using 0.4.22 Solidity compiler which uses the constructor keyword

Unitialized Storage Pointers

Occurs When:

  • Solidity defaults local variables to storage (opposed to memory). So an object references slot[0] and can overwrite values

Prevent With:

  1. Solidity lint for pointers
  2. Explicit memory use
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment