カテゴリー
サインイン 新規登録

間違いや改善の指摘

内容の技術的な誤り・誤字脱字やミスのご報告・解説やトピックの追記/改善のご要望は教材をさらに良くしていく上でとても貴重なご意見になります。

少しでも気になった点があれば、ご遠慮なく投稿いただけると幸いです🙏

実際には誤りではなく勘違いであっても、ご報告いただけることで教材のブラッシュアップにつながります。

質問ポリシー①

教材受講者みなさんのスムーズな問題解決のために、心がけていただきたいことがあります。

教材の内容に関する質問を投稿しましょう

教材の内容に関係のない質問や教材とは異なる環境・バージョンで進めている場合のエラーなど、教材に関係しない質問は推奨していないため回答できない場合がございます。

その場合、teratailなどの外部サイトを利用して質問することをおすすめします。教材の誤字脱字や追記・改善の要望は「文章の間違いや改善点の指摘」からお願いします。

0-4

名簿を作ってみよう

1.4 名簿を作ってみよう

名前とEmailアドレスを記録する名簿を作りましょう。mappingによるデータ構造と関数のアクセス制限について学びます。

javascript
123456789101112131415161718192021222324252627282930313233343536373839404142
Copied!
pragma solidity ^0.4.25; contract addressBook { // ①コントラクトオーナーのアドレス address private owner; uint private numUser; // 登録件数 // ②登録情報を保存するデータ構造体 struct userInfo { string name; // 名前 string email; // Emailアドレス } mapping(uint => userInfo) private accounts; // ③コンストラクタ // コントラクトを公開した際に実行されます constructor() public { owner = msg.sender; // コントラクトを公開したアドレスをオーナーに指定する numUser = 0; // 登録数の初期化 } // ④アクセス制限の実装 modifier onlyOwner { // コントラクトを呼び出したアドレスがオーナーと一致するか確認する // 一致しない場合は処理を止める require(msg.sender == owner); _; // modifierの末尾に必要 } // ⑤modifierを関数に付与する // ユーザー情報を登録する関数 function setInfo(string _name, string _email) public onlyOwner { accounts[numUser].name = _name; accounts[numUser].email = _email; numUser++; } // ユーザー情報を取得する関数 function getInfo(uint _numUser) view public onlyOwner returns(string, string) { return (accounts[_numUser].name, accounts[_numUser].email); } }

① コントラクトオーナーのアドレス

javascript
1
Copied!
address private owner;

Ethereumではアカウントやスマートコントラクトをアドレスと呼ばれる固有の文字列で識別します。

Copied!
アドレスの例 0xca35b7d915458ef540ade6068dfe2f44e8fa733c

Ethアドレスを保存するための変数はaddress型で宣言します。

② 登録情報を保存するデータ構造体

javascript
12345
Copied!
struct userInfo { string name; // 名前 string email; // Emailアドレス } mapping(uint => userInfo) private accounts;

まずは名前とEmailアドレスをメンバに持つuserInfoという構造体を宣言します。mappingはkeyと値を組み合わせたデータ構造です。ここではuint型のkeyとuserInfo型の値を持つaccountsというデータ構造体を宣言しています。accountsには例えば以下の様にデータを保存します。

Copied!
accounts[0].name = "kappa"; accounts[0].email = "kappa@uma.com"; accounts[1].name = "kamonohashi"; accounts[1].email = "kamo@uma.com"; accounts[2].name = "baku"; accounts[2].email = "baku@uma.com";
key name email
0 accounts[0] kappa kappa@uma.com
1 accounts[1] kamonohashi kamo@uma.com
2 accounts[2] baku baku@uma.com

③ コンストラクタ

javascript
1234
Copied!
constructor() public { owner = msg.sender; // コントラクトを公開したアドレスをオーナーに指定する numUser = 0; // 登録件数の初期化 }

コンストラクタはスマートコントラクトをデプロイした際に自動的に呼び出される関数です。msg.senderは関数を呼び出したアカウントのアドレスを取得します。コンストラクタの中ではmsg.senderはスマートコントラクトをデプロイしたアドレスを示します。登録件数の初期化もコンストラクタで行っています。

④ アクセス制限の実装

javascript
1234
Copied!
modifier onlyOwner { require(msg.sender == owner); _; // modifierの末尾に必要 }

modifierは関数に付与する修飾子を定義します。modifierが付与された関数は,関数が呼び出されるとmodifierの処理が先に実行されます。requireは条件を満たさなかった場合,処理を止めます。ここでは関数の呼び出したEthアドレスとスマートコントラクトをデプロイしたEthアドレスownerが一致しなければ後の処理を行いません。修飾子はmodifierによって自由に定義できますが,代表的な予約語として以下があります。

Copied!
・payable  送金を伴う関数に必要な修飾子です。payableを付与しない関数はEthの授受ができないため,誤った送金を防ぐことができます。 ・view  変数の変化を伴わない関数に付与する修飾子です。 ・pure  変数の変化を伴わないことに加え,変数の参照もしない関数に付与する修飾子です。 ・event  トランザクションへログを出力する際に使用します。

⑤ modifierを関数に付与する

javascript
1234567891011
Copied!
// ユーザー情報を登録する関数 function setInfo(string _name, string _email) public onlyOwner { accounts[numUser].name = _name; accounts[numUser].email = _email; numUser++; } // ユーザー情報を取得する関数 function getInfo(uint _numUser) view public onlyOwner returns(string, string) { return (accounts[_numUser].name, accounts[_numUser].email); }

setInfoaccountsに名前とEmailアドレスを登録するための関数です。情報が登録される度にnumUserが1だけ増加します。getInfoaccountsのゲッターです。accountsのkeyを指定するためにuint型の引数_numUserを持ちます。これらの関数はonlyOwnerが付与されているため,スマートコントラクトをデプロイしたアドレスからのみ実行できます。

1.1と同じやり方で名簿スマートコントラクトをデプロイし,いくつか名前とEmailアドレスを入力してみましょう。

1-6.png

次にアカウントを変更してコントラクトを実行してみて下さい。modifierが働き処理が実行されないことが確認できます。

1-7.png

1-8.png

お疲れさまでした!次の章ではいよいよフリマアプリのスマートコントラクトを実装して行きます。