ERC 884
まとめ
デラウェア州の会社法に合致に特化トークン設計
DLT上のトークンをshareとして認定
株主管理がDLT上で完了する
株主名簿を作る:会社法219,220条
名簿に要求される情報を記載する:156, 159, 217(a) and 218条
株式譲渡要件を満たす: Article 8 of Subtitle I of Title 6
誰がどのように関数を使えるのかという制限がスコープ外
連邦証券法の要求を満たせないのでそもそも発行できない、という恐れがある
このままだと、関数の管理に中央集権的なアクターが必要にある
誰がどのように認証するのか、の部分もスコープ外
認証結果しか載せないので、この点も中央集権的
私見:正直、このフレームワークだけだったらわざわざETOするメリットが見いだせない気もする
他のフレームワークと統合して、ETOだった場合株主管理の部分だけこれ使おう?って感じになるのかなぁ
インターフェースの特徴
1トークン1株式(分割不可)
decimal は0を返さなければならない
株主名簿の修正が可能
ブロックチェーンが持つ不可逆性に対処
canselAndReissue()関数
event VerifiedAddressSupersededイベント
個人情報をハッシュ化させて紐づけ:hasHash()を利用
株主特定の必要性とプライバシーの必要性との妥協点
株主名と住所、Etherアドレスとを特定しておく必要有
これらは発行体のOff-chainによって管理される
誰が保持するのか?
関数
function addVerified:リストに認証アドレスを追加する関数
Input:
address addr: 追加するアドレス
bytes32 hash: アドレスを持つ株主のハッシュ化情報
Return:
bool: 基本的にtrueを返答
既にトークンを持っていたり、アドレスが0だったらthrowを返答
エラーメッセージを出せるよう例外処理を行えるようにするため
実行後、event VerifiedAddressAddedを実行させる必要性有
function removeVerified:アドレスをリストから削除する関数
Input:
address addr: 削除されるアドレス
Return:
bool: トークンを保持していないかを判断
トークンを持っている場合はthrowを返答
エラーメッセージを出せるよう例外処理を行えるようにするため
関数の中で、event VerifiedAddressRemovedを実行する必要有
一度verifiedされている限り、verified accountであるデータは残存
function updateVerified:株主情報を更新する関数
Input:
address addr: 情報を変更するアドレス
bytes32 hash: 新たな株主情報のハッシュ値
Return:
bool: 正しく更新されているかを判断
以前と情報が同じ場合falseを返答
addrが未認証アドレスだった場合、throwを返答
エラーメッセージを出せるよう例外処理を行えるようにするため
関数内で、event VerifiedAddressUpdatedを実行する必要有
function cancelAndReissue:株主のアドレスを変更する関数
厳重にコントロールされる必要性アリ
株主が秘密鍵をなくしたり、盗まれたりした場合に稼働
Input:
address original: 変更前のアドレス
address replacement: 変更後のアドレス
return:
bool:変更後のアドレスが適切かを判断
replacementがverified address出なかった場合false
replacementがトークンを既に持っていた場合false
original:がそもそもトークンを持っていなかった場合false
関数内で、event VerifiedAddressSupersededを起動させる必要性有
function transfer:トークンの送付を実行するアドレス
Input:
address to:送付先アドレス
uint256 value: 送付量
return:
bool: 送付先toがunverifiedであればfalseを返答
これでownerのトークン数が0になった場合、function removeVerifiedを起動させる必要性有
toが持つトークン数が0だった場合、function addVerifiedを起動させる必要有
function transferFrom:第三者が送付を実行する場合のアドレス
Input:
address from: 送付者のアドレス
address to:送付先アドレス
uint256 value: 送付量
Return:
bool: toアドレスが認証されていなかった場合にfalseを返答
function isVerified:アドレスが認証されているアドレスかを判断する
Input:
address addr:確認するアドレス
Return:
bool:コントラクトに認証されていないアドレスだった場合falseを返答
function isHolder:アドレスが株主になっているかを判断
Input:
address addr:確認するアドレス
return:
bool:アドレスがトークンを持っていなかった場合falseを返答
function hasHash:ハッシュ値が登録されている株主アドレスとマッチするかを確認する関数
Input:
address addr: 確認するアドレス
bytes32 hash:確認するハッシュ値
Return:
bool: アドレスとハッシュ値とが、function addVerifiedかfunction updateVerifiedでとうろくさたペアと一致した場合にtrueを返答
具体的にどのようにHash化するかは発行体次第
function holderCount:株主の数をカウントする関数
Input:無し
Return:
uint:アドレスの数を返答
株主数制限はこの関数より管理可能
function holderAt: リストの指定した番号の株主情報を返答する関数
Input:
uint256 index:指定する順番を指定
Return:
address:指定された株主のアドレスを返答
番号がholderCountで指定された数字より大きかった場合はエラーを返答
function isSuperseded:指定されたアドレスが変更されていないか確認する関数
Input:
address addr:チェックするアドレス
Return:
bool:もし変更されていたらtrueを返答
function getCurrentFor:変更後のアドレスを獲得する関数
Input:
address addr:チェックするアドレス
Return:
address:最新版のアドレスを返答
何度も変更が行われている可能性があるので、実装では最新版まで追えるようなものにしておく必要有
イベント
event VerifiedAddressAdded: 新たなアドレスが認証されたことを通知
Input:
address indexed addr: 認証されるアドレス
bytes32 hash: 追加されたアドレスの株主株主情報のハッシュ値
address indexed sender : 認証情報を送ったアドレス
senderは誰が就任することができるのか?
event VerifiedAddressRemoved:認証アドレスがリストから削除されたことを通知
Input:
address indexed addr:削除されるアドレス
address indexed sender:削除情報を送ったアドレス
event VerifiedAddressUpdated:認証アドレスの株主情報が更新されたことを通知
Input:
address indexed addr: 変更情報を有するアドレス
bytes32 oldHash: 昔の株主情報が入ったハッシュ値
bytes32 hash:新しい株主情報が入ったハッシュ値
address indexed sender:変更情報を送ったアドレス
event VerifiedAddressSuperseded:認証アドレスを変更されたことを通知
このイベントは、株主が秘密鍵をなくしたり漏洩してしまった場合に対処法として行われる
Input:
address indexed original: 変更前のアドレス
address indexed replacement:変更後のアドレス
address indexed sender:変更を実施したアドレス
インターフェース
code:ERC884(javascript)
/**
* An ERC20 compatible token that conforms to Delaware State Senate,
* 149th General Assembly, Senate Bill No. 69: An act to Amend Title 8
* of the Delaware Code Relating to the General Corporation Law.
*
* Implementation Details.
*
* An implementation of this token standard SHOULD provide the following:
*
* name - for use by wallets and exchanges.
* symbol - for use by wallets and exchanges.
*
* The implementation MUST take care not to allow unauthorised access to
* share-transfer functions.
*
* In addition to the above the following optional ERC20 function MUST be defined.
*
* decimals — MUST return 0 as each token represents a single share and shares are non-divisible.
*
*/
contract ERC884 is ERC20 {
/**
* This event is emitted when a verified address and associated identity hash are
* added to the contract.
* @param addr The address that was added.
* @param hash The identity hash associated with the address.
* @param sender The address that caused the address to be added.
*/
event VerifiedAddressAdded(
address indexed addr,
bytes32 hash,
address indexed sender
);
/**
* This event is emitted when a verified address and associated identity hash are
* removed from the contract.
* @param addr The address that was removed.
* @param sender The address that caused the address to be removed.
*/
event VerifiedAddressRemoved(address indexed addr, address indexed sender);
/**
* This event is emitted when the identity hash associated with a verified address is updated.
* @param addr The address whose hash was updated.
* @param oldHash The identity hash that was associated with the address.
* @param hash The hash now associated with the address.
* @param sender The address that caused the hash to be updated.
*/
event VerifiedAddressUpdated(
address indexed addr,
bytes32 oldHash,
bytes32 hash,
address indexed sender
);
/**
* This event is emitted when an address is cancelled and replaced with
* a new address. This happens in the case where a shareholder has
* lost access to their original address and needs to have their share
* reissued to a new address. This is the equivalent of issuing replacement
* share certificates.
* @param original The address being superseded.
* @param replacement The new address.
* @param sender The address that caused the address to be superseded.
*/
event VerifiedAddressSuperseded(
address indexed original,
address indexed replacement,
address indexed sender
);
/**
* Add a verified address, along with an associated verification hash to the contract.
* Upon successful addition of a verified address, the contract must emit
* VerifiedAddressAdded(addr, hash, msg.sender).
* It MUST throw if the supplied address or hash are zero, or if the address has already been supplied.
* @param addr The address of the person represented by the supplied hash.
* @param hash A cryptographic hash of the address holder's verified information.
*/
function addVerified(address addr, bytes32 hash) public;
/**
* Remove a verified address, and the associated verification hash. If the address is
* unknown to the contract then this does nothing. If the address is successfully removed, this
* function must emit VerifiedAddressRemoved(addr, msg.sender).
* It MUST throw if an attempt is made to remove a verifiedAddress that owns tokens.
* @param addr The verified address to be removed.
*/
function removeVerified(address addr) public;
/**
* Update the hash for a verified address known to the contract.
* Upon successful update of a verified address the contract must emit
* VerifiedAddressUpdated(addr, oldHash, hash, msg.sender).
* If the hash is the same as the value already stored then
* no VerifiedAddressUpdated event is to be emitted.
* It MUST throw if the hash is zero, or if the address is unverified.
* @param addr The verified address of the person represented by the supplied hash.
* @param hash A new cryptographic hash of the address holder's updated verified information.
*/
function updateVerified(address addr, bytes32 hash) public;
/**
* Cancel the original address and reissue the tokens to the replacement address.
* Access to this function MUST be strictly controlled.
* The original address MUST be removed from the set of verified addresses.
* Throw if the original address supplied is not a shareholder.
* Throw if the replacement address is not a verified address.
* Throw if the replacement address already holds tokens.
* This function MUST emit the VerifiedAddressSuperseded event.
* @param original The address to be superseded. This address MUST NOT be reused.
*/
function cancelAndReissue(address original, address replacement) public;
/**
* The transfer function MUST NOT allow transfers to addresses that
* have not been verified and added to the contract.
* If the to address is not currently a shareholder then it MUST become one.
* If the transfer will reduce msg.sender's balance to 0 then that address
* MUST be removed from the list of shareholders.
*/
function transfer(address to, uint256 value) public returns (bool);
/**
* The transferFrom function MUST NOT allow transfers to addresses that
* have not been verified and added to the contract.
* If the to address is not currently a shareholder then it MUST become one.
* If the transfer will reduce from's balance to 0 then that address
* MUST be removed from the list of shareholders.
*/
function transferFrom(address from, address to, uint256 value) public returns (bool);
/**
* Tests that the supplied address is known to the contract.
* @param addr The address to test.
* @return true if the address is known to the contract.
*/
function isVerified(address addr) public view returns (bool);
/**
* Checks to see if the supplied address is a shareholder.
* @param addr The address to check.
* @return true if the supplied address owns a token.
*/
function isHolder(address addr) public view returns (bool);
/**
* Checks that the supplied hash is associated with the given address.
* @param addr The address to test.
* @param hash The hash to test.
* @return true if the hash matches the one supplied with the address in addVerified, or updateVerified.
*/
function hasHash(address addr, bytes32 hash) public view returns (bool);
/**
* The number of addresses that hold tokens.
* @return the number of unique addresses that hold tokens.
*/
function holderCount() public view returns (uint);
/**
* By counting the number of token holders using holderCount
* you can retrieve the complete list of token holders, one at a time.
* It MUST throw if index >= holderCount().
* @param index The zero-based index of the holder.
* @return the address of the token holder with the given index.
*/
function holderAt(uint256 index) public view returns (address);
/**
* Checks to see if the supplied address was superseded.
* @param addr The address to check.
* @return true if the supplied address was superseded by another address.
*/
function isSuperseded(address addr) public view returns (bool);
/**
* Gets the most recent address, given a superseded one.
* Addresses may be superseded multiple times, so this function needs to
* follow the chain of addresses until it reaches the final, verified address.
* @param addr The superseded address.
* @return the verified address that ultimately holds the share.
*/
function getCurrentFor(address addr) public view returns (address);
}
Source