### Install ERC5192 with npm Source: https://github.com/attestate/erc5192/blob/main/readme.md Install the ERC5192 library using npm. ```bash npm install erc5192 ``` -------------------------------- ### Configure and Import ERC-5192 Source: https://context7.com/attestate/erc5192/llms.txt Setup remappings in foundry.toml and import the necessary contracts into your Solidity project. ```solidity // foundry.toml - Add remappings if needed // [profile.default] // remappings = ["ERC5192/=lib/ERC5192/src/"] // Import in your contract import {ERC5192} from "ERC5192/ERC5192.sol"; import {IERC5192} from "ERC5192/IERC5192.sol"; ``` -------------------------------- ### Install ERC5192 with Forge Source: https://github.com/attestate/erc5192/blob/main/readme.md Install the ERC5192 library using the Forge package manager. ```bash forge install https://github.com/attestate/ERC5192 ``` -------------------------------- ### Install ERC-5192 Package Source: https://context7.com/attestate/erc5192/llms.txt Commands to install the ERC-5192 library using Foundry or npm. ```bash # Install with Foundry forge install https://github.com/attestate/ERC5192 # Or install with npm npm install erc5192 ``` -------------------------------- ### Create Non-Transferrable Token (NTT) Source: https://context7.com/attestate/erc5192/llms.txt Example implementation of a permanently locked token and its deployment. When locked, all transfer and approval operations will revert. ```solidity // SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.13; import {ERC5192} from "ERC5192/ERC5192.sol"; contract NonTransferrableToken is ERC5192 { bool private isLocked; constructor(string memory _name, string memory _symbol, bool _isLocked) ERC5192(_name, _symbol, _isLocked) { isLocked = _isLocked; } function safeMint(address to, uint256 tokenId) external { _safeMint(to, tokenId); if (isLocked) emit Locked(tokenId); } } // Deployment and usage example contract DeployNTT { function deploy() public { // Create a permanently locked soulbound token string memory name = "Achievement Badge"; string memory symbol = "BADGE"; bool isLocked = true; NonTransferrableToken ntt = new NonTransferrableToken(name, symbol, isLocked); // Mint a token to a user address recipient = msg.sender; uint256 tokenId = 1; ntt.safeMint(recipient, tokenId); // Query lock status - returns true bool status = ntt.locked(tokenId); // true // Attempting transfer will revert with ErrLocked() // ntt.transferFrom(recipient, address(0x123), tokenId); // REVERTS! } } ``` -------------------------------- ### GET locked(tokenId) Source: https://context7.com/attestate/erc5192/llms.txt Queries the locking status of a specific Soulbound Token. Returns true if the token is locked and non-transferrable. ```APIDOC ## GET locked(tokenId) ### Description Returns the locking status of a Soulbound Token. If the token does not exist, the function reverts with an error. ### Method GET ### Parameters #### Path Parameters - **tokenId** (uint256) - Required - The identifier for the SBT. ### Response #### Success Response (200) - **isLocked** (bool) - Returns true if the token is locked, false otherwise. ``` -------------------------------- ### Use the Non-Transferrable Token (NTT) Contract Source: https://github.com/attestate/erc5192/blob/main/readme.md This contract demonstrates how to deploy and use the NTT contract. Minting is successful, but subsequent transfer attempts will revert because the token is locked. ```solidity contract UseNTT { function useNTT() public { string memory name = "Non-transferrable NFT"; string memory symbol = "NTT"; bool isLocked = true; NTT ntt = new NTT(name, symbol, isLocked); address minter = address(this); uint256 tokenId = 0; ntt.safeMint(minter, tokenId); ntt.transferFrom(minter, receiver, tokenId); // revert. token is locked. } } ``` -------------------------------- ### Implement a Non-Transferrable Token (NTT) Source: https://github.com/attestate/erc5192/blob/main/readme.md This contract extends ERC5192 to create a non-transferrable NFT. It requires OpenZeppelin's ERC721 implementation. Ensure the `isLocked` parameter is set to `true` during deployment for non-transferability. ```solidity import {ERC5192} from "ERC5192/ERC5192.sol"; contract NTT is ERC5192 { bool private isLocked; constructor(string memory _name, string memory _symbol, bool _isLocked) ERC5192(_name, _symbol, _isLocked) { isLocked = _isLocked; } function safeMint(address to, uint256 tokenId) external { _safeMint(to, tokenId); if (isLocked) emit Locked(tokenId); } } ``` -------------------------------- ### Implement ERC5192 Abstract Contract Source: https://context7.com/attestate/erc5192/llms.txt An abstract base contract extending ERC721 that provides the locking logic and interface support. Requires implementation of specific minting logic in derived contracts. ```solidity // SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.13; import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import {IERC5192} from "./IERC5192.sol"; abstract contract ERC5192 is ERC721, IERC5192 { bool private isLocked; error ErrLocked(); error ErrNotFound(); constructor(string memory _name, string memory _symbol, bool _isLocked) ERC721(_name, _symbol) { isLocked = _isLocked; } modifier checkLock() { if (isLocked) revert ErrLocked(); _; } function locked(uint256 tokenId) external view returns (bool) { if (!_exists(tokenId)) revert ErrNotFound(); return isLocked; } function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC5192).interfaceId || super.supportsInterface(interfaceId); } } ``` -------------------------------- ### Detect ERC-5192 Interface via ERC-165 Source: https://context7.com/attestate/erc5192/llms.txt Use the ERC-165 supportsInterface method to verify if a contract implements the ERC-5192 standard. ```solidity contract InterfaceDetection { // ERC-5192 interface ID bytes4 constant ERC5192_INTERFACE_ID = 0xb45a3c0e; function checkERC5192Support(address tokenContract) external view returns (bool) { IERC5192 token = IERC5192(tokenContract); // Check if contract supports ERC-5192 // Returns true for any ERC5192-compliant contract return IERC165(tokenContract).supportsInterface(type(IERC5192).interfaceId); } function checkAllInterfaces(address tokenContract) external view returns ( bool isERC721, bool isERC5192 ) { IERC165 token = IERC165(tokenContract); // Check ERC-721 support isERC721 = token.supportsInterface(0x80ac58cd); // ERC721 interface ID // Check ERC-5192 support isERC5192 = token.supportsInterface(type(IERC5192).interfaceId); } } ``` -------------------------------- ### Define IERC5192 Interface Source: https://context7.com/attestate/erc5192/llms.txt The standard interface for ERC-5192, defining events for lock state changes and a function to query the locking status of a token. ```solidity // SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.0; interface IERC5192 { /// @notice Emitted when the locking status is changed to locked. /// @dev If a token is minted and the status is locked, this event should be emitted. /// @param tokenId The identifier for a token. event Locked(uint256 tokenId); /// @notice Emitted when the locking status is changed to unlocked. /// @dev If a token is minted and the status is unlocked, this event should be emitted. /// @param tokenId The identifier for a token. event Unlocked(uint256 tokenId); /// @notice Returns the locking status of an Soulbound Token /// @dev SBTs assigned to zero address are considered invalid, and queries about them do throw. /// @param tokenId The identifier for an SBT. function locked(uint256 tokenId) external view returns (bool); } ``` -------------------------------- ### Manage ERC-5192 Approval Restrictions Source: https://context7.com/attestate/erc5192/llms.txt Approval methods are blocked when a token is locked to prevent delegated transfers. These operations function normally only when the token is unlocked. ```solidity contract ApprovalExample { NonTransferrableToken unlockedToken; NonTransferrableToken lockedToken; function demonstrateApprovals() public { address owner = address(this); address operator = address(0x456); uint256 tokenId = 0; unlockedToken = new NonTransferrableToken("Transferrable", "TRF", false); lockedToken = new NonTransferrableToken("Soulbound", "SBT", true); unlockedToken.safeMint(owner, tokenId); lockedToken.safeMint(owner, tokenId); // UNLOCKED TOKEN - Approvals work // Approve single token unlockedToken.approve(operator, tokenId); assert(unlockedToken.getApproved(tokenId) == operator); // Approve all tokens for operator unlockedToken.setApprovalForAll(operator, true); assert(unlockedToken.isApprovedForAll(owner, operator) == true); // LOCKED TOKEN - Approvals revert // Both of these will revert with ErrLocked(): // lockedToken.approve(operator, tokenId); // lockedToken.setApprovalForAll(operator, true); } } ``` -------------------------------- ### Query ERC-5192 Lock Status Source: https://context7.com/attestate/erc5192/llms.txt Use the locked() function to verify if a token is transferrable. Reverts with ErrNotFound() if the token does not exist. ```solidity // Check if a token is locked contract LockStatusChecker { function checkLockStatus(address tokenContract, uint256 tokenId) external view returns (bool) { IERC5192 token = IERC5192(tokenContract); // Returns true if locked, false if unlocked // Reverts with ErrNotFound() if tokenId doesn't exist bool isLocked = token.locked(tokenId); return isLocked; } } // Example usage in tests contract LockStatusTest { NonTransferrableToken lockedToken; NonTransferrableToken unlockedToken; function setUp() public { lockedToken = new NonTransferrableToken("Locked", "LCK", true); unlockedToken = new NonTransferrableToken("Unlocked", "UNL", false); } function testLockStatus() public { address recipient = address(this); uint256 tokenId = 0; lockedToken.safeMint(recipient, tokenId); unlockedToken.safeMint(recipient, tokenId); // Locked token returns true assert(lockedToken.locked(tokenId) == true); // Unlocked token returns false assert(unlockedToken.locked(tokenId) == false); } function testNonExistentToken() public { // Querying non-existent token reverts // vm.expectRevert(ERC5192.ErrNotFound.selector); // lockedToken.locked(999); } } ``` -------------------------------- ### Handle ERC-5192 Transfer Restrictions Source: https://context7.com/attestate/erc5192/llms.txt Standard ERC-721 transfer methods revert with ErrLocked() when a token is locked. Unlocked tokens behave as standard ERC-721 assets. ```solidity contract TransferExample { NonTransferrableToken unlockedToken; NonTransferrableToken lockedToken; function setUp() public { unlockedToken = new NonTransferrableToken("Transferrable", "TRF", false); lockedToken = new NonTransferrableToken("Soulbound", "SBT", true); } function demonstrateTransfers() public { address owner = address(this); address receiver = address(0x123); uint256 tokenId = 0; // Mint tokens unlockedToken.safeMint(owner, tokenId); lockedToken.safeMint(owner, tokenId); // UNLOCKED TOKEN - All transfers work // Standard transfer unlockedToken.transferFrom(owner, receiver, tokenId); assert(unlockedToken.ownerOf(tokenId) == receiver); // Safe transfer (with receiver contract check) // unlockedToken.safeTransferFrom(owner, receiver, tokenId); // Safe transfer with data // bytes memory data = ""; // unlockedToken.safeTransferFrom(owner, receiver, tokenId, data); // LOCKED TOKEN - All transfers revert // All of these will revert with ErrLocked(): // lockedToken.transferFrom(owner, receiver, tokenId); // lockedToken.safeTransferFrom(owner, receiver, tokenId); // lockedToken.safeTransferFrom(owner, receiver, tokenId, ""); } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.