この記事はISL Advent Calendar 2020 15日目の記事です。
ブログの環境を作り直そうと思ったら間に合わなかったので取り急ぎNotionで公開
ETH2.0の文脈でデポジットコントラクトというものが存在します。この1つのコントラクトには、2020年の12月15日時点で約146万ETH(約8.5億ドル相当の時価)にも及ぶETHがデポジットされています。現在もデポジットされるETHの量は増え続けており、今後さらに増えることが予想されます。
このコントラクトはEthereumがPoWからPoSへ移行するために大切なもので、ETH2.0の開発が一定のフェーズに達するまで預けたETHを取り出すことができません。預けるインセンティブとして、32ETH以上を預けた人に報酬が支払われます。いわゆるステーキングと呼ばれるものです。PoSへの移行においてコミュニティの同意を得ることや、ネットワークの分権性を維持し続けることを目的としているのだと思われます。
私のような一般人は32ETHも持っていませんので、ステーキングに参加したければ32ETHを貯める必要があります。取引所等が少額で手軽に始められるステーキングプールのようなサービスを展開していたりしますが、特定の取引所等に資産が長期間ロックされるのはあまり気が乗りません。 強い意志を持って自力で少しずつ貯めればよいのですが、途中で魔が差して売却してしまいそうです。 そこで、ETHを強制的に貯めるためのタイムロック式コントラクトを作り、自分ひとりだけで無報酬の虚無ステーキング(むしろ手数料で損しそうな貯金)をやってみましょう。
スマートコントラクト開発の入門として適切な題材だと思います。
もちろんETHの価額は変動しますので、実際にメインネットでやった場合「ETHの保有枚数は増えても日本円換算の時価は減っている!」みたいなリスクがあります。
貯金というより、正確には貯ETHですね。 マスタリングイーサリアムで紹介されているコードを少し改変して作ってみます。
// 以下のコードは簡易的なサンプルコードです。メインネット上では利用しないでください。発生した損失等について私は責任を追いません。
pragma solidity 0.6.11;
contract EtherStore{
// ミューテックス
bool reEntrancyMutex = false;
// デポジットの開始時間と残高はアドレスに紐付け
mapping(address => uint256) public startTime;
mapping(address => uint256) public balances;
// デポジット
function depositFunds() public payable{
require(msg.value != 0);
balances[msg.sender] += msg.value;
if(startTime[msg.sender] == 0){
startTime[msg.sender] = now;
}
}
// 引き出し
function withdrawFunds (uint256 _weiToWithdraw) public {
// ミューテックスの確認
require(!reEntrancyMutex);
// 残高の確認
require(balances[msg.sender] >= _weiToWithdraw);
// 引き出し条件を確認
require((now >= startTime[msg.sender] + 5 * 365 days) || (balances[msg.sender] >= 50 ether));
// 残高の状態変数を変更
balances[msg.sender] -= _weiToWithdraw;
reEntrancyMutex = true;
// 実際に送金
msg.sender.transfer(_weiToWithdraw);
reEntrancyMutex = false;
}
}