はじめに
『DApps開発入門』という本や色々記事を書いているかるでねです。
今回は、ERC20の送付時に送付先がコントラクトの場合に、ERC20を取り扱うことができるか確認する仕組みを提案しているERC4524についてまとめていきます!
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
他にも様々なEIPについてまとめています。
概要
ERC4524は、従来のERC20トークンにEIP165を組み込む提案をしています。
EIP165を導入することで、コントラクトがどのインターフェースを実装しているかをsupportsInterface
関数を呼び出すことで確認できるようになります。
また、NFT標準のERC721やマルチトークン標準のERC1155で用いられている、トークン受信時の検証や処理を行う関数群をERC20に取り込みます。
これにより、トークンを受け取るコントラクトが正しく受信機能を実装していることを保証できます。
EIP165については以下を参考にしてください。
動機
拡張機能の検出が難しい
ERC20はトークンの送受信だけを定義しており、トークン・パーミット(ERC2612など、一度のトランザクションで承認と送付を同時に行う仕組み)を実装しているかどうかをアプリや他のコントラクトが外部から判断する手段がありません。
ERC2612については以下を参考にしてください。
モジュール設計の促進
EIP165のsupportsInterface
を活用すると、開発者やコントラクトは特定のEIPを実装しているかを動的に判別できます。
これにより、トークンごとに異なる機能対応を自動で分岐しやすくなり、柔軟で拡張性の高いプラットフォーム構築を支援します。
標準の一貫性維持
ERC721やERC1155はすでにEIP165を取り入れており、NFTやマルチトークン領域で広く活用されています。
同様の仕組みをERC20にも導入することで、今後の拡張標準との相互運用性が向上してコミュニティ全体での統一的な開発体験が実現します。
仕様
-
ERC20トークンにEIP165(インターフェース検出機能)を組み込み、コントラクトがどのインターフェースを実装しているかを
supportsInterface
で判定できるようにする。 - 受信コントラクトが正しくトークンを扱えるかを保証するため、ERC721やERC1155で用いられる「
safeTransfer
」機能をERC20にも導入する。
実装要件
- ERC20準拠のコントラクトは、IERC20とIERC165を継承し、以下のインターフェースを実装する。
- このインターフェースのEIP165用
interfaceId
は0x534f5876
である。
pragma solidity 0.8.10;
import './IERC20.sol';
import './IERC165.sol';
// the EIP-165 interfaceId for this interface is 0x534f5876
interface SaferERC-20 is IERC20, IERC165 {
function safeTransfer(address to, uint256 amount) external returns(bool);
function safeTransfer(address to, uint256 amount, bytes memory data) external returns(bool);
function safeTransferFrom(address from, address to, uint256 amount) external returns(bool);
function safeTransferFrom(address from, address to, uint256 amount, bytes memory data) external returns(bool);
}
safeTransfer
とsafeTransferFrom
は、以下の処理を実行できる必要があります。
- EOA(外部所有アカウント)への送金はこれまで通り成功させる。
-
ERC20Receiverを実装し、
onERC20Received
呼び出しで返り値0x4fc35859
を返すコントラクトへの送金は成功させる。 - 受信コントラクトがERC20Receiverを実装していない、あるいは正しいセレクタを返さない場合はロールバックする。
safeTrransfer
を受け入れるコントラクトは、以下のインターフェースを実装し、onERC20Received
が返り値0x4fc35859
を返す必要があります。
pragma solidity 0.8.10;
import './IERC165.sol';
interface ERC20Receiver is IERC165 {
function onERC20Received(
address _operator,
address _from,
uint256 _amount,
bytes _data
) external returns(bytes4);
}
関数
safeTransfer
function safeTransfer(address to, uint256 amount) external returns(bool);
EOAアドレスおよびERC20Receiverを実装しonERC20Received
が0x4fc35859
を返すコントラクトに対して、指定したamount
分のトークンを送付する関数。
受信側がERC20Receiverを実装していない、または正しいセレクタを返さない場合はロールバックします。
引数
-
to
- トークンを受け取るアドレス。
-
amount
- 送付するトークンの数量。
戻り値
-
bool
- 送付が成功した場合に
true
を返す。
- 送付が成功した場合に
safeTransfer
function safeTransfer(address to, uint256 amount, bytes memory data) external returns(bool);
第一引数to
に指定したアドレスへ、amount
分のトークンとともにdata
を渡して送付する関数。
EOAとERC20Receiver実装コントラクトには成功し、未実装や誤った返り値の場合はロールバックします。
引数
-
to
- トークンを受け取るアドレス。
-
amount
- 送付するトークンの数量。
-
data
- 追加情報を含むバイト列。
戻り値
-
bool
- 送付が成功した場合に
true
を返す。
- 送付が成功した場合に
safeTransferFrom
function safeTransferFrom(address from, address to, uint256 amount) external returns(bool);
第三者のfrom
アドレスからto
アドレスへ、amount
分のトークンを送付する関数。
EOAとERC20Receiver実装コントラクトには成功し、未実装や誤った返り値の場合はロールバックします。
引数
-
from
- トークンを引き落とすアドレス。
-
to
- トークンを受け取るアドレス。
-
amount
- 送付するトークンの数量。
戻り値
-
bool
- 送付が成功した場合に
true
を返す。
- 送付が成功した場合に
safeTransferFrom
function safeTransferFrom(address from, address to, uint256 amount, bytes memory data) external returns(bool);
from
からto
へ、amount
分のトークンとdata
を送付する関数。
EOAとERC20Receiver実装コントラクトには成功し、未実装や誤った返り値の場合はロールバックします。
引数
-
from
- トークンを引き落とすアドレス。
-
to
- トークンを受け取るアドレス。
-
amount
- 送付するトークンの数量。
-
data
- 追加情報を含むバイト列。
戻り値
-
bool
- 送付が成功した場合に
true
を返す。
- 送付が成功した場合に
onERC20Received
function onERC20Received(
address _operator,
address _from,
uint256 _amount,
bytes _data
) external returns(bytes4);
ERC20Receiverインターフェースの一部として、safeTransfer
やsafeTransferFrom
から呼び出される関数。呼び出し元コントラクトは返り値が0x4fc35859
であることを確認し、これが正しくない場合は転送をロールバックします。
引数
-
_operator
- 送付を実行したコントラクトのアドレス。
-
_from
- 元のトークン所有者アドレス。
-
_amount
- 送付されたトークンの数量。
-
_data
- 送付時に渡された追加情報のバイト列。
戻り値
-
bytes4
- 成功を示すセレクタ
0x4fc35859
を返す。
- 成功を示すセレクタ
補足
最小限の実装方針
ERC4524では、ERC20にEIP165を導入する時のコード増加をできるだけ抑えた設計を採用しています。
追加されるコード量は最小限のため、コントラクトサイズがわずかに増える以外に大きなデメリットはありません。
safeTransfer
系関数の命名と利点
safeTransfer
およびsafeTransferFrom
は、ERC721やERC1155で既に広く使われている名前をそのまま踏襲しています。
この命名規則を維持することで、開発者は事前にコントラクトが安全にトークンを送付する機能をサポートしているかを簡単に確認でき、意図しないトークン消失リスクを低減できます。
メタデータURIの未採用理由
ERC721やERC1155ではトークン情報参照のためにメタデータURIが使われますが、ERC4524ではあえて含めていません。
理由は二つあります。
ひとつは「最小限の実装」にこだわるためであり、もうひとつはトークンメタデータURI機能がERC1046で既に十分にカバーされているためです。
これにより重複する仕様を避け、シンプルさを維持しています。
ERC1046については以下の記事を参考にしてください。
互換性
互換性の問題はありません。
セキュリティ
onERC20Received
はコールバック関数です。
コールバック関数は悪用された事例があるため、実装が脆弱にならないよう注意が必要です。
引用
William Schwab (@wschwab), "ERC-4524: Safer ERC-20 [DRAFT]," Ethereum Improvement Proposals, no. 4524, December 2021. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-4524.
最後に
今回は「ERC20の送付時に送付先がコントラクトの場合に、ERC20を取り扱うことができるか確認する仕組みを提案しているERC4524」についてまとめてきました!
いかがだったでしょうか?
質問などがある方は以下のTwitterのDMなどからお気軽に質問してください!
他の媒体でも情報発信しているのでぜひ他も見ていってください!