文件 1 的 34:AccessControl.sol
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
modifier onlyRole(bytes32 role) {
_checkRole(role, _msgSender());
_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
function hasRole(bytes32 role, address account) public view override returns (bool) {
return _roles[role].members[account];
}
function _checkRole(bytes32 role, address account) internal view {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(uint160(account), 20),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
return _roles[role].adminRole;
}
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
function _grantRole(bytes32 role, address account) private {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) private {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}
文件 2 的 34:Address.sol
pragma solidity ^0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 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);
}
}
}
}
文件 3 的 34: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;
}
}
文件 4 的 34:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 5 的 34:ERC20.sol
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
unchecked {
_approve(sender, _msgSender(), currentAllowance - amount);
}
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
}
return true;
}
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
_afterTokenTransfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
文件 6 的 34:FixedPoint96.sol
pragma solidity >=0.4.0;
library FixedPoint96 {
uint8 internal constant RESOLUTION = 96;
uint256 internal constant Q96 = 0x1000000000000000000000000;
}
文件 7 的 34:FullMath.sol
pragma solidity >=0.4.0;
library FullMath {
function mulDiv(
uint256 a,
uint256 b,
uint256 denominator
) internal pure returns (uint256 result) {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(a, b, not(0))
prod0 := mul(a, b)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
require(denominator > 0);
assembly {
result := div(prod0, denominator)
}
return result;
}
require(denominator > prod1);
uint256 remainder;
assembly {
remainder := mulmod(a, b, denominator)
}
assembly {
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (~denominator + 1);
assembly {
denominator := div(denominator, twos)
}
assembly {
prod0 := div(prod0, twos)
}
assembly {
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inv = (3 * denominator) ^ 2;
inv *= 2 - denominator * inv;
inv *= 2 - denominator * inv;
inv *= 2 - denominator * inv;
inv *= 2 - denominator * inv;
inv *= 2 - denominator * inv;
inv *= 2 - denominator * inv;
result = prod0 * inv;
return result;
}
function mulDivRoundingUp(
uint256 a,
uint256 b,
uint256 denominator
) internal pure returns (uint256 result) {
result = mulDiv(a, b, denominator);
if (mulmod(a, b, denominator) > 0) {
require(result < type(uint256).max);
result++;
}
}
}
文件 8 的 34:GStakingManager.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "./interfaces/IUniswapV3CrossPoolOracle.sol";
import "./interfaces/IGStakingVault.sol";
import "./mock/Mintable.sol";
import "./interfaces/INonfungiblePositionManager.sol";
import "./interfaces/IUniswapPoolV3.sol";
import "./interfaces/IUniswapV3Factory.sol";
import "./libs/SqrtPriceMath.sol";
import "./libs/LiquidityMath.sol";
import "./libs/TickMath.sol";
contract GStakingManager is AccessControl, ReentrancyGuard {
using SafeERC20 for IERC20;
uint64 private constant ACCUMULATED_MULTIPLIER = 1e12;
bytes32 public constant BIG_GUARDIAN_ROLE = 0x05c653944982f4fec5b037dad255d4ecd85c5b85ea2ec7654def404ae5f686ec;
bytes32 public constant GUARDIAN_ROLE = 0x55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041;
bytes32 public constant MINTER_ROLE = 0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6;
uint256 public constant USDC_THRESHOLD = 1000 * 10**6;
uint256 public constant SILVER_PIVOT = 50 days;
uint256 public constant GOLD_PIVOT = 100 days;
uint256 public constant MAX_FAUCET = 50;
uint256 public constant PERCENT = 10000;
struct RewardInfo {
mapping(StakeType => uint256) rewardDebt;
uint256 pendingReward;
}
struct PoolInfo {
IERC20 rewardToken;
mapping(StakeType => uint256) totalReward;
uint256 openTime;
uint256 closeTime;
mapping(StakeType => uint256) lastRewardSecond;
mapping(StakeType => uint256) accRewardPerShare;
uint128 chainId;
PoolType poolType;
}
struct StakeInfo {
uint256 amount;
uint256 startStake;
uint256 nftInGpoolAmount;
}
struct SetTierParam {
address account;
Tier tier;
}
struct SetDateParam {
address account;
uint256 time;
}
struct LockedReward {
address rewardToken;
uint256 amount;
}
struct NFTInfo {
address pool;
address token0;
address token1;
int24 tickLower;
int24 tickUpper;
uint128 liquidity;
uint256 amount0;
uint256 amount1;
}
enum Tier {
NORANK,
BRONZE,
SILVER,
GOLD
}
enum PoolType {
CLAIMABLE,
REWARD_CALC
}
enum StakeType {
GPOOL,
NFT
}
mapping(uint256 => mapping(address => LockedReward)) public lockingAmounts;
mapping(address => bool) public hadStake;
mapping(address => StakeInfo) public stakeInfo;
mapping(uint256 => mapping(address => RewardInfo)) public rewardInfo;
mapping(PoolType => uint256[]) public poolTypes;
mapping(address => uint256) public lockTime;
mapping(address => mapping(uint256 => uint256)) public nftRecords;
PoolInfo[] public poolInfo;
uint256 public totalGpoolStaked;
uint256 public totalNFTStaked;
uint32 public twapPeriod;
uint256 public gpoolRewardPercent = 5000;
uint256 public firstStakingFee;
address payable public feeTo;
IERC20 public gpoolToken;
address public weth;
IERC20 public usdc;
IGStakingVault public vault;
IUniswapV3CrossPoolOracle public oracle;
INonfungiblePositionManager public positionManager;
IUniswapV3Factory public uniswapFactory;
event Stake(address sender, uint256 amount, uint256 startStake);
event StakeNFT(address sender, uint256 tokenId, uint256 amount, uint256 startStake);
event Unstake(address sender, uint256 amount, uint256 startStake);
event UnstakeNFT(address sender, uint256 tokenId, uint256 amount, uint256 startStake);
event ClaimLockedReward(address sender, uint256 poolId, uint256 amount);
event ClaimReward(address sender, uint256 poolId, uint256 amount);
event CreatePool(uint256 poolId, PoolType poolType, uint128 chainId, address rewardToken, uint256 totalReward, uint256 openTime, uint256 closeTime);
event UpdatePoolReward(uint256 poolId, uint256 amountReward);
event UpdatePoolRewardRate(uint256 oldRate, uint256 newRate);
event UpdatePoolTime(uint256 poolId, uint256 startTime, uint256 endTime);
event SetTier(address account, Tier tier, uint256 startStake);
event SetDate(address account, Tier tier, uint256 startDate);
event VaultUpdated(address oldVault, address newVault);
event UpdateFirstStakingFee(uint256 _fee, address payable _feeTo);
modifier validatePoolById(uint256 pid) {
require(pid < poolInfo.length, "StakingPool: pool is not exist");
_;
}
constructor(
IGStakingVault _vault,
IUniswapV3CrossPoolOracle _oracle,
IERC20 _gpoolToken,
IERC20 _usdc,
address _weth,
INonfungiblePositionManager _positionManager,
IUniswapV3Factory _uniswapFactory,
address payable _feeTo,
uint256 _firstStakingFee,
address[] memory _admins
) {
vault = _vault;
oracle = _oracle;
gpoolToken = _gpoolToken;
usdc = _usdc;
weth = _weth;
positionManager = _positionManager;
uniswapFactory = _uniswapFactory;
twapPeriod = 1;
firstStakingFee = _firstStakingFee;
feeTo = _feeTo;
for (uint256 i = 0; i < _admins.length; ++i) {
_setupRole(GUARDIAN_ROLE, _admins[i]);
}
_setRoleAdmin(GUARDIAN_ROLE, BIG_GUARDIAN_ROLE);
_setupRole(GUARDIAN_ROLE, msg.sender);
_setupRole(BIG_GUARDIAN_ROLE, msg.sender);
}
function transferBigGuardian(address _newGuardian) public onlyRole(BIG_GUARDIAN_ROLE) {
require(_newGuardian != address(0) && _newGuardian != msg.sender, "Invalid new guardian");
renounceRole(BIG_GUARDIAN_ROLE, msg.sender);
_setupRole(BIG_GUARDIAN_ROLE, _newGuardian);
}
function updateVaultAddress(address _vault) public onlyRole(BIG_GUARDIAN_ROLE) {
require(_vault != address(0), "Vault address is invalid");
require(_vault != address(vault), "Vault address is exactly the same");
emit VaultUpdated(address(vault), _vault);
vault = IGStakingVault(_vault);
}
function requestTokens(uint256 amount) external {
ERC20Mintable gptoken = ERC20Mintable(address(gpoolToken));
require(amount <= MAX_FAUCET, "Can faucet max 50 token per time");
require(block.timestamp > lockTime[msg.sender], "lock time has not expired. Please try again later");
_setupRole(MINTER_ROLE, msg.sender);
gptoken.mint(msg.sender, amount);
lockTime[msg.sender] = block.timestamp + 1 days;
}
function getTotalStake(StakeType stakeType) public view returns (uint256) {
return stakeType == StakeType.GPOOL ? totalGpoolStaked : totalNFTStaked;
}
function stake(uint256 amount) external payable nonReentrant {
require(gpoolToken.balanceOf(msg.sender) >= amount, "not enough gpool");
_getStakeFeeIfNeed(msg.value, msg.sender);
StakeInfo storage staker = stakeInfo[msg.sender];
require(
gpoolInUSDC(staker.amount + amount + staker.nftInGpoolAmount) >= USDC_THRESHOLD,
"minimum stake does not match"
);
gpoolToken.safeTransferFrom(msg.sender, address(this), amount);
if (staker.startStake == 0) {
staker.startStake = block.timestamp;
}
StakeType stakeType = StakeType.GPOOL;
uint256 length = poolInfo.length;
for (uint256 pid = 0; pid < length; ++pid) {
PoolInfo storage pool = poolInfo[pid];
if (block.timestamp <= pool.openTime) {
continue;
}
RewardInfo storage user = rewardInfo[pid][msg.sender];
updatePool(pid, stakeType);
uint256 pending = ((staker.amount * pool.accRewardPerShare[stakeType]) / ACCUMULATED_MULTIPLIER) -
user.rewardDebt[stakeType];
user.pendingReward = user.pendingReward + pending;
user.rewardDebt[stakeType] =
((staker.amount + amount) * pool.accRewardPerShare[stakeType]) /
ACCUMULATED_MULTIPLIER;
}
staker.amount += amount;
totalGpoolStaked += amount;
emit Stake(msg.sender, amount, staker.startStake);
}
function stakeNFT(uint256 tokenId) public payable nonReentrant {
_getStakeFeeIfNeed(msg.value, msg.sender);
StakeInfo storage staker = stakeInfo[msg.sender];
NFTInfo memory ntfInfo = getAmountFromTokenId(tokenId);
uint256 amout0InGpool = (ntfInfo.token0 == address(gpoolToken))
? ntfInfo.amount0
: tokenInGpool(ntfInfo.token0, ntfInfo.amount0);
uint256 amout1InGpool = (ntfInfo.token1 == address(gpoolToken))
? ntfInfo.amount1
: tokenInGpool(ntfInfo.token1, ntfInfo.amount1);
uint256 amount = amout0InGpool + amout1InGpool;
require(
gpoolInUSDC(staker.amount + amount + staker.nftInGpoolAmount) >= USDC_THRESHOLD,
"minimum stake does not match"
);
positionManager.transferFrom(msg.sender, address(this), tokenId);
if (staker.startStake == 0) {
staker.startStake = block.timestamp;
}
StakeType stakeType = StakeType.NFT;
uint256 length = poolInfo.length;
for (uint256 pid = 0; pid < length; ++pid) {
PoolInfo storage pool = poolInfo[pid];
if (block.timestamp <= pool.openTime) {
continue;
}
RewardInfo storage user = rewardInfo[pid][msg.sender];
updatePool(pid, stakeType);
uint256 pending = ((staker.nftInGpoolAmount * pool.accRewardPerShare[stakeType]) / ACCUMULATED_MULTIPLIER) -
user.rewardDebt[stakeType];
user.pendingReward = user.pendingReward + pending;
user.rewardDebt[stakeType] =
((staker.nftInGpoolAmount + amount) * pool.accRewardPerShare[stakeType]) /
ACCUMULATED_MULTIPLIER;
}
staker.nftInGpoolAmount += amount;
totalNFTStaked += amount;
nftRecords[msg.sender][tokenId] = amount;
emit StakeNFT(msg.sender, tokenId, amount, staker.startStake);
}
function unstake(uint256 amount) external nonReentrant {
StakeInfo storage staker = stakeInfo[msg.sender];
require(amount <= staker.amount, "not enough balance");
uint256 length = poolInfo.length;
for (uint256 pid = 0; pid < length; ++pid) {
_updateUserReward(pid, amount, StakeType.GPOOL);
}
staker.amount -= amount;
totalGpoolStaked -= amount;
if (
(staker.amount + staker.nftInGpoolAmount) == 0 ||
gpoolInUSDC(staker.amount + staker.nftInGpoolAmount) < USDC_THRESHOLD
) {
staker.startStake = 0;
} else {
staker.startStake = block.timestamp;
}
gpoolToken.safeTransfer(msg.sender, amount);
emit Unstake(msg.sender, amount, staker.startStake);
}
function unstakeNFT(uint256 tokenId) external nonReentrant {
StakeInfo storage staker = stakeInfo[msg.sender];
uint256 amount = nftRecords[msg.sender][tokenId];
require(amount > 0, "invalid tokenId");
uint256 length = poolInfo.length;
for (uint256 pid = 0; pid < length; ++pid) {
_updateUserReward(pid, amount, StakeType.NFT);
}
staker.nftInGpoolAmount -= amount;
totalNFTStaked -= amount;
if (
(staker.amount + staker.nftInGpoolAmount) == 0 ||
gpoolInUSDC(staker.amount + staker.nftInGpoolAmount) < USDC_THRESHOLD
) {
staker.startStake = 0;
} else {
staker.startStake = block.timestamp;
}
nftRecords[msg.sender][tokenId] = 0;
positionManager.transferFrom(address(this), msg.sender, tokenId);
emit UnstakeNFT(msg.sender, tokenId, amount, staker.startStake);
}
function _getStakeFeeIfNeed(uint256 amount, address user) private {
if (!hadStake[user]) {
require(amount == firstStakingFee, "Fee is not valid");
hadStake[user] = true;
feeTo.transfer(amount);
} else {
require(amount == 0, "Fee only apply in first staking");
}
}
function _updateUserReward(
uint256 pid,
uint256 amount,
StakeType stakeType
) internal {
PoolInfo storage pool = poolInfo[pid];
if (block.timestamp <= pool.openTime) {
return;
}
RewardInfo storage user = rewardInfo[pid][msg.sender];
StakeInfo storage staker = stakeInfo[msg.sender];
uint256 userAmountByType = (stakeType == StakeType.GPOOL) ? staker.amount : staker.nftInGpoolAmount;
updatePool(pid, stakeType);
uint256 pending = ((userAmountByType * pool.accRewardPerShare[stakeType]) / ACCUMULATED_MULTIPLIER) -
user.rewardDebt[stakeType];
if (pending > 0) {
user.pendingReward = user.pendingReward + pending;
}
user.rewardDebt[stakeType] =
((userAmountByType - amount) * pool.accRewardPerShare[stakeType]) /
ACCUMULATED_MULTIPLIER;
}
function claimLockedReward(uint256 pid) public validatePoolById(pid) returns (uint256) {
require(getTier(msg.sender) == Tier.GOLD, "Be gold to claim!");
LockedReward memory lockedReward = lockingAmounts[pid][msg.sender];
require(lockedReward.amount > 0, "Nothing to claim!");
vault.claimReward(address(lockedReward.rewardToken), msg.sender, lockedReward.amount);
emit ClaimLockedReward(msg.sender, pid, lockedReward.amount);
delete lockingAmounts[pid][msg.sender];
return lockedReward.amount;
}
function claimReward(uint256 pid) public validatePoolById(pid) returns (uint256) {
Tier userTier = getTier(msg.sender);
require(getTier(msg.sender) != Tier.NORANK, "only tier");
require(
gpoolInUSDC(stakeInfo[msg.sender].amount + stakeInfo[msg.sender].nftInGpoolAmount) >= USDC_THRESHOLD,
"minimum stake does not match"
);
PoolInfo storage pool = poolInfo[pid];
require(pool.poolType == PoolType.CLAIMABLE, "Not able to claim from reward_calc pool!");
if (block.timestamp <= pool.openTime) {
return 0;
}
updatePool(pid, StakeType.GPOOL);
updatePool(pid, StakeType.NFT);
RewardInfo storage user = rewardInfo[pid][msg.sender];
StakeInfo storage staker = stakeInfo[msg.sender];
LockedReward memory lockedReward = lockingAmounts[pid][msg.sender];
uint256 totalPending = pendingReward(pid, msg.sender);
user.pendingReward = 0;
user.rewardDebt[StakeType.GPOOL] =
(staker.amount * pool.accRewardPerShare[StakeType.GPOOL]) /
(ACCUMULATED_MULTIPLIER);
user.rewardDebt[StakeType.NFT] =
(staker.nftInGpoolAmount * pool.accRewardPerShare[StakeType.NFT]) /
(ACCUMULATED_MULTIPLIER);
if (totalPending > 0) {
uint256 rewardByTier = (totalPending * uint256(userTier)) / uint256(Tier.GOLD);
uint256 lockedAmount = totalPending - rewardByTier;
_lockUserReward(msg.sender, pid, lockedAmount);
vault.claimReward(address(pool.rewardToken), msg.sender, rewardByTier);
totalPending = rewardByTier;
}
if (userTier == Tier.GOLD && lockedReward.amount > 0) {
vault.claimReward(address(pool.rewardToken), msg.sender, lockedReward.amount);
emit ClaimLockedReward(msg.sender, pid, lockedReward.amount);
delete lockingAmounts[pid][msg.sender];
}
emit ClaimReward(msg.sender, pid, totalPending);
return totalPending;
}
function claimAll(uint256[] memory pids) external {
uint256 length = pids.length;
for (uint256 i = 0; i < length; ++i) {
claimReward(pids[i]);
}
}
function pendingReward(uint256 pid, address userAddress) public view validatePoolById(pid) returns (uint256) {
PoolInfo storage pool = poolInfo[pid];
RewardInfo storage user = rewardInfo[pid][userAddress];
StakeInfo memory staker = stakeInfo[userAddress];
uint256 accRewardPerShareGpool = pool.accRewardPerShare[StakeType.GPOOL];
uint256 accRewardPerShareNFT = pool.accRewardPerShare[StakeType.NFT];
uint256 endTime = pool.closeTime < block.timestamp ? pool.closeTime : block.timestamp;
if (endTime > pool.lastRewardSecond[StakeType.GPOOL] && totalGpoolStaked != 0) {
uint256 poolReward = (pool.totalReward[StakeType.GPOOL] *
(endTime - pool.lastRewardSecond[StakeType.GPOOL])) / (pool.closeTime - pool.openTime);
accRewardPerShareGpool = (accRewardPerShareGpool +
((poolReward * ACCUMULATED_MULTIPLIER) / totalGpoolStaked));
}
if (endTime > pool.lastRewardSecond[StakeType.NFT] && totalNFTStaked != 0) {
uint256 poolReward = (pool.totalReward[StakeType.NFT] * (endTime - pool.lastRewardSecond[StakeType.NFT])) /
(pool.closeTime - pool.openTime);
accRewardPerShareNFT = (accRewardPerShareNFT + ((poolReward * ACCUMULATED_MULTIPLIER) / totalNFTStaked));
}
uint256 totalUserDebt = user.rewardDebt[StakeType.NFT] + user.rewardDebt[StakeType.GPOOL];
uint256 totalPendingReward = (user.pendingReward +
(((staker.amount * accRewardPerShareGpool + staker.nftInGpoolAmount * accRewardPerShareNFT) /
ACCUMULATED_MULTIPLIER) - totalUserDebt));
return totalPendingReward;
}
function updatePool(uint256 pid, StakeType stakeType) public validatePoolById(pid) {
PoolInfo storage pool = poolInfo[pid];
uint256 endTime = pool.closeTime < block.timestamp ? pool.closeTime : block.timestamp;
if (endTime <= pool.lastRewardSecond[stakeType]) {
return;
}
uint256 totalStake = getTotalStake(stakeType);
if (totalStake == 0) {
pool.lastRewardSecond[stakeType] = endTime;
return;
}
uint256 poolReward = (pool.totalReward[stakeType] * (endTime - pool.lastRewardSecond[stakeType])) /
(pool.closeTime - pool.openTime);
uint256 deltaRewardPerShare = (poolReward * ACCUMULATED_MULTIPLIER) / totalStake;
if (deltaRewardPerShare == 0 && block.timestamp < pool.closeTime) {
return;
}
pool.accRewardPerShare[stakeType] = pool.accRewardPerShare[stakeType] + deltaRewardPerShare;
pool.lastRewardSecond[stakeType] = endTime;
}
function massUpdatePools() public {
uint256 length = poolInfo.length;
for (uint256 pid = 0; pid < length; ++pid) {
updatePool(pid, StakeType.GPOOL);
updatePool(pid, StakeType.NFT);
}
}
function createPool(
IERC20 rewardToken,
uint256 totalReward,
uint256 openTime,
uint256 closeTime,
PoolType poolType,
uint128 chainId
) external onlyRole(GUARDIAN_ROLE) {
require(block.timestamp <= openTime, "only future");
require(closeTime > openTime, "invalid time");
require(totalReward > 0, "invalid totalReward");
massUpdatePools();
if (poolType == PoolType.CLAIMABLE) {
require(rewardToken.balanceOf(msg.sender) >= totalReward, "not enough token balance");
rewardToken.safeTransferFrom(msg.sender, address(vault), totalReward);
}
poolInfo.push();
PoolInfo storage pool = poolInfo[poolInfo.length - 1];
pool.rewardToken = rewardToken;
pool.totalReward[StakeType.GPOOL] = (totalReward * gpoolRewardPercent) / PERCENT;
pool.totalReward[StakeType.NFT] = totalReward - pool.totalReward[StakeType.GPOOL];
pool.openTime = openTime;
pool.closeTime = closeTime;
pool.lastRewardSecond[StakeType.GPOOL] = openTime;
pool.lastRewardSecond[StakeType.NFT] = openTime;
pool.poolType = poolType;
pool.chainId = chainId;
uint256 pid = poolInfo.length - 1;
poolTypes[poolType].push(pid);
emit CreatePool(pid, poolType, chainId, address(rewardToken), totalReward, openTime, closeTime);
}
function updatePoolTime(
uint256 pid,
uint256 startTime,
uint256 endTime
) external onlyRole(GUARDIAN_ROLE) validatePoolById(pid) {
PoolInfo storage pool = poolInfo[pid];
require(pool.openTime > block.timestamp, "pool started");
require(block.timestamp <= startTime, "only future");
require(endTime > startTime, "invalid time");
pool.openTime = startTime;
pool.closeTime = endTime;
pool.lastRewardSecond[StakeType.GPOOL] = startTime;
pool.lastRewardSecond[StakeType.NFT] = startTime;
emit UpdatePoolTime(pid, startTime, endTime);
}
function updatePoolReward(uint256 pid, uint256 amountReward)
external
onlyRole(GUARDIAN_ROLE)
validatePoolById(pid)
{
PoolInfo storage pool = poolInfo[pid];
require(pool.openTime > block.timestamp, "pool started");
require(amountReward > 0, "invalid totalReward");
uint256 oldTotalReward = pool.totalReward[StakeType.NFT] + pool.totalReward[StakeType.GPOOL];
pool.totalReward[StakeType.GPOOL] = (amountReward * gpoolRewardPercent) / PERCENT;
pool.totalReward[StakeType.NFT] = amountReward - pool.totalReward[StakeType.GPOOL];
if (pool.poolType == PoolType.CLAIMABLE) {
if (amountReward > oldTotalReward) {
pool.rewardToken.safeTransferFrom(msg.sender, address(vault), amountReward - oldTotalReward);
} else if (amountReward < oldTotalReward) {
vault.claimReward(address(pool.rewardToken), msg.sender, oldTotalReward - amountReward);
}
}
emit UpdatePoolReward(pid, amountReward);
}
function updatePoolRewardRate(uint256 _gpoolRewardPercent) public onlyRole(GUARDIAN_ROLE) {
require(_gpoolRewardPercent <= PERCENT, "Rate is not valid");
uint256 oldRate = gpoolRewardPercent;
gpoolRewardPercent = _gpoolRewardPercent;
for (uint256 pid = 0; pid < poolInfo.length; ++pid) {
PoolInfo storage pool = poolInfo[pid];
if (block.timestamp >= pool.openTime) {
continue;
}
uint256 totalRewardByPool = pool.totalReward[StakeType.NFT] + pool.totalReward[StakeType.GPOOL];
pool.totalReward[StakeType.GPOOL] = (totalRewardByPool * gpoolRewardPercent) / PERCENT;
pool.totalReward[StakeType.NFT] = totalRewardByPool - pool.totalReward[StakeType.GPOOL];
}
emit UpdatePoolRewardRate(oldRate, _gpoolRewardPercent);
}
function updateFirstStakingFee(uint256 _fee, address payable _feeTo) public onlyRole(GUARDIAN_ROLE) {
feeTo = _feeTo;
firstStakingFee = _fee;
emit UpdateFirstStakingFee(_fee, _feeTo);
}
function gpoolInUSDC(uint256 gpoolAmount) public view returns (uint256) {
return oracle.assetToAsset(address(gpoolToken), gpoolAmount, address(usdc), twapPeriod);
}
function tokenInGpool(address token, uint256 amount) public view returns (uint256) {
return oracle.assetToAsset(address(token), amount, address(gpoolToken), twapPeriod);
}
function getTier(address user) public view returns (Tier) {
StakeInfo memory staker = stakeInfo[user];
if (staker.startStake == 0) {
return Tier.NORANK;
}
if (block.timestamp <= staker.startStake + SILVER_PIVOT) {
return Tier.BRONZE;
}
if (block.timestamp <= staker.startStake + GOLD_PIVOT) {
return Tier.SILVER;
}
return Tier.GOLD;
}
function setTwapPeriod(uint32 _twapPeriod) external onlyRole(GUARDIAN_ROLE) {
twapPeriod = _twapPeriod;
}
function setTiers(SetTierParam[] calldata params) external onlyRole(GUARDIAN_ROLE) {
uint256 length = params.length;
for (uint256 i = 0; i < length; ++i) {
StakeInfo storage staker = stakeInfo[params[i].account];
uint256 startStake = 0;
if (params[i].tier == Tier.GOLD) {
startStake = block.timestamp - GOLD_PIVOT - 1;
} else if (params[i].tier == Tier.SILVER) {
startStake = block.timestamp - SILVER_PIVOT - 1;
} else if (params[i].tier == Tier.BRONZE) {
startStake = block.timestamp - 1;
}
staker.startStake = startStake;
emit SetTier(params[i].account, params[i].tier, startStake);
}
}
function setDateStake(SetDateParam[] calldata params) external onlyRole(GUARDIAN_ROLE) {
uint256 length = params.length;
for (uint256 i = 0; i < length; ++i) {
StakeInfo storage staker = stakeInfo[params[i].account];
uint256 startStake = block.timestamp - params[i].time - 1;
staker.startStake = startStake;
Tier tier;
if (params[i].time <= 50 days) {
tier = Tier.BRONZE;
} else if (params[i].time <= 100 days) {
tier = Tier.SILVER;
} else {
tier = Tier.GOLD;
}
emit SetDate(params[i].account, tier, startStake);
}
}
function withdrawReward(IERC20 token, uint256 amount) external onlyRole(GUARDIAN_ROLE) {
require(token != gpoolToken, "only reward token");
token.safeTransfer(msg.sender, amount);
}
function _lockUserReward(
address _user,
uint256 _poolId,
uint256 _lockedAmount
) internal {
if (_lockedAmount > 0) {
PoolInfo storage pool = poolInfo[_poolId];
LockedReward memory userLockedReward = lockingAmounts[_poolId][_user];
uint256 updatedLockingAmount = userLockedReward.amount + _lockedAmount;
lockingAmounts[_poolId][_user] = LockedReward(address(pool.rewardToken), updatedLockingAmount);
}
}
function getUniswapPoolInfo(uint256 tokenId) internal view returns (NFTInfo memory info) {
(
,
,
address token0,
address token1,
uint24 fee,
int24 tickLower,
int24 tickUpper,
uint128 liquidity,
,
,
,
) = positionManager.positions(tokenId);
info.pool = uniswapFactory.getPool(token0, token1, fee);
info.tickLower = tickLower;
info.tickUpper = tickUpper;
info.liquidity = liquidity;
info.token0 = token0;
info.token1 = token1;
}
function getAmountFromTokenId(uint256 tokenId) public view returns (NFTInfo memory) {
NFTInfo memory nftInfo = getUniswapPoolInfo(tokenId);
require(_isValidToken(nftInfo.token0, nftInfo.token1), "NFT: Wrong NFT type");
int24 tickLower = nftInfo.tickLower;
int24 tickUpper = nftInfo.tickUpper;
uint128 liquidityDelta = nftInfo.liquidity;
IUniswapPoolV3 uniswapPool = IUniswapPoolV3(nftInfo.pool);
IUniswapPoolV3.Slot0 memory slot = uniswapPool.slot0();
uint128 liquidity = uniswapPool.liquidity();
if (slot.tick < tickLower) {
nftInfo.amount0 = SqrtPriceMath.getAmount0DeltaV2(
TickMath.getSqrtRatioAtTick(tickLower),
TickMath.getSqrtRatioAtTick(tickUpper),
liquidityDelta,
true
);
} else if (slot.tick < tickUpper) {
uint128 liquidityBefore = liquidity;
nftInfo.amount0 = SqrtPriceMath.getAmount0DeltaV2(
slot.sqrtPriceX96,
TickMath.getSqrtRatioAtTick(tickUpper),
liquidityDelta,
true
);
nftInfo.amount1 = SqrtPriceMath.getAmount1DeltaV2(
TickMath.getSqrtRatioAtTick(tickLower),
slot.sqrtPriceX96,
liquidityDelta,
true
);
liquidity = LiquidityMath.addDelta(liquidityBefore, liquidityDelta);
} else {
nftInfo.amount1 = SqrtPriceMath.getAmount1DeltaV2(
TickMath.getSqrtRatioAtTick(tickLower),
TickMath.getSqrtRatioAtTick(tickUpper),
liquidityDelta,
true
);
}
return nftInfo;
}
function _isValidToken(address token0, address token1) private view returns (bool) {
if ((token0 == weth && token1 == address(gpoolToken)) || (token1 == weth && token0 == address(gpoolToken))) {
return true;
}
return false;
}
}
文件 9 的 34:IAccessControl.sol
pragma solidity ^0.8.0;
interface IAccessControl {
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
文件 10 的 34:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 11 的 34:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, 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 sender,
address recipient,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 12 的 34:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 13 的 34:IERC721.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
文件 14 的 34:IERC721Enumerable.sol
pragma solidity ^0.8.0;
import "../IERC721.sol";
interface IERC721Enumerable is IERC721 {
function totalSupply() external view returns (uint256);
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);
function tokenByIndex(uint256 index) external view returns (uint256);
}
文件 15 的 34:IERC721Metadata.sol
pragma solidity ^0.8.0;
import "../IERC721.sol";
interface IERC721Metadata is IERC721 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
文件 16 的 34:IERC721Permit.sol
pragma solidity >=0.7.5;
import '@openzeppelin/contracts/token/ERC721/IERC721.sol';
interface IERC721Permit is IERC721 {
function PERMIT_TYPEHASH() external pure returns (bytes32);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function permit(
address spender,
uint256 tokenId,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external payable;
}
文件 17 的 34:IGStakingVault.sol
pragma solidity ^0.8.0;
interface IGStakingVault {
function claimReward(address _token, address _receiver, uint _amount) external;
function recoverFund(address _token, address _receiver) external;
}
文件 18 的 34:INonfungiblePositionManager.sol
pragma solidity >=0.8.0;
pragma abicoder v2;
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
import "@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol";
import "@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol";
import "@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol";
import "@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol";
interface INonfungiblePositionManager is
IPoolInitializer,
IPeripheryPayments,
IPeripheryImmutableState,
IERC721Metadata,
IERC721Enumerable,
IERC721Permit
{
event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);
event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);
event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);
function positions(uint256 tokenId)
external
view
returns (
uint96 nonce,
address operator,
address token0,
address token1,
uint24 fee,
int24 tickLower,
int24 tickUpper,
uint128 liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128,
uint128 tokensOwed0,
uint128 tokensOwed1
);
struct MintParams {
address token0;
address token1;
uint24 fee;
int24 tickLower;
int24 tickUpper;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
address recipient;
uint256 deadline;
}
function mint(MintParams calldata params)
external
payable
returns (
uint256 tokenId,
uint128 liquidity,
uint256 amount0,
uint256 amount1
);
struct IncreaseLiquidityParams {
uint256 tokenId;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
function increaseLiquidity(IncreaseLiquidityParams calldata params)
external
payable
returns (
uint128 liquidity,
uint256 amount0,
uint256 amount1
);
struct DecreaseLiquidityParams {
uint256 tokenId;
uint128 liquidity;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
function decreaseLiquidity(DecreaseLiquidityParams calldata params)
external
payable
returns (uint256 amount0, uint256 amount1);
struct CollectParams {
uint256 tokenId;
address recipient;
uint128 amount0Max;
uint128 amount1Max;
}
function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);
function burn(uint256 tokenId) external payable;
}
文件 19 的 34:IPeripheryImmutableState.sol
pragma solidity >=0.5.0;
interface IPeripheryImmutableState {
function factory() external view returns (address);
function WETH9() external view returns (address);
}
文件 20 的 34:IPeripheryPayments.sol
pragma solidity >=0.7.5;
interface IPeripheryPayments {
function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;
function refundETH() external payable;
function sweepToken(
address token,
uint256 amountMinimum,
address recipient
) external payable;
}
文件 21 的 34:IPoolInitializer.sol
pragma solidity >=0.7.5;
pragma abicoder v2;
interface IPoolInitializer {
function createAndInitializePoolIfNecessary(
address token0,
address token1,
uint24 fee,
uint160 sqrtPriceX96
) external payable returns (address pool);
}
文件 22 的 34:IUniswapPoolV3.sol
pragma solidity ^0.8.0;
interface IUniswapPoolV3 {
struct Slot0 {
uint160 sqrtPriceX96;
int24 tick;
uint16 observationIndex;
uint16 observationCardinality;
uint16 observationCardinalityNext;
uint8 feeProtocol;
bool unlocked;
}
function slot0() external view returns (Slot0 memory);
function liquidity() external view returns (uint128);
}
文件 23 的 34:IUniswapV3CrossPoolOracle.sol
pragma solidity ^0.8.0;
interface IUniswapV3CrossPoolOracle {
function assetToAsset(
address _tokenIn,
uint256 _amountIn,
address _tokenOut,
uint32 _twapPeriod
) external view returns (uint256 amountOut);
}
文件 24 的 34:IUniswapV3Factory.sol
pragma solidity >=0.5.0;
interface IUniswapV3Factory {
function getPool(
address tokenA,
address tokenB,
uint24 fee
) external view returns (address pool);
}
文件 25 的 34:LiquidityMath.sol
pragma solidity >=0.5.0;
library LiquidityMath {
function addDelta(uint128 x, uint128 y) internal pure returns (uint128 z) {
require((z = x + uint128(y)) >= x, 'LA');
}
}
文件 26 的 34:LowGasSafeMath.sol
pragma solidity >=0.7.0;
library LowGasSafeMath {
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x + y) >= x);
}
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x - y) <= x);
}
function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
require(x == 0 || (z = x * y) / x == y);
}
function add(int256 x, int256 y) internal pure returns (int256 z) {
require((z = x + y) >= x == (y >= 0));
}
function sub(int256 x, int256 y) internal pure returns (int256 z) {
require((z = x - y) <= x == (y >= 0));
}
}
文件 27 的 34:Mintable.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
abstract contract ERC20Mintable is ERC20 {
bool private _mintingFinished = false;
event MintFinished();
modifier canMint() {
require(!_mintingFinished, "ERC20Mintable: minting is finished");
_;
}
function mintingFinished() public view returns (bool) {
return _mintingFinished;
}
function mint(address account, uint256 amount) public canMint {
_mint(account, amount);
}
function finishMinting() public canMint {
_finishMinting();
}
function _finishMinting() internal virtual {
_mintingFinished = true;
emit MintFinished();
}
}
文件 28 的 34:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 29 的 34:SafeCast.sol
pragma solidity >=0.5.0;
library SafeCast {
function toUint160(uint256 y) internal pure returns (uint160 z) {
require((z = uint160(y)) == y);
}
function toInt128(int256 y) internal pure returns (int128 z) {
require((z = int128(y)) == y);
}
function toInt256(uint256 y) internal pure returns (int256 z) {
require(y < 2**255);
z = int256(y);
}
}
文件 30 的 34:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.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 _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");
}
}
}
文件 31 的 34:SqrtPriceMath.sol
pragma solidity >=0.5.0;
import "./LowGasSafeMath.sol";
import "./SafeCast.sol";
import "./FullMath.sol";
import "./UnsafeMath.sol";
import "./FixedPoint96.sol";
library SqrtPriceMath {
using LowGasSafeMath for uint256;
using SafeCast for uint256;
function getNextSqrtPriceFromAmount0RoundingUp(
uint160 sqrtPX96,
uint128 liquidity,
uint256 amount,
bool add
) internal pure returns (uint160) {
if (amount == 0) return sqrtPX96;
uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;
if (add) {
uint256 product;
if ((product = amount * sqrtPX96) / amount == sqrtPX96) {
uint256 denominator = numerator1 + product;
if (denominator >= numerator1)
return uint160(FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator));
}
return uint160(UnsafeMath.divRoundingUp(numerator1, (numerator1 / sqrtPX96).add(amount)));
} else {
uint256 product;
require((product = amount * sqrtPX96) / amount == sqrtPX96 && numerator1 > product);
uint256 denominator = numerator1 - product;
return FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator).toUint160();
}
}
function getNextSqrtPriceFromAmount1RoundingDown(
uint160 sqrtPX96,
uint128 liquidity,
uint256 amount,
bool add
) internal pure returns (uint160) {
if (add) {
uint256 quotient =
(
amount <= type(uint160).max
? (amount << FixedPoint96.RESOLUTION) / liquidity
: FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity)
);
return uint256(sqrtPX96).add(quotient).toUint160();
} else {
uint256 quotient =
(
amount <= type(uint160).max
? UnsafeMath.divRoundingUp(amount << FixedPoint96.RESOLUTION, liquidity)
: FullMath.mulDivRoundingUp(amount, FixedPoint96.Q96, liquidity)
);
require(sqrtPX96 > quotient);
return uint160(sqrtPX96 - quotient);
}
}
function getNextSqrtPriceFromInput(
uint160 sqrtPX96,
uint128 liquidity,
uint256 amountIn,
bool zeroForOne
) internal pure returns (uint160 sqrtQX96) {
require(sqrtPX96 > 0);
require(liquidity > 0);
return
zeroForOne
? getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountIn, true)
: getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountIn, true);
}
function getNextSqrtPriceFromOutput(
uint160 sqrtPX96,
uint128 liquidity,
uint256 amountOut,
bool zeroForOne
) internal pure returns (uint160 sqrtQX96) {
require(sqrtPX96 > 0);
require(liquidity > 0);
return
zeroForOne
? getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountOut, false)
: getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountOut, false);
}
function getAmount0DeltaV2(
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96,
uint128 liquidity,
bool roundUp
) internal pure returns (uint256 amount0) {
if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;
uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;
require(sqrtRatioAX96 > 0);
return
roundUp
? UnsafeMath.divRoundingUp(
FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),
sqrtRatioAX96
)
: FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;
}
function getAmount1DeltaV2(
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96,
uint128 liquidity,
bool roundUp
) internal pure returns (uint256 amount1) {
if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
return
roundUp
? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)
: FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);
}
function getAmount0Delta(
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96,
int128 liquidity
) internal pure returns (int256 amount0) {
return
liquidity < 0
? -getAmount0DeltaV2(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()
: getAmount0DeltaV2(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();
}
function getAmount1Delta(
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96,
int128 liquidity
) internal pure returns (int256 amount1) {
return
liquidity < 0
? -getAmount1DeltaV2(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()
: getAmount1DeltaV2(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();
}
}
文件 32 的 34:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
文件 33 的 34:TickMath.sol
pragma solidity >=0.5.0;
library TickMath {
int24 internal constant MIN_TICK = -887272;
int24 internal constant MAX_TICK = -MIN_TICK;
uint160 internal constant MIN_SQRT_RATIO = 4295128739;
uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;
function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {
uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));
require(absTick <= uint256(int256(MAX_TICK)), 'T');
uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;
if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;
if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;
if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;
if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;
if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;
if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;
if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;
if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;
if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;
if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;
if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;
if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;
if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;
if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;
if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;
if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;
if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;
if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;
if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;
if (tick > 0) ratio = type(uint256).max / ratio;
sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));
}
function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {
require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');
uint256 ratio = uint256(sqrtPriceX96) << 32;
uint256 r = ratio;
uint256 msb = 0;
assembly {
let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(5, gt(r, 0xFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(4, gt(r, 0xFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(3, gt(r, 0xFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(2, gt(r, 0xF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(1, gt(r, 0x3))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := gt(r, 0x1)
msb := or(msb, f)
}
if (msb >= 128) r = ratio >> (msb - 127);
else r = ratio << (127 - msb);
int256 log_2 = (int256(msb) - 128) << 64;
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(63, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(62, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(61, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(60, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(59, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(58, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(57, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(56, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(55, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(54, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(53, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(52, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(51, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(50, f))
}
int256 log_sqrt10001 = log_2 * 255738958999603826347141;
int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);
int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);
tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;
}
}
文件 34 的 34:UnsafeMath.sol
pragma solidity >=0.5.0;
library UnsafeMath {
function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := add(div(x, y), gt(mod(x, y), 0))
}
}
}
{
"compilationTarget": {
"contracts/GStakingManager.sol": "GStakingManager"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "none",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IGStakingVault","name":"_vault","type":"address"},{"internalType":"contract IUniswapV3CrossPoolOracle","name":"_oracle","type":"address"},{"internalType":"contract IERC20","name":"_gpoolToken","type":"address"},{"internalType":"contract IERC20","name":"_usdc","type":"address"},{"internalType":"address","name":"_weth","type":"address"},{"internalType":"contract INonfungiblePositionManager","name":"_positionManager","type":"address"},{"internalType":"contract IUniswapV3Factory","name":"_uniswapFactory","type":"address"},{"internalType":"address payable","name":"_feeTo","type":"address"},{"internalType":"uint256","name":"_firstStakingFee","type":"uint256"},{"internalType":"address[]","name":"_admins","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"poolId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClaimLockedReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"poolId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClaimReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"poolId","type":"uint256"},{"indexed":false,"internalType":"enum GStakingManager.PoolType","name":"poolType","type":"uint8"},{"indexed":false,"internalType":"uint128","name":"chainId","type":"uint128"},{"indexed":false,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"openTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"closeTime","type":"uint256"}],"name":"CreatePool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"enum GStakingManager.Tier","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"startDate","type":"uint256"}],"name":"SetDate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"enum GStakingManager.Tier","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"startStake","type":"uint256"}],"name":"SetTier","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startStake","type":"uint256"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startStake","type":"uint256"}],"name":"StakeNFT","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startStake","type":"uint256"}],"name":"Unstake","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startStake","type":"uint256"}],"name":"UnstakeNFT","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_fee","type":"uint256"},{"indexed":false,"internalType":"address payable","name":"_feeTo","type":"address"}],"name":"UpdateFirstStakingFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"poolId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountReward","type":"uint256"}],"name":"UpdatePoolReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"UpdatePoolRewardRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"poolId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"UpdatePoolTime","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldVault","type":"address"},{"indexed":false,"internalType":"address","name":"newVault","type":"address"}],"name":"VaultUpdated","type":"event"},{"inputs":[],"name":"BIG_GUARDIAN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GOLD_PIVOT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUARDIAN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FAUCET","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SILVER_PIVOT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDC_THRESHOLD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"pids","type":"uint256[]"}],"name":"claimAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pid","type":"uint256"}],"name":"claimLockedReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pid","type":"uint256"}],"name":"claimReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"rewardToken","type":"address"},{"internalType":"uint256","name":"totalReward","type":"uint256"},{"internalType":"uint256","name":"openTime","type":"uint256"},{"internalType":"uint256","name":"closeTime","type":"uint256"},{"internalType":"enum GStakingManager.PoolType","name":"poolType","type":"uint8"},{"internalType":"uint128","name":"chainId","type":"uint128"}],"name":"createPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeTo","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"firstStakingFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getAmountFromTokenId","outputs":[{"components":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"},{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"internalType":"struct GStakingManager.NFTInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getTier","outputs":[{"internalType":"enum GStakingManager.Tier","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum GStakingManager.StakeType","name":"stakeType","type":"uint8"}],"name":"getTotalStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"gpoolAmount","type":"uint256"}],"name":"gpoolInUSDC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gpoolRewardPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gpoolToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"hadStake","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lockTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"lockingAmounts","outputs":[{"internalType":"address","name":"rewardToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"massUpdatePools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"nftRecords","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract IUniswapV3CrossPoolOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pid","type":"uint256"},{"internalType":"address","name":"userAddress","type":"address"}],"name":"pendingReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolInfo","outputs":[{"internalType":"contract IERC20","name":"rewardToken","type":"address"},{"internalType":"uint256","name":"openTime","type":"uint256"},{"internalType":"uint256","name":"closeTime","type":"uint256"},{"internalType":"uint128","name":"chainId","type":"uint128"},{"internalType":"enum GStakingManager.PoolType","name":"poolType","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum GStakingManager.PoolType","name":"","type":"uint8"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolTypes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"positionManager","outputs":[{"internalType":"contract INonfungiblePositionManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"requestTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"rewardInfo","outputs":[{"internalType":"uint256","name":"pendingReward","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"time","type":"uint256"}],"internalType":"struct GStakingManager.SetDateParam[]","name":"params","type":"tuple[]"}],"name":"setDateStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"enum GStakingManager.Tier","name":"tier","type":"uint8"}],"internalType":"struct GStakingManager.SetTierParam[]","name":"params","type":"tuple[]"}],"name":"setTiers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_twapPeriod","type":"uint32"}],"name":"setTwapPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakeInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"startStake","type":"uint256"},{"internalType":"uint256","name":"nftInGpoolAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"stakeNFT","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"tokenInGpool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalGpoolStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalNFTStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newGuardian","type":"address"}],"name":"transferBigGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"twapPeriod","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapFactory","outputs":[{"internalType":"contract IUniswapV3Factory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"unstakeNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"address payable","name":"_feeTo","type":"address"}],"name":"updateFirstStakingFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pid","type":"uint256"},{"internalType":"enum GStakingManager.StakeType","name":"stakeType","type":"uint8"}],"name":"updatePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pid","type":"uint256"},{"internalType":"uint256","name":"amountReward","type":"uint256"}],"name":"updatePoolReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gpoolRewardPercent","type":"uint256"}],"name":"updatePoolRewardRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pid","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"updatePoolTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"}],"name":"updateVaultAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usdc","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract IGStakingVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawReward","outputs":[],"stateMutability":"nonpayable","type":"function"}]