嘿有人可以向我解释一下这个智能合约 - LP 质押合约
嘿,所以我在 github 上寻找 LP 质押智能合约,我遇到了这个
// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
contract StakingV2 is Ownable {
using SafeMath for uint;
using SafeERC20 for IERC20;
struct Stake {
uint amount;
uint stakeTime;
uint fraction;
uint rewardOut;
}
mapping(uint => mapping(address => Stake)) public stakes;
// Info of each pool.
struct Pool {
uint rewardAmount; // Pool reward tokens limit
uint startTime;
uint endTime;
uint total;
uint freezeTime;
uint freezePercent;
}
Pool[] public pools;
address public stakeToken; // Uniswap LP token from pool MRCH/USDT
address public rewardToken; // MRCH token
event AddPool(uint pid, uint reward, uint startTime, uint endTime, uint freezeTime, uint percent);
event PoolTotal(uint pid, uint oldTotal, uint newTotal);
event StakerFraction(uint pid, address staker, uint oldFraction, uint newFraction);
event Staked(uint pid, address staker, uint amount);
event RewardOut(uint pid, address staker, address token, uint amount);
constructor(
address stakeToken_,
address rewardToken_
) {
require(stakeToken_ != address(0), "MRCHStaking::constructor: stake token address is 0x0");
stakeToken = stakeToken_;
require(rewardToken_ != address(0), "MRCHStaking::constructor: reward token address is 0x0");
rewardToken = rewardToken_;
}
function addPool(uint rewardAmount_, uint startTime_, uint endTime_, uint freezeTime_, uint freezePercent_) public onlyOwner {
require(getTimeStamp() <= startTime_, "MRCHStaking::addPool: bad timing for the request");
require(startTime_ < endTime_, "MRCHStaking::addPool: endTime > startTime");
doTransferIn(msg.sender, rewardToken, rewardAmount_);
pools.push(
Pool({
rewardAmount: rewardAmount_,
startTime: startTime_,
endTime: endTime_,
total: 0,
freezeTime: freezeTime_,
freezePercent: freezePercent_ // scaled by 1e18, for example 5% = 5e18, 0.01% = 1e16
})
);
emit AddPool(pools.length - 1, rewardAmount_, startTime_, endTime_, freezeTime_, freezePercent_);
}
function stake(uint pid, uint amount) public returns (bool) {
require(amount > 0, "MRCHStaking::stake: amount must be positive");
uint timeStamp = getTimeStamp();
require(timeStamp < pools[pid].endTime, "MRCHStaking::stake: bad timing for the request");
address staker = msg.sender;
doTransferIn(staker, stakeToken, amount);
// Transfer is completed
stakes[pid][staker].amount = stakes[pid][staker].amount.add(amount);
uint addition;
if (timeStamp < pools[pid].startTime) {
stakes[pid][staker].stakeTime = pools[pid].startTime;
addition = (pools[pid].endTime.sub(pools[pid].startTime)).mul(amount);
} else {
stakes[pid][staker].stakeTime = timeStamp;
addition = (pools[pid].endTime.sub(timeStamp)).mul(amount);
}
uint oldFraction = stakes[pid][staker].fraction;
stakes[pid][staker].fraction = stakes[pid][staker].fraction.add(addition);
uint oldTotal = pools[pid].total;
pools[pid].total = pools[pid].total.add(addition);
emit Staked(pid, staker, amount);
emit StakerFraction(pid, staker, oldFraction, stakes[pid][staker].fraction);
emit PoolTotal(pid, oldTotal, pools[pid].total);
return true;
}
function withdraw(uint pid) public returns (bool) {
require(claim(pid), "MRCHStaking::withdraw: claim error");
uint amount = stakes[pid][msg.sender].amount;
return withdrawWithoutReward(pid, amount);
}
function withdrawWithoutReward(uint pid, uint amount) public returns (bool) {
return withdrawInternal(pid, msg.sender, amount);
}
function withdrawInternal(uint pid, address staker, uint amount) internal returns (bool) {
require(amount > 0, "MRCHStaking::withdrawInternal: amount must be positive");
require(amount <= stakes[pid][msg.sender].amount, "MRCHStaking::withdrawInternal: not enough balance");
stakes[pid][staker].amount = stakes[pid][staker].amount.sub(amount);
uint freezeTime = stakes[pid][staker].stakeTime.add(pools[pid].freezeTime);
if (getTimeStamp() < freezeTime) {
uint freezeAmount = amount.mul(pools[pid].freezePercent).div(100);
amount = amount.sub(freezeAmount);
}
doTransferOut(stakeToken, staker, amount);
return true;
}
function claim(uint pid) public returns (bool) {
require(getTimeStamp() > pools[pid].endTime, "MRCHStaking::claim: bad timing for the request");
address staker = msg.sender;
uint rewardAmount = currentTotalReward(pid, staker);
if (rewardAmount == 0) {
return true;
}
doTransferOut(rewardToken, staker, rewardAmount);
stakes[pid][staker].rewardOut = stakes[pid][staker].rewardOut.add(rewardAmount);
emit RewardOut(pid, staker, rewardToken, rewardAmount);
return true;
}
function currentTotalReward(uint pid, address staker) public view returns (uint) {
uint totalRewardAmount = pools[pid].rewardAmount;
uint total = pools[pid].total;
if (total == 0) {
return 0;
}
uint fraction = stakes[pid][staker].fraction;
uint rewardOut = stakes[pid][staker].rewardOut;
uint rewardAmount = totalRewardAmount.mul(fraction).div(total);
return rewardAmount.sub(rewardOut);
}
function doTransferOut(address token, address to, uint amount) internal {
if (amount == 0) {
return;
}
IERC20 ERC20Interface = IERC20(token);
ERC20Interface.safeTransfer(to, amount);
}
function doTransferIn(address from, address token, uint amount) internal {
IERC20 ERC20Interface = IERC20(token);
ERC20Interface.safeTransferFrom(from, address(this), amount);
}
function transferTokens(address token, address to, uint amount) public onlyOwner {
doTransferOut(token, to, amount);
}
function getTimeStamp() public view virtual returns (uint) {
return block.timestamp;
}
function getPoolLength() public view returns(uint) {
return pools.length;
}
}
,所以在成功部署到 rinkeby 测试网后,我不确定这意味着什么(其中一些)。
所以我知道一个事实:rewardAmount_ - 是每个区块将分配多少奖励。
startTime_ 是池应该启动的时间(例如您可以使用的日期和时间 https://www.epochconverter.com / 是指
合约停止分配奖励
的时间,就像锁定代币一样,因此当用户尝试在冻结时间之前取出时,他们将无法执行
冻结百分比 。减少超过 我不太了解它,
所以如果错了,请纠正,原因是;如果我对冻结时间和冻结百分比的理解是正确的,
我知道 如何做到这一点。 freezePercentage 可以这样输入 5% = 5e18,
但是 freezeTime 又是什么呢?
如果有人有更好的理解,请与我分享。
hey so i was looking through github for a LP staking smart contract and i came across this
// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
contract StakingV2 is Ownable {
using SafeMath for uint;
using SafeERC20 for IERC20;
struct Stake {
uint amount;
uint stakeTime;
uint fraction;
uint rewardOut;
}
mapping(uint => mapping(address => Stake)) public stakes;
// Info of each pool.
struct Pool {
uint rewardAmount; // Pool reward tokens limit
uint startTime;
uint endTime;
uint total;
uint freezeTime;
uint freezePercent;
}
Pool[] public pools;
address public stakeToken; // Uniswap LP token from pool MRCH/USDT
address public rewardToken; // MRCH token
event AddPool(uint pid, uint reward, uint startTime, uint endTime, uint freezeTime, uint percent);
event PoolTotal(uint pid, uint oldTotal, uint newTotal);
event StakerFraction(uint pid, address staker, uint oldFraction, uint newFraction);
event Staked(uint pid, address staker, uint amount);
event RewardOut(uint pid, address staker, address token, uint amount);
constructor(
address stakeToken_,
address rewardToken_
) {
require(stakeToken_ != address(0), "MRCHStaking::constructor: stake token address is 0x0");
stakeToken = stakeToken_;
require(rewardToken_ != address(0), "MRCHStaking::constructor: reward token address is 0x0");
rewardToken = rewardToken_;
}
function addPool(uint rewardAmount_, uint startTime_, uint endTime_, uint freezeTime_, uint freezePercent_) public onlyOwner {
require(getTimeStamp() <= startTime_, "MRCHStaking::addPool: bad timing for the request");
require(startTime_ < endTime_, "MRCHStaking::addPool: endTime > startTime");
doTransferIn(msg.sender, rewardToken, rewardAmount_);
pools.push(
Pool({
rewardAmount: rewardAmount_,
startTime: startTime_,
endTime: endTime_,
total: 0,
freezeTime: freezeTime_,
freezePercent: freezePercent_ // scaled by 1e18, for example 5% = 5e18, 0.01% = 1e16
})
);
emit AddPool(pools.length - 1, rewardAmount_, startTime_, endTime_, freezeTime_, freezePercent_);
}
function stake(uint pid, uint amount) public returns (bool) {
require(amount > 0, "MRCHStaking::stake: amount must be positive");
uint timeStamp = getTimeStamp();
require(timeStamp < pools[pid].endTime, "MRCHStaking::stake: bad timing for the request");
address staker = msg.sender;
doTransferIn(staker, stakeToken, amount);
// Transfer is completed
stakes[pid][staker].amount = stakes[pid][staker].amount.add(amount);
uint addition;
if (timeStamp < pools[pid].startTime) {
stakes[pid][staker].stakeTime = pools[pid].startTime;
addition = (pools[pid].endTime.sub(pools[pid].startTime)).mul(amount);
} else {
stakes[pid][staker].stakeTime = timeStamp;
addition = (pools[pid].endTime.sub(timeStamp)).mul(amount);
}
uint oldFraction = stakes[pid][staker].fraction;
stakes[pid][staker].fraction = stakes[pid][staker].fraction.add(addition);
uint oldTotal = pools[pid].total;
pools[pid].total = pools[pid].total.add(addition);
emit Staked(pid, staker, amount);
emit StakerFraction(pid, staker, oldFraction, stakes[pid][staker].fraction);
emit PoolTotal(pid, oldTotal, pools[pid].total);
return true;
}
function withdraw(uint pid) public returns (bool) {
require(claim(pid), "MRCHStaking::withdraw: claim error");
uint amount = stakes[pid][msg.sender].amount;
return withdrawWithoutReward(pid, amount);
}
function withdrawWithoutReward(uint pid, uint amount) public returns (bool) {
return withdrawInternal(pid, msg.sender, amount);
}
function withdrawInternal(uint pid, address staker, uint amount) internal returns (bool) {
require(amount > 0, "MRCHStaking::withdrawInternal: amount must be positive");
require(amount <= stakes[pid][msg.sender].amount, "MRCHStaking::withdrawInternal: not enough balance");
stakes[pid][staker].amount = stakes[pid][staker].amount.sub(amount);
uint freezeTime = stakes[pid][staker].stakeTime.add(pools[pid].freezeTime);
if (getTimeStamp() < freezeTime) {
uint freezeAmount = amount.mul(pools[pid].freezePercent).div(100);
amount = amount.sub(freezeAmount);
}
doTransferOut(stakeToken, staker, amount);
return true;
}
function claim(uint pid) public returns (bool) {
require(getTimeStamp() > pools[pid].endTime, "MRCHStaking::claim: bad timing for the request");
address staker = msg.sender;
uint rewardAmount = currentTotalReward(pid, staker);
if (rewardAmount == 0) {
return true;
}
doTransferOut(rewardToken, staker, rewardAmount);
stakes[pid][staker].rewardOut = stakes[pid][staker].rewardOut.add(rewardAmount);
emit RewardOut(pid, staker, rewardToken, rewardAmount);
return true;
}
function currentTotalReward(uint pid, address staker) public view returns (uint) {
uint totalRewardAmount = pools[pid].rewardAmount;
uint total = pools[pid].total;
if (total == 0) {
return 0;
}
uint fraction = stakes[pid][staker].fraction;
uint rewardOut = stakes[pid][staker].rewardOut;
uint rewardAmount = totalRewardAmount.mul(fraction).div(total);
return rewardAmount.sub(rewardOut);
}
function doTransferOut(address token, address to, uint amount) internal {
if (amount == 0) {
return;
}
IERC20 ERC20Interface = IERC20(token);
ERC20Interface.safeTransfer(to, amount);
}
function doTransferIn(address from, address token, uint amount) internal {
IERC20 ERC20Interface = IERC20(token);
ERC20Interface.safeTransferFrom(from, address(this), amount);
}
function transferTokens(address token, address to, uint amount) public onlyOwner {
doTransferOut(token, to, amount);
}
function getTimeStamp() public view virtual returns (uint) {
return block.timestamp;
}
function getPoolLength() public view returns(uint) {
return pools.length;
}
}
so after successfully deploying to the rinkeby testnet am not sure what this means ( some of them).
so i know for a fact the rewardAmount_ - is how much reward will be distributed per block.
The startTime_ is when the pool should start ( like the daye and time which you can use https://www.epochconverter.com/ for that.
The startTime_is when the contract will stop distributing the rewards.
The freeze time is like locking the token so when users try to take out before the freeze time they wont be able to.
The freeze percentage is Apy which reduces over time.
i dont really understand it very well so if am wrong please correct. and the reason why am here is that ; if my understanding about the freezetime and freezepercentage are correct how how i do that or enter it in the field.
i know that the freezePercentage can be entered like this 5% = 5e18.
but what of the freezeTime?.
and if anyone has a better understanding please share with me
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
回答你的问题:
我知道可以像这样输入 freezePercentage 5% = 5e18。 - 这是正确的。您可以输入一个整数百分比并对其进行处理,例如,5 将是 0.05,
但是 freezeTime 又如何呢?冻结时间是质押 LP 代币冻结部分可以以 unix 时间戳格式释放的结束日期。在这种情况下,当有人撤回他们的股份时,如果您使用 AddPool 创建池,并在冻结时间中输入诸如“1679505397(2023 年 3 月)”之类的值,它将撤回他们的股份减去冻结金额,在这种情况下上面,它被硬编码为 5%。例如,我质押了 10 个 LP 代币。我今天选择提现,但是只能取回9.5,因为冻结百分比是5,而且时间戳小于冻结时间。我必须等到 2023 年 3 月才能撤回最终的 0.5。
To answer your question:
i know that the freezePercentage can be entered like this 5% = 5e18. - This is correct. You can enter a percentage as a whole number and treat it as such, example, 5 will be .05
but what of the freezeTime? The freeze time is the end date the staked LP token frozen portion can be released in unix timestamp format. In this case, when someone withdraws their stake, and if you created the pool using AddPool, and put in a value such as "1679505397 (March 2023)" in Freeze Time, it will withdraw their stake minus the frozen amount, in the case above, it's hard coded to be 5%. For example, I staked 10 LP tokens. I choose to withdraw today, but I will only get back 9.5, because the freeze percentage is 5, and the timestamp is less than the freeze time. I will have to wait until March 2023 to withdraw the final .5.