文件 1 的 13:Address.sol
pragma solidity ^0.7.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) 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);
}
}
}
}
文件 2 的 13:Context.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
文件 3 的 13:ERC1155.sol
pragma solidity ^0.7.0;
import "./IERC1155.sol";
import "./IERC1155MetadataURI.sol";
import "./IERC1155Receiver.sol";
import "./Context.sol";
import "./ERC165.sol";
import "./safemath.sol";
import "./Address.sol";
contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
using SafeMath for uint256;
using Address for address;
mapping (uint256 => mapping(address => uint256)) private _balances;
mapping (address => mapping(address => bool)) private _operatorApprovals;
string private _uri;
bytes4 private constant _INTERFACE_ID_ERC1155 = 0xd9b67a26;
bytes4 private constant _INTERFACE_ID_ERC1155_METADATA_URI = 0x0e89341c;
constructor (string memory uri_) {
_setURI(uri_);
_registerInterface(_INTERFACE_ID_ERC1155);
_registerInterface(_INTERFACE_ID_ERC1155_METADATA_URI);
}
function uri(uint256) external view virtual override returns (string memory) {
return _uri;
}
function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {
require(account != address(0), "ERC1155: balance query for the zero address");
return _balances[id][account];
}
function balanceOfBatch(
address[] memory accounts,
uint256[] memory ids
)
public
view
virtual
override
returns (uint256[] memory)
{
require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch");
uint256[] memory batchBalances = new uint256[](accounts.length);
for (uint256 i = 0; i < accounts.length; ++i) {
batchBalances[i] = balanceOf(accounts[i], ids[i]);
}
return batchBalances;
}
function setApprovalForAll(address operator, bool approved) public virtual override {
require(_msgSender() != operator, "ERC1155: setting approval status for self");
_operatorApprovals[_msgSender()][operator] = approved;
emit ApprovalForAll(_msgSender(), operator, approved);
}
function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {
return _operatorApprovals[account][operator];
}
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
)
public
virtual
override
{
require(to != address(0), "ERC1155: transfer to the zero address");
require(
from == _msgSender() || isApprovedForAll(from, _msgSender()),
"ERC1155: caller is not owner nor approved"
);
address operator = _msgSender();
_beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);
_balances[id][from] = _balances[id][from].sub(amount, "ERC1155: insufficient balance for transfer");
_balances[id][to] = _balances[id][to].add(amount);
emit TransferSingle(operator, from, to, id, amount);
_doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
}
function safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
)
public
virtual
override
{
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
require(to != address(0), "ERC1155: transfer to the zero address");
require(
from == _msgSender() || isApprovedForAll(from, _msgSender()),
"ERC1155: transfer caller is not owner nor approved"
);
address operator = _msgSender();
_beforeTokenTransfer(operator, from, to, ids, amounts, data);
for (uint256 i = 0; i < ids.length; ++i) {
uint256 id = ids[i];
uint256 amount = amounts[i];
_balances[id][from] = _balances[id][from].sub(
amount,
"ERC1155: insufficient balance for transfer"
);
_balances[id][to] = _balances[id][to].add(amount);
}
emit TransferBatch(operator, from, to, ids, amounts);
_doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
}
function _setURI(string memory newuri) internal virtual {
_uri = newuri;
}
function _mint(address account, uint256 id, uint256 amount, bytes memory data) internal virtual {
require(account != address(0), "ERC1155: mint to the zero address");
address operator = _msgSender();
_beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);
_balances[id][account] = _balances[id][account].add(amount);
emit TransferSingle(operator, address(0), account, id, amount);
_doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);
}
function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual {
require(to != address(0), "ERC1155: mint to the zero address");
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
address operator = _msgSender();
_beforeTokenTransfer(operator, address(0), to, ids, amounts, data);
for (uint i = 0; i < ids.length; i++) {
_balances[ids[i]][to] = amounts[i].add(_balances[ids[i]][to]);
}
emit TransferBatch(operator, address(0), to, ids, amounts);
_doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
}
function _burn(address account, uint256 id, uint256 amount) internal virtual {
require(account != address(0), "ERC1155: burn from the zero address");
address operator = _msgSender();
_beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), "");
_balances[id][account] = _balances[id][account].sub(
amount,
"ERC1155: burn amount exceeds balance"
);
emit TransferSingle(operator, account, address(0), id, amount);
}
function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) internal virtual {
require(account != address(0), "ERC1155: burn from the zero address");
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
address operator = _msgSender();
_beforeTokenTransfer(operator, account, address(0), ids, amounts, "");
for (uint i = 0; i < ids.length; i++) {
_balances[ids[i]][account] = _balances[ids[i]][account].sub(
amounts[i],
"ERC1155: burn amount exceeds balance"
);
}
emit TransferBatch(operator, account, address(0), ids, amounts);
}
function _beforeTokenTransfer(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
)
internal
virtual
{ }
function _doSafeTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
)
private
{
if (to.isContract()) {
try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
if (response != IERC1155Receiver(to).onERC1155Received.selector) {
revert("ERC1155: ERC1155Receiver rejected tokens");
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC1155: transfer to non ERC1155Receiver implementer");
}
}
}
function _doSafeBatchTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
)
private
{
if (to.isContract()) {
try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (bytes4 response) {
if (response != IERC1155Receiver(to).onERC1155BatchReceived.selector) {
revert("ERC1155: ERC1155Receiver rejected tokens");
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC1155: transfer to non ERC1155Receiver implementer");
}
}
}
function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {
uint256[] memory array = new uint256[](1);
array[0] = element;
return array;
}
}
文件 4 的 13:ERC165.sol
pragma solidity ^0.7.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
mapping(bytes4 => bool) private _supportedInterfaces;
constructor () {
_registerInterface(_INTERFACE_ID_ERC165);
}
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return _supportedInterfaces[interfaceId];
}
function _registerInterface(bytes4 interfaceId) internal virtual {
require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
_supportedInterfaces[interfaceId] = true;
}
}
文件 5 的 13:IERC1155.sol
pragma solidity ^0.7.0;
import "./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;
}
文件 6 的 13:IERC1155MetadataURI.sol
pragma solidity ^0.7.0;
import "./IERC1155.sol";
interface IERC1155MetadataURI is IERC1155 {
function uri(uint256 id) external view returns (string memory);
}
文件 7 的 13:IERC1155Receiver.sol
pragma solidity ^0.7.0;
import "./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);
}
文件 8 的 13:IERC165.sol
pragma solidity ^0.7.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 9 的 13:lynccrafter.sol
pragma solidity ^0.7.0;
import "./ERC1155.sol";
contract LYNCCrafter is ERC1155 {
address public owner;
address public rewardContract;
uint256 public cardID = 1;
uint256 public cardCountETH = 9950;
uint256 public cardCountLYNC = 9975;
struct CardStats {
string collectionName;
uint256 cardType;
uint256 boostAmount;
uint256 redeemInitial;
uint256 redeemLeft;
uint256 redeemInterval;
uint256 useLastTimeStamp;
uint256 tokenReward;
uint256 percentageReward;
}
event BulkCardCrafted(address indexed _to, uint256 cardID, uint256 _amountOfCards, uint256 _tokenReward, uint256 _percentageReward);
event CollectionCardCrafted(address indexed _to, uint256 cardID, uint256 _redeemInitial, uint256 _redeemInterval, uint256 _tokenReward, uint256 _percentageReward);
event BoosterCardCrafted(address indexed _to, uint256 cardID, uint256 _amountOfCards, uint256 _boostAmount);
event BulkBoosterCardIncreased(address indexed _to, uint256 _amountOfCards, uint256 _cardID);
event RewardCardCrafted(address indexed _to, uint256 _cardCounter);
event CardStatsUpdated(uint256 _cardID);
event BoosterCardApplied(uint256 _cardID, uint256 _newRedeemTotal);
event CardBurned(uint256 _cardID, uint256 _amount);
event CardBurnedByOwner(address indexed _cardholder, uint256 _cardID, uint256 _amount);
event RewardContractAddressUpdated(address indexed _previousRewardAddress, address indexed _newRewardAddress);
event OwnershipTransferred(address indexed _previousOwner, address indexed _newOwner);
event OwnershipRenounced(address indexed _previousOwner, address indexed _newOwner);
mapping(uint256 => CardStats) public cards;
mapping(string => mapping(uint256 => uint256)) public collections;
constructor(string memory _uri) ERC1155(_uri) {
owner = msg.sender;
}
function craftBulkCard(address _to, uint256 _amountOfCards, uint256 _tokenReward, uint256 _percentageReward) public onlyOwner {
_mint(_to, cardID, _amountOfCards, "");
cards[cardID].cardType = 1;
cards[cardID].tokenReward = _tokenReward;
cards[cardID].percentageReward = _percentageReward;
emit BulkCardCrafted(_to, cardID, _amountOfCards, _tokenReward, _percentageReward);
cardID += 1;
}
function craftCollectionCard(address _to, string memory _collectionName, uint256 _amountOfCards, uint256 _redeemInitial, uint256 _redeemInterval, uint256 _tokenReward, uint256 _percentageReward) public onlyOwner {
require(collections[_collectionName][0] == 0, "This collection name aready exists!");
collections[_collectionName][0] = _amountOfCards;
for (uint256 i = 1; i <= _amountOfCards; i++) {
collections[_collectionName][i] = cardID;
_mint(_to, cardID, 1, "");
cards[cardID].collectionName = _collectionName;
cards[cardID].cardType = 2;
cards[cardID].redeemInitial = _redeemInitial;
cards[cardID].redeemLeft = _redeemInitial;
cards[cardID].redeemInterval = _redeemInterval;
cards[cardID].tokenReward = _tokenReward;
cards[cardID].percentageReward = _percentageReward;
emit CollectionCardCrafted(_to, cardID, _redeemInitial, _redeemInterval, _tokenReward, _percentageReward);
cardID += 1;
}
}
function craftBoosterCard(address _to, uint256 _amountOfCards, uint256 _boostAmount) public onlyOwner {
_mint(_to, cardID, _amountOfCards, "");
cards[cardID].cardType = 3;
cards[cardID].boostAmount = _boostAmount;
emit BoosterCardCrafted(_to, cardID, _amountOfCards, _boostAmount);
cardID += 1;
}
function increaseBulkBoosterCard(address _to, uint256 _amountOfCards, uint256 _cardID) public onlyOwner {
require(cards[_cardID].cardType != 2, "Cannot increase a collection / unique card");
require(_cardID > 0 && _cardID < cardID, "Card ID has not been crafted yet");
_mint(_to, _cardID, _amountOfCards, "");
emit BulkBoosterCardIncreased(_to, _amountOfCards, _cardID);
}
function craftRewardCard(address _to, uint256 _cardID, string memory _collectionName) public onlyRewardContract {
uint256 _cardCounter;
if(_cardID < 3) {
_cardCounter = cardCountETH;
cardCountETH += 1;
} else {
_cardCounter = cardCountLYNC;
cardCountLYNC += 1;
}
collections[_collectionName][0] += 1;
_mint(_to, _cardCounter, 1, "");
cards[_cardCounter].collectionName = _collectionName;
cards[_cardCounter].cardType = 2;
cards[_cardCounter].redeemInitial = 6;
cards[_cardCounter].redeemLeft = 6;
cards[_cardCounter].redeemInterval = 28;
cards[_cardCounter].tokenReward = 400;
cards[_cardCounter].percentageReward = 4;
emit RewardCardCrafted(_to, _cardCounter);
}
function updateCardStats(uint256 _cardID) public onlyRewardContract {
cards[_cardID].redeemLeft -= 1;
cards[_cardID].useLastTimeStamp = block.timestamp;
emit CardStatsUpdated(_cardID);
}
function applyCardBooster(uint256 _cardID, uint256 _newRedeemTotal) public onlyRewardContract {
cards[_cardID].redeemLeft += _newRedeemTotal;
emit BoosterCardApplied(_cardID, _newRedeemTotal);
}
function burnCard(address _cardholder, uint256 _cardID, uint256 _amount) public onlyRewardContract {
_burn(_cardholder, _cardID, _amount);
emit CardBurned(_cardID, _amount);
}
function ownerBurnCard(address _cardholder, uint256 _cardID, uint256 _amount) public onlyOwner {
_burn(_cardholder, _cardID, _amount);
emit CardBurnedByOwner(_cardholder, _cardID, _amount);
}
function updateRewardContractAddress(address _newRewardContractAddress) public onlyOwner {
require(_newRewardContractAddress != address(0), "New reward contract address cannot be a zero address");
emit RewardContractAddressUpdated(rewardContract, _newRewardContractAddress);
rewardContract = _newRewardContractAddress;
}
function transferOwnership(address _newOwner) public onlyOwner {
require(_newOwner != address(0), "New owner cannot be a zero address");
emit OwnershipTransferred(owner, _newOwner);
owner = _newOwner;
}
function renounceOwnership() public onlyOwner {
emit OwnershipRenounced(owner, address(0));
owner = address(0);
}
modifier onlyOwner() {
require(owner == msg.sender, "Only the owner of the crafter contract can call this function");
_;
}
modifier onlyRewardContract() {
require(rewardContract == msg.sender, "Only the reward contract address can call this function");
_;
}
}
文件 10 的 13:lyncnftrewards.sol
pragma solidity ^0.7.0;
import "./lynctoken.sol";
import "./lyncstakingv1.sol";
import "./lynccrafter.sol";
contract LYNCNFTRewardsV1 {
using SafeMath for uint256;
address payable public owner;
uint256 public oneDay = 86400;
uint256 public SCALAR = 1e18;
LYNCToken public tokenContract;
LYNCStakingV1 public stakingContract;
LYNCCrafter public crafterContract;
event OwnershipTransferred(address indexed _previousOwner, address indexed _newOwner);
event OwnershipRenounced(address indexed _previousOwner, address indexed _newOwner);
constructor(LYNCToken _tokenContract, LYNCStakingV1 _stakingContract, LYNCCrafter _crafterContract) {
owner = msg.sender;
tokenContract = _tokenContract;
stakingContract = _stakingContract;
crafterContract = _crafterContract;
}
function mulDiv(uint x, uint y, uint z) public pure returns (uint) {
(uint l, uint h) = fullMul (x, y);
assert (h < z);
uint mm = mulmod(x, y, z);
if (mm > l) h -= 1;
l -= mm;
uint pow2 = z & -z;
z /= pow2;
l /= pow2;
l += h * ((-pow2) / pow2 + 1);
uint r = 1;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
return l * r;
}
function fullMul(uint x, uint y) private pure returns (uint l, uint h) {
uint mm = mulmod(x, y, uint (-1));
l = x * y;
h = mm - l;
if (mm < l) h -= 1;
}
function redeemLotto(uint256 _cardID) public {
require(crafterContract.balanceOf(msg.sender, _cardID) > 0, "You do not own this card");
require(_cardID < 5, "Card is not a lotto card");
uint256 _cardAmount = 1;
string memory _collectionName;
if(_cardID < 3) {
_collectionName = "Ethereum Lotto";
if(_cardID == 1) {
_cardAmount = 10;
require(crafterContract.balanceOf(msg.sender, _cardID) >= _cardAmount, "10 common cards required to craft");
} else {
require(crafterContract.balanceOf(msg.sender, _cardID) >= _cardAmount, "1 rare card required to craft");
}
} else {
_collectionName = "LYNC Token Lotto";
if(_cardID == 3) {
_cardAmount = 10;
require(crafterContract.balanceOf(msg.sender, _cardID) >= _cardAmount, "10 common cards required to craft");
} else {
require(crafterContract.balanceOf(msg.sender, _cardID) >= _cardAmount, "1 rare card required to craft");
}
}
crafterContract.craftRewardCard(msg.sender, _cardID, _collectionName);
crafterContract.burnCard(msg.sender, _cardID, _cardAmount);
}
function redeemReward(uint256 _cardID) public {
require(crafterContract.balanceOf(msg.sender, _cardID) > 0, "You do not own this card");
(,uint256 cardType,,,uint256 _redeemLeft,uint256 _redeemInterval,uint256 _redeemLastTimeStamp,uint256 _tokenReward,uint256 _percentageRedeem) = crafterContract.cards(_cardID);
require(block.timestamp > (_redeemLastTimeStamp + _redeemInterval.mul(oneDay)), "This card has already been redeemed this interval, wait until reset");
require(cardType != 3, "Booster cards do not have any rewards associated with them");
if(cardType != 2) {
crafterContract.burnCard(msg.sender, _cardID, 1);
} else {
require(_redeemLeft > 0, "No redeems available on this card");
crafterContract.updateCardStats(_cardID);
}
if(_tokenReward > 0) {
require(tokenContract.transfer(msg.sender, _tokenReward.mul(SCALAR)));
}
if(_percentageRedeem > 0) {
(uint256 _stakedTokens,,) = stakingContract.stakerInformation(msg.sender);
uint256 _percentageReward = mulDiv(_stakedTokens, _percentageRedeem, 100);
require(tokenContract.transfer(msg.sender, _percentageReward));
}
}
function redeemBoosterCard(uint256 _cardID, uint256 _cardToBoost) public {
require(crafterContract.balanceOf(msg.sender, _cardID) > 0, "You do not own this card");
(,uint256 _cardType, uint256 boostAmount,,,,,,) = crafterContract.cards(_cardID);
require(_cardType == 3, "This is not a booster card");
(,uint256 _cardTypeToBoost,,uint256 _intialRedeems,,,,,) = crafterContract.cards(_cardToBoost);
require(_cardTypeToBoost == 2, "Destructable and booster cards cannot be boosted");
require(_intialRedeems > 0, "Collectable cards with no rewards cannot be boosted");
crafterContract.applyCardBooster(_cardToBoost, boostAmount);
crafterContract.burnCard(msg.sender,_cardID,1);
}
function transferOwnership(address payable _newOwner) public onlyOwner {
require(_newOwner != address(0), "New owner cannot be a zero address");
emit OwnershipTransferred(owner, _newOwner);
owner = _newOwner;
}
function renounceOwnership() public onlyOwner {
emit OwnershipRenounced(owner, address(0));
owner = address(0);
}
function closeContract() public payable onlyOwner {
require(tokenContract.transfer(owner, tokenContract.balanceOf(address(this))));
selfdestruct(owner);
}
modifier onlyOwner() {
require(owner == msg.sender, "Only the owner of the rewards contract can call this function");
_;
}
}
文件 11 的 13:lyncstakingv1.sol
pragma solidity ^0.7.0;
import "./lynctoken.sol";
contract LYNCStakingV1 {
using SafeMath for uint256;
address public owner;
address public contractAddress;
uint256 public totalRewards = 0;
uint256 public totalRewardsClaimed = 0;
uint256 public totalStakedV1 = 0;
uint256 public oneDay = 86400;
uint256 public SCALAR = 1e18;
uint256 public minimumTokenStake = 98;
uint256 public endOfStakeFee = 4;
LYNCToken public tokenContract;
event Stake(address _from, uint256 tokens);
event Unstake(address _to, uint256 tokens);
event UnstakeFee(address _to, uint256 tokens);
event CollectRewards(address _to, uint256 tokens);
struct Staker {
uint256 staked;
uint256 poolAtLastClaim;
uint256 userTimeStamp;
}
mapping(address => Staker) stakers;
constructor(LYNCToken _tokenContract) {
owner = msg.sender;
tokenContract = _tokenContract;
contractAddress = address(this);
}
function mulDiv(uint x, uint y, uint z) public pure returns (uint) {
(uint l, uint h) = fullMul (x, y);
assert (h < z);
uint mm = mulmod(x, y, z);
if (mm > l) h -= 1;
l -= mm;
uint pow2 = z & -z;
z /= pow2;
l /= pow2;
l += h * ((-pow2) / pow2 + 1);
uint r = 1;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
r *= 2 - z * r;
return l * r;
}
function fullMul(uint x, uint y) private pure returns (uint l, uint h) {
uint mm = mulmod(x, y, uint (-1));
l = x * y;
h = mm - l;
if (mm < l) h -= 1;
}
function rewardPoolBalance() public view returns(uint256) {
return tokenContract.balanceOf(address(this)).sub(totalStakedV1);
}
function stakerInformation(address _stakerAddress) public view returns(uint256, uint256, uint256) {
return (stakers[_stakerAddress].staked, stakers[_stakerAddress].poolAtLastClaim, stakers[_stakerAddress].userTimeStamp);
}
function stakeTokens(uint256 _numberOfTokens) external returns (bool) {
if(stakers[msg.sender].staked == 0) {
require(_numberOfTokens > (minimumTokenStake * SCALAR), "Not enough tokens to start staking");
require(tokenContract.transferFrom(msg.sender, address(this), _numberOfTokens));
stakers[msg.sender].poolAtLastClaim = totalRewards;
stakers[msg.sender].userTimeStamp = block.timestamp;
} else {
require(tokenContract.transferFrom(msg.sender, address(this), _numberOfTokens));
}
uint256 _feeAmount = (_numberOfTokens.mul(tokenContract.feePercent())).div(100);
uint256 _stakedAfterFee = _numberOfTokens.sub(_feeAmount);
stakers[msg.sender].staked = (stakers[msg.sender].staked).add(_stakedAfterFee);
totalStakedV1 = totalStakedV1.add(_stakedAfterFee);
totalRewards = rewardPoolBalance().add(totalRewardsClaimed);
emit Stake(msg.sender, _numberOfTokens);
return true;
}
function unstakeTokens() external returns (bool) {
uint256 _stakedTokens = stakers[msg.sender].staked;
uint256 _feeAmount = (_stakedTokens.mul(endOfStakeFee)).div(100);
uint256 _unstakeTokens = (stakers[msg.sender].staked).sub(_feeAmount);
require(tokenContract.transfer(msg.sender, _unstakeTokens));
totalStakedV1 = totalStakedV1.sub(_stakedTokens);
stakers[msg.sender].staked = 0;
stakers[msg.sender].poolAtLastClaim = 0;
stakers[msg.sender].userTimeStamp = 0;
totalRewards = rewardPoolBalance().add(totalRewardsClaimed);
emit Unstake(msg.sender, _unstakeTokens);
emit UnstakeFee(msg.sender, _feeAmount);
return true;
}
function claimRewards() external returns (bool) {
totalRewards = rewardPoolBalance().add(totalRewardsClaimed);
require(stakers[msg.sender].staked > 0, "You do not have any tokens staked");
require(block.timestamp > (stakers[msg.sender].userTimeStamp + oneDay), "You can only claim 24 hours after staking and once every 24 hours");
uint256 _poolSinceLastClaim = totalRewards.sub(stakers[msg.sender].poolAtLastClaim);
uint256 _rewardPercent = mulDiv(stakers[msg.sender].staked, 10000, totalStakedV1);
uint256 _rewardToClaim = mulDiv(_poolSinceLastClaim, _rewardPercent, 10000);
require(tokenContract.transfer(msg.sender, _rewardToClaim));
stakers[msg.sender].poolAtLastClaim = totalRewards;
stakers[msg.sender].userTimeStamp = block.timestamp;
totalRewardsClaimed = totalRewardsClaimed.add(_rewardToClaim);
totalRewards = rewardPoolBalance().add(totalRewardsClaimed);
emit CollectRewards(msg.sender, _rewardToClaim);
return true;
}
function updateStakeMinimum(uint256 _minimumTokenStake) public onlyOwner {
minimumTokenStake = _minimumTokenStake;
}
modifier onlyOwner() {
require(owner == msg.sender, "Only current owner can call this function");
_;
}
}
文件 12 的 13:lynctoken.sol
pragma solidity ^0.7.0;
import "./safemath.sol";
contract LYNCToken {
using SafeMath for uint256;
string constant public name = "LYNC Network";
string constant public symbol = "LYNC";
uint8 constant public decimals = 18;
address public owner;
address public rewardPoolAddress;
uint256 public maxTokenSupply = 1e24;
uint256 public feePercent = 1;
uint256 public feePercentMax = 10;
event Transfer(address indexed _from, address indexed _to, uint256 _tokens);
event Approval(address indexed _owner,address indexed _spender, uint256 _tokens);
event TranserFee(uint256 _tokens);
event UpdateFee(uint256 _fee);
event RewardPoolUpdated(address indexed _rewardPoolAddress, address indexed _newRewardPoolAddress);
event OwnershipTransferred(address indexed _previousOwner, address indexed _newOwner);
event OwnershipRenounced(address indexed _previousOwner, address indexed _newOwner);
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) private allowances;
constructor () {
owner = msg.sender;
rewardPoolAddress = address(this);
balanceOf[msg.sender] = maxTokenSupply;
emit Transfer(address(0), msg.sender, maxTokenSupply);
}
function totalSupply() public view returns (uint256) {
return maxTokenSupply;
}
function transfer(address _to, uint256 _tokens) public returns (bool) {
transferWithFee(msg.sender, _to, _tokens);
return true;
}
function transferFrom(address _from, address _to, uint256 _tokens) public returns (bool) {
require(_tokens <= balanceOf[_from], "Not enough tokens in the approved address balance");
require(_tokens <= allowances[_from][msg.sender], "token amount is larger than the current allowance");
transferWithFee(_from, _to, _tokens);
allowances[_from][msg.sender] = allowances[_from][msg.sender].sub(_tokens);
return true;
}
function approve(address _spender, uint256 _tokens) public returns (bool) {
allowances[msg.sender][_spender] = _tokens;
emit Approval(msg.sender, _spender, _tokens);
return true;
}
function allowance(address _owner, address _spender) public view returns (uint256) {
return allowances[_owner][_spender];
}
function transferWithFee(address _from, address _to, uint256 _tokens) internal returns (bool) {
require(balanceOf[_from] >= _tokens, "Not enough tokens in the senders balance");
uint256 _feeAmount = (_tokens.mul(feePercent)).div(100);
balanceOf[_from] = balanceOf[_from].sub(_tokens);
balanceOf[_to] = balanceOf[_to].add(_tokens.sub(_feeAmount));
balanceOf[rewardPoolAddress] = balanceOf[rewardPoolAddress].add(_feeAmount);
emit Transfer(_from, _to, _tokens.sub(_feeAmount));
emit Transfer(_from, rewardPoolAddress, _feeAmount);
emit TranserFee(_tokens);
return true;
}
function updateFee(uint256 _updateFee) public onlyOwner {
require(_updateFee <= feePercentMax, "Transaction fee cannot be greater than 10%");
feePercent = _updateFee;
emit UpdateFee(_updateFee);
}
function updateRewardPool(address _newRewardPoolAddress) public onlyOwner {
require(_newRewardPoolAddress != address(0), "New reward pool address cannot be a zero address");
rewardPoolAddress = _newRewardPoolAddress;
emit RewardPoolUpdated(rewardPoolAddress, _newRewardPoolAddress);
}
function rewardPoolBalanceTransfer() public onlyOwner returns (bool) {
uint256 _currentBalance = balanceOf[address(this)];
transferWithFee(address(this), rewardPoolAddress, _currentBalance);
return true;
}
function transferOwnership(address _newOwner) public onlyOwner {
require(_newOwner != address(0), "New owner cannot be a zero address");
emit OwnershipTransferred(owner, _newOwner);
owner = _newOwner;
}
function renounceOwnership() public onlyOwner {
emit OwnershipRenounced(owner, address(0));
owner = address(0);
}
modifier onlyOwner() {
require(owner == msg.sender, "Only current owner can call this function");
_;
}
}
文件 13 的 13:safemath.sol
pragma solidity ^0.7.0;
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
{
"compilationTarget": {
"lyncnftrewards.sol": "LYNCNFTRewardsV1"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract LYNCToken","name":"_tokenContract","type":"address"},{"internalType":"contract LYNCStakingV1","name":"_stakingContract","type":"address"},{"internalType":"contract LYNCCrafter","name":"_crafterContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"_newOwner","type":"address"}],"name":"OwnershipRenounced","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"},{"inputs":[],"name":"SCALAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"closeContract","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"crafterContract","outputs":[{"internalType":"contract LYNCCrafter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"},{"internalType":"uint256","name":"z","type":"uint256"}],"name":"mulDiv","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"oneDay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cardID","type":"uint256"},{"internalType":"uint256","name":"_cardToBoost","type":"uint256"}],"name":"redeemBoosterCard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cardID","type":"uint256"}],"name":"redeemLotto","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cardID","type":"uint256"}],"name":"redeemReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingContract","outputs":[{"internalType":"contract LYNCStakingV1","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenContract","outputs":[{"internalType":"contract LYNCToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]