CookingFirevsMasterChef

Created Diff never expires
92 removals
313 lines
106 additions
327 lines
contract MasterChef is Ownable, ReentrancyGuard {
contract CookingFire is Ownable, ReentrancyGuard {
using SafeMath for uint256;
using SafeMath for uint256;
using SafeBEP20 for IBEP20;
using SafeBEP20 for IBEP20;


// 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.
uint256 rewardLockedUp; // Reward locked up.
uint256 rewardLockedUp; // Reward locked up.
uint256 nextHarvestUntil; // When can the user harvest again.
uint256 nextHarvestUntil; // When can the user harvest again.
//
//
// We do some fancy math here. Basically, any point in time, the amount of PANTHERs
// We do some fancy math here. Basically, any point in time, the amount of BLAZEs
// entitled to a user but is pending to be distributed is:
// entitled to a user but is pending to be distributed is:
//
//
// pending reward = (user.amount * pool.accPantherPerShare) - user.rewardDebt
// pending reward = (user.amount * pool.accBlazePerShare) - 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:
// 1. The pool's `accPantherPerShare` (and `lastRewardBlock`) gets updated.
// 1. The pool's `accBlazePerShare` (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 {
IBEP20 lpToken; // Address of LP token contract.
IBEP20 lpToken; // Address of LP token contract.
uint256 allocPoint; // How many allocation points assigned to this pool. PANTHERs to distribute per block.
uint256 allocPoint; // How many allocation points assigned to this pool. BLAZEs to distribute per block.
uint256 lastRewardBlock; // Last block number that PANTHERs distribution occurs.
uint256 lastRewardBlock; // Last block number that BLAZEs distribution occurs.
uint256 accPantherPerShare; // Accumulated PANTHERs per share, times 1e12. See below.
uint256 accBlazePerShare; // Accumulated BLAZEs per share, times 1e12. See below.
uint16 depositFeeBP; // Deposit fee in basis points
uint16 depositFeeBP; // Deposit fee in basis points
uint256 harvestInterval; // Harvest interval in seconds
uint256 harvestInterval; // Harvest interval in seconds
}
}


// The PANTHER TOKEN!
// The BLAZE TOKEN!
PantherToken public panther;
BlazeToken public blaze;
// Dev address.
// Dev address.
address public devAddress;
address public devAddress;
// Deposit Fee address
// Deposit Fee address
address public feeAddress;
address public feeAddress;
// PANTHER tokens created per block.
// BLAZE tokens created per block.
uint256 public pantherPerBlock;
uint256 public blazePerBlock;
// Bonus muliplier for early panther makers.
// Bonus muliplier for early blaze makers.
uint256 public constant BONUS_MULTIPLIER = 1;
uint256 public constant BONUS_MULTIPLIER = 1;
// Max harvest interval: 14 days.
// Max harvest interval: 14 days.
uint256 public constant MAXIMUM_HARVEST_INTERVAL = 14 days;
uint256 public constant MAXIMUM_HARVEST_INTERVAL = 14 days;


// 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;
// Total allocation points. Must be the sum of all allocation points in all pools.
// Total allocation points. Must be the sum of all allocation points in all pools.
uint256 public totalAllocPoint = 0;
uint256 public totalAllocPoint = 0;
// The block number when PANTHER mining starts.
// The block number when BLAZE mining starts.
uint256 public startBlock;
uint256 public startBlock;
// Total locked up rewards
// Total locked up rewards
uint256 public totalLockedUpRewards;
uint256 public totalLockedUpRewards;


// Panther referral contract address.
// Blaze referral contract address.
IPantherReferral public pantherReferral;
IBlazeReferral public blazeReferral;
// Referral commission rate in basis points.
// Referral commission rate in basis points.
uint16 public referralCommissionRate = 100;
uint16 public referralCommissionRate = 100;
// Max referral commission rate: 10%.
// Max referral commission rate: 10%.
uint16 public constant MAXIMUM_REFERRAL_COMMISSION_RATE = 1000;
uint16 public constant MAXIMUM_REFERRAL_COMMISSION_RATE = 1000;
address private _operator;


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);
event EmissionRateUpdated(address indexed caller, uint256 previousAmount, uint256 newAmount);
event EmissionRateUpdated(address indexed caller, uint256 previousAmount, uint256 newAmount);
event ReferralCommissionPaid(address indexed user, address indexed referrer, uint256 commissionAmount);
event ReferralCommissionPaid(address indexed user, address indexed referrer, uint256 commissionAmount);
event RewardLockedUp(address indexed user, uint256 indexed pid, uint256 amountLockedUp);
event RewardLockedUp(address indexed user, uint256 indexed pid, uint256 amountLockedUp);
modifier onlyOperator() {
require(_operator == msg.sender, "operator: caller is not the operator");
_;
}


constructor(
constructor(
PantherToken _panther,
BlazeToken _blaze,
uint256 _startBlock,
uint256 _startBlock,
uint256 _pantherPerBlock
uint256 _blazePerBlock
) public {
) public {
panther = _panther;
blaze = _blaze;
startBlock = _startBlock;
startBlock = _startBlock;
pantherPerBlock = _pantherPerBlock;
blazePerBlock = _blazePerBlock;

_operator = msg.sender;
devAddress = msg.sender;
devAddress = msg.sender;
feeAddress = msg.sender;
feeAddress = msg.sender;
}
}


function poolLength() external view returns (uint256) {
function poolLength() external view returns (uint256) {
return poolInfo.length;
return poolInfo.length;
}
}
function updateOperator(address _op) public onlyOperator {
_operator = _op;
}
function updateStartBlock(uint256 _startBlock) public onlyOperator {
require(block.number > startBlock, "updateStartBlock: farming already initiated");
startBlock = _startBlock;
}
// 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, IBEP20 _lpToken, uint16 _depositFeeBP, uint256 _harvestInterval, bool _withUpdate) public onlyOwner {
function add(uint256 _allocPoint, IBEP20 _lpToken, uint16 _depositFeeBP, uint256 _harvestInterval, bool _withUpdate) public onlyOperator {
require(_depositFeeBP <= 10000, "add: invalid deposit fee basis points");
require(_depositFeeBP <= 10000, "add: invalid deposit fee basis points");
require(_harvestInterval <= MAXIMUM_HARVEST_INTERVAL, "add: invalid harvest interval");
require(_harvestInterval <= MAXIMUM_HARVEST_INTERVAL, "add: invalid harvest interval");
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,
accPantherPerShare: 0,
accBlazePerShare: 0,
depositFeeBP: _depositFeeBP,
depositFeeBP: _depositFeeBP,
harvestInterval: _harvestInterval
harvestInterval: _harvestInterval
}));
}));
}
}


// Update the given pool's PANTHER allocation point and deposit fee. Can only be called by the owner.
// Update the given pool's BLAZE allocation point and deposit fee. Can only be called by the owner.
function set(uint256 _pid, uint256 _allocPoint, uint16 _depositFeeBP, uint256 _harvestInterval, bool _withUpdate) public onlyOwner {
function set(uint256 _pid, uint256 _allocPoint, uint16 _depositFeeBP, uint256 _harvestInterval, bool _withUpdate) public onlyOperator {
require(_depositFeeBP <= 10000, "set: invalid deposit fee basis points");
require(_depositFeeBP <= 10000, "set: invalid deposit fee basis points");
require(_harvestInterval <= MAXIMUM_HARVEST_INTERVAL, "set: invalid harvest interval");
require(_harvestInterval <= MAXIMUM_HARVEST_INTERVAL, "set: invalid harvest interval");
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;
poolInfo[_pid].depositFeeBP = _depositFeeBP;
poolInfo[_pid].depositFeeBP = _depositFeeBP;
poolInfo[_pid].harvestInterval = _harvestInterval;
poolInfo[_pid].harvestInterval = _harvestInterval;
}
}


// 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 pure returns (uint256) {
function getMultiplier(uint256 _from, uint256 _to) public pure returns (uint256) {
return _to.sub(_from).mul(BONUS_MULTIPLIER);
return _to.sub(_from).mul(BONUS_MULTIPLIER);
}
}


// View function to see pending PANTHERs on frontend.
// View function to see pending BLAZEs on frontend.
function pendingPanther(uint256 _pid, address _user) external view returns (uint256) {
function pendingBlaze(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];
uint256 accPantherPerShare = pool.accPantherPerShare;
uint256 accBlazePerShare = pool.accBlazePerShare;
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);
uint256 pantherReward = multiplier.mul(pantherPerBlock).mul(pool.allocPoint).div(totalAllocPoint);
uint256 blazeReward = multiplier.mul(blazePerBlock).mul(pool.allocPoint).div(totalAllocPoint);
accPantherPerShare = accPantherPerShare.add(pantherReward.mul(1e12).div(lpSupply));
accBlazePerShare = accBlazePerShare.add(blazeReward.mul(1e12).div(lpSupply));
}
}
uint256 pending = user.amount.mul(accPantherPerShare).div(1e12).sub(user.rewardDebt);
uint256 pending = user.amount.mul(accBlazePerShare).div(1e12).sub(user.rewardDebt);
return pending.add(user.rewardLockedUp);
return pending.add(user.rewardLockedUp);
}
}


// View function to see if user can harvest PANTHERs.
// View function to see if user can harvest BLAZEs.
function canHarvest(uint256 _pid, address _user) public view returns (bool) {
function canHarvest(uint256 _pid, address _user) public view returns (bool) {
UserInfo storage user = userInfo[_pid][_user];
UserInfo storage user = userInfo[_pid][_user];
return block.timestamp >= user.nextHarvestUntil;
return block.timestamp >= user.nextHarvestUntil;
}
}


// 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 || pool.allocPoint == 0) {
if (lpSupply == 0 || pool.allocPoint == 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);
uint256 pantherReward = multiplier.mul(pantherPerBlock).mul(pool.allocPoint).div(totalAllocPoint);
uint256 blazeReward = multiplier.mul(blazePerBlock).mul(pool.allocPoint).div(totalAllocPoint);
panther.mint(devAddress, pantherReward.div(10));
blaze.mint(devAddress, blazeReward.div(10));
panther.mint(address(this), pantherReward);
blaze.mint(address(this), blazeReward);
pool.accPantherPerShare = pool.accPantherPerShare.add(pantherReward.mul(1e12).div(lpSupply));
pool.accBlazePerShare = pool.accBlazePerShare.add(blazeReward.mul(1e12).div(lpSupply));
pool.lastRewardBlock = block.number;
pool.lastRewardBlock = block.number;
}
}


// Deposit LP tokens to MasterChef for PANTHER allocation.
// Deposit LP tokens to CookingFire for BLAZE allocation.
function deposit(uint256 _pid, uint256 _amount, address _referrer) public nonReentrant {
function deposit(uint256 _pid, uint256 _amount, address _referrer) public nonReentrant {
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 (_amount > 0 && address(pantherReferral) != address(0) && _referrer != address(0) && _referrer != msg.sender) {
if (_amount > 0 && address(blazeReferral) != address(0) && _referrer != address(0) && _referrer != msg.sender) {
pantherReferral.recordReferral(msg.sender, _referrer);
blazeReferral.recordReferral(msg.sender, _referrer);
}
}
payOrLockupPendingPanther(_pid);
payOrLockupPendingBlaze(_pid);
if (_amount > 0) {
if (_amount > 0) {
pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount);
pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount);
if (address(pool.lpToken) == address(panther)) {
uint256 transferTax = _amount.mul(panther.transferTaxRate()).div(10000);
_amount = _amount.sub(transferTax);
}
if (pool.depositFeeBP > 0) {
if (pool.depositFeeBP > 0) {
uint256 depositFee = _amount.mul(pool.depositFeeBP).div(10000);
uint256 depositFee = _amount.mul(pool.depositFeeBP).div(10000);
pool.lpToken.safeTransfer(feeAddress, depositFee);
pool.lpToken.safeTransfer(feeAddress, depositFee);
user.amount = user.amount.add(_amount).sub(depositFee);
user.amount = user.amount.add(_amount).sub(depositFee);
} else {
} else {
user.amount = user.amount.add(_amount);
user.amount = user.amount.add(_amount);
}
}
}
}
user.rewardDebt = user.amount.mul(pool.accPantherPerShare).div(1e12);
user.rewardDebt = user.amount.mul(pool.accBlazePerShare).div(1e12);
emit Deposit(msg.sender, _pid, _amount);
emit Deposit(msg.sender, _pid, _amount);
}
}


// Withdraw LP tokens from MasterChef.
// Withdraw LP tokens from CookingFire.
function withdraw(uint256 _pid, uint256 _amount) public nonReentrant {
function withdraw(uint256 _pid, uint256 _amount) public nonReentrant {
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);
payOrLockupPendingPanther(_pid);
payOrLockupPendingBlaze(_pid);
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);
}
}
user.rewardDebt = user.amount.mul(pool.accPantherPerShare).div(1e12);
user.rewardDebt = user.amount.mul(pool.accBlazePerShare).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 nonReentrant {
function emergencyWithdraw(uint256 _pid) public nonReentrant {
PoolInfo storage pool = poolInfo[_pid];
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
UserInfo storage user = userInfo[_pid][msg.sender];
uint256 amount = user.amount;
uint256 amount = user.amount;
user.amount = 0;
user.amount = 0;
user.rewardDebt = 0;
user.rewardDebt = 0;
user.rewardLockedUp = 0;
user.rewardLockedUp = 0;
user.nextHarvestUntil = 0;
user.nextHarvestUntil = 0;
pool.lpToken.safeTransfer(address(msg.sender), amount);
pool.lpToken.safeTransfer(address(msg.sender), amount);
emit EmergencyWithdraw(msg.sender, _pid, amount);
emit EmergencyWithdraw(msg.sender, _pid, amount);
}
}


// Pay or lockup pending PANTHERs.
// Pay or lockup pending BLAZEs.
function payOrLockupPendingPanther(uint256 _pid) internal {
function payOrLockupPendingBlaze(uint256 _pid) internal {
PoolInfo storage pool = poolInfo[_pid];
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
UserInfo storage user = userInfo[_pid][msg.sender];


if (user.nextHarvestUntil == 0) {
if (user.nextHarvestUntil == 0) {
user.nextHarvestUntil = block.timestamp.add(pool.harvestInterval);
user.nextHarvestUntil = block.timestamp.add(pool.harvestInterval);
}
}


uint256 pending = user.amount.mul(pool.accPantherPerShare).div(1e12).sub(user.rewardDebt);
uint256 pending = user.amount.mul(pool.accBlazePerShare).div(1e12).sub(user.rewardDebt);
if (canHarvest(_pid, msg.sender)) {
if (canHarvest(_pid, msg.sender)) {
if (pending > 0 || user.rewardLockedUp > 0) {
if (pending > 0 || user.rewardLockedUp > 0) {
uint256 totalRewards = pending.add(user.rewardLockedUp);
uint256 totalRewards = pending.add(user.rewardLockedUp);


// reset lockup
// reset lockup
totalLockedUpRewards = totalLockedUpRewards.sub(user.rewardLockedUp);
totalLockedUpRewards = totalLockedUpRewards.sub(user.rewardLockedUp);
user.rewardLockedUp = 0;
user.rewardLockedUp = 0;
user.nextHarvestUntil = block.timestamp.add(pool.harvestInterval);
user.nextHarvestUntil = block.timestamp.add(pool.harvestInterval);


// send rewards
// send rewards
safePantherTransfer(msg.sender, totalRewards);
safeBlazeTransfer(msg.sender, totalRewards);
payReferralCommission(msg.sender, totalRewards);
payReferralCommission(msg.sender, totalRewards);
}
}
} else if (pending > 0) {
} else if (pending > 0) {
user.rewardLockedUp = user.rewardLockedUp.add(pending);
user.rewardLockedUp = user.rewardLockedUp.add(pending);
totalLockedUpRewards = totalLockedUpRewards.add(pending);
totalLockedUpRewards = totalLockedUpRewards.add(pending);
emit RewardLockedUp(msg.sender, _pid, pending);
emit RewardLockedUp(msg.sender, _pid, pending);
}
}
}
}


// Safe panther transfer function, just in case if rounding error causes pool to not have enough PANTHERs.
// Safe blaze transfer function, just in case if rounding error causes pool to not have enough BLAZEs.
function safePantherTransfer(address _to, uint256 _amount) internal {
function safeBlazeTransfer(address _to, uint256 _amount) internal {
uint256 pantherBal = panther.balanceOf(address(this));
uint256 blazeBal = blaze.balanceOf(address(this));
if (_amount > pantherBal) {
if (_amount > blazeBal) {
panther.transfer(_to, pantherBal);
blaze.transfer(_to, blazeBal);
} else {
} else {
panther.transfer(_to, _amount);
blaze.transfer(_to, _amount);
}
}
}
}


// Update dev address by the previous dev.
// Update dev address by the previous dev.
function setOperator(address _op) public onlyOperator {
_operator = _op;
}
function setDevAddress(address _devAddress) public {
function setDevAddress(address _devAddress) public {
require(msg.sender == devAddress, "setDevAddress: FORBIDDEN");
require(msg.sender == devAddress, "setDevAddress: FORBIDDEN");
require(_devAddress != address(0), "setDevAddress: ZERO");
require(_devAddress != address(0), "setDevAddress: ZERO");
devAddress = _devAddress;
devAddress = _devAddress;
}
}


function setFeeAddress(address _feeAddress) public {
function setFeeAddress(address _feeAddress) public {
require(msg.sender == feeAddress, "setFeeAddress: FORBIDDEN");
require(msg.sender == feeAddress, "setFeeAddress: FORBIDDEN");
require(_feeAddress != address(0), "setFeeAddress: ZERO");
require(_feeAddress != address(0), "setFeeAddress: ZERO");
feeAddress = _feeAddress;
feeAddress = _feeAddress;
}
}


// Pancake has to add hidden dummy pools in order to alter the emission, here we make it simple and transparent to all.
// Pancake has to add hidden dummy pools in order to alter the emission, here we make it simple and transparent to all.
function updateEmissionRate(uint256 _pantherPerBlock) public onlyOwner {
function updateEmissionRate(uint256 _blazePerBlock) public onlyOperator {
massUpdatePools();
massUpdatePools();
emit EmissionRateUpdated(msg.sender, pantherPerBlock, _pantherPerBlock);
emit EmissionRateUpdated(msg.sender, blazePerBlock, _blazePerBlock);
pantherPerBlock = _pantherPerBlock;
blazePerBlock = _blazePerBlock;
}
}


// Update the panther referral contract address by the owner
// Update the blaze referral contract address by the owner
function setPantherReferral(IPantherReferral _pantherReferral) public onlyOwner {
function setBlazeReferral(IBlazeReferral _blazeReferral) public onlyOwner {
pantherReferral = _pantherReferral;
blazeReferral = _blazeReferral;
}
}


// Update referral commission rate by the owner
// Update referral commission rate by the owner
function setReferralCommissionRate(uint16 _referralCommissionRate) public onlyOwner {
function setReferralCommissionRate(uint16 _referralCommissionRate) public onlyOwner {
require(_referralCommissionRate <= MAXIMUM_REFERRAL_COMMISSION_RATE, "setReferralCommissionRate: invalid referral commission rate basis points");
require(_referralCommissionRate <= MAXIMUM_REFERRAL_COMMISSION_RATE, "setReferralCommissionRate: invalid referral commission rate basis points");
referralCommissionRate = _referralCommissionRate;
referralCommissionRate = _referralCommissionRate;
}
}


// Pay referral commission to the referrer who referred this user.
// Pay referral commission to the referrer who referred this user.
function payReferralCommission(address _user, uint256 _pending) internal {
function payReferralCommission(address _user, uint256 _pending) internal {
if (address(pantherReferral) != address(0) && referralCommissionRate > 0) {
if (address(blazeReferral) != address(0) && referralCommissionRate > 0) {
address referrer = pantherReferral.getReferrer(_user);
address referrer = blazeReferral.getReferrer(_user);
uint256 commissionAmount = _pending.mul(referralCommissionRate).div(10000);
uint256 commissionAmount = _pending.mul(referralCommissionRate).div(10000);


if (referrer != address(0) && commissionAmount > 0) {
if (referrer != address(0) && commissionAmount > 0) {
panther.mint(referrer, commissionAmount);
blaze.mint(referrer, commissionAmount);
pantherReferral.recordReferralCommission(referrer, commissionAmount);
blazeReferral.recordReferralCommission(referrer, commissionAmount);
emit ReferralCommissionPaid(_user, referrer, commissionAmount);
emit ReferralCommissionPaid(_user, referrer, commissionAmount);
}
}
}
}
}
}
}
}