スマートコントラクトプログラミング言語であるSolidityの配列について記載します。
Solidityの配列
Solidityでの配列は、すべての要素がインデックスと呼ばれる特定の場所を持ち、同じデータ型の要素の固定コレクションを格納するデータ構造として定義されています。
Solidity では、配列は固定サイズまたは動的サイズにすることができ、同じ型の個々の変数を多数作成する代わりに、必要なサイズの 1 つの配列を宣言し、要素を配列に格納し、インデックスを使用してアクセスします。
Solidity 配列の構文
1 |
<データ型> <配列名>[サイズ] = <初期化> |
固定サイズの配列
配列のサイズを事前に定義する固定サイズの配列について記載します。
配列のサイズを指定した場合、要素の総数が配列のサイズを超えてはなりません。
以下のソースコードでは、固定サイズの配列を宣言して初期化する方法を示したコントラクトとなります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract ArrayTest { // ステート配列変数を定義 uint[5] arr_data; int[7] arr_data2; // 配列に値を設定するファンクション function array_func() public returns (uint[5] memory,int[7] memory){ arr_data = [uint(1), 2, 3, 4, 5]; arr_data2 = [int(-1), -2, 3, -4, 5,6,7]; return (arr_data,arr_data2); } } |
このスマートコントラクトをDeployし、array_funcファンクションを呼び出すと、下記のように配列の値が表示されます。
動的配列
動的配列では配列のサイズを変数定義時に事前定義する必要はありません。
配列の要素が追加されると、配列のサイズも児童に変更され、スマートコントラクト実行時に配列のサイズが決定されます。
以下のソースコードでは、動的配列を作成および初期化するコントラクトです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract ArrayTest { // ステートの固定サイズの配列を定義 uint[] fixedData = [1, 2, 3, 4, 5]; // ステートの動的配列を定義 int[] dynamicData; // 動的配列 function set() public returns(uint[] memory, int[] memory){ dynamicData = [int(-1), 2, -3, 4, 5, 6, 7,8,9,10]; return (fixedData, dynamicData); } } |
このスマートコントラクトをDeployし、setファンクションを呼び出すと、下記のように配列の値が表示されます。
配列の操作方法
次に配列の操作方法について記載します。
要素へのアクセス
配列の要素へのアクセスにはインデックス番号を使用してアクセスします。
i 番目の要素にアクセスする場合は、(i-1) 番目のインデックスにアクセスする必要があります。
下記のソースコードでは、最初に配列を初期化し、次に配列のインデックス番号2に設定された要素の値を取得するコントラクトとなります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract ArrayTest { // ステートの配列を定義 uint[5] arr; // 配列に値を設定するsetファンクション function set() public payable returns (uint[5] memory){ //ステート配列に値を設定 arr= [uint(1), 2, 3, 4, 5]; return arr; } // 配列の値を指定したインデックスからアクセスする関数の定義 function setElement() public payable returns (uint){ uint x = arr[2]; return x; } } |
このスマートコントラクトをDeployし、setファンクションを呼び出すと、下記のように配列の値が表示されます。
次にsetElementファンクションを呼び出しすると下記のように配列の値が表示されます。
配列2番目のインデックス番号の要素は3のため正常に取得できていることが確認出来ます。
配列の長さ
配列の長さは、配列内に存在する要素の数をチェックするために使用されます。
下記のソースコードでは、配列を初期化し、次に配列の長さを取得するコントラクトとなります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract ArrayTest { // 配列を宣言 uint[5] arr; // 配列に値を設定するsetファンクション function set() public payable returns (uint[5] memory){ arr = [uint(1), 2, 3, 4, 5]; return arr; } // 配列の長さを取得し、返り値とするcheckLengthファンクション function checkLength() public view returns(uint) { uint x = arr.length; return x; } } |
このスマートコントラクトをDeployし、setファンクションを呼び出すと、下記のように配列の値が表示されます。
次にgetLength関数を呼び出しすると下記が表示されます。
配列変数arrには1,2,3,4,5と5つの値が設定されているので長さは5が表示されていることが確認できるかと思います。
Push
Pushは、新しい要素が動的配列に追加されるときに使用されます。
新しい要素は常に配列の最後のインデックスに追加されます。
以下のソースコードでは、最初に配列を初期化し、次に値を配列にプッシュ(追加)するコントラクトとなります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract ArrayTest { // 配列を定義 uint[] arr = [1, 2, 3, 4, 5]; // pushで配列にデータを追加するarr_pushファンくそhン function arr_push() public returns(uint[] memory){ //pushファンクションで配列に要素を追加 arr.push(6); arr.push(7); arr.push(8); return arr; } } |
このスマートコントラクトをDeployし、arr_pushファンクションを呼び出すと、下記のように配列の値が表示されます。
配列変数arr = [1, 2, 3, 4, 5]の値から6,7,8が順番に追加されていることが確認できるかと思います。
Pop
Popは、動的配列の中で配列の最後の要素を削除する場合に使用します。
下記のソースコードでは、配列を初期化し、次にpopファンクションを用いて配列から値を削除しているコントラクトとなります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract ArrayTest { // 配列を定義 uint[] arr = [1, 2, 3, 4, 5]; // 配列からpopするarr_popファンクションを定義 function arr_pop() public returns(uint[] memory){ arr.pop(); return arr; } } |
このスマートコントラクトをDeployし、arr_popファンクションを呼び出すと、下記のように配列の値が表示されます。
配列変数arr = [1, 2, 3, 4, 5]の値から一番最後のインデックスの5が削除されていることが確認できるかと思います。
スマートコントラクトで配列を利用するうえで注意するべき点
イーサリアムの世界では、ブロックチェーン上のデータを編集する取引にはガス代がかかるため、スマートコントラクトからできるだけ効率的にデータを保存/取得することを考えることが重要です。
配列のデータが大きくなりすぎないようにしましょう。
また極力配列を使ったすべてのデータに対するループ処理などもガス代が高額になる原因になるため避けるべきです。
多くのデータから一意のデータを取得する必要がある場合は、マッピング型を使用してデータを扱うことも検討してみてください。
solidityのmappingについては下記に記載しています。

最後に
今回紹介したSolidityの仕様やコードをRemix IDEやHardhatで実際に実行やテストをして確認してみましょう。
実際に動かしたり、テストすることで理解が深まるかと思います。
hardhatのインストール手順

HardhatでスマートコントラクトのDeploy手順
