From 517efcbdd81c8f17e6ab25189549b76d33cd241d Mon Sep 17 00:00:00 2001 From: Akash Paul Date: Mon, 7 Oct 2024 15:07:51 +0530 Subject: [PATCH] fix map key errors and add interaction guide. --- ERC1155/erc1155.coco | 8 +++-- ERC721/erc721.coco | 30 ++++++++++------ ERC721/guide.md | 85 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 14 deletions(-) create mode 100644 ERC721/guide.md diff --git a/ERC1155/erc1155.coco b/ERC1155/erc1155.coco index 785dc27..f62306a 100644 --- a/ERC1155/erc1155.coco +++ b/ERC1155/erc1155.coco @@ -1,3 +1,5 @@ +// Read the specifications for more details https://eips.ethereum.org/EIPS/eip-1155 + coco MT //Multi Tokens class TokenMetadata: @@ -101,12 +103,12 @@ func persistent _transfer(from Address, to Address, id U256, amount U256): if BalanceOf[from][id] < amount: throw "Insufficient balance for transfer" mutate BalanceOf <- MT.BalanceOf: - BalanceOf[from][id] -= amount + generate BalanceOf[from][id] -= amount if !BalanceOf[to]?: disperse BalanceOf[to] <- make(Map[U256]U256) if !BalanceOf[to][id]?: BalanceOf[to][id] = 0 - BalanceOf[to][id] += amount + generate BalanceOf[to][id] += amount endpoint invoke persistent safeTransferFrom(from Address, to Address, id U256, amount U256, data []Bytes): memory isApproved = _isApprovedForAll(account: from, operator: Address(Sender)) @@ -140,7 +142,7 @@ endpoint invoke persistent mint(to Address, tokenId U256, amount U256, tokenURI disperse BalanceOf[to] <- make(Map[U256]U256) if !BalanceOf[to][tokenId]?: BalanceOf[to][tokenId] = 0 - BalanceOf[to][tokenId] += amount + generate BalanceOf[to][tokenId] += amount TotalSupply += amount emit TransferSingle(Address(Sender), Address(0), to, tokenId, amount) diff --git a/ERC721/erc721.coco b/ERC721/erc721.coco index d723e95..1251f6c 100644 --- a/ERC721/erc721.coco +++ b/ERC721/erc721.coco @@ -1,3 +1,5 @@ +// Read the specifications for more details https://eips.ethereum.org/EIPS/eip-721 + coco NFT class TokenMetadata: @@ -59,6 +61,8 @@ func readonly _isApprovedOrOwner(spender Address, tokenId U256) -> (isApproved B endpoint invoke readonly balanceOf(owner Address) -> (Balance U256): observe BalanceOf <- NFT.BalanceOf: + if !BalanceOf[owner]?: + throw "Owner not found in BalanceOf map" return Balance BalanceOf[owner] endpoint invoke readonly ownerOf(tokenId U256) -> (Owner Address): @@ -75,17 +79,21 @@ endpoint invoke persistent approve(to Address, tokenId U256): owner = Tokens[tokenId].owner if to == owner: throw "Approval to current owner" - memory isAll = OperatorApprovals[owner][Address(Sender)] + memory isAll + if !OperatorApprovals[owner][Address(Sender)]?: + throw "Token does not exist" + else: + isAll = OperatorApprovals[owner][Address(Sender)] if Address(Sender) != owner && !isAll: throw "Caller is not token owner or approved operator" mutate TokenApprovals <- NFT.TokenApprovals: - TokenApprovals[tokenId] = to + generate TokenApprovals[tokenId] = to emit Approval(owner, to, tokenId) endpoint invoke readonly getApproved(tokenId U256) -> (Approved Address, Exists Bool): - observe Tokens, TokenApprovals <- NFT.Tokens, NFT.TokenApprovals: - if !Tokens[tokenId]?: + observe TokenApprovals <- NFT.TokenApprovals: + if !TokenApprovals[tokenId]?: return (Approved: Address(0), Exists: false) return (Approved: TokenApprovals[tokenId], Exists: true) @@ -95,7 +103,7 @@ endpoint invoke persistent setApprovalForAll(operator Address, approved Bool): mutate OperatorApprovals <- NFT.OperatorApprovals: if !OperatorApprovals[Address(Sender)]?: disperse OperatorApprovals[Address(Sender)] <- make(Map[Address]Bool) - OperatorApprovals[Address(Sender)][operator] = approved + generate OperatorApprovals[Address(Sender)][operator] = approved emit ApprovalForAll(Address(Sender), operator, approved) endpoint invoke readonly isApprovedForAll(owner Address, operator Address) -> (IsApproved Bool): @@ -120,8 +128,8 @@ endpoint invoke persistent transferFrom(from Address, to Address, tokenId U256): mutate Tokens, BalanceOf, TokenApprovals <- NFT.Tokens, NFT.BalanceOf, NFT.TokenApprovals: TokenApprovals[tokenId] = Address(0) - BalanceOf[from] -= 1 - BalanceOf[to] += 1 + generate BalanceOf[from] -= 1 + generate BalanceOf[to] += 1 Tokens[tokenId].owner = to emit Transfer(from, to, tokenId) @@ -142,8 +150,8 @@ endpoint invoke persistent safeTransferFrom(from Address, to Address, tokenId U2 mutate Tokens, BalanceOf, TokenApprovals <- NFT.Tokens, NFT.BalanceOf, NFT.TokenApprovals: TokenApprovals[tokenId] = Address(0) - BalanceOf[from] -= 1 - BalanceOf[to] += 1 + generate BalanceOf[from] -= 1 + generate BalanceOf[to] += 1 Tokens[tokenId].owner = to emit Transfer(from, to, tokenId) @@ -158,8 +166,8 @@ endpoint invoke persistent mint(to Address, tokenId U256, tokenURI String): mutate Tokens, BalanceOf, TotalSupply <- NFT.Tokens, NFT.BalanceOf, NFT.TotalSupply: disperse Tokens[tokenId] <- TokenMetadata{tokenId: tokenId, owner: to, tokenURI: tokenURI} - BalanceOf[to] += 1 - TotalSupply += 1 + generate BalanceOf[to] += 1 + generate TotalSupply += 1 emit Transfer(Address(0), to, tokenId) diff --git a/ERC721/guide.md b/ERC721/guide.md new file mode 100644 index 0000000..384a52e --- /dev/null +++ b/ERC721/guide.md @@ -0,0 +1,85 @@ +# NFT Contract Interaction Guide + +- Start API server ``logiclab start -d ~/.coco/lab`` +- ```cd ERC721/``` +- ```coco lab start``` Cocolab REPL start +- ```compile NFT``` +- ```get NFT``` lists alll endpoints +- ```register username``` +- ```set default.sender username``` + +## 1. Deploy the contract with a name and symbol +``` +deploy NFT.Init(name: "CryptoCocoNFT", symbol: "COCO") +``` + +## 2. Mint three tokens to different addresses +``` +invoke NFT.mint(to: 0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b, tokenId: 1, tokenURI: "https://example.com/metadata/1") +invoke NFT.mint(to: 0x2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3, tokenId: 2, tokenURI: "https://example.com/metadata/2") +invoke NFT.mint(to: 0x3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4, tokenId: 3, tokenURI: "https://example.com/metadata/3") +``` + +## 3. Check token ownership and balance for an address +``` +invoke NFT.ownerOf(tokenId: 1) +invoke NFT.balanceOf(owner: 0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b) +``` + +## 4. Approve another address to transfer a specific token +``` +invoke NFT.approve(to: 0x4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5, tokenId: 1) +``` + +## 5. Check the approval status for a token +``` +invoke NFT.getApproved(tokenId: 1) +``` + +## 6. Set approval for all tokens to an operator +``` +invoke NFT.setApprovalForAll(operator: 0x5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e, approved: true) +``` + +## 7. Check if an address is approved for all tokens of an owner +``` +invoke NFT.isApprovedForAll(owner: 0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b, operator: 0x5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e) +``` + +## 8. Transfer a token using the regular transfer method +``` +invoke NFT.transferFrom(from: 0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b, to: 0x6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7, tokenId: 1) +``` + +## 9. Transfer a token using the safe transfer method +``` +invoke NFT.safeTransferFrom(from: 0x2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3, to: 0x7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8, tokenId: 2) +``` + +## 10. Get the URI for a token +``` +invoke NFT.tokenURI(tokenId: 1) +``` + +## 11. Get the contract name and symbol +``` +invoke NFT.name() +invoke NFT.symbol() +``` + +## 12. Get the total supply of tokens +``` +invoke NFT.totalSupply() +``` + +## 13. Get a token by its index +``` +invoke NFT.tokenByIndex(index: 0) +``` + +## 14. Get a token of a specific owner by index +``` +invoke NFT.tokenOfOwnerByIndex(owner: 0x3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4, index: 0) +``` + +Note: Replace the example addresses with actual addresses when using this guide. Ensure that you have the necessary permissions to perform these operations on the NFT contract. \ No newline at end of file