编译器
0.8.19+commit.7dd6d404
文件 1 的 8:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 8:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 3 的 8:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
文件 4 的 8:LockedFarming.sol
pragma solidity 0.8.19;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {SafeMath} from "@openzeppelin/contracts/utils/math/SafeMath.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
contract SMD_v5 is Ownable {
using SafeMath for uint256;
using SafeERC20 for IERC20;
uint256 public constant SECONDS_PER_HOUR = 3600;
address public tokenAddress;
address public rewardTokenAddress;
uint256 public totalStaked;
uint256 public currentStakedBalance;
uint256 public stakedBalanceCurrPeriod;
uint256 public rewardBalance;
uint256 public totalReward;
uint256 public startingDate;
uint256 public endingDate;
uint256 public periodCounter;
uint256 public accShare;
uint256 public lastSharesUpdateTime;
uint256 public totalParticipants;
uint256 public lockDuration;
bool public isPaused;
IERC20 internal _erc20Interface;
struct Deposits {
uint256 amount;
uint256 latestStakeAt;
uint256 latestClaimAt;
uint256 userAccShare;
uint256 currentPeriod;
}
struct PeriodDetails {
uint256 periodCounter;
uint256 accShare;
uint256 rewPerSecond;
uint256 startingDate;
uint256 endingDate;
uint256 rewards;
}
mapping(address => Deposits) private deposits;
mapping(address => bool) public isPaid;
mapping(address => bool) public hasStaked;
mapping(uint256 => PeriodDetails) public endAccShare;
event NewPeriodSet(
uint256 periodCounter,
uint256 startDate,
uint256 endDate,
uint256 lockDuration,
uint256 rewardAmount
);
event Paused(
uint256 indexed periodCounter,
uint256 indexed totalParticipants,
uint256 indexed currentStakedBalance,
uint256 totalReward
);
event UnPaused(
uint256 indexed periodCounter,
uint256 indexed totalParticipants,
uint256 indexed currentStakedBalance,
uint256 totalReward
);
event PeriodExtended(
uint256 periodCounter,
uint256 endDate,
uint256 rewards
);
event Staked(
address indexed token,
address indexed staker_,
uint256 stakedAmount_
);
event PaidOut(
address indexed token,
address indexed rewardToken,
address indexed staker_,
uint256 amount_,
uint256 reward_
);
constructor(address _tokenAddress, address _rewardTokenAddress) Ownable() {
require(_tokenAddress != address(0), "Zero token address");
tokenAddress = _tokenAddress;
require(
_rewardTokenAddress != address(0),
"Zero reward token address"
);
rewardTokenAddress = _rewardTokenAddress;
isPaused = true;
}
function __configNewPeriod(
uint256 _start,
uint256 _end,
uint256 _lockDuration
) private {
require(totalReward > 0, "Add rewards for this periodCounter");
startingDate = _start;
endingDate = _end;
lockDuration = _lockDuration;
periodCounter++;
lastSharesUpdateTime = _start;
}
function __addReward(
uint256 _rewardAmount
)
private
hasAllowance(msg.sender, _rewardAmount, rewardTokenAddress)
returns (bool)
{
totalReward = totalReward.add(_rewardAmount);
rewardBalance = rewardBalance.add(_rewardAmount);
if (!__payMe(msg.sender, _rewardAmount, rewardTokenAddress)) {
return false;
}
return true;
}
function __saveOldPeriod() private {
if (
block.timestamp > endingDate &&
endAccShare[periodCounter].startingDate == 0
) {
endAccShare[periodCounter] = PeriodDetails(
periodCounter,
accShare,
rewPerSecond(),
startingDate,
endingDate,
rewardBalance
);
}
}
function __reset() private {
totalReward = 0;
stakedBalanceCurrPeriod = 0;
totalParticipants = 0;
}
function setNewPeriod(
uint256 _rewardAmount,
uint256 _start,
uint256 _end,
uint256 _lockDuration
) external onlyOwner returns (bool) {
require(
_start > block.timestamp,
"Start should be more than block.timestamp"
);
require(_end > _start, "End block should be greater than start");
require(_rewardAmount > 0, "Reward must be positive");
require(block.timestamp > endingDate, "Wait till end of this period");
__updateShare();
__saveOldPeriod();
__reset();
bool rewardAdded = __addReward(_rewardAmount);
require(rewardAdded, "Rewards error");
__configNewPeriod(_start, _end, _lockDuration);
emit NewPeriodSet(
periodCounter,
_start,
_end,
_lockDuration,
_rewardAmount
);
isPaused = false;
return true;
}
function pause() external onlyOwner {
isPaused = true;
emit Paused(
periodCounter,
totalParticipants,
currentStakedBalance,
totalReward
);
}
function unPause() external onlyOwner {
isPaused = false;
emit UnPaused(
periodCounter,
totalParticipants,
currentStakedBalance,
totalReward
);
}
function __updateShare() private {
if (block.timestamp <= lastSharesUpdateTime) {
return;
}
if (stakedBalanceCurrPeriod == 0) {
lastSharesUpdateTime = block.timestamp;
return;
}
uint256 secSinceLastPeriod;
if (block.timestamp >= endingDate) {
secSinceLastPeriod = endingDate.sub(lastSharesUpdateTime);
} else {
secSinceLastPeriod = block.timestamp.sub(lastSharesUpdateTime);
}
uint256 rewards = secSinceLastPeriod.mul(rewPerSecond());
accShare = accShare.add(
(rewards.mul(1e6).div(stakedBalanceCurrPeriod))
);
if (block.timestamp >= endingDate) {
lastSharesUpdateTime = endingDate;
} else {
lastSharesUpdateTime = block.timestamp;
}
}
function rewPerSecond() public view returns (uint256) {
if (totalReward == 0 || rewardBalance == 0) return 0;
uint256 rewardPerSecond = totalReward.div(
(endingDate.sub(startingDate))
);
return (rewardPerSecond);
}
function stake(
uint256 amount
) external hasAllowance(msg.sender, amount, tokenAddress) returns (bool) {
require(!isPaused, "Contract is paused");
require(
block.timestamp >= startingDate && block.timestamp < endingDate,
"No active pool (time)"
);
require(amount > 0, "Can't stake 0 amount");
return (__stake(msg.sender, amount));
}
function __stake(address from, uint256 amount) private returns (bool) {
__updateShare();
if (!hasStaked[from]) {
deposits[from] = Deposits({
amount: amount,
latestStakeAt: block.timestamp,
latestClaimAt: block.timestamp,
userAccShare: accShare,
currentPeriod: periodCounter
});
totalParticipants = totalParticipants.add(1);
hasStaked[from] = true;
}
else {
if (deposits[from].currentPeriod != periodCounter) {
bool renew_ = __renew(from);
require(renew_, "Error renewing");
}
else {
bool claim = __claimRewards(from);
require(claim, "Error paying rewards");
}
uint256 userAmount = deposits[from].amount;
deposits[from] = Deposits({
amount: userAmount.add(amount),
latestStakeAt: block.timestamp,
latestClaimAt: block.timestamp,
userAccShare: accShare,
currentPeriod: periodCounter
});
}
stakedBalanceCurrPeriod = stakedBalanceCurrPeriod.add(amount);
totalStaked = totalStaked.add(amount);
currentStakedBalance += amount;
if (!__payMe(from, amount, tokenAddress)) {
return false;
}
emit Staked(tokenAddress, from, amount);
return true;
}
function userDeposits(
address from
) external view returns (Deposits memory deposit) {
return deposits[from];
}
function fetchUserShare(address from) public view returns (uint256) {
require(hasStaked[from], "No stakes found for user");
if (stakedBalanceCurrPeriod == 0) {
return 0;
}
require(
deposits[from].currentPeriod == periodCounter,
"Please renew in the active valid periodCounter"
);
uint256 userAmount = deposits[from].amount;
require(userAmount > 0, "No stakes available for user");
return 1;
}
function claimRewards() public returns (bool) {
require(!isPaused, "Contract paused");
require(fetchUserShare(msg.sender) > 0, "No stakes found for user");
return (__claimRewards(msg.sender));
}
function __claimRewards(address from) private returns (bool) {
uint256 userAccShare = deposits[from].userAccShare;
__updateShare();
uint256 amount = deposits[from].amount;
uint256 rewDebt = amount.mul(userAccShare).div(1e6);
uint256 rew = (amount.mul(accShare).div(1e6)).sub(rewDebt);
require(rew > 0, "No rewards generated");
require(rew <= rewardBalance, "Not enough rewards in the contract");
deposits[from].userAccShare = accShare;
deposits[from].latestClaimAt = block.timestamp;
rewardBalance = rewardBalance.sub(rew);
bool payRewards = __payDirect(from, rew, rewardTokenAddress);
require(payRewards, "Rewards transfer failed");
emit PaidOut(tokenAddress, rewardTokenAddress, from, amount, rew);
return true;
}
function renew() public returns (bool) {
require(!isPaused, "Contract paused");
require(hasStaked[msg.sender], "No stakings found, please stake");
require(
deposits[msg.sender].currentPeriod != periodCounter,
"Already renewed"
);
require(
block.timestamp > startingDate && block.timestamp < endingDate,
"Wrong time"
);
return (__renew(msg.sender));
}
function __renew(address from) private returns (bool) {
__updateShare();
if (_viewOldRewards(from) > 0) {
bool claimed = claimOldRewards();
require(claimed, "Error paying old rewards");
}
deposits[from].currentPeriod = periodCounter;
deposits[from].latestStakeAt = block.timestamp;
deposits[from].latestClaimAt = block.timestamp;
deposits[from].userAccShare = accShare;
stakedBalanceCurrPeriod = stakedBalanceCurrPeriod.add(
deposits[from].amount
);
totalParticipants = totalParticipants.add(1);
return true;
}
function viewOldRewards(address from) public view returns (uint256) {
require(!isPaused, "Contract paused");
require(hasStaked[from], "No stakings found, please stake");
return _viewOldRewards(from);
}
function _viewOldRewards(address from) internal view returns (uint256) {
if (deposits[from].currentPeriod == periodCounter) {
return 0;
}
uint256 userPeriod = deposits[from].currentPeriod;
uint256 accShare1 = endAccShare[userPeriod].accShare;
uint256 userAccShare = deposits[from].userAccShare;
if (deposits[from].latestClaimAt >= endAccShare[userPeriod].endingDate)
return 0;
uint256 amount = deposits[from].amount;
uint256 rewDebt = amount.mul(userAccShare).div(1e6);
uint256 rew = (amount.mul(accShare1).div(1e6)).sub(rewDebt);
require(rew <= rewardBalance, "Not enough rewards");
return (rew);
}
function claimOldRewards() public returns (bool) {
require(!isPaused, "Contract paused");
require(hasStaked[msg.sender], "No stakings found, please stake");
require(
deposits[msg.sender].currentPeriod != periodCounter,
"Already renewed"
);
__saveOldPeriod();
uint256 userPeriod = deposits[msg.sender].currentPeriod;
uint256 accShare1 = endAccShare[userPeriod].accShare;
uint256 userAccShare = deposits[msg.sender].userAccShare;
require(
deposits[msg.sender].latestClaimAt <
endAccShare[userPeriod].endingDate,
"Already claimed old rewards"
);
uint256 amount = deposits[msg.sender].amount;
uint256 rewDebt = amount.mul(userAccShare).div(1e6);
uint256 rew = (amount.mul(accShare1).div(1e6)).sub(rewDebt);
require(rew <= rewardBalance, "Not enough rewards");
deposits[msg.sender].latestClaimAt = endAccShare[userPeriod]
.endingDate;
rewardBalance = rewardBalance.sub(rew);
bool paidOldRewards = __payDirect(msg.sender, rew, rewardTokenAddress);
require(paidOldRewards, "Error paying");
emit PaidOut(
tokenAddress,
rewardTokenAddress,
msg.sender,
amount,
rew
);
return true;
}
function calculate(address from) public view returns (uint256) {
if (fetchUserShare(from) == 0) return 0;
return (__calculate(from));
}
function __calculate(address from) private view returns (uint256) {
uint256 userAccShare = deposits[from].userAccShare;
uint256 currentAccShare = accShare;
if (block.timestamp <= lastSharesUpdateTime) {
return 0;
}
if (stakedBalanceCurrPeriod == 0) {
return 0;
}
uint256 secSinceLastPeriod;
if (block.timestamp >= endingDate) {
secSinceLastPeriod = endingDate.sub(lastSharesUpdateTime);
} else {
secSinceLastPeriod = block.timestamp.sub(lastSharesUpdateTime);
}
uint256 rewards = secSinceLastPeriod.mul(rewPerSecond());
uint256 newAccShare = currentAccShare.add(
(rewards.mul(1e6).div(stakedBalanceCurrPeriod))
);
uint256 amount = deposits[from].amount;
uint256 rewDebt = amount.mul(userAccShare).div(1e6);
uint256 rew = (amount.mul(newAccShare).div(1e6)).sub(rewDebt);
return (rew);
}
function emergencyWithdraw() external returns (bool) {
require(
block.timestamp >
deposits[msg.sender].latestStakeAt.add(
lockDuration.mul(SECONDS_PER_HOUR)
),
"Can't withdraw before lock duration"
);
require(hasStaked[msg.sender], "No stakes available for user");
require(!isPaid[msg.sender], "Already Paid");
return (__withdraw(msg.sender, deposits[msg.sender].amount));
}
function __withdraw(address from, uint256 amount) private returns (bool) {
__updateShare();
deposits[from].amount = deposits[from].amount.sub(amount);
if (deposits[from].currentPeriod == periodCounter) {
stakedBalanceCurrPeriod -= amount;
}
bool paid = __payDirect(from, amount, tokenAddress);
require(paid, "Error during withdraw");
if (deposits[from].amount == 0) {
isPaid[from] = true;
hasStaked[from] = false;
if (deposits[from].currentPeriod == periodCounter) {
totalParticipants = totalParticipants.sub(1);
}
delete deposits[from];
}
currentStakedBalance -= amount;
return true;
}
function withdraw(uint256 amount) external returns (bool) {
require(!isPaused, "Contract paused");
require(
block.timestamp >
deposits[msg.sender].latestStakeAt.add(
lockDuration.mul(SECONDS_PER_HOUR)
),
"Can't withdraw before lock duration"
);
require(amount <= deposits[msg.sender].amount, "Wrong value");
if (deposits[msg.sender].currentPeriod == periodCounter) {
if (calculate(msg.sender) > 0) {
bool rewardsPaid = claimRewards();
require(rewardsPaid, "Error paying rewards");
}
}
if (_viewOldRewards(msg.sender) > 0) {
bool oldRewardsPaid = claimOldRewards();
require(oldRewardsPaid, "Error paying old rewards");
}
return (__withdraw(msg.sender, amount));
}
function extendCurrentPeriod(
uint256 rewardsToBeAdded
) external onlyOwner returns (bool) {
require(
block.timestamp > startingDate && block.timestamp < endingDate,
"No active pool (time)"
);
require(rewardsToBeAdded > 0, "Zero rewards");
bool addedRewards = __payMe(
msg.sender,
rewardsToBeAdded,
rewardTokenAddress
);
require(addedRewards, "Error adding rewards");
endingDate = endingDate.add(rewardsToBeAdded.div(rewPerSecond()));
totalReward = totalReward.add(rewardsToBeAdded);
rewardBalance = rewardBalance.add(rewardsToBeAdded);
emit PeriodExtended(periodCounter, endingDate, rewardsToBeAdded);
return true;
}
function __payMe(
address payer,
uint256 amount,
address token
) private returns (bool) {
return __payTo(payer, address(this), amount, token);
}
function __payTo(
address allower,
address receiver,
uint256 amount,
address token
) private returns (bool) {
_erc20Interface = IERC20(token);
_erc20Interface.safeTransferFrom(allower, receiver, amount);
return true;
}
function __payDirect(
address to,
uint256 amount,
address token
) private returns (bool) {
require(
token == tokenAddress || token == rewardTokenAddress,
"Invalid token address"
);
_erc20Interface = IERC20(token);
_erc20Interface.safeTransfer(to, amount);
return true;
}
modifier hasAllowance(
address allower,
uint256 amount,
address token
) {
require(
token == tokenAddress || token == rewardTokenAddress,
"Invalid token address"
);
_erc20Interface = IERC20(token);
uint256 ourAllowance = _erc20Interface.allowance(
allower,
address(this)
);
require(amount <= ourAllowance, "Make sure to add enough allowance");
_;
}
function recoverLostERC20(address token, address to) external onlyOwner {
if (token == address(0)) revert("Token_Zero_Address");
if (to == address(0)) revert("To_Zero_Address");
uint256 amount = IERC20(token).balanceOf(address(this));
if (token == rewardTokenAddress) amount -= rewardBalance;
if (token == tokenAddress) amount -= currentStakedBalance;
IERC20(token).safeTransfer(to, amount);
}
}
文件 5 的 8:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 6 的 8:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 7 的 8:SafeMath.sol
pragma solidity ^0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
文件 8 的 8:draft-IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
{
"compilationTarget": {
"contracts/LockedFarming.sol": "SMD_v5"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 20000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"address","name":"_rewardTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"periodCounter","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startDate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endDate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockDuration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"name":"NewPeriodSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":true,"internalType":"address","name":"staker_","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reward_","type":"uint256"}],"name":"PaidOut","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"periodCounter","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"totalParticipants","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"currentStakedBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalReward","type":"uint256"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"periodCounter","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endDate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewards","type":"uint256"}],"name":"PeriodExtended","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"staker_","type":"address"},{"indexed":false,"internalType":"uint256","name":"stakedAmount_","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"periodCounter","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"totalParticipants","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"currentStakedBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalReward","type":"uint256"}],"name":"UnPaused","type":"event"},{"inputs":[],"name":"SECONDS_PER_HOUR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"}],"name":"calculate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimOldRewards","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentStakedBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emergencyWithdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"endAccShare","outputs":[{"internalType":"uint256","name":"periodCounter","type":"uint256"},{"internalType":"uint256","name":"accShare","type":"uint256"},{"internalType":"uint256","name":"rewPerSecond","type":"uint256"},{"internalType":"uint256","name":"startingDate","type":"uint256"},{"internalType":"uint256","name":"endingDate","type":"uint256"},{"internalType":"uint256","name":"rewards","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endingDate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rewardsToBeAdded","type":"uint256"}],"name":"extendCurrentPeriod","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"}],"name":"fetchUserShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"hasStaked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isPaid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastSharesUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"periodCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"recoverLostERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renew","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewPerSecond","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_rewardAmount","type":"uint256"},{"internalType":"uint256","name":"_start","type":"uint256"},{"internalType":"uint256","name":"_end","type":"uint256"},{"internalType":"uint256","name":"_lockDuration","type":"uint256"}],"name":"setNewPeriod","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakedBalanceCurrPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startingDate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalParticipants","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"}],"name":"userDeposits","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"latestStakeAt","type":"uint256"},{"internalType":"uint256","name":"latestClaimAt","type":"uint256"},{"internalType":"uint256","name":"userAccShare","type":"uint256"},{"internalType":"uint256","name":"currentPeriod","type":"uint256"}],"internalType":"struct SMD_v5.Deposits","name":"deposit","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"}],"name":"viewOldRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]