はじめに

初めまして。 CryptoGamesというブロックチェーンゲーム企業でエンジニアをしている cardene(かるでね) です! スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。

代表的なゲームはクリプトスペルズというブロックチェーンゲームです。

今回は、ERC20トークンのtransfer(送付)やapprove(承認)後に、追加で送付先や承認先のコントラクト内の関数を実行するERC1363についてまとめていきます!

以下にまとめられているものをChatGPTも使用しながら、翻訳・要約・補足してまとめていきます。

この提案は、ERC20トークンのインターフェースを定義し、トランザクションの実行後に別の処理を行うコードを実行できるようにするものです。 具体的には、トークンのtransfer(送付)やapprove(承認)後に、別の処理を行うコードを自動的に呼び出す方法を提供します。

erc1363.png

この提案では、以下の新しい関数を導入します。

transferAndCallとtransferFromAndCall

ERC1363ReceiverコントラクトのonTransferReceived関数を呼び出します。 これにより、transfer(送付)やtransferFrom(承認された送付)を実行した後に、追加の処理を実行することができます。

transfer.png

approveAndCall

ERC1363SpenderコントラクトのonApprovalReceived関数を呼び出します。 これにより、approve(承認)を実行した後に追加の処理を実行することができます。

approve.png

Spenderとは、トークンのtransfer(送付)の承認をされたアドレスのことを指します。

動機

現在、ERC20トークンのtransfer(送付)やapprove(承認)後にコードを実行する方法がないため、もし他の関数を実行したい場合は別のトランザクションを送信して2回のGASを支払う必要があります。

この提案は、トークン支払いをより簡単に行い、別のリスナーを使用せずにトランザクション後にコードを実行できるようにすることを目的としています。

例として、以下のようなEthereumスマートコントラクトを想定しています。

ICO

クラウドセールの略で、新しい暗号通貨(トークン)を発行して、それを投資家や一般のユーザーに対して販売する資金調達手法の1つのことです。 購入者がトークンをtransfer(送付)してからトークンの配布を行うとします。 ERC1363を使用することで、投資家がトークンをtransfer(送付)した後に、自動的にクラウドセールのコントラクト内の関数が実行され、送られたトークン量に応じて購入者にクラウドセールトークンを配布することができます。

サービス提供

サービス提供者がトークンを受け取ることでサービスを提供する場合、ERC1363を使用してサービス提供の確認およびトークンの受け取り処理を自動化することができます。 顧客がトークンをtransfer(送付)したら、トークンの数量に応じたサービス提供を開始する処理が可能です。

請求書支払い

請求書をトークンで支払う場合、ERC1363を使用して請求書の支払い処理を自動化することができます。 請求書を発行した企業が支払われたトークンの数量に応じて請求書の支払いを確認することができます。

サブスクリプション

定期的な支払いをトークンで行いたい場合、、ERC1363を使用して定期的な支払いの処理を自動化することができます。 トークンをtransfer(送付)された時に、サブスクリプションを有効化しサービスの提供が開始されます。 その後、特定の期間ごとにトークンを受け取り、対応するサービスの提供を継続します。 もし定期的な支払いに必要なトークンが不足している場合、支払いが失敗し通知することができます。

この提案はERC721のonERC721ReceivedとERC721TokenReceiverの仕組みに着想を得ています。

仕様

ERC1363

javascript
pragma solidity ^0.8.0;

interface ERC1363 /* is ERC20, ERC165 */ {
  function transferAndCall(address to, uint256 value) external returns (bool);

  function transferAndCall(address to, uint256 value, bytes memory data) external returns (bool);

  function transferFromAndCall(address from, address to, uint256 value) external returns (bool);

  function transferFromAndCall(address from, address to, uint256 value, bytes memory data) external returns (bool);

  function approveAndCall(address spender, uint256 value) external returns (bool);

  function approveAndCall(address spender, uint256 value, bytes memory data) external returns (bool);
}

interface ERC20 {
  function totalSupply() external view returns (uint256);
  function balanceOf(address account) external view returns (uint256);
  function transfer(address recipient, uint256 amount) external returns (bool);
  function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
  function allowance(address owner, address spender) external view returns (uint256);
  function approve(address spender, uint256 amount) external returns (bool);
  event Transfer(address indexed from, address indexed to, uint256 value);
  event Approval(address indexed owner, address indexed spender, uint256 value);
}

interface ERC165 {
  function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

transferAndCall

トークンをtransfer(送付)した後、トークンの受け取りコントラクト内のonTransferReceived関数を呼び出す関数。 受け取りコントラクトに追加のデータを送信もできます。

transferFromAndCall

他のアドレスからトークンを受け取り、トークンの受け取りコントラクト内のonTransferReceived関数を呼び出す関数。 受け取りコントラクトに追加のデータを送信もできます。

approveAndCall

他のアドレスに対してトークンのapprove(承認)を行い対応するSpenderコントラクト内のonApprovalReceived関数を呼び出す関数。 受け取りコントラクトに追加のデータを送信もできます。

ERC20については以下を参照してください。

ERC165については以下を参照してください。

ERC1363Receiver

javascript
interface ERC1363Receiver {
  function onTransferReceived(address operator, address from, uint256 value, bytes memory data) external returns (bytes4);
}

ERC1363Receiverインターフェースの識別子は0x88a7ca5cです。

onTransferReceived

ERC1363のトークンコントラクトからtransferまたはtransferFrom関数が実行された後に、受け取りコントラクト内で呼び出される関数。 受け取りコントラクトは、この関数を実装することで、トークンの受け取り時に特定の処理を実行することができます。 戻り値として、bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))を返す。 それ以外の値を返すとトランザクションがリバート(巻き戻し)されます。 これにより、トランザクションの正常性を確認することができます。

  • operator
    • transferAndCallまたはtransferFromAndCall関数を呼び出したアドレス(トークンの送信元または承認元)。
  • from
    • トークンが送信されたアドレス(transferまたはtransferFromの送信元)。
  • value
    • トークンの数量(送信されたトークンの量)。
  • data
    • 追加のデータ(特定のフォーマットが指定されていない追加の情報)。

ERC1363Spender

javascript
interface ERC1363Spender {
  function onApprovalReceived(address owner, uint256 value, bytes memory data) external returns (bytes4);
}

ERC1363Spenderインターフェースの識別子は0x7b04a2d0です。

onApprovalReceived

ERC1363のトークンコントラクトからapprove関数が実行された後に、Spenderのコントラクト内で呼び出される関数です。 Spenderのコントラクトは、この関数を実装することでトークンの承認時に特定の処理を実行することができます。 戻り値として、bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))を返す。 それ以外の値を返すとトランザクションがリバート(巻き戻し)されます。 これにより、トランザクションの正常性を確認することができます。

  • owner
    • approveAndCall関数を呼び出したアドレス(トークンの所有者)。
  • value
    • 承認されたトークンの数量(承認されたトークンの量)。
  • data
    • 追加のデータ(特定のフォーマットが指定されていない追加の情報)。

補足

transferAndCall、transferFromAndCall、approveAndCallの関数名は、ERC20トークンの関数名から派生しています。 これらの関数は、transfer、transferFrom、およびapproveと同じ振る舞いをしながら、受け取りコントラクトやSpenderに対してコールバックを追加したものです。

コールバックとは、ある処理が完了した後に自動的に実行される関数のことを指します。

つまり、トークンのtransfer(送付)やapprove(承認)が行われた後に、受け取りコントラクトやSpenderのコントラクトで特定の処理を実行することができます。

互換性

この提案は、ERC223やERC677からのインスピレーションを受けていますが、ERC20の手法を採用しています。 つまり、ERC20のtransferおよびtransferFromメソッドを上書きせず、ERC20の後方互換性を保ちながら、新たな機能を追加しています。 これにより、既存のERC20トークンの実装を変更することなく、新しい機能を導入できます。

セキュリティ上の考慮

approveAndCallおよびtransferFromAndCallメソッドは、標準のERC20のapproveおよびtransferFrom関数と同じ問題に影響を受ける可能性があります。 approveAndCallメソッドでtransfer(送付)許可を変更する際に、トランザクションの順序によって古い許可と新しい許可の両方が使用される危険性があります。 この競合条件を緩和するための解決策は、まずSpenderの許可をfalseに変更し、その後に目的の値を設定する方法があります。

コード

コードは以下のコードをそのまま使用しています。

以下が自分のリポジトリです。

テスト

以下がテストコードです。

考察

トークンのtransfer(送付)やapprove(承認)したときに、追加でトランザクションを走らせずに処理を実行できるの便利です。 可能性はだいぶ広がりますが、実装の難易度は高そうな印象を受けました。 また、トークンのtransfer(送付)やapprove(承認)先はコントラクトである必要があるため、コントラクトアドレスか確認することが重要です。 サブスクリプションを実装できるのは個人的に面白そうだと思ったので、何かしら作ってみたいと思いました。 ぜひ皆さんも色々とアイデアを出してみてください!

引用

Vittorio Minacori (@vittominacori), "ERC-1363: Payable Token," Ethereum Improvement Proposals, no. 1363, January 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-1363.

最後に

今回は「ERC721とERC20の機能を併せ持つ半代替性トークンと呼ばれているERC3525」についてまとめてきました! いかがだったでしょうか?

質問などがある方は以下のTwitterのDMなどからお気軽に質問してください!

採用強化中!

CryptoGamesでは一緒に働く仲間を大募集中です。

この記事で書いた自分の経験からもわかるように、裁量権を持って働くことができて一気に成長できる環境です。 「ブロックチェーンやWeb3、NFTに興味がある」、「スマートコントラクトの開発に携わりたい」など、少しでも興味を持っている方はまずはお話ししましょう!