資金の引き出しを実装しよう
🛠 資金を引き出す機能を実装する
前回まででスマートコントラクトをデプロイし、ユーザーがドメインを作成できるようにするReactベースのWebアプリケーションを作成してきました。
これでかの有名なBored Apeを購入し、ミームを1日中Twitterに投稿することもできます。
しかしまだできないことがあります。
まだ資金を引き出す方法を作成できていないからです。
では、人々がドメインに支払ってくれたトークンにどのようにアクセスできるでしょうか?
👻 関数修飾子と撤回関数
その機能を追加するためにコントラクト(つまりバックエンド側です)を修正していきましょう。
Domains.solに以下を追加します。
modifier onlyOwner() {
require(isOwner(), "You aren't the owner");
_;
}
function isOwner() public view returns (bool) {
return msg.sender == owner;
}
function withdraw() public onlyOwner {
uint amount = address(this).balance;
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Failed to withdraw Matic");
}
現在、エラーが発生している可能性があります。
でも心配しないでください。予想通りです。
先に進んで、これを少し分解しましょう:
最初に作成するのは関数modifierです。 これにより、関数の動作を変更できます。
requireステートメントを実装するための便利な手法です。
この修飾子が行うのは、 isOwner()関数がtrueを返すことだけです。 trueでない場合、この修飾子で宣言された関数は実行できません。
初見で不思議に思える部分は最後の_;でしょう。modifier修飾子を使用する関数は、requireの後に実行する必要があります。_;がrequireの前にある場合、withdraw関数が最初に呼び出され、次にrequireが呼び出されることになります。これではrequireが役に立ちません。
_;を記載することで、その後の処理を続行するという意味になります。
withdraw()関数に関しては、コントラクトの残高を取得し、それをリクエスター(関数を実行するためには所有者である必要があります)に送信することだけです。 これは資金を引き出すのに簡単な手法です。 msg.sender.call {value:amount}(" ")は、送金するための書き方です。 構文は少し奇妙ですがamountを渡す方法に注目してください。 require(successは、トランザクションが成功したことが想定されるところです。 成功しない場合は、トランザクションをエラーとして認識し、"Failed to withdraw Matic"と表示します。
🤠 コントラクトオーナーの設定
厄介なownerエラーを修正するには、コントラクトの先頭にグローバルなowner変数を作成し、次のようにコンストラクターに設定するだけです。
address payable public owner;
constructor(string memory _tld) ERC721 ("Ninja Name Service", "NNS") payable {
owner = payable(msg.sender);
tld = _tld;
console.log("%s name service deployed", _tld);
}
重要な点は、payableタイプとして設定したことです。 これは、所有者のaddressが支払いを受け取ることができることを意味し、明示的に宣言する必要があります。 詳細については、こちらをご参照ください。
これでコントラクトにある資金を引き出すことができます。