编译器
0.8.12+commit.f00d7308
文件 1 的 11: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;
}
}
文件 2 的 11:Controller.sol
pragma solidity 0.8.12;
library Controller {
function equals(bytes memory self, bytes memory other) public pure returns (bool equal) {
if (self.length != other.length) {
return false;
}
uint256 addr;
uint256 addr2;
assembly {
addr := add(
self,
32
)
addr2 := add(
other,
32
)
}
equal = memoryEquals(addr, addr2, self.length);
}
function memoryEquals(
uint256 addr,
uint256 addr2,
uint256 len
) public pure returns (bool equal) {
assembly {
equal := eq(keccak256(addr, len), keccak256(addr2, len))
}
}
function isContract(address _addr) public view returns (bool isContract) {
uint32 size;
assembly {
size := extcodesize(_addr)
}
return (size > 0);
}
}
文件 3 的 11:EnumerableSet.sol
pragma solidity ^0.8.0;
library EnumerableSet {
struct Set {
bytes32[] _values;
mapping(bytes32 => uint256) _indexes;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastvalue = set._values[lastIndex];
set._values[toDeleteIndex] = lastvalue;
set._indexes[lastvalue] = valueIndex;
}
set._values.pop();
delete set._indexes[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
struct Bytes32Set {
Set _inner;
}
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
return _values(set._inner);
}
struct AddressSet {
Set _inner;
}
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
struct UintSet {
Set _inner;
}
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
}
文件 4 的 11:IERC1155.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC1155 is IERC165 {
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);
function balanceOf(address account, uint256 id) external view returns (uint256);
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
external
view
returns (uint256[] memory);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address account, address operator) external view returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}
文件 5 的 11:IERC1155Receiver.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC1155Receiver is IERC165 {
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}
文件 6 的 11:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 7 的 11: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 to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 8 的 11: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;
}
文件 9 的 11:IERC721Receiver.sol
pragma solidity ^0.8.0;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 10 的 11:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 11 的 11:SatoshiStaking.sol
pragma solidity 0.8.12;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "../lib/Controller.sol";
contract SatoshiStaking is IERC1155Receiver, IERC721Receiver, Ownable {
event NftStaked(address user, address collection, uint256 id, uint256 stakedTime, uint256 nftBalance);
event NftUnstaked(address user, address collection, uint256 id, uint256 timeStamp, uint256 leftReward);
event RewardClaimed(address user, address collection, uint256 id, uint256 timeStamp, uint256 givenReward, uint256 leftReward);
event CollectionAdded(address collection, address rewardToken, uint256 dailyReward);
event StakingEnabled(uint256 time);
event StakingDisabled(uint256 time);
event NFTProgramFunded(address admin, uint256 rewardAmount, address token, address collection);
event WithdrawnFunds(address admin, address rewardToken, uint256 amount);
struct NFT {
address user;
address collection;
uint256 id;
uint256 stakedTime;
uint256 balance;
uint256 claimedTotal;
uint256 leftTime;
bool isStakedBefore;
bool isStaked;
Collection collec;
}
struct Collection {
uint256 rewardsPerDay;
uint256 startTime;
uint256 lifetime;
uint256 promisedRewards;
address rewardTokenAddr;
}
using EnumerableSet for EnumerableSet.AddressSet;
EnumerableSet.AddressSet private collec721;
EnumerableSet.AddressSet private collec1155;
bytes private magicData;
mapping(address => mapping(uint256 => NFT)) public nftInfo;
mapping(address => Collection) public collectionInfo;
constructor(bytes memory _data) {
require(_data.length != 0, "Magic data can not be equal to zero");
magicData = _data;
}
function computeReward(
address _collection,
uint256 _id,
uint256 _timestamp
) public view returns (uint256 _unclaimedRewards, uint256 _days) {
if (nftInfo[_collection][_id].user == address(0)) return (0, 0);
uint256 _stakeTime = _timestamp - nftInfo[_collection][_id].stakedTime;
uint256 _leftTime = nftInfo[_collection][_id].leftTime;
uint256 _dailyReward = collectionInfo[_collection].rewardsPerDay;
if (_leftTime < _stakeTime) _stakeTime = _leftTime;
_days = _stakeTime / 1 days;
_unclaimedRewards = (_dailyReward * _days);
}
function getNFTInformation(address _collection, uint256 _id)
external
view
returns (
uint256 _claimedRewards,
uint256 _unclaimedRewards,
uint256 _leftDays,
uint256 _leftHours,
uint256 _leftRewards,
uint256 _dailyReward,
address _owner
)
{
require(collec721.contains(_collection) || collec1155.contains(_collection), "This NFT is not supported! Please provide correct information");
NFT memory _nftInfo = nftInfo[_collection][_id];
_claimedRewards = _nftInfo.claimedTotal;
uint256 leftTimeInSeconds;
uint256 _timeStamp;
!_nftInfo.isStaked ? _timeStamp = _nftInfo.stakedTime : _timeStamp = block.timestamp;
if ((_timeStamp - _nftInfo.stakedTime) > _nftInfo.leftTime) leftTimeInSeconds = 0;
else leftTimeInSeconds = _nftInfo.leftTime - (_timeStamp - _nftInfo.stakedTime);
_leftDays = leftTimeInSeconds / 1 days;
uint256 leftHoursInSeconds = leftTimeInSeconds - (_leftDays * 1 days);
_leftHours = leftHoursInSeconds / 3600;
(_unclaimedRewards, ) = computeReward(_collection, _id, _timeStamp);
_leftRewards = _nftInfo.balance - _unclaimedRewards;
_dailyReward = collectionInfo[_collection].rewardsPerDay;
_owner = _nftInfo.user;
}
function getRewardTokenBalance(address _token) external view returns (uint256 _balance) {
_balance = IERC20(_token).balanceOf(address(this));
}
function getAllSupportedERC721() external view returns (address[] memory) {
return collec721.values();
}
function getAllSupportedERC1155() external view returns (address[] memory) {
return collec1155.values();
}
function addCollection(
address _collection,
Collection calldata _collecInfo,
bool _is721
) external onlyOwner {
require(_collection != address(0), "Collection can't be zero address");
require(_collecInfo.rewardsPerDay > 0, "Daily reward can not be zero");
require(_collecInfo.startTime >= block.timestamp, "Staking start time cannot be lower than current timestamp");
require(Controller.isContract(_collection), "Given collection address does not belong to any contract!");
require(Controller.isContract(_collecInfo.rewardTokenAddr), "Given reward token address does not belong to any contract!");
_is721 ? collec721.add(_collection) : collec1155.add(_collection);
Collection storage newCollection = collectionInfo[_collection];
newCollection.lifetime = _collecInfo.lifetime * 1 days;
newCollection.rewardsPerDay = _collecInfo.rewardsPerDay;
newCollection.startTime = _collecInfo.startTime;
newCollection.rewardTokenAddr = _collecInfo.rewardTokenAddr;
emit CollectionAdded(_collection, _collecInfo.rewardTokenAddr, _collecInfo.rewardsPerDay);
}
function removeCollection(address _collection, bool _is721) external onlyOwner {
require(_collection != address(0), "Collection can't be zero address");
if (_is721) {
collec721.remove(_collection);
} else {
collec1155.remove(_collection);
}
}
function stakeSingleNFT(address _collection, uint256 _id) public {
if (collec721.contains(_collection)) {
IERC721(_collection).safeTransferFrom(msg.sender, address(this), _id, magicData);
} else if (collec1155.contains(_collection)) {
IERC1155(_collection).safeTransferFrom(msg.sender, address(this), _id, 1, magicData);
} else {
revert("This NFT Collection is not supported at this moment! Please try again");
}
NFT memory _nftInfo = nftInfo[_collection][_id];
require(collectionInfo[_collection].startTime <= block.timestamp, "Staking of this collection has not started yet!");
if (!_nftInfo.isStakedBefore) {
_nftInfo.collection = _collection;
_nftInfo.id = _id;
_nftInfo.collec.lifetime = collectionInfo[_collection].lifetime;
_nftInfo.leftTime = _nftInfo.collec.lifetime;
_nftInfo.isStakedBefore = true;
_nftInfo.collec.rewardsPerDay = collectionInfo[_collection].rewardsPerDay;
}
_nftInfo.user = msg.sender;
_nftInfo.stakedTime = block.timestamp;
_nftInfo.balance = (_nftInfo.leftTime * collectionInfo[_collection].rewardsPerDay) / 1 days;
_nftInfo.isStaked = true;
nftInfo[_collection][_id] = _nftInfo;
collectionInfo[_collection].promisedRewards += (_nftInfo.leftTime * collectionInfo[_collection].rewardsPerDay) / 1 days;
emit NftStaked(msg.sender, _collection, _id, block.timestamp, _nftInfo.balance);
}
function stakeBatchNFT(address[] calldata _collections, uint256[] calldata _ids) external {
require(_collections.length <= 5, "Please send 5 or less NFTs.");
require(_collections.length == _ids.length, "Collections and Ids number are mismatch, Check again please.");
for (uint256 i = 0; i < _collections.length; i++) {
stakeSingleNFT(_collections[i], _ids[i]);
}
}
function claimReward(address _collection, uint256 _id) public {
uint256 timeStamp = block.timestamp;
NFT memory _nftInfo = nftInfo[_collection][_id];
require(collec721.contains(_collection) || collec1155.contains(_collection), "We could not recognize this contract address.");
require(_nftInfo.user != address(0), "This NFT is not staked!");
require(_nftInfo.user == msg.sender, "This NFT does not belong to you!");
require(_nftInfo.balance > 0, "This NFT does not have any reward inside anymore! We suggest to unstake your NFTs");
(uint256 reward, uint256 _days) = computeReward(_collection, _id, timeStamp);
address tokenAdd = collectionInfo[_collection].rewardTokenAddr;
uint256 rewardTokenBalance = IERC20(tokenAdd).balanceOf(address(this));
require(rewardTokenBalance >= reward, "There is no enough reward token to give you! Please contact with support!");
collectionInfo[_collection].promisedRewards -= reward;
uint256 _stakedTime = _nftInfo.stakedTime;
uint256 _leftTime = _nftInfo.leftTime;
_nftInfo.stakedTime = _stakedTime + (_days * 1 days);
_nftInfo.balance -= reward;
_nftInfo.claimedTotal += reward;
if (_leftTime < (timeStamp - _stakedTime)) _nftInfo.leftTime = 0;
else _nftInfo.leftTime -= (_days * 1 days);
nftInfo[_collection][_id] = _nftInfo;
require(IERC20(tokenAdd).transfer(msg.sender, reward), "Couldn't transfer the amount!");
emit RewardClaimed(msg.sender, _collection, _id, timeStamp, reward, _nftInfo.balance);
}
function unStake(
address _collection,
uint256 _id,
bool _is721
) external {
require(nftInfo[_collection][_id].user != address(0), "This NFT is not staked!");
require(nftInfo[_collection][_id].user == msg.sender, "This NFT doesn't not belong to you!");
require(nftInfo[_collection][_id].isStaked, "This card is already unstaked!");
if (nftInfo[_collection][_id].leftTime > 0) claimReward(_collection, _id);
NFT memory _nftInfo = nftInfo[_collection][_id];
_nftInfo.user = address(0);
_nftInfo.isStaked = false;
(, , , , uint256 _leftRewards, , ) = this.getNFTInformation(_collection, _id);
collectionInfo[_collection].promisedRewards -= _leftRewards;
nftInfo[_collection][_id] = _nftInfo;
if (_is721) {
IERC721(_collection).safeTransferFrom(address(this), msg.sender, _id);
} else {
IERC1155(_collection).safeTransferFrom(address(this), msg.sender, _id, 1, "");
}
emit NftUnstaked(msg.sender, _collection, _id, block.timestamp, _nftInfo.balance);
}
function fundCollection(address _collection, uint256 _amount) external onlyOwner {
IERC20 rewardToken = IERC20(collectionInfo[_collection].rewardTokenAddr);
require(
collec721.contains(_collection) || collec1155.contains(_collection),
"This address does not match with any staker program NFT contract addresses!. Please be sure to give correct information"
);
require(rewardToken.balanceOf(msg.sender) >= _amount, "You do not enough balance for funding reward token! Please have enough token balance");
uint256 oneNFTReward = (collectionInfo[_collection].lifetime * collectionInfo[_collection].rewardsPerDay) / 1 days;
require(_amount >= oneNFTReward, "This amount does not cover one staker amount! Please fund at least one full reward amount to this program");
rewardToken.transferFrom(msg.sender, address(this), _amount);
emit NFTProgramFunded(msg.sender, _amount, address(rewardToken), _collection);
}
function withdrawFunds(address _collection, uint256 _amount) external onlyOwner {
IERC20 _rewardToken = IERC20(collectionInfo[_collection].rewardTokenAddr);
uint256 _balanceOfContract = _rewardToken.balanceOf(address(this));
require(_amount > 0, "Please enter a valid amount! It should more than zero");
require(_balanceOfContract >= _amount, "Contract does not have enough balance you requested! Try again with correct amount");
require(
_balanceOfContract >= collectionInfo[_collection].promisedRewards,
"You should only withdraw exceeded reward tokens! Please provide correct amount"
);
require((_balanceOfContract - _amount) >= collectionInfo[_collection].promisedRewards, "Withdrawn amount is not valid!");
require(_rewardToken.transfer(msg.sender, _amount), "Transfer failed");
emit WithdrawnFunds(msg.sender, address(_rewardToken), _amount);
}
function emergencyConfig(
address _collection,
address _rewardToken,
uint256 _amount,
address _to,
address _withdrawTokenAddr
) external onlyOwner {
collectionInfo[_collection].rewardTokenAddr = _rewardToken;
IERC20(_withdrawTokenAddr).transfer(_to, _amount);
}
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes calldata data
) external view returns (bytes4) {
require(Controller.equals(data, magicData), "No direct transfer!");
return bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"));
}
function onERC1155BatchReceived(
address,
address,
uint256[] calldata,
uint256[] calldata,
bytes calldata
) external pure returns (bytes4) {
return 0x00;
}
function onERC721Received(
address,
address,
uint256,
bytes calldata data
) external view returns (bytes4) {
require(Controller.equals(data, magicData), "No direct transfer!");
return IERC721Receiver.onERC721Received.selector;
}
function onERC721Received(
address,
address,
uint256
) external pure returns (bytes4) {
return 0x00;
}
function supportsInterface(bytes4 interfaceId) external pure returns (bool) {
return (interfaceId == type(IERC1155Receiver).interfaceId || interfaceId == type(IERC721Receiver).interfaceId);
}
}
{
"compilationTarget": {
"contracts/SatoshiStaking.sol": "SatoshiStaking"
},
"evmVersion": "london",
"libraries": {
"lib/Controller.sol:Controller": "0x8fed8b0599a8937a2d34d54ae15e8db48f69a575"
},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"dailyReward","type":"uint256"}],"name":"CollectionAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"collection","type":"address"}],"name":"NFTProgramFunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakedTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nftBalance","type":"uint256"}],"name":"NftStaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timeStamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"leftReward","type":"uint256"}],"name":"NftUnstaked","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":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timeStamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"givenReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"leftReward","type":"uint256"}],"name":"RewardClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"StakingDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"StakingEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawnFunds","type":"event"},{"inputs":[{"internalType":"address","name":"_collection","type":"address"},{"components":[{"internalType":"uint256","name":"rewardsPerDay","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"lifetime","type":"uint256"},{"internalType":"uint256","name":"promisedRewards","type":"uint256"},{"internalType":"address","name":"rewardTokenAddr","type":"address"}],"internalType":"struct SatoshiStaking.Collection","name":"_collecInfo","type":"tuple"},{"internalType":"bool","name":"_is721","type":"bool"}],"name":"addCollection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"claimReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"collectionInfo","outputs":[{"internalType":"uint256","name":"rewardsPerDay","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"lifetime","type":"uint256"},{"internalType":"uint256","name":"promisedRewards","type":"uint256"},{"internalType":"address","name":"rewardTokenAddr","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"computeReward","outputs":[{"internalType":"uint256","name":"_unclaimedRewards","type":"uint256"},{"internalType":"uint256","name":"_days","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_collection","type":"address"},{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"address","name":"_withdrawTokenAddr","type":"address"}],"name":"emergencyConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"fundCollection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllSupportedERC1155","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllSupportedERC721","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"getNFTInformation","outputs":[{"internalType":"uint256","name":"_claimedRewards","type":"uint256"},{"internalType":"uint256","name":"_unclaimedRewards","type":"uint256"},{"internalType":"uint256","name":"_leftDays","type":"uint256"},{"internalType":"uint256","name":"_leftHours","type":"uint256"},{"internalType":"uint256","name":"_leftRewards","type":"uint256"},{"internalType":"uint256","name":"_dailyReward","type":"uint256"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getRewardTokenBalance","outputs":[{"internalType":"uint256","name":"_balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"nftInfo","outputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"stakedTime","type":"uint256"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"claimedTotal","type":"uint256"},{"internalType":"uint256","name":"leftTime","type":"uint256"},{"internalType":"bool","name":"isStakedBefore","type":"bool"},{"internalType":"bool","name":"isStaked","type":"bool"},{"components":[{"internalType":"uint256","name":"rewardsPerDay","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"lifetime","type":"uint256"},{"internalType":"uint256","name":"promisedRewards","type":"uint256"},{"internalType":"address","name":"rewardTokenAddr","type":"address"}],"internalType":"struct SatoshiStaking.Collection","name":"collec","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_collection","type":"address"},{"internalType":"bool","name":"_is721","type":"bool"}],"name":"removeCollection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_collections","type":"address[]"},{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"stakeBatchNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"stakeSingleNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"bool","name":"_is721","type":"bool"}],"name":"unStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"}]