文件 1 的 1:rewardPool.sol
pragma solidity 0.7.5;
library LowGasSafeMath {
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x + y) >= x);
}
function add32(uint32 x, uint32 y) internal pure returns (uint32 z) {
require((z = x + y) >= x);
}
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x - y) <= x);
}
function sub32(uint32 x, uint32 y) internal pure returns (uint32 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));
}
function div(uint256 x, uint256 y) internal pure returns(uint256 z){
require(y > 0);
z=x/y;
}
}
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);
}
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 _functionCallWithValue(
address target,
bytes memory data,
uint256 weiValue,
string memory errorMessage
) private returns (bytes memory) {
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(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
) private 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);
}
}
}
function addressToString(address _address) internal pure returns(string memory) {
bytes32 _bytes = bytes32(uint256(_address));
bytes memory HEX = "0123456789abcdef";
bytes memory _addr = new bytes(42);
_addr[0] = '0';
_addr[1] = 'x';
for(uint256 i = 0; i < 20; i++) {
_addr[2+i*2] = HEX[uint8(_bytes[i + 12] >> 4)];
_addr[3+i*2] = HEX[uint8(_bytes[i + 12] & 0x0f)];
}
return string(_addr);
}
}
contract OwnableData {
address public owner;
address public Nodes;
address public pendingOwner;
}
contract Ownable is OwnableData {
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
owner = msg.sender;
emit OwnershipTransferred(address(0), msg.sender);
}
function transferOwnership(
address newOwner,
bool direct,
bool renounce
) public onlyOwner {
if (direct) {
require(newOwner != address(0) || renounce, "Ownable: zero address");
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
pendingOwner = address(0);
} else {
pendingOwner = newOwner;
}
}
function claimOwnership() public {
address _pendingOwner = pendingOwner;
require(msg.sender == _pendingOwner, "Ownable: caller != pending owner");
emit OwnershipTransferred(owner, _pendingOwner);
owner = _pendingOwner;
pendingOwner = address(0);
}
function setNodesAddress(address _nodes) public {
require(msg.sender == owner, "Ownable: caller is not the owner");
Nodes = _nodes;
}
modifier onlyOwner() {
require(msg.sender == owner, "Ownable: caller is not the owner");
_;
}
modifier onlyNodes() {
require(msg.sender == Nodes, "Ownable: caller is not the nodes address");
_;
}
}
contract rewardPool is Ownable {
using LowGasSafeMath for uint;
using LowGasSafeMath for uint32;
struct NftData{
address owner;
uint256 lastClaim;
}
uint256 public rewardRate = 54794520547945201664;
uint256 public maxRewardTotal = 20000000000000000000000;
mapping (uint256 => NftData) public nftInfo;
mapping(uint256 => uint256) public nftMintTime;
mapping(uint256 => uint256) public nftRewardTotalClaimed;
uint256 totalNodes = 0;
address public Cosmic;
constructor(address _cosmicAddress) {
Cosmic = _cosmicAddress;
}
receive() external payable {
}
function addNodeInfo(uint256 _nftId, address _owner) external onlyNodes returns (bool success) {
require(nftInfo[_nftId].owner == address(0), "Node already exists");
nftInfo[_nftId].owner = _owner;
nftInfo[_nftId].lastClaim = block.timestamp;
nftMintTime[_nftId] = block.timestamp;
totalNodes += 1;
return true;
}
function updateNodeOwner(uint256 _nftId, address _owner) external onlyNodes returns (bool success) {
require(nftInfo[_nftId].owner != address(0), "Node does not exist");
nftInfo[_nftId].owner = _owner;
return true;
}
function pendingRewardFor(uint256 _nftId) public view returns (uint256 _reward) {
uint256 _lastClaim = nftInfo[_nftId].lastClaim;
uint256 _daysSinceLastClaim = ((block.timestamp - _lastClaim).mul(1e9)) / 86400;
_reward = (_daysSinceLastClaim * rewardRate).div(1e9);
if (nftRewardTotalClaimed[_nftId] + _reward > maxRewardTotal) {
_reward = maxRewardTotal - nftRewardTotalClaimed[_nftId];
}
return _reward;
}
function claimReward(uint256 _nftId) external onlyNodes returns (bool success) {
uint256 _reward = pendingRewardFor(_nftId);
require(_reward > 0, "No reward to claim");
nftRewardTotalClaimed[_nftId] += _reward;
nftInfo[_nftId].lastClaim = block.timestamp;
IERC20(Cosmic).transfer(nftInfo[_nftId].owner, _reward);
return true;
}
}