/*
* OpenGPU Network World's Leading Decentralized GPU Ecosystem
*
* Website: https://opengpu.network/
* Staking: https://stake.opengpu.network/
* Telegram: https://t.me/opengpuportal
* Twitter: https://x.com/opengpunetwork
* Whitepaper: https://opengpu.network/docs/whitepaper.pdf
* Yellowpaper: https://opengpu.network/docs/yellowpaper.pdf
*
*/
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
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);
}
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(_owner == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
* consider using {ReentrancyGuardTransient} instead.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}
interface IUniswapV2Factory {
function createPair(address tokenA, address tokenB) external returns (address pair);
}
interface IUniswapV2Router02 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
contract oGPUStaking is Ownable, ReentrancyGuard {
IERC20 public oGPU;
uint256 public gpuId;
struct UserInfo {
address user; // User address
uint256 poolId; // Pool ID
uint256 amount; // How many oGPU tokens the user has provided.
uint256 stakeTime; // Time when user staked
uint256 points; // How many points the user has, accumulated.
uint256 gpuId; // GPU gpuId
bool claimed; // default false
uint256 lastBoostTime; // Last time user boosted
uint256 claimedETH; // Claimed ETH
uint256 claimedoGPU; // Claimed oGPU
}
struct UserInfoWithShares {
address user; // User address
uint256 poolId; // Pool ID
uint256 amount; // How many oGPU tokens the user has provided.
uint256 stakeTime; // Time when user staked
uint256 points; // How many points the user has, accumulated.
uint256 gpuId; // GPU gpuId
bool claimed; // default false
uint256 lastBoostTime; // Last time user boosted
uint256 claimedETH; // Claimed ETH
uint256 claimedoGPU; // Claimed oGPU
uint256 share; // User share of ETH
}
struct PoolInfo {
uint256 poolId; // Pool ID
uint256 totalPoints; // Total points accumulated by all users
uint256 totalAmount; // Total amount of oGPU tokens staked
uint256 totalETHStaked; // Total ETH share
uint256 startTime; // Start time of the pool
uint256 duration; // Duration of the pool
uint256 endTime; // End time of the pools
bool ended; // default false
}
PoolInfo[] public poolInfo;
mapping (uint256 => mapping (address => UserInfo)) public userInfoMap;
mapping (uint256 => UserInfo[]) public poolUsers;
mapping (address => mapping (uint256 => uint256)) public userPoolIndex;
event EmergencyWithdraw(address indexed user, uint256 poolId, uint256 amount);
event Claimed(address indexed user, uint256 poolId, uint256 amount);
event PoolEnded(uint256 poolId, uint256 endTime);
event Staked(address indexed user, uint256 amount, uint256 gpuType);
event PoolCreated(uint256 stakeID, uint256 stakingStartTimestamp, uint256 duration, uint256 stakingEndTimestamp);
constructor(IERC20 _oGPU) {
oGPU = _oGPU;
}
receive() external payable {
}
function createPool(uint256 _duration) external onlyOwner {
require(_duration <= 90 days, "Staking: duration should be less than 90 days");
uint256 _poolId = poolInfo.length;
uint256 _startTime = block.timestamp;
uint256 _endTime = _startTime + _duration;
poolInfo.push(PoolInfo({
poolId: _poolId,
totalPoints: 0,
totalAmount: 0,
totalETHStaked: 0,
startTime: _startTime,
duration: _duration,
endTime: _endTime,
ended: false
}));
emit PoolCreated(_poolId, _startTime, _duration, _endTime);
}
function stake(uint256 _poolId, uint256 _amount, uint256 _gpuID) external nonReentrant {
require(_amount > 0, "Staking: amount must be greater than 0");
require(_poolId < poolInfo.length, "Staking: invalid pool id");
PoolInfo storage pool = poolInfo[_poolId];
require(block.timestamp >= pool.startTime, "Staking: pool not started");
require(block.timestamp < pool.endTime, "Staking: pool ended");
require(!pool.ended, "Staking: pool ended");
oGPU.transferFrom(msg.sender, address(this), _amount);
UserInfo storage user = userInfoMap[_poolId][msg.sender];
// if user.amount is zero and userpoolindex is zero, then user is new
if (user.amount == 0 && userPoolIndex[msg.sender][_poolId] == 0) {
user.user = msg.sender;
user.stakeTime = block.timestamp;
user.poolId = _poolId;
user.lastBoostTime = block.timestamp;
user.gpuId = _gpuID;
user.amount = _amount;
uint256 totalStakeTime = pool.endTime - block.timestamp;
uint256 _points = _amount * (totalStakeTime / 2 days + 1);
pool.totalAmount = pool.totalAmount + _amount;
if (_gpuID < 130) {
_points += (_points * 15) / 100;
} else if (_gpuID < 360) {
_points += (_points * 10) / 100;
} else {
_points += (_points * 5) / 100;
}
user.points = _points;
pool.totalPoints = pool.totalPoints + user.points;
uint256 userLength = poolUsers[_poolId].length;
poolUsers[_poolId].push(user);
userPoolIndex[msg.sender][_poolId] = userLength;
} else {
user.gpuId = _gpuID;
user.amount = user.amount + _amount;
uint256 totalStakeTime = pool.endTime - block.timestamp;
uint256 _points = _amount * (totalStakeTime / 2 days + 1);
if (_gpuID < 130) {
_points += (_points * 15) / 100;
} else if (_gpuID < 360) {
_points += (_points * 10) / 100;
} else {
_points += (_points * 5) / 100;
}
user.points += _points;
pool.totalAmount = pool.totalAmount + _amount;
pool.totalPoints = pool.totalPoints + _points;
uint256 userIndex = userPoolIndex[msg.sender][_poolId];
poolUsers[_poolId][userIndex] = user;
}
emit Staked(msg.sender, _poolId, _amount);
}
function boostGPU(uint256 _poolId) external nonReentrant{
require(_poolId < poolInfo.length, "Staking: invalid pool id");
UserInfo storage user = userInfoMap[_poolId][msg.sender];
require(user.amount > 0, "Staking: user has no stake");
require(block.timestamp < poolInfo[_poolId].endTime, "Staking: pool ended");
require(!user.claimed, "Staking: user already claimed");
require(!poolInfo[_poolId].ended, "Staking: pool ended");
// user can boost once every 24 hours
require(block.timestamp - user.lastBoostTime >= 1 days, "Staking: user can boost once every 24 hours");
user.lastBoostTime = block.timestamp;
// update pool points
PoolInfo storage pool = poolInfo[_poolId];
pool.totalPoints -= user.points;
uint256 _gpuID = user.gpuId;
if (_gpuID < 130) {
user.points += (user.points * 3) / 100;
} else if (_gpuID < 360) {
user.points += (user.points * 2) / 100;
} else {
user.points += user.points / 100;
}
pool.totalPoints += user.points;
uint256 userIndex = userPoolIndex[msg.sender][_poolId];
poolUsers[_poolId][userIndex] = user;
}
function claim(uint256 _poolId) external nonReentrant {
require(_poolId < poolInfo.length, "Staking: invalid pool id");
PoolInfo storage pool = poolInfo[_poolId];
UserInfo storage user = userInfoMap[_poolId][msg.sender];
require(pool.ended, "Staking: claim period is not started");
require(user.amount > 0, "Staking: user has no stake");
require(block.timestamp >= pool.endTime, "Staking: pool not ended");
require(!user.claimed, "Staking: user already claimed");
user.claimed = true;
uint256 _amount = user.amount;
user.claimedoGPU = _amount;
user.amount = 0;
oGPU.transfer(msg.sender, _amount);
uint256 _points = user.points;
user.points = 0;
// userpoolindex
uint256 userIndex = userPoolIndex[msg.sender][_poolId];
uint256 _share = (_points * pool.totalETHStaked) / pool.totalPoints;
user.claimedETH = _share;
poolUsers[_poolId][userIndex] = user;
payable(msg.sender).transfer(_share);
emit Claimed(msg.sender, _poolId, _amount);
}
function emergencyWithdraw(uint256 _poolId) external nonReentrant {
require(_poolId < poolInfo.length, "Staking: invalid pool id");
PoolInfo storage pool = poolInfo[_poolId];
UserInfo storage user = userInfoMap[_poolId][msg.sender];
require(user.amount > 0, "Staking: user has no stake");
require(block.timestamp < pool.endTime, "Staking: pool ended");
uint256 _amount = user.amount;
pool.totalAmount -= _amount;
pool.totalPoints -= user.points;
user.amount = 0;
user.points = 0;
uint256 userIndex = userPoolIndex[msg.sender][_poolId];
poolUsers[_poolId][userIndex] = user;
oGPU.transfer(msg.sender, (_amount * 90) / 100);
oGPU.transfer(address(owner()),(_amount * 10)/ 100);
emit EmergencyWithdraw(msg.sender, _poolId, _amount);
}
function endPool(uint256 _poolId) external onlyOwner {
require(_poolId < poolInfo.length, "Staking: invalid pool id");
PoolInfo storage pool = poolInfo[_poolId];
require(block.timestamp >= pool.endTime, "Staking: pool not ended");
pool.ended = true;
emit PoolEnded(_poolId, block.timestamp);
}
function getAllPools() external view returns (PoolInfo[] memory) {
return poolInfo;
}
function getUserInfo(uint256 _poolId, address _user) external view returns (UserInfo memory) {
require(_poolId < poolInfo.length, "Staking: invalid pool id");
return userInfoMap[_poolId][_user];
}
function getPoolUsers(uint256 _poolId) external view returns (UserInfo[] memory) {
require(_poolId < poolInfo.length, "Staking: invalid pool id");
return poolUsers[_poolId];
}
function getPoolUsersWithShares(uint256 _poolId) external view returns (UserInfoWithShares[] memory) {
require(_poolId < poolInfo.length, "Staking: invalid pool id");
if (poolInfo[_poolId].totalPoints == 0) {
return new UserInfoWithShares[](0);
}
UserInfo[] memory users = poolUsers[_poolId];
UserInfoWithShares[] memory usersWithShares = new UserInfoWithShares[](users.length);
for (uint256 i = 0; i < users.length; i++) {
UserInfo memory user = users[i];
usersWithShares[i] = UserInfoWithShares({
user: user.user,
poolId: user.poolId,
amount: user.amount,
stakeTime: user.stakeTime,
points: user.points,
gpuId: user.gpuId,
claimed: user.claimed,
lastBoostTime: user.lastBoostTime,
claimedETH: user.claimedETH,
claimedoGPU: user.claimedoGPU,
share: (user.points * poolInfo[_poolId].totalETHStaked) / poolInfo[_poolId].totalPoints
});
}
return usersWithShares;
}
function getPoolUsersWithSharesRange(uint256 _poolId, uint256 _start, uint256 _end) external view returns (UserInfoWithShares[] memory) {
require(_poolId < poolInfo.length, "Staking: invalid pool id");
require(_start < poolUsers[_poolId].length, "Staking: invalid start index");
require(_end < poolUsers[_poolId].length, "Staking: invalid end index");
UserInfo[] memory users = poolUsers[_poolId];
UserInfoWithShares[] memory usersWithShares = new UserInfoWithShares[](_end - _start + 1);
for (uint256 i = _start; i <= _end; i++) {
UserInfo memory user = users[i];
usersWithShares[i - _start] = UserInfoWithShares({
user: user.user,
poolId: user.poolId,
amount: user.amount,
stakeTime: user.stakeTime,
points: user.points,
gpuId: user.gpuId,
claimed: user.claimed,
lastBoostTime: user.lastBoostTime,
claimedETH: user.claimedETH,
claimedoGPU: user.claimedoGPU,
share: (user.points * poolInfo[_poolId].totalETHStaked) / poolInfo[_poolId].totalPoints
});
}
return usersWithShares;
}
function getPoolUser(uint256 _poolId, address _user) external view returns (UserInfo memory) {
require(_poolId < poolInfo.length, "Staking: invalid pool id");
return userInfoMap[_poolId][_user];
}
function getPoolUsersLength(uint256 _poolId) external view returns (uint256) {
require(_poolId < poolInfo.length, "Staking: invalid pool id");
return poolUsers[_poolId].length;
}
function getPoolUserReward(uint256 _poolId, address _user) external view returns (uint256) {
require(_poolId < poolInfo.length, "Staking: invalid pool id");
UserInfo storage user = userInfoMap[_poolId][_user];
PoolInfo storage pool = poolInfo[_poolId];
// Reward on ETH is calculated based on the points
uint256 _points = user.points;
uint256 _share = (_points * pool.totalETHStaked) / pool.totalPoints;
return _share;
}
function addETHToPool(uint256 _poolId, uint256 _amount) external payable onlyOwner {
require(_amount > 0, "Staking: amount must be greater than 0");
require(_amount == msg.value, "Staking: invalid amount");
require(_poolId < poolInfo.length, "Staking: invalid pool id");
PoolInfo storage pool = poolInfo[_poolId];
require(block.timestamp >= pool.startTime, "Staking: pool not started");
require(block.timestamp < pool.endTime, "Staking: pool ended");
require(!pool.ended, "Staking: pool ended");
pool.totalETHStaked += _amount;
}
// retrieve all ETH from the contract
function retrieveETH() external onlyOwner {
payable(msg.sender).transfer(address(this).balance);
}
// retrieve all oGPU from the contract
function retrieveoGPU() external onlyOwner {
oGPU.transfer(msg.sender, oGPU.balanceOf(address(this)));
}
}
{
"compilationTarget": {
"oGPUStaking.sol": "oGPUStaking"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IERC20","name":"_oGPU","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"poolId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"poolId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyWithdraw","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":false,"internalType":"uint256","name":"stakeID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakingStartTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakingEndTimestamp","type":"uint256"}],"name":"PoolCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"poolId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"PoolEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gpuType","type":"uint256"}],"name":"Staked","type":"event"},{"inputs":[{"internalType":"uint256","name":"_poolId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"addETHToPool","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_poolId","type":"uint256"}],"name":"boostGPU","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_poolId","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"createPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_poolId","type":"uint256"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_poolId","type":"uint256"}],"name":"endPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllPools","outputs":[{"components":[{"internalType":"uint256","name":"poolId","type":"uint256"},{"internalType":"uint256","name":"totalPoints","type":"uint256"},{"internalType":"uint256","name":"totalAmount","type":"uint256"},{"internalType":"uint256","name":"totalETHStaked","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bool","name":"ended","type":"bool"}],"internalType":"struct oGPUStaking.PoolInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_poolId","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"getPoolUser","outputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"poolId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"stakeTime","type":"uint256"},{"internalType":"uint256","name":"points","type":"uint256"},{"internalType":"uint256","name":"gpuId","type":"uint256"},{"internalType":"bool","name":"claimed","type":"bool"},{"internalType":"uint256","name":"lastBoostTime","type":"uint256"},{"internalType":"uint256","name":"claimedETH","type":"uint256"},{"internalType":"uint256","name":"claimedoGPU","type":"uint256"}],"internalType":"struct oGPUStaking.UserInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_poolId","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"getPoolUserReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_poolId","type":"uint256"}],"name":"getPoolUsers","outputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"poolId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"stakeTime","type":"uint256"},{"internalType":"uint256","name":"points","type":"uint256"},{"internalType":"uint256","name":"gpuId","type":"uint256"},{"internalType":"bool","name":"claimed","type":"bool"},{"internalType":"uint256","name":"lastBoostTime","type":"uint256"},{"internalType":"uint256","name":"claimedETH","type":"uint256"},{"internalType":"uint256","name":"claimedoGPU","type":"uint256"}],"internalType":"struct oGPUStaking.UserInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_poolId","type":"uint256"}],"name":"getPoolUsersLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_poolId","type":"uint256"}],"name":"getPoolUsersWithShares","outputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"poolId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"stakeTime","type":"uint256"},{"internalType":"uint256","name":"points","type":"uint256"},{"internalType":"uint256","name":"gpuId","type":"uint256"},{"internalType":"bool","name":"claimed","type":"bool"},{"internalType":"uint256","name":"lastBoostTime","type":"uint256"},{"internalType":"uint256","name":"claimedETH","type":"uint256"},{"internalType":"uint256","name":"claimedoGPU","type":"uint256"},{"internalType":"uint256","name":"share","type":"uint256"}],"internalType":"struct oGPUStaking.UserInfoWithShares[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_poolId","type":"uint256"},{"internalType":"uint256","name":"_start","type":"uint256"},{"internalType":"uint256","name":"_end","type":"uint256"}],"name":"getPoolUsersWithSharesRange","outputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"poolId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"stakeTime","type":"uint256"},{"internalType":"uint256","name":"points","type":"uint256"},{"internalType":"uint256","name":"gpuId","type":"uint256"},{"internalType":"bool","name":"claimed","type":"bool"},{"internalType":"uint256","name":"lastBoostTime","type":"uint256"},{"internalType":"uint256","name":"claimedETH","type":"uint256"},{"internalType":"uint256","name":"claimedoGPU","type":"uint256"},{"internalType":"uint256","name":"share","type":"uint256"}],"internalType":"struct oGPUStaking.UserInfoWithShares[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_poolId","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"getUserInfo","outputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"poolId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"stakeTime","type":"uint256"},{"internalType":"uint256","name":"points","type":"uint256"},{"internalType":"uint256","name":"gpuId","type":"uint256"},{"internalType":"bool","name":"claimed","type":"bool"},{"internalType":"uint256","name":"lastBoostTime","type":"uint256"},{"internalType":"uint256","name":"claimedETH","type":"uint256"},{"internalType":"uint256","name":"claimedoGPU","type":"uint256"}],"internalType":"struct oGPUStaking.UserInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gpuId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oGPU","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolInfo","outputs":[{"internalType":"uint256","name":"poolId","type":"uint256"},{"internalType":"uint256","name":"totalPoints","type":"uint256"},{"internalType":"uint256","name":"totalAmount","type":"uint256"},{"internalType":"uint256","name":"totalETHStaked","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bool","name":"ended","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolUsers","outputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"poolId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"stakeTime","type":"uint256"},{"internalType":"uint256","name":"points","type":"uint256"},{"internalType":"uint256","name":"gpuId","type":"uint256"},{"internalType":"bool","name":"claimed","type":"bool"},{"internalType":"uint256","name":"lastBoostTime","type":"uint256"},{"internalType":"uint256","name":"claimedETH","type":"uint256"},{"internalType":"uint256","name":"claimedoGPU","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"retrieveETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"retrieveoGPU","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_poolId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_gpuID","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"userInfoMap","outputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"poolId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"stakeTime","type":"uint256"},{"internalType":"uint256","name":"points","type":"uint256"},{"internalType":"uint256","name":"gpuId","type":"uint256"},{"internalType":"bool","name":"claimed","type":"bool"},{"internalType":"uint256","name":"lastBoostTime","type":"uint256"},{"internalType":"uint256","name":"claimedETH","type":"uint256"},{"internalType":"uint256","name":"claimedoGPU","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userPoolIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]