// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.7;
import "https://github.com/sda-p/ethereum-erc721/src/contracts/tokens/nf-token-metadata.sol";
import "https://github.com/sda-p/ethereum-erc721/src/contracts/ownership/ownable.sol";
contract EtherGals is NFTokenMetadata, Ownable
{
// Properties
address payable feeAddress;
uint constant public galPrice = 0.05555 ether;
uint constant public giftGals = 55; // Gals Reserved for Giveaways and Team
uint constant public maxGals = 5555; // Total Gal Supply
bool public buyingActive = false; // Can you reserve a gal? Yes or no.
bool public mintingActive = false; // Is minting open? Yes or no.
bool public isWhiteListActive = true; // Is the public sale open or is it only whitelisted?
mapping(address => bool) private whiteList; // Map of addresses on the whitelist.
mapping(address => uint256) public galsReserved; // Map of how many gals are reserved for buyer addresses.
mapping(address => uint256) private galsClaimed; // How many gals an address has claimed.
mapping(address => uint256) public simps; //Tracks simps
mapping(uint => uint256) public simpedTo; //Tracks total simping for each token ID
uint256 public purchaseLimit = 5; // Purchase limit per wallet and Max per txn
uint256 public currentMintedGal = 0;
uint256 public currentReservedGal = 0;
uint256 public currentGiftGal = 0;
uint public adjustedSimpingTax = 33; // 3.3% SIMPing tax goes to the treasury
string private metaAddress = "https://api.ethergals.io/metadata/";
string constant private jsonAppend = ".json";
// Events
event Reserved(address sender, uint256 count);
event Minted(address sender, uint256 count);
event Simped(address simper, uint256 simpee, uint256 amount);
event LimitChanged(uint256 amount);
constructor()
{
nftName = "EtherGals";
nftSymbol = "EG";
feeAddress = payable(msg.sender);
}
function tokenURI(uint tokenID) external view returns (string memory)
{ // @dev Token URIs are generated dynamically on view requests.
// This is to allow easy server changes and reduce gas fees for minting. -ssa2
require(tokenID <= currentMintedGal, "Token hasn't been minted yet.");
bytes32 gal;
bytes memory concat;
gal = uintToBytes(tokenID);
concat = abi.encodePacked(metaAddress, gal, jsonAppend);
return string(concat);
}
// Toggle whether any gals can be minted at all.
function toggleMinting() public onlyOwner
{
mintingActive = !mintingActive;
}
// Toggle whether any gals can be purchased and reserved.
function toggleBuying() public onlyOwner
{
buyingActive = !buyingActive;
}
// Toggle if we're in the Whitelist or Public Sale.
function toggleWhiteList() public onlyOwner
{
isWhiteListActive = !isWhiteListActive;
}
// Add a list of wallet addresses to the Whitelist.
function addToWhiteList(address[] calldata addresses) external onlyOwner {
for (uint256 i = 0; i < addresses.length; i++) {
require(addresses[i] != address(0), "Can't add the null address");
whiteList[addresses[i]] = true;
//galsClaimed[addresses[i]] > 0 ? galsClaimed[addresses[i]] : 0;
}
}
// Tells teh world if a given address is whitelisted or not uwu.
function onWhiteList(address addr) external view returns (bool) {
return whiteList[addr];
}
// }:)
function removeFromwhiteList(address[] calldata addresses) external onlyOwner {
for (uint256 i = 0; i < addresses.length; i++) {
require(addresses[i] != address(0), "Can't add the null address");
whiteList[addresses[i]] = false;
}
}
// Tells teh world how many gals a given address has reserved to mint.
function galsReservedBy(address owner) external view returns (uint256){
require(owner != address(0), 'Zero address cant into reservations');
return galsReserved[owner];
}
// Tells teh world how many gals a given address has bongos binted.
function galsClaimedBy(address owner) external view returns (uint256){
require(owner != address(0), 'Zero address cant into mintings');
return galsClaimed[owner];
}
// NOTE: please remember to set this to peleus.eth send it all to me
function updateRecipient(address payable _newAddress) public onlyOwner
{
feeAddress = _newAddress;
}
// nininininininini - Runs In Circles (does string stuff)
function uintToBytes(uint v) private pure returns (bytes32 ret) {
if (v == 0)
{
ret = '0';
}
else
{
while (v > 0)
{
ret = bytes32(uint(ret) / (2 ** 8));
ret |= bytes32(((v % 10) + 48) * 2 ** (8 * 31));
v /= 10;
}
}
return ret;
}
function buy(uint8 _galNum) public payable
{
require(buyingActive, 'Reservations are not open.');
require(_galNum > 0, 'Must reserve at least one. Cannot buy 0.');
require(_galNum <= purchaseLimit, 'Cannot go over the current purchase limit.');
require(currentReservedGal + giftGals + _galNum <= maxGals, 'Cannot reserve more gals than there are left to buy.');
require(galsClaimed[msg.sender] + galsReserved[msg.sender] + _galNum <= purchaseLimit, 'Purchase exceeds max allowed per wallet.');
require(msg.value >= galPrice * _galNum, "Insufficient ETH for the selected amount.");
if(isWhiteListActive)
{
require(whiteList[msg.sender], 'You are not on the Whitelist.');
}
currentReservedGal += _galNum;
galsReserved[msg.sender] += _galNum;
emit Reserved(msg.sender, _galNum);
}
// Public Sale minting function
function mint(uint8 _galNum) public payable
{
require(mintingActive, 'Mintings are not yet open.');
require(_galNum > 0, 'Must mint at least one. Cannot mint 0.');
require(_galNum <= galsReserved[msg.sender], 'Cannot mint more Gals than you have left reserved.');
require(currentMintedGal + _galNum <= maxGals, 'Cannot mint more gals than there are left to mint.');
galsReserved[msg.sender] -= _galNum;
for(uint i=0; i < _galNum; i++)
{
currentMintedGal += 1;
super._mint(msg.sender, currentMintedGal);
galsClaimed[msg.sender] += 1;
}
emit Minted(msg.sender, _galNum);
}
// Mint one of the 55 team-giveaway gals to an array of hodlers.
function gift(address[] calldata to) external onlyOwner
{
require(currentMintedGal < maxGals, "All Gals have been minted.");
require(currentGiftGal + to.length <= giftGals, 'Not enough Gals left to gift');
for(uint256 i = 0; i < to.length; i++)
{
currentGiftGal += 1;
currentMintedGal += 1;
super._mint(to[i], currentMintedGal); // SER PLS FIX
}
}
// Mint one of the 55 team-giveaway gals. Ir's am itnrad sdlxs
function devMint(uint8 _giftNum) external onlyOwner
{
require(currentMintedGal < maxGals, "All Gals have been minted.");
require(currentGiftGal + _giftNum <= giftGals, 'Not enough Gals left to gift');
for(uint256 i = 0; i < _giftNum; i++)
{
currentGiftGal += 1;
currentMintedGal += 1;
super._mint(msg.sender, currentMintedGal);
}
}
// Father forgive me for I have SIMPED.
function simp(uint ID) public payable
{
simps[msg.sender] += msg.value;
uint256 simptax = (msg.value / 1000) * adjustedSimpingTax;
uint256 transferam = msg.value - simptax;
simpedTo[ID] += transferam;
payable(NFToken.ownerOfInternal(ID)).transfer(transferam);
feeAddress.transfer(simptax);
emit Simped(msg.sender, ID, msg.value);
}
// Withdraw the ETH stored in the contract.
function withdrawETH() external onlyOwner {
payable(msg.sender).transfer(address(this).balance);
}
// Update the metadata URI to a new server or IPFS if needed.
function updateURI(string calldata _URI) external onlyOwner {
metaAddress = _URI;
}
// Increase the amount of Gals that can be minted.
function updateLimit(uint newLimit) external onlyOwner
{
purchaseLimit = newLimit;
emit LimitChanged(purchaseLimit);
}
function updateSimpingTax(uint newSimpTax) external onlyOwner
{
adjustedSimpingTax = newSimpTax;
}
}
{
"compilationTarget": {
"ethergals.sol": "EtherGals"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_operator","type":"address"},{"indexed":false,"internalType":"bool","name":"_approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LimitChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"count","type":"uint256"}],"name":"Minted","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":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"count","type":"uint256"}],"name":"Reserved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"simper","type":"address"},{"indexed":false,"internalType":"uint256","name":"simpee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Simped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"CANNOT_TRANSFER_TO_ZERO_ADDRESS","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NOT_CURRENT_OWNER","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"}],"name":"addToWhiteList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"adjustedSimpingTax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_approved","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_galNum","type":"uint8"}],"name":"buy","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"buyingActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentGiftGal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentMintedGal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentReservedGal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_giftNum","type":"uint8"}],"name":"devMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"galPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"galsClaimedBy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"galsReserved","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"galsReservedBy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"to","type":"address[]"}],"name":"gift","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"giftGals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isWhiteListActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxGals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_galNum","type":"uint8"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintingActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"_name","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"onWhiteList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"purchaseLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"}],"name":"removeFromwhiteList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"ID","type":"uint256"}],"name":"simp","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"simpedTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"simps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"_symbol","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleBuying","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleMinting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleWhiteList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenID","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newLimit","type":"uint256"}],"name":"updateLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_newAddress","type":"address"}],"name":"updateRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newSimpTax","type":"uint256"}],"name":"updateSimpingTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_URI","type":"string"}],"name":"updateURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"}]