craft-nft

A standalone NFT implementation for real-world arts and crafts assets
Log | Files | Refs | README

commit 5c2d7031a4479153fffcd425149dab180db429e8
Author: lash <dev@holbrook.no>
Date:   Fri, 16 Dec 2022 13:15:38 +0000

Initial commit

Diffstat:
A.gitignore | 5+++++
Apython/eth_craft_nft/__init__.py | 1+
Apython/eth_craft_nft/data/CraftNFT.bin | 2++
Apython/eth_craft_nft/data/CraftNFT.json | 1+
Apython/eth_craft_nft/nft.py | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Apython/requirements.txt | 1+
Apython/test_requirements.txt | 2++
Apython/tests/test_basic.py | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asolidity/CraftNFT.sol | 129+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asolidity/Makefile | 9+++++++++
10 files changed, 258 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,5 @@ +__pycache__ +*.pyc +egg-info/* +solidity/*.bin +solidity/*.json diff --git a/python/eth_craft_nft/__init__.py b/python/eth_craft_nft/__init__.py @@ -0,0 +1 @@ +from .nft import CraftNFT diff --git a/python/eth_craft_nft/data/CraftNFT.bin b/python/eth_craft_nft/data/CraftNFT.bin @@ -0,0 +1 @@ +60806040523480156200001157600080fd5b506040516200185e3803806200185e833981810160405281019062000037919062000236565b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550816006908162000088919062000506565b5080600790816200009a919062000506565b505050620005ed565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200010c82620000c1565b810181811067ffffffffffffffff821117156200012e576200012d620000d2565b5b80604052505050565b600062000143620000a3565b905062000151828262000101565b919050565b600067ffffffffffffffff821115620001745762000173620000d2565b5b6200017f82620000c1565b9050602081019050919050565b60005b83811015620001ac5780820151818401526020810190506200018f565b60008484015250505050565b6000620001cf620001c98462000156565b62000137565b905082815260208101848484011115620001ee57620001ed620000bc565b5b620001fb8482856200018c565b509392505050565b600082601f8301126200021b576200021a620000b7565b5b81516200022d848260208601620001b8565b91505092915050565b6000806040838503121562000250576200024f620000ad565b5b600083015167ffffffffffffffff811115620002715762000270620000b2565b5b6200027f8582860162000203565b925050602083015167ffffffffffffffff811115620002a357620002a2620000b2565b5b620002b18582860162000203565b9150509250929050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200030e57607f821691505b602082108103620003245762000323620002c6565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026200038e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200034f565b6200039a86836200034f565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620003e7620003e1620003db84620003b2565b620003bc565b620003b2565b9050919050565b6000819050919050565b6200040383620003c6565b6200041b6200041282620003ee565b8484546200035c565b825550505050565b600090565b6200043262000423565b6200043f818484620003f8565b505050565b5b8181101562000467576200045b60008262000428565b60018101905062000445565b5050565b601f821115620004b65762000480816200032a565b6200048b846200033f565b810160208510156200049b578190505b620004b3620004aa856200033f565b83018262000444565b50505b505050565b600082821c905092915050565b6000620004db60001984600802620004bb565b1980831691505092915050565b6000620004f68383620004c8565b9150826002028217905092915050565b6200051182620002bb565b67ffffffffffffffff8111156200052d576200052c620000d2565b5b620005398254620002f5565b620005468282856200046b565b600060209050601f8311600181146200057e576000841562000569578287015190505b620005758582620004e8565b865550620005e5565b601f1984166200058e866200032a565b60005b82811015620005b85784890151825560018201915060208501945060208101905062000591565b86831015620005d85784890151620005d4601f891682620004c8565b8355505b6001600288020188555050505b505050505050565b61126180620005fd6000396000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c80637dd56411116100715780637dd56411146101c757806395d89b41146101f7578063a22cb46514610215578063bee2c0b514610231578063e985e9c514610261578063f9613ab214610291576100b4565b806301ffc9a7146100b957806306fdde03146100e9578063081812fc146101075780634d03546a146101375780635b1f1c6d1461016757806370a0823114610197575b600080fd5b6100d360048036038101906100ce9190610c29565b6102c1565b6040516100e09190610c71565b60405180910390f35b6100f16103a5565b6040516100fe9190610d1c565b60405180910390f35b610121600480360381019061011c9190610d74565b610433565b60405161012e9190610de2565b60405180910390f35b610151600480360381019061014c9190610e71565b610470565b60405161015e9190610c71565b60405180910390f35b610181600480360381019061017c9190610edd565b6105b6565b60405161018e9190610f53565b60405180910390f35b6101b160048036038101906101ac9190610f6e565b61067b565b6040516101be9190610faa565b60405180910390f35b6101e160048036038101906101dc9190610fc5565b610682565b6040516101ee9190610de2565b60405180910390f35b6101ff6106a2565b60405161020c9190610d1c565b60405180910390f35b61022f600480360381019061022a919061101e565b610730565b005b61024b6004803603810190610246919061105e565b6109d2565b60405161025891906110ca565b60405180910390f35b61027b600480360381019061027691906110e5565b610aad565b6040516102889190610c71565b60405180910390f35b6102ab60048036038101906102a69190610fc5565b610b45565b6040516102b89190610f53565b60405180910390f35b60006380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036102f957600190506103a0565b635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160361032f57600190506103a0565b63780e9d6360e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160361036557600190506103a0565b6301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160361039b57600190506103a0565b600090505b919050565b600680546103b290611154565b80601f01602080910402602001604051908101604052809291908181526020018280546103de90611154565b801561042b5780601f106104005761010080835404028352916020019161042b565b820191906000526020600020905b81548152906001019060200180831161040e57829003601f168201915b505050505081565b60006004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104cb57600080fd5b60006002600085815260200190815260200160002080549050111561054d5760006002600085815260200190815260200160002060008154811061051257610511611185565b5b90600052602060002090600591828204019190066006029054906101000a900465ffffffffffff1665ffffffffffff161161054c57600080fd5b5b600260008481526020019081526020016000208290806001815401808255809150506001900390600052602060002090600591828204019190066006029091909190916101000a81548165ffffffffffff021916908365ffffffffffff16021790555092915050565b600080600062ffffff60001b871690507f800000000000000000000000000000000000000000000000000000000000000060001b8117905060c881901b90508360601b6bffffffffffffffffffffffff1916811790507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000060001b871691508460d01b79ffffffffffffffffffffffffffffffffffffffffffffffffffff1916821791508060036000848152602001908152602001600020819055505050949350505050565b6000919050565b6000600360008381526020019081526020016000205460601c9050919050565b600780546106af90611154565b80601f01602080910402602001604051908101604052809291908181526020018280546106db90611154565b80156107285780601f106106fd57610100808354040283529160200191610728565b820191906000526020600020905b81548152906001019060200180831161070b57829003601f168201915b505050505081565b801561085157600073ffffffffffffffffffffffffffffffffffffffff16600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146107ce57600080fd5b81600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610969565b600073ffffffffffffffffffffffffffffffffffffffff16600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036108e957600080fd5b6000600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516109c69190610c71565b60405180910390a35050565b6000808290505b6002600086815260200190815260200160002080549050811015610a8157836fffffffffffffffffffffffffffffffff16600260008781526020019081526020016000208281548110610a2f57610a2e611185565b5b90600052602060002090600591828204019190066006029054906101000a900465ffffffffffff1665ffffffffffff161115610a6e5780915050610aa6565b8080610a79906111e3565b9150506109d9565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90505b9392505050565b60008173ffffffffffffffffffffffffffffffffffffffff16600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905092915050565b600080600360008481526020019081526020016000205490506000801b7f800000000000000000000000000000000000000000000000000000000000000060001b821611610b9257600080fd5b60c881901c90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000060001b83168117905080915050919050565b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610c0681610bd1565b8114610c1157600080fd5b50565b600081359050610c2381610bfd565b92915050565b600060208284031215610c3f57610c3e610bcc565b5b6000610c4d84828501610c14565b91505092915050565b60008115159050919050565b610c6b81610c56565b82525050565b6000602082019050610c866000830184610c62565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610cc6578082015181840152602081019050610cab565b60008484015250505050565b6000601f19601f8301169050919050565b6000610cee82610c8c565b610cf88185610c97565b9350610d08818560208601610ca8565b610d1181610cd2565b840191505092915050565b60006020820190508181036000830152610d368184610ce3565b905092915050565b6000819050919050565b610d5181610d3e565b8114610d5c57600080fd5b50565b600081359050610d6e81610d48565b92915050565b600060208284031215610d8a57610d89610bcc565b5b6000610d9884828501610d5f565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610dcc82610da1565b9050919050565b610ddc81610dc1565b82525050565b6000602082019050610df76000830184610dd3565b92915050565b6000819050919050565b610e1081610dfd565b8114610e1b57600080fd5b50565b600081359050610e2d81610e07565b92915050565b600065ffffffffffff82169050919050565b610e4e81610e33565b8114610e5957600080fd5b50565b600081359050610e6b81610e45565b92915050565b60008060408385031215610e8857610e87610bcc565b5b6000610e9685828601610e1e565b9250506020610ea785828601610e5c565b9150509250929050565b610eba81610dc1565b8114610ec557600080fd5b50565b600081359050610ed781610eb1565b92915050565b60008060008060808587031215610ef757610ef6610bcc565b5b6000610f0587828801610e1e565b9450506020610f1687828801610d5f565b9350506040610f2787828801610e5c565b9250506060610f3887828801610ec8565b91505092959194509250565b610f4d81610dfd565b82525050565b6000602082019050610f686000830184610f44565b92915050565b600060208284031215610f8457610f83610bcc565b5b6000610f9284828501610ec8565b91505092915050565b610fa481610d3e565b82525050565b6000602082019050610fbf6000830184610f9b565b92915050565b600060208284031215610fdb57610fda610bcc565b5b6000610fe984828501610e1e565b91505092915050565b610ffb81610c56565b811461100657600080fd5b50565b60008135905061101881610ff2565b92915050565b6000806040838503121561103557611034610bcc565b5b600061104385828601610ec8565b925050602061105485828601611009565b9150509250929050565b60008060006060848603121561107757611076610bcc565b5b600061108586828701610e1e565b935050602061109686828701610d5f565b92505060406110a786828701610d5f565b9150509250925092565b6000819050919050565b6110c4816110b1565b82525050565b60006020820190506110df60008301846110bb565b92915050565b600080604083850312156110fc576110fb610bcc565b5b600061110a85828601610ec8565b925050602061111b85828601610ec8565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061116c57607f821691505b60208210810361117f5761117e611125565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006111ee82610d3e565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036112205761121f6111b4565b5b60018201905091905056fea2646970667358221220dc3bc927113728e44891d4d0268b66036150a17745558e7fc1242014e9c6f18464736f6c63430008110033 +\ No newline at end of file diff --git a/python/eth_craft_nft/data/CraftNFT.json b/python/eth_craft_nft/data/CraftNFT.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"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":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"bytes32","name":"content","type":"bytes32"},{"internalType":"uint48","name":"count","type":"uint48"}],"name":"allocate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"content","type":"bytes32"},{"internalType":"uint256","name":"superIndex","type":"uint256"},{"internalType":"uint256","name":"startAt","type":"uint256"}],"name":"batchOf","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_truncatedId","type":"bytes32"}],"name":"getDigest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"content","type":"bytes32"},{"internalType":"uint256","name":"batch","type":"uint256"},{"internalType":"uint48","name":"index","type":"uint48"},{"internalType":"address","name":"recipient","type":"address"}],"name":"mintFromBatchTo","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tokenId","type":"bytes32"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_approved","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"}] diff --git a/python/eth_craft_nft/nft.py b/python/eth_craft_nft/nft.py @@ -0,0 +1,50 @@ +# standard imports +import os + +# external imports +from chainlib.eth.tx import TxFormat +from eth_erc721 import ERC721 +from hexathon import strip_0x + +moddir = os.path.dirname(__file__) +datadir = os.path.join(moddir, 'data') + + +class CraftNFT(ERC721): + + __abi = None + __bytecode = None + + @staticmethod + def abi(): + if CraftNFT.__abi == None: + f = open(os.path.join(datadir, 'CraftNFT.json'), 'r') + CraftNFT.__abi = json.load(f) + f.close() + return CraftNFT.__abi + + + @staticmethod + def bytecode(): + if CraftNFT.__bytecode == None: + f = open(os.path.join(datadir, 'CraftNFT.bin')) + CraftNFT.__bytecode = f.read() + f.close() + return CraftNFT.__bytecode + + + @staticmethod + def gas(code=None): + return 4000000 + + + def constructor(self, sender_address, name, symbol, tx_format=TxFormat.JSONRPC): + code = CraftNFT.bytecode() + enc = ABIContractEncoder() + enc.string(name) + enc.string(symbol) + code += enc.get() + tx = self.template(sender_address, None, use_nonce=True) + tx = self.set_code(tx, code) + return self.finalize(tx, tx_format) + diff --git a/python/requirements.txt b/python/requirements.txt @@ -0,0 +1 @@ +eth-erc721~=0.0.4 diff --git a/python/test_requirements.txt b/python/test_requirements.txt @@ -0,0 +1,2 @@ +eth_tester==0.5.0b3 +py-evm==0.3.0a20 diff --git a/python/tests/test_basic.py b/python/tests/test_basic.py @@ -0,0 +1,58 @@ +# standard imports +import os +import unittest +import json +import logging + +# external imports +from chainlib.eth.unittest.ethtester import EthTesterCase +from chainlib.connection import RPCConnection +from chainlib.eth.nonce import RPCNonceOracle +from chainlib.eth.address import to_checksum_address +from chainlib.eth.tx import ( + receipt, + transaction, + TxFormat, + ) +from chainlib.eth.contract import ( + abi_decode_single, + ABIContractType, + ) +from chainlib.error import JSONRPCException +from chainlib.eth.constant import ZERO_ADDRESS +from hexathon import ( + add_0x, + strip_0x, + ) + + +# local imports +from eth_craft_nft import CraftNFT + +logging.basicConfig(level=logging.DEBUG) +logg = logging.getLogger() + +testdir = os.path.dirname(__file__) + + +class Test(EthTesterCase): + + def setUp(self): + super(Test, self).setUp() + nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc) + c = CraftNFT(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle) + (tx_hash, o) = c.constructor(self.accounts[0], 'DevBadge', 'DEV') + self.conn = RPCConnection.connect(self.chain_spec, 'default') + r = self.conn.do(o) + logg.debug('deployed with hash {}'.format(r)) + + o = receipt(r) + r = self.conn.do(o) + self.address = to_checksum_address(r['contract_address']) + + def test_basic(self): + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/solidity/CraftNFT.sol b/solidity/CraftNFT.sol @@ -0,0 +1,129 @@ +pragma solidity >= 0.8.0; + +contract CraftNFT { + + address owner; + bytes32[] tokens; + mapping(bytes32 => uint48[]) token; + mapping(bytes32 => bytes32) mintedToken; + mapping(uint256 => address) tokenAllowance; // backend for approve + mapping(address => address) tokenOperator; // backend for setApprovalForAll + + // ERC-721 (Metadata - optional) + string public name; + + // ERC-721 (Metadata - optional) + string public symbol; + + + // ERC-721 + event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); + // ERC-721 + event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); + // ERC-721 + event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); + + constructor(string memory _name, string memory _symbol) { + owner = msg.sender; + name = _name; + symbol = _symbol; + } + + function getDigest(bytes32 _truncatedId) public view returns (bytes32) { + bytes32 digest; + + digest = mintedToken[_truncatedId]; + require(digest & 0x8000000000000000000000000000000000000000000000000000000000000000 > 0); + + digest >>= 200; + digest |= _truncatedId & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000; + return digest; + } + + // allocate a batch of tokens + function allocate(bytes32 content, uint48 count) public returns (bool) { + require(msg.sender == owner); + if (token[content].length > 0) { + require(token[content][0] > 0); + } + token[content].push(count); + } + + // ERC-721 + function ownerOf(bytes32 _tokenId) external view returns (address) { + return address(bytes20(mintedToken[_tokenId])); + } + + function batchOf(bytes32 content, uint256 superIndex, uint256 startAt) public view returns (int256) { + for (uint256 i = startAt; i < token[content].length; i++) { + if (token[content][i] > uint128(superIndex)) { + return int256(i); + } + } + return -1; + } + + function mintFromBatchTo(bytes32 content, uint256 batch, uint48 index, address recipient) public returns (bytes32) { + bytes32 left; + bytes32 right; + + right = content & 0x0000000000000000000000000000000000000000000000000000000000ffffff; + right |= 0x8000000000000000000000000000000000000000000000000000000000000000; // "is defined" bit + right <<= 200; + right |= bytes20(recipient); + + left = content & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000; + left |= bytes6(index); + + mintedToken[left] = right; + } + + // ERC-721 + function balanceOf(address _owner) external view returns (uint256) { + return 0; + } + + // ERC-721 + function setApprovalForAll(address _operator, bool _approved) external { + if (_approved) { + require(tokenOperator[msg.sender] == address(0)); // save a few bucks in gas if fail + tokenOperator[msg.sender] = _operator; + } else { + require(tokenOperator[msg.sender] != address(0)); + tokenOperator[msg.sender] = address(0); + } + emit ApprovalForAll(msg.sender, _operator, _approved); + } + + // ERC-721 + function getApproved(uint256 _tokenId) external view returns (address) { + return tokenAllowance[_tokenId]; + } + + // ERC-721 + function isApprovedForAll(address _owner, address _operator) external view returns (bool) { + return tokenOperator[_owner] == _operator; + } + + // ERC-721 + //function ownerOf(uint256 _tokenId) external view returns (address) { + // return tokenOwner[_tokenId]; + //} + + // EIP-165 + function supportsInterface(bytes4 interfaceID) external pure returns (bool) { + if (interfaceID == 0x80ac58cd) { // EIP 721 + return true; + } + if (interfaceID == 0x5b5e139f) { // EIP 721 (Metadata - optional) + return true; + } + if (interfaceID == 0x780e9d63) { // EIP 721 (Enumerable - optional) + return true; + } + if (interfaceID == 0x01ffc9a7) { // EIP 165 + return true; + } + return false; + } +} diff --git a/solidity/Makefile b/solidity/Makefile @@ -0,0 +1,9 @@ +SOLC = /usr/bin/solc + +all: + $(SOLC) --bin CraftNFT.sol | awk 'NR>3' > CraftNFT.bin + truncate -s -1 CraftNFT.bin + $(SOLC) --abi CraftNFT.sol | awk 'NR>3' > CraftNFT.json + +install: all + cp -v CraftNFT*{json,bin} ../python/eth_craft_nft/data/