.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/fraud/scam_contracts/plot_01_verified_source_deception.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code or to run this example in your browser via JupyterLite. .. rst-class:: sphx-glr-example-title .. _sphx_glr_api_gallery_fraud_scam_contracts_plot_01_verified_source_deception.py: Verified source code, and why a verified source can still deceive (2016) ======================================================================== Block explorers let a contract's author publish its source and *verify* it: the explorer compiles the source and checks that the bytecode matches the code at the address. Solidity's metadata hash, added in December 2016, made the match exact, and a green "verified" badge came to read as "safe". It certifies only which code sits at one address. A buyer who checks the verified source of an upgradeable token reads a proxy: .. code-block:: solidity contract Proxy { // keccak256("eip1967.proxy.implementation") - 1 bytes32 constant IMPLEMENTATION_SLOT = 0x3608...bbc; fallback() external payable { address impl = StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value; (bool ok, ) = impl.delegatecall(msg.data); require(ok); } } The behavior lives at whatever address the slot holds, and the admin can change it at any time. The code that runs is .. math:: \text{code}(\text{proxy}) \circ \text{code}\big(\text{storage}_{\text{proxy}}[\text{slot}]\big), and only the first factor is verified. .. GENERATED FROM PYTHON SOURCE LINES 36-40 .. code-block:: Python import matplotlib.pyplot as plt import blockchainkit as bk .. GENERATED FROM PYTHON SOURCE LINES 41-43 A verified proxy in front of a plain token ------------------------------------------ .. GENERATED FROM PYTHON SOURCE LINES 43-53 .. code-block:: Python world = bk.contracts.World() v1 = world.deploy("dev", bk.fraud.UpgradeableToken, name="token v1") token = world.deploy("dev", bk.contracts.EIP1967Proxy, v1, name="token") world.transact("dev", token, "initialize", 1_000_000) world.transact("dev", token, "transfer", "buyer", 250_000) # The buyer pays off-chain. print("verified:", bk.fraud.verify_source(world, token, bk.contracts.EIP1967Proxy)) print("runs:", bk.fraud.effective_code(world, token).__name__) assert world.transact("dev", token, "seize", "buyer", 1).error is not None # No such function. .. rst-class:: sphx-glr-script-out .. code-block:: none verified: True runs: UpgradeableToken .. GENERATED FROM PYTHON SOURCE LINES 54-56 The same badge, different code ------------------------------ .. GENERATED FROM PYTHON SOURCE LINES 56-72 .. code-block:: Python v2 = world.deploy("dev", bk.fraud.SeizableToken, name="token v2") world.transact("dev", token, "upgrade_to", v2) assert bk.fraud.verify_source(world, token, bk.contracts.EIP1967Proxy) # Still verified. print("now runs:", bk.fraud.effective_code(world, token).__name__) seized = world.transact("dev", token, "seize", "buyer", 250_000) print("seize:", seized.success, "buyer holds", world.view(token, "balance_of", "buyer")) assert seized.success and world.view(token, "balance_of", "buyer") == 0 fig, ax = plt.subplots(figsize=(7, 3)) ax.barh(["before the upgrade", "after the upgrade"], [250_000, 0], color=["#16a34a", "#dc2626"]) ax.set(xlabel="buyer's tokens", title="The verified address never changed") fig.tight_layout() plt.show() .. image-sg:: /api/gallery/fraud/scam_contracts/images/sphx_glr_plot_01_verified_source_deception_001.png :alt: The verified address never changed :srcset: /api/gallery/fraud/scam_contracts/images/sphx_glr_plot_01_verified_source_deception_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none now runs: SeizableToken seize: True buyer holds 0 .. GENERATED FROM PYTHON SOURCE LINES 73-78 Exercise -------- List three other ways in which a contract with a verified source can run code its reader never saw. Which of them can a reader detect from the verified source alone? .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.022 seconds) .. _sphx_glr_download_api_gallery_fraud_scam_contracts_plot_01_verified_source_deception.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: lite-badge .. image:: images/jupyterlite_badge_logo.svg :target: ../../../../lite/lab/index.html?path=api/gallery/fraud/scam_contracts/plot_01_verified_source_deception.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_01_verified_source_deception.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_01_verified_source_deception.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_01_verified_source_deception.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_