# masterChef learning

$$f=\frac{sushiPerBlock\times \frac{pool.allocPoint}{totalAllocPoint}}{lpSupply}$$

=>

$$Index(N)=Index(N-1)+\delta N\times \frac{sushiPerBlock}{lpSupply(N-1)} \times\frac{pool.allocPoint}{totalAllocPoint}$$

$$deltaBlocks = block.number - pool.lastRewardBlock$$

$$sushiReward = deltaBlocks sushiPerBlock pool.allocPoint / totalAllocPoint$$

$$pool.accSushiPerShare _b= pool.accSushiPerShare_a + sushiReward / lpSupply$$

## 合约实现

pending reward = user.amount * pool.accSushiPerShare - user.rewardDebt

principalNew = principal * borrowIndexNew / interestIndex;

//masterchef
struct UserInfo {
uint256 amount;
uint256 rewardDebt;
}
//compound
struct BorrowSnapshot {
uint256 principal;
uint256 interestIndex;
}

struct PoolInfo {
uint256 allocPoint; // allocation points assinged to this pool
uint256 lastRewardBlock; //last block number that sushi distributed
uint256 accSushiPerShare; //accumulated sushi per share, mantissa=12
}

SushiToken public sushi;
uint256 public bonusEndBlock;
uint256 public sushiPerBlock;
uint256 public constant BONUS_MULTIPLIER = 10;
IMigratorChef public migrator;
PoolInfo[] public poolInfo;
mapping(uint256 => mapping(address => UserInfo)) public userInfo;
uint256 public totalAllocPoint = 0;
uint256 public startBlock;

1. user related

1. Deposit => deposit LP to get sushi

//用户存款的核心方法,用户存LP，获取sushi收益

function deposit(uint256 _pid, uint256 _amount) public {}
//第一步：根据pid在list中找到对应的pool，保存在storage中
//第二步：根据pid和msg.sender,在userInfo的map中找到用户的在该pid对应的userInfo结构体,保存到storage中
//第三步：最重要的一步：调用updatePool方法，更新池子
//第四步：如果userInfo中的amount>0,它代表的是用户之前在池子中的lp存款数量，根据公式：userinfo.amount * pool.accSushiPerShare - userinfo.rewardDebt计算出应该给用户转账的sushi数量，然后执行sushi的转账
//第五步：把用户的LPtoken转账到该资金池中
//第六步：更新用户的存款：userinfo.amount += amount
//第七步：更新用户的已cliamedSushi：
//userInfo.rewardDebt += userinfo.amount * pool.accSushiPerShare -userinfo.rewardDebt
//= userinfo.amount * pool.accSushiPerShare
2. Withdraw => withdraw LP from Masterchef

//用户提款的核心方法：用户提走LPtoken，同时应该将此时的sushi收益分给用户
function withdraw(uint _pid, uint256 _amount) public {}

//第一步：根据pid在list中找到对应的pool，保存在storage中
//第二步：根据pid和msg.sender地址在map userInfo中找到对应的userinfo，保存在storage中
//第三步：进行判断，用户在池子中存入的amount >= 此次要提出的amount
//第四步：最重要的一步：更新池子状态
//第五步：计算出用户的pendingSushi，根据公式：userinfo.amount * pool.accSushiPerShare - userinfo.rewardDebt
//第六步：把sushi转账给用户
//第七步：更新userinfo.amount数量
//第八步：更新userinfo.rewardDebt数量
//第九步：把lPtoken转账回用户。
3. emergencyWithdraw => withdraw LP from masterchef regradless the rewards

//紧急撤离，看来大多数的protocol里面都涉及到这部分功能，即我不要你的奖励，我只要我的本金安全。

function emergencyWithdraw(uint256 _pid) public {}
//第一步：根据pid在list中找到对应的pool，保存在storage中
//第二步：根据pid和msg.sender地址在map userInfo中找到对应的userinfo，保存在storage中
//第三步：更新userinfo.amount = 0
//第四步：更新userinfo.rewardDebt = 0
//第五步：把lptoken转账给用户，用户的全部
2. pool related

1. massUpdatePools => update all pools

//批量更新所有的池子，简单就是利用一个循环来调用updatePool方法即可
function massUpdatePools() public{}
2. updatePool => update the rewardIndex

//应该是masterchef中最核心的方法，用于更新rewardIndex指数，并且直接把sushi给mint到该池子中，也会mint一部分到dev中
//rewardIndex_b = rewardIndex_a + deltaBlocks * sushiPerBlock * pool.allocPoint / totalAllcoPoint / lpSupply

function updatePool(uint256 _pid) public {}

//第一步：根据pid在list中找到对应的pool，保存成memory
//第二步：判断是否在同一个块中，因为一个块只更新一次。如果在同一个块，则直接返回
//第三步：利用pool.lpToken.balanceOf方法，获取目前lpToken的总数lpSupply
//第四步：如果lpSupply==0，即分母为0，需要特殊考虑，这里更新完blocknumber后直接返回
//第五步：利用getMultiplier方法，根据当前的block.number和pool中记录的lastRewardBlock计算deltaBlocks
//第六步：计算sushiReward，即deltaBlocks * sushiPerBlock * pool.allocPoint / totalAllcoPoint，这里是整个池子在这段区块中的总的reward
//第七步：给DEV地址，mint 10%的sushiReward的sushi
//第八步：给pool地址，mint 这个池子应该得到的sushi
//第九步：计算池子的rewardIndex：rewardIndex_b = rewardIndex_a + sushiReward/ lpSupply
//第十步：更新池子的lastRewardBlock=block.number
3. helper

1. poolLength => return poolInfo.length;
2. getMultiplier => return deltaBlocks
3. pendingSushi => pending sushi for user for pid pools
4. safeSushiTransfer => transfer sushi token
5. Dev => update dev address
4. onlyOwner

2. Set => set allowcation point
3. setMigrator => set migrator
5. Migrate:

1. Migrate

//作用是把一个池子中的LP token转移到另一个池子里，这里的思路是先由合约的owner设定一个migrate合约地址，然后由任何人来调用其migrate方法
function migrate(uint256 _pid) public {}
//第一步：检查migrate合约地址不能为空
//第二步：把对应pid的pool找到，放在storage中
//第三步：拿到对应的pool的lptoken地址
//第四步：获取该lptoken的总余额
//第五步：approve migrate合约
//第六步：调用migrate合约的migrate方法，返回一个新的LP合约地址
//第七步：migrate后的数量与之前一致
//第八步：更新pool的lptoken地址

• 发表于 2021-11-27 18:52
• 阅读 ( 898 )
• 学分 ( 51 )
• 分类：智能合约

bixia1994

39 篇文章, 925 学分