meowbored-staking
v0.1.2
Published
To run the project, make sure you have installed dependencies including NPM and Node.js.
Downloads
2
Readme
To run the project, make sure you have installed dependencies including NPM and Node.js.
Please edit the chainID
in _app.js
with the actual ID you want to build.
The chainID 0x7f8c26
is currently offline, so please replace it.
function connect() {
if (window.ethereum) {
window.ethereum
.request({
method: "wallet_switchEthereumChain",
params: [{ chainId: "0x7f8c26" }],
})
.then(checkNetwork)
.catch((error) => {
console.error("Error switching network:", error);
});
} else {
console.error("Metamask extension not detected.");
}
}
async function switchNetwork() {
try {
await ethereum.request({
method: "wallet_addEthereumChain",
params: [
{
chainId: "0x7f8c26",
chainName: "meowbored",
nativeCurrency: {
name: "meowbored",
symbol: "BLUED",
decimals: 18,
},
rpcUrls: ["https://meowbored.pro/"],
},
],
});
} catch (error) {
console.error("Error switching to custom network:", error);
}
}
Inside the components folder, please also edit masterchefAddress
and chainId
in config.js
.
const masterchefAddr = '0x7a843F02C34Ad1c56b7719048fc8E9Ce906CB11D';
const chainId = '0x7f8c26';
Deploy Masterchef smart contract on any network and use this smart contract.
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "./n2drewards.sol";
import "./n2dpay.sol";
/*
*/
contract N2DMasterChefV1 is Ownable, ReentrancyGuard {
using SafeMath for uint256;
using SafeERC20 for IERC20;
struct UserInfo {
uint256 amount;
uint256 pendingReward;
}
struct PoolInfo {
IERC20 lpToken;
uint256 allocPoint;
uint256 lastRewardBlock;
uint256 rewardTokenPerShare;
}
N2DRewards public n2dr;
N2DRPay public n2drpay;
address public dev;
uint256 public n2drPerBlock;
PoolInfo[] public poolInfo;
mapping (uint256 => mapping (address => UserInfo)) public userInfo;
uint256 public totalAllocation = 0;
uint256 public startBlock;
uint256 public BONUS_MULTIPLIER;
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(
N2DRewards _n2dr,
N2DRPay _n2drpay,
address _dev,
uint256 _n2drPerBlock,
uint256 _startBlock,
uint256 _multiplier,
address _initialOwner
) Ownable(_initialOwner) {
n2dr = _n2dr;
n2drpay = _n2drpay;
dev = _dev;
n2drPerBlock = _n2drPerBlock;
startBlock = _startBlock;
BONUS_MULTIPLIER = _multiplier;
poolInfo.push(PoolInfo({
lpToken: _n2dr,
allocPoint: 1000,
lastRewardBlock: startBlock,
rewardTokenPerShare: 0
}));
totalAllocation = 1000;
}
modifier validatePool(uint256 _pid) {
require(_pid < poolInfo.length, "pool Id Invalid");
_;
}
function updateMultiplier(uint256 multiplierNumber) public onlyOwner {
BONUS_MULTIPLIER = multiplierNumber;
}
function poolLength() external view returns (uint256) {
return poolInfo.length;
}
function checkPoolDuplicate(IERC20 _lpToken) public view {
uint256 length = poolInfo.length;
for (uint256 _pid = 0; _pid < length; _pid++) {
require(poolInfo[_pid].lpToken != _lpToken, "add: existing pool");
}
}
function add(uint256 _allocPoint, IERC20 _lpToken, bool _withUpdate) public onlyOwner {
if (_withUpdate) {
massUpdatePools();
}
checkPoolDuplicate(_lpToken);
uint256 lastRewardBlock = block.number > startBlock ? block.number : startBlock;
totalAllocation = totalAllocation.add(_allocPoint);
poolInfo.push(PoolInfo({
lpToken: _lpToken,
allocPoint: _allocPoint,
lastRewardBlock: lastRewardBlock,
rewardTokenPerShare: 0
}));
updateStakingPool();
}
function set(uint256 _pid, uint256 _allocPoint, bool _withUpdate) public onlyOwner {
if (_withUpdate) {
massUpdatePools();
}
uint256 prevAllocPoint = poolInfo[_pid].allocPoint;
poolInfo[_pid].allocPoint = _allocPoint;
if (prevAllocPoint != _allocPoint) {
totalAllocation = totalAllocation.sub(prevAllocPoint).add(_allocPoint);
updateStakingPool();
}
}
function updateStakingPool() internal {
uint256 length = poolInfo.length;
uint256 points = 0;
for (uint256 pid = 1; pid < length; ++pid) {
points = points.add(poolInfo[pid].allocPoint);
}
if (points != 0) {
points = points.div(3);
totalAllocation = totalAllocation.sub(poolInfo[0].allocPoint).add(points);
poolInfo[0].allocPoint = points;
}
}
function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256) {
return _to.sub(_from).mul(BONUS_MULTIPLIER);
}
function pendingReward(uint256 _pid, address _user) external view returns (uint256) {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][_user];
uint256 rewardTokenPerShare = pool.rewardTokenPerShare;
uint256 lpSupply = pool.lpToken.balanceOf(address(this));
if (block.number > pool.lastRewardBlock && lpSupply != 0) {
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);
uint256 tokenReward = multiplier.mul(n2drPerBlock).mul(pool.allocPoint).div(totalAllocation);
rewardTokenPerShare = rewardTokenPerShare.add(tokenReward.mul(1e12).div(lpSupply));
}
return user.amount.mul(rewardTokenPerShare).div(1e12).sub(user.pendingReward);
}
function massUpdatePools() public {
uint256 length = poolInfo.length;
for (uint256 pid = 0; pid < length; ++pid) {
updatePool(pid);
}
}
function updatePool(uint256 _pid) public validatePool(_pid) {
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 tokenReward = multiplier.mul(n2drPerBlock).mul(pool.allocPoint).div(totalAllocation);
n2dr.mint(dev, tokenReward.div(10));
n2dr.mint(address(n2drpay), tokenReward);
pool.rewardTokenPerShare = pool.rewardTokenPerShare.add(tokenReward.mul(1e12).div(lpSupply));
pool.lastRewardBlock = block.number;
}
function stake(uint256 _pid, uint256 _amount) public validatePool(_pid) {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
updatePool(_pid);
if (user.amount > 0) {
uint256 pending = user.amount.mul(pool.rewardTokenPerShare).div(1e12).sub(user.pendingReward);
if(pending > 0) {
safeN2drTransfer(msg.sender, pending);
}
}
if (_amount > 0) {
pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount);
user.amount = user.amount.add(_amount);
}
user.pendingReward = user.amount.mul(pool.rewardTokenPerShare).div(1e12);
emit Deposit(msg.sender, _pid, _amount);
}
function autoCompound() public {
PoolInfo storage pool = poolInfo[0];
UserInfo storage user = userInfo[0][msg.sender];
updatePool(0);
if (user.amount > 0) {
uint256 pending = user.amount.mul(pool.rewardTokenPerShare).div(1e12).sub(user.pendingReward);
if(pending > 0) {
user.amount = user.amount.add(pending);
}
}
user.pendingReward = user.amount.mul(pool.rewardTokenPerShare).div(1e12);
}
function unstake(uint256 _pid, uint256 _amount) public validatePool(_pid) {
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.rewardTokenPerShare).div(1e12).sub(user.pendingReward);
if(pending > 0) {
safeN2drTransfer(msg.sender, pending);
}
if(_amount > 0) {
user.amount = user.amount.sub(_amount);
pool.lpToken.safeTransfer(address(msg.sender), _amount);
}
user.pendingReward = user.amount.mul(pool.rewardTokenPerShare).div(1e12);
emit Withdraw(msg.sender, _pid, _amount);
}
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.pendingReward = 0;
}
function getPoolInfo(uint256 _pid) public view
returns(address lpToken, uint256 allocPoint, uint256 lastRewardBlock, uint256 rewardTokenPerShare) {
return (address(poolInfo[_pid].lpToken),
poolInfo[_pid].allocPoint,
poolInfo[_pid].lastRewardBlock,
poolInfo[_pid].rewardTokenPerShare);
}
function safeN2drTransfer(address _to, uint256 _amount) internal {
n2drpay.safeN2drTransfer(_to, _amount);
}
function changeDev(address _dev) public {
require(msg.sender == dev, "Not Authorized");
dev = _dev;
}
}
install dependencies
npm i
test project
npm run dev