Diff
checker
Texto
Texto
Imagens
Documentos
Excel
Pastas
Legal
Enterprise
Aplicativo para desktop
Preços
Fazer login
Baixar o Diffchecker Desktop
Comparar texto
Encontre a diferença entre dois arquivos de texto
Ferramentas
Histórico
Editor live
Recolher inalteradas
Sem quebra de linha
Layout
Dividido
Unificado
Nível de detalhe
Inteligente
Palavra
Caractere
Realce de sintaxe
Escolher sintaxe
Ignorar
Transformar texto
Ir à primeira mudança
Editar entrada
Diffchecker Desktop
A maneira mais segura de usar o Diffchecker. Obtenha o aplicativo Diffchecker Desktop: seus diffs nunca saem do seu computador!
Obter Desktop
StableXSwap Code versus SushiChef.sol
Criado
há 6 anos
O diff nunca expira
Limpar
Exportar
Compartilhar
Explicar
94 remoções
Linhas
Total
Removido
Caracteres
Total
Removido
Para continuar usando este recurso, atualize para
Diff
checker
Pro
Ver preços
263 linhas
Copiar tudo
92 adições
Linhas
Total
Adicionado
Caracteres
Total
Adicionado
Para continuar usando este recurso, atualize para
Diff
checker
Pro
Ver preços
262 linhas
Copiar tudo
pragma solidity 0.6.12;
pragma solidity 0.6.12;
Copiar
Copiado
Copiar
Copiado
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/utils/EnumerableSet.sol";
import "@openzeppelin/contracts/utils/EnumerableSet.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
Copiar
Copiado
Copiar
Copiado
import "./
SushiToken
.sol";
import "./
StaxToken
.sol";
interface IMigratorChef {
interface IMigratorChef {
Copiar
Copiado
Copiar
Copiado
// Perform LP token migration from legacy
UniswapV2
to
SushiSwap
.
// Perform LP token migration from legacy
PancakeSwap
to
StableX Swap
.
// Take the current LP token address and return the new LP token address.
// Take the current LP token address and return the new LP token address.
// Migrator should have full access to the caller's LP token.
// Migrator should have full access to the caller's LP token.
// Return the new LP token address.
// Return the new LP token address.
//
//
Copiar
Copiado
Copiar
Copiado
// XXX Migrator must have allowance access to
UniswapV2
LP tokens.
// XXX Migrator must have allowance access to
PancakeSwap
LP tokens.
//
SushiSwap
must mint EXACTLY the same amount of
SushiSwap
LP tokens or
//
CakeSwap
must mint EXACTLY the same amount of
CakeSwap
LP tokens or
// else something bad will happen. Traditional
UniswapV2
does not
// else something bad will happen. Traditional
PancakeSwap
does not
// do that so be careful!
// do that so be careful!
Copiar
Copiado
Copiar
Copiado
function migrate(I
ERC
20 token) external returns (I
ERC
20);
function migrate(I
BEP
20 token) external returns (I
BEP
20);
}
}
Copiar
Copiado
Copiar
Copiado
//
MasterChef
is the master of
Sushi
. He can make
Sushi
and he is a fair guy.
//
SuperChef
is the master of
StableX
. He can make
STAX
and he is a fair guy.
//
//
// Note that it's ownable and the owner wields tremendous power. The ownership
// Note that it's ownable and the owner wields tremendous power. The ownership
Copiar
Copiado
Copiar
Copiado
// will be transferred to a governance smart contract once
SUSHI
is sufficiently
// will be transferred to a governance smart contract once
STAX
is sufficiently
// distributed and the community can show to govern itself.
// distributed and the community can show to govern itself.
//
//
// Have fun reading it. Hopefully it's bug-free. God bless.
// Have fun reading it. Hopefully it's bug-free. God bless.
Copiar
Copiado
Copiar
Copiado
contract
MasterChef
is Ownable {
contract
SuperChef
is Ownable {
using SafeMath for uint256;
using SafeMath for uint256;
using SafeERC20 for IERC20;
using SafeERC20 for IERC20;
// Info of each user.
// Info of each user.
struct UserInfo {
struct UserInfo {
uint256 amount; // How many LP tokens the user has provided.
uint256 amount; // How many LP tokens the user has provided.
uint256 rewardDebt; // Reward debt. See explanation below.
uint256 rewardDebt; // Reward debt. See explanation below.
//
//
Copiar
Copiado
Copiar
Copiado
// We do some fancy math here. Basically, any point in time, the amount of
SUSHIs
// We do some fancy math here. Basically, any point in time, the amount of
STAXs
// entitled to a user but is pending to be distributed is:
// entitled to a user but is pending to be distributed is:
//
//
Copiar
Copiado
Copiar
Copiado
// pending reward = (user.amount * pool.accS
ushi
PerShare) - user.rewardDebt
// pending reward = (user.amount * pool.accS
tax
PerShare) - user.rewardDebt
//
//
// Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:
// Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:
Copiar
Copiado
Copiar
Copiado
// 1. The pool's `accS
ushi
PerShare` (and `lastRewardBlock`) gets updated.
// 1. The pool's `accS
tax
PerShare` (and `lastRewardBlock`) gets updated.
// 2. User receives the pending reward sent to his/her address.
// 2. User receives the pending reward sent to his/her address.
// 3. User's `amount` gets updated.
// 3. User's `amount` gets updated.
// 4. User's `rewardDebt` gets updated.
// 4. User's `rewardDebt` gets updated.
}
}
// Info of each pool.
// Info of each pool.
struct PoolInfo {
struct PoolInfo {
IERC20 lpToken; // Address of LP token contract.
IERC20 lpToken; // Address of LP token contract.
Copiar
Copiado
Copiar
Copiado
uint256 allocPoint; // How many allocation points assigned to this pool.
SUSHIs to distribute per block.
uint256 allocPoint; // How many allocation points assigned to this pool.
uint256 lastRewardBlock; // Last block number that
SUSHIs
distribution occurs.
uint256 lastRewardBlock; // Last block number that
STAXs
distribution occurs.
uint256 accS
ushi
PerShare; // Accumulated
SUSHIs
per share, times 1e12. See below.
uint256 accS
tax
PerShare; // Accumulated
STAXs
per share, times 1e12. See below.
}
}
Copiar
Copiado
Copiar
Copiado
// The
SUSHI
TOKEN!
// The
STAX
TOKEN!
SushiToken
public
sushi
;
StaxToken
public
stax
;
// Dev address.
// Dev address.
address public devaddr;
address public devaddr;
Copiar
Copiado
Copiar
Copiado
// Block number when bonus
SUSHI
period ends.
// Block number when bonus
STAX
period ends.
uint256 public bonusEndBlock;
uint256 public bonusEndBlock;
Copiar
Copiado
Copiar
Copiado
//
SUSHI
tokens created per block.
//
STAX
tokens created per block.
uint256 public s
ushi
PerBlock;
uint256 public s
tax
PerBlock;
// Bonus muliplier for early
sushi
makers.
// Bonus muliplier for early
stax
makers.
uint256 public constant BONUS_MULTIPLIER = 10;
uint256 public constant BONUS_MULTIPLIER = 10;
// The migrator contract. It has a lot of power. Can only be set through governance (owner).
// The migrator contract. It has a lot of power. Can only be set through governance (owner).
IMigratorChef public migrator;
IMigratorChef public migrator;
// Info of each pool.
// Info of each pool.
PoolInfo[] public poolInfo;
PoolInfo[] public poolInfo;
// Info of each user that stakes LP tokens.
// Info of each user that stakes LP tokens.
mapping (uint256 => mapping (address => UserInfo)) public userInfo;
mapping (uint256 => mapping (address => UserInfo)) public userInfo;
Copiar
Copiado
Copiar
Copiado
// Total allocation poi
nt
s. Must be the sum of all allocation points in all pools.
// Total allocation poi
tn
s. Must be the sum of all allocation points in all pools.
uint256 public totalAllocPoint = 0;
uint256 public totalAllocPoint = 0;
Copiar
Copiado
Copiar
Copiado
// The block number when
SUSHI
mining starts.
// The block number when
STAX
mining starts.
uint256 public startBlock;
uint256 public startBlock;
event Deposit(address indexed user, uint256 indexed pid, uint256 amount);
event Deposit(address indexed user, uint256 indexed pid, uint256 amount);
event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);
event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);
event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount);
event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount);
constructor(
constructor(
Copiar
Copiado
Copiar
Copiado
SushiToken _sushi
,
StaxToken _stax
,
address _devaddr,
address _devaddr,
Copiar
Copiado
Copiar
Copiado
uint256 _s
ushi
PerBlock,
uint256 _s
tax
PerBlock,
uint256 _startBlock,
uint256 _startBlock,
uint256 _bonusEndBlock
uint256 _bonusEndBlock
) public {
) public {
Copiar
Copiado
Copiar
Copiado
sushi
= _
sushi
;
stax
= _
stax
;
devaddr = _devaddr;
devaddr = _devaddr;
Copiar
Copiado
Copiar
Copiado
s
ushi
PerBlock = _s
ushi
PerBlock;
s
tax
PerBlock = _s
tax
PerBlock;
bonusEndBlock = _bonusEndBlock;
bonusEndBlock = _bonusEndBlock;
startBlock = _startBlock;
startBlock = _startBlock;
}
}
Copiar
Copiado
Copiar
Copiado
Text moved with changes from lines 130-146 (99.6% similarity)
// Set the migrator contract. Can only be called by the owner.
function setMigrator(IMigratorChef _migrator) public onlyOwner {
migrator = _migrator;
}
// Migrate lp token to another lp contract. Can be called by anyone. We trust that migrator contract is good.
function migrate(uint256 _pid) public {
require(address(migrator) != address(0), "migrate: no migrator");
PoolInfo storage pool = poolInfo[_pid];
IBEP20 lpToken = pool.lpToken;
uint256 bal = lpToken.balanceOf(address(this));
lpToken.safeApprove(address(migrator), bal);
IBEP20 newLpToken = migrator.migrate(lpToken);
require(bal == newLpToken.balanceOf(address(this)), "migrate: bad");
pool.lpToken = newLpToken;
}
function poolLength() external view returns (uint256) {
function poolLength() external view returns (uint256) {
return poolInfo.length;
return poolInfo.length;
}
}
// Add a new lp to the pool. Can only be called by the owner.
// Add a new lp to the pool. Can only be called by the owner.
// XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do.
// XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do.
function add(uint256 _allocPoint, IERC20 _lpToken, bool _withUpdate) public onlyOwner {
function add(uint256 _allocPoint, IERC20 _lpToken, bool _withUpdate) public onlyOwner {
if (_withUpdate) {
if (_withUpdate) {
massUpdatePools();
massUpdatePools();
}
}
uint256 lastRewardBlock = block.number > startBlock ? block.number : startBlock;
uint256 lastRewardBlock = block.number > startBlock ? block.number : startBlock;
totalAllocPoint = totalAllocPoint.add(_allocPoint);
totalAllocPoint = totalAllocPoint.add(_allocPoint);
poolInfo.push(PoolInfo({
poolInfo.push(PoolInfo({
lpToken: _lpToken,
lpToken: _lpToken,
allocPoint: _allocPoint,
allocPoint: _allocPoint,
lastRewardBlock: lastRewardBlock,
lastRewardBlock: lastRewardBlock,
Copiar
Copiado
Copiar
Copiado
accS
ushi
PerShare: 0
accS
tax
PerShare: 0
}));
}));
}
}
Copiar
Copiado
Copiar
Copiado
// Update the given pool's
SUSHI
allocation point. Can only be called by the owner.
// Update the given pool's
STAX
allocation point. Can only be called by the owner.
function set(uint256 _pid, uint256 _allocPoint, bool _withUpdate) public onlyOwner {
function set(uint256 _pid, uint256 _allocPoint, bool _withUpdate) public onlyOwner {
if (_withUpdate) {
if (_withUpdate) {
massUpdatePools();
massUpdatePools();
}
}
totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint);
totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint);
poolInfo[_pid].allocPoint = _allocPoint;
poolInfo[_pid].allocPoint = _allocPoint;
}
}
Copiar
Copiado
Copiar
Copiado
Text moved with changes to lines 100-116 (99.6% similarity)
// Set the migrator contract. Can only be called by the owner.
function setMigrator(IMigratorChef _migrator) public onlyOwner {
migrator = _migrator;
}
// Migrate lp token to another lp contract. Can be called by anyone. We trust that migrator contract is good.
function migrate(uint256 _pid) public {
require(address(migrator) != address(0), "migrate: no migrator");
PoolInfo storage pool = poolInfo[_pid];
IERC20 lpToken = pool.lpToken;
uint256 bal = lpToken.balanceOf(address(this));
lpToken.safeApprove(address(migrator), bal);
IERC20 newLpToken = migrator.migrate(lpToken);
require(bal == newLpToken.balanceOf(address(this)), "migrate: bad");
pool.lpToken = newLpToken;
}
// Return reward multiplier over the given _from to _to block.
// Return reward multiplier over the given _from to _to block.
function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256) {
function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256) {
if (_to <= bonusEndBlock) {
if (_to <= bonusEndBlock) {
return _to.sub(_from).mul(BONUS_MULTIPLIER);
return _to.sub(_from).mul(BONUS_MULTIPLIER);
} else if (_from >= bonusEndBlock) {
} else if (_from >= bonusEndBlock) {
return _to.sub(_from);
return _to.sub(_from);
} else {
} else {
return bonusEndBlock.sub(_from).mul(BONUS_MULTIPLIER).add(
return bonusEndBlock.sub(_from).mul(BONUS_MULTIPLIER).add(
_to.sub(bonusEndBlock)
_to.sub(bonusEndBlock)
);
);
}
}
}
}
Copiar
Copiado
Copiar
Copiado
// View function to see pending
SUSHIs
on frontend.
// View function to see pending
STAXs
on frontend.
function pendingS
ushi
(uint256 _pid, address _user) external view returns (uint256) {
function pendingS
tax
(uint256 _pid, address _user) external view returns (uint256) {
PoolInfo storage pool = poolInfo[_pid];
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][_user];
UserInfo storage user = userInfo[_pid][_user];
Copiar
Copiado
Copiar
Copiado
uint256 accS
ushi
PerShare = pool.accS
ushi
PerShare;
uint256 accS
tax
PerShare = pool.accS
tax
PerShare;
uint256 lpSupply = pool.lpToken.balanceOf(address(this));
uint256 lpSupply = pool.lpToken.balanceOf(address(this));
if (block.number > pool.lastRewardBlock && lpSupply != 0) {
if (block.number > pool.lastRewardBlock && lpSupply != 0) {
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);
Copiar
Copiado
Copiar
Copiado
uint256 s
ushi
Reward = multiplier.mul(s
ushi
PerBlock).mul(pool.allocPoint).div(totalAllocPoint);
uint256 s
tax
Reward = multiplier.mul(s
tax
PerBlock).mul(pool.allocPoint).div(totalAllocPoint);
accS
ushi
PerShare = accS
ushi
PerShare.add(s
ushi
Reward.mul(1e12).div(lpSupply));
accS
tax
PerShare = accS
tax
PerShare.add(s
tax
Reward.mul(1e12).div(lpSupply));
}
}
Copiar
Copiado
Copiar
Copiado
return user.amount.mul(accS
ushi
PerShare).div(1e12).sub(user.rewardDebt);
return user.amount.mul(accS
tax
PerShare).div(1e12).sub(user.rewardDebt);
}
}
// Update reward variables for all pools. Be careful of gas spending!
// Update reward variables for all pools. Be careful of gas spending!
function massUpdatePools() public {
function massUpdatePools() public {
uint256 length = poolInfo.length;
uint256 length = poolInfo.length;
for (uint256 pid = 0; pid < length; ++pid) {
for (uint256 pid = 0; pid < length; ++pid) {
updatePool(pid);
updatePool(pid);
}
}
}
}
// Update reward variables of the given pool to be up-to-date.
// Update reward variables of the given pool to be up-to-date.
function updatePool(uint256 _pid) public {
function updatePool(uint256 _pid) public {
PoolInfo storage pool = poolInfo[_pid];
PoolInfo storage pool = poolInfo[_pid];
if (block.number <= pool.lastRewardBlock) {
if (block.number <= pool.lastRewardBlock) {
return;
return;
}
}
uint256 lpSupply = pool.lpToken.balanceOf(address(this));
uint256 lpSupply = pool.lpToken.balanceOf(address(this));
if (lpSupply == 0) {
if (lpSupply == 0) {
pool.lastRewardBlock = block.number;
pool.lastRewardBlock = block.number;
return;
return;
}
}
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);
Copiar
Copiado
Copiar
Copiado
uint256 s
ushi
Reward = multiplier.mul(s
ushi
PerBlock).mul(pool.allocPoint).div(totalAllocPoint);
uint256 s
tax
Reward = multiplier.mul(s
tax
PerBlock).mul(pool.allocPoint).div(totalAllocPoint);
sushi
.mint(devaddr, s
ushi
Reward.div(
10
));
stax
.mint(devaddr, s
tax
Reward.div(
8
));
sushi
.mint(address(this), s
ushi
Reward);
stax
.mint(address(this), s
tax
Reward);
pool.accS
ushi
PerShare = pool.accS
ushi
PerShare.add(s
ushi
Reward.mul(1e12).div(lpSupply));
pool.accS
tax
PerShare = pool.accS
tax
PerShare.add(s
tax
Reward.mul(1e12).div(lpSupply));
pool.lastRewardBlock = block.number;
pool.lastRewardBlock = block.number;
}
}
Copiar
Copiado
Copiar
Copiado
// Deposit LP tokens to
MasterChef
for
SUSHI
allocation.
// Deposit LP tokens to
SuperChef
for
STAX
allocation.
function deposit(uint256 _pid, uint256 _amount) public {
function deposit(uint256 _pid, uint256 _amount) public {
PoolInfo storage pool = poolInfo[_pid];
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
UserInfo storage user = userInfo[_pid][msg.sender];
updatePool(_pid);
updatePool(_pid);
if (user.amount > 0) {
if (user.amount > 0) {
Copiar
Copiado
Copiar
Copiado
uint256 pending = user.amount.mul(pool.accS
ushi
PerShare).div(1e12).sub(user.rewardDebt);
uint256 pending = user.amount.mul(pool.accS
tax
PerShare).div(1e12).sub(user.rewardDebt);
if(pending > 0) {
if(pending > 0) {
Copiar
Copiado
Copiar
Copiado
safeS
ushi
Transfer(msg.sender, pending);
safeS
tax
Transfer(msg.sender, pending);
}
}
}
}
if(_amount > 0) {
if(_amount > 0) {
pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount);
pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount);
user.amount = user.amount.add(_amount);
user.amount = user.amount.add(_amount);
}
}
Copiar
Copiado
Copiar
Copiado
user.rewardDebt = user.amount.mul(pool.accS
ushi
PerShare).div(1e12);
user.rewardDebt = user.amount.mul(pool.accS
tax
PerShare).div(1e12);
emit Deposit(msg.sender, _pid, _amount);
emit Deposit(msg.sender, _pid, _amount);
}
}
Copiar
Copiado
Copiar
Copiado
// Withdraw LP tokens from
MasterChef
.
// Withdraw LP tokens from
SuperChef
.
function withdraw(uint256 _pid, uint256 _amount) public {
function withdraw(uint256 _pid, uint256 _amount) public {
PoolInfo storage pool = poolInfo[_pid];
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
UserInfo storage user = userInfo[_pid][msg.sender];
require(user.amount >= _amount, "withdraw: not good");
require(user.amount >= _amount, "withdraw: not good");
updatePool(_pid);
updatePool(_pid);
Copiar
Copiado
Copiar
Copiado
uint256 pending = user.amount.mul(pool.accS
ushi
PerShare).div(1e12).sub(user.rewardDebt);
uint256 pending = user.amount.mul(pool.accS
tax
PerShare).div(1e12).sub(user.rewardDebt);
if(pending > 0) {
if(pending > 0) {
Copiar
Copiado
Copiar
Copiado
safeS
ushi
Transfer(msg.sender, pending);
safeS
tax
Transfer(msg.sender, pending);
}
}
if(_amount > 0) {
if(_amount > 0) {
user.amount = user.amount.sub(_amount);
user.amount = user.amount.sub(_amount);
pool.lpToken.safeTransfer(address(msg.sender), _amount);
pool.lpToken.safeTransfer(address(msg.sender), _amount);
}
}
Copiar
Copiado
Copiar
Copiado
user.rewardDebt = user.amount.mul(pool.accS
ushi
PerShare).div(1e12);
user.rewardDebt = user.amount.mul(pool.accS
tax
PerShare).div(1e12);
emit Withdraw(msg.sender, _pid, _amount);
emit Withdraw(msg.sender, _pid, _amount);
}
}
// Withdraw without caring about rewards. EMERGENCY ONLY.
// Withdraw without caring about rewards. EMERGENCY ONLY.
function emergencyWithdraw(uint256 _pid) public {
function emergencyWithdraw(uint256 _pid) public {
PoolInfo storage pool = poolInfo[_pid];
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
UserInfo storage user = userInfo[_pid][msg.sender];
pool.lpToken.safeTransfer(address(msg.sender), user.amount);
pool.lpToken.safeTransfer(address(msg.sender), user.amount);
emit EmergencyWithdraw(msg.sender, _pid, user.amount);
emit EmergencyWithdraw(msg.sender, _pid, user.amount);
user.amount = 0;
user.amount = 0;
user.rewardDebt = 0;
user.rewardDebt = 0;
}
}
Copiar
Copiado
Copiar
Copiado
// Safe
sushi
transfer function, just in case if rounding error causes pool to not have enough
SUSHIs
.
// Safe
stax
transfer function, just in case if rounding error causes pool to not have enough
STAXs
.
function safeS
ushi
Transfer(address _to, uint256 _amount) internal {
function safeS
tax
Transfer(address _to, uint256 _amount) internal {
uint256
sushiBal
=
sushi
.balanceOf(address(this));
uint256
staxBal
=
stax
.balanceOf(address(this));
if (_amount >
sushiBal
) {
if (_amount >
staxBal
) {
sushi
.transfer(_to,
sushiBal
);
stax
.transfer(_to,
staxBal
);
} else {
} else {
Copiar
Copiado
Copiar
Copiado
sushi
.transfer(_to, _amount);
stax
.transfer(_to, _amount);
}
}
}
}
// Update dev address by the previous dev.
// Update dev address by the previous dev.
function dev(address _devaddr) public {
function dev(address _devaddr) public {
require(msg.sender == devaddr, "dev: wut?");
require(msg.sender == devaddr, "dev: wut?");
devaddr = _devaddr;
devaddr = _devaddr;
}
}
}
}
Diferenças salvas
Texto original
Abrir arquivo
pragma solidity 0.6.12; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import "@openzeppelin/contracts/utils/EnumerableSet.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "./SushiToken.sol"; interface IMigratorChef { // Perform LP token migration from legacy UniswapV2 to SushiSwap. // Take the current LP token address and return the new LP token address. // Migrator should have full access to the caller's LP token. // Return the new LP token address. // // XXX Migrator must have allowance access to UniswapV2 LP tokens. // SushiSwap must mint EXACTLY the same amount of SushiSwap LP tokens or // else something bad will happen. Traditional UniswapV2 does not // do that so be careful! function migrate(IERC20 token) external returns (IERC20); } // MasterChef is the master of Sushi. He can make Sushi and he is a fair guy. // // Note that it's ownable and the owner wields tremendous power. The ownership // will be transferred to a governance smart contract once SUSHI is sufficiently // distributed and the community can show to govern itself. // // Have fun reading it. Hopefully it's bug-free. God bless. contract MasterChef is Ownable { using SafeMath for uint256; using SafeERC20 for IERC20; // Info of each user. struct UserInfo { uint256 amount; // How many LP tokens the user has provided. uint256 rewardDebt; // Reward debt. See explanation below. // // We do some fancy math here. Basically, any point in time, the amount of SUSHIs // entitled to a user but is pending to be distributed is: // // pending reward = (user.amount * pool.accSushiPerShare) - user.rewardDebt // // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: // 1. The pool's `accSushiPerShare` (and `lastRewardBlock`) gets updated. // 2. User receives the pending reward sent to his/her address. // 3. User's `amount` gets updated. // 4. User's `rewardDebt` gets updated. } // Info of each pool. struct PoolInfo { IERC20 lpToken; // Address of LP token contract. uint256 allocPoint; // How many allocation points assigned to this pool. SUSHIs to distribute per block. uint256 lastRewardBlock; // Last block number that SUSHIs distribution occurs. uint256 accSushiPerShare; // Accumulated SUSHIs per share, times 1e12. See below. } // The SUSHI TOKEN! SushiToken public sushi; // Dev address. address public devaddr; // Block number when bonus SUSHI period ends. uint256 public bonusEndBlock; // SUSHI tokens created per block. uint256 public sushiPerBlock; // Bonus muliplier for early sushi makers. uint256 public constant BONUS_MULTIPLIER = 10; // The migrator contract. It has a lot of power. Can only be set through governance (owner). IMigratorChef public migrator; // Info of each pool. PoolInfo[] public poolInfo; // Info of each user that stakes LP tokens. mapping (uint256 => mapping (address => UserInfo)) public userInfo; // Total allocation points. Must be the sum of all allocation points in all pools. uint256 public totalAllocPoint = 0; // The block number when SUSHI mining starts. uint256 public startBlock; event Deposit(address indexed user, uint256 indexed pid, uint256 amount); event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount); constructor( SushiToken _sushi, address _devaddr, uint256 _sushiPerBlock, uint256 _startBlock, uint256 _bonusEndBlock ) public { sushi = _sushi; devaddr = _devaddr; sushiPerBlock = _sushiPerBlock; bonusEndBlock = _bonusEndBlock; startBlock = _startBlock; } function poolLength() external view returns (uint256) { return poolInfo.length; } // Add a new lp to the pool. Can only be called by the owner. // XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do. function add(uint256 _allocPoint, IERC20 _lpToken, bool _withUpdate) public onlyOwner { if (_withUpdate) { massUpdatePools(); } uint256 lastRewardBlock = block.number > startBlock ? block.number : startBlock; totalAllocPoint = totalAllocPoint.add(_allocPoint); poolInfo.push(PoolInfo({ lpToken: _lpToken, allocPoint: _allocPoint, lastRewardBlock: lastRewardBlock, accSushiPerShare: 0 })); } // Update the given pool's SUSHI allocation point. Can only be called by the owner. function set(uint256 _pid, uint256 _allocPoint, bool _withUpdate) public onlyOwner { if (_withUpdate) { massUpdatePools(); } totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint); poolInfo[_pid].allocPoint = _allocPoint; } // Set the migrator contract. Can only be called by the owner. function setMigrator(IMigratorChef _migrator) public onlyOwner { migrator = _migrator; } // Migrate lp token to another lp contract. Can be called by anyone. We trust that migrator contract is good. function migrate(uint256 _pid) public { require(address(migrator) != address(0), "migrate: no migrator"); PoolInfo storage pool = poolInfo[_pid]; IERC20 lpToken = pool.lpToken; uint256 bal = lpToken.balanceOf(address(this)); lpToken.safeApprove(address(migrator), bal); IERC20 newLpToken = migrator.migrate(lpToken); require(bal == newLpToken.balanceOf(address(this)), "migrate: bad"); pool.lpToken = newLpToken; } // Return reward multiplier over the given _from to _to block. function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256) { if (_to <= bonusEndBlock) { return _to.sub(_from).mul(BONUS_MULTIPLIER); } else if (_from >= bonusEndBlock) { return _to.sub(_from); } else { return bonusEndBlock.sub(_from).mul(BONUS_MULTIPLIER).add( _to.sub(bonusEndBlock) ); } } // View function to see pending SUSHIs on frontend. function pendingSushi(uint256 _pid, address _user) external view returns (uint256) { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][_user]; uint256 accSushiPerShare = pool.accSushiPerShare; uint256 lpSupply = pool.lpToken.balanceOf(address(this)); if (block.number > pool.lastRewardBlock && lpSupply != 0) { uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number); uint256 sushiReward = multiplier.mul(sushiPerBlock).mul(pool.allocPoint).div(totalAllocPoint); accSushiPerShare = accSushiPerShare.add(sushiReward.mul(1e12).div(lpSupply)); } return user.amount.mul(accSushiPerShare).div(1e12).sub(user.rewardDebt); } // Update reward variables for all pools. Be careful of gas spending! function massUpdatePools() public { uint256 length = poolInfo.length; for (uint256 pid = 0; pid < length; ++pid) { updatePool(pid); } } // Update reward variables of the given pool to be up-to-date. function updatePool(uint256 _pid) public { PoolInfo storage pool = poolInfo[_pid]; if (block.number <= pool.lastRewardBlock) { return; } uint256 lpSupply = pool.lpToken.balanceOf(address(this)); if (lpSupply == 0) { pool.lastRewardBlock = block.number; return; } uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number); uint256 sushiReward = multiplier.mul(sushiPerBlock).mul(pool.allocPoint).div(totalAllocPoint); sushi.mint(devaddr, sushiReward.div(10)); sushi.mint(address(this), sushiReward); pool.accSushiPerShare = pool.accSushiPerShare.add(sushiReward.mul(1e12).div(lpSupply)); pool.lastRewardBlock = block.number; } // Deposit LP tokens to MasterChef for SUSHI allocation. function deposit(uint256 _pid, uint256 _amount) public { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; updatePool(_pid); if (user.amount > 0) { uint256 pending = user.amount.mul(pool.accSushiPerShare).div(1e12).sub(user.rewardDebt); if(pending > 0) { safeSushiTransfer(msg.sender, pending); } } if(_amount > 0) { pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount); user.amount = user.amount.add(_amount); } user.rewardDebt = user.amount.mul(pool.accSushiPerShare).div(1e12); emit Deposit(msg.sender, _pid, _amount); } // Withdraw LP tokens from MasterChef. function withdraw(uint256 _pid, uint256 _amount) public { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; require(user.amount >= _amount, "withdraw: not good"); updatePool(_pid); uint256 pending = user.amount.mul(pool.accSushiPerShare).div(1e12).sub(user.rewardDebt); if(pending > 0) { safeSushiTransfer(msg.sender, pending); } if(_amount > 0) { user.amount = user.amount.sub(_amount); pool.lpToken.safeTransfer(address(msg.sender), _amount); } user.rewardDebt = user.amount.mul(pool.accSushiPerShare).div(1e12); emit Withdraw(msg.sender, _pid, _amount); } // Withdraw without caring about rewards. EMERGENCY ONLY. function emergencyWithdraw(uint256 _pid) public { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; pool.lpToken.safeTransfer(address(msg.sender), user.amount); emit EmergencyWithdraw(msg.sender, _pid, user.amount); user.amount = 0; user.rewardDebt = 0; } // Safe sushi transfer function, just in case if rounding error causes pool to not have enough SUSHIs. function safeSushiTransfer(address _to, uint256 _amount) internal { uint256 sushiBal = sushi.balanceOf(address(this)); if (_amount > sushiBal) { sushi.transfer(_to, sushiBal); } else { sushi.transfer(_to, _amount); } } // Update dev address by the previous dev. function dev(address _devaddr) public { require(msg.sender == devaddr, "dev: wut?"); devaddr = _devaddr; } }
Texto alterado
Abrir arquivo
pragma solidity 0.6.12; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import "@openzeppelin/contracts/utils/EnumerableSet.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "./StaxToken.sol"; interface IMigratorChef { // Perform LP token migration from legacy PancakeSwap to StableX Swap. // Take the current LP token address and return the new LP token address. // Migrator should have full access to the caller's LP token. // Return the new LP token address. // // XXX Migrator must have allowance access to PancakeSwap LP tokens. // CakeSwap must mint EXACTLY the same amount of CakeSwap LP tokens or // else something bad will happen. Traditional PancakeSwap does not // do that so be careful! function migrate(IBEP20 token) external returns (IBEP20); } // SuperChef is the master of StableX. He can make STAX and he is a fair guy. // // Note that it's ownable and the owner wields tremendous power. The ownership // will be transferred to a governance smart contract once STAX is sufficiently // distributed and the community can show to govern itself. // // Have fun reading it. Hopefully it's bug-free. God bless. contract SuperChef is Ownable { using SafeMath for uint256; using SafeERC20 for IERC20; // Info of each user. struct UserInfo { uint256 amount; // How many LP tokens the user has provided. uint256 rewardDebt; // Reward debt. See explanation below. // // We do some fancy math here. Basically, any point in time, the amount of STAXs // entitled to a user but is pending to be distributed is: // // pending reward = (user.amount * pool.accStaxPerShare) - user.rewardDebt // // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: // 1. The pool's `accStaxPerShare` (and `lastRewardBlock`) gets updated. // 2. User receives the pending reward sent to his/her address. // 3. User's `amount` gets updated. // 4. User's `rewardDebt` gets updated. } // Info of each pool. struct PoolInfo { IERC20 lpToken; // Address of LP token contract. uint256 allocPoint; // How many allocation points assigned to this pool. uint256 lastRewardBlock; // Last block number that STAXs distribution occurs. uint256 accStaxPerShare; // Accumulated STAXs per share, times 1e12. See below. } // The STAX TOKEN! StaxToken public stax; // Dev address. address public devaddr; // Block number when bonus STAX period ends. uint256 public bonusEndBlock; // STAX tokens created per block. uint256 public staxPerBlock; // Bonus muliplier for early stax makers. uint256 public constant BONUS_MULTIPLIER = 10; // The migrator contract. It has a lot of power. Can only be set through governance (owner). IMigratorChef public migrator; // Info of each pool. PoolInfo[] public poolInfo; // Info of each user that stakes LP tokens. mapping (uint256 => mapping (address => UserInfo)) public userInfo; // Total allocation poitns. Must be the sum of all allocation points in all pools. uint256 public totalAllocPoint = 0; // The block number when STAX mining starts. uint256 public startBlock; event Deposit(address indexed user, uint256 indexed pid, uint256 amount); event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount); constructor( StaxToken _stax, address _devaddr, uint256 _staxPerBlock, uint256 _startBlock, uint256 _bonusEndBlock ) public { stax = _stax; devaddr = _devaddr; staxPerBlock = _staxPerBlock; bonusEndBlock = _bonusEndBlock; startBlock = _startBlock; } // Set the migrator contract. Can only be called by the owner. function setMigrator(IMigratorChef _migrator) public onlyOwner { migrator = _migrator; } // Migrate lp token to another lp contract. Can be called by anyone. We trust that migrator contract is good. function migrate(uint256 _pid) public { require(address(migrator) != address(0), "migrate: no migrator"); PoolInfo storage pool = poolInfo[_pid]; IBEP20 lpToken = pool.lpToken; uint256 bal = lpToken.balanceOf(address(this)); lpToken.safeApprove(address(migrator), bal); IBEP20 newLpToken = migrator.migrate(lpToken); require(bal == newLpToken.balanceOf(address(this)), "migrate: bad"); pool.lpToken = newLpToken; } function poolLength() external view returns (uint256) { return poolInfo.length; } // Add a new lp to the pool. Can only be called by the owner. // XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do. function add(uint256 _allocPoint, IERC20 _lpToken, bool _withUpdate) public onlyOwner { if (_withUpdate) { massUpdatePools(); } uint256 lastRewardBlock = block.number > startBlock ? block.number : startBlock; totalAllocPoint = totalAllocPoint.add(_allocPoint); poolInfo.push(PoolInfo({ lpToken: _lpToken, allocPoint: _allocPoint, lastRewardBlock: lastRewardBlock, accStaxPerShare: 0 })); } // Update the given pool's STAX allocation point. Can only be called by the owner. function set(uint256 _pid, uint256 _allocPoint, bool _withUpdate) public onlyOwner { if (_withUpdate) { massUpdatePools(); } totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint); poolInfo[_pid].allocPoint = _allocPoint; } // Return reward multiplier over the given _from to _to block. function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256) { if (_to <= bonusEndBlock) { return _to.sub(_from).mul(BONUS_MULTIPLIER); } else if (_from >= bonusEndBlock) { return _to.sub(_from); } else { return bonusEndBlock.sub(_from).mul(BONUS_MULTIPLIER).add( _to.sub(bonusEndBlock) ); } } // View function to see pending STAXs on frontend. function pendingStax(uint256 _pid, address _user) external view returns (uint256) { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][_user]; uint256 accStaxPerShare = pool.accStaxPerShare; uint256 lpSupply = pool.lpToken.balanceOf(address(this)); if (block.number > pool.lastRewardBlock && lpSupply != 0) { uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number); uint256 staxReward = multiplier.mul(staxPerBlock).mul(pool.allocPoint).div(totalAllocPoint); accStaxPerShare = accStaxPerShare.add(staxReward.mul(1e12).div(lpSupply)); } return user.amount.mul(accStaxPerShare).div(1e12).sub(user.rewardDebt); } // Update reward variables for all pools. Be careful of gas spending! function massUpdatePools() public { uint256 length = poolInfo.length; for (uint256 pid = 0; pid < length; ++pid) { updatePool(pid); } } // Update reward variables of the given pool to be up-to-date. function updatePool(uint256 _pid) public { PoolInfo storage pool = poolInfo[_pid]; if (block.number <= pool.lastRewardBlock) { return; } uint256 lpSupply = pool.lpToken.balanceOf(address(this)); if (lpSupply == 0) { pool.lastRewardBlock = block.number; return; } uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number); uint256 staxReward = multiplier.mul(staxPerBlock).mul(pool.allocPoint).div(totalAllocPoint); stax.mint(devaddr, staxReward.div(8)); stax.mint(address(this), staxReward); pool.accStaxPerShare = pool.accStaxPerShare.add(staxReward.mul(1e12).div(lpSupply)); pool.lastRewardBlock = block.number; } // Deposit LP tokens to SuperChef for STAX allocation. function deposit(uint256 _pid, uint256 _amount) public { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; updatePool(_pid); if (user.amount > 0) { uint256 pending = user.amount.mul(pool.accStaxPerShare).div(1e12).sub(user.rewardDebt); if(pending > 0) { safeStaxTransfer(msg.sender, pending); } } if(_amount > 0) { pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount); user.amount = user.amount.add(_amount); } user.rewardDebt = user.amount.mul(pool.accStaxPerShare).div(1e12); emit Deposit(msg.sender, _pid, _amount); } // Withdraw LP tokens from SuperChef. function withdraw(uint256 _pid, uint256 _amount) public { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; require(user.amount >= _amount, "withdraw: not good"); updatePool(_pid); uint256 pending = user.amount.mul(pool.accStaxPerShare).div(1e12).sub(user.rewardDebt); if(pending > 0) { safeStaxTransfer(msg.sender, pending); } if(_amount > 0) { user.amount = user.amount.sub(_amount); pool.lpToken.safeTransfer(address(msg.sender), _amount); } user.rewardDebt = user.amount.mul(pool.accStaxPerShare).div(1e12); emit Withdraw(msg.sender, _pid, _amount); } // Withdraw without caring about rewards. EMERGENCY ONLY. function emergencyWithdraw(uint256 _pid) public { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; pool.lpToken.safeTransfer(address(msg.sender), user.amount); emit EmergencyWithdraw(msg.sender, _pid, user.amount); user.amount = 0; user.rewardDebt = 0; } // Safe stax transfer function, just in case if rounding error causes pool to not have enough STAXs. function safeStaxTransfer(address _to, uint256 _amount) internal { uint256 staxBal = stax.balanceOf(address(this)); if (_amount > staxBal) { stax.transfer(_to, staxBal); } else { stax.transfer(_to, _amount); } } // Update dev address by the previous dev. function dev(address _devaddr) public { require(msg.sender == devaddr, "dev: wut?"); devaddr = _devaddr; } }
Encontrar Diferença