commit 5c2d7031a4479153fffcd425149dab180db429e8
Author: lash <dev@holbrook.no>
Date: Fri, 16 Dec 2022 13:15:38 +0000
Initial commit
Diffstat:
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/