文件 1 的 4: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;
}
}
文件 2 的 4:MoonTurtlezMinter.sol
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
interface MoonTurtlez {
function owner() external view returns (address);
function mintToAddress(address to, uint256 amount) external;
function transferOwnership(address newOwner) external;
}
contract MoonTurtlezMinter is Ownable, ReentrancyGuard {
uint256 private _maxMintPerTx = 2;
uint256 private _maxMintPerWallet = 2;
bool private _mintStatus = false;
MoonTurtlez private _moonTurtlez;
mapping(address => uint256) private _mints;
constructor(address turtlezAddress) {
_moonTurtlez = MoonTurtlez(turtlezAddress);
}
function isMintingActive() external view returns (bool) {
return _mintStatus;
}
function getMintsOfAccount(address account)
external
view
returns (uint256)
{
return _mints[account];
}
function mint(uint256 amount) external turtleOwnerIsMinter nonReentrant {
if (!_mintStatus) revert("Minting has not started yet.");
if (amount == 0) revert("The amount must be greater than 0.");
if (amount > _maxMintPerTx)
revert("The amount exceeds the limit per tx.");
if (_mints[msg.sender] + amount > _maxMintPerWallet)
revert("The amount exceeds the limit per wallet.");
_moonTurtlez.mintToAddress(msg.sender, amount);
_mints[msg.sender] += amount;
}
function setMaxMintPerTx(uint256 newValue) external onlyOwner {
_maxMintPerTx = newValue;
}
function setMaxMintPerWallet(uint256 newValue) external onlyOwner {
_maxMintPerWallet = newValue;
}
function toggleMintStatus() external onlyOwner {
_mintStatus = !_mintStatus;
}
function setTurtlezContract(address turtlezAddress) external onlyOwner {
_moonTurtlez = MoonTurtlez(turtlezAddress);
}
function reclaimOwnership() external turtleOwnerIsMinter onlyOwner {
_moonTurtlez.transferOwnership(msg.sender);
}
modifier turtleOwnerIsMinter() {
if (_moonTurtlez.owner() != address(this))
revert(
"The owner of MoonTurtlez's contract must be this contract."
);
_;
}
}
文件 3 的 4: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() {
_transferOwnership(_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 {
_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);
}
}
文件 4 的 4:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
{
"compilationTarget": {
"contracts/moonturtlez/MoonTurtlezMinter.sol": "MoonTurtlezMinter"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"turtlezAddress","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"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getMintsOfAccount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isMintingActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reclaimOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setMaxMintPerTx","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setMaxMintPerWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"turtlezAddress","type":"address"}],"name":"setTurtlezContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleMintStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]