编译器
0.8.10+commit.fc410830
文件 1 的 5: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;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
文件 2 的 5:GracyStaking.sol
pragma solidity 0.8.10;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract GracyStaking is Ownable {
using SafeCast for uint256;
using SafeCast for int256;
struct Pool {
uint48 lastRewardedTimestamp;
uint16 lastRewardsRangeIndex;
uint96 stakedAmount;
uint96 accumulatedRewardsPerShare;
TimeRange[] timeRanges;
}
struct TimeRange {
uint48 startTimestampDay;
uint48 endTimestampDay;
uint96 rewardsPerHour;
}
struct Position {
uint256 stakedAmount;
int256 rewardsDebt;
}
struct PublicPool {
uint256 stakedAmount;
TimeRange currentTimeRange;
}
struct DashboardStake {
uint256 staked;
uint256 unclaimed;
uint256 rewardsDay;
}
mapping (address => Position) public addressPosition;
IERC20 public immutable GRACY;
uint256 private constant GRACY_PRECISION = 1e18;
uint256 private MIN_STAKE_AMOUNT = 1 * GRACY_PRECISION;
uint256 private constant SECONDS_PER_HOUR = 3600;
uint256 private constant SECONDS_PER_MINUTE = 60;
Pool public pool;
event UpdatePool(
uint256 lastRewardedBlock,
uint256 stakedAmount,
uint256 accumulatedRewardsPerShare
);
event Stake(
address indexed user,
uint64 timestamp,
uint256 amount
);
event Withdraw(
address indexed user,
uint64 timestamp,
uint256 amount
);
event ClaimRewards(
address indexed user,
uint64 timestamp,
uint256 amount
);
event WithdrawAll(
address indexed user,
uint64 timestamp,
uint256 amount,
uint256 rewards
);
event ClaimReStake(
address indexed user,
uint64 timestamp,
uint256 rewards
);
error StakeMoreThanOneGRACY();
error StartMustEqualLastEnd();
error ExceededWithdrawAmount();
error MinAmountMoreThanZeroAmount();
error TimeDiffMustBeMoreThan24Hours();
constructor(address _GRACYTokenAddress) {
GRACY = IERC20(_GRACYTokenAddress);
}
function stakeGRACY(uint256 _amount) private {
if (_amount < MIN_STAKE_AMOUNT) revert StakeMoreThanOneGRACY();
updatePool();
Position storage position = addressPosition[msg.sender];
_stake(position, _amount);
GRACY.transferFrom(msg.sender, address(this), _amount);
emit Stake(
msg.sender,
block.timestamp.toUint64(),
_amount
);
}
function stakeSelfGRACY(uint256 _amount) external {
stakeGRACY(_amount);
}
function claimGRACY() private {
updatePool();
Position storage position = addressPosition[msg.sender];
uint256 rewardsToBeClaimed = _claim(position, msg.sender);
emit ClaimRewards(
msg.sender,
block.timestamp.toUint64(),
rewardsToBeClaimed
);
}
function claimSelfGRACY() external {
claimGRACY();
}
function withdrawGRACY(uint256 _amount) private {
updatePool();
Position storage position = addressPosition[msg.sender];
uint256 rewardsToBeClaimed;
if (_amount == position.stakedAmount) rewardsToBeClaimed = _claim(position, msg.sender);
_withdraw(position, _amount);
GRACY.transfer(msg.sender, _amount);
if (position.stakedAmount == 0) emit WithdrawAll(
msg.sender,
block.timestamp.toUint64(),
_amount,
rewardsToBeClaimed
);
else emit Withdraw(
msg.sender,
block.timestamp.toUint64(),
_amount
);
}
function withdrawSelfGRACY(uint256 _amount) external {
withdrawGRACY(_amount);
}
function claimReStakeGRACY() private {
updatePool();
Position storage position = addressPosition[msg.sender];
uint256 rewardsToBeClaimed = _claimReStake(position);
emit ClaimReStake(
msg.sender,
block.timestamp.toUint64(),
rewardsToBeClaimed
);
}
function claimReStakeSelfGRACY() external {
claimReStakeGRACY();
}
function addTimeRange(
uint256 _amount,
uint256 _startTimestampDay,
uint256 _endTimestampDay
) external onlyOwner
{
uint256 length = pool.timeRanges.length;
if (length > 0) {
if (_startTimestampDay != pool.timeRanges[length-1].endTimestampDay) revert StartMustEqualLastEnd();
}
if (_endTimestampDay - _startTimestampDay < (SECONDS_PER_HOUR * 24)) revert TimeDiffMustBeMoreThan24Hours();
uint256 dayInSeconds = _endTimestampDay - _startTimestampDay;
uint256 rewardsPerHour = _amount * SECONDS_PER_HOUR / dayInSeconds;
TimeRange memory next = TimeRange(_startTimestampDay.toUint48(), _endTimestampDay.toUint48(), rewardsPerHour.toUint96());
pool.timeRanges.push(next);
}
function removeLastTimeRange() external onlyOwner {
pool.timeRanges.pop();
}
function getTimeRangeBy(uint256 _index) public view returns (TimeRange memory) {
return pool.timeRanges[_index];
}
function rewardsBy(uint256 _from, uint256 _to) public view returns (uint256, uint256) {
uint256 currentIndex = pool.lastRewardsRangeIndex;
if (_to < pool.timeRanges[0].startTimestampDay) return (0, currentIndex);
while(_from > pool.timeRanges[currentIndex].endTimestampDay && _to > pool.timeRanges[currentIndex].endTimestampDay) {
unchecked {
++currentIndex;
}
}
uint256 rewards;
TimeRange memory current;
uint256 startTimestamp;
uint256 endTimestamp;
uint256 length = pool.timeRanges.length;
for(uint256 i = currentIndex; i < length;) {
current = pool.timeRanges[i];
startTimestamp = _from <= current.startTimestampDay ? current.startTimestampDay : _from;
endTimestamp = _to <= current.endTimestampDay ? _to : current.endTimestampDay;
rewards = rewards + (endTimestamp - startTimestamp) * current.rewardsPerHour / SECONDS_PER_HOUR;
if(_to <= endTimestamp) {
return (rewards, i);
}
unchecked {
++i;
}
}
return (rewards, length -1);
}
function updatePool() public {
if (block.timestamp < pool.timeRanges[0].startTimestampDay) return;
if (block.timestamp <= pool.lastRewardedTimestamp + SECONDS_PER_HOUR) return;
uint48 lastTimestampDay = pool.timeRanges[pool.timeRanges.length -1].endTimestampDay;
uint48 previousTimestamp = getPreviousTimestampHour().toUint48();
if (pool.stakedAmount == 0) {
pool.lastRewardedTimestamp = previousTimestamp > lastTimestampDay ? lastTimestampDay : previousTimestamp;
return;
}
(uint256 rewards, uint256 index) = rewardsBy(pool.lastRewardedTimestamp, previousTimestamp);
if (pool.lastRewardsRangeIndex != index) {
pool.lastRewardsRangeIndex = index.toUint16();
}
if ((pool.accumulatedRewardsPerShare + (rewards * GRACY_PRECISION) / pool.stakedAmount) > type(uint96).max) return;
pool.accumulatedRewardsPerShare = (pool.accumulatedRewardsPerShare + (rewards * GRACY_PRECISION) / pool.stakedAmount).toUint96();
pool.lastRewardedTimestamp = previousTimestamp > lastTimestampDay ? lastTimestampDay : previousTimestamp;
emit UpdatePool(
pool.lastRewardedTimestamp,
pool.stakedAmount,
pool.accumulatedRewardsPerShare
);
}
function setMinStakeAmount(uint256 _amount) external onlyOwner {
if (_amount == 0) revert MinAmountMoreThanZeroAmount();
MIN_STAKE_AMOUNT = _amount;
}
function getMinStakeAmount() external view returns (uint256) {
return MIN_STAKE_AMOUNT;
}
function getCurrentTimeRangeIndex() private view returns (uint256) {
uint256 current = pool.lastRewardsRangeIndex;
if (block.timestamp < pool.timeRanges[current].startTimestampDay) return current;
for (current = pool.lastRewardsRangeIndex; current < pool.timeRanges.length; ++current) {
TimeRange memory currentTimeRange = pool.timeRanges[current];
if (currentTimeRange.startTimestampDay <= block.timestamp && block.timestamp <= currentTimeRange.endTimestampDay) return current;
}
revert ('distribution ended');
}
function getPublicPool() external view returns (PublicPool memory) {
uint256 current = getCurrentTimeRangeIndex();
return PublicPool(pool.stakedAmount, pool.timeRanges[current]);
}
function stakedTotal(address _address) external view returns (uint256) {
return addressPosition[_address].stakedAmount;
}
function stakedAPR() external view returns (uint256) {
uint256 current = getCurrentTimeRangeIndex();
TimeRange memory currentTimeRange = pool.timeRanges[current];
return (uint256(currentTimeRange.rewardsPerHour) * 24 * 365 * 100 * 1000) / pool.stakedAmount;
}
function getGRACYStake(address _address) public view returns (DashboardStake memory) {
uint256 staked = addressPosition[_address].stakedAmount;
uint256 unclaimed = staked > 0 ? this.pendingRewards(_address) : 0;
Position memory position = addressPosition[_address];
TimeRange memory rewards = getTimeRangeBy(pool.lastRewardsRangeIndex);
uint256 rewardsDay = staked > 0 ? _estimateDayRewards(position, rewards) : 0;
return DashboardStake(staked, unclaimed, rewardsDay);
}
function _estimateDayRewards(Position memory position, TimeRange memory rewards) private view returns (uint256) {
return (position.stakedAmount * uint256(rewards.rewardsPerHour) * 24) / uint256(pool.stakedAmount);
}
function getEstimateGRACYStake(uint256 _amount) public view returns (DashboardStake memory) {
uint256 staked = _amount;
uint256 unclaimed = _amount;
Position memory position = Position(_amount, 0);
TimeRange memory rewards = getTimeRangeBy(pool.lastRewardsRangeIndex);
uint256 rewardsDay = _estimateDayRewardWithAmount(position, rewards);
return DashboardStake(staked, unclaimed, rewardsDay);
}
function _estimateDayRewardWithAmount(Position memory position, TimeRange memory rewards) private view returns (uint256) {
return (position.stakedAmount * uint256(rewards.rewardsPerHour) * 24) / (uint256(pool.stakedAmount) + position.stakedAmount);
}
function pendingRewards(address _address) external view returns (uint256) {
Position memory position = addressPosition[_address];
(uint256 rewardsSinceLastCalculated,) = rewardsBy(pool.lastRewardedTimestamp, getPreviousTimestampHour());
uint256 accumulatedRewardsPerShare = pool.accumulatedRewardsPerShare;
if (block.timestamp > pool.lastRewardedTimestamp + SECONDS_PER_HOUR && pool.stakedAmount != 0) {
accumulatedRewardsPerShare = accumulatedRewardsPerShare + rewardsSinceLastCalculated * GRACY_PRECISION / pool.stakedAmount;
}
return ((position.stakedAmount * accumulatedRewardsPerShare).toInt256() - position.rewardsDebt).toUint256() / GRACY_PRECISION;
}
function getMinute(uint256 timestamp) internal pure returns (uint256 minute) {
uint256 secs = timestamp % SECONDS_PER_HOUR;
minute = secs / SECONDS_PER_MINUTE;
}
function getSecond(uint256 timestamp) internal pure returns (uint256 second) {
second = timestamp % SECONDS_PER_MINUTE;
}
function getPreviousTimestampHour() internal view returns (uint256) {
return block.timestamp - (getMinute(block.timestamp) * 60 + getSecond(block.timestamp));
}
function _stake(Position storage _position, uint256 _amount) private {
_position.stakedAmount += _amount;
pool.stakedAmount += _amount.toUint96();
_position.rewardsDebt += (_amount * pool.accumulatedRewardsPerShare).toInt256();
}
function _claim(Position storage _position, address _recipient) private returns (uint256 rewardsToBeClaimed) {
int256 accumulatedGRACYs = (_position.stakedAmount * uint256(pool.accumulatedRewardsPerShare)).toInt256();
rewardsToBeClaimed = (accumulatedGRACYs - _position.rewardsDebt).toUint256() / GRACY_PRECISION;
_position.rewardsDebt = accumulatedGRACYs;
if (rewardsToBeClaimed != 0) {
GRACY.transfer(_recipient, rewardsToBeClaimed);
}
}
function _claimReStake(Position storage _position) private returns (uint256 rewardsToBeClaimed) {
int256 accumulatedGRACYs = (_position.stakedAmount * uint256(pool.accumulatedRewardsPerShare)).toInt256();
rewardsToBeClaimed = (accumulatedGRACYs - _position.rewardsDebt).toUint256() / GRACY_PRECISION;
_position.rewardsDebt = accumulatedGRACYs;
if (rewardsToBeClaimed != 0) {
_stake(_position, rewardsToBeClaimed);
}
}
function _withdraw(Position storage _position, uint256 _amount) private {
if (_amount > _position.stakedAmount) revert ExceededWithdrawAmount();
_position.stakedAmount -= _amount;
pool.stakedAmount -= _amount.toUint96();
_position.rewardsDebt -= (_amount * pool.accumulatedRewardsPerShare).toInt256();
}
}
文件 3 的 5: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 的 5: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);
}
}
文件 5 的 5:SafeCast.sol
pragma solidity ^0.8.0;
library SafeCast {
function toUint248(uint256 value) internal pure returns (uint248) {
require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
return uint248(value);
}
function toUint240(uint256 value) internal pure returns (uint240) {
require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
return uint240(value);
}
function toUint232(uint256 value) internal pure returns (uint232) {
require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
return uint232(value);
}
function toUint224(uint256 value) internal pure returns (uint224) {
require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
return uint224(value);
}
function toUint216(uint256 value) internal pure returns (uint216) {
require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
return uint216(value);
}
function toUint208(uint256 value) internal pure returns (uint208) {
require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
return uint208(value);
}
function toUint200(uint256 value) internal pure returns (uint200) {
require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
return uint200(value);
}
function toUint192(uint256 value) internal pure returns (uint192) {
require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
return uint192(value);
}
function toUint184(uint256 value) internal pure returns (uint184) {
require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
return uint184(value);
}
function toUint176(uint256 value) internal pure returns (uint176) {
require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
return uint176(value);
}
function toUint168(uint256 value) internal pure returns (uint168) {
require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
return uint168(value);
}
function toUint160(uint256 value) internal pure returns (uint160) {
require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
return uint160(value);
}
function toUint152(uint256 value) internal pure returns (uint152) {
require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
return uint152(value);
}
function toUint144(uint256 value) internal pure returns (uint144) {
require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
return uint144(value);
}
function toUint136(uint256 value) internal pure returns (uint136) {
require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
return uint136(value);
}
function toUint128(uint256 value) internal pure returns (uint128) {
require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
function toUint120(uint256 value) internal pure returns (uint120) {
require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
return uint120(value);
}
function toUint112(uint256 value) internal pure returns (uint112) {
require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
return uint112(value);
}
function toUint104(uint256 value) internal pure returns (uint104) {
require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
return uint104(value);
}
function toUint96(uint256 value) internal pure returns (uint96) {
require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
return uint96(value);
}
function toUint88(uint256 value) internal pure returns (uint88) {
require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
return uint88(value);
}
function toUint80(uint256 value) internal pure returns (uint80) {
require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
return uint80(value);
}
function toUint72(uint256 value) internal pure returns (uint72) {
require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
return uint72(value);
}
function toUint64(uint256 value) internal pure returns (uint64) {
require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
return uint64(value);
}
function toUint56(uint256 value) internal pure returns (uint56) {
require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
return uint56(value);
}
function toUint48(uint256 value) internal pure returns (uint48) {
require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
return uint48(value);
}
function toUint40(uint256 value) internal pure returns (uint40) {
require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
return uint40(value);
}
function toUint32(uint256 value) internal pure returns (uint32) {
require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
return uint32(value);
}
function toUint24(uint256 value) internal pure returns (uint24) {
require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
return uint24(value);
}
function toUint16(uint256 value) internal pure returns (uint16) {
require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
return uint16(value);
}
function toUint8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
}
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
}
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
}
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
}
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
}
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
}
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
}
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
}
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
}
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
}
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
}
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
}
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
}
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
}
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
}
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
}
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
}
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
}
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
}
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
}
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
}
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
}
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
}
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
}
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
}
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
}
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
}
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
}
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
}
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
}
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
}
function toInt256(uint256 value) internal pure returns (int256) {
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}
{
"compilationTarget": {
"contracts/GracyStaking.sol": "GracyStaking"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_GRACYTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ExceededWithdrawAmount","type":"error"},{"inputs":[],"name":"MinAmountMoreThanZeroAmount","type":"error"},{"inputs":[],"name":"StakeMoreThanOneGRACY","type":"error"},{"inputs":[],"name":"StartMustEqualLastEnd","type":"error"},{"inputs":[],"name":"TimeDiffMustBeMoreThan24Hours","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint64","name":"timestamp","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"rewards","type":"uint256"}],"name":"ClaimReStake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint64","name":"timestamp","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClaimRewards","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":"user","type":"address"},{"indexed":false,"internalType":"uint64","name":"timestamp","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"lastRewardedBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"accumulatedRewardsPerShare","type":"uint256"}],"name":"UpdatePool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint64","name":"timestamp","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint64","name":"timestamp","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewards","type":"uint256"}],"name":"WithdrawAll","type":"event"},{"inputs":[],"name":"GRACY","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_startTimestampDay","type":"uint256"},{"internalType":"uint256","name":"_endTimestampDay","type":"uint256"}],"name":"addTimeRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"addressPosition","outputs":[{"internalType":"uint256","name":"stakedAmount","type":"uint256"},{"internalType":"int256","name":"rewardsDebt","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimReStakeSelfGRACY","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimSelfGRACY","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getEstimateGRACYStake","outputs":[{"components":[{"internalType":"uint256","name":"staked","type":"uint256"},{"internalType":"uint256","name":"unclaimed","type":"uint256"},{"internalType":"uint256","name":"rewardsDay","type":"uint256"}],"internalType":"struct GracyStaking.DashboardStake","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getGRACYStake","outputs":[{"components":[{"internalType":"uint256","name":"staked","type":"uint256"},{"internalType":"uint256","name":"unclaimed","type":"uint256"},{"internalType":"uint256","name":"rewardsDay","type":"uint256"}],"internalType":"struct GracyStaking.DashboardStake","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMinStakeAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPublicPool","outputs":[{"components":[{"internalType":"uint256","name":"stakedAmount","type":"uint256"},{"components":[{"internalType":"uint48","name":"startTimestampDay","type":"uint48"},{"internalType":"uint48","name":"endTimestampDay","type":"uint48"},{"internalType":"uint96","name":"rewardsPerHour","type":"uint96"}],"internalType":"struct GracyStaking.TimeRange","name":"currentTimeRange","type":"tuple"}],"internalType":"struct GracyStaking.PublicPool","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getTimeRangeBy","outputs":[{"components":[{"internalType":"uint48","name":"startTimestampDay","type":"uint48"},{"internalType":"uint48","name":"endTimestampDay","type":"uint48"},{"internalType":"uint96","name":"rewardsPerHour","type":"uint96"}],"internalType":"struct GracyStaking.TimeRange","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"pendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"uint48","name":"lastRewardedTimestamp","type":"uint48"},{"internalType":"uint16","name":"lastRewardsRangeIndex","type":"uint16"},{"internalType":"uint96","name":"stakedAmount","type":"uint96"},{"internalType":"uint96","name":"accumulatedRewardsPerShare","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"removeLastTimeRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_from","type":"uint256"},{"internalType":"uint256","name":"_to","type":"uint256"}],"name":"rewardsBy","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setMinStakeAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stakeSelfGRACY","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakedAPR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"stakedTotal","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":"updatePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawSelfGRACY","outputs":[],"stateMutability":"nonpayable","type":"function"}]