<?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: RareSkills</title>
    <description>The latest articles on Forem by RareSkills (@rareskills).</description>
    <link>https://forem.com/rareskills</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%2F972226%2F6f4b42fb-c54d-4e7c-808f-1c7b987bb424.jpeg</url>
      <title>Forem: RareSkills</title>
      <link>https://forem.com/rareskills</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rareskills"/>
    <language>en</language>
    <item>
      <title>Smart Contract Security</title>
      <dc:creator>RareSkills</dc:creator>
      <pubDate>Tue, 09 May 2023 06:57:46 +0000</pubDate>
      <link>https://forem.com/rareskills/smart-contract-security-1bcp</link>
      <guid>https://forem.com/rareskills/smart-contract-security-1bcp</guid>
      <description>&lt;p&gt;This article serves as a mini-course on smart contract security and provides an extensive list of the issues and vulnerabilities that tend to recur in Solidity smart contracts.&lt;/p&gt;

&lt;p&gt;A security issue in Solidity boils down to smart contracts not behaving the way they were intended to. This can fall into four broad categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Funds getting stolen&lt;/li&gt;
&lt;li&gt;Funds getting locked up or frozen inside a contract&lt;/li&gt;
&lt;li&gt;People receive less rewards than anticipated (rewards are delayed or reduced)&lt;/li&gt;
&lt;li&gt;People receive more rewards than anticipated (leading to inflation and devaluation)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It isn’t possible to make a comprehensive list of everything that can go wrong. However, just as traditional software engineering has common themes of vulnerabilities such as SQL injection, buffer overruns, and cross site scripting, smart contracts have recurring anti-patterns that can be documented.&lt;/p&gt;

&lt;p&gt;Think of this guide as more of a reference. It isn’t possible to discuss everything concept in detail without turning this into a book (fair warning: this article is 10k+ words long, so feel free to bookmark it and read it in chunks). However, it serves as a list of what to look out for and what to study. If a topic feels unfamiliar, that should serve as an indicator that it is worth putting time into practicing identifying that class of vulnerability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;This article assumes basic proficiency in &lt;a href="https://www.rareskills.io/solidity-bootcamp"&gt;Solidity&lt;/a&gt;. If you are new to Solidity, please see our &lt;a href="https://www.rareskills.io/learn-solidity"&gt;free Solidity tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reentrancy
&lt;/h2&gt;

&lt;p&gt;We’ve written extensively on &lt;a href="https://notion.so/Smart-Contract-Auditing-0d29d798ef9346758c0379f565975ef4"&gt;smart contract reentrancy&lt;/a&gt; so we won’t repeat it here. But here is a quick summary:&lt;/p&gt;

&lt;p&gt;Whenever a smart contract calls the function of another smart contract, sends Ether to it, or transfers a token to it, then there is a possibility of re-entrancy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When Ether is transferred, the receiving contract’s fallback or receive function is called. This hands control over to the receiver.&lt;/li&gt;
&lt;li&gt;Some token protocols alert the receiving smart contract that they have received the token by calling a predetermined function. This hands the control flow over to that function.&lt;/li&gt;
&lt;li&gt;When an attacking contract receives control, it doesn’t have to call the same function that handed over control. It could call a different function in the victim smart contract (cross-function reentrancy) or even a different contract (cross-contract reentrancy)&lt;/li&gt;
&lt;li&gt;Read-only reentrancy happens when a view function is accessed while the contract is in an intermediate state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Despite reentrancy likely being the most well known smart contract vulnerability, it only makes up a small percentage of hacks that happen in the wild. Security researcher Pascal Caversaccio (pcaveraccio) keeps an up-to-date github &lt;a href="https://github.com/pcaversaccio/reentrancy-attacks"&gt;list of reentrancy attacks&lt;/a&gt;. As of April 2023, 46 reentrancy attacks have been documented in that repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Access Control
&lt;/h2&gt;

&lt;p&gt;It seems like a simple mistake, but forgetting to place restrictions on who can call a sensitive function (like withdrawing ether or changing ownership) happens surprisingly often.&lt;/p&gt;

&lt;p&gt;Even if a modifier is in place, there have been cases where the modifier was not implemented correctly, such as in the example below where the require statement is missing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// DO NOT USE!
modifier onlyMinter {
    minters[msg.sender] == true_;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This above code is a real example from this audit: &lt;a href="https://code4rena.com/reports/2023-01-rabbithole/#h-01-bad-implementation-in-minter-access-control-for-rabbitholereceipt-and-rabbitholetickets-contracts"&gt;https://code4rena.com/reports/2023-01-rabbithole/#h-01-bad-implementation-in-minter-access-control-for-rabbitholereceipt-and-rabbitholetickets-contracts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is another way access control can go wrong&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function claimAirdrop(bytes32 calldata proof[]) {

    bool verified = MerkleProof.verifyCalldata(proof, merkleRoot, keccak256(abi.encode(msg.sender)));
    require(verified, "not verified");
    require(alreadyClaimed[msg.sender], "already claimed");

    _transfer(msg.sender, AIRDROP_AMOUNT);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In this case, “alreadyClaimed” is never set to true, so the claimant can issue call the function multiple times.&lt;/p&gt;
&lt;h2&gt;
  
  
  Real life example: Trader bot exploited
&lt;/h2&gt;

&lt;p&gt;A fairly recent example of insufficient access control was an unprotected function to receive flashloans by a trading bot (which went by the name 0xbad, as the address started with that sequence). It racked up over a million dollars in profit until one day an attacker noticed any address could call the flashloan receive function, not just the flashloan provider.&lt;/p&gt;

&lt;p&gt;As is usually the case with trading bots, the smart contract code to execute the trades was not verified, but the attacker discovered the weakness anyway. More info in the &lt;a href="https://rekt.news/ripmevbot/"&gt;rekt news&lt;/a&gt; coverage.&lt;/p&gt;
&lt;h2&gt;
  
  
  Improper Input Validation
&lt;/h2&gt;

&lt;p&gt;If access control is about controlling who calls a function, input validation is about controlling what they call the contract with.&lt;/p&gt;

&lt;p&gt;This usually comes down to forgetting to put the proper require statements in place.&lt;/p&gt;

&lt;p&gt;Here is a rudimentary example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract UnsafeBank {
    mapping(address =&amp;gt; uint256) public balances;

    // allow depositing on other's behalf
    function deposit(address for) public payable {
        balances += msg.value;
    }

    function withdraw(address from, uint256 amount) public {
        require(balances[from] &amp;lt;= amount, "insufficient balance");

        balances[from] -= amount;
        msg.sender.call{value: amout}("");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The contract above does check that you aren’t withdrawing more than you have in your account, but it doesn’t stop you from withdrawing from an arbitrary account.&lt;/p&gt;
&lt;h2&gt;
  
  
  Real life example: Sushiswap
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.sushi.com/"&gt;Sushiswap&lt;/a&gt; experienced a hack of this type due to one of the parameters of an external function not being sanitized.&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
    &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__two-pics"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UfATtOXm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://pbs.twimg.com/media/FtPiV67aUAEVXq5.jpg" alt="unknown tweet media content"&gt;
    &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--nhQWwus3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://pbs.twimg.com/profile_images/987282435812421632/pYNsUGGp_normal.jpg" alt="PeckShield Inc. profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        PeckShield Inc.
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @peckshield
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kDgU_xDI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      It seems the &lt;a href="https://twitter.com/SushiSwap"&gt;@SushiSwap&lt;/a&gt;  RouterProcessor2 contact has an approve-related bug, which leads to the loss of  &amp;gt;$3.3M loss (about 1800 eth)  from &lt;a href="https://twitter.com/0xSifu"&gt;@0xSifu&lt;/a&gt;. &lt;br&gt;&lt;br&gt;If you have approved &lt;a href="https://t.co/E1YvC6VZsP"&gt;etherscan.io/address/0x044b…&lt;/a&gt;, please *REVOKE* ASAP!&lt;br&gt;&lt;br&gt;One example hack tx: &lt;a href="https://t.co/ldg0ww3hAN"&gt;etherscan.io/tx/0xea3480f1f…&lt;/a&gt; &lt;a href="https://t.co/hJURVmx481"&gt;twitter.com/i/web/status/1…&lt;/a&gt; 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      03:36 AM - 09 Apr 2023
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1644907207530774530" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OXOJJiQT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1644907207530774530" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--foTp-unf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1644907207530774530" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SFHqU4bF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is the difference between improper access control and improper input validation?
&lt;/h2&gt;

&lt;p&gt;Improper access control means msg.sender does not have adequate restrictions. Improper input validation means the arguments to the function are not sufficiently sanitized. There is also an inverse to this anti-pattern: placing too much restriction on a function call.&lt;/p&gt;
&lt;h2&gt;
  
  
  Excessive function restriction
&lt;/h2&gt;

&lt;p&gt;Excessive validation probably means funds won’t get stolen, but it could mean funds get locked into the contract. Having too many safeguards in place is not a good thing either.&lt;/p&gt;
&lt;h2&gt;
  
  
  Real life example: Akutars NFT
&lt;/h2&gt;

&lt;p&gt;One of the most high-profile incidents was the Akutars NFT which ended up with 34 million dollars worth of Eth stuck inside the smart contract and unwithdrawable.&lt;/p&gt;

&lt;p&gt;The contract had a well-intentioned mechanism to prevent the owner of the contract from withdrawing until all refunds from paying above the dutch auction price had been given. But due to a bug documented in the Twitter thread linked below, the owner was unable to withdraw the funds.&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--NItzaCDy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://pbs.twimg.com/profile_images/1614130178569162752/afuhYNnz_normal.png" alt="0xInuarashi profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        0xInuarashi
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @0xinuarashi
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kDgU_xDI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      &lt;a href="https://t.co/A9lobVZC3p"&gt;etherscan.io/address/0xf42c…&lt;/a&gt;&lt;br&gt;34 Million USD gone. Just like that. Locked in the contract forever.&lt;br&gt;&lt;br&gt;A lot of people put light on the grieving which locked processRefunds() for a bit, that was the first exploit.&lt;br&gt;&lt;br&gt;Luckily that was unlocked, but funds are still locked forever. How?&lt;br&gt;&lt;br&gt;🧵 1/
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      01:19 AM - 23 Apr 2022
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1517674505975394304" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OXOJJiQT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1517674505975394304" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--foTp-unf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1517674505975394304" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SFHqU4bF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Getting the balance right
&lt;/h2&gt;

&lt;p&gt;Sushiswap gave too much power to untrusted users, and the Akutars NFT gave too little power to the admin. When designing smart contracts, a subjective judgement about how much liberty each class of users must be made, and this decision cannot be left to automated testing and tooling. There are significant tradeoffs with decentralization, security, and UX that must be considered.&lt;/p&gt;

&lt;p&gt;For the smart contract programmer, explicitly writing out what users should and should not be able to do with certain functions is an important part of the development process.&lt;/p&gt;

&lt;p&gt;We will revisit the topic of overpowered admins later.&lt;/p&gt;
&lt;h2&gt;
  
  
  Security often boils down to managing the way money exits the contract
&lt;/h2&gt;

&lt;p&gt;As stated in the introduction, there are four primary ways smart contracts get hacked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Money stolen&lt;/li&gt;
&lt;li&gt;Money frozen&lt;/li&gt;
&lt;li&gt;Insufficient rewards&lt;/li&gt;
&lt;li&gt;Excessive rewards&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;“Money” here means anything of value, such as tokens, not just cryptocurrency. When coding or auditing a smart contract, the developer must be conscientious of the intended ways value is to flow in and out of the contract. The issues listed above are the primary ways smart contracts get hacked, but there are a lot of other root causes that can cascade into major issues, which are documented below.&lt;/p&gt;
&lt;h2&gt;
  
  
  Double voting or msg.sender spoofing
&lt;/h2&gt;

&lt;p&gt;Using vanilla ERC20 tokens or NFTs as tickets to weigh vote is unsafe because attackers can vote with one address, transfer the tokens to another address, and vote again from that address.&lt;/p&gt;

&lt;p&gt;Here is a minimal example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// A malicious voter can simply transfer their tokens to
// another address and vote again.
contract UnsafeBallot {

    uint256 public proposal1VoteCount;
    uint256 public proposal2VoteCount;

    IERC20 immutable private governanceToken;

    constructor(IERC20 _governanceToken) {
        governanceToken = _governanceToken;
    }

    function voteFor1() external notAlreadyVoted {
        proposal1VoteCount += governanceToken.balanceOf(msg.sender);
    }

    function voteFor2() external notAlreadyVoted {
        proposal2VoteCount += governanceToken.balanceOf(msg.sender);
    }

    // prevent the same address from voting twice,
    // however the attacker can simply
    // transfer to a new address
    modifier notAlreadyVoted {
        require(!alreadyVoted[msg.sender], "already voted");
        _;
        alreadyVoted[msg.sender] = true;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To prevent this attack, ERC20 Snapshot or ERC20 Votes should be used. By snapshotting a point of time in the past, the current token balances cannot be manipulated to gain illicit voting power.&lt;/p&gt;
&lt;h2&gt;
  
  
  Flashloan Governance Attacks
&lt;/h2&gt;

&lt;p&gt;However, using an ERC20 token with a snapshot or vote capability doesn’t fully solve the problem if someone can take a flashloan to temporarily increase their balance, then take a snapshot of their balance in the same transaction. If that snapshot is used for voting, they will have an unreasonably large amount of votes at their disposal.&lt;/p&gt;

&lt;p&gt;A flashloan lends a large amount of Ether or token to an address, but reverts if the money is not repaid in the same transaction.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract SimpleFlashloan {

    function borrowERC20Tokens() public {
        uint256 before = token.balanceOf(address(this));

        // send tokens to the borrower
        token.transfer(msg.sender, amount);

        // hand control back to the borrower to 
        // let them do something
        IBorrower(msg.sender).onFlashLoan();

        // require that the tokens got returned
        require(token.balanceOf(address(this) &amp;gt;= before);
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;An attacker can use a flashloan to suddenly gain a lot of votes to swing proposals in their favor and/or do something malicious.&lt;/p&gt;
&lt;h2&gt;
  
  
  Flashloan Price Attacks
&lt;/h2&gt;

&lt;p&gt;This is arguably the most common (or at least most high-profile) attack on DeFi, accounting for hundreds of millions of dollars lost. Here is a list of high profile ones.&lt;/p&gt;

&lt;p&gt;The price of an asset on the &lt;a href="https://www.rareskills.io/web3-blockchain-bootcamps"&gt;blockchain&lt;/a&gt; is often calculated as the current exchange rate between assets. For example, if a contract is currently trading 1 USDC for 100 k9coin, then you could say k9coin has a price of 0.01 USDC. However, prices generally move in response to buying and selling pressure, and flash loans can create massive buying and selling pressure.&lt;/p&gt;

&lt;p&gt;When querying another smart contract about the price of an asset, the developer needs to be very careful because they are assuming the smart contract they are calling is immune to flash loan manipulation.&lt;/p&gt;
&lt;h2&gt;
  
  
  Bypassing the contract check
&lt;/h2&gt;

&lt;p&gt;You can “check” if an address is a smart contract by looking at it’s bytecode size. Externally owned accounts (regular wallets) don’t have any bytecode. Here are a few ways of doing it&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import "@openzeppelin/contracts/utils/Address.sol"
contract CheckIfContract {

    using Address for address;

    function addressIsContractV1(address _a) {
        return _a.code.length == 0;
    }

    function addressIsContractV2(address _a) {

        // use the openzeppelin libraryreturn _a.isContract();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;However, this has a few limitations&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a contract makes an external call from a constructor, then it’s apparent bytecode size will be zero because the smart contract deployment code hasn’t returned the runtime code yet&lt;/li&gt;
&lt;li&gt;The space might be empty now, but an attacker might know they can deploy a smart contract there in the future using create2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In general checking if an address is a contract is usually (but not always) an antipattern. Multisignature wallets are smart contracts themselves, and doing anything that might break multisignature wallets breaks composability.&lt;/p&gt;

&lt;p&gt;The exception to this is checking if the target is a smart contract before calling a transfer hook. More on this later.&lt;/p&gt;
&lt;h2&gt;
  
  
  tx.origin
&lt;/h2&gt;

&lt;p&gt;There is rarely a good reason to use tx.origin. If tx.origin is used to identify the sender, then a man-in-the-middle attack is possible. If the user is tricked into calling a malicious smart contract, then the smart contract can use all the authority tx.origin has to wreak havoc.&lt;/p&gt;

&lt;p&gt;Consider this following exercise and the comments above the code.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract Phish {
    function phishingFunction() public {

        // this fails, because this contract does not have approval/allowance
        token.transferFrom(msg.sender, address(this), token.balanceOf(msg.sender));

        // this also fails, because this creates approval for the contract,// not the wallet calling this phishing function
        token.approve(address(this), type(uint256).max);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This does not mean you are safe calling arbitrary smart contracts. But there is a layer of safety built into most protocols that will be bypassed if tx.origin is used for authentication.&lt;/p&gt;

&lt;p&gt;Sometimes, you might see code that looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require(msg.sender == tx.origin, "no contracts");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When a smart contract calls another smart contract, msg.sender will be the smart contract and tx.origin will be the user’s wallet, thus giving a reliable indication that the incoming call is from a smart contract. This is true even if the call happens from the constructor.&lt;/p&gt;

&lt;p&gt;Most of the time, this design pattern not a good idea. Multisignature wallets and Wallets from EIP 4337 won’t be able to interact with a function that has this code. This pattern can commonly be seen in NFT mints, where it’s reasonable to expect most users are using a traditional wallet. But as account abstraction becomes more popular, this pattern will hinder more than it helps.&lt;/p&gt;
&lt;h2&gt;
  
  
  Gas Griefing or Denial of Service
&lt;/h2&gt;

&lt;p&gt;A griefing attack means the hacker is trying to "cause grief" for other people, even if they don't gain economically from doing so.&lt;/p&gt;

&lt;p&gt;A smart contract can maliciously use up all the gas forwarded to it by going into an infinite loop. Consider the following example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract Mal {

    fallback() external payable {

        // infinite loop uses up all the gas
        while (true) {

        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If another contract distributes ether to a list of addresses such as follows:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract Distribute {
    funtion distribute(uint256 total) public nonReentrant {
        for (uint i; i &amp;lt; addresses.length; ) {

            (bool ok, ) addresses.call{value: total / addresses.length}("");
            // ignore ok, if it reverts we move on
            // traditional gas saving trick for for loops
            unchecked {
                ++i;
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then the function will revert when it sends ether to Mal. The call in the code above forwards 63 / 64 of the gas available (read more about this rule in &lt;a href="https://www.rareskills.io/post/eip-150-and-the-63-64-rule-for-gas"&gt;our article on EIP 150&lt;/a&gt;), so there likely won’t be enough gas to complete the operation with only 1/64 of the gas left.&lt;/p&gt;

&lt;p&gt;A smart contract can return a large memory array that consumes a lot of gas&lt;/p&gt;

&lt;p&gt;Consider the following example&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function largeReturn() public {

    // result might be extremely long!
    (book ok, bytes memory result) =     
        otherContract.call(abi.encodeWithSignature("foo()"));

    require(ok, "call failed");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Memory arrays use up quadratic amount of gas after 724 bytes, so a carefully chosen return data size can grief the caller.&lt;/p&gt;

&lt;p&gt;Even if the variable result is not used, it is still copied to memory. If you want to restrict the return size to a certain amount, you can use assembly&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function largeReturn() public {
    assembly {
        let ok := call(gas(), destinationAddress, value, dataOffset, dataSize, 0x00, 0x00);
        // nothing is copied to memory until you 
        // use returndatacopy()
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Deleting arrays that others can add to is also an denial of service vector
&lt;/h2&gt;

&lt;p&gt;Although erasing storage is a gas-efficient operation, it still has a net cost. If an array becomes too long, it becomes impossible to delete. Here is a minimal example&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract VulnerableArray {

    address[] public stuff;

    function addSomething(address something) public {
        stuff.push(something);
    }

    // if stuff is too long, this will become undeletable due to
    // the gas cost
    function deleteEverything() public onlyOwner {
        delete stuff;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  ERC777, ERC721, and ERC1155 can also be griefing vectors
&lt;/h2&gt;

&lt;p&gt;If a smart contract transfers tokens that have transfer hooks, an attacker can set up a contract that does not accept the token (it either does not have an onReceive function or programs the function to revert). This will make the token untransferable and cause the entire transaction to revert.&lt;/p&gt;

&lt;p&gt;Before using safeTransfer or transfer, consider the possibility that the receiver might force the transaction to revert.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract Mal is IERC721Receiver, IERC1155Receiver, IERC777Receiver {

    // this will intercept any transfer hook
    fallback() external payable {

        // infinite loop uses up all the gaswhile (true) {

        }
    }

    // we could also selectively deny transactions
    function onERC721Received(address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4) {

        if (wakeUpChooseViolence()) {
            revert();
        }
        else {
            return IERC721Receiver.onERC721Received.selector;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Insecure Randomness
&lt;/h2&gt;

&lt;p&gt;It is currently not possible to generate randomness securely with a single transaction on the blockchain. Blockchains need to be fully deterministic, otherwise distributed nodes would not be able to reach a consensus about the state. Because they are fully deterministic, any “random” number can be predicted. The following dice rolling function can be exploited.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract UnsafeDice {
    function randomness() internal returns (uint256) {
        return keccak256(abi.encode(msg.sender, tx.origin, block.timestamp, tx.gasprice, blockhash(block.number - 1);
    }

    // our dice can land on one of {0,1,2,3,4,5}function rollDice() public payable {
        require(msg.value == 1 ether);

        if (randomness() % 6) == 5) {
            msg.sender.call{value: 2 ether}("");
        }
    }
}

contract ExploitDice {
    function randomness() internal returns (uint256) {
        return keccak256(abi.encode(msg.sender, tx.origin, block.timestamp, tx.gasprice, blockhash(block.number - 1);
    }

    function betSafely(IUnsafeDice game) public payable {
        if (randomness % 6) == 5)) {
            game.betSafely{value: 1 ether}()
        }

        // else don't do anything
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It doesn’t matter how you generate randomness because an attacker can replicate it exactly. Throwing in more sources of “entropy” such as the msg.sender, timestamp, etc won’t have any effect because the smart contract can measure it two.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using the Chainlink Randomness Oracle Wrong
&lt;/h2&gt;

&lt;p&gt;Chainlink is a popular solution to get secure random numbers. It does it in two steps. First, the smart contracts sends a randomness request to the oracle, then some blocks later, the oracle responds with a random number.&lt;/p&gt;

&lt;p&gt;Since an attacker can’t predict the future, they can’t predict the random number.&lt;/p&gt;

&lt;p&gt;Unless the smart contract uses the oracle wrong.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The smart contract requesting randomness must not do anything until the random number is returned. Otherwise, an attacker can monitor the mempool for the oracle returning the randomness and frontrun the oracle, knowing what the random number will be.&lt;/li&gt;
&lt;li&gt;The randomness oracles themselves might try to manipulate your application. They cannot pick random numbers without consensus from other nodes, but they can withhold and re-order random numbers if your application requests several at the same time.&lt;/li&gt;
&lt;li&gt;Finality is not instant on &lt;a href="https://www.rareskills.io/post/solidity-precompiles"&gt;Ethereum&lt;/a&gt; or most other EVM chains. Just because some block is the most recent one, it doesn’t mean it won’t necessarily stay that way. This is called a “chain re-org”. In fact, the chain can alter more than just the final block. This is called the “re-org depth.” Etherscan reports re-orgs for various chains, for example Ethereum reorgs and Polygon reorgs. Reorgs can be as deep as 30 or more blocks on Polygon, so waiting fewer blocks can make the application vulnerable (this may change when the zk-evm becomes the standard consensus on Polygon, because the finality will match Ethereum’s but this is a future prediction, not a fact about the present).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are the other chainlink randomness security considerations.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting stale data from a price Oracle
&lt;/h2&gt;

&lt;p&gt;There is no SLA (service level agreement) for Chainlink to keep it’s price oracles up to date within a certain time frame. When the chain is severely congested (such as when the Yuga Labs &lt;a href="https://opensea.io/collection/otherdeed"&gt;Otherside&lt;/a&gt; mint &lt;a href="https://decrypt.co/99256/bored-ape-creators-slammed-nightmare-ethereum-nft-land-drop"&gt;overwhealmed Ethereum&lt;/a&gt; to the point of no transactions going through), the price updates might be delayed.&lt;/p&gt;

&lt;p&gt;A smart contract that uses a price oracle must explicitly check the data is not stale, I.e. has been updated recently within some threshold. Otherwise, it cannot make a reliable decision with respect to prices.&lt;/p&gt;

&lt;p&gt;There is an added complication that if the price doesn’t change past a &lt;a href="https://blog.chain.link/chainlink-price-feeds-secure-defi/"&gt;deviation threshold&lt;/a&gt;, the oracle might not update the price to save gas, so this could affect what time threshold is considered “stale.”&lt;/p&gt;

&lt;p&gt;It is important to understand the SLA of an oracle a smart contract relies on.&lt;/p&gt;
&lt;h2&gt;
  
  
  Relying on only one oracle
&lt;/h2&gt;

&lt;p&gt;No matter how secure an oracle seems, an attack may be discovered in the future. The only defense against this is to use multiple independent oracles.&lt;/p&gt;
&lt;h2&gt;
  
  
  Oracles in general are hard to get right
&lt;/h2&gt;

&lt;p&gt;The blockchain can be quite secure, but putting data onto the chain in the first place necessitates some kind of off-chain operation which forgoes all the security guarantees blockchains provides. Even if oracles remain honest, their source of data can be manipulated. For example, an oracle can reliably report prices from a centralized exchange, but those can be manipulated with large buy and sell orders. Similarly, oracles that depend on sensor data or some web2 API are subject to traditional hacking vectors.&lt;/p&gt;

&lt;p&gt;A good smart contract architecture avoids the use of oracles altogether where possible.&lt;/p&gt;
&lt;h2&gt;
  
  
  Mixed accounting
&lt;/h2&gt;

&lt;p&gt;Consider the following contract&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract MixedAccounting {
    uint256 myBalance;

    function deposit() public payable {
        myBalance = myBalance + msg.value;
    }

    function myBalanceIntrospect() public view returns (uint256) {
        return address(this).balance;
    }

    function myBalanceVariable() public view returns (uint256) {
        return myBalance;
    }

    function notAlwaysTrue() public view returns (bool) {
        return myBalanceIntrospect() == myBalanceVariable();
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The contract above does not have a receive or fallback function, so directly transferring Ether to it will revert. However, a contract can forcefully send Ether to it with selfdestruct. In that case, myBalanceIntrospect() will be greater than myBalanceVariable(). Ether accounting method is fine, but if you use both, then the contract may have inconsistent behavior.&lt;/p&gt;

&lt;p&gt;The same applies for ERC20 tokens.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract MixedAccountingERC20 {

    IERC20 token;
    uint256 myTokenBalance;

    function deposit(uint256 amount) public {
        token.transferFrom(msg.sender, address(this), amount);
        myTokenBalance = myTokenBalance + amount;
    }

    function myBalanceIntrospect() public view returns (uint256) {
        return token.balanceOf(address(this));
    }

    function myBalanceVariable() public view returns (uint256) {
        return myTokenBalance;
    }

    function notAlwaysTrue() public view returns (bool) {
        return myBalanceIntrospect() == myBalanceVariable();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Again we cannot assume that myBalanceIntrospect() and myBalanceVariable() will always return the same value. It is possible to directly transfer ERC20 tokens to MixedAccountingERC20, bypassing the deposit function and not updating the myTokenBalance variable.&lt;/p&gt;

&lt;p&gt;When checking the balances with introspection, strict using equality checks should be avoided as the balance can be changed by an outsider at will.&lt;/p&gt;
&lt;h2&gt;
  
  
  Treating cryptographic proofs like passwords
&lt;/h2&gt;

&lt;p&gt;This isn’t a quirk of Solidity, more of a common misunderstanding among developers about how to use cryptography to give addresses special privileges. The following code is insecure&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract InsecureMerkleRoot {
    bytes32 merkleRoot;
    function airdrop(bytes[] calldata proof, bytes32 leaf) external {

        require(MerkleProof.verifyCalldata(proof, merkleRoot, leaf), "not verified");
        require(!alreadyClaimed[leaf], "already claimed airdrop");
        alreadyClaimed[leaf] = true;

        mint(msg.sender, AIRDROP_AMOUNT);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This code is insecure for three reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Anyone who knows the addresses that are selected for the airdrop can recreate the merkle tree and create a valid proof. &lt;/li&gt;
&lt;li&gt;The leaf isn’t hashed. An attacker can submit a leaf that equals the merkle root and bypass the require statement.&lt;/li&gt;
&lt;li&gt;Even if the above two issues are fixed, once someone submits a valid proof, they can be frontrun.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cryptographic proofs (merkle trees, signatures, etc) need to be tied to msg.sender, which an attacker cannot manipulate without acquiring the private key.&lt;/p&gt;
&lt;h2&gt;
  
  
  Solidity does not upcast to the final uint size
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function limitedMultiply(uint8 a, uint8 b) public pure returns (uint256 product) {
    product = a * b;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Although product is a uint256 variable, the multiplication result cannot be larger than 255 or the code will revert.&lt;/p&gt;

&lt;p&gt;This issue can be mitigated by individually upcasting each variable.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function unlimitedMultiply(uint8 a, uint8 b) public pure returns (uint256 product) {
    product = uint256(a) * uint256(b);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A situation like this can occur if multiplying integers packed in a struct. You should be mindful of this when multiplying small values that were packed in a struct&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct Packed {
    uint8 time;
    uint16 rewardRate
}

//...

Packed p;
p.time * p.rewardRate; // this might revert!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Solidity downcasting does not revert on overflow
&lt;/h2&gt;

&lt;p&gt;Solidity does not check if it is safe to cast an integer to a smaller one. Unless some business logic ensures that the downcasting is safe, a library like SafeCast should be used.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function test(int256 value) public pure returns (int8) {
    return int8(value + 1); // overflows and does not revert
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Writes to storage pointers don’t save new data.
&lt;/h2&gt;

&lt;p&gt;The code looks like it copies the data in myArray[1] to myArray[0], but it doesn’t. If you comment out the final line in the function, the compiler will say the function should be turned to a view function. The write to foo doesn’t write to the underlying storage.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract DoesNotWrite {
    struct Foo {
        uint256 bar;
    }
    Foo[] public myArray;

    function moveToSlot0() external {
        Foo storage foo = myArray[0];
        foo = myArray[1]; // myArray[0] is unchanged
        // we do this to make the function a state 
        // changing operation
        // and silence the compiler warning
        myArray[1] = Foo({bar: 100});
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So don’t write to storage pointers.&lt;/p&gt;
&lt;h2&gt;
  
  
  Deleting structs that contain dynamic datatypes does not delete the dynamic data
&lt;/h2&gt;

&lt;p&gt;If a mapping (or dynamic array) is inside a struct, and the struct is deleted, the mapping or array will not be deleted.&lt;/p&gt;

&lt;p&gt;With the exception of deleting an array, the delete keyword can only delete one storage slot. If the storage slot contains references to other storage slots, those won’t be deleted.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract NestedDelete {

    mapping(uint256 =&amp;gt; Foo) buzz;

    struct Foo {
        mapping(uint256 =&amp;gt; uint256) bar;
    }

    Foo foo;

    function addToFoo(uint256 i) external {
        buzz[i].bar[5] = 6;
    }

    function getFromFoo(uint256 i) external view returns (uint256) {
        return buzz[i].bar[5];
    }

    function deleteFoo(uint256 i) external {
        // internal map still holds the data in the 
        // mapping and array
        delete buzz[i];
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now let’s do the following transaction sequence&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;addToFoo(1)&lt;/li&gt;
&lt;li&gt;getFromFoo(1) returns 6&lt;/li&gt;
&lt;li&gt;deleteFoo(1)&lt;/li&gt;
&lt;li&gt;getFromFoo(1) still returns 6!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember, maps are never “empty” in Solidity. So if someone accesses an item which has been deleted, the transaction will not revert but instead return the zero value for that datatype.&lt;/p&gt;
&lt;h2&gt;
  
  
  ERC20 token issues
&lt;/h2&gt;

&lt;p&gt;If you only deal with trusted ERC20 tokens, most of these issues do not apply. However, when interacting with an arbitrary or partially untrusted ERC20 token, here are some things to watch out for.&lt;/p&gt;
&lt;h2&gt;
  
  
  ERC20: Fee on transfer
&lt;/h2&gt;

&lt;p&gt;When dealing with untrusted tokens, you shouldn’t assume that your balance necessarily increases by the amount. It is possible for an ERC20 token to implement it’s transfer function as follows:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract ERC20 {

    // internally called by transfer() and transferFrom()
    // balance and approval checks happen in the caller
    function _transfer(address from, address to, uint256 amount) internal returns (bool) {
        fee = amount * 100 / 99;

        balanceOf[from] -= to;
        balanceOf[to] += (amount - fee);

        balanceOf[TREASURY] += fee;

        emit Transfer(msg.sender, to, (amount - fee));
        return true;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This token applies a 1% tax to every transaction. So if a smart contract interacts with the token as follows, we will either get unexpected reverts or stolen money.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract Stake {

    mapping(address =&amp;gt; uint256) public balancesInContract;

    function stake(uint256 amount) public {
        token.transferFrom(msg.sender, address(this), amount);

        balancesInContract[msg.sender] += amount; // THIS IS WRONG!
    }

    function unstake() public {
        uint256 toSend = balancesInContract[msg.sender];
        delete balancesInContract[msg.sender];

        // this could revert because toSend is 1% greater than// the amount in the contract. Otherwise, 1% will be "stolen"// from other depositors.
        token.transfer(msg.sender, toSend);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  ERC20: rebasing tokens
&lt;/h2&gt;

&lt;p&gt;The rebasing token was popularized by &lt;a href="https://www.olympusdao.finance/"&gt;Olympus DAO&lt;/a&gt;’s sOhm token and &lt;a href="https://www.ampleforth.org/"&gt;Ampleforth’s&lt;/a&gt; AMPL token. Coingecko maintains a &lt;a href="https://www.coingecko.com/en/categories/rebase-tokens"&gt;list&lt;/a&gt; of rebasing ERC20 tokens.&lt;/p&gt;

&lt;p&gt;When a token rebases, the total supply changes and everyone’s balance increases or decreases depending on the rebase direction.&lt;/p&gt;

&lt;p&gt;The following code is likely to break when dealing with a rebasing token&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract WillBreak {
    mapping(address =&amp;gt; uint256) public balanceHeld;
    IERC20 private rebasingToken

    function deposit(uint256 amount) external {
        balanceHeld[msg.sender] = amount;
        rebasingToken.transferFrom(msg.sender, address(this), amount);
    }

    function withdraw() external {
        amount = balanceHeld[msg.sender];
        delete balanceHeld[msg.sender];

        // ERROR, amount might exceed the amount 
        // actually held by the contract
        rebasingToken.transfer(msg.sender, amount);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The solution of many contracts is to simply disallow rebasing tokens. However, one could modify the code above to check balanceOf(address(this)) before transfering the account balance to the sender. Then it would still work even if the balance changes.&lt;/p&gt;
&lt;h2&gt;
  
  
  ERC20: ERC777 in ERC20 clothing
&lt;/h2&gt;

&lt;p&gt;ERC20, if implemented according to the standard, ERC20 tokens do not have transfer hooks, and thus transfer and transferFrom do not have a reentrancy issue.&lt;/p&gt;

&lt;p&gt;There are meaningful advantages to tokens with transfer hooks, which is why all NFT standards implement them, and why ERC777 was finalized. However, it’s caused enough confusion that Openzeppelin &lt;a href="https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4066"&gt;deprecated&lt;/a&gt; the ERC777 library.&lt;/p&gt;

&lt;p&gt;If you want your protocol to be compatible with tokens that behave like ERC20 tokens but have transfer hooks, then it’s a simple matter of treating the functions transfer and transferFrom like they will issue a function call to the receiver.&lt;/p&gt;

&lt;p&gt;This ERC777 re-entrancy happened to Uniswap (Openzeppelin documented the exploit here if you are curious).&lt;/p&gt;

&lt;p&gt;ERC20: Not all ERC20 tokens return true&lt;/p&gt;

&lt;p&gt;The ERC20 specification dictates that an &lt;a href="https://www.rareskills.io/post/erc20-snapshot"&gt;ERC20 token must return true when a transfer succeeds&lt;/a&gt;. Because most ERC20 implementations cannot fail unless the allowance is insufficient or the amount transferred is too much, most devs have become accustomed to ignoring the return value of ERC20 tokens and assuming a failed transfer will revert.&lt;/p&gt;

&lt;p&gt;Frankly, this is not consequential if you are only working with a trusted ERC20 token you know the behavior of. But when dealing with arbitrary ERC20 tokens, this variance in behavior must be accounted for.&lt;/p&gt;

&lt;p&gt;There is an implicit expectation in many contracts that failed transfers should always revert, not return false because most ERC20 tokens don’t have a mechanism to return false, so this has lead to a lot of confusion.&lt;/p&gt;

&lt;p&gt;Further complicating this matter is that some ERC20 tokens don’t follow the protocol of returning true, notably Tether. Some tokens revert on a failure to transfer, which will cause the revert to bubble up to the caller. Thus, some libraries wrap ERC20 token transfer calls to intercept the revert and return a boolean instead. Here are some implementations&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol"&gt;Openzeppelin SafeTransfer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Vectorized/solady/blob/main/src/utils/SafeTransferLib.sol"&gt;Solady SafeTransfer&lt;/a&gt; (considerably more gas efficient)&lt;/p&gt;
&lt;h2&gt;
  
  
  ERC20: Address Poisoning
&lt;/h2&gt;

&lt;p&gt;This is not a smart contract vulnerability, but we mention it here for completeness.&lt;/p&gt;

&lt;p&gt;Transferring zero ERC20 tokens is permitted by the specification. This can lead to confusion for frontend applications, and possible trick users about who they recently sent tokens to. &lt;a href="https://metamask.io/"&gt;Metamask&lt;/a&gt; has more on that in this &lt;a href="https://twitter.com/MetaMaskSupport/status/1613255316870729728"&gt;thread&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  ERC20: Just flat out rugged
&lt;/h2&gt;

&lt;p&gt;(In web3 parlance “rugged” means “having the rug pulled out from under you.”)&lt;/p&gt;

&lt;p&gt;There’s nothing stopping someone from adding a function to an ERC20 token that lets them create, transfer, and burn tokens at will — or selfdestructing or upgrading. So fundamentally, there is a limit to how “untrusted” an ERC20 token can be.&lt;/p&gt;
&lt;h2&gt;
  
  
  Unchecked return values
&lt;/h2&gt;

&lt;p&gt;There are two ways to call an external smart contract: 1) calling the function with an interface definition; 2) using the .call method. This is illustrated below&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract A {
    uint256 public x;

    function setx(uint256 _x) external {
        require(_x &amp;gt; 10, "x must be bigger than 10");
        x = _x;
    }
}

interface IA {
    function setx(uint256 _x) external;
}

contract B {
    function setXV1(IA a, uint256 _x) external {
        a.setx(_x);
    }

    function setXV2(address a, uint256 _x) external {
        (bool success, ) =
            a.call(abi.encodeWithSignature("setx(uint256)", _x));
        // success is not checked!
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In contract B, setXV2 can silently fail if _x is less than 10. When a function is called via the .call method, the callee can revert, but the parent will not revert. The value of success must be checked and the code behavior must branch accordingly.&lt;/p&gt;
&lt;h2&gt;
  
  
  Private Variables
&lt;/h2&gt;

&lt;p&gt;Private variables are still visible on the blockchain, so sensitive information should never be stored there. If they weren’t accessible, how would the validators be able to process transactions that depend on their values? Private variables cannot be read from an outside Solidity contract, but they can be read off-chain using an Ethereum client.&lt;/p&gt;

&lt;p&gt;To read a variable, you need to know its storage slot. In the following example, the storage slot of myPrivateVar is 0.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract PrivateVarExample {
    uint256 private myPrivateVar;

    constructor(uint256 _initialValue) {
        myPrivateVar = _initialValue;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here is the javascript code to read the private variable of the deployed smart contract&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Web3 = require("web3");
const PRIVATE_VAR_EXAMPLE_ADDRESS = "0x123..."; // Replace with your contract address

async function readPrivateVar() {
  const web3 = new Web3("http://localhost:8545"); // Replace with your provider's URL

  // Read storage slot 0 (where 'myPrivateVar' is stored)
  const storageSlot = 0;
  const privateVarValue = await web3.eth.getStorageAt(
    PRIVATE_VAR_EXAMPLE_ADDRESS,
    storageSlot
  );

  console.log("Value of private variable 'myPrivateVar':",
  web3.utils.hexToNumberString(privateVarValue));
}

readPrivateVar();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Insecure Delegate Call
&lt;/h2&gt;

&lt;p&gt;Delegatecall should never be used with untrusted contracts as it hands over all control to the delegatecallee. In this example, the untrusted contract steals all the ether in the contract.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract UntrustedDelegateCall {
    constructor() payable {
        require(msg.value == 1 ether);
    }

    function doDelegateCall(address _delegate, bytes calldata data) public {
        (bool ok, ) = _delegate.delegatecall(data);
        require(ok, "delegatecall failed");
    }

    }

    contract StealEther {
        function steal() public {
            // you could also selfdestruct here 
            // if you really wanted to be mean
            (bool ok,) = 
                tx.origin.call{value: address(this).balance}("");
            require(ok);
        }

        function attack(address victim) public {
            UntrustedDelegateCall(victim).doDelegateCall(
                address(this),
                abi.encodeWithSignature("steal()"));
        }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Upgrade bugs related to proxies
&lt;/h2&gt;

&lt;p&gt;We can’t do justice to this topic in a single section. Most upgrade bugs can be generally avoided by using the hardhat plugin from Openzeppelin and reading about what issues it protects against. (&lt;a href="https://docs.openzeppelin.com/upgrades-plugins/1.x/"&gt;https://docs.openzeppelin.com/upgrades-plugins/1.x/&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;As a quick summary, here are issues related to smart contract upgrades:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;selfdestruct and delegatecall should not be used inside implementation contracts&lt;/li&gt;
&lt;li&gt;care must be taken that storage variables never overwrite each other during upgrades&lt;/li&gt;
&lt;li&gt;calling external libraries should be avoided in implementation contracts because it isn’t possible to predict how they will affect storage access&lt;/li&gt;
&lt;li&gt;deployer must never neglect to call the initialization function&lt;/li&gt;
&lt;li&gt;not including a gap variable in base contracts to prevent storage collision when new variables are added to the base contract (this is handled by the hardhat plugin automatically)&lt;/li&gt;
&lt;li&gt;the values in immutable variables are not preserved between upgrades&lt;/li&gt;
&lt;li&gt;doing anything in the constructor is highly discouraged because future upgrades would have to carry out identical constructor logic to maintain compatibility.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Overpowered Admins
&lt;/h2&gt;

&lt;p&gt;Just because a contract has an owner or an admin, it doesn’t mean that their power needs to be unlimited. Consider an NFT. It’s reasonably for only the owner to withdraw the earnings from the NFT sale, but being able to pause the contract (block transfers) could wreak havoc if the owner’s private keys get compromised. Generally, administrator priviledges should be as minimal as possible to minimize unnecessary risk.&lt;/p&gt;

&lt;p&gt;Speaking of contract ownership…&lt;/p&gt;
&lt;h2&gt;
  
  
  Use Ownable2Step instead of Ownable
&lt;/h2&gt;

&lt;p&gt;This is technically not a vulnerability, but OpenZeppelin ownable can lead to loss of contract ownership if ownership is transferred to a non-existent address. Ownable2step requires the receiver to confirm ownership. This insures against accidentally sending ownership to a mistyped address.&lt;/p&gt;
&lt;h2&gt;
  
  
  Rounding Errors
&lt;/h2&gt;

&lt;p&gt;Solidity does not have floats, so rounding errors are inevitable. The designer must be conscious of whether the right thing to do is to round up or to round down, and in whose favor the rounding should be.&lt;/p&gt;

&lt;p&gt;Division should always be performed last. The following code incorrectly converts between stablecoins that have a different number of decimals. The following exchange mechanism allows a user to take a small amount of USDC (which has 6 decimals) for free when exchanging for dai (which has 18 decimals). The variable daiToTake will round down to zero, taking nothing from the user in exchange for a non-zero usdcAmount.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract Exchange {

    uint256 private constant CONVERSION = 1e12;

    function swapDAIForUSDC(uint256 usdcAmount) external pure returns (uint256 a) {
        uint256 daiToTake = usdcAmount / CONVERSION;
        conductSwap(daiToTake, usdcAmount);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Frontrunning
&lt;/h2&gt;

&lt;p&gt;Frontrunning in the context of Etheruem (and similar chains) means observing a pending transaction and executing another transaction before it by paying a higher gas price. That is, the attacker has “run in front” of the transaction. If the transaction is a profitable trade, then it makes sense to copy the transaction exactly except pay a higher gas price. This phenomenon is sometimes referred to as MEV, which means miner extractable value, but sometimes maximal extractable value in other contexts. Block producers have unlimited power to reorder transactions and insert their own, and historically, block producers were miners before Ethereum went to proof of stake, hence the name.&lt;/p&gt;
&lt;h2&gt;
  
  
  Frontrunning: Unprotected withdraw
&lt;/h2&gt;

&lt;p&gt;Withdrawing Ether from a smart contract can be considered a “profitable trade.” You execute a zero-cost transaction (aside from the gas) and end up with more cryptocurrency than you started with.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract UnprotectedWithdraw {

    constructor() payable {
        require(msg.value == 1 ether, "must create with 1 eth");
    }

    function unsafeWithdraw() external {
        (bool ok, ) = msg.sender.call{value: address(this).value}("");
        require(ok, "transfer failed").
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you deploy this contract and try to withdraw, a frontrunner bot will notice your call to “unsafeWithdraw” in the mempool and copy it to get the Ether first.&lt;/p&gt;
&lt;h2&gt;
  
  
  Frontrunning: ERC4626 Inflation attack, a combination of frontrunning and rounding errors
&lt;/h2&gt;

&lt;p&gt;We’ve written in depth about the ERC-4626 inflation attack in our ERC4626 tutorial. But the gist of it is that an ERC4626 contract distributes “share” tokens based on the percentage of “assets” that a trader contributes. Roughly, it works as follows:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function getShares(...) external {
    // code
    shares_received = assets_contributed / total_assets;
    // more code
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Of course, nobody will contribute assets and get no shares back, but they can’t predict that will happen if someone can frontruns the trade to get the shares.&lt;/p&gt;

&lt;p&gt;For example, they contributes 200 assets when the pool has 20, they expect to get 100 shares. But if someone frontruns the transaction to deposit 200 assets, then the formula will be 200 / 220, which rounds down to zero, causing the victim to lose assets and get zero shares back.&lt;/p&gt;
&lt;h2&gt;
  
  
  Frontrunning: ERC20 approval
&lt;/h2&gt;

&lt;p&gt;It’s best to illustrate this with a real example rather than describe it in the abstract&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Suppose Alice approves Eve for 100 tokens. (Eve is always the evil person, not Bob, so we will keep convention).&lt;/li&gt;
&lt;li&gt;Alice changes her mind and sends a transaction to change Eve’s approval to 50.&lt;/li&gt;
&lt;li&gt;Before the transaction to change the approval to 50 is included in the block, it sits in the mempool where Eve can see it.&lt;/li&gt;
&lt;li&gt;Eve sends a transaction to claim her 100 tokens to frontrun the approval for 50.&lt;/li&gt;
&lt;li&gt;The approval for 50 goes through&lt;/li&gt;
&lt;li&gt;Eve collects the 50 tokens.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now Eve has 150 tokens instead of 100 or 50. The solution to this is to set the approval to zero before increasing or decreasing it, when dealing with untrusted approvals.&lt;/p&gt;
&lt;h2&gt;
  
  
  Frontrunning: Sandwich attacks
&lt;/h2&gt;

&lt;p&gt;The price of an asset moves in response to buying and selling pressure. If a large order is sitting in the mempool, traders have an incentive to copy the order but with a higher gas price. That way, they purcase the asset, let the large order move the price up, then they sell right away. The sell order is sometimes called “backrunning.” The sell order can be done with by placing a sell order with a lower gas price so that the sequence looks like this&lt;/p&gt;

&lt;p&gt;1.frontrun buy&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;large buy&lt;/li&gt;
&lt;li&gt;sell&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The primary defense against this attack is to provide a “slippage” parameter. If the “frontrun buy” itself pushes the price up past a certain threshld, the “large buy” order will revert making the frontrunner fail on the trade.&lt;/p&gt;

&lt;p&gt;It’s called a sandwhich, because the large buy is sandwhiched by the frontrun buy and the backrun sell. This attack also works with large sell orders, just in the opposite direction.&lt;/p&gt;
&lt;h2&gt;
  
  
  Learn more about frontrunning
&lt;/h2&gt;

&lt;p&gt;Frontrunning is a massive topic. Flashbots has researched the topic extensively and published several tools and research articles to help minimize it’s negative externalities. Whether frontrunning can be “designed away” with proper blockchain architecture is a subject for debate which has not been conclusively settled. The following two articles are enduring classics on the subject:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.paradigm.xyz/2020/08/ethereum-is-a-dark-forest"&gt;Ethereum is a dark forest&lt;/a&gt;&lt;br&gt;
&lt;a href="https://samczsun.com/escaping-the-dark-forest/"&gt;Escaping the dark forest&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Signature Related
&lt;/h2&gt;

&lt;p&gt;Digital signatures have two uses in the context of smart contracts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;enabling addresses to authorize some transaction on the blockchain without making an actual transaction&lt;/li&gt;
&lt;li&gt;proving to a smart contract that the sender has some authority to do something, according to a predefined address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is an example of using digital signatures safely to give a user the priviledge to mint an NFT:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

contract NFT is ERC721("name", "symbol") {
    function mint(bytes calldata signature) external {
        address recovered = keccak256(abi.encode(msg.sender)).toEthSignedMessageHash().recover(signature);
        require(recovered == authorizer, "signature does not match");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A classic example is the Approve functionality in ERC20. To approve an address to withdraw a certain amount of tokens from our account, we have to make an actual Ethereum transaction, which costs gas.&lt;/p&gt;

&lt;p&gt;It’s sometimes more efficient to pass a digital signature to the recipient off-chain, then the recipient supplies the signature to the smart contract to prove they were authorized to conduct the transaction.&lt;/p&gt;

&lt;p&gt;ERC20Permit enables approvals with a digital signature. The function is described as follows&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function permit(address owner,
    address spender,
    uint256 amount,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) public
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Rather than sending an actual approve transaction, the owner can “sign” the approval for the spender (along with a deadline). The approved spender can then call the permit function with the provided parameters.&lt;/p&gt;
&lt;h2&gt;
  
  
  Anatomy of a signature
&lt;/h2&gt;

&lt;p&gt;You’ll see the variables, v, r, and s frequently. They are represented in solidity with the datatypes uint8, bytes32, and bytes32 respectively. Sometimes, signatures are represented as a 65 byte array which is all of these values concatenated together as abi.encodePacked(r, s, v);&lt;/p&gt;

&lt;p&gt;The other two essential components of a signature are the message hash (32 bytes) and the signing address. The sequence looks like this&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A private key (privKey) is used to generate a public address (ethAddress)&lt;/li&gt;
&lt;li&gt;A smart contract stores ethAddress in advance&lt;/li&gt;
&lt;li&gt;An offchain user hashes a message and signs the hash. This produces the pair msgHash and the signature (r, s, v)&lt;/li&gt;
&lt;li&gt;The smart contract receives a message, hashes it to produce msgHash, then combines it with (r, s, v) to see what address comes out.&lt;/li&gt;
&lt;li&gt;If the address matches ethAddress, the signature is valid (under certain assumptions which we will see soon!)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Smart contracts use the precompiled contract ecrecover in step 4 to do what we called the combination and get the address back.&lt;/p&gt;

&lt;p&gt;There are a lot of steps in this process where things can go sideways.&lt;/p&gt;
&lt;h2&gt;
  
  
  Signatures: ecrecover returns address(0) and doesn’t revert when the address is invalid
&lt;/h2&gt;

&lt;p&gt;This can lead to a vulnerability if an uninitialized variable is compared to the output of ecrecover.&lt;/p&gt;

&lt;p&gt;This code is vulnerable&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract InsecureContract {

    address signer; 
    // defaults to address(0)
    // who lets us give the beneficiary the airdrop without them// spending gas
    function airdrop(address who, uint256 amount, uint8 v, bytes32 r, bytes32 s) external {

        // ecrecover returns address(0) if the signature is invalid
        require(signer == ecrecover(keccak256(abi.encode(who, amount)), v, r, s), "invalid signature");

        mint(msg.sender, AIRDROP_AMOUNT);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Signature replay
&lt;/h2&gt;

&lt;p&gt;The signature replay happens when a contract doesn’t track if a signature has been used previously. In the following code, we fix the previous issue, but it’s still not secure.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract InsecureContract {

    address signer;

    function airdrop(address who, uint256 amount, uint8 v, bytes32 r, bytes32 s) external {

        address recovered == ecrecover(keccak256(abi.encode(who, amount)), v, r, s);
        require(recovered != address(0), "invalid signature");
        require(recovered == signer, "recovered signature not equal signer");


        mint(msg.sender, amount);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;People can claim the airdrop as many times as they want!&lt;/p&gt;

&lt;p&gt;We could add the following lines&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bytes memory signature = abi.encodePacked(v, r, s);
require(!used[signature], "signature already used"); 
// mapping(bytes =&amp;gt; bool);
used[signature] = true;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Alas, the code is still not secure!&lt;/p&gt;
&lt;h2&gt;
  
  
  Signature malleability
&lt;/h2&gt;

&lt;p&gt;Given a valid signature, an attacker can do some quick arithmetic to derive a different one. The attacker can then “replay” this modified signature. But first, let’s provide some code that demonstrates we can start with a valid signature, modify it, and show the new signature still passes.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract Malleable {

    // v = 28
    // r = 0xf8479d94c011613baeffe9239e4ff65e2adbac744c34217ca7d51378e72c5204
    // s = 0x57af17590a914b759c45aaeabaf513d5ef72d7da1bdd19d9f2e1bc371ece5b86
    // m = 0x0000000000000000000000000000000000000000000000000000000000000003
    function foo(bytes calldata msg, uint8 v, bytes32 r, bytes32 s) public pure returns (address, address){
        bytes32 h = keccak256(msg);
        address a = ecrecover(h, v, r, s);


        // The following is math magic to invert the 
        // signature and create a valid one
        // flip s
        bytes32 s2 = bytes32(uint256(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141) - uint256(s));

        // invert v
        uint8 v2;
        require(v == 27 || v == 28, "invalid v");
        v2 = v == 27 ? 28 : 27;

        address b = ecrecover(h, v2, r, s2);

        assert(a == b); 
        // different signatures, same address!;
        return (a, b);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As such, our running example is still vulnerable. Once someone presents a valid signature, it’s mirror image signature can be produced and bypass the used signature check.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract InsecureContract {

    address signer;

    function airdrop(address who, uint256 amount, uint8 v, bytes32 r, bytes32 s) external {

        address recovered == ecrecover(keccak256(abi.encode(who, amount)), v, r, s);
        require(recovered != address(0), "invalid signature");
        require(recovered == signer, "recovered signature not equal signer");

        bytes memory signature = abi.encodePacked(v, r, s);
        require(!used[signature], "signature already used"); // this can be bypassed
        used[signature] = true;

        mint(msg.sender, amount);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Secure signatures
&lt;/h2&gt;

&lt;p&gt;You’re probably wanting some secure signature code at this point, right? We refer you to our tutorial on &lt;a href="https://www.rareskills.io/post/openzeppelin-verify-signature"&gt;creating signatures in solidity&lt;/a&gt; and testing them in foundry. But here is the checklist.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use openzeppelin's library to prevent malleability attacks and recover to zero issues&lt;/li&gt;
&lt;li&gt;Don't use signatures as a password. The messages needs to contain information that attackers cannot easily re-use (e.g. msg.sender)&lt;/li&gt;
&lt;li&gt;Hash what you are signing on-chain&lt;/li&gt;
&lt;li&gt;Use a nonce to prevent replay attacks. Better yet, follow EIP712 so that usese can see what they are signing and you can prevent signatures from being re-used between contracts and different chains.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Signatures can be forged or crafted without proper safeguards
&lt;/h2&gt;

&lt;p&gt;The attack above can be generalized further if hashing is not done on chain. In the examples above, the hashing was done in the smart contract, so the above examples are not vulnerable to the following exploit.&lt;/p&gt;

&lt;p&gt;Let’s look at the code for recovering signatures&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// this code is vulnerable!
function recoverSigner(bytes32 hash, uint8 v, bytes32 r, bytes32 s) public returns (address signer) {
    require(signer == ecrecover(hash, v, r, s), "signer does not match");
    // more actions
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The user supplies both the hash and the signatures. If the attacker has already seen a valid signature from the signer, they can simply reuse the hash and signature of another message.&lt;/p&gt;

&lt;p&gt;This is why it is very important to hash the message &lt;strong&gt;in the smart contract&lt;/strong&gt;, not off-chain.&lt;/p&gt;

&lt;p&gt;To see this exploit in action, see the CTF we posted on Twitter.&lt;/p&gt;

&lt;p&gt;Original Challenge:&lt;/p&gt;

&lt;p&gt;Part 1: &lt;a href="https://twitter.com/RareSkills_io/status/1650869999266037760"&gt;https://twitter.com/RareSkills_io/status/1650869999266037760&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Part 2: &lt;a href="https://twitter.com/RareSkills_io/status/1650897671543197701"&gt;https://twitter.com/RareSkills_io/status/1650897671543197701&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Solutions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/RareSkills_io/status/1651527648676573185"&gt;https://twitter.com/RareSkills_io/status/1651527648676573185&lt;/a&gt; &lt;a href="https://twitter.com/RareSkills_io/status/1651224817465540611"&gt;https://twitter.com/RareSkills_io/status/1651224817465540611&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Signatures as identifiers
&lt;/h2&gt;

&lt;p&gt;Signatures should not be used to identify users. Because of malleability, they cannot be assumed to be unique. Msg.sender has much stronger uniqueness guarantees.&lt;/p&gt;
&lt;h2&gt;
  
  
  Some Solidity compiler versions have bugs
&lt;/h2&gt;

&lt;p&gt;See a security exercise we hosted on Twitter here. When auditing a codebase, check the Solidity version against the release announcements on the Solidity page to see if a bug might be present.&lt;/p&gt;
&lt;h2&gt;
  
  
  Assuming smart contracts are immutable
&lt;/h2&gt;

&lt;p&gt;Smart contracts can be upgraded with the Proxy Pattern (or more rarely, the metamorphic pattern). Smart contracts should not rely on the functionality of an arbitrary smart contract to remain unchanged.&lt;/p&gt;
&lt;h2&gt;
  
  
  Transfer() and send() can break with multi-signature wallets
&lt;/h2&gt;

&lt;p&gt;The solidity functions transfer and send should not be used. They intentionally limit the amount of gas forwarded with the transaction to 2,300, which will cause most operations to run out of gas.&lt;/p&gt;

&lt;p&gt;The commonly used gnosis safe multi-signature wallet supports forwarding the call to another address in the fallback function. If someone uses transfer or send to send Ether to the multisig wallet, the fallback function could run out of gas and the transfer would fail. A screenshot of the gnosis safe fallback function is provided below. The reader can clearly see there is more than enough operations to use up the 2300 gas.&lt;/p&gt;

&lt;p&gt;If you need to interact with a contract that uses transfer and send, see our article on &lt;a href="https://www.rareskills.io/post/eip-2930-optional-access-list-ethereum"&gt;Ethereum access list transactions&lt;/a&gt; that allows you to reduce the gas cost of storage and contract access operations.&lt;/p&gt;
&lt;h2&gt;
  
  
  Is Arithmetic overflow still relevant?
&lt;/h2&gt;

&lt;p&gt;Solidity 0.8.0 has built in overflow and underflow protection. So unless an unchecked block is present, or low level code in Yul is used, there is no danger of overflow. As such, SafeMath libraries should not be used as they waste gas on the extra checks.&lt;/p&gt;
&lt;h2&gt;
  
  
  What about block.timestamp?
&lt;/h2&gt;

&lt;p&gt;Some literature documents that block.timestamp is a vulnerability vector because miners can manipulate it. This usually applies to using timestamps as a source of randomness, which should not be done anyway as documented earlier. Post-merge Ethereum updates the timestamp in exactly 12 second (or multiples of 12 second) intervals. However, measuring time in second-level granularity is an anti-pattern. On the scale of one minute, there is considerable opportunity for error if a validator misses their block slot and a 24 second gap in block production happens.&lt;/p&gt;
&lt;h2&gt;
  
  
  Corner Cases, Edge Cases, and Off By One Errors
&lt;/h2&gt;

&lt;p&gt;Corner cases cannot be easily defined, but once you have seen enough of them, you start to develop an intuition for them. A corner case can be something like someone trying to claim a reward, but having nothing staked. This is valid, we should just give them zero reward. Similarly, we generally want to divide up rewards evenly, but what if there is only one recipient, and technically no division should happen?&lt;/p&gt;
&lt;h2&gt;
  
  
  Corner Case: Example 1
&lt;/h2&gt;

&lt;p&gt;This example was taken from Akshay Srivastav’s &lt;a href="https://twitter.com/akshaysrivastv/status/1648310441058115592"&gt;twitter thread&lt;/a&gt; and modified.&lt;/p&gt;

&lt;p&gt;Consider the case where someone can conduct a privileged action if a set of privileged addresses provide a signature for it.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract VulnerableMultisigAuthorization {
    struct Authorization {
        bytes signature;
        address authorizer;
        bytes32 hashOfAction;
        // more fields
    }

    // more codef
    unction takeAction(Authorization[] calldata auths, bytes calldata action) public {
        // logic for avoiding replay attacks
        for (uint256 i; i &amp;lt; auths.length; ++i) {

            require(validateSignature(auths[i].signature, auths[i].authorizer), "invalid signature");
            require(authorizers[auths[i].authorizer], "address is not an authorizer");

        }

        doTheAction(action)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If any of the signatures are not valid, or the signatures don’t match to a valid address, the revert will happen. But what if the array is empty? In that case, it will jump all the way down to doTheAction without the need for any signatures.&lt;/p&gt;
&lt;h2&gt;
  
  
  Off-By-One: Example 2
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract ProportionalRewards {

    mapping(address =&amp;gt; uint256) originalId;
    address[] stakers;

    function stake(uint256 id) public {
        nft.transferFrom(msg.sender, address(this), id);
        stakers.append(msg.sender);
    }

    function unstake(uint256 id) public {
        require(originalId[id] == msg.sender, "not the owner");

        removeFromArray(msg.sender, stakers);

        sendRewards(msg.sender, 
            totalRewardsSinceLastclaim() / stakers.length());

        nft.transferFrom(address(this), msg.sender, id);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Although the code above doesn’t show all the function implementations, even if the functions behave as their names describe, there is still a bug. Can you spot it? Here is a picture to give you some space to not see the answer before you scroll down.&lt;/p&gt;

&lt;p&gt;The removeFromArray and sendRewards function are in the wrong order. If there is only one user in the stakers array, there will be a divide by zero error, and the user won’t be able to withdraw their NFT. Furthermore, the rewards are probably not divided the way the author intends. If there were original four stakers, and one person withdraws, he will get a third of the rewards since the array length is 3 at the time of withdrawal.&lt;/p&gt;
&lt;h2&gt;
  
  
  Corner Case Example 3: Compound Finance Reward Miscalculation
&lt;/h2&gt;

&lt;p&gt;Let’s use a real example that by some estimates caused over $100 million dollars of damage. Don’t worry if you don’t fully understand the Compound protocol, we will only focus on the relevant parts. (Also the Compound protocol is one of the most important and consequential protocols in the history of DeFi, we teach it in our &lt;a href="https://www.rareskills.io/defi-bootcamp"&gt;DeFi bootcamp&lt;/a&gt;, so if this is your first impression of the protocol, don’t be misguided).&lt;/p&gt;

&lt;p&gt;Anyway, the point of Compound is to reward users for lending their idle cryptocurrency to other traders who might have a use for it. The lenders are paid both in interest and in COMP tokens (the borrowers could claim a COMP token reward to, but we won’t focus on that right now).&lt;/p&gt;

&lt;p&gt;The Compound Comptroller is a proxy contract that delegates calls to implementations that can be set by the Compound Governance.&lt;/p&gt;

&lt;p&gt;At governance &lt;a href="https://compound.finance/governance/proposals/62"&gt;proposal 62&lt;/a&gt; on September 30, 2021, the &lt;a href="https://etherscan.io/address/0x374abb8ce19a73f2c4efad642bda76c797f19233/advanced#internaltx"&gt;implementation contract&lt;/a&gt; was set to an implementation contract that had the vulnerability. The same day it went live, it was observed on &lt;a href="https://twitter.com/napgener/status/1443350694635921409"&gt;Twitter&lt;/a&gt; that some transactions were claiming COMP rewards despite staking zero tokens.&lt;/p&gt;

&lt;p&gt;The vulnerable function distributeSupplierComp()&lt;/p&gt;

&lt;p&gt;Here is the original code&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;The bug, ironically, is in the TODO comment. “Don’t distribute supplier COMP if the user is not in the supplier market.” But there is no check in the code for that. As long as the user holds staking token in their wallet (CToken(cToken).balanceOf(supplier);), then&lt;/p&gt;

&lt;p&gt;&lt;a href="https://compound.finance/governance/proposals/64"&gt;Proposal 64&lt;/a&gt; fixed the bug on October 9, 2021.&lt;/p&gt;

&lt;p&gt;Although this could be argued to be an input validation bug, the users didn’t submit anything malicious. If someone tries to claim a reward for not staking anything, the correct computation should be zero. Arguably, it’s more of a business logic or corner case error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real World Hacks
&lt;/h2&gt;

&lt;p&gt;DeFi hacks that happen in the real world often times don’t fall into the nice categories above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pairity Wallet Freeze (November 2017)
&lt;/h2&gt;

&lt;p&gt;The parity wallet was not intended to be used directly. It was a reference implementation that &lt;a href="https://www.rareskills.io/post/eip-1167-minimal-proxy-standard-with-initialization-clone-pattern"&gt;smart contract clones&lt;/a&gt; would point to. To implementation allowed for the clones to selfdestruct if desired, but this required all the wallet owners to sign off on it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// throw unless the contract is not yet initialized.modifier only_uninitialized { if (m_numOwners &amp;gt; 0) throw; _; }

function initWallet(address[] _owners, uint _required, uint _daylimit) only_uninitialized {
  initDaylimit(_daylimit);
  initMultiowned(_owners, _required);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The wallet owners are declared&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// kills the contract sending everything to `_to`.function kill(address _to) onlymanyowners(sha3(msg.data)) external {
  suicide(_to);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some literature describes this as an “unprotected selfdestruct” i.e. an access control failure, but this isn’t quite accurate. The problem was that the initWallet function was not called on the implementation contract and that allowed someone to call the initWallet function themselves and make themselves the owner. That gave them the authority to call the kill function. The root cause was that the implementation was not initialized. Therefore, the bug was introduced not due to faulty solidity code, but due to a faulty deployment process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Badger DAO Hack (December 2021)
&lt;/h2&gt;

&lt;p&gt;No Solidity code was exploited in this hack. Instead, the attackers obtain the Cloudflare API key and injected a script into the website frontend that altered user transactions to direct withdrawals to the attacker address. Read more in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attack vectors for wallets
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Private keys with insufficient randomness
&lt;/h2&gt;

&lt;p&gt;The motivation for discovering addresses with a lot of leading zeros is that they are more gas efficient to use. An Ethereum transaction is charged 4 gas for a zero byte in the transaction data and 16 gas for a non-zero byte. As such,&lt;/p&gt;

&lt;p&gt;Wintermute was hacked because it used the profanity address (&lt;a href="https://www.halborn.com/blog/post/explained-the-wintermute-hack-september-2022"&gt;writeup&lt;/a&gt;). Here is 1inch’s writeup of how the profanity address generator was compromised.&lt;/p&gt;

&lt;p&gt;The trust wallet had a similar vulnerability documented in this article (&lt;a href="https://blog.ledger.com/Funds-of-every-wallet-created-with-the-Trust-Wallet-browser-extension-could-have-been-stolen/"&gt;https://blog.ledger.com/Funds-of-every-wallet-created-with-the-Trust-Wallet-browser-extension-could-have-been-stolen/&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Note that this does not apply to smart contracts with leading zeros discovered by changing the salt in create2, as smart contracts do not have private keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reused nonces or insufficiently random nonces.
&lt;/h2&gt;

&lt;p&gt;The “r” and “s” point on the Elliptic Curve signature is generated as follows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;r = k * G (mod N)
s = k^-1 * (h + r * privateKey) (mod N)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;G, r, s, h, an N are all publicly known. If “k” becomes public, then “privateKey” is the only unknown variable, and can be solved for. Because of this wallets need to generate k perfectly randomly and never reuse it. If the randomness isn’t perfectly random, then k can be inferred. Insecure randomness generation in the Java library left a lot of Android bitcoin wallets vulnerable in 2013. (Bitcoin uses the same signature algorithm as Ethereum.) (&lt;a href="https://arstechnica.com/information-technology/2013/08/all-android-created-bitcoin-wallets-vulnerable-to-theft/"&gt;https://arstechnica.com/information-technology/2013/08/all-android-created-bitcoin-wallets-vulnerable-to-theft/&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Most vulnerabilities are application specific
&lt;/h2&gt;

&lt;p&gt;Training yourself to quickly recognize the anti-patterns in this list will make you a more effective smart contract programmer, but most smart contract bugs of consequence are due to a mismatch between the intended business logic and what the code actually does.&lt;/p&gt;

&lt;p&gt;Other areas where bugs can occur:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bad tokenomic incentives&lt;/li&gt;
&lt;li&gt;off by one errors&lt;/li&gt;
&lt;li&gt;typographical errors&lt;/li&gt;
&lt;li&gt;admins or users getting their private keys stolen&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Many vulnerabilities could have been caught with unit tests
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.rareskills.io/post/foundry-testing-solidity"&gt;Smart contract unit testing&lt;/a&gt; is arguably the most basic safeguards for smart contract, but a shocking number of smart contracts either lack them or have insufficient &lt;a href="https://www.rareskills.io/post/foundry-forge-coverage"&gt;test coverage&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But unit tests tend only to test the “happy path” (expected/designed behavior) of contracts. To test the surprising cases, additional test methodologies must be applied.&lt;/p&gt;

&lt;p&gt;Before a smart contract is sent for audit, the following should be done first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Static analysis with tools such as Slither to ensure basic mistakes were not missed&lt;/li&gt;
&lt;li&gt;100% line and branch coverage through unit testing&lt;/li&gt;
&lt;li&gt;Mutation testing to ensure the unit tests have robust assert statements&lt;/li&gt;
&lt;li&gt;Fuzz testing, especially for arithmetic&lt;/li&gt;
&lt;li&gt;Invariant testing for stateful properties&lt;/li&gt;
&lt;li&gt;Formal verification where appropriate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For those unfamiliar with some of the methodologies here, Patrick Collins of Cyfrin Audits has a humorous introduction to stateful and stateless fuzzing in his &lt;a href="https://www.youtube.com/watch?v=juyY-CTolac"&gt;video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Tools to accomplish these tasks are rapidly becoming more widespread and easier to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  More resources
&lt;/h2&gt;

&lt;p&gt;Some authors have compiled a list of previous DeFi hacks in these Repos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/coinspect/learn-evm-attacks"&gt;https://github.com/coinspect/learn-evm-attacks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/SunWeb3Sec/DeFiHackLabs"&gt;https://github.com/SunWeb3Sec/DeFiHackLabs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rekt.news/"&gt;https://rekt.news/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Secureum has been widely used to study and practice security, but keep in mind the repo hasn’t been substantially updated for 2 years&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/x676f64/secureum-mind_map"&gt;https://github.com/x676f64/secureum-mind_map&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can practice exploiting solidity vulnerabilities with our &lt;a href="https://github.com/RareSkills/solidity-riddles"&gt;Solidity Riddles repository&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/RareSkills/solidity-riddles"&gt;https://github.com/RareSkills/solidity-riddles&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DamnVulnerableDeFi is a classic wargame every developer should practice&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://damnvulnerabledefi.xyz"&gt;https://damnvulnerabledefi.xyz&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Capture The Ether and Ethernaut are classics, but keep in mind some of the problems are unrealistically easy or teach outdated Solidity concepts&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://capturetheether.com"&gt;https://capturetheether.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ethernaut.openzeppelin.com"&gt;https://ethernaut.openzeppelin.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some reputable crowdsourced security firms have a useful list of past audits to study.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://code4rena.com/"&gt;https://code4rena.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sherlock.xyz/"&gt;https://www.sherlock.xyz/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Becoming a smart contract auditor
&lt;/h2&gt;

&lt;p&gt;If you aren’t fluent in Solidity, then there is no way you’ll be able to audit Ethereum smart contracts. See our &lt;a href="https://www.rareskills.io/learn-solidity"&gt;free Solidity tutorial&lt;/a&gt; if you are just starting off.&lt;/p&gt;

&lt;p&gt;There is no industry recognized certification for becoming a smart contract auditor. Anyone can create a website and social media profiles claiming to be a solidity auditor and start selling services, and many have done so. Therefore, use caution and get referrals before hiring one.&lt;/p&gt;

&lt;p&gt;To become a smart contract auditor, you need to be substantially better than the average solidity developer at spotting bugs. As such, &lt;strong&gt;the “roadmap” to becoming an auditor is nothing more than months and months of relentless and deliberate practice until you are better smart contract bug catcher than most&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you lack the determination to outperform your peers at identifying vulnerabilities, it’s unlikely you’ll spot the critical issues before the highly trained and motivated criminals do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cold truth about your chances of success of becoming a smart contract security auditor
&lt;/h2&gt;

&lt;p&gt;Smart contract auditing recently has been perceived as a desirable field to work in due to the perception that it is lucrative. Indeed, some bug bounty payouts have exceeded 1 million dollars, but this is the exceedingly rare exception, not the norm.&lt;/p&gt;

&lt;p&gt;Code4rena has a public &lt;a href="https://code4rena.com/leaderboard/"&gt;leaderboard&lt;/a&gt; of payouts from competitors in their audit contests, which gives us some data about success rates.&lt;/p&gt;

&lt;p&gt;There are 1171 names on the board, yet&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only 29 competitors have over $100,000 in lifetime earnings (2.4%)&lt;/li&gt;
&lt;li&gt;Only 57 have over $50,000 in lifetime earnings (4.9%)&lt;/li&gt;
&lt;li&gt;Only 170 have over $10,000 in lifetime earnings (14.5%)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also consider this, when Openzeppelin opened up an application for a security research fellowship (not a job, a pre-job screening and training), they received over 300 applications only to select fewer than 10 candidates, of which even fewer would get a full time job.&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--Gx8DR7wk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://pbs.twimg.com/profile_images/1354235852851875845/_nJknn-5_normal.jpg" alt="David Bessin profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        David Bessin
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @david_bessin
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kDgU_xDI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      325 &lt;a href="https://twitter.com/OpenZeppelin"&gt;@OpenZeppelin&lt;/a&gt; fellowship applications when we closed the application page 🔥 if you haven’t heard from us yet, we still have to review another 95 or so. Thanks for your patience!
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      16:19 PM - 13 Feb 2023
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1625167906328944640" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OXOJJiQT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1625167906328944640" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--foTp-unf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1625167906328944640" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SFHqU4bF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;That’s a lower admission rate than Harvard.&lt;/p&gt;

&lt;p&gt;Smart contract auditing is a competitive zero-sum game. There are only so many projects to audit, only so much budget for security, and only so many bugs to find. If you begin studying security now, there are dozens of highly motivated individuals and teams with a massive headstart on you. Most projects are willing to pay a premium for an auditor with a reputation rather than an untested new auditor.&lt;/p&gt;

&lt;p&gt;In this article, we’ve listed at least 20 different categories of vulnerabilites. If you spent one week mastering each one (which is somewhat optimistic), you’re only just starting to understand what is common knowledge to experienced auditors. We haven’t covered gas optimization or tokenomics in this article, both of which are important topics for an auditor to understand. Do the math and you’ll see this not a short journey.&lt;/p&gt;

&lt;p&gt;That said, the community is generally friendly and helpful to newcomers and tips and tricks abound. But for those reading this article in hopes of making a career out of smart contract security, it is important to clearly understand that the odds of obtaining a lucrative career are not in your favor. Success is not the default outcome.&lt;/p&gt;

&lt;p&gt;It can be done of course, and quite a few people have gone from knowing no Solidity to having a lucrative career in auditing. It’s arguably easier to get a job as a smart contract auditor in a two year timespan than it is to get admitted into law school and pass the bar exam. It certainly has more upside compared to a lot of other career choices.&lt;/p&gt;

&lt;p&gt;But it will nevertheless require herculean perseverance on your part to master the mountain of rapidly evolving knowledge ahead of you and hone your intuition for spotting bugs.&lt;/p&gt;

&lt;p&gt;This is not to say that learning smart contract security is not a worthwhile pursuit. It absolutely is. But if you are approaching the field with dollar signs in your eyes, keep your expectations in check.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;It is important to be aware of the known anti-patterns. However, most real-world bugs are application specific. Identifying either category of vulnerabilities requires continual and deliberate practice.&lt;/p&gt;

&lt;p&gt;Learn smart contract security, and many more Ethereum development topics with &lt;a href="https://www.rareskills.io/solidity-bootcamp"&gt;our industry-leading solidity training&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>smartcontract</category>
      <category>solidity</category>
      <category>learning</category>
      <category>smartcontracts</category>
    </item>
    <item>
      <title>Wagmi + ReactJS Example: Transfer Crypto and Mint an NFT</title>
      <dc:creator>RareSkills</dc:creator>
      <pubDate>Wed, 26 Apr 2023 13:38:51 +0000</pubDate>
      <link>https://forem.com/rareskills/wagmi-reactjs-example-transfer-crypto-and-mint-an-nft-2bf2</link>
      <guid>https://forem.com/rareskills/wagmi-reactjs-example-transfer-crypto-and-mint-an-nft-2bf2</guid>
      <description>&lt;p&gt;In this tutorial, we'll be learn how to build a Web 3 Dapp (Decentralized Application) that connects to your crypto wallet, allowing you to transfer funds and mint NFTs. We'll be using Next.js, a popular React framework, and Wagmi.sh, a collection of React Hooks that easily integrates your wallet into your website.&lt;/p&gt;

&lt;p&gt;Here's an outline of the tutorial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Getting Started&lt;/li&gt;
&lt;li&gt;Part 1: Transferring Crypto with React + Wagmi&lt;/li&gt;
&lt;li&gt;Part 2: Minting an NFT with React + Wagmi&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Authorship
&lt;/h2&gt;

&lt;p&gt;This article was co-authored by Aymeric Taylor (&lt;a href="https://www.linkedin.com/in/aymeric-russel-taylor/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://twitter.com/TaylorAymeric" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;), a research intern at RareSkills.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;For the sake of simplicity, we'll be using "Polygon Mumbai" as our test network for this tutorial, It is also supported on OpenSea.&lt;br&gt;
Connect your Wallet to Polygon Mumbai - MetaMask&lt;br&gt;
Navigate through MetaMask → Settings → Advanced and make sure you allow Show test networks.&lt;br&gt;
&lt;a href="https://media.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%2Fsjucgqu5blsqudukj7rp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fsjucgqu5blsqudukj7rp.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, click on the Network Selection on the top right section and select Add network&lt;br&gt;
&lt;a href="https://media.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%2F5p6orlnsp8bjh7mixseu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5p6orlnsp8bjh7mixseu.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If Polygon Mumbai isn't already available to select from, you can follow the steps below.&lt;br&gt;
Select Add a network manually and input the following:&lt;br&gt;
Network Name: Matic Mumbai&lt;br&gt;
New RPC URL : &lt;a href="https://rpc-mumbai.maticvigil.com/" rel="noopener noreferrer"&gt;https://rpc-mumbai.maticvigil.com/&lt;/a&gt;&lt;br&gt;
Chain ID : 80001&lt;br&gt;
Currency Symbol : MATIC&lt;br&gt;
Block explorer URL (optional) : &lt;a href="https://mumbai.polygonscan.com/" rel="noopener noreferrer"&gt;https://mumbai.polygonscan.com/&lt;/a&gt;&lt;br&gt;
Now simply switch onto the Polygon Network&lt;/p&gt;
&lt;h2&gt;
  
  
  Part 1: Transfering Ether with React + Wagmi
&lt;/h2&gt;
&lt;h2&gt;
  
  
  Step 1: Set up website with node js
&lt;/h2&gt;

&lt;p&gt;You'll need to have nodejs installed for this.&lt;br&gt;
First create your Next.js project with&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npx create-next-app@latest myapp


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Check the Typescript and ESLint option using the arrows and enter key. It should look something like this:&lt;br&gt;
&lt;a href="https://media.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%2F3gkoi4eqrb5ckihud8r1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F3gkoi4eqrb5ckihud8r1.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open your project in vscode and install wagmi.sh and use-debounce package (we'll get into that later).&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm i wagmi ethers@^5
npm i use-debounce --save


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Wagmi is basically a set of React Hooks that simplifies Ethereum development by providing useful features such as connecting wallets and interacting with contracts which we'll learn in this tutorial. More on wagmi.sh.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Use configureChains to pick the network to connect to
&lt;/h2&gt;

&lt;p&gt;Head over to pages/_app.tsx and add in the following code. Each of functionalities are explained in the comment sections.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We now have our networks configured, our next step is to allow users to choose which wallet to connect to. As you can see above, we have 4 wallet connectors set up. MetaMask, WalletConnect, Coinbase and Injected(which again is basically your default wallet).&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Use useConnect to enable picking the browser wallet
&lt;/h2&gt;

&lt;p&gt;On pages/index.tsx copy and paste the following code. Make sure you add the css, so it looks good!&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Step 4: Add css to make it look nice
&lt;/h2&gt;

&lt;p&gt;Delete everything on styles/globals.css and styles/Home.module.css.&lt;br&gt;
Copy paste the css code below on styles/globals.css.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

body {
    height: 100vh;     
    background: rgb(11,3,48); /* For browsers that do not support gradients */     
    background: linear-gradient(to bottom right,#0b0330, #5904a4);   
    font-family: 'Inter Medium', sans-serif;
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Copy paste the css code below into styles/Home.module.css.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Step 5: Run the website and test it
&lt;/h2&gt;

&lt;p&gt;When you run this, this should initiate a connection to your wallet. Once you've approved the connection, it should look something like this:&lt;/p&gt;

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

npm run dev


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Step 6: Add ability to transfer cryptocurrency
&lt;/h2&gt;

&lt;p&gt;Now that we've connected our wallet, we can transfer funds from our wallet to others. Make sure you have some Mumbai MATIC in your wallet. You can get some here &lt;a href="https://faucet.polygon.technology" rel="noopener noreferrer"&gt;https://faucet.polygon.technology&lt;/a&gt;&lt;br&gt;
We'll now be creating the input fields and send button for the transaction. Create a new file under pages/ directory and name it RareSend.tsx. Copy paste the code below. The explanations are in the code comments.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h2&gt;
  
  
  useDebounce() explained
&lt;/h2&gt;

&lt;p&gt;To avoid overloading the RPC and getting rate-limited, we'll limit the use of usePrepareContractWrite hook, which requests gas estimates on component mount and args modification. We use useDebounce hook in the component to delay updating the token ID by 500ms if no changes have been made.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Insert sendFunds component
&lt;/h2&gt;

&lt;p&gt;Next, simply add the  like this in pages/index.tsx.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As long as you have Matic in your address, you're able send it to another account!&lt;br&gt;
This should be how your website looks like:&lt;/p&gt;

&lt;p&gt;Congratulations on reaching this point! You have successfully created your own website that can send funds from your wallet to another account. You are now able to easily transfer cryptocurrency between accounts, without having to rely on a third-party service or manually entering transaction details. Well done! It's that easy!&lt;/p&gt;
&lt;h2&gt;
  
  
  Part 2: Minting an NFT with React + Wagmi
&lt;/h2&gt;

&lt;p&gt;We assume you have already have deployed an NFT smart contract to the blockchain. You can follow this video tutorial to do so: &lt;a href="https://youtu.be/LIoFbudNVZs" rel="noopener noreferrer"&gt;https://youtu.be/LIoFbudNVZs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The mint function can be created as follows. Create a mint.tsx and add the codes below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now you can simply insert it into the index.tsx file like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Your final website should look something like this:&lt;/p&gt;

&lt;p&gt;Congratulations! You've just made your own Decentralized Application that is capable of Sending Transactions and Minting an NFT.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn More
&lt;/h2&gt;

&lt;p&gt;This is used as teaching material for our &lt;a href="https://www.rareskills.io/dapp-bootcamp" rel="noopener noreferrer"&gt;Dapp Bootcamp&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>A free solidity tutorial for experienced programmers</title>
      <dc:creator>RareSkills</dc:creator>
      <pubDate>Thu, 20 Apr 2023 16:24:28 +0000</pubDate>
      <link>https://forem.com/rareskills/a-free-solidity-tutorial-for-experienced-programmers-434j</link>
      <guid>https://forem.com/rareskills/a-free-solidity-tutorial-for-experienced-programmers-434j</guid>
      <description>&lt;p&gt;RareSkills has released a free and comprehensive introduction to Solidity for experienced programmers.&lt;/p&gt;

&lt;p&gt;Although there are many resources for the language, many of them are written to audiences new to programming. It is wonderful that blockchain has introduced many people to the world of coding.&lt;/p&gt;

&lt;p&gt;But for senior engineers, using these resources can sometimes be frustrating and slow-moving. Our new tutorial is an up-to-date (2023), information-dense guide with tailored hands-on exercises.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The resource is recent, with all examples written in the latest Solidity syntax (0.8.19)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Obvious concepts like for loops and if statements are glossed over.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unique topics like how code can transfer cryptocurrency and interact with other smart contracts are explained thoroughly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each chapter concludes with a list of exercises to practice. These exercises are open-sourced in our &lt;a href="https://github.com/RareSkills/Solidity-Exercises"&gt;solidity exercises&lt;/a&gt; Github repo. The exercises are written in the &lt;a href="https://book.getfoundry.sh/"&gt;Foundry framework&lt;/a&gt;, which is the most advanced and up-to-date development framework for Solidity as of 2023.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The curriculum is designed to help the reader start developing real smart contracts as soon as possible, instead of toy examples. This helps motivate the information. We created the topic progression by working backward from common protocols like ERC20 tokens and NFTs rather than enumerating common topics in Ethereum development.&lt;/p&gt;

&lt;p&gt;The smart contract and blockchain space will do well to attract experienced coders who can knowledge transfer useful know-how from other programming domains. This resource will help facilitate their introduction.&lt;/p&gt;

&lt;p&gt;You can see the &lt;a href="https://rareskills.io/learn-solidity"&gt;free solidity tutorial&lt;/a&gt; here. No credit card or email is required.&lt;/p&gt;

</description>
      <category>solidity</category>
      <category>ethereum</category>
      <category>web3</category>
      <category>smartcontract</category>
    </item>
    <item>
      <title>Solidity test internal function</title>
      <dc:creator>RareSkills</dc:creator>
      <pubDate>Sat, 08 Apr 2023 05:30:18 +0000</pubDate>
      <link>https://forem.com/rareskills/solidity-test-internal-function-3259</link>
      <guid>https://forem.com/rareskills/solidity-test-internal-function-3259</guid>
      <description>&lt;p&gt;To test an internal solidity function, create a child contract that inherits from the contract being tested, wrap the parent contract's internal function with an external one, then test the external function in the child.&lt;br&gt;
Foundry calls this inheriting contract a "harness" though others call it a "fixture."&lt;br&gt;
Don't change the solidity function to become virtual or public to make it easier to extend, you want to test the contract you will actually deploy.&lt;/p&gt;

&lt;p&gt;Here is an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract InternalFunction { 
  function calculateReward(uint256 depositTime) internal view returns (uint256 reward) {
    reward = (block.timestamp - depositTime) * REWARD_RATE_PER_SECOND;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function above gives a linear reward rate for each unit of time that passes by.&lt;br&gt;
The fixture (or harness) would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract InternalFunctionHarness is InternalFunction {
  function calculateReward(uint256 depositTime) external view returns (uint256 reward) {
    reward = super.calculateReward(depositTime);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you call a parent function that has the same name as the child, you must use the super keyword of the function will call itself and go into infinite recursion.&lt;br&gt;
Alternatively, you can explicitly label your test function as a harness or fixture as follows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract InternalFunctionHarness is InternalFunction {
  function calculateReward_HARNESS(uint256 depositTime) external view returns (uint256 reward) {
    reward = calculateReward(depositTime);
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Don't change the function to be public
&lt;/h2&gt;

&lt;p&gt;Changing the function to become public isn't a good solution because this will increase the contract size. If a function doesn't need to be public, then don't make it public. It will increase the gas cost both for deployment, and the execution of the other functions.&lt;br&gt;
When a contract receives a transaction, it must compare the function selector to all the public ones in a linear or binary search. In either case, it has more selectors to search through. Furthermore, the added selector is added bytecode which increases the deployment cost.&lt;/p&gt;
&lt;h2&gt;
  
  
  Don't override virtual solidity functions
&lt;/h2&gt;

&lt;p&gt;Suppose we had the following contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract InternalFunction {
  function calculateReward(uint256 depositTime) internal view virtual returns (uint256 reward) {
    reward = (block.timestamp - depositTime) * REWARD_RATE_PER_SECOND;
   }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It could be tempting to simply override it on the the fixture for convenience, but this is not advisable since you end up duplicating code and if your implementation in the harness diverges from the parent contract, you won't be actually testing your business logic anymore.&lt;br&gt;
Note that this method forces us to copy and paste the original code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract InternalFunctionHarness in InternalFunction {
  function calculateReward(uint256 depositTime) external view override returns (uint256 reward) {
    reward = (block.timestamp - depositTime) * REWARD_RATE_PER_SECOND;
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What about testing private solidity functions?&lt;br&gt;
There is no way to test private functions in solidity as they are not visible to the child contract. The distinction between an internal function and a private function doesn't exist after the contract is compiled. Therefore, you can change private functions to be internal with no negative effect on the gas cost.&lt;br&gt;
As an exercise for the reader, benchmark the following code to see that changing "foo" to be internal does not affect the gas cost.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract A {
    // change this to be private
    function foo() internal pure returns (uint256 f) {
        f = 2;
    }
    function bar() internal pure returns (uint256 b) {
        b = foo();
    }
}

contract B is A {
    // 146 gas: 0.8.7 no optimizer
    function baz() external pure returns (uint256 b) {
        b = bar();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;p&gt;See our &lt;a href="https://www.rareskills.io/solidity-bootcamp"&gt;advanced solidity bootcamp&lt;/a&gt; to learn more advanced testing methodologies.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Uint256 max value</title>
      <dc:creator>RareSkills</dc:creator>
      <pubDate>Wed, 05 Apr 2023 07:29:30 +0000</pubDate>
      <link>https://forem.com/rareskills/uint256-max-value-3eap</link>
      <guid>https://forem.com/rareskills/uint256-max-value-3eap</guid>
      <description>&lt;p&gt;The maximum value of uint256 can be obtained with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type(uint256).max;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which is equal to 115792089237316195423570985008687907853269984665640564039457584007913129639935 (2²⁵⁶ - 1). But it's cleaner and safer to use type(uint256).max.&lt;br&gt;
The same can be used for signed integer types&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//57896044618658097711785492504343953926634992332820282019728792003956564819967
type(int256).max;

//-57896044618658097711785492504343953926634992332820282019728792003956564819968
type(int256).min;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Hacky ways to get the uint256 maximum value
&lt;/h2&gt;

&lt;p&gt;You could also specify it with hexadecimal, which would be a little cleaner than using the decimal representation, but still space consuming and error prone.&lt;br&gt;
&lt;/p&gt;

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

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's exactly 64 'f's, don't get it wrong! The 64 is derived from 256 bits divided by 8 to get the number of bytes (32), and each maximum byte is represented in hex by 0xff.&lt;br&gt;
Another ugly solution is to underflow the integer&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function maximum() public pure returns(uint256) {
   unchecked { return uint256(0) - uint256(1); }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following code works properly, but it is deceptive and not recommended for use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function maxUint() public pure returns (uint256) {
    return 2**256 - 1;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returns the correct value, which you can verify with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;assert(2**256 - 1 == type(uint256).max);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you write 2*&lt;em&gt;256 as a constant in solidity, the code won't compile because the compiler recognized 2&lt;/em&gt;*256 is too large to fit in uint256. But if it is immediately followed by a "- 1", then the compiler recognized the result of the arithmetic is valid with the type.&lt;br&gt;
It's better to just avoid all these gymnastics and just do type(uint256).max;&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;p&gt;If you are new to Solidity, see our learn &lt;a href="https://www.rareskills.io/learn-solidity"&gt;solidity free for beginners course&lt;/a&gt;.&lt;br&gt;
For intermediate and advanced developers, please see our &lt;a href="https://www.rareskills.io/solidity-bootcamp"&gt;expert solidity bootcamp&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>uint256</category>
      <category>solidity</category>
    </item>
    <item>
      <title>Solidity Events</title>
      <dc:creator>RareSkills</dc:creator>
      <pubDate>Sun, 02 Apr 2023 15:42:38 +0000</pubDate>
      <link>https://forem.com/rareskills/solidity-events-3n2</link>
      <guid>https://forem.com/rareskills/solidity-events-3n2</guid>
      <description>&lt;p&gt;Solidity events are the closest thing to a print or console.log statement in Ethereum. We will explain how they work, when to use them, and go into a lot of technical details often omitted in other resources.&lt;/p&gt;

&lt;p&gt;Here is a minimal example of a solidity event.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Perhaps the most well-known events are those emitted by ERC20 tokens when they are transferred. The sender, receiver, and amount are recorded in an event.&lt;br&gt;
Isn't this redundant? We can already look through the past transactions to see the transfers, and then we could look into the calldata to see the same information.&lt;br&gt;
This is correct, one could delete events and have no effect on the business logic of the smart contract. However, this would not be an efficient way to look at history.&lt;/p&gt;
&lt;h2&gt;
  
  
  Retrieving transactions faster
&lt;/h2&gt;

&lt;p&gt;The Ethereum client does not have an API for listing transactions by "type." Here are your options if you want to query transactions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;getTransaction
getTransactionFromBlock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;getTransactionFromBlock can only tell you what transactions occured on a particular block, it cannot target smart contracts across multiple blocks.&lt;br&gt;
getTransaction can only inspect transactions you know the transaction hash for.&lt;br&gt;
Events on the other hand can be retrieved much more easily. Here are the Ethereum client options:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;events
events.allEvents
getPastEvents
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Each of these require specifying the smart contract address the querier wishes to examine, and returns a subset (or all) of the events a smart contract emitted according to the query parameters specified.&lt;br&gt;
To summarize: Ethereum does not provide a mechanism to get all transactions for a smart contract, but it does provide a mechanism for getting all events from a smart contract.&lt;br&gt;
Why is this? Making events quickly retrievable requires additional storage overhead. If Ethereum did this for every transaction, this would make the chain considerably larger. With events, solidity programmers can be selective about what kind of information is worth paying the additional storage overhead for, to enable quick off-chain retrieval.&lt;/p&gt;
&lt;h2&gt;
  
  
  Listening to Events
&lt;/h2&gt;

&lt;p&gt;Here is an example of using the API described above. In this code, the client subscribes to events from a smart contract.&lt;/p&gt;
&lt;h2&gt;
  
  
  Example 1: Listening to ERC20 Transfer events.
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { ethers } = require("ethers");

// const provider = your provider

const abi = [
  "event Transfer(address indexed from, address indexed to, uint256 value)"
];

const tokenAddress = "0x...";
const contract = new ethers.Contract(tokenAddress, abi, provider);

contract.on("Transfer", (from, to, value, event) =&amp;gt; {
  console.log(`Transfer event detected: from=${from}, to=${to}, value=${value}`);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This code triggers a callback every time an ERC20 token emits a transfer Event.&lt;/p&gt;

&lt;p&gt;Example 2: Filtering an ERC20 approval for a specific address&lt;/p&gt;

&lt;p&gt;If we want to look at events retroactively, we can use the following code. In this example, we look to the past for Approval transactions in an ERC20 token.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const ethers = require('ethers');

const tokenAddress = '0x...';

const filterAddress = '0x...';

const tokenAbi = [
  // ...
];

const tokenContract = new ethers.Contract(tokenAddress, tokenAbi, provider);

// this line filters for Approvals for a particular address.
const filter = tokenContract.filters.Approval(filterAddress, null, null);

tokenContract.queryFilter(filter).then((events) =&amp;gt; {
  console.log(events);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you wanted to look for a trade between to particular addresses (if such a transaction exists), the ethers js javscript code would be as follows:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tokenContract.filters.Transfer(address1, address2, null);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Indexed vs non-indexed
&lt;/h2&gt;

&lt;p&gt;The example above works because the Approve (and Transfer) event in ERC20 sets the sender to be indexed. Here is the declaration in Solidity.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;event Approval(address indexed owner, address indexed spender, uint256 value);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If the "owner" argument was not indexed, the javascript code earlier would silently fail. The implication here is that you cannot filter for ERC20 events that have a specific value for the transfer, because that is not indexed. You must pull in all the events and filter them javascript-side; it cannot be done in the Ethereum client.&lt;br&gt;
An indexed argument for an event declaration is called a topic.&lt;/p&gt;
&lt;h2&gt;
  
  
  When to use events
&lt;/h2&gt;

&lt;p&gt;The generally accepted best practice for events is to log them whenever a state change happens. Some examples include:&lt;br&gt;
Changing the owner of the contract&lt;br&gt;
Moving ether&lt;br&gt;
Conducting a trade&lt;/p&gt;

&lt;p&gt;Not every state change requires an event. The question the Solidity developers should ask themselves is "would someone have an interest in retrieving or discovering this transaction quickly?"&lt;/p&gt;
&lt;h2&gt;
  
  
  Events cannot be used in view functions
&lt;/h2&gt;

&lt;p&gt;Events are state changing; they alter the state of the blockchain by storing the log. Therefore, they cannot be used in view (or pure) functions.&lt;br&gt;
Events are not as useful for debugging the way console.log and print are in other languages; because events themselves are state-changing, they are not emitted if a transaction reverts.&lt;/p&gt;
&lt;h2&gt;
  
  
  How many arguments can an event take?
&lt;/h2&gt;

&lt;p&gt;For unindexed arguments, there is no intrinsic limit to the number of arguments, though of course there are contract size and gas limits that apply. The following nonsensical example is valid solidity:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract ExampleContract {
    event Numbers(uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Similarly, there is no intrinsic limit to the length of strings or arrays stored in a log.&lt;br&gt;
However, there cannot be more than three indexed arguments (topics) in an event. An anonymous event can have 4 indexed arguments (we will cover this distinction later).&lt;br&gt;
An argument with zero events is also valid.&lt;/p&gt;
&lt;h2&gt;
  
  
  Variable names in events are optional but recommended
&lt;/h2&gt;

&lt;p&gt;The following events behave identically&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;event NewOwner(address newOwner);
event NewOwner(address);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In general, including the variable name would be ideal because the semantics behind the following example are very ambiguous.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;event Trade(address,address,address,uint256,uint256);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We can guess that the addresses correspond to the sender, and the token addresses, while the uint256es correspond to the amounts, but this is hard to decipher.&lt;br&gt;
It is conventional to capitalize the name of an event, but the compiler does not require it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Events can be inherited through parent contracts and interfaces
&lt;/h2&gt;

&lt;p&gt;When an event is declared in a parent contract, it can be emitted by the child contract. Events are internal and cannot be modified to be private or public. Here is an example&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
contract ParentContract {
  event NewNumber(uint256 number);

  function doSomething(uint256 number) public {
    emit NewNumber(number);
  }
}

contract ChildContract is ParentContract {
  function doSomethingElse(uint256 number) public {
    emit NewNumber(number);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Similarly, events can be declared in an interface and used in the child, as in the following example.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface IExampleInterface {
    event Deposit(address indexed sender, uint256 amount);
}

contract ExampleContract is IExampleInterface {
    function deposit() external payable {
        emit Deposit(msg.sender, msg.value);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Event selector
&lt;/h2&gt;

&lt;p&gt;The EVM (Ethereum Virtual Machine) identifies events with the keccak256 of their signature.&lt;br&gt;
For solidity versions 0.8.15 or higher, you can also retrieve the selector using the .selector member.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pragma solidity ^0.8.15;
contract ExampleContract {

    event SomeEvent(uint256 blocknum, uint256 indexed timestamp);

    function selector() external pure returns (bool) {

        // true
        return SomeEvent.selector == keccak256("SomeEvent(uint256,uint256)");
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The event selector is actually a topic itself (we will discuss this further in a later section).&lt;br&gt;
Marking variables as indexed or not does not change the selector.&lt;/p&gt;
&lt;h2&gt;
  
  
  Anonymous Events
&lt;/h2&gt;

&lt;p&gt;Events can be marked as anonymous, in which case they will not have a selector. This means that client-side code cannot specifically isolate them as a subset like our earlier examples.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pragma solidity ^0.8.15;
contract ExampleContract {

    event SomeEvent(uint256 blocknum, uint256 timestamp) anonymous;

    function selector() public pure returns (bool) {

        // ERROR: does not compile, anonymous events don't have selectors
        return SomeEvent.selector == keccak256("SomeEvent(uint256,uint256)");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Because the event signature is used as one of the indexes, an anonymous function can have four indexed topics, since the function signature is "freed up" as one of the topics.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract ExampleContract {
    // valid
    event SomeEvent(uint256 indexed, uint256 indexed, address indexed, address indexed) anonymous;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Anonymous events are rarely used in practice.&lt;/p&gt;
&lt;h2&gt;
  
  
  Advanced topics about events
&lt;/h2&gt;

&lt;p&gt;This section describes events at the assembly level of the EVM. This section can be skipped for programmers new to blockchain development.&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementation detail: Bloom filters
&lt;/h2&gt;

&lt;p&gt;To retrieve every transaction that has happened with a smart contract, the Ethereum client would have to scan every block, which would be an extremely heavy I/O operation; but Ethereum uses an important optimization.&lt;br&gt;
Events are stored in a Bloom Filter data structure for each block. A Bloom Filter is a probabilistic set that efficiently answers if a member is in the set or not. Instead of scanning the entire block, the client can ask the bloom filter if an event was emitted in the block. This allows the client to scan the blockchain much faster to find events.&lt;br&gt;
Bloom Filters are probabilistic: they sometimes incorrectly return that an item is a member of the set even if it isn't. The more members that are stored in a Bloom Filter, the higher the chance of error, and the larger the bloom filter must be (storage wise) to compensate for this. Because of this, Ethereum doesn't store all the transactions in a Bloom Filter. There are far fewer events than there are transactions. This keeps the storage size on the blockchain manageable.&lt;br&gt;
When the client gets a positive membership response from a bloom filter, it must scan the block to verify the event took place. However, this will only happens for a tiny subset of blocks, so on average the Ethereum client saves a lot of computation by checking the bloom filter for event presence first.&lt;/p&gt;
&lt;h2&gt;
  
  
  Yul Events
&lt;/h2&gt;

&lt;p&gt;In the Yul intermediate representation the distinction between indexed arguments (topics) an unindexed arguments becomes clear.&lt;br&gt;
The following Yul functions are available for emitting events (and their EVM opcode bears the same name). The table is copied from the yul documentation with some simplification.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;An log can have up to 4 topics, but a non-anonymous solidity event can have up to 3 indexed arguments. That is because the first topic is used to store the event signature. There is no opcode or Yul function for emitting more than four topics.&lt;br&gt;
The unindexed parameters are simply abi-encoded in the memory region [p…(p+s)) and emitted as one long byte sequence.&lt;br&gt;
Recall earlier that there was no limit in principle for how many unindexed arguments an event in Solidity can have. The underlying reason is that there is no explicit limit on how long the memory region pointed to in the first two parameters of the log op code takes. There is of course, limits provided by the contract size and memory expansion gas costs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gas Cost of Events
&lt;/h2&gt;

&lt;p&gt;Events are substantially cheaper than writing to storage variables. Events are not intended to be accessible by smart contracts, so the relative lack of overhead justifies a lower gas cost.&lt;br&gt;
The formula for how much gas an event costs is as follows (source):&lt;br&gt;
375 + 375 * num_topics + 8 * data_size + mem_expansion cost&lt;br&gt;
Each event costs at least 375 gas. An additional 375 is paid for each indexed parameter. A non-anonymous event has the event selector as an indexed parameter, so that cost is included most of the time. Then we pay 8 times the number of 32 byte words written to the chain. Because this region is stored in memory before being emitted, the memory expansion cost must be accounted for also.&lt;br&gt;
The most significant factor in an event's gas cost is the number of indexed events, so don't index the variables if it isn't necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Events are for clients to quickly retrieve transactions that may be of interest. Although they don't alter smart contract functionality, they allow the programmer to specify which transactions should be quickly retrievable. This is important for improving transparency in smart contracts.&lt;br&gt;
Events are relatively cheap gas-wise compared to other operations, but the most important factor in their cost is the number of indexed parameters, assuming the coder does not use an inordinate amount of memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn More
&lt;/h2&gt;

&lt;p&gt;Like what you see here? See our &lt;a href="https://www.rareskills.io/solidity-bootcamp"&gt;Solidity Bootcamp&lt;/a&gt; to learn more!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Verify Signature Solidity in Foundry</title>
      <dc:creator>RareSkills</dc:creator>
      <pubDate>Tue, 14 Mar 2023 08:57:29 +0000</pubDate>
      <link>https://forem.com/rareskills/verify-signature-solidity-in-foundry-olj</link>
      <guid>https://forem.com/rareskills/verify-signature-solidity-in-foundry-olj</guid>
      <description>&lt;p&gt;Here is a minimal (copy and paste) example of how to safely create and verify ECDSA signatures with OpenZeppelin in the &lt;a href="https://book.getfoundry.sh/"&gt;Foundry&lt;/a&gt; environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contract: Verifier.sol
&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;// SPDX-License-Identifier: MIT
&lt;/span&gt;&lt;span class="k"&gt;pragma&lt;/span&gt; &lt;span class="n"&gt;solidity&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mf"&gt;0.8&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="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"@openzeppelin/contracts/utils/cryptography/ECDSA.sol"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;Verifier&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;ECDSA&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="kt"&gt;bytes32&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;verifyingAddress&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;_verifyingAddress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;verifyingAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_verifyingAddress&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;verifyV1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;calldata&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;uint8&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;signedMessageHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;keccak256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toEthSignedMessageHash&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;signedMessageHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recover&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;verifyingAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"signature not valid v1"&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;verifyV2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;calldata&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;bytes&lt;/span&gt; &lt;span class="k"&gt;calldata&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;signedMessageHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;keccak256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toEthSignedMessageHash&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;signedMessageHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recover&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;verifyingAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"signature not valid v2"&lt;/span&gt;
        &lt;span class="p"&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;



&lt;h2&gt;
  
  
  Test (Verifier.t.sol)
&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;// SPDX-License-Identifier: MIT
&lt;/span&gt;&lt;span class="k"&gt;pragma&lt;/span&gt; &lt;span class="n"&gt;solidity&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mf"&gt;0.8&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="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"forge-std/Test.sol"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"../src/Verify.sol"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"@openzeppelin/contracts/utils/cryptography/ECDSA.sol"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"forge-std/console.sol"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;TestSigs1&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;Test&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;ECDSA&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="kt"&gt;bytes32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;Verifier&lt;/span&gt; &lt;span class="n"&gt;verifier&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="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;privateKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="mh"&gt;0x1010101010101010101010101010101010101010101010101010101010101010&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;setUp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&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;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;verifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Verifier&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;testVerifyV1andV2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"attack at dawn"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kt"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;msgHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;keccak256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toEthSignedMessageHash&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msgHash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;bytes&lt;/span&gt; &lt;span class="k"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encodePacked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;assertEq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;verifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;verifyV1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;verifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;verifyV2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&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;



&lt;p&gt;This will work even if you change the data type from "string" to something else.&lt;/p&gt;

&lt;p&gt;Note that OpenZeppelin supports two ways to represent the signature. It's generally more convenient to use the bytes version because this is only one extra piece of data to pass around. Note however that ERC20-Permit uses the three part signature &lt;code&gt;(r, s, v)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This article was originally published &lt;a href="https://www.rareskills.io/post/openzeppelin-verify-signature"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn More
&lt;/h2&gt;

&lt;p&gt;This article is used as reference material in our &lt;a href="https://www.rareskills.io/solidity-bootcamp"&gt;Solidity Bootcamp&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>solidity</category>
      <category>ethereum</category>
      <category>blockchain</category>
      <category>web3</category>
    </item>
    <item>
      <title>What makes blockchain immutable?</title>
      <dc:creator>RareSkills</dc:creator>
      <pubDate>Fri, 17 Feb 2023 01:18:40 +0000</pubDate>
      <link>https://forem.com/rareskills/what-makes-blockchain-immutable-on5</link>
      <guid>https://forem.com/rareskills/what-makes-blockchain-immutable-on5</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: This article is intended to be understandable by non-technical readers, to gain a very technical understanding, refer to our&lt;/em&gt; &lt;a href="https://www.rareskills.io/web3-blockchain-bootcamps"&gt;&lt;em&gt;blockchain bootcamp&lt;/em&gt;&lt;/a&gt; &lt;em&gt;after reading this article.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Contrary to popular belief, blockchains are not immutable because of cryptography, but because of economic incentives. Cryptography is just a nice tool that makes the economic incentive easier to apply.&lt;/p&gt;

&lt;h3&gt;
  
  
  How can a file be immutable?
&lt;/h3&gt;

&lt;p&gt;A blockchain is a file at the end of the day — it’s a file that contains the transaction history of the network. And we all know that files can be edited. So what makes blockchains immutable?&lt;/p&gt;

&lt;p&gt;If you store the same file across thousands of independent computers, and those computers don’t collude with each other, making an identical change on all of the computers is infeasible.&lt;/p&gt;

&lt;p&gt;If you make a change on one computer (such as deleting a transaction), the file on that computer won’t match what the other computers have.&lt;/p&gt;

&lt;p&gt;The next step to immutability is making changes easy to detect. Blockchains are gigabytes large, so sending an entire file across the network each time you need to compare notes to see if history was tampered with would be too costly.&lt;/p&gt;

&lt;p&gt;All files can be succinctly represented with a &lt;em&gt;hash function&lt;/em&gt;. A hash function takes an arbitrary file and outputs a number between 0 and&lt;/p&gt;

&lt;p&gt;115,792,089,237,316,195,423,570,985,008,687,907,853,269,984,665,640,564,039,457,584,007,913,129,639,935.&lt;/p&gt;

&lt;p&gt;You can think of a Hash Function as generating a digital fingerprint for a large file. If even one-bit changes in the file, the fingerprint will be a totally different number. Thus, it is easy to see if the file changed just by looking at the number.&lt;/p&gt;

&lt;p&gt;It’s generated by taking a sliding window over the file and using the file contents to trigger a “scramble” of the large number. Change just one letter, and the scramble will be entirely different. An animation is provided here&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mu40hPma--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mhb0pmcj5f4l27hjajwq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mu40hPma--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mhb0pmcj5f4l27hjajwq.gif" alt="Hash function animation" width="600" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, it’s easy for you to compare the following two numbers and see:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;is not the same number as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;111615780842736058021275746192495359629127277574153577922775094394736461370563.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you see two different very large numbers, you see the two different files it fingerprinted are different.&lt;/p&gt;

&lt;p&gt;These very large numbers are referred to as &lt;em&gt;“&lt;/em&gt;&lt;strong&gt;&lt;em&gt;blockhashes&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;File → Hash Function → Very Large Number&lt;/p&gt;

&lt;p&gt;If you use a block explorer like &lt;a href="http://etherscan.io/"&gt;&lt;/a&gt;&lt;a href="http://etherscan.io"&gt;etherscan.io&lt;/a&gt;, you’ll see this Very Large Number referred to as the &lt;strong&gt;blockhash.&lt;/strong&gt; That’s what we’ll call it for the rest of the article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---vL81vtj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1067/0%2Afu3_cVw1ccWJzOpL.jpg%2520align%3D%2522left%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---vL81vtj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1067/0%2Afu3_cVw1ccWJzOpL.jpg%2520align%3D%2522left%2522" alt="" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of sharing the entire file, computers in the network share the blockhash.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transaction Sequence
&lt;/h3&gt;

&lt;p&gt;When a computer shares a transaction, it needs to share three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The blockhash before the transaction&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The new transaction&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The blockhash after the new transaction&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the blockhash in step 1 doesn’t match a computer’s local blockhash, the computer rejects it. If the blockhash in step 3 doesn’t result after the transaction in step 2, the transaction is rejected.&lt;/p&gt;

&lt;p&gt;The only way to convince thousands of computers that your number is valid is to use the same blockhash (which represents your history) as the majority of computers. It’s easier to go with the majority than try to convince the majority they are wrong and this immense difficulty of going against the majority is what makes blockchain immutable and secure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ensuring non-collusion
&lt;/h3&gt;

&lt;p&gt;Even if you have thousands of computers around the world, if those computers are actually all controlled by a single entity, then making a change to the blockchain history would be easy for the controlling entity.&lt;/p&gt;

&lt;p&gt;The key is to make it hard for one person to participate in a majority of the network. This is what we refer to as “decentralization”&lt;/p&gt;

&lt;p&gt;Bitcoin uses a lot of electricity by design, because it is assumed that no single entity can consume a majority of the energy globally.&lt;/p&gt;

&lt;p&gt;Ethereum uses proof of stake (you need to lock up &lt;a href="https://www.rareskills.io/post/ethereum-contract-creation-code"&gt;Ethereum&lt;/a&gt; to participate in the Ethereum) because it is assumed that nobody can buy the majority of the Ethereum and lock it up to control a majority of the computers in the network.&lt;/p&gt;

&lt;p&gt;The fewer participants there are in the network, the more likely collusion becomes, which is why blockchains with lots of computers in the network advertise that number.&lt;/p&gt;

&lt;h3&gt;
  
  
  Relationship with distributed ledger
&lt;/h3&gt;

&lt;p&gt;Blockchains are sometimes referred to as “distributed ledgers.” or in other words, distributed and widely-accepted transaction histories. This is key because being distributed is an important part of being immutable.&lt;/p&gt;

&lt;p&gt;As we saw in the first section, unless several copies of the blockchain file are stored around the globe by non-colluding participants, then the file can be mutated.&lt;/p&gt;

&lt;p&gt;If a file is managed by only a few computers, then it isn’t really distributed, and thus isn’t really a blockchain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Economic incentive
&lt;/h3&gt;

&lt;p&gt;A computer in the network will not include a transaction in the network if it believes it would harm itself. For example, you run a computer in the network, and you see an incoming transaction that says “Bob suddenly has a million dollars out of nowhere.” Someone getting money for free (and missing out on the profit) is not something most computers would feel good about, so they reject the transaction and don’t accept blockhashes that correspond to a history containing that transaction. Knowing people won’t accept you inventing transactions that are illegitimately favorable to you discourages people from trying to include transactions like that.&lt;/p&gt;

&lt;p&gt;But what if all the computers got together and said “let’s each print ourselves a million coins?” A very interesting economic phenomenon happens: the value of the currency doesn’t change.&lt;/p&gt;

&lt;p&gt;Imagine one day the government says “everyone can trade their one dollar bills for ten neo-dollars, 5 dollar bills for 50-neo dollars, and so forth.” What would happen to the value of the currency? Nothing! The price of everything in the economy would simply have another zero in front of it and things would proceed as normal.&lt;/p&gt;

&lt;p&gt;For this kind of collusion to happen, everyone needs to agree on &lt;strong&gt;&lt;em&gt;exactly&lt;/em&gt;&lt;/strong&gt; how much extra money they will all get. If there is a disagreement, then everyone will have different blockhashes representing their history. If there is a disagreement like that, the network will grind to a halt, because the Transaction Sequence above won’t work anymore. If the network breaks, then everyone loses their money in the system, so there is an incentive to &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt; break the network.&lt;/p&gt;

&lt;h3&gt;
  
  
  When economic incentive isn’t sufficient
&lt;/h3&gt;

&lt;p&gt;To show immutability is primarily economic, not cryptographic, imagine a group of college students starting a new blockchain, let’s call it college-coin. Their collective net worth is less than $20,000. Then I come along as an evil billionaire with an offer they cannot refuse: give them each $20,000 to edit the blockchain exactly as I want. This is an offer they cannot refuse.&lt;/p&gt;

&lt;p&gt;Because they all make identical edits, they all get an identical blockhashes, and the network proceeds as normal. People then show each other this new blockhash when they make transactions, and everyone can spend money normally — but with the new item I added to the history.&lt;/p&gt;

&lt;p&gt;Small blockchains with insufficient economic incentives are vulnerable to attacks like these.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mutual Self Interest
&lt;/h3&gt;

&lt;p&gt;If you tamper with your file, your blockhash won’t match what the rest of the computers have. And if your blockhash doesn’t match what the other computer’s have, you won’t be able to spend money.&lt;/p&gt;

&lt;p&gt;Because every participant is incentivized to not tamper with their local copy of the blockchain (and thus get cut off from spending money), the blockchain does not get tampered with. This is what causes the blockchain to be immutable.&lt;/p&gt;

&lt;p&gt;All computer files are mutable. But if you put the appropriate economic incentives in place, people won’t change them.&lt;/p&gt;

</description>
      <category>blockchain</category>
    </item>
    <item>
      <title>Solidity gasleft()</title>
      <dc:creator>RareSkills</dc:creator>
      <pubDate>Sat, 04 Feb 2023 08:26:20 +0000</pubDate>
      <link>https://forem.com/rareskills/solidity-gasleft-1cne</link>
      <guid>https://forem.com/rareskills/solidity-gasleft-1cne</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The purpose of this article is to describe the behavior of the solidity &lt;code&gt;gasleft()&lt;/code&gt; function and its uses.&lt;/p&gt;

&lt;p&gt;It is a built-in function that is used to check the remaining gas during a contract call. It is one of the special variables and functions that always exist in the global namespace and thus does not need to be imported. &lt;code&gt;gasleft()&lt;/code&gt; was previously known as &lt;code&gt;msg.gas&lt;/code&gt; before Solidity version &lt;code&gt;0.4.21&lt;/code&gt;(&lt;a href="https://docs.soliditylang.org/en/v0.4.21/units-and-global-variables.html#block-and-transaction-properties:~:text=%3A%20complete%20calldata-,msg.gas,-(uint)%3A%20remaining" rel="noopener noreferrer"&gt;msg.gas&lt;/a&gt;)&lt;/p&gt;

&lt;h3&gt;
  
  
  Authorship
&lt;/h3&gt;

&lt;p&gt;This article was co-written by Jesse Raymond (&lt;a href="https://www.linkedin.com/in/jesse-raymond4/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://twitter.com/Jesserc_" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;) as part of the RareSkills Technical Writing Program.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why gasleft() matters
&lt;/h4&gt;

&lt;p&gt;The amount of gas used by smart contracts depends on the complexity of the code being run and the amount of data that is being processed during the contract call. &lt;/p&gt;

&lt;p&gt;If the provided gas isn't enough, the transaction reverts with an &lt;strong&gt;"out of gas"&lt;/strong&gt; error.&lt;/p&gt;

&lt;p&gt;Proper use of the &lt;code&gt;gasleft()&lt;/code&gt; function can prevent situations where contract transactions run out of gas. Let's look at an example in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example of preventing out-of-gas error
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Not running out of gas while distributing Ether
&lt;/h3&gt;

&lt;p&gt;Sending Ether to multiple addresses in smart contracts via loops can be very expensive, especially when dealing with a large array of addresses.&lt;/p&gt;

&lt;p&gt;If the amount of gas used to execute the transaction is not sufficient, the function will fail with an "&lt;strong&gt;out of gas&lt;/strong&gt;" error, as stated earlier.&lt;/p&gt;

&lt;p&gt;However, the &lt;code&gt;gasleft()&lt;/code&gt; function can be used to ensure that the remaining gas is sufficient to conduct the next transfer, and exit early otherwise.&lt;/p&gt;

&lt;p&gt;The following code demonstrates this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

contract GasConsumer{
    uint constant MINIMUM_AMOUNT = 10_000;

    // this is for illustration purposes only, not production
    function distributeEther(address[] calldata receivers) external {
        for (uint i = 0; i &amp;lt; receivers.length; i++) {

            payable(receivers[i]).transfer(1 ether);

            if (gasleft() &amp;lt; MINIMUM_AMOUNT) {
                return;
            }
        }
    }

    receive() external payable {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function "distributeEther" in the contract above takes an array of addresses, iterates through the array using a for loop, and sends 1 ether to each address with the "transfer" function.&lt;/p&gt;

&lt;p&gt;The "if statement" checks if the remaining gas after each Ether transfer in the loop is sufficient for the next transfer by checking whether the "gas left" after a transfer is less than 10,000 (9,000 for transferring Eth and an extra 1,000 for other minor opcodes). If it is less, the transaction ends without reverting the previous transfers.&lt;/p&gt;

&lt;p&gt;(Note that it is not a good idea to push out Ether unless the address are trusted. A malicious receiver could submit an address of a smart contract that reverts when receiving ether).&lt;/p&gt;

&lt;h2&gt;
  
  
  Benchmarks in Remix
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Using the gasleft() function to measure execution cost
&lt;/h3&gt;

&lt;p&gt;Another example is using the &lt;code&gt;gasleft()&lt;/code&gt; function to measure the total amount of gas used by a section of code.&lt;/p&gt;

&lt;p&gt;Here's an example in remix:&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%2F4z7lx4f3hycrzt02clku.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%2F4z7lx4f3hycrzt02clku.png" alt="solidity Gas left benchmark" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case, the &lt;code&gt;gasleft()&lt;/code&gt; function is used to find out how much gas is being used when a number is appended to the "numArr" array using the "updateArray" function. This is not the total amount of gas used by the function, but the amount of gas used before and after a number is appended to the array at the code &lt;code&gt;numArr.push(_num)&lt;/code&gt; at line 30. &lt;/p&gt;

&lt;h4&gt;
  
  
  Explaining the highlighted numbers
&lt;/h4&gt;

&lt;p&gt;We set "gasUsed" to be a public variable, so we can easily see the contents after the function is executed. A test for this is done by deploying the "GasCalc" contract and calling the "updateArray" function. &lt;/p&gt;

&lt;p&gt;The function returns a tuple, with the first entry resulting in &lt;strong&gt;80,348&lt;/strong&gt;, which is the "initialGas".&lt;/p&gt;

&lt;p&gt;The second entry in the tuple is "finalGas" and it was &lt;strong&gt;35,923&lt;/strong&gt;, &lt;strong&gt;this includes the gas cost for the &lt;code&gt;gasleft()&lt;/code&gt; function itself&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;By subtracting the final gas from the initial gas, we determine the execution cost of line 30 is &lt;strong&gt;44,425&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  The opcode behind gasleft requires "2 gas" to execute
&lt;/h4&gt;

&lt;p&gt;Solidity is a high-level language that is compiled into bytecodes which are executed on the Ethereum Virtual Machine(EVM).&lt;/p&gt;

&lt;p&gt;The opcode for the &lt;code&gt;gasleft()&lt;/code&gt; function is &lt;code&gt;GAS&lt;/code&gt; (bytecode 0x5A), which costs &lt;strong&gt;"2 gas"&lt;/strong&gt; according to the &lt;a href="https://ethereum.org/en/developers/docs/evm/opcodes/" rel="noopener noreferrer"&gt;ethereum documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Applications
&lt;/h2&gt;

&lt;h3&gt;
  
  
  OpenZeppelin proxy -- used to forward all gas to the implementation contract
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Using gasleft in yul
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;gasleft()&lt;/code&gt; function can also be accessed in Solidity smart contracts via yul (inline assembly), as &lt;code&gt;gas()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The OpenZeppelin proxy contract is an excellent example of how this is done. It is used in the “delegatecall” function which the proxy uses to call the implementation contract. &lt;code&gt;gas()&lt;/code&gt; is a convenient way to specify using the maximum available gas for this operation.&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%2Fxqs3y9z713n2j7gh6iyi.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%2Fxqs3y9z713n2j7gh6iyi.png" alt="openzeppelin proxy gas in yul" width="789" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link: &lt;a href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/18691d1a6f56dd906c175072a97dc5ed93ab968c/contracts/proxy/Proxy.sol#L31" rel="noopener noreferrer"&gt;OpenZeppelin Proxy Contract&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenZeppelin Minimal Forwarder -- used to validate the relayer sent enough gas to execute the transaction
&lt;/h3&gt;

&lt;p&gt;A “Relayer” is an off-chain entity that pays for the gas of another user’s transactions and the transaction is sent to a “Forwarder” contract which executes the transaction.&lt;/p&gt;

&lt;p&gt;When a user sends a request to the relayer, the user specifies the amount of gas to include in the transaction, and digitally signs their request.&lt;/p&gt;

&lt;p&gt;However, the relayer might not respect the gas limit requested by the user, and send a lower amount. This attack is documented in the &lt;a href="https://swcregistry.io/docs/SWC-126" rel="noopener noreferrer"&gt;SWC Registry&lt;/a&gt; as SWC-126.&lt;/p&gt;

&lt;p&gt;This causes a gas-griefing attack. If the relayer's call to the forwarding contract succeeds, but the sub call the user wants fails, then the relayer can "blame" the user for sending a transaction that reverts when the real reason was the subcall ran out of gas due to the relayer not sending enough.&lt;/p&gt;

&lt;p&gt;A subcall can fail due to a revert or an out-of-gas error, but the failure reason is generally not given, just the boolean success variable returns false. Because of this, we don't know if the subcall failed due to insufficient gas or bad instructions from the original sender.&lt;/p&gt;

&lt;p&gt;We can use "gasleft" to determine which case it is.&lt;/p&gt;

&lt;p&gt;When the execution to "call" happens, only 63/64 of the gas is forwarded. This 63/64 limit was introduced in EIP 150 and you can read more about it &lt;a href="https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After the subcall completes, then the amount of gas left should be at least 1/64 of the original limit specified by the user.&lt;/p&gt;

&lt;p&gt;If there is less than 1/64 of the requested gas after the subcall, then we know the relayer didn't send all of the gas they were supposed to.&lt;/p&gt;

&lt;p&gt;The forwarding contract here checks if at least 1/63 of the original limit is left as a margin of safety.&lt;/p&gt;

&lt;p&gt;The invalid code is used to cause the relayer's transaction to fail to make it clear the transaction failed due to the relayer, not the subcall.&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%2F56p3f33k7whqwltoivlp.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%2F56p3f33k7whqwltoivlp.png" alt="Openzeppelin minimal forwarder solidity gasleft" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
 Link: &lt;a href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/18691d1a6f56dd906c175072a97dc5ed93ab968c/contracts/metatx/MinimalForwarder.sol#L60" rel="noopener noreferrer"&gt;OpenZeppelin Minimal Forwarder Contract&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Chainlink EthBalanceMonitor Contract -- used to prevent the out-of-gas error from blocking Ether distribution
&lt;/h3&gt;

&lt;p&gt;This is a real-life application of the first example in this article, where we distributed ether in a loopp. There is more business logic in this code compared to earlier, but if we highlight the "gasleft()" check that causes an early exit from the loop, we see it is fundamentally the same design.&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%2Fbt3797bo7mw3im2h5kgg.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%2Fbt3797bo7mw3im2h5kgg.png" alt="chainlink gasleft" width="637" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link: &lt;a href="https://github.com/smartcontractkit/chainlink/blob/e1e78865d4f3e609e7977777d7fb0604913b63ed/contracts/src/v0.8/upkeeps/EthBalanceMonitor.sol#L140" rel="noopener noreferrer"&gt;Chainlink EthBalanceMonitor Contract&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Chainlink VRFCoordinatorV2 Contract -- used to get the amount of gas used for Chainlink VRFCoordinatorV2 fulfillments
&lt;/h3&gt;

&lt;p&gt;The Chainlink "VRFCoordinatorV2" smart contract is a  "Verifiable Random Function" coordinator, used for generating cryptographically &lt;a href="https://www.rareskills.io/post/generate-a-random-number-with-solidity-on-the-blockchain" rel="noopener noreferrer"&gt;secure random numbers on the blockchain&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The smart contract is the oracle for the smart contract to request and receive randomness.  (see here: &lt;a href="https://docs.chain.link/vrf/v2/introduction/" rel="noopener noreferrer"&gt;VRFCoordinatorV2&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;gasleft()&lt;/code&gt; function is used in the contract's "calculatePaymentAmount" function to charge the user a larger fee if the nodes need to pay more gas to fulfill the randomness.&lt;/p&gt;

&lt;p&gt;The lower gasleft() is in this circumstance, the higher the fee will be because (startGas - gasleft()) increases as more gas is consumed.&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%2Frmgfyiob0a956ouin6gv.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%2Frmgfyiob0a956ouin6gv.png" alt="chainlink fee solidity gasleft" width="774" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link: &lt;a href="https://github.com/smartcontractkit/chainlink/blob/e1e78865d4f3e609e7977777d7fb0604913b63ed/contracts/src/v0.8/VRFCoordinatorV2.sol#L617" rel="noopener noreferrer"&gt;Chainlink VRFCoordinatorV2 Contract&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we have discussed various use cases for &lt;code&gt;gasleft&lt;/code&gt;(). These include preventing out-of-gas errors, benchmarking solidity code execution cost, forwarding all gas to implementation contracts, and preventing relayer DOS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;p&gt;Check out the RareSkills &lt;a href="https://www.rareskills.io/web3-blockchain-bootcamps" rel="noopener noreferrer"&gt;blockchain bootcamp&lt;/a&gt; for more advanced blockchain programming topics!&lt;/p&gt;

</description>
      <category>announcement</category>
      <category>devto</category>
      <category>blockchain</category>
      <category>web3</category>
    </item>
    <item>
      <title>Generate Ethereum Address from Private Key Python</title>
      <dc:creator>RareSkills</dc:creator>
      <pubDate>Tue, 31 Jan 2023 04:43:48 +0000</pubDate>
      <link>https://forem.com/rareskills/generate-ethereum-address-from-private-key-python-5c5j</link>
      <guid>https://forem.com/rareskills/generate-ethereum-address-from-private-key-python-5c5j</guid>
      <description>&lt;h2&gt;
  
  
  Generate Ethereum Address from Public Key
&lt;/h2&gt;

&lt;p&gt;An ethereum address is the last 20 bytes of the keccack256 of the public key. The public key algorithm is secp256k1, the same used in bitcoin.&lt;/p&gt;

&lt;p&gt;Because it is an elliptic curve algorithm, the public key is an (x, y) pair corresponds to a point on the elliptic curve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generate the Elliptic Curve Public Key.
&lt;/h2&gt;

&lt;p&gt;The public key is the concatenation of x and y, and that is what we take the hash of.&lt;/p&gt;

&lt;p&gt;The code is provided below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;ecpy.curves&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Curve&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;ecpy.keys&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ECPublicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ECPrivateKey&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;sha3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;keccak_256&lt;/span&gt;

&lt;span class="n"&gt;private_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80&lt;/span&gt;

&lt;span class="n"&gt;cv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Curve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_curve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'secp256k1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;pv_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ECPrivateKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;private_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;pu_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pv_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_public_key&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# equivalent alternative for illustration:
# concat_x_y = bytes.fromhex(hex(pu_key.W.x)[2:] + hex(pu_key.W.y)[2:])
&lt;/span&gt;
&lt;span class="n"&gt;concat_x_y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pu_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;byteorder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'big'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;pu_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;byteorder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'big'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;eth_addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'0x'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;keccak_256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;concat_x_y&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;:].&lt;/span&gt;&lt;span class="nb"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'private key: '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;private_key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'eth_address: '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;eth_addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ecpy library is here &lt;a href="https://github.com/cslashm/ECPy"&gt;https://github.com/cslashm/ECPy&lt;/a&gt;. This library implements the elliptic curve math in python, so it won’t be as fast as a wrapper around the bitcoin C implementation, which is used by the &lt;a href="https://github.com/ofek/coincurve/"&gt;coincurve&lt;/a&gt; library.&lt;/p&gt;

&lt;p&gt;However, the python implementation allows you to see step by step the elliptic curve math used to derive the public key.&lt;/p&gt;

&lt;p&gt;You can use this code to generate an ethereum vanity address with brute force, but be mindful that if your source of randomness is not secure or has too few bits of randomness, you may fall victim to a hack similar to &lt;a href="https://cointelegraph.com/news/almost-1m-in-crypto-stolen-from-vanity-address-exploit"&gt;this&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  About secp256k1: Public Key from Private Key
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The shape of the Curve
&lt;/h3&gt;

&lt;p&gt;Secp256k1 defines the shape of the elliptic curve y² = x³ + y (mod p) where p is the prime number 115792089237316195423570985008687907853269984665640564039457584007908834671663&lt;/p&gt;

&lt;p&gt;Or 2²⁵⁶ — 2³² — 977&lt;/p&gt;

&lt;p&gt;The prime p should not be confused with the order of the curve. Not every value n in 0 &amp;lt; n &amp;lt; p satisfies the equation above. However, operations on the curve are guaranteed to be closed. That is, if two valid points are added or multiplied, the result will be a valid number on the curve.&lt;/p&gt;

&lt;h3&gt;
  
  
  The starting point
&lt;/h3&gt;

&lt;p&gt;The other important parameter in secp256k1 is the starting point G. Since G is a point on the elliptic curve, it is 2-dimensional and has the parameters&lt;/p&gt;

&lt;p&gt;x = 55066263022277343669578718895168534326250603453777594175500187360389116729240&lt;br&gt;
y = 32670510020758816978083085130507043184471273380659243275938904335757337482424&lt;/p&gt;

&lt;p&gt;To see G is a valid point, you can plug the numbers into python&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;55066263022277343669578718895168534326250603453777594175500187360389116729240&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;32670510020758816978083085130507043184471273380659243275938904335757337482424&lt;/span&gt;
&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;115792089237316195423570985008687907853269984665640564039457584007908834671663&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create a public / private key pair, a random number s is created (this is the secret key). The point G is added to itself s times and the new point (x, y) is the public key. It is not feasible to derive s from G and (x, y) if s is sufficiently large.&lt;/p&gt;

&lt;p&gt;Signing messages in this scheme boils down to demonstrating you know s without revealing it.&lt;/p&gt;

&lt;p&gt;Adding G to itself s times is the same as multiplying s * G. In fact, we can see this operation at a lower level in by stripping away some of the abstractions the library is providing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;ecpy.curves&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Curve&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;sha3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;keccak_256&lt;/span&gt;

&lt;span class="n"&gt;private_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80&lt;/span&gt;

&lt;span class="n"&gt;cv&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Curve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_curve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'secp256k1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;pu_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;private_key&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt; &lt;span class="c1"&gt;# just multiplying the private key by generator point (EC multiplication)
&lt;/span&gt;
&lt;span class="n"&gt;concat_x_y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pu_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;byteorder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'big'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;pu_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;byteorder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'big'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;eth_addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'0x'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;keccak_256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;concat_x_y&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;:].&lt;/span&gt;&lt;span class="nb"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'private key: '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;private_key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'eth_address: '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;eth_addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The public key is simply the private key multiplied by the point G on the secp256k1 elliptic curve. That’s it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn More
&lt;/h2&gt;

&lt;p&gt;Check out our advanced &lt;a href="https://www.rareskills.io/web3-blockchain-bootcamps"&gt;blockchain bootcamp&lt;/a&gt; today and become a blockchain developer who knows the hard stuff other coders don’t.&lt;/p&gt;

</description>
      <category>solidity</category>
      <category>ethereum</category>
      <category>cryptography</category>
      <category>python</category>
    </item>
    <item>
      <title>Smart Contract Creation Cost</title>
      <dc:creator>RareSkills</dc:creator>
      <pubDate>Sun, 01 Jan 2023 00:40:00 +0000</pubDate>
      <link>https://forem.com/rareskills/smart-contract-creation-cost-2ag6</link>
      <guid>https://forem.com/rareskills/smart-contract-creation-cost-2ag6</guid>
      <description>&lt;p&gt;The cost to deploy a smart contract on ethereum has six factors. The biggest factors are the contract size and what code gets executed during the deployment phase. We will give a step by step example with a simple contract.&lt;/p&gt;

&lt;p&gt;We will translate "gas" into dollars at the end of the article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Smart contract deployment cost
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The 21,000 gas that all Ethereum transactions must pay&lt;/li&gt;
&lt;li&gt;A fixed cost of 32,000 gas for creating a new contract&lt;/li&gt;
&lt;li&gt;22,100 gas for each storage variable set&lt;/li&gt;
&lt;li&gt;4 gas for each zero byte in the transaction data 16 gas for each non-zero byte in the transaction.&lt;/li&gt;
&lt;li&gt;The cost to execute each bytecode during the initialization&lt;/li&gt;
&lt;li&gt;200 gas per byte of deployed bytecode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s use an example of a deploying a minimal Solidity contract in Remix&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pragma solidity 0.8.7;

contract Minimal {
    constructor() payable {

    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F2l84k0d0mmmhej477jbg.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%2F2l84k0d0mmmhej477jbg.png" alt="Minimal contract to measure solidity contract deployment cost on Ethereum" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that the deployment cost according to remix was 66,862. We will break down this cost in this article.&lt;/p&gt;

&lt;p&gt;We have made the constructor payable and set the optimizer to 200 runs. This has the effect of making the smart contract smaller.&lt;/p&gt;

&lt;p&gt;Let’s add it up&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;21,000 gas | deployment
32,000 gas | creation
Total: 53,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We still have 13,862 gas to account for&lt;/p&gt;

&lt;h3&gt;
  
  
  Transaction bytecode gas cost (tx.data)
&lt;/h3&gt;

&lt;p&gt;The transaction bytecode was&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Each hex par is a byte, so let’s add spaces to make it more readable.&lt;/p&gt;

&lt;p&gt;To split it up like that, we can use the following python code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;itertools&lt;/span&gt;

&lt;span class="c1"&gt;# note that we manually removed the "0x" at the beginning
&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;6080604052603f8060116000396000f3fe6080604052600080fdfea2646970667358221220c5cad0aa1e64e2ca6a6cdf28a25255a8ebbf3cdd5ea0b8e4129a3c83c4fbb72a64736f6c63430008070033&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;itertools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zip_longest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[::&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])])&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We get&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;60 80 60 40 52 60 3f 80 60 11 60 00 39 60 00 f3 fe 60 80 60 40 52 60 00 80 fd fe a2 64 69 70 66 73 58 22 12 20 c5 ca d0 aa 1e 64 e2 ca 6a 6c df 28 a2 52 55 a8 eb bf 3c dd 5e a0 b8 e4 12 9a 3c 83 c4 fb b7 2a 64 73 6f 6c 63 43 00 08 07 00 33
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each non-zero byte costs 16 gas, and each zero byte (00) costs 4 gas.&lt;/p&gt;

&lt;p&gt;To count them, we can use this python one-liner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;60 80 60 40 52 60 3f 80 60 11 60 00 39 60 00 f3 fe 60 80 60 40 52 60 00 80 fd fe a2 64 69 70 66 73 58 22 12 20 c5 ca d0 aa 1e 64 e2 ca 6a 6c df 28 a2 52 55 a8 eb bf 3c dd 5e a0 b8 e4 12 9a 3c 83 c4 fb b7 2a 64 73 6f 6c 63 43 00 08 07 00 33&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# non-zero bytes
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;00&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;
&lt;span class="c1"&gt;# prints 75
&lt;/span&gt;
&lt;span class="c1"&gt;# zero bytes
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;00&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;
&lt;span class="c1"&gt;# prints 5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have 75 non-zero bytes and 5 zero bytes. The math works out to 75 x 16 + 5 x 4 = 1220 gas&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;21,000 gas | deployment
32,000 gas | creation
 1,220 gas | bytecode cost
Total: 54,220 gas. 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have 12,642 gas to account for to bring the total cost to 66,862.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment code gas cost
&lt;/h2&gt;

&lt;p&gt;Let’s look at the bytecode again&lt;/p&gt;

&lt;p&gt;60 80 60 40 52 60 3f 80 60 11 60 00 39 60 00 f3 fe &lt;strong&gt;60 80 60 40 52 60 00 80 fd fe a2 64 69 70 66 73 58 22 12 20 c5 ca d0 aa 1e 64 e2 ca 6a 6c df 28 a2 52 55 a8 eb bf 3c dd 5e a0 b8 e4 12 9a 3c 83 c4 fb b7 2a 64 73 6f 6c 63 43 00 08 07 00 33&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The parts in bold are the deployment code. The first part is the initialization code. We need to multiply each of the deployment code by 200 gas to get the cost. This has a higher cost than the bytecode cost above because this is stored in the Ethereum state.&lt;/p&gt;

&lt;p&gt;Let’s do that in python again&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;deployment_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;60 80 60 40 52 60 00 80 fd fe a2 64 69 70 66 73 58 22 12 20 c5 ca d0 aa 1e 64 e2 ca 6a 6c df 28 a2 52 55 a8 eb bf 3c dd 5e a0 b8 e4 12 9a 3c 83 c4 fb b7 2a 64 73 6f 6c 63 43 00 08 07 00 33&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deployment_code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="c1"&gt;# 63
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;63 x 200 = 12,600 gas&lt;/p&gt;

&lt;p&gt;So here is the breakdown so far&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;21,000 gas | deployment
32,000 gas | creation
 1,220 gas | bytecode cost
12,600 gas | deployed bytecode
Total: 66,820
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Almost there! We are 42 gas short of our 66,862 target.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bytecode execution gas cost
&lt;/h2&gt;

&lt;p&gt;We also need to factor in the actual execution of the initialization bytecode.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;60 80 60 40 52 60 3f 80 60 11 60 00 39 60 00 f3 fe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can translate that to a more convenient format using the &lt;a href="https://www.evm.codes/playground?fork=grayGlacier" rel="noopener noreferrer"&gt;evm playground tool&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUSH1 0x80 | 3 gas 
PUSH1 0x40 | 3 gas 
MSTORE     | 12 gas 
PUSH1 0x3f | 3 gas 
DUP1       | 3 gas 
PUSH1 0x11 | 3 gas 
PUSH1 0x00 | 3 gas 
CODECOPY   | 9 gas 
PUSH1 0x00 | 3 gas 
RETURN     | 0 gas 
INVALID    | not executed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the total is 42, as expected. These gas costs were obtained by running the remix debugger.&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%2Fmduq9jl1u74ut2g8t1xr.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%2Fmduq9jl1u74ut2g8t1xr.png" alt="Debugging solidity contract deployment cost on Ethereum" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And we are done, we have accounted for each component of the deployment of a smart contract.&lt;/p&gt;

&lt;p&gt;So here is the final breakdown&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;21,000 gas | deployment
32,000 gas | creation
 1,220 gas | bytecode cost
12,600 gas | deployed bytecode
    42 gas | deployment execution cost
Total: 66,862 gas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that if we set storage variables in the constructor, the cost would be higher. We’d have to pay 22,100 gas for each variable set. But to keep this walkthrough manageable, we have omitted that case.&lt;/p&gt;

&lt;p&gt;If you want to become a solidity ninja and be able to account for gas costs fluently, sign up for our &lt;a href="https://www.rareskills.io/solidity-bootcamp" rel="noopener noreferrer"&gt;Solidity coding bootcamp&lt;/a&gt;, which is the first &lt;a href="https://www.rareskills.io/web3-blockchain-bootcamps" rel="noopener noreferrer"&gt;blockchain bootcamp in our series of web3 bootcamps&lt;/a&gt;. If you want a gentle introduction to gas cost calculation, sign up for our &lt;a href="https://www.udemy.com/course/advanced-solidity-understanding-and-optimizing-gas-costs/?referralCode=C4684D6872713525E349" rel="noopener noreferrer"&gt;Udemy course&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;All the numbers for gas cost obtained here are from the &lt;a href="https://ethereum.github.io/yellowpaper/paper.pdf" rel="noopener noreferrer"&gt;Ethereum Yellow Paper&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Translating smart contract creation cost to dollars
&lt;/h2&gt;

&lt;p&gt;To turn units of "gas" into dollars, the formula is &lt;/p&gt;

&lt;p&gt;gas x gas per gwei x price of ether ÷ 1 billion.&lt;/p&gt;

&lt;p&gt;Gas per gwei can be obtain from sites like ethgasstation or etherscan. In our example, assuming Eth costs $1,000 and the price of gas is 20 gwei, the cost in dollars would be&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;66,862 x 20 x 1000 ÷ 1 billion = $1.34
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this seems low, remember, this is a minimal contract with low gas prices. If, like it was in 2021, gas was 100 gwei, the contract deployment cost was 1 million gas, and ether prices was $4,000, then it would come out to $400.&lt;/p&gt;

</description>
      <category>emptystring</category>
    </item>
    <item>
      <title>Solana Smart Contract Language</title>
      <dc:creator>RareSkills</dc:creator>
      <pubDate>Sat, 31 Dec 2022 07:01:02 +0000</pubDate>
      <link>https://forem.com/rareskills/solana-smart-contract-language-25o1</link>
      <guid>https://forem.com/rareskills/solana-smart-contract-language-25o1</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XzPPwpxE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lx09ezrwk6mda34hj3u4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XzPPwpxE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lx09ezrwk6mda34hj3u4.jpg" alt="Solana Rust Metaplex Library" width="880" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The primary Solana programming language is Rust, but &lt;a href="https://docs.solana.com/developing/on-chain-programs/developing-c"&gt;C, C++&lt;/a&gt;, and even &lt;a href="https://seahorse-lang.org/"&gt;Python&lt;/a&gt; are supported.&lt;/p&gt;

&lt;p&gt;Solana uses Rust, C, and C++ in a similar way. We’ll discuss Python in a later section.&lt;/p&gt;

&lt;p&gt;Rust is a compiled language. If you compile Rust on your computer, it will ultimately turn into LLVM-IR (low level virtual machine intermediate representation), and LLVM turns it into the bytecode that can run on your machine (x86, arm64, etc.).&lt;/p&gt;

&lt;p&gt;In Solana, the sequence looks like this: 1) Compile Rust to LLVM-IR, then to BPF (Berkeley Packet Filter) and store the bytecode on the blockchain. 2) The validators JIT compile (&lt;a href="https://en.wikipedia.org/wiki/Just-in-time_compilation"&gt;just in time compile&lt;/a&gt;) the BPF to the instruction set compatible with their hardware, usually x86, but arm64 might be another common target.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Packet Filter&lt;/em&gt;, you ask? Why would the Solana programming language have to do with internet packets?&lt;/p&gt;

&lt;p&gt;This is actually a clever design choice on Solana’s part.&lt;/p&gt;

&lt;h2&gt;
  
  
  User space vs kernel space
&lt;/h2&gt;

&lt;p&gt;Linux has a notion of kernel space and a user space. If you want to do things like open a file or start another process, your executable needs to ask the operating system to do that for it. Let’s say you write a python script to open a file and print out every even line. The actual loading of the file’s bytecode happens in kernel space, but once the bytecode is given to the script, the interpretation to ASCII and determining if a line number is even or odd happens in userspace.&lt;/p&gt;

&lt;p&gt;This abstraction exists for several reasons, but one obvious one is security. Not every user or executable should be able to open or execute arbitrary files. The operating system determines which “APIs” are permitted. (By the way, the “API” to open a file is technically called a “system call” in operating system speak).&lt;/p&gt;

&lt;p&gt;Similarly, programs and executables should not be allowed to arbitrarily access incoming internet packets. They must, by default, make system calls to ask the operating system permission to view packets, which can only be accessed from kernel space.&lt;/p&gt;

&lt;p&gt;One important concept must be emphasized here: transitioning back and forth between user space and kernel space is generally slow.&lt;/p&gt;

&lt;p&gt;If you are filtering incoming internet packets, then that is a lot of jumps back and forth from userspace and kernel space. Imagine copying every incoming packet from kernel space to user space. That would create a lot of overhead.&lt;/p&gt;

&lt;p&gt;This is why BPF was invented. You can run executables inside the kernel space to avoid this jumping.&lt;/p&gt;

&lt;p&gt;But if you know anything about having kernel privileges, you know this is extremely dangerous! Having control over the kernel (operating system) could cause the computer to crash if there is a bug. Worse, if malicious code gets executed, the damage is limitless.&lt;/p&gt;

&lt;p&gt;Of course, the BPF designers thought of this. Before BPF code is executed, it gets validated to ensure that it runs for a fixed amount of time, I.e. must terminate, can only access a designated memory area, and follows other suitable restrictions.&lt;/p&gt;

&lt;p&gt;As an aside, since its invention, BPF has expanded its use beyond just filtering packets, but its name has stuck.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Solana uses BPF
&lt;/h2&gt;

&lt;p&gt;By leveraging the existing research that went into making BPF programs safe, Solana can run smart contracts where they run the fastest — inside the kernel! This is pretty remarkable if you think about it. You can run untrusted smart contracts which could have been written by anyone in the most sensitive (but efficient) part of the operating system — the operating system kernel. Solana gets to leverage decades of research and investment in this area to get a nice performance boost.&lt;/p&gt;

&lt;p&gt;BPF is not machine instructions; it’s still its own set of bytecode. However, it can be JIT compiled to a variety of CPU architectures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back to Rust, C, and C++
&lt;/h2&gt;

&lt;p&gt;These three programming languages have long been supported by LLVM. This is another area where Solana can take advantage of decades of investment (yes, it’s odd to speak of tech in terms of decades, but &lt;a href="https://en.wikipedia.org/wiki/LLVM"&gt;LLVM came out in 2003&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;You can use C or C++ as a Solana programming language, but you will get far less support with tooling. It’s generally recommended that you use Rust even if you are a C or C++ expert. Rust will be easy to learn if you are already fluent in C++.&lt;/p&gt;

&lt;h2&gt;
  
  
  How much Rust do you need to know to program Solana?
&lt;/h2&gt;

&lt;p&gt;Not that much, but it still requires some study. Rust is not a language that you can “google your way through.” For example, suppose you are programming in ruby from a java or scala background. In that case, you can pretty easily ask google for the equivalent programming patterns (your code might not look idiomatic, but it will be readable and functional). If (when) you copy and paste code from Stackoverflow, you’ll still have a good intuition about what the code is doing.&lt;/p&gt;

&lt;p&gt;However, if you do this with Rust, you will run into some frustrating roadblocks. Rust has syntax that is hard to look up (try looking up a “#” in the search engine), and it has concepts that aren’t found in other programming languages.&lt;/p&gt;

&lt;p&gt;Rust is a vast language. However, you only need to know a subset of it. Thus, our &lt;a href="https://www.rareskills.io/rust-bootcamp"&gt;Rust Bootcamp&lt;/a&gt; and &lt;a href="https://www.rareskills.io/solana-bootcamp"&gt;Solana Bootcamp&lt;/a&gt; is designed to focus on Rust first, but only the parts that you need to know to be comfortable coding smart contracts for Solana (Solana programs).&lt;/p&gt;

&lt;h2&gt;
  
  
  How Solana can use the Python programming language
&lt;/h2&gt;

&lt;p&gt;Compiling Rust, C, or C++ to BPF is straightforward. With Python, it’s quite different; Python, obviously, is an interpreted language, not a language that can be compiled with LLVM.&lt;/p&gt;

&lt;p&gt;To oversimplify, Python is &lt;a href="https://en.wikipedia.org/wiki/Source-to-source_compiler"&gt;transpiled&lt;/a&gt; to Rust, and then everything behaves as above.&lt;/p&gt;

&lt;p&gt;If you want the exact workflow, it’s documented visually on the &lt;a href="https://github.com/ameliatastic/seahorse-lang"&gt;seahorse-lang github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Solana programs usually aren’t written in raw Rust; most developers use the Anchor Framework. Therefore, although Seahorse does fairly typical transpilation, it’s also taking advantage of planned framework similarities.&lt;/p&gt;

&lt;p&gt;The Seahorse Framework closely models the Anchor Framework so that the python code can be translated into Rust code that closely models the way it would be written in an Anchor framework.&lt;/p&gt;

&lt;p&gt;Note that this project is in beta right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Addendum: Rust is migrating BPF to SBF.
&lt;/h2&gt;

&lt;p&gt;As of October 2022, Solana began migrating from BPF to SBF (Solana binary format). As of the time of writing, the documentation on this change is quite sparse, but this won’t affect most developers. If your build tool is configured to compile to BPF, you will get a deprecation warning, but everything will still run. Just change your build flags.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;p&gt;Like what you see here? Check out our &lt;a href="https://www.rareskills.io/web3-blockchain-bootcamps"&gt;blockchain bootcamp&lt;/a&gt;. &lt;a href="https://www.rareskills.io/solana-bootcamp"&gt;Solana&lt;/a&gt; and &lt;a href="https://www.rareskills.io/rust-bootcamp"&gt;Rust&lt;/a&gt; are two of the &lt;a href="https://www.rareskills.io/web3-blockchain-bootcamps"&gt;web3 bootcamps&lt;/a&gt; that we teach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.kernel.org/doc/html/latest/bpf/instruction-set.html"&gt;https://www.kernel.org/doc/html/latest/bpf/instruction-set.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;sbf migration&lt;br&gt;
&lt;a href="https://docs.rs/solana_rbpf/latest/solana_rbpf/ebpf/index.html"&gt;https://docs.rs/solana_rbpf/latest/solana_rbpf/ebpf/index.html&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=5jQvuPWpzcE"&gt;https://www.youtube.com/watch?v=5jQvuPWpzcE&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;eBPF&lt;br&gt;
&lt;a href="https://ebpf.io/what-is-ebpf/"&gt;https://ebpf.io/what-is-ebpf/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=Q8eY67hDvkc"&gt;https://www.youtube.com/watch?v=Q8eY67hDvkc&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>solana</category>
      <category>blockchain</category>
      <category>smartcontract</category>
    </item>
  </channel>
</rss>
