.. 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_04_torres_solidity_quirks.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_04_torres_solidity_quirks.py: Torres et al.: the Solidity quirks honeypots exploit (2019) =========================================================== Four of the honeypot techniques Torres, Steichen and State classified are quirks of the Solidity language or compiler of the time, which the reader of the source does not suspect. They are reproduced here by their effect; nothing is compiled. *Inheritance disorder*: the child redeclares ``owner``, so the bidder who becomes ``owner`` is not the one the parent's modifier checks. .. code-block:: solidity contract Ownable { address owner = msg.sender; modifier onlyOwner { require(msg.sender == owner); _; } } contract KingOfTheHill is Ownable { address public owner; function() payable { if (msg.value > jackpot) owner = msg.sender; jackpot += msg.value; } function takeAll() onlyOwner { msg.sender.transfer(this.balance); jackpot = 0; } } *Uninitialised storage struct*: ``GuessHistory guessHistory;`` without ``memory`` points at slot 0, so recording the player's address overwrites the "private" number the reader read from storage. *Type deduction overflow*: ``for (var i = 0; i < 2 * msg.value; i++)`` makes ``i`` a ``uint8``, and the doubled counter wraps at :math:`2 \cdot 128 \equiv 0 \pmod{256}`, ending the loop with a payout of 254 wei. *Skipped empty string literal*: before Solidity 0.4.12, the call ``loggedTransfer(amount, "", msg.sender, owner)`` was encoded without the ``""``, so the owner received the investor's refund. .. GENERATED FROM PYTHON SOURCE LINES 36-50 .. code-block:: Python import matplotlib.pyplot as plt import blockchainkit as bk world = bk.contracts.World() world.fund("creator", 20_000) losses = {} def victim(name, amount): world.fund(name, amount) return name .. GENERATED FROM PYTHON SOURCE LINES 51-53 Inheritance disorder -------------------- .. GENERATED FROM PYTHON SOURCE LINES 53-66 .. code-block:: Python hill = world.deploy("creator", bk.fraud.KingOfTheHill, name="KingOfTheHill") world.transact("creator", hill, value=1_000) king = victim("bidder", 1_500) world.transact(king, hill, value=1_500) print( "public owner:", world.view(hill, "owner"), "| takeAll:", world.transact(king, hill, "take_all").error, ) losses["inheritance disorder"] = 1_500 - world.balance(king) .. rst-class:: sphx-glr-script-out .. code-block:: none public owner: bidder | takeAll: only the owner .. GENERATED FROM PYTHON SOURCE LINES 67-69 Uninitialised storage struct ---------------------------- .. GENERATED FROM PYTHON SOURCE LINES 69-78 .. code-block:: Python game = world.deploy("creator", bk.fraud.GuessNumber, 7, 100, name="GuessNumber") world.transact("creator", game, value=1_000) secret = world.read(game, "number") # "private" is not secret on a public chain. guesser = victim("guesser", 100) world.transact(guesser, game, "guess", secret, value=100) print("the secret was", secret, "and slot 0 now holds", world.read(game, "number")) losses["uninitialised struct"] = 100 - world.balance(guesser) .. rst-class:: sphx-glr-script-out .. code-block:: none the secret was 7 and slot 0 now holds guesser .. GENERATED FROM PYTHON SOURCE LINES 79-81 Type deduction overflow ----------------------- .. GENERATED FROM PYTHON SOURCE LINES 81-90 .. code-block:: Python doubler = world.deploy("creator", bk.fraud.ForTest, 1_000, name="For_Test") world.transact("creator", doubler, value=5_000) sender = victim("doubler", 2_000) world.transact(sender, doubler, "test", value=2_000) print("sent 2,000, got back", world.balance(sender)) losses["type deduction overflow"] = 2_000 - world.balance(sender) assert world.balance(sender) == 254 .. rst-class:: sphx-glr-script-out .. code-block:: none sent 2,000, got back 254 .. GENERATED FROM PYTHON SOURCE LINES 91-93 Skipped empty string literal ---------------------------- .. GENERATED FROM PYTHON SOURCE LINES 93-109 .. code-block:: Python fund = world.deploy("creator", bk.fraud.DividendDistributor, name="DividendDistributor") investor = victim("investor", 1_000) world.transact(investor, fund, "invest", value=1_000) refund = world.transact(investor, fund, "divest", 1_000) print("refund paid to:", refund.events[0].fields["target"]) losses["skipped empty string"] = 1_000 - world.balance(investor) assert all(loss > 0 for loss in losses.values()) fig, ax = plt.subplots(figsize=(7, 3.5)) ax.barh(list(losses), list(losses.values()), color="#9333ea") ax.set(xlabel="ether lost by the victim", title="Four Solidity quirks, by their effect") fig.tight_layout() plt.show() .. image-sg:: /api/gallery/fraud/scam_contracts/images/sphx_glr_plot_04_torres_solidity_quirks_001.png :alt: Four Solidity quirks, by their effect :srcset: /api/gallery/fraud/scam_contracts/images/sphx_glr_plot_04_torres_solidity_quirks_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none refund paid to: creator .. GENERATED FROM PYTHON SOURCE LINES 110-115 Exercise -------- In the type-deduction honeypot, what is the largest payout the loop can ever compute, whatever the deposit? Replay the loop by hand for a deposit of 50 wei and explain why the honeypot sets a minimum deposit. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.030 seconds) .. _sphx_glr_download_api_gallery_fraud_scam_contracts_plot_04_torres_solidity_quirks.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_04_torres_solidity_quirks.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_04_torres_solidity_quirks.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_04_torres_solidity_quirks.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_04_torres_solidity_quirks.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_