<?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>Logic</title>
        <link>https://paragraph.com/@logic-6</link>
        <description>Blockchain 🔗 | Front-end ⚛️ | Books 📚 | An empty man learning Web3 👾 | Exploring #AccountAbstraction 💳 and #ERC4337</description>
        <lastBuildDate>Tue, 12 May 2026 10:50:11 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[Solidity Study Notes]]></title>
            <link>https://paragraph.com/@logic-6/solidity-study-notes</link>
            <guid>FsGhVfnv8iHOuqoK5UsY</guid>
            <pubDate>Wed, 16 Aug 2023 06:22:56 GMT</pubDate>
            <description><![CDATA[Solidity LearningChapter #1Calculate Transaction FeeTransaction Fee = ( Block Base Fee Per Gas + MaxPriorityFee Per Gas ) * Gas UsedBase Fee: The minimum "gas price" to send your transaction1 Eth = 1000000000 GWei = 1000000000000000000 WeiConsensusConsensus is the mechanism used to agree on the state of a blockchain.1. Chain Selection Algorithm2. Sybil Resistance MechanismLike PoW(Proof of Work) and PoS(Proof of Stake)Chapter #2First Contract in Remix// SPDX-License-Identifier: MIT pragma sol...]]></description>
            <content:encoded><![CDATA[<h1 id="h-solidity-learning" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Solidity Learning</h1><h2 id="h-chapter-1" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Chapter #1</h2><h3 id="h-calculate-transaction-fee" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Calculate Transaction Fee</h3><p>Transaction Fee = ( Block Base Fee Per Gas + MaxPriorityFee Per Gas ) * Gas Used</p><ul><li><p>Base Fee: The minimum &quot;gas price&quot; to send your transaction</p></li><li><p>1 Eth = 1000000000 GWei = 1000000000000000000 Wei</p></li></ul><h3 id="h-consensus" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Consensus</h3><p>Consensus is the mechanism used to agree on the state of a blockchain.</p><h4 id="h-1-chain-selection-algorithm" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">1. Chain Selection Algorithm</h4><h4 id="h-2-sybil-resistance-mechanism" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">2. Sybil Resistance Mechanism</h4><ul><li><p>Like PoW(Proof of Work) and PoS(Proof of Stake)</p></li></ul><h2 id="h-chapter-2" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Chapter #2</h2><h3 id="h-first-contract-in-remix" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">First Contract in Remix</h3><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

// This is a smart contract
contract SimpleStorage {
    // The basic types: boolean | unit | int | address | bytes
    // unit: POSITIVE number only

    bool hasFavoriteNumber = true;
    uint favoriteNumber = 123;
    string favoriteNumberInText = &apos;five&apos;;
    bytes favoriteBytes = &apos;cat&apos;;
}
"><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-comment">// This is a smart contract</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">SimpleStorage</span> </span>{
    <span class="hljs-comment">// The basic types: boolean | unit | int | address | bytes</span>
    <span class="hljs-comment">// unit: POSITIVE number only</span>

    <span class="hljs-keyword">bool</span> hasFavoriteNumber <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
    <span class="hljs-keyword">uint</span> favoriteNumber <span class="hljs-operator">=</span> <span class="hljs-number">123</span>;
    <span class="hljs-keyword">string</span> favoriteNumberInText <span class="hljs-operator">=</span> <span class="hljs-string">'five'</span>;
    <span class="hljs-keyword">bytes</span> favoriteBytes <span class="hljs-operator">=</span> <span class="hljs-string">'cat'</span>;
}
</code></pre><blockquote><p>Default Value <code>uint favoriteNumber; // 0</code></p></blockquote><h3 id="h-function" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Function</h3><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

// Contract: 0xd9145CCE52D386f254917e481eB44e9943F39138
contract SimpleStorage {
    uint256 favoriteNumber;

    function store(uint256 _favoriteNumber) public {
        favoriteNumber = _favoriteNumber;
    }

    // getter function of favoriteNumber
    function retrieve() public view returns(uint256) {
        return favoriteNumber;
    }
}
"><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-comment">// Contract: 0xd9145CCE52D386f254917e481eB44e9943F39138</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">SimpleStorage</span> </span>{
    <span class="hljs-keyword">uint256</span> favoriteNumber;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">store</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> _favoriteNumber</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        favoriteNumber <span class="hljs-operator">=</span> _favoriteNumber;
    }

    <span class="hljs-comment">// getter function of favoriteNumber</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">retrieve</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> favoriteNumber;
    }
}
</code></pre><blockquote><p><strong>Tips:</strong></p><ul><li><p>Smart Contracts have addresses just like our wallet accounts do.</p></li><li><p>Any time you change something on-chain, including making a new contract, it happens in a transaction.(部署合约其实就是在发送一个交易；我们在区块链上做任何事情，修改任何状态，其实就是在发送一个交易)</p></li><li><p><code>view, pure</code>: 标记上后不会花费 gas，因为这意味着我们只会读取这个合约的状态（除非你在要花费 gas 的 store 函数中调用它）</p></li><li><p><code>view and pure</code> functions disallow modification of state.(我们不可以在这个函数里修改任何状态)</p></li></ul></blockquote><h4 id="h-function-visibility-specifiers" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Function Visibility Specifiers</h4><ul><li><p>public: it creates <code>getter()</code> automatically.</p></li><li><p>private: only visible in current contract.(此合约可见)</p></li><li><p>external: only visible externally.(合约外部可见，合约外的账户可以调用这个函数)</p></li><li><p>internal(default visibility ): only visible internally.(合约内部可见，这有这个合约或者继承它的合约可以调取)</p></li></ul><h3 id="h-arrays-and-structure" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Arrays and Structure</h3><p>We want to store different people with different numbers here. So we are using <code>struct</code>.</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

// Contract: 0xd9145CCE52D386f254917e481eB44e9943F39138
contract SimpleStorage {
    uint256 public favoriteNumber;
    // Instantiate a person
    People public person = People({favoriteNumber: 12, name: &apos;Logic&apos;});

    struct People {
        uint256 favoriteNumber;
        string name;
    }

    function store(uint256 _favoriteNumber) public {
        favoriteNumber = _favoriteNumber;
    }

    // getter function of favoriteNumber
    function retrieve() public view returns(uint256) {
        return favoriteNumber;
    }

}
"><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-comment">// Contract: 0xd9145CCE52D386f254917e481eB44e9943F39138</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">SimpleStorage</span> </span>{
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> favoriteNumber;
    <span class="hljs-comment">// Instantiate a person</span>
    People <span class="hljs-keyword">public</span> person <span class="hljs-operator">=</span> People({favoriteNumber: <span class="hljs-number">12</span>, name: <span class="hljs-string">'Logic'</span>});

    <span class="hljs-keyword">struct</span> <span class="hljs-title">People</span> {
        <span class="hljs-keyword">uint256</span> favoriteNumber;
        <span class="hljs-keyword">string</span> name;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">store</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> _favoriteNumber</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        favoriteNumber <span class="hljs-operator">=</span> _favoriteNumber;
    }

    <span class="hljs-comment">// getter function of favoriteNumber</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">retrieve</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> favoriteNumber;
    }

}
</code></pre><p>We are storing the structures as an array here</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

// Contract: 0xd9145CCE52D386f254917e481eB44e9943F39138
contract SimpleStorage {
    uint256 public favoriteNumber;

    struct People {
        uint256 favoriteNumber;
        string name;
    }

    // 这里用people数组来存储多个`struct`的实例`People`
    People[] public people;

    // Add `people` function
    function addPerson(string memory _name, uint256 _favoriteNumber) public  {
        People memory newPerson = People({favoriteNumber: _favoriteNumber, name: _name});
        // People memory newPerson = People(_favoriteNumber, _name);
        people.push(newPerson);
    }

    function store(uint256 _favoriteNumber) public {
        favoriteNumber = _favoriteNumber;
    }

    // getter function of favoriteNumber
    function retrieve() public view returns(uint256) {
        return favoriteNumber;
    }

}
"><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-comment">// Contract: 0xd9145CCE52D386f254917e481eB44e9943F39138</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">SimpleStorage</span> </span>{
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> favoriteNumber;

    <span class="hljs-keyword">struct</span> <span class="hljs-title">People</span> {
        <span class="hljs-keyword">uint256</span> favoriteNumber;
        <span class="hljs-keyword">string</span> name;
    }

    <span class="hljs-comment">// 这里用people数组来存储多个`struct`的实例`People`</span>
    People[] <span class="hljs-keyword">public</span> people;

    <span class="hljs-comment">// Add `people` function</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addPerson</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> _name, <span class="hljs-keyword">uint256</span> _favoriteNumber</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span>  </span>{
        People <span class="hljs-keyword">memory</span> newPerson <span class="hljs-operator">=</span> People({favoriteNumber: _favoriteNumber, name: _name});
        <span class="hljs-comment">// People memory newPerson = People(_favoriteNumber, _name);</span>
        people.<span class="hljs-built_in">push</span>(newPerson);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">store</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> _favoriteNumber</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        favoriteNumber <span class="hljs-operator">=</span> _favoriteNumber;
    }

    <span class="hljs-comment">// getter function of favoriteNumber</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">retrieve</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> favoriteNumber;
    }

}
</code></pre><blockquote><ul><li><p>创建了 people 数组，编制后会有一个<code>people</code>的按钮，这里可以输入<code>index</code>来找到对应的 structure；</p></li><li><p>同时，这里还写了<code>addPerson</code>函数来添加 structure 到 array 中；</p></li><li><p><code>memory</code>是一种 solidity 的存储方式，这里表示的是临时存储，函数执行完毕后数据会被清除。</p></li></ul></blockquote><h3 id="h-memory-storage-and-calldata" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Memory, Storage and Calldata</h3><p>EVM can access and store information in six places:</p><ol><li><p>Stack</p></li><li><p>Memory: 可以被修改的临时变量</p></li><li><p>Storage: 可以被修改的永久变量</p></li><li><p>Calldata: 不能被修改的临时变量</p></li><li><p>Code</p></li><li><p>Logs</p></li></ol><blockquote><p>Data location can only be specified for <code>array</code>, <code>struct</code> or <code>mapping</code> types <code>string</code> type actually is a <code>bytes</code> type</p></blockquote><h3 id="h-mappings" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Mappings</h3><p>A mapping is a data structure where a key is &quot;mapped&quot; to a single value.</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

// Contract: 0xd9145CCE52D386f254917e481eB44e9943F39138
contract SimpleStorage {
    uint256 public favoriteNumber;

    mapping(string =&gt; uint256) public nameToFavoriteNumber;

    // Add `people` function
    function addPerson(string memory _name, uint256 _favoriteNumber) public  {
        nameToFavoriteNumber[_name] = _favoriteNumber;
    }

}
"><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-comment">// Contract: 0xd9145CCE52D386f254917e481eB44e9943F39138</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">SimpleStorage</span> </span>{
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> favoriteNumber;

    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">string</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> <span class="hljs-keyword">uint256</span>) <span class="hljs-keyword">public</span> nameToFavoriteNumber;

    <span class="hljs-comment">// Add `people` function</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addPerson</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> _name, <span class="hljs-keyword">uint256</span> _favoriteNumber</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span>  </span>{
        nameToFavoriteNumber[_name] <span class="hljs-operator">=</span> _favoriteNumber;
    }

}
</code></pre><h3 id="h-import-from-other-contracts" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Import from other Contracts</h3><h1 id="h-learn-from-wtf-academic" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Learn from WTF Academic</h1><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">函数类型</h2><h3 id="h-pure" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0"><code>pure</code> 关键字</h3><p><code>pure</code> 函数不能读也不能写，如果这样 ⬇️ 的代码加上<code>pure</code>关键字就会报错，如果这个<code>add()</code>在一个 contract 中，内部定义了 <code>uint256 public number = 5</code>；但这个<code>pure</code>函数既不能读也不能写，所以他不可能读取<code>number</code>变量，更加不能再改变<code>number</code>的变量</p><pre data-type="codeBlock" text=" // 默认
    function add() external {
        number = number + 1;
    }
"><code> <span class="hljs-comment">// 默认</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
        number <span class="hljs-operator">=</span> number <span class="hljs-operator">+</span> <span class="hljs-number">1</span>;
    }
</code></pre><p>但是我们可以这样 ⬇️</p><p>可以给函数传递一个参数 <code>_number</code>，然后让他返回 <code>_number+1</code>。</p><pre data-type="codeBlock" text="    // pure: 纯纯牛马
    function addPure(uint256 _number) external pure returns(uint256 new_number){
        new_number = _number+1;
    }
"><code>    <span class="hljs-comment">// pure: 纯纯牛马</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addPure</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> _number</span>) <span class="hljs-title"><span class="hljs-keyword">external</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">uint256</span> new_number</span>)</span>{
        new_number <span class="hljs-operator">=</span> _number<span class="hljs-operator">+</span><span class="hljs-number">1</span>;
    }
</code></pre><h3 id="h-view" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0"><code>view</code>关键字</h3><p><code>view</code>那就是只能读，不能写了</p><pre data-type="codeBlock" text="    // view: 看客
    function addView() external view returns(uint256 new_number) {
        new_number = number + 1;
    }
"><code>    <span class="hljs-comment">// view: 看客</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addView</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">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> new_number</span>) </span>{
        new_number <span class="hljs-operator">=</span> number <span class="hljs-operator">+</span> <span class="hljs-number">1</span>;
    }
</code></pre><h3 id="h-internal-external" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0"><code>internal</code> 和 <code>external</code></h3><p><code>internal</code>函数（内部函数）是没有办法被直接调用的，意思是部署了一个合约，里面有个 internal 函数，但是我们在部署后在 remix 是找不到这个函数的 button 的</p><h3 id="h-payable" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">payable</h3><pre data-type="codeBlock" text="   // payable: 递钱，能给合约支付eth的函数
    function minusPayable() external payable returns(uint256 balance) {
        minus();
        balance = address(this).balance;
    }
"><code>   <span class="hljs-comment">// payable: 递钱，能给合约支付eth的函数</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">minusPayable</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 class="hljs-title"><span class="hljs-keyword">returns</span></span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> balance</span>) </span>{
        minus();
        balance <span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>).<span class="hljs-built_in">balance</span>;
    }
</code></pre><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">函数输出</h2><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">结构式赋值</h3><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

contract Test {

    // It returns the variables automatically, we don&apos;t have to add `return` in function
    function returnNamed() public pure returns (uint256 _number, bool _bool, uint256[3] memory _array) {
        _number = 2;
        _bool = false;
        _array = [uint256(3), 2, 1];
    }

    // Destructuring assignments
    function readReturn() public pure {
        uint256 _number;
        bool _bool;
        uint256[3] memory _array;
        (_number, _bool, _array) = returnNamed();
    }
}
"><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">Test</span> </span>{

    <span class="hljs-comment">// It returns the variables automatically, we don't have to add `return` in function</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">returnNamed</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">pure</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span> _number, <span class="hljs-keyword">bool</span> _bool, <span class="hljs-keyword">uint256</span>[<span class="hljs-number">3</span>] <span class="hljs-keyword">memory</span> _array</span>) </span>{
        _number <span class="hljs-operator">=</span> <span class="hljs-number">2</span>;
        _bool <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;
        _array <span class="hljs-operator">=</span> [<span class="hljs-keyword">uint256</span>(<span class="hljs-number">3</span>), <span class="hljs-number">2</span>, <span class="hljs-number">1</span>];
    }

    <span class="hljs-comment">// Destructuring assignments</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readReturn</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">pure</span></span> </span>{
        <span class="hljs-keyword">uint256</span> _number;
        <span class="hljs-keyword">bool</span> _bool;
        <span class="hljs-keyword">uint256</span>[<span class="hljs-number">3</span>] <span class="hljs-keyword">memory</span> _array;
        (_number, _bool, _array) <span class="hljs-operator">=</span> returnNamed();
    }
}
</code></pre><h2 id="h-storagememorycalldata" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">变量数据存储和作用域 storage/memory/calldata</h2><h3 id="h-solidity" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Solidity 中的引用类型</h3><p>引用类型(Reference Type)：包括数组（array），结构体（struct）和映射（mapping），这类变量占空间大，赋值时候直接传递地址（类似指针）。由于这类变量比较复杂，占用存储空间大，我们在使用时必须要声明数据存储的位置。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">数据位置</h3><p>solidity 数据存储位置有三类：storage，memory 和 calldata。不同存储位置的 gas 成本不同。storage 类型的数据存在链上，类似计算机的硬盘，消耗 gas 多；memory 和 calldata 类型的临时存在内存里，消耗 gas 少。大致用法：</p><ol><li><p><code>storage</code>：合约里的状态变量默认都是<code>storage</code>，存储在链上。</p></li><li><p><code>memory</code>：函数里的参数和临时变量一般用<code>memory</code>，存储在内存中，不上链。</p></li><li><p><code>calldata</code>：和<code>memory</code>类似，存储在内存中，不上链。与<code>memory</code>的不同在于<code>calldata</code>变量不能修改(<code>immutable</code>)，一般用于函数的参数。</p></li></ol><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">数值位置和赋值规则</h3><ol><li><p>在不同存储类型相互赋值时候，有时会产生独立的副本（修改新变量不会影响原变量），有时会产生引用（修改新变量会影响原变量）。</p></li></ol><p>⬇️ 此时的 <code>x[0]</code> 已经变成了 100</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

contract Test {
    uint[] x = [1, 2, 3];

    function fStorage() public {
        uint[] storage xStorage = x;
        xStorage[0] = 100;
    }
}
"><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">Test</span> </span>{
    <span class="hljs-keyword">uint</span>[] x <span class="hljs-operator">=</span> [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fStorage</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-keyword">uint</span>[] <span class="hljs-keyword">storage</span> xStorage <span class="hljs-operator">=</span> x;
        xStorage[<span class="hljs-number">0</span>] <span class="hljs-operator">=</span> <span class="hljs-number">100</span>;
    }
}
</code></pre><ol><li><p><code>storage</code> 赋值给 <code>memory</code>，会创建独立的复本，修改其中一个不会影响另一个；反之亦然。例子：</p></li></ol><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

contract Test {
    uint[] x = [1, 2, 3];

    function fMemory() public view{
        //声明一个Memory的变量xMemory，复制x。修改xMemory不会影响x
        uint[] memory xMemory = x;
        xMemory[0] = 100;
        xMemory[1] = 200;
        uint[] memory xMemory2 = x;
        xMemory2[0] = 300;
    }
}
"><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">Test</span> </span>{
    <span class="hljs-keyword">uint</span>[] x <span class="hljs-operator">=</span> [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fMemory</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>{
        <span class="hljs-comment">//声明一个Memory的变量xMemory，复制x。修改xMemory不会影响x</span>
        <span class="hljs-keyword">uint</span>[] <span class="hljs-keyword">memory</span> xMemory <span class="hljs-operator">=</span> x;
        xMemory[<span class="hljs-number">0</span>] <span class="hljs-operator">=</span> <span class="hljs-number">100</span>;
        xMemory[<span class="hljs-number">1</span>] <span class="hljs-operator">=</span> <span class="hljs-number">200</span>;
        <span class="hljs-keyword">uint</span>[] <span class="hljs-keyword">memory</span> xMemory2 <span class="hljs-operator">=</span> x;
        xMemory2[<span class="hljs-number">0</span>] <span class="hljs-operator">=</span> <span class="hljs-number">300</span>;
    }
}
</code></pre><ol><li><p><code>memory</code> 赋值给 <code>memory</code>，会创建引用，改变新变量会影响原变量。</p></li><li><p>其他情况，变量赋值给 <code>storage</code>，会创建独立的复本，修改其中一个不会影响另一个。</p></li></ol><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">变量的作用域</h3><p>Solidity 中变量按作用域划分有三种，分别是状态变量（state variable），局部变量（local variable）和全局变量(global variable)</p><p>状态变量是存储在链上的变量，所有合约内函数都可以访问，gas 耗费是最高的。</p><h2 id="h-array-struct" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">引用类型, array, struct</h2><p>在可变长度数组中，<code>bytes</code>比较特殊，它是数组，但是不用加<code>[]</code></p><pre data-type="codeBlock" text="    // 可变长度 Array
    uint[] array4;
    bytes1[] array5;
    address[] array6;
    bytes array7;
"><code>    // 可变长度 Array
    uint<span class="hljs-section">[]</span> array4<span class="hljs-comment">;</span>
    bytes1<span class="hljs-section">[]</span> array5<span class="hljs-comment">;</span>
    address<span class="hljs-section">[]</span> array6<span class="hljs-comment">;</span>
    bytes array7<span class="hljs-comment">;</span>
</code></pre><h2 id="h-mapping" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">映射类型 Mapping</h2><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

contract Test {
    // Learning Mapping
    mapping (uint =&gt; address) public idToAddress;

    function writeMap(uint _key, address _Value) public {
        idToAddress[_key] = _Value;
    }
}
"><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">Test</span> </span>{
    <span class="hljs-comment">// Learning Mapping</span>
    <span class="hljs-keyword">mapping</span> (<span class="hljs-keyword">uint</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> <span class="hljs-keyword">address</span>) <span class="hljs-keyword">public</span> idToAddress;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">writeMap</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span> _key, <span class="hljs-keyword">address</span> _Value</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        idToAddress[_key] <span class="hljs-operator">=</span> _Value;
    }
}
</code></pre><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">变量初始值</h2><h3 id="h-delete" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0"><code>delete</code> 操作符</h3><p><code>delete a</code> 会让变量 <code>a</code> 的值变为初始值。</p><pre data-type="codeBlock" text="// delete操作符
bool public _bool2 = true;
function d() external {
    delete _bool2; // delete 会让_bool2变为默认值，false
}
"><code><span class="hljs-comment">// delete操作符</span>
<span class="hljs-keyword">bool</span> <span class="hljs-keyword">public</span> _bool2 <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">d</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
    <span class="hljs-keyword">delete</span> _bool2; <span class="hljs-comment">// delete 会让_bool2变为默认值，false</span>
}
</code></pre><h2 id="h-constant-immutable" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">常数 constant 和 immutable</h2><p>状态变量声明<code>constant</code>（常量）或 <code>immutable</code>（不变量）后，不能在合约后更改数值；并且还可以节省 gas。另外，只有数值变量可以声明<code>constant</code>和<code>immutable</code>；<code>string</code>和<code>bytes</code>可以声明为<code>constant</code>，但不能为<code>immutable</code>。</p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">构造函数和修饰器</h2><p>修饰器（modifier）是 solidity 特有的语法，类似于面向对象编程中的 decorator，声明函数拥有的特性，并减少代码冗余。它就像钢铁侠的智能盔甲，穿上它的函数会带有某些特定的行为。modifier 的主要使用场景是运行函数前的检查，例如地址，变量，余额等。</p><p>这里做一个<code>onlyOwner</code>的 modifier：</p><pre data-type="codeBlock" text="   // 定义modifier
   modifier onlyOwner {
      require(msg.sender == owner); // 检查调用者是否为owner地址
      _; // 如果是的话，继续运行函数主体；否则报错并revert交易
   }
"><code>   <span class="hljs-comment">// 定义modifier</span>
   <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">onlyOwner</span> </span>{
      <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> owner); <span class="hljs-comment">// 检查调用者是否为owner地址</span>
      <span class="hljs-keyword">_</span>; <span class="hljs-comment">// 如果是的话，继续运行函数主体；否则报错并revert交易</span>
   }
</code></pre><p>带有<code>onlyOwner</code>修饰符的函数只能被 owner 地址调用，比如下面这个例子：</p><pre data-type="codeBlock" text="   function changeOwner(address _newOwner) external onlyOwner{
      owner = _newOwner; // 只有owner地址运行这个函数，并改变owner
   }
"><code>   <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">changeOwner</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _newOwner</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">onlyOwner</span></span>{
      owner <span class="hljs-operator">=</span> _newOwner; <span class="hljs-comment">// 只有owner地址运行这个函数，并改变owner</span>
   }
</code></pre><p>我们定义了一个 changeOwner 函数，运行他可以改变合约的 owner，但是由于 onlyOwner 修饰符的存在，只有原先的 owner 可以调用，别人调用就会报错。这也是最常用的控制智能合约权限的方法。</p><h2 id="h-event" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">事件 Event</h2><p>Solidity 中的事件（event）是 EVM 上日志的抽象，它具有两个特点：</p><ul><li><p>响应：应用程序（ethers.js）可以通过 RPC 接口订阅和监听这些事件，并在前端做响应。</p></li><li><p>经济：事件是 EVM 上比较经济的存储数据的方式，每个大概消耗 2,000 gas；相比之下，链上存储一个新变量至少需要 20,000 gas。</p></li></ul><p>事件的 demo</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

contract Event {
    // 记录每个地址的持币数量
    mapping (address =&gt; uint256) public _balances;

    // 定义event，记录transfer交易的转账地址，接收地址和转账数量
    event Transfer(address indexed from, address indexed to, uint256 value);

    // 执行转账逻辑
    function _transfer (
        address from,
        address to,
        uint256 amount
    ) external {
        // 初始化一些代币
        // 转账地址的代币初始化为1000
        _balances[from] = 1000;

        // 1000 - 转出去的代币
        _balances[from] -= amount;
        _balances[to] += amount;

        // 释放事件
        emit Transfer(from, to, amount);
    }
}
"><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">Event</span> </span>{
    <span class="hljs-comment">// 记录每个地址的持币数量</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">uint256</span>) <span class="hljs-keyword">public</span> _balances;

    <span class="hljs-comment">// 定义event，记录transfer交易的转账地址，接收地址和转账数量</span>
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">Transfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">indexed</span> <span class="hljs-keyword">from</span>, <span class="hljs-keyword">address</span> <span class="hljs-keyword">indexed</span> to, <span class="hljs-keyword">uint256</span> value</span>)</span>;

    <span class="hljs-comment">// 执行转账逻辑</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_transfer</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> amount
    </span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
        <span class="hljs-comment">// 初始化一些代币</span>
        <span class="hljs-comment">// 转账地址的代币初始化为1000</span>
        _balances[<span class="hljs-keyword">from</span>] <span class="hljs-operator">=</span> <span class="hljs-number">1000</span>;

        <span class="hljs-comment">// 1000 - 转出去的代币</span>
        _balances[<span class="hljs-keyword">from</span>] <span class="hljs-operator">-</span><span class="hljs-operator">=</span> amount;
        _balances[to] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount;

        <span class="hljs-comment">// 释放事件</span>
        <span class="hljs-keyword">emit</span> Transfer(<span class="hljs-keyword">from</span>, to, amount);
    }
}
</code></pre><p>详情的需要看 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.wtf.academy/solidity-start/Event/">wtf</a> 的教程</p><h2 id="h-inheritance" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">继承 inheritance</h2><p>继承是面向对象编程很重要的组成部分，可以显著减少重复代码。如果把合约看作是对象的话，solidity 也是面向对象的编程，也支持继承。</p><ul><li><p><code>virtual</code>：父合约中的函数，如果希望子合约重写，需要加上 <code>virtual</code> 关键字。</p></li><li><p><code>override</code>：子合约重写了父合约中的函数，需要加上 <code>override</code> 关键字。</p></li></ul><p>demo is here</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

contract Yeye {
    event Log(string msg);

    function hip() public virtual {
        emit Log(&quot;Yeye&quot;);
    }

    function pop() public virtual {
        emit Log(&quot;Yeye&quot;);
    }

    function yeye() public virtual {
        emit Log(&quot;Yeye&quot;);
    }
}

contract Baba is Yeye {
    function hip() public override {
        emit Log(&quot;Baba&quot;);
    }

    function pop() public override {
        emit Log(&quot;Baba&quot;);
    }

    function baba() public virtual  {
        emit Log(&quot;Baba&quot;);
    }
}
"><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">Yeye</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">Log</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-built_in">msg</span></span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hip</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">virtual</span></span> </span>{
        <span class="hljs-keyword">emit</span> Log(<span class="hljs-string">"Yeye"</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">pop</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">virtual</span></span> </span>{
        <span class="hljs-keyword">emit</span> Log(<span class="hljs-string">"Yeye"</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">yeye</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">virtual</span></span> </span>{
        <span class="hljs-keyword">emit</span> Log(<span class="hljs-string">"Yeye"</span>);
    }
}

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Baba</span> <span class="hljs-keyword">is</span> <span class="hljs-title">Yeye</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hip</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">override</span></span> </span>{
        <span class="hljs-keyword">emit</span> Log(<span class="hljs-string">"Baba"</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">pop</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">override</span></span> </span>{
        <span class="hljs-keyword">emit</span> Log(<span class="hljs-string">"Baba"</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">baba</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">virtual</span></span>  </span>{
        <span class="hljs-keyword">emit</span> Log(<span class="hljs-string">"Baba"</span>);
    }
}
</code></pre><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">多重继承</h3><p><code>solidity</code> 的合约可以继承多个合约。规则：</p><p>继承时要按辈分最高到最低的顺序排。比如我们写一个 <code>Erzi</code> 合约，继承 Yeye 合约和 Baba 合约，那么就要写成 <code>contract Erzi is Yeye, Baba</code>，而不能写成 <code>contract Erzi is Baba, Yeye</code>，不然就会报错。</p><p>如果某一个函数在多个继承的合约里都存在，比如例子中的 <code>hip()</code>和 <code>pop()</code>，在子合约里必须重写，不然会报错。</p><p>重写在多个父合约中都重名的函数时，<code>override</code> 关键字后面要加上所有父合约名字，例如 <code>override(Yeye, Baba)</code>。</p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">抽象合约</h2><p>如果一个智能合约里至少有一个未实现的函数，即某个函数缺少主体{}中的内容，则必须将该合约标为 abstract，不然编译会报错；另外，未实现的函数需要加 virtual，以便子合约重写。</p><pre data-type="codeBlock" text="abstract contract InsertionSort{
    function insertionSort(uint[] memory a) public pure virtual returns(uint[] memory);
}
"><code><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">InsertionSort</span></span>{
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">insertionSort</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span>[] <span class="hljs-keyword">memory</span> a</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">virtual</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span>(<span class="hljs-params"><span class="hljs-keyword">uint</span>[] <span class="hljs-keyword">memory</span></span>)</span>;
}
</code></pre><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">接口</h3><p>接口类似于抽象合约，但它不实现任何功能。接口的规则：</p><ol><li><p>不能包含状态变量</p></li><li><p>不能包含构造函数</p></li><li><p>不能继承除接口外的其他合约</p></li><li><p>所有函数都必须是 external 且不能有函数体</p></li><li><p>继承接口的合约必须实现接口定义的所有功能</p></li></ol><p>虽然接口不实现任何功能，但它非常重要。接口是智能合约的骨架，定义了合约的功能以及如何触发它们：如果智能合约实现了某种接口（比如 ERC20 或 ERC721），其他 Dapps 和智能合约就知道如何与它交互。因为接口提供了两个重要的信息：</p><ol><li><p>合约里每个函数的 bytes4 选择器以及函数签名函数名(每个参数类型）</p></li><li><p>接口 id（更多信息见 EIP165）</p></li></ol><p>另外，接口与合约 ABI（Application Binary Interface）等价，可以相互转换：编译接口可以得到合约的 ABI，利用 abi-to-sol 工具也可以将 ABI json 文件转换为接口 sol 文件。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">什么时候使用接口？</h3><p>如果我们知道一个合约实现了 IERC721 接口，我们不需要知道它具体代码实现，就可以与它交互。</p><p>无聊猿 BAYC 属于 ERC721 代币，实现了 IERC721 接口的功能。我们不需要知道它的源代码，只需知道它的合约地址，用 IERC721 接口就可以与它交互，比如用 balanceOf()来查询某个地址的 BAYC 余额，用 safeTransferFrom()来转账 BAYC。</p><pre data-type="codeBlock" text="contract interactBAYC {
    // 利用BAYC地址创建接口合约变量（ETH主网）
    IERC721 BAYC = IERC721(0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D);

    // 通过接口调用BAYC的balanceOf()查询持仓量
    function balanceOfBAYC(address owner) external view returns (uint256 balance){
        return BAYC.balanceOf(owner);
    }

    // 通过接口调用BAYC的safeTransferFrom()安全转账
    function safeTransferFromBAYC(address from, address to, uint256 tokenId) external{
        BAYC.safeTransferFrom(from, to, tokenId);
    }
}
"><code><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">interactBAYC</span> </span>{
    <span class="hljs-comment">// 利用BAYC地址创建接口合约变量（ETH主网）</span>
    IERC721 BAYC <span class="hljs-operator">=</span> IERC721(<span class="hljs-number">0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D</span>);

    <span class="hljs-comment">// 通过接口调用BAYC的balanceOf()查询持仓量</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">balanceOfBAYC</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> owner</span>) <span class="hljs-title"><span class="hljs-keyword">external</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> balance</span>)</span>{
        <span class="hljs-keyword">return</span> BAYC.balanceOf(owner);
    }

    <span class="hljs-comment">// 通过接口调用BAYC的safeTransferFrom()安全转账</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">safeTransferFromBAYC</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>) <span class="hljs-title"><span class="hljs-keyword">external</span></span></span>{
        BAYC.safeTransferFrom(<span class="hljs-keyword">from</span>, to, tokenId);
    }
}
</code></pre>]]></content:encoded>
            <author>logic-6@newsletter.paragraph.com (Logic)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/7178216758f7d7720bdb32cd115f2073cbfec6a5ae17cd74561c1ea9ecfe9de0.png" length="0" type="image/png"/>
        </item>
    </channel>
</rss>