{
  "$schema": "https://degreesofsatoshi.com/encyclopedia/schemas/article-v1.json",
  "schemaVersion": "1.0.0",
  "id": "delegatecall-explained",
  "canonical": "https://degreesofsatoshi.com/encyclopedia/delegatecall-explained/",
  "collection": "ethereum",
  "title": "Delegatecall: whose code runs, and whose storage changes?",
  "description": "Understand why Ethereum delegatecall uses another contract’s code with the caller’s storage and why code selection becomes an authority decision.",
  "aliases": [],
  "dates": {
    "published": "2026-10-02",
    "modified": "2026-10-02",
    "verified": "2026-10-02T18:12:41.505Z",
    "dataAsOf": "2026-10-02"
  },
  "authorship": {
    "publisher": "Degrees of Satoshi editorial project",
    "process": "AI-assisted research and drafting with a separate automated source-verification pass; no external expert or named human review is implied."
  },
  "quickAnswer": {
    "text": "DELEGATECALL executes code from another address in the calling contract’s context. Storage, address and balance remain those of the caller, while msg.sender and msg.value are preserved from that context. This enables proxies and libraries, but delegated code can act on the caller’s state with substantial authority.",
    "claimId": "delegatecall-explained-quick-answer",
    "sourceIds": [
      "solidity-delegatecall"
    ]
  },
  "keyFacts": [
    {
      "label": "Code",
      "value": "The target supplies code, not a separate storage context.",
      "sourceIds": [
        "solidity-delegatecall"
      ],
      "id": "code",
      "claimId": "delegatecall-explained-fact-code"
    },
    {
      "label": "State",
      "value": "Storage writes affect the calling context.",
      "sourceIds": [
        "solidity-delegatecall"
      ],
      "id": "state",
      "claimId": "delegatecall-explained-fact-state"
    },
    {
      "label": "Caller information",
      "value": "msg.sender and msg.value are preserved rather than replaced as in an ordinary nested call.",
      "sourceIds": [
        "solidity-delegatecall"
      ],
      "id": "caller-information",
      "claimId": "delegatecall-explained-fact-caller-information"
    }
  ],
  "prerequisites": [
    "ethereum-virtual-machine"
  ],
  "sections": [
    {
      "id": "example",
      "heading": "One instruction changes which storage is edited",
      "sourceIds": [
        "solidity-delegatecall",
        "solidity-layout"
      ],
      "paragraphs": [
        "Suppose a proxy delegates to logic that writes an owner field. That write changes the proxy’s storage slot under the implementation’s layout assumptions. It does not simply edit an independent owner field at the implementation address.",
        "If layouts disagree, a write intended for one variable can corrupt another. This is a code-and-state compatibility issue, not merely a display problem."
      ]
    },
    {
      "id": "authority",
      "heading": "Choosing code can amount to choosing policy",
      "sourceIds": [
        "oz-proxy"
      ],
      "paragraphs": [
        "An authority that can select a new delegated implementation may change transfer rules, permissions and asset-handling behavior within the design’s constraints.",
        "The security boundary includes the implementation-selection mechanism. Reviewing only the currently selected logic leaves future authorized changes out of the analysis."
      ]
    },
    {
      "id": "trace",
      "heading": "Read delegated calls differently from ordinary calls",
      "sourceIds": [
        "geth-tracing",
        "solidity-delegatecall"
      ],
      "paragraphs": [
        "A trace labels DELEGATECALL separately because its target identifies the code source. It should not automatically be read as an ETH payment to that target.",
        "To understand the outcome, follow storage context, call type and any subsequent external calls. The presence of a target address alone is insufficient."
      ]
    }
  ],
  "faq": [
    {
      "question": "Is delegatecall always a vulnerability?",
      "answer": "No. It is an intentional EVM mechanism used by libraries and proxies. Its safety depends on trusted code selection, compatible storage and correctly enforced authority.",
      "sourceIds": [
        "solidity-delegatecall",
        "oz-proxy"
      ]
    }
  ],
  "claims": [
    {
      "id": "delegatecall-explained-quick-answer",
      "articleSlug": "delegatecall-explained",
      "statement": "DELEGATECALL executes code from another address in the calling contract’s context. Storage, address and balance remain those of the caller, while msg.sender and msg.value are preserved from that context. This enables proxies and libraries, but delegated code can act on the caller’s state with substantial authority.",
      "sourceIds": [
        "source-7399ee01181109d4"
      ],
      "sourceLocators": [
        {
          "sourceId": "source-7399ee01181109d4",
          "locator": "Delegatecall and Libraries; Storage, Memory and the Stack; Logs; Message Calls"
        }
      ],
      "scope": {
        "collection": "ethereum",
        "dataAsOf": "2026-10-02",
        "blockHeight": null
      },
      "qualification": "",
      "evidenceStatus": "documented",
      "verification": {
        "status": "verified",
        "method": "independent automated source review",
        "checkedAt": "2026-10-02T18:12:41.505Z",
        "reviewer": "Codex independent automated reviewer /root/verify_ethereum_100",
        "notes": [
          "Independently checked Solidity Delegatecall and Libraries: calling-context storage, address, balance, msg.sender and msg.value are retained.",
          "Geth callTracer separates DELEGATECALL target semantics; proxy upgrade selection and storage-layout compatibility explain authority without claiming every delegatecall is vulnerable."
        ]
      }
    },
    {
      "id": "delegatecall-explained-fact-code",
      "articleSlug": "delegatecall-explained",
      "statement": "Code: The target supplies code, not a separate storage context.",
      "sourceIds": [
        "source-7399ee01181109d4"
      ],
      "sourceLocators": [
        {
          "sourceId": "source-7399ee01181109d4",
          "locator": "Delegatecall and Libraries; Storage, Memory and the Stack; Logs; Message Calls"
        }
      ],
      "scope": {
        "collection": "ethereum",
        "dataAsOf": "2026-10-02",
        "blockHeight": null
      },
      "qualification": "",
      "evidenceStatus": "documented",
      "verification": {
        "status": "verified",
        "method": "independent automated source review",
        "checkedAt": "2026-10-02T18:12:41.505Z",
        "reviewer": "Codex independent automated reviewer /root/verify_ethereum_100",
        "notes": [
          "Independently checked Solidity Delegatecall and Libraries: calling-context storage, address, balance, msg.sender and msg.value are retained.",
          "Geth callTracer separates DELEGATECALL target semantics; proxy upgrade selection and storage-layout compatibility explain authority without claiming every delegatecall is vulnerable."
        ]
      }
    },
    {
      "id": "delegatecall-explained-fact-state",
      "articleSlug": "delegatecall-explained",
      "statement": "State: Storage writes affect the calling context.",
      "sourceIds": [
        "source-7399ee01181109d4"
      ],
      "sourceLocators": [
        {
          "sourceId": "source-7399ee01181109d4",
          "locator": "Delegatecall and Libraries; Storage, Memory and the Stack; Logs; Message Calls"
        }
      ],
      "scope": {
        "collection": "ethereum",
        "dataAsOf": "2026-10-02",
        "blockHeight": null
      },
      "qualification": "",
      "evidenceStatus": "documented",
      "verification": {
        "status": "verified",
        "method": "independent automated source review",
        "checkedAt": "2026-10-02T18:12:41.505Z",
        "reviewer": "Codex independent automated reviewer /root/verify_ethereum_100",
        "notes": [
          "Independently checked Solidity Delegatecall and Libraries: calling-context storage, address, balance, msg.sender and msg.value are retained.",
          "Geth callTracer separates DELEGATECALL target semantics; proxy upgrade selection and storage-layout compatibility explain authority without claiming every delegatecall is vulnerable."
        ]
      }
    },
    {
      "id": "delegatecall-explained-fact-caller-information",
      "articleSlug": "delegatecall-explained",
      "statement": "Caller information: msg.sender and msg.value are preserved rather than replaced as in an ordinary nested call.",
      "sourceIds": [
        "source-7399ee01181109d4"
      ],
      "sourceLocators": [
        {
          "sourceId": "source-7399ee01181109d4",
          "locator": "Delegatecall and Libraries; Storage, Memory and the Stack; Logs; Message Calls"
        }
      ],
      "scope": {
        "collection": "ethereum",
        "dataAsOf": "2026-10-02",
        "blockHeight": null
      },
      "qualification": "",
      "evidenceStatus": "documented",
      "verification": {
        "status": "verified",
        "method": "independent automated source review",
        "checkedAt": "2026-10-02T18:12:41.505Z",
        "reviewer": "Codex independent automated reviewer /root/verify_ethereum_100",
        "notes": [
          "Independently checked Solidity Delegatecall and Libraries: calling-context storage, address, balance, msg.sender and msg.value are retained.",
          "Geth callTracer separates DELEGATECALL target semantics; proxy upgrade selection and storage-layout compatibility explain authority without claiming every delegatecall is vulnerable."
        ]
      }
    }
  ],
  "sources": [
    {
      "id": "solidity-delegatecall",
      "label": "Solidity: Delegatecall and Libraries",
      "publisher": "Solidity contributors",
      "url": "https://docs.soliditylang.org/en/v0.8.30/introduction-to-smart-contracts.html",
      "locator": "Delegatecall and Libraries; Storage, Memory and the Stack; Logs; Message Calls",
      "note": "Execution uses another contract’s code in the caller’s context and storage.",
      "version": "Solidity 0.8.30 documentation",
      "checkedAt": "2026-10-02T17:03:42.822Z",
      "contentSha256": "9fde27b9eb16bcd47d5e9fb73a80d2d3b288ae7b74ac56b29956267028fe7a55",
      "recordId": "source-7399ee01181109d4"
    },
    {
      "id": "solidity-layout",
      "label": "Layout of State Variables in Storage and Transient Storage",
      "publisher": "Solidity contributors",
      "url": "https://docs.soliditylang.org/en/v0.8.30/internals/layout_in_storage.html",
      "locator": "Layout of State Variables; Mappings and Dynamic Arrays",
      "note": "Persistent storage slots, packing and mappings.",
      "version": "Solidity 0.8.30 documentation",
      "checkedAt": "2026-10-02T17:03:42.820Z",
      "contentSha256": "de5fd67613e71fdb6b46e30bcb1c7e63380ea40d9521e757cfba947a5ee8d738",
      "recordId": "source-2b10f2b55ba1af87"
    },
    {
      "id": "oz-proxy",
      "label": "Proxy contracts",
      "publisher": "OpenZeppelin",
      "url": "https://docs.openzeppelin.com/contracts/5.x/api/proxy",
      "locator": "TransparentUpgradeableProxy; UUPSUpgradeable; ERC1967Proxy",
      "note": "Proxy implementation slots, delegated execution and upgrade authority.",
      "version": "OpenZeppelin Contracts 5.x",
      "checkedAt": "2026-10-02T17:03:43.024Z",
      "contentSha256": "58fe40b9eaa6d3cf92e48caed2d8db247a790b1a3055948095a48c7f8eb77854",
      "recordId": "source-16bb921e662a5173"
    },
    {
      "id": "geth-tracing",
      "label": "Geth built-in tracers",
      "publisher": "Go Ethereum",
      "url": "https://geth.ethereum.org/docs/developers/evm-tracing/built-in-tracers",
      "locator": "callTracer; prestateTracer",
      "note": "Nested EVM call traces and the distinction between tracing and top-level transactions.",
      "version": null,
      "checkedAt": "2026-10-02T17:25:58.908Z",
      "contentSha256": "0528d605bfb3fb8f0e38525282805a88734c04f9f3763e7a05dff9b3934b11a3",
      "recordId": "source-269c0acf9654acdf"
    }
  ],
  "related": {
    "articles": [
      "contract-proxies",
      "ethereum-state-and-storage",
      "internal-transactions"
    ],
    "dossiers": [],
    "wallets": []
  },
  "revisionHistory": [
    {
      "date": "2026-10-02",
      "kind": "published",
      "summary": "First publication after primary-source research and independent automated verification."
    }
  ],
  "citation": "Degrees of Satoshi editorial project. “Delegatecall: whose code runs, and whose storage changes?.” Published 2026-10-02; updated 2026-10-02. https://degreesofsatoshi.com/encyclopedia/delegatecall-explained/"
}
