<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Solidity on truegav</title>
		<link>/tags/solidity/</link>
		<description>Recent content in Solidity on truegav</description>
		<generator>Hugo</generator>
		<language>en-us</language>
		
		
		
		
			<lastBuildDate>Fri, 05 Jul 2024 14:00:00 +0530</lastBuildDate>
		
			<atom:link href="/tags/solidity/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>ecrecover has been lying for eight years and your code still trusts it</title>
				<link>/posts/ecrecover-has-been-lying-for-eight-years/</link>
				<pubDate>Fri, 05 Jul 2024 14:00:00 +0530</pubDate>
				<guid>/posts/ecrecover-has-been-lying-for-eight-years/</guid>
				<description>&lt;h2 id=&#34;the-liar-at-address-0x01&#34;&gt;The liar at address 0x01&lt;/h2&gt;&#xA;&lt;p&gt;There is a function baked into the EVM protocol at &lt;code&gt;0x01&lt;/code&gt; that has been deceiving developers since the Frontier release in 2015. Not a smart contract bug. Not a compiler issue. A precompile. Hardcoded into every Ethereum node. When ECDSA public key recovery succeeds, it returns the signer&amp;rsquo;s address. When recovery fails, it returns &lt;code&gt;address(0)&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Zero. The null address. Delivered with the emotional affect of a cinder block. No revert. No event. No error state. Just zero.&lt;/p&gt;</description>
			</item>
			<item>
				<title>You put msg.value in a loop and lost money, what did you expect</title>
				<link>/posts/msgvalue-in-loop-lost-money/</link>
				<pubDate>Thu, 28 Sep 2023 14:00:00 +0530</pubDate>
				<guid>/posts/msgvalue-in-loop-lost-money/</guid>
				<description>&lt;h2 id=&#34;the-variable-that-never-moves&#34;&gt;The variable that never moves&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;msg.value&lt;/code&gt; does not change inside a loop. That sentence has cost the crypto industry more than a hundred million dollars and it will cost more because the sentence is technically correct and the mental model of every developer who writes a loop is technically wrong and the EVM has no mechanism for caring about the distance between the two.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;msg.value&lt;/code&gt; is established once at the start of a transaction. It holds the total ether attached. It persists unchanged through every internal call, every delegatecall, and every iteration of every loop in the entire call tree. It never decreases. It never subdivides. It holds one number from the first instruction to the last.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Your inheritance chain is a crime scene and you are the suspect</title>
				<link>/posts/inheritance-chain-crime-scene/</link>
				<pubDate>Thu, 15 Jun 2023 14:00:00 +0530</pubDate>
				<guid>/posts/inheritance-chain-crime-scene/</guid>
				<description>&lt;h2 id=&#34;the-quiz&#34;&gt;The quiz&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-solidity&#34; data-lang=&#34;solidity&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;contract&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;A&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;foo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;virtual&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;pure&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;returns&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;A&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;contract&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;B&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;foo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;virtual&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;override&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;pure&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;returns&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;B&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;contract&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;C&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;foo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;virtual&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;override&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;pure&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;returns&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;C&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;contract&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;D&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;B&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;C&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;foo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;override&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;B&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;C&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;pure&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;returns&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;super&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;foo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What does &lt;code&gt;D.foo()&lt;/code&gt; return?&lt;/p&gt;&#xA;&lt;p&gt;If you said B, your diamond inheritance contains a bug and you do not know it. If you said C, you either understand C3 linearization or you guessed and your luck will expire on the next diamond you deploy. If you said some variation of &amp;ldquo;I have no idea,&amp;rdquo; congratulations on being honest. You are in the majority. The majority is where protocols get drained.&lt;/p&gt;</description>
			</item>
			<item>
				<title>OpenZeppelin fixed this five years ago and your code still has it, why</title>
				<link>/posts/openzeppelin-fixed-this-five-years-ago/</link>
				<pubDate>Wed, 18 May 2022 14:00:00 +0530</pubDate>
				<guid>/posts/openzeppelin-fixed-this-five-years-ago/</guid>
				<description>&lt;h2 id=&#34;two-functions&#34;&gt;Two functions&lt;/h2&gt;&#xA;&lt;p&gt;Solidity provides two encoding functions for preparing data before hashing. &lt;code&gt;abi.encode&lt;/code&gt; pads every argument to a full 32 bytes with zero-fill. &lt;code&gt;abi.encodePacked&lt;/code&gt; concatenates raw bytes with nothing separating adjacent arguments.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-solidity&#34; data-lang=&#34;solidity&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;abi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;encodePacked&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;address&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0xdead&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;uint256&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0xbeef&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;abi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;encodePacked&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;address&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0xdead000000000000000000000000000000000000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;uint16&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0xbeef&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These two calls produce identical byte output. An address with trailing zero bytes next to a small uint packs into the exact same bytestring as a different address next to a large uint. Hash this output and use it as a signature commitment. An attacker can forge equivalent messages by shifting the type boundary between the arguments because the padding that differentiates them does not exist.&lt;/p&gt;</description>
			</item>
			<item>
				<title>I found your extcodesize bug, I am better than your auditor, and I am tired</title>
				<link>/posts/extcodesize-better-than-your-auditor/</link>
				<pubDate>Thu, 10 Feb 2022 14:00:00 +0530</pubDate>
				<guid>/posts/extcodesize-better-than-your-auditor/</guid>
				<description>&lt;h2 id=&#34;the-liar-embedded-in-the-protocol&#34;&gt;The liar embedded in the protocol&lt;/h2&gt;&#xA;&lt;p&gt;extcodesize has been lying to Solidity developers since the Ethereum genesis block. Every developer discovers this lie during an active exploit. Never during development. Never during the audit. Never during code review. Always during a production incident while funds are exiting the protocol.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-solidity&#34; data-lang=&#34;solidity&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;isContract&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;address&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;view&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;returns&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;code&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This function is inside your deployed bytecode. It compiles without warnings. It passes every test you wrote. It is catastrophically wrong during the only moment in its operational lifetime when correctness matters.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Six years after the DAO and you still write this bug, fucking embarrassing</title>
				<link>/posts/reentrancy-six-years-after-dao/</link>
				<pubDate>Sun, 20 Jun 2021 14:00:00 +0530</pubDate>
				<guid>/posts/reentrancy-six-years-after-dao/</guid>
				<description>&lt;h2 id=&#34;the-beetle-that-will-outlive-you&#34;&gt;The beetle that will outlive you&lt;/h2&gt;&#xA;&lt;p&gt;The DAO was drained for sixty million dollars on June 17, 2016. I have reviewed twelve contracts in the last six months. Every single one contained the exact same reentrancy bug. All twelve were audited. Some by firms whose LinkedIn profiles you might recognize.&lt;/p&gt;&#xA;&lt;p&gt;If a bug could win a Darwin Award for persistence, this bug would have a trophy case the size of a warehouse. It has survived every EIP. Every hard fork. Every static analysis tool. Every blog post titled &amp;ldquo;How to Prevent Reentrancy Once and For All.&amp;rdquo; It is the roach of the EVM. It was here before you learned Solidity and it will be here after you retire.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Delegatecall is a war crime and I keep committing it</title>
				<link>/posts/delegatecall-war-crime/</link>
				<pubDate>Mon, 15 Mar 2021 14:00:00 +0530</pubDate>
				<guid>/posts/delegatecall-war-crime/</guid>
				<description>&lt;h2 id=&#34;three-opcodes-and-two-want-you-dead&#34;&gt;Three opcodes and two want you dead&lt;/h2&gt;&#xA;&lt;p&gt;The EVM provides three ways to invoke another contract.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;call&lt;/code&gt; sends ETH and returns data. Civilized. Predictable. What a normal engineer would design.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;staticcall&lt;/code&gt; is read-only and cannot modify state. Has never caused anyone harm.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;delegatecall&lt;/code&gt; runs the target&amp;rsquo;s bytecode inside your storage context. Your balance becomes their balance. Your identity becomes their identity. The target code reads your variables and writes to your slots using its own names. The EVM sits in the corner and allows this because the EVM was designed by people who considered this an acceptable tradeoff between code reuse and safety.&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
