文件 1 的 5:ButtheadsFreeMint.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
abstract contract BH {
function mintButt(uint256 _numberOfButts) external payable virtual;
function buttsOfOwner(address _owner)
external
view
virtual
returns (uint256[] memory);
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual;
}
contract BHFreeMint is ERC721Holder, Ownable {
BH private butts;
address wallet = 0x8a8320ceb5D99b6BB5B3967f40f422E471BeD72B;
uint256 public _mintPrice = 0.06 ether;
uint256 public startTimeSale = 0;
bool public _freeMintActive = false;
mapping(address => bool) private _freeMintList;
mapping(address => uint256) private _freeMintListClaimed;
mapping(address => uint256) private _freeMintAllowed;
constructor(address dependedContract) {
butts = BH(dependedContract);
}
modifier onlyFreeMinters() {
require(
_freeMintList[_msgSender()],
"You are not on the free mint list"
);
_;
}
function addToFreeList(
address[] calldata addresses,
uint256[] calldata allowed
) external onlyOwner {
for (uint256 i = 0; i < addresses.length; i++) {
require(addresses[i] != address(0), "Address can not be null");
_freeMintList[addresses[i]] = true;
_freeMintListClaimed[addresses[i]] > 0
? _freeMintListClaimed[addresses[i]]
: 0;
_freeMintAllowed[addresses[i]] = allowed[i];
}
}
function setStartTimeSale(uint256 _startSale) external onlyOwner {
startTimeSale = _startSale;
}
function setPrice(uint256 _price) external onlyOwner {
_mintPrice = _price;
}
function onFreeMintList(address addr) external view returns (bool) {
return _freeMintList[addr];
}
function freeMintsLeft(address addr) external view returns (uint256) {
return
_freeMintList[addr]
? _freeMintAllowed[addr] - _freeMintListClaimed[addr]
: 0;
}
function setFreeMintState(bool val) external onlyOwner {
_freeMintActive = val;
}
function removeFromFreeMintList(address[] calldata addresses)
external
onlyOwner
{
for (uint256 i = 0; i < addresses.length; i++) {
require(addresses[i] != address(0), "Address can not be null");
_freeMintList[addresses[i]] = false;
}
}
function _mint(address _to, uint256 _butts) internal {
require(
address(this).balance >= _mintPrice * _butts,
"Not enough money in the contract"
);
butts.mintButt{value: _mintPrice * _butts}(_butts);
uint256[] memory booties = butts.buttsOfOwner(address(this));
for (uint256 i = 0; i < _butts; i++) {
butts.transferFrom(address(this), _to, booties[i]);
}
}
function gift(address _to, uint256 _butts) external onlyOwner {
_mint(_to, _butts);
}
function giftMany(address[] calldata _to, uint256[] calldata _butts)
external
onlyOwner
{
for (uint256 i = 0; i < _butts.length; i++) {
_mint(_to[i], _butts[i]);
}
}
function freeMint(uint256 _numberOfButts) external onlyFreeMinters {
require(_freeMintActive, "Free Mint is not active");
require(block.timestamp >= startTimeSale, "Free Mint did not start yet");
require(
_freeMintListClaimed[_msgSender()] + _numberOfButts <=
_freeMintAllowed[_msgSender()],
"Purchase exceeds max allowed"
);
_freeMintListClaimed[_msgSender()] += _numberOfButts;
_mint(_msgSender(), _numberOfButts);
}
function withdraw() public onlyOwner {
uint256 _amount = address(this).balance;
require(payable(wallet).send(_amount));
}
fallback() external payable {}
receive() external payable {}
}
文件 2 的 5: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;
}
}
文件 3 的 5:ERC721Holder.sol
pragma solidity ^0.8.0;
import "../IERC721Receiver.sol";
contract ERC721Holder is IERC721Receiver {
function onERC721Received(
address,
address,
uint256,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC721Received.selector;
}
}
文件 4 的 5:IERC721Receiver.sol
pragma solidity ^0.8.0;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 5 的 5: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() {
_setOwner(_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 {
_setOwner(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
{
"compilationTarget": {
"contracts/ButtheadsFreeMint.sol": "BHFreeMint"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"dependedContract","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":"OwnershipTransferred","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"_freeMintActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_mintPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"allowed","type":"uint256[]"}],"name":"addToFreeList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_numberOfButts","type":"uint256"}],"name":"freeMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"freeMintsLeft","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_butts","type":"uint256"}],"name":"gift","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_to","type":"address[]"},{"internalType":"uint256[]","name":"_butts","type":"uint256[]"}],"name":"giftMany","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"onFreeMintList","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":"address[]","name":"addresses","type":"address[]"}],"name":"removeFromFreeMintList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"val","type":"bool"}],"name":"setFreeMintState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_startSale","type":"uint256"}],"name":"setStartTimeSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startTimeSale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]