编译器
0.8.17+commit.8df45f5f
文件 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:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 3 的 8:IBase721A.sol
pragma solidity ^0.8.12;
interface IBase721A {
function mintTo(
address to,
uint256 amount,
uint24 extraData
) external;
}
文件 4 的 8:IERC1155.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC1155 is IERC165 {
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);
function balanceOf(address account, uint256 id) external view returns (uint256);
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
external
view
returns (uint256[] memory);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address account, address operator) external view returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}
文件 5 的 8:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 6 的 8:ITPLRevealedParts.sol
pragma solidity ^0.8.12;
import {IBase721A} from "../../utils/tokens/ERC721/IBase721A.sol";
interface ITPLRevealedParts is IBase721A {
struct TokenData {
uint256 generation;
uint256 originalId;
uint256 bodyPart;
uint256 model;
uint256[] stats;
}
function isOwnerOfBatch(address account, uint256[] calldata tokenIds) external view returns (bool);
function partData(uint256 tokenId) external view returns (TokenData memory);
function partDataBatch(uint256[] calldata tokenIds) external view returns (TokenData[] memory);
function burnBatch(uint256[] calldata tokenIds) external;
function batchTransferFrom(
address _from,
address _to,
uint256[] calldata _tokenIds
) external;
}
文件 7 的 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);
}
}
文件 8 的 8:TPLMechCrafter.sol
pragma solidity ^0.8.12;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ERC165, IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import {ITPLRevealedParts} from "../TPLRevealedParts/ITPLRevealedParts.sol";
contract TPLMechCrafter is Ownable {
error UserNotPartsOwner();
error InvalidBodyPart();
error InvalidPartsAmount();
error InvalidModelAmount();
error DelegationInactive();
error NotAuthorized();
error InvalidFees();
error ErrorWithdrawing();
error NothingToWithdraw();
error ErrorDisassemblyFeePayment();
error CraftingDisabled();
error InvalidLength();
event MechAssembly(uint256 indexed id, uint256 partsIds, uint256 extraData);
address public immutable TPL_REVEALED;
address public immutable TPL_AFTERGLOW;
address public immutable TPL_MECH;
address public immutable TPL_PARTS_ESCROW;
address public immutable DELEGATE_REGISTRY;
uint256 public disassemblyFee;
address public disassemblyFeeRecipient;
bool public delegationActive;
bool public craftingPublic;
mapping(address => bool) public allowedCrafters;
mapping(uint256 => uint256) public engineIds;
modifier craftingAllowed() {
if (!craftingPublic) {
if (!allowedCrafters[msg.sender]) {
revert CraftingDisabled();
}
}
_;
}
constructor(
address tplRevealed,
address tplAfterglow,
address tplMech,
address tplPartsEscrow,
address delegateRegistry,
address disassemblyFeeRecipient_,
uint256 disassemblyFee_
) {
TPL_REVEALED = tplRevealed;
TPL_AFTERGLOW = tplAfterglow;
TPL_MECH = tplMech;
TPL_PARTS_ESCROW = tplPartsEscrow;
DELEGATE_REGISTRY = delegateRegistry;
disassemblyFeeRecipient = disassemblyFeeRecipient_;
disassemblyFee = disassemblyFee_;
}
function parseExtraData(
uint256 extraData
) external pure returns (uint256 seed, uint256[] memory colors, bool[] memory colorsActive, bool emissive) {
seed = extraData & 0xffffff;
extraData = extraData >> 24;
colors = new uint256[](5);
for (uint256 i; i < 5; i++) {
colors[i] = extraData & 0xffffff;
extraData = extraData >> 24;
}
colorsActive = new bool[](5);
for (uint256 i; i < 5; i++) {
colorsActive[i] = 1 == (extraData & 1);
extraData = extraData >> 4;
}
emissive = (extraData & 1) == 1;
}
function craft(uint256[] calldata partsIds, uint256 afterglowId, uint256 extraData) external craftingAllowed {
_craft(partsIds, afterglowId, msg.sender, extraData);
}
function craftFor(
uint256[] calldata partsIds,
uint256 afterglowId,
uint256 extraData,
address vault
) external craftingAllowed {
if (!delegationActive) {
revert DelegationInactive();
}
_requireDelegate(vault);
_craft(partsIds, afterglowId, vault, extraData);
}
function disassemble(uint256 mechId) external payable {
_disassemble(mechId, msg.sender);
}
function disassembleFor(uint256 mechId, address vault) external payable {
if (!delegationActive) {
revert DelegationInactive();
}
_requireDelegate(vault);
_disassemble(mechId, vault);
}
function setDisassemblyFee(address newDisassemblyFeeRecipient, uint256 newFee) external onlyOwner {
disassemblyFeeRecipient = newDisassemblyFeeRecipient;
disassemblyFee = newFee;
}
function setDelegationActive(bool isActive) external onlyOwner {
delegationActive = isActive;
}
function setAllowedCrafters(address[] calldata crafters, bool allowed) external onlyOwner {
uint256 length = crafters.length;
if (length == 0) {
revert InvalidLength();
}
for (uint i; i < length; i++) {
allowedCrafters[crafters[i]] = allowed;
}
}
function setCraftingPublic(bool isPublic) external onlyOwner {
craftingPublic = isPublic;
}
function withdraw(address to) external onlyOwner {
uint256 balance = address(this).balance;
if (balance == 0) {
revert NothingToWithdraw();
}
(bool success, ) = to.call{value: balance}("");
if (!success) {
revert ErrorWithdrawing();
}
}
function _craft(uint256[] calldata partsIds, uint256 afterglowId, address account, uint256 extraData) internal {
uint256 length = partsIds.length;
if (length != 6) {
revert InvalidPartsAmount();
}
ITPLRevealedParts.TokenData[] memory tokenPartsData = ITPLRevealedParts(TPL_REVEALED).partDataBatch(partsIds);
uint256 packedIds;
unchecked {
uint256 engineModel = tokenPartsData[5].model;
uint256 sameModelAsEngine;
if (
tokenPartsData[0].bodyPart != 0 ||
tokenPartsData[1].bodyPart != 0 ||
tokenPartsData[2].bodyPart != 1 ||
tokenPartsData[3].bodyPart != 2 ||
tokenPartsData[4].bodyPart != 3 ||
tokenPartsData[5].bodyPart != 4
) {
revert InvalidBodyPart();
}
do {
length--;
if (tokenPartsData[length].model == engineModel) {
sameModelAsEngine++;
}
packedIds = packedIds | (partsIds[length] << (length * 32));
} while (length > 0);
if (sameModelAsEngine < 3) {
revert InvalidModelAmount();
}
}
packedIds = packedIds | (afterglowId << (6 * 32));
ITPLRevealedParts(TPL_REVEALED).batchTransferFrom(account, TPL_PARTS_ESCROW, partsIds);
IERC1155(TPL_AFTERGLOW).safeTransferFrom(account, TPL_PARTS_ESCROW, afterglowId, 1, "");
uint256 engineKnownId = engineIds[partsIds[5]];
if (engineKnownId != 0) {
ITPLMech(TPL_MECH).mintToken(engineKnownId, account, packedIds);
} else {
engineKnownId = ITPLMech(TPL_MECH).mintNext(account, packedIds);
engineIds[partsIds[5]] = engineKnownId;
}
emit MechAssembly(engineKnownId, packedIds, extraData);
}
function _disassemble(uint256 mechId, address account) internal {
if (msg.value != disassemblyFee) {
revert InvalidFees();
}
if (account != ITPLMech(TPL_MECH).ownerOf(mechId)) {
revert NotAuthorized();
}
(uint256[] memory partsIds, uint256 afterglowId) = ITPLMech(TPL_MECH).getMechPartsIds(mechId);
ITPLMech(TPL_MECH).burn(mechId);
ITPLRevealedParts(TPL_REVEALED).batchTransferFrom(TPL_PARTS_ESCROW, account, partsIds);
IERC1155(TPL_AFTERGLOW).safeTransferFrom(TPL_PARTS_ESCROW, account, afterglowId, 1, "");
if (msg.value > 0) {
address disassemblyFeeRecipient_ = disassemblyFeeRecipient;
if (disassemblyFeeRecipient_ != address(0)) {
(bool success, ) = disassemblyFeeRecipient_.call{value: msg.value}("");
if (!success) {
revert ErrorDisassemblyFeePayment();
}
}
}
}
function _requireDelegate(address vault) internal view {
if (!IDelegateRegistry(DELEGATE_REGISTRY).checkDelegateForContract(msg.sender, vault, address(this))) {
if (!IDelegateRegistry(DELEGATE_REGISTRY).checkDelegateForContract(msg.sender, vault, TPL_REVEALED)) {
revert NotAuthorized();
}
}
}
}
interface ITPLMech {
function mintNext(address to, uint256 packedIds) external returns (uint256);
function mintToken(uint256 tokenId, address to, uint256 packedIds) external;
function ownerOf(uint256 mechId) external view returns (address);
function burn(uint256 tokenId) external;
function getMechPartsIds(uint256 tokenId) external view returns (uint256[] memory, uint256);
}
interface IDelegateRegistry {
function checkDelegateForContract(address delegate, address vault, address contract_) external view returns (bool);
}
{
"compilationTarget": {
"src/TPL/TPLMech/TPLMechCrafter.sol": "TPLMechCrafter"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"tplRevealed","type":"address"},{"internalType":"address","name":"tplAfterglow","type":"address"},{"internalType":"address","name":"tplMech","type":"address"},{"internalType":"address","name":"tplPartsEscrow","type":"address"},{"internalType":"address","name":"delegateRegistry","type":"address"},{"internalType":"address","name":"disassemblyFeeRecipient_","type":"address"},{"internalType":"uint256","name":"disassemblyFee_","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CraftingDisabled","type":"error"},{"inputs":[],"name":"DelegationInactive","type":"error"},{"inputs":[],"name":"ErrorDisassemblyFeePayment","type":"error"},{"inputs":[],"name":"ErrorWithdrawing","type":"error"},{"inputs":[],"name":"InvalidBodyPart","type":"error"},{"inputs":[],"name":"InvalidFees","type":"error"},{"inputs":[],"name":"InvalidLength","type":"error"},{"inputs":[],"name":"InvalidModelAmount","type":"error"},{"inputs":[],"name":"InvalidPartsAmount","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"NothingToWithdraw","type":"error"},{"inputs":[],"name":"UserNotPartsOwner","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"partsIds","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"extraData","type":"uint256"}],"name":"MechAssembly","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"},{"inputs":[],"name":"DELEGATE_REGISTRY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TPL_AFTERGLOW","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TPL_MECH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TPL_PARTS_ESCROW","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TPL_REVEALED","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"allowedCrafters","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"partsIds","type":"uint256[]"},{"internalType":"uint256","name":"afterglowId","type":"uint256"},{"internalType":"uint256","name":"extraData","type":"uint256"}],"name":"craft","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"partsIds","type":"uint256[]"},{"internalType":"uint256","name":"afterglowId","type":"uint256"},{"internalType":"uint256","name":"extraData","type":"uint256"},{"internalType":"address","name":"vault","type":"address"}],"name":"craftFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"craftingPublic","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delegationActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"mechId","type":"uint256"}],"name":"disassemble","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"mechId","type":"uint256"},{"internalType":"address","name":"vault","type":"address"}],"name":"disassembleFor","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"disassemblyFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"disassemblyFeeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"engineIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"extraData","type":"uint256"}],"name":"parseExtraData","outputs":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256[]","name":"colors","type":"uint256[]"},{"internalType":"bool[]","name":"colorsActive","type":"bool[]"},{"internalType":"bool","name":"emissive","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"crafters","type":"address[]"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"setAllowedCrafters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isPublic","type":"bool"}],"name":"setCraftingPublic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isActive","type":"bool"}],"name":"setDelegationActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newDisassemblyFeeRecipient","type":"address"},{"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"setDisassemblyFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]