/// @description This contract is designed to grant exclusive access to Metal Tools products for existing holders of METAL Tools V1 tokens and NFT holders.
/// The Soulbound NFTs minted through this contract are non-transferable, cannot be purchased, and do not possess any financial value.
/// These tokens are purely intended to provide privileged access and benefits to METAL Tools community members.
/// @note This contract does not support transfer, purchase, or any form of financial transactions involving the tokens.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract MetalSoulbound {
/// @notice Thrown when trying to transfer a Soulbound token
error Soulbound();
event Transfer(
address indexed from,
address indexed to,
uint256 indexed id
);
/// @notice The symbol for the token
string public constant symbol = "MetalAccess";
/// @notice The name for the token
string public constant name = "MetalAccess Soulbound";
/// @notice The owner of this contract (set to the deployer)
address public immutable owner = msg.sender;
/// @notice Get the owner of a certain tokenID
mapping(uint256 => address) public ownerOf;
/// @notice Get how many SoulMinter NFTs a certain user owns
mapping(address => uint256) public balanceOf;
/// @dev Counter for the next tokenID, defaults to 1 for better gas on first mint
uint256 internal nextTokenId = 1;
constructor() payable {}
/// @notice This function was disabled to make the token Soulbound. Calling it will revert
function approve(address, uint256) public virtual {
revert Soulbound();
}
/// @notice This function was disabled to make the token Soulbound. Calling it will revert
function isApprovedForAll(address, address) public pure {
revert Soulbound();
}
/// @notice This function was disabled to make the token Soulbound. Calling it will revert
function getApproved(uint256) public pure {
revert Soulbound();
}
/// @notice This function was disabled to make the token Soulbound. Calling it will revert
function setApprovalForAll(address, bool) public virtual {
revert Soulbound();
}
/// @notice This function was disabled to make the token Soulbound. Calling it will revert
function transferFrom(
address,
address,
uint256
) public virtual {
revert Soulbound();
}
/// @notice This function was disabled to make the token Soulbound. Calling it will revert
function safeTransferFrom(
address,
address,
uint256
) public virtual {
revert Soulbound();
}
/// @notice This function was disabled to make the token Soulbound. Calling it will revert
function safeTransferFrom(
address,
address,
uint256,
bytes calldata
) public virtual {
revert Soulbound();
}
function supportsInterface(bytes4 interfaceId) public pure returns (bool) {
return
interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
}
/// @notice Mint a new Soulbound NFT to `to`
/// @param to The recipient of the NFT
function mint(address to) public payable {
unchecked {
balanceOf[to]++;
}
ownerOf[nextTokenId] = to;
emit Transfer(address(0), to, nextTokenId++);
}
}
{
"compilationTarget": {
"MetalSoulbound.sol": "MetalSoulbound"
},
"evmVersion": "cancun",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"payable","type":"constructor"},{"inputs":[],"name":"Soulbound","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","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":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"safeTransferFrom","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":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bool","name":"","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]