<?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>Adachi Tomoki</title>
        <link>https://paragraph.com/@adachi-tomoki</link>
        <description>AndLaw inc.  CTO</description>
        <lastBuildDate>Tue, 26 May 2026 13:16:52 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>Adachi Tomoki</title>
            <url>https://storage.googleapis.com/papyrus_images/f269a58446b7fe21edb946704b8c8f3529bca23bae98af485a79c82ec61f2e96.jpg</url>
            <link>https://paragraph.com/@adachi-tomoki</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[ブロックチェーンは不変ではありません]]></title>
            <link>https://paragraph.com/@adachi-tomoki/BRNqOk9HwBUQUJt2h1AB</link>
            <guid>BRNqOk9HwBUQUJt2h1AB</guid>
            <pubDate>Tue, 22 Mar 2022 13:04:46 GMT</pubDate>
            <description><![CDATA[「ブロックチェーンは耐改竄性が高く、一度ブロックに取り込まれたら元に戻せない」的なことを様々な記事で書かれています。 ブロックチェーン初学者である私はそれを鵜呑みにした結果ふと疑問が浮かびました。「スマートコントラクトのstorageってブロックチェーンに永久に刻まれるのになんで更新できるの？？」https://mirror.xyz/0x221E25Ad7373Fbaf33C7078B8666816586222A09/0YK76_OJ5bkyH-RiFsiAiwFYD0yLxllKwIUPMocMaoo storageについてこの記事で説明していますが、storageはブロックチェーン上に永久に保存される変数です。 ブロックチェーンは改竄できないという認識だったのでブロックチェーン上にあるstorageを更新できることに違和感を覚えていました。 しかし、この違和感の原因は「ブロックチェーンは不変である」という先入観にありました。 確かにブロックチェーンは不変ではありますが、その対象はブロックやトランザクションそれ自体です。 Bitcoinであれば取引金額を変えることはできません。...]]></description>
            <content:encoded><![CDATA[<h2 id="h-yuan" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">「ブロックチェーンは耐改竄性が高く、一度ブロックに取り込まれたら元に戻せない」</h2><p>的なことを様々な記事で書かれています。</p><p>ブロックチェーン初学者である私はそれを鵜呑みにした結果ふと疑問が浮かびました。</p><h2 id="h-storage" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">「スマートコントラクトのstorageってブロックチェーンに永久に刻まれるのになんで更新できるの？？」</h2><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/0x221E25Ad7373Fbaf33C7078B8666816586222A09/0YK76_OJ5bkyH-RiFsiAiwFYD0yLxllKwIUPMocMaoo">https://mirror.xyz/0x221E25Ad7373Fbaf33C7078B8666816586222A09/0YK76_OJ5bkyH-RiFsiAiwFYD0yLxllKwIUPMocMaoo</a></p><p>storageについてこの記事で説明していますが、storageはブロックチェーン上に永久に保存される変数です。</p><p>ブロックチェーンは改竄できないという認識だったのでブロックチェーン上にあるstorageを更新できることに違和感を覚えていました。</p><p>しかし、この違和感の原因は「<strong>ブロックチェーンは不変である</strong>」という先入観にありました。</p><p>確かにブロックチェーンは不変ではありますが、その対象は<strong>ブロックやトランザクションそれ自体</strong>です。</p><p>Bitcoinであれば取引金額を変えることはできません。これはトランザクションのデータになっているためです。</p><p>これがEthereumのスマートコントラクトになった場合はどうでしょうか？</p><p>よく言われているのは「コントラクトをデプロイすると永久に残り続けるので慎重に上げるべき」というような話です。</p><p>これは間違ってはいません。なぜならコントラクトの「<strong>コード</strong>」はトランザクションのデータになるので不変です。</p><p>しかし、スマートコントラクト内のstorageやmemoryの変数はトランザクションのデータというよりもすマートコントラクト内のデータなので変数として扱うことが可能です。</p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">最後に</h2><p>ここまで述べたようにブロックチェーンには不変である部分と不変ではない部分があることがわかりました。</p><p>この誤解はそもそもブロックチェーンの定義を曖昧にしていたことやそもそも明確に説明してある情報が少ないことも起因しているとも感じています。</p><p>これから自分でもどんどん発信していけるように頑張ります！</p><p>もし認識が間違っている箇所があれば教えていただきたいです🙏</p><p>【参考記事】</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://jaredstauffer.medium.com/is-the-ethereum-blockchain-really-immutable-71ff3753ace7">https://jaredstauffer.medium.com/is-the-ethereum-blockchain-really-immutable-71ff3753ace7</a></p>]]></content:encoded>
            <author>adachi-tomoki@newsletter.paragraph.com (Adachi Tomoki)</author>
        </item>
        <item>
            <title><![CDATA[Rollupのお勉強]]></title>
            <link>https://paragraph.com/@adachi-tomoki/rollup</link>
            <guid>9RL0D6BkIT2vRgKwDqX1</guid>
            <pubDate>Tue, 22 Mar 2022 01:15:53 GMT</pubDate>
            <description><![CDATA[Rollupとは何か？Ethereumのスケーリング技術の一つ。いわゆるL2ソリューション。 という説明だと理解しにくいので前提から説明します。Rollup誕生の経緯Rollupの内容の前になぜRollupが誕生したのかを見る必要があります。 ブロックチェーンのトリレンマ(分散性、セキュリティ、スケーラビリティ)の中でEthereumにおいてはスケーラビリティ(処理能力)が問題になる。 そこでベースのブロックチェーン(レイヤー1・この場合Ethereum)ではなく、ベースのものではないブロックチェーン(レイヤー2)で処理することでスケーラビリティ問題を解決しようとした。 そのレイヤー2(以下、L2)は大きく4つあります。zk-Rollup、Validium、Optimistic Rollup、Plasmaの4つです。 その中の2つのソリューションにRollupが使用されています。RollUpの特徴Rollupは、Plasmaに似たL2スケーリングソリューション。 Plasma Ethereumのブロックチェーンを親ブロックチェーン(ルートブロックチェーン)として、それぞれのプラズ...]]></description>
            <content:encoded><![CDATA[<h2 id="h-rollup" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Rollupとは何か？</h2><p>Ethereumのスケーリング技術の一つ。いわゆるL2ソリューション。</p><p>という説明だと理解しにくいので前提から説明します。</p><h3 id="h-rollup" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Rollup誕生の経緯</h3><p>Rollupの内容の前になぜRollupが誕生したのかを見る必要があります。</p><p>ブロックチェーンのトリレンマ(分散性、セキュリティ、スケーラビリティ)の中でEthereumにおいてはスケーラビリティ(処理能力)が問題になる。</p><p>そこでベースのブロックチェーン(レイヤー1・この場合Ethereum)ではなく、ベースのものではないブロックチェーン(レイヤー2)で処理することでスケーラビリティ問題を解決しようとした。</p><p>そのレイヤー2(以下、L2)は大きく4つあります。<strong>zk-Rollup、Validium、Optimistic Rollup、Plasma</strong>の4つです。</p><p>その中の2つのソリューションにRollupが使用されています。</p><h2 id="h-rollup" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">RollUpの特徴</h2><p>Rollupは、Plasmaに似たL2スケーリングソリューション。</p><p><strong>Plasma</strong></p><p>Ethereumのブロックチェーンを親ブロックチェーン(ルートブロックチェーン)として、それぞれのプラズマブロックチェーンをツリー状に接続していく。</p><p>トランザクションはPlasmaブロックチェーン上で処理され、その結果が接続している親Plasmaブロックチェーンに伝わっていく。最終的にEthereumブロックチェーンにトランザクションが記録される。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f7c4571e9e740eb4dfba9d09f716960b79b70cf177edfad23c46ab092986a5ba.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>しかし、Plasmaではスマートコントラクトの複雑性やルートチェーンに51％攻撃を受けるとプラズマチェーン全体に影響を受けてしまうなど、可用性の部分で問題になってしまう。</p><p>一方でRollupはデータ処理の一部をL2で行うが、L1であるEthereumの方にも処理を部分的に残していることによってセキュリティを維持した状態でスケーラビリティを向上させることができます。</p><h3 id="h-rollup" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Rollupの基本的な処理</h3><ol><li><p>EVMを通じてトランザクションを実行</p></li><li><p>データの抽出</p></li><li><p>データの圧縮</p></li><li><p>Ethereumに書き込む</p></li></ol><p>4でEthereumに書き込む際には何千ものトランザクションを1つのRollupブロックにまとめて書き込むようになっている。</p><p>しかし、4で書き込む際にデータの有効性や悪意のあるデータかどうかを判断する必要があります。その判断を行う手法が先ほど述べた<strong>zk-Rollup、Optimistic Rollup</strong>になります。</p><h3 id="h-optimistic-rollup" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Optimistic Rollup</h3><p>zk-Rollupとは異なり、毎回Rollupコントラクトで検証しない。代わりに不正を告発するための紛争期間（Dispute period）を1〜7日程度設け、その期間内で無効なトランザクションを指摘したオペレーターやユーザーは該当ブロックを元に戻す、悪意のあるトランザクションを生成した当事者にペナルティを与える。</p><p><strong>課題</strong></p><p>L1のファイナリティに時間がかかるため、L1からの引き出しに時間がかかる。</p><h3 id="h-zk-rollup" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">zk-Rollup</h3><p>全ての状態遷移に関して**ゼロ知識証明(SNARK)**を生成する必要がある。メインチェーン(Ethereum)のRollupコントラクトで検証を行う。</p><p>ゼロ知識証明とは、秘密を知っていることを秘密を教えることなく、第三者に秘密を知っていると証明できる仕組みのことで、私も具体的な仕組みはあまり理解していません、、、</p><p><strong>zk-Rollupの流れ</strong></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/3a6000738251e1b9e04af97d4c497159299bbe7f27ffdfb28a270fbbd900e4c8.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><ol><li><p>ユーザーがトランザクションに署名してオペレーターに渡す</p></li><li><p>オペレーターは複数のトランザクションを受け取る</p></li><li><p>オペレーターは回路にトランザクションやMerkle Treeの情報をinputとして計算する(Prove)</p></li><li><p>検証者(Ethereumのコントラクト)にProof(3の生成物)を渡して検証する</p></li><li><p>新しいMerkle RootがEthereumコントラクトに刻まれる→残高が反映され、状態遷移が完了する</p></li></ol><p><strong>課題</strong></p><p>証明生成の計算に時間とコストがかかる。</p>]]></content:encoded>
            <author>adachi-tomoki@newsletter.paragraph.com (Adachi Tomoki)</author>
        </item>
        <item>
            <title><![CDATA[PoWとPoSについて]]></title>
            <link>https://paragraph.com/@adachi-tomoki/pow-pos</link>
            <guid>xaUM2GKFH8ikAqbOcgag</guid>
            <pubDate>Sun, 20 Mar 2022 13:31:02 GMT</pubDate>
            <description><![CDATA[はじめにhttps://beincrypto.com/ethereum-merge-successfully-kiln-testnet/ ついにEthereumのMergeがテストネットで成功しました🎉 それに伴ってコンセンサスアルゴリズムがPoWからPoSに変更になりました。そこで両者の違いを自分なりにまとめてみました。PoWProof of Workの略。Bitcoinで使用されていることで有名。 ブロックチェーンの仕組上、取引がなされた際にその取引データは他の人に承認されてブロックに取り込まれる。 その際にブロックの承認を行うために必要な計算(Nonceの計算)があり、それを早く解き切るとマイナーに選ばれ、報酬を受け取ることができる。 しかし、電力消費量が非常に大きくため、環境に負荷がかかる・個人で行うには設備等で莫大な費用がかかる。PoSProof of Stakeの略。 トークンを一定数以上ステーキング持っているユーザーからランダムに選択し(バリデーターの選出)、そのバリデーターがブロックを承認することによって報酬を得ることができる。 特徴トークンを一定数有していると...]]></description>
            <content:encoded><![CDATA[<h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">はじめに</h2><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://beincrypto.com/ethereum-merge-successfully-kiln-testnet/">https://beincrypto.com/ethereum-merge-successfully-kiln-testnet/</a></p><p>ついにEthereumのMergeがテストネットで成功しました🎉</p><p>それに伴ってコンセンサスアルゴリズムがPoWからPoSに変更になりました。そこで両者の違いを自分なりにまとめてみました。</p><h2 id="h-pow" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">PoW</h2><p>Proof of Workの略。Bitcoinで使用されていることで有名。</p><p>ブロックチェーンの仕組上、取引がなされた際にその取引データは他の人に承認されてブロックに取り込まれる。</p><p>その際にブロックの承認を行うために必要な計算(Nonceの計算)があり、それを早く解き切るとマイナーに選ばれ、報酬を受け取ることができる。</p><p>しかし、電力消費量が非常に大きくため、環境に負荷がかかる・個人で行うには設備等で莫大な費用がかかる。</p><h2 id="h-pos" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">PoS</h2><p>Proof of Stakeの略。</p><p>トークンを一定数以上ステーキング持っているユーザーからランダムに選択し(バリデーターの選出)、そのバリデーターがブロックを承認することによって報酬を得ることができる。</p><p><strong>特徴</strong></p><ul><li><p>トークンを一定数有していると一定の信用があるという考え方</p></li><li><p>PoWのように高性能のハードウェアを必要としない</p></li><li><p>個人での参入障壁が下がる</p></li><li><p>Layer2ソリューションのRollup等と組み合わせてスケーラビリティの問題に対処できる</p></li></ul><h2 id="h-ethereumpos" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">EthereumにおけるPoSの動き</h2><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">バリデーターのやること</h3><p>選ばれた場合→ブロックの作成</p><p>選ばれなかった場合→ブロックの検証を行う</p><p>ブロックの検証を<strong>attesting</strong>といい、「このブロックは良さそうだ」というのを証明しているイメージ。</p><p>もし、悪意のブロックに対してattestingした場合にはステークを失う。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">シャードチェーン</h3><p>シャーディングによってネットワークの混雑を減らし、シャードチェーンを作成することによって、1 秒あたりのトランザクションを増加させる。</p><p>64のシャードチェーンが存在し、それぞれがネットワークの状態を共有することになっている。</p><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">シャーディング</h4><p>データベースを水平に分割して負荷分散を行うプロセス。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">ビーコンチェーン</h3><p>シャードチェーンの調整を行うチェーン。</p><p>シャードから状態情報を受け取り、他のシャードがそれを利用できるようにすることで、ネットワークの同期を保つことができる。</p><p>また、ビーコンチェーンは、バリデータのステーク入金登録から報酬・ペナルティの発行も管理する。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">バリデーションの働き</h3><p>シャードでトランザクションを送信すると、バリデータがそのトランザクションをシャーブロックに追加する役割を担う。</p><p>バリデータはビーコンチェーンのアルゴリズムによって選ばれ、新しいブロックを提案できるようにする。</p><h4 id="h-attestation" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Attestation</h4><p>上記とか異なりバリデータが新しいシャードブロックを提案するのに選ばれなかった場合、他のバリデータが行ったブロックの提案に対して認証を行う。</p><p>ビーコンチェーンには取引自体ではなく、この認証に対して行われている。</p><p>各シャードブロックには少なくとも128人のバリデータが必要で、これを 「<strong>committee</strong>」と呼ぶ。</p><p>committeeにはシャードブロックを提案し、検証するための時間枠があり、それを「<strong>slot</strong>」と呼ぶ。</p><p>1つのslotには1つの有効なブロックを作成する。そのslotが32個まとまったものを「<strong>epoch</strong>」といい、1つのepochの検証が終了したらcommitteeは解散する。</p><p>その後、再び異なるランダムな参加者でcommiteeが再結成される。これによって悪質なcommiteeからシャードを保護することができる。</p><h4 id="h-crosslink" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Crosslink</h4><p>新しいシャードブロックの提案に十分な認証が得られると、ビーコンチェーンにブロックと取引が含まれることを確認する「<strong>Crosslink</strong>」が作成される。</p><p>このCrosslinkでビーコンチェーンとシャードチェーンがつながり、同期を行っている。</p><p><strong>Crosslink</strong>ができると、そのブロックを提案したバリデータは報酬を得ることができる。</p><p><strong>Finality</strong></p><p>分散型ネットワークでは、ある取引が変更不可能なブロックの一部となっている場合、その取引は「<strong>Finality</strong>」を持つ。</p><p>PoSでこれを実現するために、<strong>Finality</strong>のプロトコルであるCasperが使用される。</p><p>これはあるチェックポイントでのブロックの状態についてバリデーターに同意させるもの。</p><p>バリデータの2/3が同意すれば、そのブロックはファイナライズされる。</p><p>もしバリデータは、ファイナライズされたブロックを51％攻撃によって元に戻そうとすると、すべてのステークを失うことになる。</p>]]></content:encoded>
            <author>adachi-tomoki@newsletter.paragraph.com (Adachi Tomoki)</author>
        </item>
        <item>
            <title><![CDATA[Solidityのmemoryとstorageについての備忘録]]></title>
            <link>https://paragraph.com/@adachi-tomoki/solidity-memory-storage</link>
            <guid>gODODVmOLLYeQmldhEbr</guid>
            <pubDate>Thu, 17 Mar 2022 11:40:08 GMT</pubDate>
            <description><![CDATA[mirror初投稿です！Web3に関心があるのでこれからコーディング等のWeb3に関する知識のアウトプットに利用していこうと思います！ 今回はdAppsを練習で実装している際に「storage」と「memory」の扱い方に関して少し戸惑ったので備忘録として残しておきます。storagestorageはブロックチェーン上に永久に保存される変数。 可変長配列を使用する場合、storageで宣言する必要がある。 関数外で宣言する場合、デフォルトでstorageになっている。 ブロックチェーン上に保存するので、ガス代が高くなる。memoryコントラクトを実行する場合にのみ保持される変数。 →ブロックチェーン自体に保存されるわけではないため、storageと異なりガス代もかからない。 関数内で宣言する場合にはデフォルトでmemoryになっている。実装の際に苦労した点可変長配列を返そうと考えたが、結構苦戦しました。 以下がうまくいかなかったコードです。function _transferableNFTs(uint256 stage) private view returns (NFTItem...]]></description>
            <content:encoded><![CDATA[<h3 id="h-mirror" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">mirror初投稿です！</h3><p>Web3に関心があるのでこれからコーディング等のWeb3に関する知識のアウトプットに利用していこうと思います！</p><p>今回はdAppsを練習で実装している際に「storage」と「memory」の扱い方に関して少し戸惑ったので備忘録として残しておきます。</p><h2 id="h-storage" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">storage</h2><p>storageはブロックチェーン上に永久に保存される変数。</p><p><strong>可変長配列を使用する場合</strong>、storageで宣言する必要がある。</p><p>関数外で宣言する場合、<strong>デフォルトでstorage</strong>になっている。</p><p>ブロックチェーン上に保存するので、ガス代が高くなる。</p><h2 id="h-memory" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">memory</h2><p>コントラクトを実行する場合にのみ保持される変数。</p><p>→ブロックチェーン自体に保存されるわけではないため、storageと異なりガス代もかからない。</p><p>関数内で宣言する場合には<strong>デフォルトでmemory</strong>になっている。</p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">実装の際に苦労した点</h2><p>可変長配列を返そうと考えたが、結構苦戦しました。</p><p>以下がうまくいかなかったコードです。</p><pre data-type="codeBlock" text="function _transferableNFTs(uint256 stage) private view returns (NFTItem[] memory) {
        // return用の変数の宣言
        NFTItem[] list;
        // itemsは状態変数
        for (uint256 index = 0; index &lt; items.length; index++) {
            if (items[index].stage == stage &amp;&amp; !items[index].sold) {
                list.push(items[index]);
            }
        }
        return list;
}
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_transferableNFTs</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> stage</span>) <span class="hljs-title"><span class="hljs-keyword">private</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">NFTItem[] <span class="hljs-keyword">memory</span></span>) </span>{
        <span class="hljs-comment">// return用の変数の宣言</span>
        NFTItem[] list;
        <span class="hljs-comment">// itemsは状態変数</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">uint256</span> index <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; index <span class="hljs-operator">&#x3C;</span> items.<span class="hljs-built_in">length</span>; index<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
            <span class="hljs-keyword">if</span> (items[index].stage <span class="hljs-operator">=</span><span class="hljs-operator">=</span> stage <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> <span class="hljs-operator">!</span>items[index].sold) {
                list.<span class="hljs-built_in">push</span>(items[index]);
            }
        }
        <span class="hljs-keyword">return</span> list;
}
</code></pre><p>memoryであるにもかかわらず配列の宣言の際に初期化を行っていないのでエラーになりました。</p><p>そして次に書いたのが以下のコード</p><pre data-type="codeBlock" text="function _transferableNFTs(uint256 stage) private view returns (NFTItem[] storage) {
        // return用の変数の宣言
        NFTItem[] storage list;
        // itemsは状態変数
        for (uint256 index = 0; index &lt; items.length; index++) {
            if (items[index].stage == stage &amp;&amp; !items[index].sold) {
                list.push(items[index]);
            }
        }
        return list;
}
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_transferableNFTs</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> stage</span>) <span class="hljs-title"><span class="hljs-keyword">private</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">NFTItem[] <span class="hljs-keyword">storage</span></span>) </span>{
        <span class="hljs-comment">// return用の変数の宣言</span>
        NFTItem[] <span class="hljs-keyword">storage</span> list;
        <span class="hljs-comment">// itemsは状態変数</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">uint256</span> index <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; index <span class="hljs-operator">&#x3C;</span> items.<span class="hljs-built_in">length</span>; index<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
            <span class="hljs-keyword">if</span> (items[index].stage <span class="hljs-operator">=</span><span class="hljs-operator">=</span> stage <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> <span class="hljs-operator">!</span>items[index].sold) {
                list.<span class="hljs-built_in">push</span>(items[index]);
            }
        }
        <span class="hljs-keyword">return</span> list;
}
</code></pre><p>デフォルトでmemoryになっているので宣言の際に「storage」を追加し、返り値もstorageに変更しました。</p><p>しかし、<strong>storageを返り値にすることができない</strong>ためエラーになります。</p><p>そして以下のようなコードに変更しました</p><pre data-type="codeBlock" text="function _transferableNFTs(uint256 stage) private view returns (NFTItem[] memory) {
        // _transferableNFTCountで事前に配列の数を取得する
        uint256 count = _transferableNFTCount(stage);

        // return用の変数の宣言
        NFTItem[] list = new NFTItemUnsupported embed;

        // 新しい配列用のインデックスの宣言
        uint256 currentIndex = 0;

        // itemsは状態変数
        for (uint256 index = 0; index &lt; items.length; index++) {
            if (items[index].stage == stage &amp;&amp; !items[index].sold) {
                // pushではなく代入にする
                list[currentIndex] = items[index];
                currentIndex++;
            }
        }
        return list;
}
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_transferableNFTs</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> stage</span>) <span class="hljs-title"><span class="hljs-keyword">private</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">NFTItem[] <span class="hljs-keyword">memory</span></span>) </span>{
        <span class="hljs-comment">// _transferableNFTCountで事前に配列の数を取得する</span>
        <span class="hljs-keyword">uint256</span> count <span class="hljs-operator">=</span> _transferableNFTCount(stage);

        <span class="hljs-comment">// return用の変数の宣言</span>
        NFTItem[] list <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> NFTItemUnsupported embed;

        <span class="hljs-comment">// 新しい配列用のインデックスの宣言</span>
        <span class="hljs-keyword">uint256</span> currentIndex <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;

        <span class="hljs-comment">// itemsは状態変数</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">uint256</span> index <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; index <span class="hljs-operator">&#x3C;</span> items.<span class="hljs-built_in">length</span>; index<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
            <span class="hljs-keyword">if</span> (items[index].stage <span class="hljs-operator">=</span><span class="hljs-operator">=</span> stage <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> <span class="hljs-operator">!</span>items[index].sold) {
                <span class="hljs-comment">// pushではなく代入にする</span>
                list[currentIndex] <span class="hljs-operator">=</span> items[index];
                currentIndex<span class="hljs-operator">+</span><span class="hljs-operator">+</span>;
            }
        }
        <span class="hljs-keyword">return</span> list;
}
</code></pre><p>storageで値を返すことはできないので、memoryの宣言に変更しました。</p><p>**memoryで宣言する場合、固定長配列になるので事前に配列の長さを定義しておく必要があります。**そのため、宣言前に配列の長さを取得しています。</p><p>また、固定長配列の場合は「push」ではなく、代入になるので「currentIndex」というインデックスを別途宣言しています。</p><p>これによってmemoryでも実質的に可変長配列を返却できるようになります。</p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">最後に</h2><p>solidityに可変長配列がなさそうだったので実質的に実装しました。</p><p>もしより効率的な方法があれば教えていただけると幸いです🙇</p>]]></content:encoded>
            <author>adachi-tomoki@newsletter.paragraph.com (Adachi Tomoki)</author>
        </item>
    </channel>
</rss>