编译器
0.8.14+commit.80d49f37
文件 1 的 8: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 的 8:ERC1155.sol
pragma solidity >=0.8.0;
abstract contract ERC1155 {
event TransferSingle(
address indexed operator,
address indexed from,
address indexed to,
uint256 id,
uint256 amount
);
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] amounts
);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);
mapping(address => mapping(uint256 => uint256)) public balanceOf;
mapping(address => mapping(address => bool)) public isApprovedForAll;
function uri(uint256 id) public view virtual returns (string memory);
function setApprovalForAll(address operator, bool approved) public virtual {
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) public virtual {
require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");
balanceOf[from][id] -= amount;
balanceOf[to][id] += amount;
emit TransferSingle(msg.sender, from, to, id, amount);
if (to.code.length != 0) {
require(
ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) ==
ERC1155TokenReceiver.onERC1155Received.selector,
"UNSAFE_RECIPIENT"
);
} else require(to != address(0), "INVALID_RECIPIENT");
}
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) public virtual {
require(ids.length == amounts.length, "LENGTH_MISMATCH");
require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");
uint256 id;
uint256 amount;
for (uint256 i = 0; i < ids.length; ) {
id = ids[i];
amount = amounts[i];
balanceOf[from][id] -= amount;
balanceOf[to][id] += amount;
unchecked {
++i;
}
}
emit TransferBatch(msg.sender, from, to, ids, amounts);
if (to.code.length != 0) {
require(
ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) ==
ERC1155TokenReceiver.onERC1155BatchReceived.selector,
"UNSAFE_RECIPIENT"
);
} else require(to != address(0), "INVALID_RECIPIENT");
}
function balanceOfBatch(address[] calldata owners, uint256[] calldata ids)
public
view
virtual
returns (uint256[] memory balances)
{
require(owners.length == ids.length, "LENGTH_MISMATCH");
balances = new uint256[](owners.length);
unchecked {
for (uint256 i = 0; i < owners.length; ++i) {
balances[i] = balanceOf[owners[i]][ids[i]];
}
}
}
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return
interfaceId == 0x01ffc9a7 ||
interfaceId == 0xd9b67a26 ||
interfaceId == 0x0e89341c;
}
function _mint(
address to,
uint256 id,
uint256 amount,
bytes memory data
) internal virtual {
balanceOf[to][id] += amount;
emit TransferSingle(msg.sender, address(0), to, id, amount);
if (to.code.length != 0) {
require(
ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) ==
ERC1155TokenReceiver.onERC1155Received.selector,
"UNSAFE_RECIPIENT"
);
} else require(to != address(0), "INVALID_RECIPIENT");
}
function _batchMint(
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {
uint256 idsLength = ids.length;
require(idsLength == amounts.length, "LENGTH_MISMATCH");
for (uint256 i = 0; i < idsLength; ) {
balanceOf[to][ids[i]] += amounts[i];
unchecked {
++i;
}
}
emit TransferBatch(msg.sender, address(0), to, ids, amounts);
if (to.code.length != 0) {
require(
ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) ==
ERC1155TokenReceiver.onERC1155BatchReceived.selector,
"UNSAFE_RECIPIENT"
);
} else require(to != address(0), "INVALID_RECIPIENT");
}
function _batchBurn(
address from,
uint256[] memory ids,
uint256[] memory amounts
) internal virtual {
uint256 idsLength = ids.length;
require(idsLength == amounts.length, "LENGTH_MISMATCH");
for (uint256 i = 0; i < idsLength; ) {
balanceOf[from][ids[i]] -= amounts[i];
unchecked {
++i;
}
}
emit TransferBatch(msg.sender, from, address(0), ids, amounts);
}
function _burn(
address from,
uint256 id,
uint256 amount
) internal virtual {
balanceOf[from][id] -= amount;
emit TransferSingle(msg.sender, from, address(0), id, amount);
}
}
abstract contract ERC1155TokenReceiver {
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes calldata
) external virtual returns (bytes4) {
return ERC1155TokenReceiver.onERC1155Received.selector;
}
function onERC1155BatchReceived(
address,
address,
uint256[] calldata,
uint256[] calldata,
bytes calldata
) external virtual returns (bytes4) {
return ERC1155TokenReceiver.onERC1155BatchReceived.selector;
}
}
文件 3 的 8:ERC1155B.sol
pragma solidity 0.8.14;
import {ERC1155TokenReceiver} from "solmate/tokens/ERC1155.sol";
abstract contract ERC1155B {
uint256 public constant MAX_SUPPLY = 18_000;
uint256 public constant MAX_ID = 17_999;
string public constant ERROR_ARRAY_LENGTH_MISMATCH = "ERC1155B: Array length mismatch";
string public constant ERROR_FROM_NOT_TOKEN_OWNER = "ERC1155B: From not token owner";
string public constant ERROR_ID_ALREADY_MINTED = "ERC1155B: ID already minted";
string public constant ERROR_ID_NOT_MINTED = "ERC1155B: ID not minted";
string public constant ERROR_INVALID_AMOUNT = "ERC1155B: Invalid amount";
string public constant ERROR_INVALID_FROM = "ERC1155B: Invalid from";
string public constant ERROR_INVALID_ID = "ERC1155B: Invalid ID";
string public constant ERROR_INVALID_RECIPIENT = "ERC1155B: Invalid recipient";
string public constant ERROR_NOT_AUTHORIZED = "ERC1155B: Not authorized";
string public constant ERROR_UNSAFE_RECIPIENT = "ERC1155B: Unsafe recipient";
bytes32 internal constant _ERROR_ENCODED_INVALID_ID = 0x45524331313535423a20496e76616c6964204944000000000000000000000000;
bytes32 internal constant _ERROR_ENCODED_INVALID_AMOUNT = 0x45524331313535423a20496e76616c696420616d6f756e740000000000000000;
bytes32 internal constant _ERROR_ENCODED_FROM_NOT_TOKEN_OWNER = 0x45524331313535423a2046726f6d206e6f7420746f6b656e206f776e65720000;
uint256 internal constant _ERROR_LENGTH_INVALID_ID = 20;
uint256 internal constant _ERROR_LENGTH_INVALID_AMOUNT = 24;
uint256 internal constant _ERROR_LENGTH_FROM_NOT_TOKEN_OWNER = 30;
bytes32 internal constant _ERROR_FUNCTION_SIGNATURE = 0x08c379a000000000000000000000000000000000000000000000000000000000;
uint256 internal constant _BITMASK_ADDRESS = 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff;
address[MAX_SUPPLY] public ownerOf;
mapping(address => mapping(address => bool)) public isApprovedForAll;
event URI(string value, uint256 indexed id);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
event TransferSingle(
address indexed operator,
address indexed from,
address indexed to,
uint256 id,
uint256 amount
);
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] amounts
);
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return
interfaceId == 0x01ffc9a7 ||
interfaceId == 0xd9b67a26 ||
interfaceId == 0x0e89341c;
}
function uri(uint256 id) public view virtual returns (string memory);
function setApprovalForAll(address operator, bool approved) public virtual {
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
function balanceOf(address owner, uint256 id) public view virtual returns (uint256 bal) {
address idOwner = ownerOf[id];
assembly {
bal := eq(idOwner, owner)
}
}
function balanceOfBatch(address[] calldata owners, uint256[] calldata ids)
public
view
virtual
returns (uint256[] memory balances)
{
require(owners.length == ids.length, ERROR_ARRAY_LENGTH_MISMATCH);
balances = new uint256[](owners.length);
unchecked {
for (uint256 i = 0; i < owners.length; ++i) {
balances[i] = balanceOf(owners[i], ids[i]);
}
}
}
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) public virtual {
require(msg.sender == from || isApprovedForAll[from][msg.sender], ERROR_NOT_AUTHORIZED);
require(id < MAX_SUPPLY, ERROR_INVALID_ID);
require(amount == 1, ERROR_INVALID_AMOUNT);
assembly {
let ownerOfIdSlot := add(ownerOf.slot, id)
let ownerOfId := sload(ownerOfIdSlot)
ownerOfId := and(ownerOfId, _BITMASK_ADDRESS)
if xor(ownerOfId, from) {
let freeMemory := mload(0x40)
mstore(freeMemory, _ERROR_FUNCTION_SIGNATURE)
mstore(add(freeMemory, 0x04), 0x20)
mstore(add(freeMemory, 0x24), _ERROR_LENGTH_FROM_NOT_TOKEN_OWNER)
mstore(add(freeMemory, 0x44), _ERROR_ENCODED_FROM_NOT_TOKEN_OWNER)
revert(freeMemory, 0x64)
}
sstore(ownerOfIdSlot, to)
}
emit TransferSingle(msg.sender, from, to, id, amount);
if (to.code.length != 0) {
require(
ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) ==
ERC1155TokenReceiver.onERC1155Received.selector,
ERROR_UNSAFE_RECIPIENT
);
} else require(to != address(0), ERROR_INVALID_RECIPIENT);
}
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) public virtual {
require(ids.length == amounts.length, ERROR_ARRAY_LENGTH_MISMATCH);
require(msg.sender == from || isApprovedForAll[from][msg.sender], ERROR_NOT_AUTHORIZED);
assembly {
let arrayLength := mul(ids.length, 0x20)
for
{ let indexOffset := 0x00 }
lt(indexOffset, arrayLength)
{ indexOffset := add(indexOffset, 0x20) }
{
let id := calldataload(add(ids.offset, indexOffset))
if gt(id, MAX_ID) {
let freeMemory := mload(0x40)
mstore(freeMemory, _ERROR_FUNCTION_SIGNATURE)
mstore(add(freeMemory, 0x04), 0x20)
mstore(add(freeMemory, 0x24), _ERROR_LENGTH_INVALID_ID)
mstore(add(freeMemory, 0x44), _ERROR_ENCODED_INVALID_ID)
revert(freeMemory, 0x64)
}
if xor(calldataload(add(amounts.offset, indexOffset)), 1) {
let freeMemory := mload(0x40)
mstore(freeMemory, _ERROR_FUNCTION_SIGNATURE)
mstore(add(freeMemory, 0x04), 0x20)
mstore(add(freeMemory, 0x24), _ERROR_LENGTH_INVALID_AMOUNT)
mstore(add(freeMemory, 0x44), _ERROR_ENCODED_INVALID_AMOUNT)
revert(freeMemory, 0x64)
}
let ownerOfIdSlot := add(ownerOf.slot, id)
let ownerOfId := sload(ownerOfIdSlot)
ownerOfId := and(ownerOfId, _BITMASK_ADDRESS)
if xor(ownerOfId, from) {
let freeMemory := mload(0x40)
mstore(freeMemory, _ERROR_FUNCTION_SIGNATURE)
mstore(add(freeMemory, 0x04), 0x20)
mstore(add(freeMemory, 0x24), _ERROR_LENGTH_FROM_NOT_TOKEN_OWNER)
mstore(add(freeMemory, 0x44), _ERROR_ENCODED_FROM_NOT_TOKEN_OWNER)
revert(freeMemory, 0x64)
}
sstore(ownerOfIdSlot, to)
}
}
emit TransferBatch(msg.sender, from, to, ids, amounts);
if (to.code.length != 0) {
require(
ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) ==
ERC1155TokenReceiver.onERC1155BatchReceived.selector,
ERROR_UNSAFE_RECIPIENT
);
} else require(to != address(0), ERROR_INVALID_RECIPIENT);
}
function _mint(
address to,
uint256 id,
bytes memory data
) internal virtual {
require(ownerOf[id] == address(0), ERROR_ID_ALREADY_MINTED);
ownerOf[id] = to;
emit TransferSingle(msg.sender, address(0), to, id, 1);
if (to.code.length != 0) {
require(
ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, 1, data) ==
ERC1155TokenReceiver.onERC1155Received.selector,
ERROR_UNSAFE_RECIPIENT
);
} else require(to != address(0), ERROR_INVALID_RECIPIENT);
}
function _batchMint(
address to,
uint256[] memory ids,
bytes memory data
) internal virtual {
uint256 idsLength = ids.length;
uint256[] memory amounts = new uint256[](idsLength);
uint256 id;
unchecked {
for (uint256 i = 0; i < idsLength; ++i) {
id = ids[i];
require(ownerOf[id] == address(0), ERROR_ID_ALREADY_MINTED);
ownerOf[id] = to;
amounts[i] = 1;
}
}
emit TransferBatch(msg.sender, address(0), to, ids, amounts);
if (to.code.length != 0) {
require(
ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) ==
ERC1155TokenReceiver.onERC1155BatchReceived.selector,
ERROR_UNSAFE_RECIPIENT
);
} else require(to != address(0), ERROR_INVALID_RECIPIENT);
}
function _burn(uint256 id) internal virtual {
address owner = ownerOf[id];
require(owner != address(0), ERROR_ID_NOT_MINTED);
ownerOf[id] = address(0);
emit TransferSingle(msg.sender, owner, address(0), id, 1);
}
function _batchBurn(address from, uint256[] memory ids) internal virtual {
require(from != address(0), ERROR_INVALID_FROM);
uint256 idsLength = ids.length;
uint256[] memory amounts = new uint256[](idsLength);
uint256 id;
unchecked {
for (uint256 i = 0; i < idsLength; ++i) {
id = ids[i];
require(from == ownerOf[id], ERROR_FROM_NOT_TOKEN_OWNER);
ownerOf[id] = address(0);
amounts[i] = 1;
}
}
emit TransferBatch(msg.sender, from, address(0), ids, amounts);
}
}
文件 4 的 8:ILockManager.sol
pragma solidity 0.8.14;
interface ILockManager {
function isLocked(address collection, address operator, address from, address to, uint256 id) external returns (bool);
function isLocked(address collection, address operator, address from, address to, uint256[] calldata ids) external returns (bool);
}
文件 5 的 8:ITickets.sol
pragma solidity 0.8.14;
interface ITickets {
function burn(address from, uint256 id, uint256 amount) external;
}
文件 6 的 8: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());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
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);
}
}
文件 7 的 8:PlayerHousing.sol
pragma solidity 0.8.14;
import "openzeppelin/access/Ownable.sol";
import "openzeppelin/utils/Strings.sol";
import "./ERC1155B.sol";
import "./ILockManager.sol";
import "./ITickets.sol";
contract PlayerHousing is ERC1155B, Ownable {
uint256 public constant MAX_SUPPLY_PER_FACTION = 6000;
uint256 public constant ID_OFFSET_ILLSKAGAARD = 6000;
uint256 public constant ID_OFFSET_LACREAN = 12000;
uint256 public constant MAX_MINT_AMOUNT_PER_TX = 5;
uint256 public constant MINT_PRICE = 0.1 ether;
uint256 public constant WHITELIST_TICKET_ID = 0;
uint256 public constant REWARDS_PER_SECOND = 105699306612548;
string public constant ERROR_NO_CONTRACT_MINTING = "PlayerHousing: No contract minting";
string public constant ERROR_NO_METADATA = "PlayerHousing: No metadata";
string public constant ERROR_NOT_APPROVED_FOR_REWARDS = "PlayerHousing: Not approved for rewards";
string public constant ERROR_OVER_MAX_AMOUNT_PER_TX_ARBORIA = "PlayerHousing: Arboria over max amount per tx";
string public constant ERROR_OVER_MAX_AMOUNT_PER_TX_ILLSKAGAARD = "PlayerHousing: Illskagaard over max amount per tx";
string public constant ERROR_OVER_MAX_AMOUNT_PER_TX_LACREAN = "PlayerHousing: Lacrean Empire over max amount per tx";
string public constant ERROR_OVER_MAX_AMOUNT_PER_TX_TOTAL = "PlayerHousing: Total over max amount per tx";
string public constant ERROR_REACHED_MAX_SUPPLY_ARBORIA = "PlayerHousing: Reached max Arboria supply";
string public constant ERROR_REACHED_MAX_SUPPLY_ILLSKAGAARD = "PlayerHousing: Reached max Illskagaard supply";
string public constant ERROR_REACHED_MAX_SUPPLY_LACREAN = "PlayerHousing: Reached max Lacrean Empire supply";
string public constant ERROR_SALE_NOT_READY_WHITELIST = "PlayerHousing: Whitelist sale not ready";
string public constant ERROR_SALE_NOT_READY_PUBLIC = "PlayerHousing: Public sale not ready";
string public constant ERROR_TOKEN_LOCKED = "PlayerHousing: Token locked";
string public constant ERROR_TOTAL_AMOUNT_BELOW_TWO = "PlayerHousing: Total amount below 2";
string public constant ERROR_WRONG_PRICE = "PlayerHousing: Wrong price";
uint256 public immutable TIMESTAMP_REWARDS_END;
uint256 public immutable TIMESTAMP_SALE_WHITELIST;
uint256 public immutable TIMESTAMP_SALE_PUBLIC;
ITickets public immutable TICKETS;
uint256 private constant _BITSHIFT_TOTAL_SUPPLY_ILLSKAGAARD = 16;
uint256 private constant _BITSHIFT_TOTAL_SUPPLY_LACREAN = 32;
uint256 private constant _BITSHIFT_REWARDS_LAST_UPDATED = 16;
uint256 private constant _BITSHIFT_REWARDS_BALANCE = 48;
uint256 private constant _BITMASK_TOTAL_SUPPLY = type(uint16).max;
uint256 private constant _BITMASK_TOTAL_SUPPLY_ARBORIA = ~_BITMASK_TOTAL_SUPPLY;
uint256 private constant _BITMASK_TOTAL_SUPPLY_ILLSKAGAARD = ~(_BITMASK_TOTAL_SUPPLY << _BITSHIFT_TOTAL_SUPPLY_ILLSKAGAARD);
uint256 private constant _BITMASK_TOTAL_SUPPLY_LACREAN = ~(_BITMASK_TOTAL_SUPPLY << _BITSHIFT_TOTAL_SUPPLY_LACREAN);
uint256 private constant _BITMASK_REWARDS_TOKEN_BALANCE = type(uint16).max;
uint256 private constant _BITMASK_REWARDS_LAST_UPDATED = type(uint32).max;
mapping(address => uint256) public rewardsBitField;
mapping(address => bool) public isApprovedForRewards;
ILockManager public lockManager;
string public baseURI;
string public uriSuffix;
uint256 private _totalSupplyBitField;
event ApprovalForRewards(address indexed operator, bool approved);
event LockManagerTransfer(address indexed previousLockManager, address indexed newLockManager);
constructor(
address owner,
uint256 timestampSaleWhitelist,
uint256 timestampSalePublic,
uint256 timestampRewardsEnd,
address tickets,
address _lockManager
) {
_transferOwnership(owner);
TIMESTAMP_SALE_WHITELIST = timestampSaleWhitelist;
TIMESTAMP_SALE_PUBLIC = timestampSalePublic;
TIMESTAMP_REWARDS_END = timestampRewardsEnd;
TICKETS = ITickets(tickets);
lockManager = ILockManager(_lockManager);
}
function uri(uint256 id) public view override returns (string memory) {
require(bytes(baseURI).length > 0, ERROR_NO_METADATA);
require(id < MAX_SUPPLY, ERROR_INVALID_ID);
return string(abi.encodePacked(baseURI, Strings.toString(id), uriSuffix));
}
function setBaseURI(string calldata _baseURI) external onlyOwner {
baseURI = _baseURI;
}
function setURISuffix(string calldata _uriSuffix) external onlyOwner {
uriSuffix = _uriSuffix;
}
function totalSupplyArboria() public view returns (uint256) {
return _totalSupplyBitField & _BITMASK_TOTAL_SUPPLY;
}
function totalSupplyIllskagaard() public view returns (uint256) {
return _totalSupplyBitField >> _BITSHIFT_TOTAL_SUPPLY_ILLSKAGAARD & _BITMASK_TOTAL_SUPPLY;
}
function totalSupplyLacrean() public view returns (uint256) {
return _totalSupplyBitField >> _BITSHIFT_TOTAL_SUPPLY_LACREAN;
}
function totalSupply() external view returns (uint256) {
return totalSupplyArboria() + totalSupplyIllskagaard() + totalSupplyLacrean();
}
function setLockManager(address _lockManager) external onlyOwner {
emit LockManagerTransfer(address(lockManager), _lockManager);
lockManager = ILockManager(_lockManager);
}
function setApprovalForRewards(address operator, bool approved) external onlyOwner {
isApprovedForRewards[operator] = approved;
emit ApprovalForRewards(operator, approved);
}
function setRewardsBitField(address owner, uint256 _rewardsBitField) external {
require(isApprovedForRewards[msg.sender], ERROR_NOT_APPROVED_FOR_REWARDS);
rewardsBitField[owner] = _rewardsBitField;
}
function balanceOf(address owner) public view returns (uint256) {
return rewardsBitField[owner] & _BITMASK_REWARDS_TOKEN_BALANCE;
}
function rewardsOf(address owner) external view returns (uint256 rewardsBalance) {
rewardsBalance = rewardsBitField[owner] >> _BITSHIFT_REWARDS_BALANCE;
uint256 lastUpdated = rewardsBitField[owner] >> _BITSHIFT_REWARDS_LAST_UPDATED & _BITMASK_REWARDS_LAST_UPDATED;
if (lastUpdated != TIMESTAMP_REWARDS_END) {
uint256 timestamp = block.timestamp < TIMESTAMP_REWARDS_END ? block.timestamp : TIMESTAMP_REWARDS_END;
uint256 tokenBalance = balanceOf(owner);
if (lastUpdated > 0) {
uint256 secondsSinceLastUpdate = timestamp - lastUpdated;
rewardsBalance += secondsSinceLastUpdate * REWARDS_PER_SECOND * tokenBalance;
}
}
}
function _updateRewardsForTransfer(address from, address to, uint256 tokenAmount) internal {
uint256 timestamp = block.timestamp < TIMESTAMP_REWARDS_END ? block.timestamp : TIMESTAMP_REWARDS_END;
uint256 _rewardsBitField = rewardsBitField[from];
uint256 lastUpdated = _rewardsBitField >> _BITSHIFT_REWARDS_LAST_UPDATED & _BITMASK_REWARDS_LAST_UPDATED;
if (lastUpdated != TIMESTAMP_REWARDS_END) {
uint256 tokenBalance = _rewardsBitField & _BITMASK_REWARDS_TOKEN_BALANCE;
uint256 rewardsBalance = _rewardsBitField >> _BITSHIFT_REWARDS_BALANCE;
if (lastUpdated > 0) {
uint256 secondsSinceLastUpdate = timestamp - lastUpdated;
unchecked {
rewardsBalance += secondsSinceLastUpdate * REWARDS_PER_SECOND * tokenBalance;
}
}
unchecked {
rewardsBitField[from] = tokenBalance - tokenAmount | timestamp << _BITSHIFT_REWARDS_LAST_UPDATED | rewardsBalance << _BITSHIFT_REWARDS_BALANCE;
}
}
_rewardsBitField = rewardsBitField[to];
lastUpdated = _rewardsBitField >> _BITSHIFT_REWARDS_LAST_UPDATED & _BITMASK_REWARDS_LAST_UPDATED;
if (lastUpdated != TIMESTAMP_REWARDS_END) {
uint256 tokenBalance = _rewardsBitField & _BITMASK_REWARDS_TOKEN_BALANCE;
uint256 rewardsBalance = _rewardsBitField >> _BITSHIFT_REWARDS_BALANCE;
if (lastUpdated > 0) {
uint256 secondsSinceLastUpdate = timestamp - lastUpdated;
unchecked {
rewardsBalance += secondsSinceLastUpdate * REWARDS_PER_SECOND * tokenBalance;
}
}
unchecked {
rewardsBitField[to] = tokenBalance + tokenAmount | timestamp << _BITSHIFT_REWARDS_LAST_UPDATED | rewardsBalance << _BITSHIFT_REWARDS_BALANCE;
}
}
}
function _updateRewardsForMint(address to, uint256 tokenAmount) internal {
uint256 _rewardsBitField = rewardsBitField[to];
uint256 tokenBalance = _rewardsBitField & _BITMASK_REWARDS_TOKEN_BALANCE;
uint256 lastUpdated = _rewardsBitField >> _BITSHIFT_REWARDS_LAST_UPDATED & _BITMASK_REWARDS_LAST_UPDATED;
uint256 rewardsBalance = _rewardsBitField >> _BITSHIFT_REWARDS_BALANCE;
if (lastUpdated > 0) {
uint256 secondsSinceLastUpdate = block.timestamp - lastUpdated;
unchecked {
rewardsBalance += secondsSinceLastUpdate * REWARDS_PER_SECOND * tokenBalance;
}
}
unchecked {
rewardsBitField[to] = tokenBalance + tokenAmount | block.timestamp << _BITSHIFT_REWARDS_LAST_UPDATED | rewardsBalance << _BITSHIFT_REWARDS_BALANCE;
}
}
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) public override {
require(msg.sender == from || isApprovedForAll[from][msg.sender], ERROR_NOT_AUTHORIZED);
require(id < MAX_SUPPLY, ERROR_INVALID_ID);
require(amount == 1, ERROR_INVALID_AMOUNT);
require(!lockManager.isLocked(address(this), msg.sender, from, to, id), ERROR_TOKEN_LOCKED);
assembly {
let ownerOfIdSlot := add(ownerOf.slot, id)
let ownerOfId := sload(ownerOfIdSlot)
ownerOfId := and(ownerOfId, _BITMASK_ADDRESS)
if xor(ownerOfId, from) {
let freeMemory := mload(0x40)
mstore(freeMemory, _ERROR_FUNCTION_SIGNATURE)
mstore(add(freeMemory, 0x04), 0x20)
mstore(add(freeMemory, 0x24), _ERROR_LENGTH_FROM_NOT_TOKEN_OWNER)
mstore(add(freeMemory, 0x44), _ERROR_ENCODED_FROM_NOT_TOKEN_OWNER)
revert(freeMemory, 0x64)
}
sstore(ownerOfIdSlot, to)
}
_updateRewardsForTransfer(from, to, amount);
emit TransferSingle(msg.sender, from, to, id, amount);
if (to.code.length != 0) {
require(
ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) ==
ERC1155TokenReceiver.onERC1155Received.selector,
ERROR_UNSAFE_RECIPIENT
);
} else require(to != address(0), ERROR_INVALID_RECIPIENT);
}
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) public override {
require(ids.length == amounts.length, ERROR_ARRAY_LENGTH_MISMATCH);
require(msg.sender == from || isApprovedForAll[from][msg.sender], ERROR_NOT_AUTHORIZED);
require(!lockManager.isLocked(address(this), msg.sender, from, to, ids), ERROR_TOKEN_LOCKED);
assembly {
let arrayLength := mul(ids.length, 0x20)
for
{ let indexOffset := 0x00 }
lt(indexOffset, arrayLength)
{ indexOffset := add(indexOffset, 0x20) }
{
let id := calldataload(add(ids.offset, indexOffset))
if gt(id, MAX_ID) {
let freeMemory := mload(0x40)
mstore(freeMemory, _ERROR_FUNCTION_SIGNATURE)
mstore(add(freeMemory, 0x04), 0x20)
mstore(add(freeMemory, 0x24), _ERROR_LENGTH_INVALID_ID)
mstore(add(freeMemory, 0x44), _ERROR_ENCODED_INVALID_ID)
revert(freeMemory, 0x64)
}
if xor(calldataload(add(amounts.offset, indexOffset)), 1) {
let freeMemory := mload(0x40)
mstore(freeMemory, _ERROR_FUNCTION_SIGNATURE)
mstore(add(freeMemory, 0x04), 0x20)
mstore(add(freeMemory, 0x24), _ERROR_LENGTH_INVALID_AMOUNT)
mstore(add(freeMemory, 0x44), _ERROR_ENCODED_INVALID_AMOUNT)
revert(freeMemory, 0x64)
}
let ownerOfIdSlot := add(ownerOf.slot, id)
let ownerOfId := sload(ownerOfIdSlot)
ownerOfId := and(ownerOfId, _BITMASK_ADDRESS)
if xor(ownerOfId, from) {
let freeMemory := mload(0x40)
mstore(freeMemory, _ERROR_FUNCTION_SIGNATURE)
mstore(add(freeMemory, 0x04), 0x20)
mstore(add(freeMemory, 0x24), _ERROR_LENGTH_FROM_NOT_TOKEN_OWNER)
mstore(add(freeMemory, 0x44), _ERROR_ENCODED_FROM_NOT_TOKEN_OWNER)
revert(freeMemory, 0x64)
}
sstore(ownerOfIdSlot, to)
}
}
_updateRewardsForTransfer(from, to, ids.length);
emit TransferBatch(msg.sender, from, to, ids, amounts);
if (to.code.length != 0) {
require(
ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) ==
ERC1155TokenReceiver.onERC1155BatchReceived.selector,
ERROR_UNSAFE_RECIPIENT
);
} else require(to != address(0), ERROR_INVALID_RECIPIENT);
}
function mintWhitelistArboria() external payable {
require(msg.sender == tx.origin, ERROR_NO_CONTRACT_MINTING);
require(block.timestamp >= TIMESTAMP_SALE_WHITELIST, ERROR_SALE_NOT_READY_WHITELIST);
require(msg.value == MINT_PRICE, ERROR_WRONG_PRICE);
TICKETS.burn(msg.sender, WHITELIST_TICKET_ID, 1);
_mintArboria(msg.sender);
}
function mintWhitelistIllskagaard() external payable {
require(msg.sender == tx.origin, ERROR_NO_CONTRACT_MINTING);
require(block.timestamp >= TIMESTAMP_SALE_WHITELIST, ERROR_SALE_NOT_READY_WHITELIST);
require(msg.value == MINT_PRICE, ERROR_WRONG_PRICE);
TICKETS.burn(msg.sender, WHITELIST_TICKET_ID, 1);
_mintIllskagaard(msg.sender);
}
function mintWhitelistLacrean() external payable {
require(msg.sender == tx.origin, ERROR_NO_CONTRACT_MINTING);
require(block.timestamp >= TIMESTAMP_SALE_WHITELIST, ERROR_SALE_NOT_READY_WHITELIST);
require(msg.value == MINT_PRICE, ERROR_WRONG_PRICE);
TICKETS.burn(msg.sender, WHITELIST_TICKET_ID, 1);
_mintLacrean(msg.sender);
}
function batchMintWhitelist(uint256 amountArboria, uint256 amountIllskagaard, uint256 amountLacrean) external payable {
require(msg.sender == tx.origin, ERROR_NO_CONTRACT_MINTING);
require(block.timestamp >= TIMESTAMP_SALE_WHITELIST, ERROR_SALE_NOT_READY_WHITELIST);
require(amountArboria <= MAX_MINT_AMOUNT_PER_TX, ERROR_OVER_MAX_AMOUNT_PER_TX_ARBORIA);
require(amountIllskagaard <= MAX_MINT_AMOUNT_PER_TX, ERROR_OVER_MAX_AMOUNT_PER_TX_ILLSKAGAARD);
require(amountLacrean <= MAX_MINT_AMOUNT_PER_TX, ERROR_OVER_MAX_AMOUNT_PER_TX_LACREAN);
uint256 amountTotal;
unchecked {
amountTotal = amountArboria + amountIllskagaard + amountLacrean;
}
require(amountTotal <= MAX_MINT_AMOUNT_PER_TX, ERROR_OVER_MAX_AMOUNT_PER_TX_TOTAL);
require(amountTotal > 1, ERROR_TOTAL_AMOUNT_BELOW_TWO);
unchecked {
require(msg.value == amountTotal * MINT_PRICE, ERROR_WRONG_PRICE);
}
TICKETS.burn(msg.sender, WHITELIST_TICKET_ID, amountTotal);
_batchMint(msg.sender, amountArboria, amountIllskagaard, amountLacrean, amountTotal);
}
function mintPublicArboria() external payable {
require(msg.sender == tx.origin, ERROR_NO_CONTRACT_MINTING);
require(block.timestamp >= TIMESTAMP_SALE_PUBLIC, ERROR_SALE_NOT_READY_PUBLIC);
require(msg.value == MINT_PRICE, ERROR_WRONG_PRICE);
_mintArboria(msg.sender);
}
function mintPublicIllskagaard() external payable {
require(msg.sender == tx.origin, ERROR_NO_CONTRACT_MINTING);
require(block.timestamp >= TIMESTAMP_SALE_PUBLIC, ERROR_SALE_NOT_READY_PUBLIC);
require(msg.value == MINT_PRICE, ERROR_WRONG_PRICE);
_mintIllskagaard(msg.sender);
}
function mintPublicLacrean() external payable {
require(msg.sender == tx.origin, ERROR_NO_CONTRACT_MINTING);
require(block.timestamp >= TIMESTAMP_SALE_PUBLIC, ERROR_SALE_NOT_READY_PUBLIC);
require(msg.value == MINT_PRICE, ERROR_WRONG_PRICE);
_mintLacrean(msg.sender);
}
function batchMintPublic(uint256 amountArboria, uint256 amountIllskagaard, uint256 amountLacrean) external payable {
require(msg.sender == tx.origin, ERROR_NO_CONTRACT_MINTING);
require(block.timestamp >= TIMESTAMP_SALE_PUBLIC, ERROR_SALE_NOT_READY_PUBLIC);
require(amountArboria <= MAX_MINT_AMOUNT_PER_TX, ERROR_OVER_MAX_AMOUNT_PER_TX_ARBORIA);
require(amountIllskagaard <= MAX_MINT_AMOUNT_PER_TX, ERROR_OVER_MAX_AMOUNT_PER_TX_ILLSKAGAARD);
require(amountLacrean <= MAX_MINT_AMOUNT_PER_TX, ERROR_OVER_MAX_AMOUNT_PER_TX_LACREAN);
uint256 amountTotal;
unchecked {
amountTotal = amountArboria + amountIllskagaard + amountLacrean;
}
require(amountTotal <= MAX_MINT_AMOUNT_PER_TX, ERROR_OVER_MAX_AMOUNT_PER_TX_TOTAL);
require(amountTotal > 1, ERROR_TOTAL_AMOUNT_BELOW_TWO);
unchecked {
require(msg.value == amountTotal * MINT_PRICE, ERROR_WRONG_PRICE);
}
_batchMint(msg.sender, amountArboria, amountIllskagaard, amountLacrean, amountTotal);
}
function mintOwnerLacrean(address to) external onlyOwner {
_mintLacrean(to);
}
function batchMintOwner(
address[] calldata tos,
uint256[] calldata amountsArboria,
uint256[] calldata amountsIllskagaard,
uint256[] calldata amountsLacrean
) external onlyOwner {
require(
tos.length == amountsArboria.length &&
amountsArboria.length == amountsIllskagaard.length &&
amountsIllskagaard.length == amountsLacrean.length,
ERROR_ARRAY_LENGTH_MISMATCH
);
uint256 arrayLength;
unchecked {
arrayLength = tos.length * 0x20;
}
for (uint256 indexOffset = 0x00; indexOffset < arrayLength;) {
address to;
uint256 amountArboria;
uint256 amountIllskagaard;
uint256 amountLacrean;
assembly {
to := calldataload(add(tos.offset, indexOffset))
amountArboria := calldataload(add(amountsArboria.offset, indexOffset))
amountIllskagaard := calldataload(add(amountsIllskagaard.offset, indexOffset))
amountLacrean := calldataload(add(amountsLacrean.offset, indexOffset))
indexOffset := add(indexOffset, 0x20)
}
unchecked {
uint256 amountTotal = amountArboria + amountIllskagaard + amountLacrean;
_batchMint(to, amountArboria, amountIllskagaard, amountLacrean, amountTotal);
}
}
}
function _mintArboria(address to) internal {
uint256 id = _totalSupplyBitField & _BITMASK_TOTAL_SUPPLY;
require(id < MAX_SUPPLY_PER_FACTION, ERROR_REACHED_MAX_SUPPLY_ARBORIA);
assembly {
let ownerOfIdSlot := add(ownerOf.slot, id)
sstore(ownerOfIdSlot, to)
}
unchecked {
_totalSupplyBitField++;
}
_updateRewardsForMint(to, 1);
emit TransferSingle(msg.sender, address(0), to, id, 1);
}
function _mintIllskagaard(address to) internal {
uint256 totalSupplyBitField = _totalSupplyBitField;
uint256 _totalSupplyIllskagaard = totalSupplyBitField >> _BITSHIFT_TOTAL_SUPPLY_ILLSKAGAARD & _BITMASK_TOTAL_SUPPLY;
require(_totalSupplyIllskagaard < MAX_SUPPLY_PER_FACTION, ERROR_REACHED_MAX_SUPPLY_ILLSKAGAARD);
uint256 id;
unchecked {
id = ID_OFFSET_ILLSKAGAARD + _totalSupplyIllskagaard;
}
assembly {
let ownerOfIdSlot := add(ownerOf.slot, id)
sstore(ownerOfIdSlot, to)
}
unchecked {
_totalSupplyBitField = totalSupplyBitField & _BITMASK_TOTAL_SUPPLY_ILLSKAGAARD | ++_totalSupplyIllskagaard << _BITSHIFT_TOTAL_SUPPLY_ILLSKAGAARD;
}
_updateRewardsForMint(to, 1);
emit TransferSingle(msg.sender, address(0), to, id, 1);
}
function _mintLacrean(address to) internal {
uint256 totalSupplyBitField = _totalSupplyBitField;
uint256 _totalSupplyLacrean = totalSupplyBitField >> _BITSHIFT_TOTAL_SUPPLY_LACREAN;
require(_totalSupplyLacrean < MAX_SUPPLY_PER_FACTION, ERROR_REACHED_MAX_SUPPLY_LACREAN);
uint256 id;
unchecked {
id = ID_OFFSET_LACREAN + _totalSupplyLacrean;
}
assembly {
let ownerOfIdSlot := add(ownerOf.slot, id)
sstore(ownerOfIdSlot, to)
}
unchecked {
_totalSupplyBitField = totalSupplyBitField & _BITMASK_TOTAL_SUPPLY_LACREAN | ++_totalSupplyLacrean << _BITSHIFT_TOTAL_SUPPLY_LACREAN;
}
_updateRewardsForMint(to, 1);
emit TransferSingle(msg.sender, address(0), to, id, 1);
}
function _batchMint(
address to,
uint256 amountArboria,
uint256 amountIllskagaard,
uint256 amountLacrean,
uint256 amountTotal
) internal {
uint256[] memory ids = new uint256[](amountTotal);
uint256[] memory amounts = new uint256[](amountTotal);
uint256 offsetIds;
uint256 offsetAmounts;
assembly {
offsetIds := add(ids, 0x20)
offsetAmounts := add(amounts, 0x20)
}
uint256 totalSupplyBitField = _totalSupplyBitField;
uint256 newTotalSupplyBitField = totalSupplyBitField;
if (amountArboria > 0) {
uint256 _totalSupplyArboria = totalSupplyBitField & _BITMASK_TOTAL_SUPPLY;
uint256 newTotalSupplyArboria;
unchecked {
newTotalSupplyArboria = _totalSupplyArboria + amountArboria;
}
require(newTotalSupplyArboria <= MAX_SUPPLY_PER_FACTION, ERROR_REACHED_MAX_SUPPLY_ARBORIA);
assembly {
for { let id := _totalSupplyArboria } lt(id, newTotalSupplyArboria) { id := add(id, 1) } {
let ownerOfIdSlot := add(ownerOf.slot, id)
sstore(ownerOfIdSlot, to)
mstore(offsetIds, id)
mstore(offsetAmounts, 1)
offsetIds := add(offsetIds, 0x20)
offsetAmounts := add(offsetAmounts, 0x20)
}
}
newTotalSupplyBitField = newTotalSupplyBitField & _BITMASK_TOTAL_SUPPLY_ARBORIA | newTotalSupplyArboria;
}
if (amountIllskagaard > 0) {
uint256 _totalSupplyIllskagaard = totalSupplyBitField >> _BITSHIFT_TOTAL_SUPPLY_ILLSKAGAARD & _BITMASK_TOTAL_SUPPLY;
uint256 newTotalSupplyIllskagaard;
unchecked {
newTotalSupplyIllskagaard = _totalSupplyIllskagaard + amountIllskagaard;
}
require(newTotalSupplyIllskagaard <= MAX_SUPPLY_PER_FACTION, ERROR_REACHED_MAX_SUPPLY_ILLSKAGAARD);
assembly {
for { let i := _totalSupplyIllskagaard } lt(i, newTotalSupplyIllskagaard) { i := add(i, 1) } {
let id := add(ID_OFFSET_ILLSKAGAARD, i)
let ownerOfIdSlot := add(ownerOf.slot, id)
sstore(ownerOfIdSlot, to)
mstore(offsetIds, id)
mstore(offsetAmounts, 1)
offsetIds := add(offsetIds, 0x20)
offsetAmounts := add(offsetAmounts, 0x20)
}
}
newTotalSupplyBitField = newTotalSupplyBitField & _BITMASK_TOTAL_SUPPLY_ILLSKAGAARD | newTotalSupplyIllskagaard << _BITSHIFT_TOTAL_SUPPLY_ILLSKAGAARD;
}
if (amountLacrean > 0) {
uint256 _totalSupplyLacrean = totalSupplyBitField >> _BITSHIFT_TOTAL_SUPPLY_LACREAN;
uint256 newTotalSupplyLacrean;
unchecked {
newTotalSupplyLacrean = _totalSupplyLacrean + amountLacrean;
}
require(newTotalSupplyLacrean <= MAX_SUPPLY_PER_FACTION, ERROR_REACHED_MAX_SUPPLY_LACREAN);
assembly {
for { let i := _totalSupplyLacrean } lt(i, newTotalSupplyLacrean) { i := add(i, 1) } {
let id := add(ID_OFFSET_LACREAN, i)
let ownerOfIdSlot := add(ownerOf.slot, id)
sstore(ownerOfIdSlot, to)
mstore(offsetIds, id)
mstore(offsetAmounts, 1)
offsetIds := add(offsetIds, 0x20)
offsetAmounts := add(offsetAmounts, 0x20)
}
}
newTotalSupplyBitField = newTotalSupplyBitField & _BITMASK_TOTAL_SUPPLY_LACREAN | newTotalSupplyLacrean << _BITSHIFT_TOTAL_SUPPLY_LACREAN;
}
_totalSupplyBitField = newTotalSupplyBitField;
_updateRewardsForMint(to, amountTotal);
emit TransferBatch(msg.sender, address(0), to, ids, amounts);
}
function owners() external view returns (address[MAX_SUPPLY] memory) {
return ownerOf;
}
function withdraw() external onlyOwner {
payable(msg.sender).transfer(address(this).balance);
}
}
文件 8 的 8:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}
{
"compilationTarget": {
"src/PlayerHousing.sol": "PlayerHousing"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 10000
},
"remappings": [
":ds-test/=lib/solmate/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":openzeppelin/=lib/openzeppelin-contracts/contracts/",
":script/=script/",
":solmate/=lib/solmate/src/",
":src/=src/",
":test/=test/"
]
}
[{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"timestampSaleWhitelist","type":"uint256"},{"internalType":"uint256","name":"timestampSalePublic","type":"uint256"},{"internalType":"uint256","name":"timestampRewardsEnd","type":"uint256"},{"internalType":"address","name":"tickets","type":"address"},{"internalType":"address","name":"_lockManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousLockManager","type":"address"},{"indexed":true,"internalType":"address","name":"newLockManager","type":"address"}],"name":"LockManagerTransfer","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":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"ERROR_ARRAY_LENGTH_MISMATCH","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_FROM_NOT_TOKEN_OWNER","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_ID_ALREADY_MINTED","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_ID_NOT_MINTED","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_INVALID_AMOUNT","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_INVALID_FROM","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_INVALID_ID","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_INVALID_RECIPIENT","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_NOT_APPROVED_FOR_REWARDS","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_NOT_AUTHORIZED","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_NO_CONTRACT_MINTING","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_NO_METADATA","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_OVER_MAX_AMOUNT_PER_TX_ARBORIA","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_OVER_MAX_AMOUNT_PER_TX_ILLSKAGAARD","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_OVER_MAX_AMOUNT_PER_TX_LACREAN","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_OVER_MAX_AMOUNT_PER_TX_TOTAL","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_REACHED_MAX_SUPPLY_ARBORIA","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_REACHED_MAX_SUPPLY_ILLSKAGAARD","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_REACHED_MAX_SUPPLY_LACREAN","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_SALE_NOT_READY_PUBLIC","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_SALE_NOT_READY_WHITELIST","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_TOKEN_LOCKED","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_TOTAL_AMOUNT_BELOW_TWO","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_UNSAFE_RECIPIENT","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERROR_WRONG_PRICE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ID_OFFSET_ILLSKAGAARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ID_OFFSET_LACREAN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_MINT_AMOUNT_PER_TX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY_PER_FACTION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINT_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARDS_PER_SECOND","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TICKETS","outputs":[{"internalType":"contract ITickets","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIMESTAMP_REWARDS_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIMESTAMP_SALE_PUBLIC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIMESTAMP_SALE_WHITELIST","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WHITELIST_TICKET_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"bal","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"owners","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tos","type":"address[]"},{"internalType":"uint256[]","name":"amountsArboria","type":"uint256[]"},{"internalType":"uint256[]","name":"amountsIllskagaard","type":"uint256[]"},{"internalType":"uint256[]","name":"amountsLacrean","type":"uint256[]"}],"name":"batchMintOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountArboria","type":"uint256"},{"internalType":"uint256","name":"amountIllskagaard","type":"uint256"},{"internalType":"uint256","name":"amountLacrean","type":"uint256"}],"name":"batchMintPublic","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountArboria","type":"uint256"},{"internalType":"uint256","name":"amountIllskagaard","type":"uint256"},{"internalType":"uint256","name":"amountLacrean","type":"uint256"}],"name":"batchMintWhitelist","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForRewards","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockManager","outputs":[{"internalType":"contract ILockManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mintOwnerLacrean","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintPublicArboria","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintPublicIllskagaard","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintPublicLacrean","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintWhitelistArboria","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintWhitelistIllskagaard","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintWhitelistLacrean","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owners","outputs":[{"internalType":"address[18000]","name":"","type":"address[18000]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardsBitField","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"rewardsOf","outputs":[{"internalType":"uint256","name":"rewardsBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","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":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_lockManager","type":"address"}],"name":"setLockManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"_rewardsBitField","type":"uint256"}],"name":"setRewardsBitField","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uriSuffix","type":"string"}],"name":"setURISuffix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupplyArboria","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupplyIllskagaard","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupplyLacrean","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":"uint256","name":"id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uriSuffix","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]