<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>abbudi</title>
        <link>https://paragraph.com/@abbudi</link>
        <description>Following my journey of learning about Ethereum security with zero prior knowledge.</description>
        <lastBuildDate>Fri, 15 May 2026 12:45:12 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>abbudi</title>
            <url>https://storage.googleapis.com/papyrus_images/bb8a54e015adb2e73d86eee027facd8911442b9dfe7ccbe62a0f16b074bae290.png</url>
            <link>https://paragraph.com/@abbudi</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[Ethernaut - Coin Flip Writeup]]></title>
            <link>https://paragraph.com/@abbudi/ethernaut-coin-flip-writeup</link>
            <guid>qxN2c8DFqvFQ3R2m6qV7</guid>
            <pubDate>Thu, 29 Jun 2023 17:59:13 GMT</pubDate>
            <description><![CDATA[Coin Flip is the third Ethernaut challenge, and it involves having to guess a “random” coin flip correctly 10 times in a row. This might seem impossible (or improbable), but we’ll learn that being random in a public blockchain is harder than it sounds. As always, you can find the full source code for this challenge below on Github. https://github.com/imam-abbudi/ethernaut-web3py-solutions/tree/main/coinflip You’re going to want to download the challenge’s source code locally for this one, kee...]]></description>
            <content:encoded><![CDATA[<p>Coin Flip is the third Ethernaut challenge, and it involves having to guess a “random” coin flip correctly 10 times in a row. This might seem impossible (or improbable), but we’ll learn that being random in a public blockchain is harder than it sounds.</p><p>As always, you can find the full source code for this challenge below on Github.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/imam-abbudi/ethernaut-web3py-solutions/tree/main/coinflip">https://github.com/imam-abbudi/ethernaut-web3py-solutions/tree/main/coinflip</a></p><p>You’re going to want to download the challenge’s source code locally for this one, keep a folder that looks something like this:</p><pre data-type="codeBlock" text="coinflip/
|_ Coinflip.sol
|_ CoinflipExploit.sol
|_ coinflip.py
"><code>coinflip<span class="hljs-operator">/</span>
<span class="hljs-operator">|</span><span class="hljs-keyword">_</span> Coinflip.sol
<span class="hljs-operator">|</span><span class="hljs-keyword">_</span> CoinflipExploit.sol
<span class="hljs-operator">|</span><span class="hljs-keyword">_</span> coinflip.py
</code></pre><p>And yes, we are going to be writing the exploit in Solidity.</p><h3 id="h-coinflipsol" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">coinflip.sol</h3><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f00639d56d8b250d3b3829a76c4033085fbd2cdd9e7026fbcd5793b4bf074372.png" alt="coinflip.sol source code" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">coinflip.sol source code</figcaption></figure><p>This file should include the source code, like this. Reading through the code, we can see that it reads the <strong>block hash</strong> of the <strong>previous block</strong>, divides it by <strong>FACTOR</strong>, and checks if the division is equals to 1. That’s how it picks the <strong>side</strong> of the coin.</p><p>It is important to note that we can’t just guess the same <strong>side</strong> ten times in a row in the same <strong>block</strong>. Because the contract will revert if it notices the same <strong>blockValue</strong> is generated twice.</p><h3 id="h-coinflipexploitsol" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">coinflipExploit.sol</h3><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/fb6478c79dbb123aeeaf459c27bdfec548e80dd1773a4515dbf498bb490d1cfd.png" alt="coinflipExploit.sol source code" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">coinflipExploit.sol source code</figcaption></figure><p>We can create an interface with the Ethernaut’s challenge by importing the source code, and entering the challenge instance’s address in the constructor when we deploy the contract.</p><p>The function <strong>flipGuess()</strong> has the exact same logic as the challenge, and since the two contracts are running on the same network, <strong>blockValue</strong> will be the same value for both contracts. Since we already know <strong>FACTOR</strong>, we can directly import it as it doesn’t change values.</p><p>If someone were to call <strong>flipGuess()</strong>, it would create all the variables, and call the challenge contract’s <strong>flip()</strong> function with the correct side. Now we just have to write a Python script to call our <strong>flipGuess()</strong> function 10 blocks in a row.</p><h3 id="h-coinflippy" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">coinflip.py</h3><p>As always we’ll import the necessary modules and variables.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/0c9c693d72bb8f4d48800015ce64250fb7e6ae0b74cbe1205055848a168ef953.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>We’ll also need to <strong>deploy</strong> our contract for this challenge. To do this, we’ll need to get both the <strong>ABI</strong> and <strong>bytecode</strong> from our exploit script.</p><p><em>A quick reminder</em>:</p><blockquote><p><strong>ABI</strong>: An interface to interact with deployed Solidity contracts on the Ethereum network.</p></blockquote><blockquote><p><strong>Bytecode</strong>: The compiled version of our Solidity program, designed for computers to read instructions rather than humans.</p></blockquote><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d8f536c7a75732ea031847ffb2b97aa667539f56f6461882a6ad839a632120c5.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>This function will read our exploit contract, and return a tuple of both the <strong>ABI</strong> and <strong>bytecode</strong>. We will use both of these variables when deploying our contract.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/806bac453c9eaf0fb65717a2b9bd9a27f0ed75fa390bbc6a2181137094bd0dc6.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>We’ll also use this function from previous challenges, it will sign the transaction we want and return the receipt.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/6dbfd47b0cb6d609ecf5dedbfb1711231df2a7fb8dd6078ae9aae96a742aed16.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Moving onto our <strong>main</strong> function, we will first save our <strong>ABI</strong> and <strong>bytecode</strong> from our exploit contract, build our transaction by supplying gas and its price, and deploy the contract.</p><p>In the <strong>constructor</strong> of our exploit contract, we will pass in the address of the Ethernaut challenge instance, which will let our exploit contract know which contract address to attack.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/98b7a977316843a3ea2ed9fa425e19316d3b4b3d102cf670d9928995fef8d544.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Using the receipt of the exploit contract deployment transaction, we can print the address of our contract if it was deployed successfully, or exit if the transaction failed.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/43a162bdcabc9e54e96d70f010b5491f161fe45453a4e0fd03dd2716a37bdbbe.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>If it was successfully deployed, we’ll use the contract address and the <strong>ABI</strong> we generated at the top of our <strong>main</strong> function to create an instance.</p><p>We will also keep track of there number of correct guesses in <strong>correct_guesses</strong>. In the <strong>while</strong> loop, we call our exploit function. If the transaction goes through, we assume the guess is correct and increment <strong>correct_guesses</strong> by one.</p><p>Once we reach 10 guesses, we print a completion message and exit the program. The challenge is now complete, and you can try submitting on Ethernaut.</p><blockquote><p><em>Note: You could also call the number of correct guesses from the Ethernaut instance itself, but I found that the guesses are always right so it makes more sense to keep a local track of the correct guesses.</em></p></blockquote>]]></content:encoded>
            <author>abbudi@newsletter.paragraph.com (abbudi)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/c7a7782fc1dbca147c554b471bcce13675650e5b91dad02acd2f1bde5cedac39.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Ethernaut - Fallout Writeup]]></title>
            <link>https://paragraph.com/@abbudi/ethernaut-fallout-writeup</link>
            <guid>Pwfmars2ektqlxvNJTeK</guid>
            <pubDate>Sun, 25 Jun 2023 23:08:49 GMT</pubDate>
            <description><![CDATA[Fallout includes a very simple exploit, but can be tricky if you trust the comments written by the author. Clear conditions:Claim ownership of the contractFallout source codeTake a read of the contract yourself, and see if anything stands out already. The constructor is a function! Even though it is labelled as a constructor by the author’s comment. This means that anyone can call Fal1out() and claim ownership of the contract.Imports & VariablesLet’s first import modules we’ll need as well as...]]></description>
            <content:encoded><![CDATA[<p>Fallout includes a very simple exploit, but can be tricky if you trust the comments written by the author.</p><p><strong>Clear conditions:</strong></p><ul><li><p>Claim ownership of the contract</p></li></ul><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/c7ebcbf91c6cc13cdfcf802a2883087cc0ce66297aab5d14665c1d1558707f9e.png" alt="Fallout source code" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Fallout source code</figcaption></figure><p>Take a read of the contract yourself, and see if anything stands out already.</p><p>The <strong>constructor</strong> is a <strong>function</strong>! Even though it is labelled as a constructor by the author’s comment.</p><p>This means that anyone can call <strong>Fal1out()</strong> and claim ownership of the contract.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/dea931c0d187c2a637aad083065b66a93420a3eab4c64e7fe434087e80b64d6a.png" alt="Imports &amp; Variables" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Imports &amp; Variables</figcaption></figure><p>Let’s first import modules we’ll need as well as read required environment variables.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/650601946b06f018f2a8fbc85e865e39d3cef90cfde5471153519f9ef8d0aa91.png" alt="Reusing functions" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Reusing functions</figcaption></figure><p>We’ll also reuse the functions we made in the previous challenge. The first function returns a contract object to allow us to interact with the challenge instance, and the second signs a transaction and returns its receipt.</p><p>If you want to learn how these functions work in greater detail, you can read the <strong>Fallback</strong> writeup:</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/0x9C6D113a0Eafcfe3BcEbF25b0CD0F77778EeB851/TibBVMl7Bb7ZEf8UVyo_4HrjcE-t01fxxZRibzOTxX0">https://mirror.xyz/0x9C6D113a0Eafcfe3BcEbF25b0CD0F77778EeB851/TibBVMl7Bb7ZEf8UVyo_4HrjcE-t01fxxZRibzOTxX0</a></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a4c99a8044d8733d43e9c235a7f7f24c54c0b20638754c99345bd121b8f7dd52.png" alt="Attack" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Attack</figcaption></figure><p>Now it’s as simple as creating the contract object, calling <strong>Fal1out()</strong>, and checking if the transaction succeeded or not.</p><p><em>Moral of the story: Don’t trust developer comments, the code may behave differently than the developer intends.</em></p><p>If you want to read the full Python code, you can find it here:</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/imam-abbudi/ethernaut-web3py-solutions/blob/main/fallout/fallout.py">https://github.com/imam-abbudi/ethernaut-web3py-solutions/blob/main/fallout/fallout.py</a></p>]]></content:encoded>
            <author>abbudi@newsletter.paragraph.com (abbudi)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/12bfa2ed5e7c6e50d6b18aba0090327623c0534ffb752318cead1bfe97da724f.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Ethernaut - Fallback Writeup]]></title>
            <link>https://paragraph.com/@abbudi/ethernaut-fallback-writeup</link>
            <guid>rZMT6GC0Rv96upZ6spzc</guid>
            <pubDate>Sun, 25 Jun 2023 20:57:27 GMT</pubDate>
            <description><![CDATA[Fallback is the first of the Ethernaut challenges. It is fairly simple, requiring only basic Solidity knowledge, mainly about fallback functions. Clear conditions:Become the owner of the contract.Empty all ether from the contract.Let’s first run through the code…Fallback ContractFirst, notice the two variables: contributions: A mapping keeping track of how much wei an address contributed. owner: A single address that can withdraw funds from the contract. The constructor then sets up the scena...]]></description>
            <content:encoded><![CDATA[<p>Fallback is the first of the Ethernaut challenges. It is fairly simple, requiring only basic Solidity knowledge, mainly about fallback functions.</p><p><strong>Clear conditions:</strong></p><ul><li><p>Become the owner of the contract.</p></li><li><p>Empty all ether from the contract.</p></li></ul><p>Let’s first run through the code…</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/bdc71c00b54749e4ad8aecf1171b48d0b94e897cf0cb7db1239afbfac3b7e10f.png" alt="Fallback Contract" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Fallback Contract</figcaption></figure><p>First, notice the two variables:</p><p><strong>contributions</strong>: A mapping keeping track of how much <strong>wei</strong> an address contributed.</p><p><strong>owner:</strong> A single address that can withdraw funds from the contract.</p><p>The constructor then sets up the scenario for this challenge, the owner of the contract is now Ethernaut who has <strong>1000 ether</strong> in contributions.</p><p>Looking at the rest of the code, two functions stand out in particular.</p><h3 id="h-contribute" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">contribute()</h3><p>This function will revert if we contribute an amount over <strong>0.001 ether</strong>, and we can only become the owner of the contract if we donate <strong>1000 ether</strong> through this function.</p><p>So let’s look for another way.</p><h3 id="h-receive" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">receive()</h3><p>If you are unfamiliar with what <strong>receive()</strong> is, it is basically the <strong>fallback</strong> function of this contract. What this means is that if you send a transaction to this contract with empty <strong>calldata</strong>, the transaction will end up triggering the <strong>receive()</strong> function instead.</p><blockquote><p><strong>calldata:</strong> Raw hexadecimal bytes sent with a transaction that specifies which external contract function you want to call, along with what parameters.</p></blockquote><p>With the basics out of the way, we notice that the receive function requires us to send some amount of money (obviously), and have some amount of a contribution.</p><p>If we fulfill both of these requirements, we can be assigned as the owner of the contract.</p><p>We can then use our ownership to empty the ether in the contract by calling <strong>withdraw()</strong>.</p><h3 id="h-the-attack" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">The attack</h3><p>Now we know we first need a contribution to become the owner of the contract, let’s write a Python3 script named &quot;<strong>fallback.py</strong>” that will:</p><ol><li><p><strong>Contribute 1 wei.</strong></p></li><li><p><strong>Send a transaction with no calldata.</strong></p></li><li><p><strong>Call the withdraw() function, emptying the contract.</strong></p></li></ol><h3 id="h-imports" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Imports</h3><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/5d0d50febeac280dc70c71287eb089f34b0b9d7dc19255a7000efccb1df5420d.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>We will only need these four modules for this challenge. Make sure to <strong>load_dotenv()</strong> before doing anything else, because we will need to import some variables from env soon.</p><p><strong>web3</strong> to interact with the Sepolia network.</p><p><strong>solcx</strong> to compile the Ethernaut contract and get the <strong>ABI</strong> needed to interact with the contract.</p><p><strong>dotenv</strong> &amp; <strong>os</strong> to read environment variables.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/ac9b21d0a0427d1dad389dc900f38e52e0c847024e5fd37d0e1881a9e51916ac.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>You can then load your <strong>private key</strong>, <strong>address</strong>, and <strong>provider</strong> like so.</p><h3 id="h-function-readcontractreturnabi" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Function -- read_contract_return_abi()</h3><p>This function will read “<strong>fallback.sol</strong>“ that exists in the same directory as our python script. In the file, we can copy the Fallback contract’s source code from Ethernaut.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/e6a2ba24882ee0c4633f83bd78499899c62115b93df8f83fc6f906af501cdc57.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>The function above first opens “<strong>fallback.sol</strong>“, installs <strong>solidity 0.8.0</strong> and compiles the contract using the source code.</p><p>Then, we get the <strong>ABI</strong>, which will allow us to encode/decode function calls. Without it, we wouldn’t be able to interact with the contract.</p><p>Finally, we return the contract object, which gives us an easy interface to encode function calls when interacting with the contract on Sepolia.</p><h3 id="h-function-signandsendtransaction" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Function -- sign_and_send_transaction()</h3><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/767f3735b5b33ec68430bb9a07547369b438eb72d5ed0a8791f050a2f9e5dbec.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>This function will allow us to sign the transactions we’ll need to exploit the contract.</p><p>We sign the transaction we want to send using our private key and store it in <strong>signed_tx</strong>, then get the receipt using the <strong>transaction hash</strong>, which allows us to look at details of our transactions, like if the transaction failed or not.</p><h3 id="h-attack" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Attack</h3><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d2b6ed881004b79ed3da36b9ee55d320165362468e8cefbbfd766f15caa4d00d.png" alt="Main function with instructions on how to attack the contract." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Main function with instructions on how to attack the contract.</figcaption></figure><p>We’ll now work on our main function, where we can now exploit the contract.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/6c6056913342eda7592b18ec72b9a8cd315ee607b767842f63e141879aa62d5a.png" alt="Getting the contract ABI." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Getting the contract ABI.</figcaption></figure><p>At the top of the main function is where we specify the <strong>gas</strong> and <strong>gas price</strong> we’ll use to send all of our transactions. <strong>web3.py</strong> does have modules to estimate how much gas a future transaction will use. But, I found that my transactions usually ran out of gas, so I’m using <strong>50,000 gas</strong> at <strong>5 gwei</strong>.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/84dd55bcca5b8df42168291a8aaa5f0eabd218e43abb013568145bd885ad3463.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Then we contribute to the contract, and save the receipt to analyze our transaction.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/02ee5954611c47a759937751fb217f7810830cad2407bc92cdbef3e357cd78ba.png" alt="Checking our contribution amount." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Checking our contribution amount.</figcaption></figure><p>Now we’ll check how much we contributed by calling <strong>contributions()</strong> with our address and save it in <strong>contribution</strong>. This is to make sure we actually contributed some amount to the contract.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/4cb62fdab96fd8062a73f31b322d0e5cda81ef723e56f55e2bb1e4fe5b86c9f5.png" alt="Logic if we contributed successfully." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Logic if we contributed successfully.</figcaption></figure><p>If we contributed successfully, we send the transaction with no calldata, then attempt to withdraw. The script will print a success message if the withdrawal worked, and the program will exit. Then submit your instance on Ethernaut and you’re done!</p><p>If you want to see the full code for this challenge, you can find it here:</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/imam-abbudi/ethernaut-web3py-solutions/blob/main/fallback/fallback.py">https://github.com/imam-abbudi/ethernaut-web3py-solutions/blob/main/fallback/fallback.py</a></p>]]></content:encoded>
            <author>abbudi@newsletter.paragraph.com (abbudi)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/f6088af1c9bdd27b9cbe0cf79d686639f486a06f209b0a99b5ef2bf0d2119fad.png" length="0" type="image/png"/>
        </item>
    </channel>
</rss>