文件 1 的 1:TigerLottery.sol
pragma solidity ^0.8.4;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
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);
}
}
library Counters {
struct Counter {
uint256 _value;
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
unchecked {
counter._value += 1;
}
}
function decrement(Counter storage counter) internal {
uint256 value = counter._value;
require(value > 0, "Counter: decrement overflow");
unchecked {
counter._value = value - 1;
}
}
function reset(Counter storage counter) internal {
counter._value = 0;
}
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
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,
bytes calldata data
) external;
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 setApprovalForAll(address operator, bool _approved) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint tokenId,
bytes calldata data
) external returns (bytes4);
}
interface IERC721Metadata is IERC721 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
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;
}
}
library Address {
function isContract(address account) internal view returns (bool) {
uint size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
}
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}
contract TigerLottery is IERC721, IERC721Metadata, Ownable{
using SafeMath for uint256;
using Address for address;
using Strings for uint256;
string public override name;
string public override symbol;
string private _baseURI;
bool private _isBlindBox = true;
uint256 public constant totalSupply = 10000;
uint256 public constant mintWalletMaximumLimit = 50;
uint256 public constant mintPriceByEther = 0.006 ether;
address private _lpWallet;
IERC20 private _tokenContract;
uint private tokenUnitQuantity;
using Counters for Counters.Counter;
Counters.Counter private _tokenIdCounter;
mapping(uint => address) private _owners;
mapping(address => uint) private _balances;
mapping(uint => address) private _tokenApprovals;
mapping(address => mapping(address => bool)) private _operatorApprovals;
bool public isMintingEnabled = false;
bool private locked = false;
modifier lockTheMinting {
require(!locked, "Reentrant call.");
locked = true;
_;
locked = false;
}
constructor(address tokenContract,address lpWallet) {
name = unicode"Tiger Lottery";
symbol = unicode"Tiger Lottery";
_lpWallet = lpWallet;
_tokenContract = IERC20(tokenContract);
tokenUnitQuantity = _tokenContract.totalSupply().div(totalSupply).div(2);
}
function mints() public payable lockTheMinting{
require(isMintingEnabled, "Minting has not started");
require(msg.value > 0 && msg.value % mintPriceByEther == 0, "each NFT Mint fee 0.006ETH");
uint256 quantity = msg.value.div(mintPriceByEther);
require(balanceOf(_msgSender()).add(quantity) <= mintWalletMaximumLimit, "the quantity of wallet mint exceeds the maximum limit");
require(_tokenIdCounter.current().add(quantity) <= totalSupply, "tokenId out of range");
for (uint i = 0; i < quantity; i++){
_tokenIdCounter.increment();
_mint(_msgSender(), _tokenIdCounter.current());
}
_tokenContract.transfer(_msgSender(),tokenUnitQuantity.mul(quantity));
}
function airDrops(address[] memory recipients) public onlyOwner lockTheMinting{
require(recipients.length > 0, "Invalid input");
require(_tokenIdCounter.current().add(recipients.length) <= totalSupply, "tokenId out of range");
for (uint256 i = 0; i < recipients.length; i++) {
_tokenIdCounter.increment();
_mint(recipients[i], _tokenIdCounter.current());
_tokenContract.transfer(recipients[i],tokenUnitQuantity);
}
}
function setMintingEnabled(bool _isMintingEnabled) public onlyOwner {
isMintingEnabled = _isMintingEnabled;
}
function withdraw() public onlyOwner{
(bool success,) = _lpWallet.call{value:address(this).balance}("");
require(success, "feild");
}
function baseURI() public view returns (string memory) {
return _baseURI;
}
function setBaseURI(string memory uri,bool isBlindBox) public onlyOwner {
_baseURI = uri;
_isBlindBox = isBlindBox;
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_owners[tokenId] != address(0), "Token Not Exist");
if(_isBlindBox){
return _baseURI;
}else{
return string(abi.encodePacked(_baseURI,Strings.toString(tokenId),".json"));
}
}
function currentMintQuantity() public view returns (uint256) {
return _tokenIdCounter.current();
}
function supportsInterface(bytes4 interfaceId) external pure override returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC165).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId;
}
function balanceOf(address owner) public view override returns (uint) {
require(owner != address(0), "owner = zero address");
return _balances[owner];
}
function ownerOf(uint tokenId) public view override returns (address owner) {
owner = _owners[tokenId];
require(owner != address(0), "token doesn't exist");
}
function isApprovedForAll(address owner, address operator) external view override returns (bool){
return _operatorApprovals[owner][operator];
}
function setApprovalForAll(address operator, bool approved) external override {
_operatorApprovals[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
function getApproved(uint tokenId) external view override returns (address) {
require(_owners[tokenId] != address(0), "token doesn't exist");
return _tokenApprovals[tokenId];
}
function _approve(address owner, address to,uint tokenId) private {
_tokenApprovals[tokenId] = to;
emit Approval(owner, to, tokenId);
}
function approve(address to, uint tokenId) external override {
address owner = _owners[tokenId];
require(msg.sender == owner || _operatorApprovals[owner][msg.sender],"not owner nor approved for all");
_approve(owner, to, tokenId);
}
function _isApprovedOrOwner(address owner,address spender,uint tokenId) private view returns (bool) {
return (spender == owner || _tokenApprovals[tokenId] == spender || _operatorApprovals[owner][spender]);
}
function _transfer(address owner,address from,address to,uint tokenId) private {
require(from == owner, "not owner");
require(to != address(0), "transfer to the zero address");
_approve(owner, address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
}
function transferFrom(address from,address to,uint tokenId) external override {
address owner = ownerOf(tokenId);
require(_isApprovedOrOwner(owner, msg.sender, tokenId),"not owner nor approved");
_transfer(owner, from, to, tokenId);
}
function _safeTransfer(address owner,address from,address to,uint tokenId,bytes memory _data) private {
_transfer(owner, from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "not ERC721Receiver");
}
function safeTransferFrom(address from,address to,uint tokenId,bytes memory _data) public override {
address owner = ownerOf(tokenId);
require(_isApprovedOrOwner(owner, msg.sender, tokenId),"not owner nor approved");
_safeTransfer(owner, from, to, tokenId, _data);
}
function safeTransferFrom(address from,address to,uint tokenId) external override {
safeTransferFrom(from, to, tokenId, "");
}
function _mint(address to, uint tokenId) internal virtual {
require(to != address(0), "mint to zero address");
require(_owners[tokenId] == address(0), "token already minted");
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
}
function _burn(uint tokenId) internal virtual {
address owner = ownerOf(tokenId);
require(msg.sender == owner, "not owner of token");
_approve(owner, address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
}
function _checkOnERC721Received(address from,address to,uint tokenId,bytes memory _data) private returns (bool) {
if (to.isContract()) {
return IERC721Receiver(to).onERC721Received(msg.sender,from,tokenId,_data) == IERC721Receiver.onERC721Received.selector;
} else {
return true;
}
}
}