ステーキングの仕組みを実装しよう
🖥 このレッスンの参考動画URL
📝 ステーキングの仕組み実装する
ここからはこのYield Farmingの根幹となるステーキングのシステムを実装していきます。
まず、TokenFarm.solを以下のように更新していきましょう。
pragma solidity ^0.8.18;
import "./DappToken.sol";
import "./MockDaiToken.sol";
contract TokenFarm{
string public name = "Dapp Token Farm";
DappToken public dappToken;
DaiToken public daiToken;
// 7. これまでにステーキングを行ったすべてのアドレスを追跡する配列を作成
address[] public stakers;
// 4.投資家のアドレスと彼らのステーキングしたトークンの量を紐づける mapping を作成
mapping (address => uint) public stakingBalance;
// 6. 投資家のアドレスをもとに彼らがステーキングを行ったか否かを紐づける mapping を作成
mapping (address => bool) public hasStaked;
// 10. 投資家の最新のステイタスを記録するマッピングを作成
mapping (address => bool) public isStaking;
constructor(DappToken _dappToken, DaiToken _daiToken){
dappToken = _dappToken;
daiToken = _daiToken;
}
// 1.ステーキング機能を作成する
function stakeTokens(uint _amount) public {
// 2. ステーキングされるトークンが0以上あることを確認
require(_amount > 0, "amount can't be 0");
// 3. 投資家のトークンを TokenFarm.sol に移動させる
daiToken.transferFrom(msg.sender, address(this), _amount);
// 5. ステーキングされたトークンの残高を更新する
stakingBalance[msg.sender] = stakingBalance[msg.sender] + _amount;
// 8. 投資家がまだステークしていない場合のみ、彼らをstakers配列に追加する
if(!hasStaked[msg.sender]){
stakers.push(msg.sender);
}
// 9. ステーキングステータスの更新
isStaking[msg.sender] = true;
hasStaked[msg.sender] = true;
}
}
コードの理解を促進するために、1から10までコメントに番号を振りました。1つずつみていきましょう。
まず、新しく追加された stakeTokens()関数に注目してください。
// 1.ステーキング機能を作成する
function stakeTokens(uint _amount) public {
:
}
stakeTokens関数は、 ステークするトークンの量(_amount)を引数としています。
- また、この関数は、スマートコントラクトの外部から呼び出せるように
public修飾子を持っています。
stakeTokens関数の主な役割は、投資家のウォレットからTokenFarm.solというスマートコントラクトに Dai トークンを転送することです。
更に詳しく見ていきましょう。
// 1. ステーキング機能を作成する
function stakeTokens(uint _amount) public {
// 2. ステーキングされるトークンが0以上あることを確認
require(_amount > 0, "amount can't be 0");
// 3. 投資家のトークンを TokenFarm.sol に移動させる
daiToken.transferFrom(msg.sender, address(this), _amount);
:
}
ここで最も重要になるのが、transferFrom()関数です。
daiTokenのもととなるスマートコントラクトMockDaiToken.solは他のERC-20トークンと同じようにtransferFrom()関数を保持しています。
transferFrom()関数の中身が気になる人は、MockDaiToken.solの中に定義されているtransferFrom()を見てみてください!
transferFrom()を使用すると、投資家に代わってコントラクト自体(TokenFarm.sol)が、実際に資金を移動させることができるようになります。
msg.senderはSolidity内部の特別な変数です。msgまたはメッセージはSolidity内のグローバル変数で、関数が呼び出されるたびに送信されるメッセージに対応します。senderは関数を呼び出した人を意味します。- 第二引数
address(this)は、アドレス型に変換されたスマートコントラクトそのもの(TokenFarm.sol)です。 - 第三引数は、
msg.senderが移動させるトークンの量amountを意味します。