🌱
Dev Compendium
  • Ethereum
    • Solidity
      • EVM
      • Architecture
      • Execution Context
      • Transactions
      • Gas
      • Calldata, Memory & Storage
      • Gas Optimisation
      • Function Declarations
      • receive() & fallback()
      • CALL vs. DELEGATE CALL
    • Yul
      • Introduction
      • Types
      • Basic Operations
      • Storage
      • Memory
        • Arrays
        • Structs
        • Tuples, revert, keccak256
        • Logs and Events
        • Gotchas
        • abi.encode
      • Calldata
        • External Calls
        • Dynamic Length Inputs
        • Transferring Value
        • Receiving Contract Calls
      • Contracts in Yul
      • Other Yul Functions
    • Foundry
    • Security
      • Common Vulnerabilities
      • Best Practices
      • Development Workflow
      • Contract Migration
    • Auditing Tools
      • Slither
      • Mythril
      • Fuzzing
    • Upgradable Contracts
      • Upgrade Patterns
      • ERC-1967 Implementation
      • Deployment
    • MEV
    • Tooling
      • Chainlink
      • IPFS
      • Radicle
    • Frontend
      • Contract Hooks
      • Wallet Connection
        • wagmi.sh
        • Rainbow Kit
      • thirdweb
    • Protocol Research
      • Uniswap v2
      • Uniswap v3
      • Curve
      • GMX
  • Starkware
    • Fundamentals
    • Account Abstraction
    • Universal Deployer
    • Cairo 1.0
    • starknet.js
    • Security Model
  • Zero Knowledge
    • Group Theory
    • ECDSA
  • Rust
    • Basic Operations
    • Set up
    • Primitives
    • Control Flow
    • Mutability & Shadowing
    • Adding Behavior
    • Lifetimes
    • Std Library
  • SUI
    • Architecture
    • Consensus Mechanism
    • Local Node Setup
    • Sui Client CLI
    • Move Contracts
      • Move
      • Move.toml
      • Move.lock
      • Accessing Time in Sui Move
      • Set up Development Framework
      • Debug & Publish
      • Package Upgrades
      • Sui Move Library
      • Difference from Core Move
    • Object Programming
      • Object Basics
      • Using Objects
      • Immutable Objects
      • Object Wrapping
      • Dynamic Fields
      • Collections
      • Unit Testing
      • Deployment with CLI
  • NEAR
    • Architecture
    • Contract Standards
      • Fungible Token (NEP-141)
      • Non-Fungible Token (NEP-171)
      • Storage Management (NEP-145)
      • Events (NEP-297)
      • Meta-Transactions
    • Rust Contracts
      • Development Workflow
      • Smart Contract Layout
      • Storage Management
      • Events & Meta-transactions
      • Method Types
      • Upgrading Contracts
      • Unit Testing
    • NEAR Libraries
    • Environment Variables
    • Serialisation
    • Security Concepts
    • Collections
    • JS SDK
Powered by GitBook
On this page
  1. Ethereum

Upgradable Contracts

Sample implementation of upgradable contracts

PreviousFuzzingNextUpgrade Patterns

Last updated 2 years ago

A smart contract upgrade is an action that can arbitrarily change the code executed in an address while preserving storage and balance.

Overview

  • A major limitation of smart contract upgrades: while it’s possible to arbitrarily change the code of a contract, only storage-compatible changes can be done to its state variables. Operations such as reordering variables, inserting new variables, changing the type of a variable, or even changing the inheritance chain of a contract can potentially break storage. The only safe change is appending state variables after any existing ones.

  • Under the unstructured proxy pattern, implementation contracts cannot have constructors. Once the implementation contract has been created, there is no way to invoke its constructor code anymore. This means that proxies cannot call into the constructor to initialize their state.

  • To work around this, constructors need to be changed into regular functions, usually called initializers. Since these are regular functions, they do get compiled into the contract, and can be delegate-called by the proxy to initialize it when it is deployed. However, since they are also regular functions, they need additional logic to ensure they can be called only once.

References

https://eips.ethereum.org/EIPS/eip-1967
https://eips.ethereum.org/EIPS/eip-1822