文件 1 的 7: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 的 7:ILand.sol
pragma solidity ^0.8.0;
interface ILand {
function maximumSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
}
文件 3 的 7:IMintPass.sol
pragma solidity ^0.8.0;
interface IMintPass {
function passExists(uint256 _passId) external view returns (bool);
function passDetail(uint256 _tokenId) external view returns (address, uint256, uint256);
function mintToken(
address _account,
uint256 _passId,
uint256 _count
) external;
function burnToken(uint256 _tokenId) external;
}
文件 4 的 7:IOre.sol
pragma solidity ^0.8.0;
interface IOre {
function balanceOf(address owner) external view returns (uint256);
function mint(address account, uint256 amount) external;
function burn(address account, uint256 amount) external;
}
文件 5 的 7:MintPassMinter.sol
pragma solidity ^0.8.0;
import "./Ownable.sol";
import "./ReentrancyGuard.sol";
import "./ILand.sol";
import "./IOre.sol";
import "./IMintPass.sol";
contract MintPassMinter is Ownable, ReentrancyGuard {
IMintPass public mintPass;
ILand public land;
IOre public ore;
mapping (uint256 => uint256) private _passPrices;
uint256 private _lastClaimTimestamp;
uint256 public totalFreePassClaimed;
mapping (uint256 => uint256) public totalPurchasedByPassId;
mapping (uint256 => uint256) public lastClaimTimestampByLandId;
uint256 private _freePassId;
constructor(
address _ore,
address _land,
address _mintPass
) {
ore = IOre(_ore);
land = ILand(_land);
mintPass = IMintPass(_mintPass);
}
function freePassId() external view returns (uint256) {
return _freePassId;
}
function passPrice(uint256 _passId) external view returns (uint256) {
require(mintPass.passExists(_passId), "Invalid PassId");
return _passPrices[_passId];
}
function setLastClaimTimestamp(uint256 _timestamp) external onlyOwner {
_lastClaimTimestamp = _timestamp;
}
function lastClaimTimestamp() external view returns (uint256) {
return _lastClaimTimestamp;
}
function setPassPrice(uint256 _passId, uint256 _price) external onlyOwner {
require(mintPass.passExists(_passId), "Invalid PassId");
_passPrices[_passId] = _price;
}
function setFreePassId(uint256 _passId) external onlyOwner {
require(mintPass.passExists(_passId), "Invalid PassId");
_freePassId = _passId;
}
function generatePassForMarketing(uint256 _passId, uint256 _count) external onlyOwner {
require(_count > 0, "Invalid Amount");
mintPass.mintToken(msg.sender, _passId, _count);
}
function unclaimedFreePass(address _account) external view returns (uint256) {
uint256 landOwned = land.balanceOf(_account);
uint256 mintCount = 0;
for (uint256 i = 0; i < landOwned; i++) {
uint256 tokenId = land.tokenOfOwnerByIndex(_account, i);
if (_lastClaimTimestamp > block.timestamp &&
_lastClaimTimestamp > lastClaimTimestampByLandId[tokenId]) {
mintCount++;
}
}
return mintCount;
}
function claimFreePass() external nonReentrant {
require(_freePassId > 0, "Pass Id Not Set");
uint256 landOwned = land.balanceOf(msg.sender);
require(landOwned > 0, "Reserved For Land Owners");
uint256 mintCount = 0;
for (uint256 i = 0; i < landOwned; i++) {
uint256 tokenId = land.tokenOfOwnerByIndex(msg.sender, i);
if (_lastClaimTimestamp > block.timestamp &&
_lastClaimTimestamp > lastClaimTimestampByLandId[tokenId]) {
mintCount++;
lastClaimTimestampByLandId[tokenId] = _lastClaimTimestamp;
}
}
require(mintCount > 0, "No Unclaimed Free Passes Found");
totalFreePassClaimed += mintCount;
mintPass.mintToken(msg.sender, _freePassId, mintCount);
}
function buyPass(uint256 _passId, uint256 _count) external nonReentrant {
require(mintPass.passExists(_passId), "Invalid PassId");
require(_passPrices[_passId] > 0, "Price Not Set");
uint256 totalPrice = _count * _passPrices[_passId];
require(ore.balanceOf(msg.sender) >= totalPrice, "Insufficient Ore");
totalPurchasedByPassId[_passId] += _count;
ore.burn(msg.sender, totalPrice);
mintPass.mintToken(msg.sender, _passId, _count);
}
}
文件 6 的 7:Ownable.sol
pragma solidity ^0.8.0;
import "./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);
}
}
文件 7 的 7: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": {
"MintPassMinter.sol": "MintPassMinter"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_ore","type":"address"},{"internalType":"address","name":"_land","type":"address"},{"internalType":"address","name":"_mintPass","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":"uint256","name":"_passId","type":"uint256"},{"internalType":"uint256","name":"_count","type":"uint256"}],"name":"buyPass","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimFreePass","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"freePassId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_passId","type":"uint256"},{"internalType":"uint256","name":"_count","type":"uint256"}],"name":"generatePassForMarketing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"land","outputs":[{"internalType":"contract ILand","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastClaimTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lastClaimTimestampByLandId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintPass","outputs":[{"internalType":"contract IMintPass","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ore","outputs":[{"internalType":"contract IOre","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_passId","type":"uint256"}],"name":"passPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_passId","type":"uint256"}],"name":"setFreePassId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"setLastClaimTimestamp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_passId","type":"uint256"},{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"setPassPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalFreePassClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalPurchasedByPassId","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":[{"internalType":"address","name":"_account","type":"address"}],"name":"unclaimedFreePass","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]