スマートコントラクト言語
最終編集者: @Frodo821(opens in a new tab), 2024年6月17日
イーサリアムの長所は、比較的デベロッパーフレンドリーな言語を使ってスマートコントラクトを記述できることです。 Pythonや中括弧を使ってブロックを表現する言語(opens in a new tab)を使用している方は、見慣れたような構文を持つ言語を使うことができます。
最も活発にメンテナンスされている言語は、以下の2つです。
- Solidity
- Vyper
また、経験豊富なデベロッパーであれば、イーサリアム仮想マシン用の中間言語であるYulや、Yulを拡張したYul+を使うのもよいでしょう。
開発中の新しい言語に興味があり、テストに協力したいとお考えの場合は、Feというまだ登場したばかりのスマートコントラクト言語を試してみることができます。
前提知識
プログラミング言語、特にJavaScriptやPythonの知識は、スマートコントラクト言語の違いを理解するのに役立ちます。 また、スマートコントラクトをコンセプトとして理解し、言語比較を深く掘り下げることをお勧めします。 スマートコントラクトの紹介
Solidity
- スマートコントラクトを実装するためのオブジェクト指向の高級言語
- C++に強い影響を受けた中括弧を使ってブロックを表現する言語
- 静的型付け(変数型はコンパイル時に決定される)
- 以下の言語機能をサポートしている
- 継承(他のコントラクトを拡張できる)
- ライブラリ(他のオブジェクト指向言語における静的クラスで定義された静的関数のように、さまざまなコントラクトから呼び出すことができる再利用可能なコードを作成できる)
- 複雑なユーザー定義型
参照すべきリンク
- ドキュメント(opens in a new tab)
- Solidity言語ポータル(opens in a new tab)
- Solidity by Example(opens in a new tab)
- GitHub(opens in a new tab)
- Solidity Gitterチャットルーム(opens in a new tab)は、Solidity Matrixチャットルーム(opens in a new tab)へブリッジされました。
- チートシート(opens in a new tab)
- Solidityブログ(opens in a new tab)
- Solidity Twitter(opens in a new tab)
コントラクトのコード例
1// SPDX-License-Identifier: GPL-3.02pragma solidity >= 0.7.0;34contract Coin {5 // The keyword "public" makes variables6 // accessible from other contracts7 address public minter;8 mapping (address => uint) public balances;910 // Events allow clients to react to specific11 // contract changes you declare12 event Sent(address from, address to, uint amount);1314 // Constructor code is only run when the contract15 // is created16 constructor() {17 minter = msg.sender;18 }1920 // Sends an amount of newly created coins to an address21 // Can only be called by the contract creator22 function mint(address receiver, uint amount) public {23 require(msg.sender == minter);24 require(amount < 1e60);25 balances[receiver] += amount;26 }2728 // Sends an amount of existing coins29 // from any caller to an address30 function send(address receiver, uint amount) public {31 require(amount <= balances[msg.sender], "Insufficient balance.");32 balances[msg.sender] -= amount;33 balances[receiver] += amount;34 emit Sent(msg.sender, receiver, amount);35 }36}すべて表示コピー
この例は、Solidityのコントラクト構文がどのようなものか理解するのに役立つでしょう。 関数と変数のより詳細な説明については、ドキュメント(opens in a new tab)を参照してください。
Vyper
- Python的なプログラミング言語
- 強い型付け
- コンパクトでわかりやすいコンパイラコード
- 効率的なバイトコード生成
- コントラクトの安全性を確保し、監査が容易になることを目的として、意図的にSolidityよりも機能を絞っている。 Vyperは以下をサポートしていない
- modifier修飾子
- 継承
- インラインアセンブリ
- 関数のオーバーロード
- オペレータのオーバーロード
- 再帰呼び出し
- 無限ループ
- 2進固定小数点
詳細については、Vyperのドキュメント(opens in a new tab)を参照してください。
参照すべきリンク
- ドキュメント(opens in a new tab)
- Vyper by Example(opens in a new tab)
- More Vyper by Example(opens in a new tab)
- GitHub(opens in a new tab)
- VyperコミュニティのDiscordチャット(opens in a new tab)
- チートシート(opens in a new tab)
- スマートコントラクト開発フレームワークとVyper用ツール
- VyperPunk - Vyperスマートコントラクトのセキュリティとハッキングを学ぶ(opens in a new tab)
- VyperExamples - Vyperの脆弱性の例(opens in a new tab)
- 開発用Vyper Hub(opens in a new tab)
- 人気を博しているVyperのスマートコントラクトの例(opens in a new tab)
- 素晴らしいVyperの厳選されたリソース(opens in a new tab)
例
1# Open Auction23# Auction params4# Beneficiary receives money from the highest bidder5beneficiary: public(address)6auctionStart: public(uint256)7auctionEnd: public(uint256)89# Current state of auction10highestBidder: public(address)11highestBid: public(uint256)1213# Set to true at the end, disallows any change14ended: public(bool)1516# Keep track of refunded bids so we can follow the withdraw pattern17pendingReturns: public(HashMap[address, uint256])1819# Create a simple auction with `_bidding_time`20# seconds bidding time on behalf of the21# beneficiary address `_beneficiary`.22@external23def __init__(_beneficiary: address, _bidding_time: uint256):24 self.beneficiary = _beneficiary25 self.auctionStart = block.timestamp26 self.auctionEnd = self.auctionStart + _bidding_time2728# Bid on the auction with the value sent29# together with this transaction.30# The value will only be refunded if the31# auction is not won.32@external33@payable34def bid():35 # Check if bidding period is over.36 assert block.timestamp < self.auctionEnd37 # Check if bid is high enough38 assert msg.value > self.highestBid39 # Track the refund for the previous high bidder40 self.pendingReturns[self.highestBidder] += self.highestBid41 # Track new high bid42 self.highestBidder = msg.sender43 self.highestBid = msg.value4445# Withdraw a previously refunded bid. The withdraw pattern is46# used here to avoid a security issue. If refunds were directly47# sent as part of bid(), a malicious bidding contract could block48# those refunds and thus block new higher bids from coming in.49@external50def withdraw():51 pending_amount: uint256 = self.pendingReturns[msg.sender]52 self.pendingReturns[msg.sender] = 053 send(msg.sender, pending_amount)5455# End the auction and send the highest bid56# to the beneficiary.57@external58def endAuction():59 # It is a good guideline to structure functions that interact60 # with other contracts (i.e. they call functions or send ether)61 # into three phases:62 # 1. checking conditions63 # 2. performing actions (potentially changing conditions)64 # 3. interacting with other contracts65 # If these phases are mixed up, the other contract could call66 # back into the current contract and modify the state or cause67 # effects (ether payout) to be performed multiple times.68 # If functions called internally include interaction with external69 # contracts, they also have to be considered interaction with70 # external contracts.7172 # 1. Conditions73 # Check if auction endtime has been reached74 assert block.timestamp >= self.auctionEnd75 # Check if this function has already been called76 assert not self.ended7778 # 2. Effects79 self.ended = True8081 # 3. Interaction82 send(self.beneficiary, self.highestBid)すべて表示コピー
この例は、Vyperのコントラクト構文がどのようなものか理解するのに役立つでしょう。 関数と変数のより詳細な説明については、ドキュメント(opens in a new tab)を参照してください。
YulとYul+
イーサリアムを使い始めたばかりで、スマートコントラクト言語を使ってコードを書いたことがない場合は、SolidityやVyperを利用することをお勧めします。 YulやYul+を検討するのは、スマートコントラクトのセキュリティの最善の方法や、EVMとの連携の具体的な内容に精通してからにしてください。
Yul
- イーサリアムのための中間言語
- EVMおよびEwasm(opens in a new tab)というイーサリアム向けのWebAssemblyをサポートしており、両方のプラットフォームで使用可能な共通部分として設計されている
- EVMとeWASMの両方のプラットフォームに同程度のメリットをもたらす、高度な最適化段階を経る対象となる
Yul+
- Yulに高効率な拡張機能を施した低レベル言語
- コントラクトのオプティミスティック・ロールアップのために設計された
- Yulに新しい機能を追加した実験的なアップグレード案として捉えることができる
参照すべきリンク
- Yulのドキュメント(opens in a new tab)
- Yul+のドキュメント(opens in a new tab)
- Yul+ Playground(opens in a new tab)
- Yul+の紹介記事(opens in a new tab)
コントラクトのコード例
以下の簡単な例では、べき乗関数を実装しています。 solc --strict-assembly --bin input.yul
を使用してコンパイルすることができます。 この例は、input.yulに記述されます。
1{2 function power(base, exponent) -> result3 {4 switch exponent5 case 0 { result := 1 }6 case 1 { result := base }7 default8 {9 result := power(mul(base, base), div(exponent, 2))10 if mod(exponent, 2) { result := mul(base, result) }11 }12 }13 let res := power(calldataload(0), calldataload(32))14 mstore(0, res)15 return(0, 32)16}すべて表示
スマートコントラクトの経験が豊富な場合は、YulによるERC20の完全な実装(opens in a new tab)をご覧ください。
Fe
- イーサリアム仮想マシン(EVM)向けの静的型付け言語
- PythonとRustの影響を受けている
- イーサリアムのエコシステムに不慣れなデベロッパーでも簡単に学習できる言語であることを目標としている
- Feの開発は未だ初期段階にあり、2021年1月にアルファ版がリリースされた
参照すべきリンク
- GitHub(opens in a new tab)
- Feに関するアナウンス(opens in a new tab)
- 2021年のFeのロードマップ(opens in a new tab)
- FeのDiscordチャット(opens in a new tab)
- Twitter(opens in a new tab)
コントラクトのコード例
Feで実装されたシンプルなコントラクトのコード例を以下に示します。
1type BookMsg = bytes[100]23contract GuestBook:4 pub guest_book: map<address, BookMsg>56 event Signed:7 book_msg: BookMsg89 pub def sign(book_msg: BookMsg):10 self.guest_book[msg.sender] = book_msg1112 emit Signed(book_msg=book_msg)1314 pub def get_msg(addr: address) -> BookMsg:15 return self.guest_book[addr].to_mem()16すべて表示
選択方法
他のプログラミング言語と同様に、個人的な好みだけでなく、行いたいことに最適なツールを選択することが重要です。
まだどの言語も試していない場合に考慮すべき事項をいくつか紹介します。
Solidityの長所
- 初心者向けに、多くのチュートリアルや学習ツールが用意されている。 詳細については、コーディングで学ぶセクションを参照
- 優れた開発ツールが利用可能
- Solidityには大きなデベロッパーコミュニティがあり、質問に対する答えをすぐに見つけることができる
Vyperの長所
- Pythonデベロッパーが、スマートコントラクトの記述を始めるのに最適な方法である
- Vyperの機能の数は絞られているため、アイデアから素早くプロトタイプを構築可能
- Vyperは監査が容易で、最大限に人間が読めるようにすることを目指している
YulとYul+の長所
- シンプルで機能的な低レベル言語
- 生のEVMに近づくことができ、コントラクトのガス使用量を最適化するのに役立つ
言語比較
コントラクトのライフサイクル、インターフェイス、演算子、データ構造、関数、制御フローなどの基本的な構文の比較については、 Auditlessによるチートシート(opens in a new tab)を参照してください。