.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/contracts/upgrades/plot_02_create2_counterfactual.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_contracts_upgrades_plot_02_create2_counterfactual.py: CREATE2 and counterfactual addresses (2019) =========================================== ``CREATE`` derives a new contract's address from the deployer and its nonce, so the address depends on everything the deployer did before. EIP-1014, by Vitalik Buterin, activated in the Constantinople upgrade of February 2019, added ``CREATE2``: .. math:: \mathrm{address} = H(\mathtt{0xff} \,\|\, \mathrm{deployer} \,\|\, \mathrm{salt} \,\|\, H(\mathrm{init\ code}))_{[12:]} . The address depends only on who deploys, a chosen salt and the code, so it is known before anything is deployed: it is *counterfactual*. A user can receive funds at a smart-contract wallet that does not exist yet, and the wallet is deployed only when it is first needed, by whoever pays for it. State channels use the same trick for contracts that are deployed only in a dispute. .. GENERATED FROM PYTHON SOURCE LINES 24-28 .. code-block:: Python import matplotlib.pyplot as plt import blockchainkit as bk .. GENERATED FROM PYTHON SOURCE LINES 29-31 Pay first, deploy later ----------------------- .. GENERATED FROM PYTHON SOURCE LINES 31-47 .. code-block:: Python world = bk.contracts.World() factory = world.deploy("dev", bk.contracts.Factory, name="factory") address = world.view(factory, "predict", 7, "alice") world.fund("bob", 100) world.transact("bob", address, value=60) print("before deployment: code", world.code(address), "balance", world.balance(address)) assert world.code(address) is None and world.balance(address) == 60 deployed = world.transact("relayer", factory, "deploy", 7, "alice").result assert ( deployed == address == bk.contracts.create2_address(factory, 7, bk.contracts.Forwarder, "alice") ) assert world.transact("anyone", address, "sweep").result == 60 and world.balance("alice") == 60 assert "already in use" in world.transact("relayer", factory, "deploy", 7, "alice").error .. rst-class:: sphx-glr-script-out .. code-block:: none before deployment: code None balance 60 .. GENERATED FROM PYTHON SOURCE LINES 48-50 What the address depends on --------------------------- .. GENERATED FROM PYTHON SOURCE LINES 50-85 .. code-block:: Python creates = [bk.contracts.create_address(factory, nonce) for nonce in range(3)] salts = [world.view(factory, "predict", salt, "alice") for salt in range(3)] owners = [world.view(factory, "predict", 7, owner) for owner in ("alice", "bob", "carol")] assert len(set(creates)) == len(set(salts)) == len(set(owners)) == 3 assert world.view(factory, "predict", 7, "alice") == address # Reproducible. fig, ax = plt.subplots(figsize=(8, 3.5)) rows = [ ("CREATE, nonce 0..2", creates), ("CREATE2, salt 0..2", salts), ("CREATE2, owner varies", owners), ] for row, (_, addresses) in enumerate(rows): for column, value in enumerate(addresses): ax.text( column, -row, value[:12] + "...", ha="center", va="center", family="monospace", bbox={"facecolor": "#e0e7ff" if value != address else "#bbf7d0", "pad": 4}, ) ax.set_yticks([-r for r in range(len(rows))], [label for label, _ in rows]) ax.set( xlim=(-0.6, 2.6), ylim=(-2.6, 0.6), xticks=[], title="Every input of the formula moves the address", ) fig.tight_layout() plt.show() .. image-sg:: /api/gallery/contracts/upgrades/images/sphx_glr_plot_02_create2_counterfactual_001.png :alt: Every input of the formula moves the address :srcset: /api/gallery/contracts/upgrades/images/sphx_glr_plot_02_create2_counterfactual_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 86-92 Exercise -------- The deployed wallet sends everything to its owner. Bob funded Alice's address before it existed, trusting that only a Forwarder for Alice can ever be deployed there. Which inputs of ``create2_address`` guarantee that, and why must the constructor's argument be part of the code hash? .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.036 seconds) .. _sphx_glr_download_api_gallery_contracts_upgrades_plot_02_create2_counterfactual.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/contracts/upgrades/plot_02_create2_counterfactual.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_02_create2_counterfactual.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_02_create2_counterfactual.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_02_create2_counterfactual.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_