ERC-1400 + ERC-1410
仕様が大きかったのでERC-1400は部分的にERC-1410として分離され、issues/1411でERC-1410を使う形にして再定義されました。
この記事は主に分離前の仕様を元にしています。
概要(+個人的な所感)
一番特徴的なのは、既存のセキュリティトークンではtransferを部分的に制限する等で使うメタデータ(ロックアップ期間、KYC済みかどうかなど)の取り扱いがまちまちなので、元のトークンのbalanceを分割したものを作ってそこにメタデータを使ってtransferの条件を指定しようというアイデア。この分割された単位をtranche(トランシェ。元の意味は「証券化商品をリスクレベルや利回りなどの条件で区分したもの」らしい。 参考: https://www.nomura.co.jp/terms/japan/to/A02687.html )と呼んでいて、tranche単位でbalanceがあるのでトークン自体はPartially-Fungible Token(PFT)と呼んでいる。 nrryuya.icon < トランシェごとに分けたときにfungible tokenと言える
詳細
Requirements
セキュリティトークンには
transferが成功するor失敗するならその理由を返すということをチェック出来るようなインターフェースが必要
法的措置(legal action)やリカバリ(fund recovery)のためのforce transferが必要
トークンの発行(issuance, mintのこと)と買い戻し(redemption, burnのこと)する時のeventが必要
ある株主(shareholder)固有の権利やtransferを制限するためのメタデータが必要
transfer時に渡すパラメータ・on-chainのデータ・off-chainのデータに基づいて、transfer時にメタデータを書き換えられることが必要
バリデーションのためにtransfer時にsigned dataを送ることがおそらく必要
アセットのクラスを特定のものに制限すべきではない
ERC20, ERC777と互換性を持つほうが良い
abstract
アセットとしては同じものを表現しているが、結びつくデータが違う証券がある
(メタデータをトークンごとに付けるとしたら)メタデータは証券がNFTであることを示唆しているけれど、実際はメタデータは証券ではなくそのサブセットに対して適用されている
トークンのbalance・メタデータをtranscheという単位に分割する
セキュリティトークンはtransferが妥当かどうか判断するのにメタデータを参照する
ロックアップ期間に従っているか、KYCが完了しているか、投資家の数や一人辺りのトークン量に制限があるかなど
ERC20, ERC777は、balanceOfやallowanceを使ってtransferが成功するかをあらかじめチェックしやすい
セキュリティトークンではtransferがfailすることだけでなくその理由も分かったほうが良い
Partially-Fungible Token(ERC1410)
分割されたbalanceやメタデータは bytes32 _tranche というキーで参照される。
function getDefaultTranches(address _tokenHolder) external view returns (bytes32[]);
ERC777の send で送るtrancheを返すやつ(複数可)
デフォルトのtrancheがなければエラー(throw)になることもある
function setDefaultTranche(bytes32[] _tranches) external;
デフォルトのtrancheを設定するやつ(複数可)
function balanceOfByTranche(bytes32 _tranche, address _tokenHolder) external view returns (uint256);
trancheごとのbalanceを取得するやつ
function sendByTranche(bytes32 _tranche, address _to, uint256 _amount, bytes _data) external returns (bytes32);
function sendByTranches(bytes32[] _tranches, address[] _tos, uint256[] _amounts, bytes _data) external returns (bytes32);
特定のtrancheを送るやつ。transferに制限があってエラーにしたい場合はここの途中でfailにする
function redeemByTranche(bytes32 _tranche, uint256 _amount, bytes _data) external;
trancheをburnするやつ
function tranchesOf(address _tokenHolder) external view returns (bytes32[]);
特定のtokenHolderのtrancheの一覧を返すやつ
Operators
トークンを管理出来るオペレータを指定するための機能。(自動課金システムなどが想定されている)
機能的にはERC-777と同じで、各trancheごとにオペレータを指定出来るように拡張されている。
nrryuya.icon < approveとかなしで、信頼されたオペレーター(自動課金ボットなど)がtransfer
function defaultOperatorsByTranche(bytes32 _tranche) external view returns (address[]);
デフォルトのtrancheのオペレータを返すやつ
function authorizeOperatorByTranche(bytes32 _tranche, address _operator) external;
特定のtrancheにオペレータを設定するやつ
function revokeOperatorByTranche(bytes32 _tranche, address _operator) external;
オペレータの許可を取り消すやつ
function isOperatorForTranche(bytes32 _tranche, address _operator, address _tokenHolder) external view returns (bool);
特定のtrancheのオペレータかどうかを返すやつ
function operatorSendByTranche(bytes32 _tranche, address _from, address _to, uint256 _amount, bytes _data, bytes _operatorData) external returns (bytes32);
function operatorSendByTranches(bytes32[] _tranches, address[] _froms, address[] _tos, uint256[] _amounts, bytes _data, bytes _operatorData) external returns (bytes32[]);
オペレータ用の sendByTranche
function operatorRedeemByTranche(bytes32 _tranche, address _tokenHolder, uint256 _amount, bytes _operatorData) external;
オペレータ用の redeemByTranche
Notes
ERC20 / ERC777 Backwards Compatibility
ERC20, ERC777との後方互換性を保つためにデフォルトのtrancheが必要だよというお話。
Security Token(ERC1400)
function getDocument(bytes32 _name) external view returns (string, bytes32);
function setDocument(bytes32 _name, string _uri, bytes32 _documentHash) external;
法的文書や関連文書のURIを置いておくところ
function canSend(address _from, address _to, bytes32 _tranche, uint256 _amount, bytes _data) external view returns (byte, bytes32, bytes32);
transferが出来るかどうかをチェックするやつ
ERC-1066 で定義された ESC (Ethereum Status Code) とアプリケーション固有のコード(後述)を返す
function issuable() external view returns (bool);
トークンを発行出来るかを返すやつ
function issueByTranche(bytes32 _tranche, address _tokenHolder, uint256 _amount, bytes _data) external;
totalSupplyを増やすために呼ぶやつ
Notes
Forced Transfers
ERC-777においてデフォルトのオペレータをrevoke出来ないようにすれば、このオペレータ経由でtransferが出来るよねというお話(?)。
Restricted Transfers
セキュリティトークンだとtransferは色んな理由で失敗するので、 canSend で失敗理由とかを返す関数を定義したよというお話。
Identity
色んなKYC/AMLがあるから canSend をIdentifyのためのproxyとして用意したよというお話。
(この関数経由でチェックしてねということ。)
Reason Codes
transfer成功時・失敗時のコードのリスト。
On-chain vs. Off-chain Transfer Restrictions
transferの制限の条件はon-chainとoff-chain両方のデータを元にする可能性があって、off-chainの場合は sendByTranche と canSend に渡す bytes _data を使うといいよというお話。
Issueのコメントの意見
WIP
リンク
ERC-1400
ERC-1410
ERC-1066
ERC-777
ERC-1400について言及しているブログなど
nrryuya.icon < issue 1410がPartially Fungible Token(PFT), issue 1411がPFTを使ったSecurity Tokenの標準の話
勉強会メモ
nrryuya.icon < セキュリティトークンは担保アセットとして非常に良いと思っているので、dhamaやMakerDAOで使いやすいといいですね
nrryuya.icon
KYCとかロックアップとか、セキュリティトークンに限らずICOの標準でいいのでは?
nrryuya.icon < trancheのデータ構造きになる
nrryuya.icon < アドレス(投資家)にどんなメタデータを持たせるか、各trancheを受け取れるかどうかを管理するかのところも標準かした方がいいのでは
shuntak.icon < ERC777なんぞ?
shuntak.icon < リファレンス実装無さそうなのでLayerXから出していきたいかも
osuke.icon>Bryantどこにでもいるな
nrryuya.icon < 暇なんじゃないですか