文件 1 的 2:ERC721A.sol
pragma solidity ^0.8.4;
import '@openzeppelin/contracts/token/ERC721/IERC721.sol';
import '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol';
import '@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol';
import '@openzeppelin/contracts/utils/Address.sol';
import '@openzeppelin/contracts/utils/Context.sol';
import '@openzeppelin/contracts/utils/Strings.sol';
import '@openzeppelin/contracts/utils/introspection/ERC165.sol';
error ApprovalCallerNotOwnerNorApproved();
error ApprovalQueryForNonexistentToken();
error ApproveToCaller();
error ApprovalToCurrentOwner();
error BalanceQueryForZeroAddress();
error MintToZeroAddress();
error MintZeroQuantity();
error OwnerQueryForNonexistentToken();
error TransferCallerNotOwnerNorApproved();
error TransferFromIncorrectOwner();
error TransferToNonERC721ReceiverImplementer();
error TransferToZeroAddress();
error URIQueryForNonexistentToken();
contract ERC721A is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
struct TokenOwnership {
address addr;
uint64 startTimestamp;
bool burned;
}
struct AddressData {
uint64 balance;
uint64 numberMinted;
uint64 numberBurned;
uint64 aux;
}
uint256 internal _currentIndex;
uint256 internal _burnCounter;
string private _name;
string private _symbol;
mapping(uint256 => TokenOwnership) internal _ownerships;
mapping(address => AddressData) private _addressData;
mapping(uint256 => address) private _tokenApprovals;
mapping(address => mapping(address => bool)) private _operatorApprovals;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
_currentIndex = _startTokenId();
}
function _startTokenId() internal view virtual returns (uint256) {
return 0;
}
function totalSupply() public view returns (uint256) {
unchecked {
return _currentIndex - _burnCounter - _startTokenId();
}
}
function _totalMinted() internal view returns (uint256) {
unchecked {
return _currentIndex - _startTokenId();
}
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
function balanceOf(address owner) public view override returns (uint256) {
if (owner == address(0)) revert BalanceQueryForZeroAddress();
return uint256(_addressData[owner].balance);
}
function _numberMinted(address owner) internal view returns (uint256) {
return uint256(_addressData[owner].numberMinted);
}
function _numberBurned(address owner) internal view returns (uint256) {
return uint256(_addressData[owner].numberBurned);
}
function _getAux(address owner) internal view returns (uint64) {
return _addressData[owner].aux;
}
function _setAux(address owner, uint64 aux) internal {
_addressData[owner].aux = aux;
}
function _ownershipOf(uint256 tokenId) internal view returns (TokenOwnership memory) {
uint256 curr = tokenId;
unchecked {
if (_startTokenId() <= curr && curr < _currentIndex) {
TokenOwnership memory ownership = _ownerships[curr];
if (!ownership.burned) {
if (ownership.addr != address(0)) {
return ownership;
}
while (true) {
curr--;
ownership = _ownerships[curr];
if (ownership.addr != address(0)) {
return ownership;
}
}
}
}
}
revert OwnerQueryForNonexistentToken();
}
function ownerOf(uint256 tokenId) public view override returns (address) {
return _ownershipOf(tokenId).addr;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
if (!_exists(tokenId)) revert URIQueryForNonexistentToken();
string memory baseURI = _baseURI();
return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : '';
}
function _baseURI() internal view virtual returns (string memory) {
return '';
}
function approve(address to, uint256 tokenId) public override {
address owner = ERC721A.ownerOf(tokenId);
if (to == owner) revert ApprovalToCurrentOwner();
if (_msgSender() != owner && !isApprovedForAll(owner, _msgSender())) {
revert ApprovalCallerNotOwnerNorApproved();
}
_approve(to, tokenId, owner);
}
function getApproved(uint256 tokenId) public view override returns (address) {
if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken();
return _tokenApprovals[tokenId];
}
function setApprovalForAll(address operator, bool approved) public virtual override {
if (operator == _msgSender()) revert ApproveToCaller();
_operatorApprovals[_msgSender()][operator] = approved;
emit ApprovalForAll(_msgSender(), operator, approved);
}
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
_transfer(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, '');
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
_transfer(from, to, tokenId);
if (to.isContract() && !_checkContractOnERC721Received(from, to, tokenId, _data)) {
revert TransferToNonERC721ReceiverImplementer();
}
}
function _exists(uint256 tokenId) internal view returns (bool) {
return _startTokenId() <= tokenId && tokenId < _currentIndex && !_ownerships[tokenId].burned;
}
function _safeMint(address to, uint256 quantity) internal {
_safeMint(to, quantity, '');
}
function _safeMint(
address to,
uint256 quantity,
bytes memory _data
) internal {
_mint(to, quantity, _data, true);
}
function _mint(
address to,
uint256 quantity,
bytes memory _data,
bool safe
) internal {
uint256 startTokenId = _currentIndex;
if (to == address(0)) revert MintToZeroAddress();
if (quantity == 0) revert MintZeroQuantity();
_beforeTokenTransfers(address(0), to, startTokenId, quantity);
unchecked {
_addressData[to].balance += uint64(quantity);
_addressData[to].numberMinted += uint64(quantity);
_ownerships[startTokenId].addr = to;
_ownerships[startTokenId].startTimestamp = uint64(block.timestamp);
uint256 updatedIndex = startTokenId;
uint256 end = updatedIndex + quantity;
if (safe && to.isContract()) {
do {
emit Transfer(address(0), to, updatedIndex);
if (!_checkContractOnERC721Received(address(0), to, updatedIndex++, _data)) {
revert TransferToNonERC721ReceiverImplementer();
}
} while (updatedIndex != end);
if (_currentIndex != startTokenId) revert();
} else {
do {
emit Transfer(address(0), to, updatedIndex++);
} while (updatedIndex != end);
}
_currentIndex = updatedIndex;
}
_afterTokenTransfers(address(0), to, startTokenId, quantity);
}
function _transfer(
address from,
address to,
uint256 tokenId
) private {
TokenOwnership memory prevOwnership = _ownershipOf(tokenId);
if (prevOwnership.addr != from) revert TransferFromIncorrectOwner();
bool isApprovedOrOwner = (_msgSender() == from ||
isApprovedForAll(from, _msgSender()) ||
getApproved(tokenId) == _msgSender());
if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();
if (to == address(0)) revert TransferToZeroAddress();
_beforeTokenTransfers(from, to, tokenId, 1);
_approve(address(0), tokenId, from);
unchecked {
_addressData[from].balance -= 1;
_addressData[to].balance += 1;
TokenOwnership storage currSlot = _ownerships[tokenId];
currSlot.addr = to;
currSlot.startTimestamp = uint64(block.timestamp);
uint256 nextTokenId = tokenId + 1;
TokenOwnership storage nextSlot = _ownerships[nextTokenId];
if (nextSlot.addr == address(0)) {
if (nextTokenId != _currentIndex) {
nextSlot.addr = from;
nextSlot.startTimestamp = prevOwnership.startTimestamp;
}
}
}
emit Transfer(from, to, tokenId);
_afterTokenTransfers(from, to, tokenId, 1);
}
function _burn(uint256 tokenId) internal virtual {
_burn(tokenId, false);
}
function _burn(uint256 tokenId, bool approvalCheck) internal virtual {
TokenOwnership memory prevOwnership = _ownershipOf(tokenId);
address from = prevOwnership.addr;
if (approvalCheck) {
bool isApprovedOrOwner = (_msgSender() == from ||
isApprovedForAll(from, _msgSender()) ||
getApproved(tokenId) == _msgSender());
if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();
}
_beforeTokenTransfers(from, address(0), tokenId, 1);
_approve(address(0), tokenId, from);
unchecked {
AddressData storage addressData = _addressData[from];
addressData.balance -= 1;
addressData.numberBurned += 1;
TokenOwnership storage currSlot = _ownerships[tokenId];
currSlot.addr = from;
currSlot.startTimestamp = uint64(block.timestamp);
currSlot.burned = true;
uint256 nextTokenId = tokenId + 1;
TokenOwnership storage nextSlot = _ownerships[nextTokenId];
if (nextSlot.addr == address(0)) {
if (nextTokenId != _currentIndex) {
nextSlot.addr = from;
nextSlot.startTimestamp = prevOwnership.startTimestamp;
}
}
}
emit Transfer(from, address(0), tokenId);
_afterTokenTransfers(from, address(0), tokenId, 1);
unchecked {
_burnCounter++;
}
}
function _approve(
address to,
uint256 tokenId,
address owner
) private {
_tokenApprovals[tokenId] = to;
emit Approval(owner, to, tokenId);
}
function _checkContractOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver(to).onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert TransferToNonERC721ReceiverImplementer();
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
function _beforeTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity
) internal virtual {}
function _afterTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity
) internal virtual {}
}
文件 2 的 2:aacc_official_mint.sol
pragma solidity ^0.8.4;
pragma abicoder v2;
import "./ERC721A.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
contract AngryApesCountryClub is ERC721A, Ownable {
using SafeMath for uint256;
using Strings for uint256;
bytes32 public merkleRoot;
bytes32 public vipMerkleRoot;
uint256 constant public MAX_SUPPLY= 5000;
uint256 constant public MAX_WL_SUPPLY = 500;
uint256 constant public MAX_VIPWL_SUPPLY = 1250;
uint256 public WL_PRICE = 0.19 ether;
uint256 public VIPWL_PRICE = 0.26 ether;
uint256 public PRICE = 0.32 ether;
uint256 public giveawayLimit = 250;
string public baseTokenURI;
bool public whitelistSaleIsActive;
bool public saleIsActive;
address private wallet1 = 0x5cB857F819E33252d75423dbF39550cD768bdc22;
address private wallet2 = 0x5f44114Cc117167982a1F08faD60aCDBF0b63ef0;
address private wallet3 = 0xdd176D72c0bC94dc10DFbA76716074F2c1D8cb02;
address private wallet4 = 0xE29cC153F6D64f5FAc547d16F07f18D0020075c5;
address private wallet5 = 0x282781484bDeBD41346D063b65F596f63fd2F03e;
address private wallet6 = 0xf02C95775A55BDaF85C6C873473f89A14920ED17;
address private wallet7 = 0x23bE357297a2f08f8456ad81F553CBc61EC6272c;
address private wallet8 = 0xEbe792d072f7dF72af667Ea5bb237B8D840De675;
address private wallet9 = 0x669bd3305D7CDaea7394DcdB99236371bBA3d259;
address private wallet10 = 0xabfF75d5D89Af95F3A27bdeED14D12B2A2Dc0C31;
address public Authorized = 0x7a29d9a21A45E269F1bFFFa15a84c16BA0050E27;
uint256 public maxPurchase = 100;
uint256 public maxWLPurchase = 5;
uint256 public maxVIPPurchase = 5;
uint256 public maxTxWL = 5;
uint256 public maxTxVIP = 5;
uint256 public maxTx = 100;
constructor() ERC721A("Angry Apes Country Club", "AACC") { }
modifier callerIsUser() {
require(tx.origin == msg.sender, "The caller is another contract");
_;
}
modifier onlyAuthorized {
require(msg.sender == owner() || msg.sender == Authorized , "Not authorized");
_;
}
function _baseURI() internal view virtual override returns (string memory) {
return baseTokenURI;
}
function setBaseURI(string memory baseURI) public onlyOwner {
baseTokenURI = baseURI;
}
function flipSaleState() external onlyOwner {
saleIsActive = !saleIsActive;
}
function flipWhitelistSaleState() external onlyOwner {
whitelistSaleIsActive = !whitelistSaleIsActive;
}
function updateMerkleRoot(bytes32 newMerkleRoot) external onlyOwner {
merkleRoot = newMerkleRoot;
}
function updateVIPMerkleRoot(bytes32 newMerkleRoot) external onlyOwner {
vipMerkleRoot = newMerkleRoot;
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
if (!_exists(tokenId)) revert URIQueryForNonexistentToken();
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString(),".json")) : "";
}
function _startTokenId() internal view virtual override returns (uint256) {
return 1;
}
function whitelistMint(uint256 numberOfTokens, bytes32[] calldata merkleProof ) payable external callerIsUser {
require(whitelistSaleIsActive, "Whitelist Sale must be active to mint");
require(totalSupply().add(numberOfTokens) <= MAX_WL_SUPPLY, "Total WL Supply has been minted");
require(numberOfTokens > 0 && numberOfTokens <= maxTxWL, "Can only mint upto 1 NFTs in a transaction");
require(msg.value == WL_PRICE.mul(numberOfTokens), "Ether value sent is not correct");
require(numberMinted(msg.sender).add(numberOfTokens) <= maxWLPurchase,"Exceeds Max mints allowed per whitelisted wallet");
require(MerkleProof.verify(merkleProof, merkleRoot, keccak256(abi.encodePacked(msg.sender)) ), "Invalid proof");
_safeMint(msg.sender, numberOfTokens);
}
function vipMint(uint256 numberOfTokens, bytes32[] calldata merkleProof ) payable external callerIsUser {
require(whitelistSaleIsActive, "Whitelist Sale must be active to mint");
require(totalSupply().add(numberOfTokens) <= MAX_VIPWL_SUPPLY, "Total VIPWL Supply has been minted");
require(numberOfTokens > 0 && numberOfTokens <= maxTxVIP, "Can only mint upto 2 NFTs in a transaction");
require(msg.value == VIPWL_PRICE.mul(numberOfTokens), "Ether value sent is not correct");
require(numberMinted(msg.sender).add(numberOfTokens) <= maxVIPPurchase,"Exceeds Max mints allowed per whitelisted wallet");
require(MerkleProof.verify(merkleProof, vipMerkleRoot, keccak256(abi.encodePacked(msg.sender)) ), "Invalid proof");
_safeMint(msg.sender, numberOfTokens);
}
function mint(uint256 numberOfTokens) external payable callerIsUser {
require(saleIsActive, "Sale must be active to mint");
require(totalSupply().add(numberOfTokens) <= MAX_SUPPLY, "Total Supply has been minted");
require(msg.value == PRICE.mul(numberOfTokens), "Ether value sent is not correct");
require(numberOfTokens > 0 && numberOfTokens <= maxTx, "1 pTX allowed");
require(numberMinted(msg.sender).add(numberOfTokens) <= maxPurchase,"Exceeds Max mints allowed per wallet");
_safeMint(msg.sender, numberOfTokens);
}
function withdraw() public onlyOwner {
uint balance = address(this).balance;
payable(msg.sender).transfer(balance);
}
function withdrawAll() external onlyOwner {
require(address(this).balance > 0, "No balance");
uint256 _amount = address(this).balance;
(bool wallet1Success, ) = wallet1.call{value: _amount.mul(35).div(100)}("");
(bool wallet2Success, ) = wallet2.call{value: _amount.mul(4).div(100)}("");
(bool wallet3Success, ) = wallet3.call{value: _amount.mul(2).div(100)}("");
(bool wallet4Success, ) = wallet4.call{value: _amount.mul(5).div(100)}("");
(bool wallet5Success, ) = wallet5.call{value: _amount.mul(5).div(100)}("");
(bool wallet6Success, ) = wallet6.call{value: _amount.mul(2).div(100)}("");
(bool wallet7Success, ) = wallet7.call{value: _amount.mul(7).div(100)}("");
(bool wallet8Success, ) = wallet8.call{value: _amount.mul(6).div(100)}("");
(bool wallet9Success, ) = wallet9.call{value: _amount.mul(17).div(100)}("");
(bool wallet10Success, ) = wallet10.call{value: _amount.mul(17).div(100)}("");
require(wallet1Success && wallet2Success && wallet3Success && wallet4Success && wallet5Success && wallet6Success && wallet7Success && wallet8Success && wallet9Success && wallet10Success, "Withdrawal failed.");
}
function giveAway(uint256 numberOfTokens, address to) external onlyOwner {
require(giveawayLimit.sub(numberOfTokens) >= 0,"Giveaways exhausted");
_safeMint(to, numberOfTokens);
giveawayLimit = giveawayLimit.sub(numberOfTokens);
}
function numberMinted(address owner) public view returns (uint256) {
return _numberMinted(owner);
}
function setPriceWL(uint256 _wlPrice) public onlyAuthorized {
WL_PRICE = _wlPrice;
}
function setPriceVIPWL(uint256 _vipwlPrice) public onlyAuthorized {
VIPWL_PRICE = _vipwlPrice;
}
function setPrice(uint256 _price) public onlyAuthorized {
PRICE = _price;
}
function setMaxTxLimit(uint256 _txLimit) public onlyAuthorized {
maxTx = _txLimit;
}
function setMaxTxWL(uint256 _txLimit) public onlyAuthorized {
maxTxWL = _txLimit;
}
function setMaxTxVIP(uint256 _txLimit) public onlyAuthorized {
maxTxVIP = _txLimit;
}
function setMaxPurchaseLimit(uint256 _limit) public onlyAuthorized {
maxPurchase = _limit;
}
function setMaxWLPurchaseLimit(uint256 _limit) public onlyAuthorized {
maxWLPurchase = _limit;
}
function setMaxVIPPurchaseLimit(uint256 _limit) public onlyAuthorized {
maxVIPPurchase = _limit;
}
}