From 705363154171179904d3683742425a9571e1d696 Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Sat, 16 Apr 2022 21:19:44 -0700 Subject: [PATCH 01/29] Created ERC1155 ownable example/template --- examples/tokens/ERC1155ownable.vy | 347 ++++++++++++++++++++ tests/tokens/test_ERC1155ownable.py | 474 ++++++++++++++++++++++++++++ 2 files changed, 821 insertions(+) create mode 100644 examples/tokens/ERC1155ownable.vy create mode 100644 tests/tokens/test_ERC1155ownable.py diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy new file mode 100644 index 0000000000..b4301a83f2 --- /dev/null +++ b/examples/tokens/ERC1155ownable.vy @@ -0,0 +1,347 @@ +# @version >=0.3.1 + +# @dev Implementation of ERC-1155 non-fungible token standard +# @dev depends on Dynarray and bytes4, which will be available with 0.3.2 release +# @dev ownable, with approval, OPENSEA compatible (name, symbol) +# @author Dr. Pixel (github: @Doc-Pixel) + +############### variables ############### +BATCH_SIZE: constant(uint256) = 128 # maximum items in a batch call. Set to 20, figure out what the practical limits are. +MAX_URI_LENGTH: constant(uint256) = 1024 # initial URI length set to 255. Check internet standards and subtract IDs. Should not be that long, keep eye on IPFS hashes. + +owner: public(address) # the contract owner +paused: public(bool) # pause status True / False +uri: public(String[1024]) # keep an eye on the total length + +# NFT marketplace compatibility +name: public(String[1024]) +symbol: public(String[1024]) + +# mappings +supportsInterfaces: HashMap[bytes4, bool] +balances: HashMap[uint256,HashMap[address, uint256]] # Mapping from token ID to account balances +operatorApprovals: HashMap[address, HashMap[address, bool]] # Mapping from account to operator approvals + +# Interface IDs +ERC165_INTERFACE_ID: constant(bytes4) = 0x01ffc9a7 +ERC1155_INTERFACE_ID: constant(bytes4) = 0xd9b67a26 +ERC1155_INTERFACE_ID_METADATA: constant(bytes4) = 0x0e89341c + +############### events ############### +event Paused: + # @dev Emits a pause event with the address that paused the contract + account: address + +event unPaused: + # @dev Emits an unpause event with the address that paused the contract + account: address + +event OwnershipTransferred: + # @dev Emits smart contract ownership transfer + # @param previousOwner The current, soon to be previous owner of the contract + # @param newOwner The new owner of the contract + previouwOwner: address + newOwner: address + +event TransferSingle: + # @dev Emits on transfer of a single token + # @param operator the address initiating the transfer. owner or authorized operator + # @param fromAddress the address sending the token + # @param to the address receiving the token + # @param id the token ID + # @param value the amount of tokens + operator: indexed(address) + fromAddress: indexed(address) + to: indexed(address) + id: uint256 + value: uint256 + +event TransferBatch: + # @dev Emits on batch transfer of tokens. the ids array correspond with the values array by their position + # @param operator the address initiating the transfer. owner or authorized operator + # @param fromAddress the address sending the token + # @param to the address receiving the token + # @param ids list of token ids + # @param values list of amounts for each token + operator: indexed(address) # indexed + fromAddress: indexed(address) + to: indexed(address) + ids: DynArray[uint256, BATCH_SIZE] + values: DynArray[uint256, BATCH_SIZE] + +event ApprovalForAll: + # @dev This emits when an operator is enabled or disabled for an owner. The operator can manage + # @dev all NFTs of the owner. + # @param account Owner of NFT. + # @param operator Address to which we are setting operator rights. + # @param approved Status of operator rights(true if operator rights are given and false if revoked). + account: indexed(address) + operator: indexed(address) + approved: bool + +############### interfaces ############### + +interface IERC165: + # @dev IERC165 interface definition. + # @param account the account granting the operator approval rights + # @param operator the approved operator + # @param approved the approval status. True of False. + def supportsInterface(_interfaceId: bytes4) -> bool: payable + +interface IERC1155Receiver: + def onERC1155Received(operator: address, fromAddress: address, to: address, id: uint256, _value: uint256, data: bytes32) -> bytes32: payable + def onERC1155BatchReceived(operator: address, fromAddress: address, to: address, _ids: DynArray[uint256, BATCH_SIZE], _amounts: DynArray[uint256, BATCH_SIZE], data: bytes32) -> bytes32: payable + +interface IERC1155MetadataURI: + def uri(id: uint256) -> String[MAX_URI_LENGTH]: payable + +############### functions ############### + +## contract status ## +@external +def pause(): + # @dev Pause the contract, checks if the caller is the owner and if the contract is paused already + # @dev emits a pause event + assert self.owner == msg.sender, "Ownable: caller is not the owner" + assert not self.paused, " the contract is already paused" + self.paused = True + log Paused(msg.sender) + +@external +def unpause(): + # @dev Unpause the contract, checks if the caller is the owner and if the contract is paused already + # @dev emits an unpause event + assert self.owner == msg.sender, "Ownable: caller is not the owner" + assert self.paused, "the contract is not paused" + self.paused = False + log unPaused(msg.sender) + +## ownership ## +@external +def isOwner() -> bool: + # @dev if the calling user it the owner, return true. Otherwise false + return self.owner == msg.sender + +@external +def transferOwnership(newOwner: address): + # @dev Transfer the ownership. Checks for contract pause status, current owner and prevent transferring to + # @dev zero address + # @dev emits an OwnershipTransferred event with the old and new owner addresses + # @param newOwner The address of the new owner. + assert not self.paused, "The contract has been paused" + assert self.owner == msg.sender, "Ownable: caller is not the owner" + assert newOwner != self.owner, "This account already owns the contract" + assert newOwner != ZERO_ADDRESS, "Transfer to ZERO_ADDRESS not allowed. Use renounceOwnership() instead." + oldOwner: address = self.owner + self.owner = newOwner + log OwnershipTransferred(oldOwner, newOwner) + +@external +def renounceOwnership(): + # @dev Transfer the ownership to ZERO_ADDRESS, this will lock the contract + # @dev emits an OwnershipTransferred event with the old and new ZERO_ADDRESS owner addresses + assert not self.paused, "The contract has been paused" + assert self.owner == msg.sender, "Ownable: caller is not the owner" + oldOwner: address = self.owner + self.owner = ZERO_ADDRESS + log OwnershipTransferred(oldOwner, ZERO_ADDRESS) + +## balance ## +@external +def balanceOf(account: address, id: uint256) -> uint256: + # @dev check the balance for a specific ID and address + # @dev will return the balance if the id is owned by the address + # @dev Can also be used to check ownership of an ID + # @param account the address to check the balance for + # @param id the token ID to check the balance + assert account != ZERO_ADDRESS, "Please enter a valid address" + return self.balances[id][account] + +@external +def balanceOfBatch(accounts: DynArray[address, BATCH_SIZE], ids: DynArray[uint256, BATCH_SIZE]) -> DynArray[uint256,BATCH_SIZE]: #uint256[BATCH_SIZE]: + # @dev check the balance for an array of specific IDs and addresses + # @dev will return an array of balances + # @dev Can also be used to check ownership of an ID + # @param accounts a dynamic array of the addresses to check the balance for + # @param ids a dynamic array of the token IDs to check the balance + assert len(accounts) == len(ids), "ERC1155: accounts and ids length mismatch" + batchBalances: DynArray[uint256, BATCH_SIZE] = empty(DynArray[uint256,BATCH_SIZE]) + j: uint256 = 0 + for i in ids: + tempBalance: uint256 = self.balances[i][accounts[j]] + batchBalances.append(tempBalance) + j += 1 + return batchBalances + +## mint ## +@external +def mint(receiver: address, id: uint256, amount:uint256, data:bytes32): + # @dev mint one new token with a certain ID + # @dev this can be a new token or "topping up" the balance of a non-fungible token ID + # @param receiver the account that will receive the minted token + # @param id the ID of the token + # @param amount of tokens for this ID + # @param data the data associated with this mint. Usually stays empty + assert not self.paused, "The contract has been paused" + assert self.owner == msg.sender, "Only the contract owner can mint" + assert receiver != ZERO_ADDRESS, "Can not mint to ZERO ADDRESS" + operator:address = msg.sender + self.balances[id][receiver] += amount + log TransferSingle(operator, ZERO_ADDRESS, receiver, id, amount) + + +@external +def mintBatch(receiver: address, ids: DynArray[uint256, BATCH_SIZE], amounts: DynArray[uint256, BATCH_SIZE], data: bytes32): + # @dev mint a batch of new tokens with the passed IDs + # @dev this can be new tokens or "topping up" the balance of existing non-fungible token IDs in the contract + # @param receiver the account that will receive the minted token + # @param ids array of ids for the tokens + # @param amounts amounts of tokens for each ID in the ids array + # @param data the data associated with this mint. Usually stays empty + assert not self.paused, "The contract has been paused" + assert self.owner == msg.sender, "Only the contract owner can mint" + assert receiver != ZERO_ADDRESS, "Can not mint to ZERO ADDRESS" + assert len(ids) == len(amounts), "ERC1155: ids and amounts length mismatch" + operator: address = msg.sender + + for i in range(BATCH_SIZE): + if i >= len(ids): + break + self.balances[ids[i]][receiver] = amounts[i] + + log TransferBatch(operator, ZERO_ADDRESS, receiver, ids, amounts) + +## burn ## +@external +def burn(id: uint256, amount: uint256): + # @dev burn one or more token with a certain ID + # @dev the amount of tokens will be deducted from the holder's balance + # @param receiver the account that will receive the minted token + # @param id the ID of the token to burn + # @param amount of tokens to burnfor this ID + assert not self.paused, "The contract has been paused" + assert self.balances[id][msg.sender] > 0 , "caller does not own this ID" + operator: address = msg.sender + fromBalance: uint256 = self.balances[id][msg.sender] + assert fromBalance >= amount, "ERC1155: burn amount exceeds balance" + self.balances[id][msg.sender] = fromBalance - amount + + log TransferSingle(operator, msg.sender, ZERO_ADDRESS, id, amount) + +@external +def burnBatch(ids: DynArray[uint256, BATCH_SIZE], amounts: DynArray[uint256, BATCH_SIZE]): + # @dev burn a batch of tokens with the passed IDs + # @dev this can be burning non fungible tokens or reducing the balance of existing non-fungible token IDs in the contract + # @dev inside the loop ownership will be checked for each token. We can not burn tokens we do not own + # @param ids array of ids for the tokens to burn + # @param amounts array of amounts of tokens for each ID in the ids array + assert not self.paused, "The contract has been paused" + assert len(ids) == len(amounts), "ERC1155: ids and amounts length mismatch" + operator: address = msg.sender + + for i in range(BATCH_SIZE): + if i >= len(ids): + break + assert self.balances[ids[i]][msg.sender] > 0 , "Caller does not own this ID or ZERO balance" + id: uint256 = ids[i] + amount: uint256 = amounts[i] + fromBalance: uint256 = self.balances[id][msg.sender] + assert fromBalance >= amount, "ERC1155: burn amount exceeds balance" + self.balances[id][msg.sender] = fromBalance - amount + + log TransferBatch(operator, msg.sender, ZERO_ADDRESS, ids, amounts) + +## approval ## +@external +def setApprovalForAll(owner: address, operator: address, approved: bool): + # @dev set an operator for a certain NFT owner address + # @param account the NFT owner address + # @param operator the operator address + assert owner == msg.sender, "You can only set operators for your own account" + assert not self.paused, "The contract has been paused" + assert owner != operator, "ERC1155: setting approval status for self" + self.operatorApprovals[owner][operator] = approved + log ApprovalForAll(owner, operator, approved) + +@external +def isApprovedForAll(account: address, operator: address) -> bool: + # @dev check wether operator is approved as an operator for the account + # @param account the NFT owner address + # @param operator the operator address + assert self.paused == False, "The contract has been paused" + return self.operatorApprovals[account][operator] + +@external +def safeTransferFrom(sender: address, receiver: address, id: uint256, amount: uint256, bytes: bytes32): + # @dev transfer token from one address to another. + # @param sender the sending account (current owner) + # @param receiver the receiving account + # @param id the token id that will be sent + # @param amount the amount of tokens for the specified id + assert not self.paused, "The contract has been paused" + assert receiver != ZERO_ADDRESS, "ERC1155: transfer to the zero address" + assert receiver != sender, "ERC1155: transfer to self" + assert (sender == msg.sender) or (self.operatorApprovals[sender][msg.sender] == True), "Caller is neither owner nor approved operator for this ID" + assert self.balances[id][sender] > 0 , "caller does not own this ID or ZERO balance" + operator: address = msg.sender + fromBalance: uint256 = self.balances[id][sender] + assert fromBalance >= amount, "ERC1155: insufficient balance for transfer" + self.balances[id][sender] = fromBalance - amount + self.balances[id][receiver] += amount + log TransferSingle(operator, sender, receiver, id, amount) + +@external +def safeBatchTransferFrom(sender: address, receiver: address, ids: DynArray[uint256, BATCH_SIZE], amounts: DynArray[uint256, BATCH_SIZE], _bytes: bytes32): + # @dev transfer tokens from one address to another. + # @param sender the sending account + # @param receiver the receiving account + # @param ids a dynamic array of the token ids that will be sent + # @param amounts a dynamic array of the amounts for the specified list of ids. + assert not self.paused, "The contract has been paused" + assert receiver != ZERO_ADDRESS, "ERC1155: transfer to the zero address" + assert (sender == msg.sender) or (self.operatorApprovals[sender][msg.sender] == True), "Caller is neither owner nor approved operator for this ID" + assert len(ids) == len(amounts), "ERC1155: ids and amounts length mismatch" + assert sender != receiver, "sending to self" + operator: address = msg.sender + for i in range(BATCH_SIZE): + if i >= len(ids): + break + assert self.balances[ids[i]][sender] > 0 , "caller does not own this ID or ZERO balance" + id: uint256 = ids[i] + amount: uint256 = amounts[i] + fromBalance: uint256 = self.balances[id][sender] + assert fromBalance >= amount, "ERC1155: transfer amount exceeds balance" + # self.balances[id][msg.sender] = fromBalance - amount + self.balances[id][sender] = fromBalance - amount + self.balances[id][receiver] += amount + + log TransferBatch(operator, sender, receiver, ids, amounts) + +# misc # +@external +def setURI(uri: String[MAX_URI_LENGTH]): + # @dev set the URI for the contract + # @param uri the new uri for the contract + assert not self.paused, "The contract has been paused" + assert self.uri != uri, "new and current URI are identical" + self.uri = uri + +@external +def supportsInterface(interfaceId: bytes4) -> bool: + return self.supportsInterfaces[interfaceId] + +@external +def __init__(name: String[1024], symbol: String[1024], uri: String[1024]): + # @dev contract initialization on deployment + # @dev will set name and symbol, interfaces, owner and URI + # @param name the smart contract name + # @param symbol the smart contract symbol + # @param uri the new uri for the contract + self.name = name + self.symbol = symbol + self.paused = False + self.supportsInterfaces[ERC165_INTERFACE_ID] = True + self.supportsInterfaces[ERC1155_INTERFACE_ID] = True + self.supportsInterfaces[ERC1155_INTERFACE_ID_METADATA] = True + self.owner = msg.sender + self.uri = uri diff --git a/tests/tokens/test_ERC1155ownable.py b/tests/tokens/test_ERC1155ownable.py new file mode 100644 index 0000000000..3775360e81 --- /dev/null +++ b/tests/tokens/test_ERC1155ownable.py @@ -0,0 +1,474 @@ +import pytest +import brownie +from brownie import ZERO_ADDRESS, accounts + +# ERC1155 ownable, opensea compatible tests +# @author Dr. Pixel (github: @Doc-Pixel) + +# constants - contract deployment +CONTRACT_NAME = 'TEST 1155' +CONTRACT_SYMBOL= 'T1155' +CONTRACT_URI = 'https://mydomain.io/NFTdata/{id}' +NEW_CONTRACT_URI = 'https://mynewdomain.io/NFTdata/{id}' +ERC165_INTERFACE_ID = '0x01ffc9a7' +ERC1155_INTERFACE_ID = '0xd9b67a26' +ERC1155_INTERFACE_ID_METADATA = '0x0e89341c' + +# minting test lists +mintBatch = [1,2,3,4,5,6,7,8,9,10] +mintBatch2 = [11,12,13,14,15,16,17,19,19,20] +minBatchSetOf10 = [1,1,1,1,1,1,1,1,1,1] +mintConflictBatch = [1,2,3] + +##### test fixtures ##### + +@pytest.fixture +def NFT_contract(ERC1155ownable, accounts, scope="module", autouse=True): + yield accounts[0].deploy(ERC1155ownable, CONTRACT_NAME, CONTRACT_SYMBOL, CONTRACT_URI) + +@pytest.fixture(autouse=True) +def isolation(fn_isolation): + pass + +@pytest.fixture +def test_mint(NFT_contract): + NFT_contract.mint(accounts[1], 1, 1, '', {"from": accounts[0]}) + NFT_contract.mint(accounts[1], 2, 1, '', {"from": accounts[0]}) + NFT_contract.mint(accounts[1], 3, 1, '', {"from": accounts[0]}) + + with brownie.reverts(): + # mint with non-owner + NFT_contract.mint(accounts[1], 4, 1, '', {"from": accounts[3]}) + + with brownie.reverts(): + # mint to zero address + NFT_contract.mint(ZERO_ADDRESS, 4, 1, '', {"from": accounts[0]}) + + +@pytest.fixture +def test_mint_batch(NFT_contract): + NFT_contract.mintBatch(accounts[1], mintBatch, minBatchSetOf10, '', {"from": accounts[0]}) + # NFT_contract.mintBatch(accounts[1], mintBatch2, minBatchSetOf10, '', {"from": accounts[0]}) + + with brownie.reverts(): + # mint with non-owner + NFT_contract.mintBatch(accounts[1], mintBatch, minBatchSetOf10, '', {"from": accounts[2]}) + + with brownie.reverts(): + # mint to zero addres + NFT_contract.mintBatch(ZERO_ADDRESS, mintBatch, minBatchSetOf10, '', {"from": accounts[0]}) + + with brownie.reverts(): + # ids dont match accounts + NFT_contract.mintBatch(accounts[1], [1,2,3], [1,1], '', {"from": accounts[0]}) + +##### tests ##### + +def test_initial_state(NFT_contract): + # Check if the constructor of the contract is set up properly + # and the contract is deployed with the desired variables + + # variables set correctly? + assert NFT_contract.name() == CONTRACT_NAME + assert NFT_contract.symbol() == CONTRACT_SYMBOL + assert NFT_contract.uri() == CONTRACT_URI + + # interfaces set up correctly? + tx1 = NFT_contract.supportsInterface(ERC165_INTERFACE_ID) + returnValue1 = tx1.return_value + assert returnValue1 == True + + tx2 = NFT_contract.supportsInterface(ERC1155_INTERFACE_ID) + returnValue2 = tx2.return_value + assert returnValue2 == True + + tx3 = NFT_contract.supportsInterface(ERC1155_INTERFACE_ID_METADATA) + returnValue3 = tx3.return_value + assert returnValue3 == True + + +def test_pause(NFT_contract): + # check the pause status, pause, check, unpause, check, with owner and non-owner accounts + # this test will check all the function that should not work when paused. + assert NFT_contract.paused() == False + + # try and pause as non-owner + with brownie.reverts(): + NFT_contract.pause({"from": accounts[1]}) + + NFT_contract.pause() + assert NFT_contract.paused() == True + + # try pausing a paused contract + with brownie.reverts(): + NFT_contract.pause() + + # try functions that should not work when paused + with brownie.reverts(): + NFT_contract.setURI(NEW_CONTRACT_URI) + + # test burn and burnbatch + with brownie.reverts(): + NFT_contract.burn(1,1,{"from": accounts[1]}) + + with brownie.reverts(): + NFT_contract.burnBatch([1,2],[1,1],{"from": accounts[1]}) + + # check mint and mintbatch + with brownie.reverts(): + NFT_contract.mint(accounts[1], 1, 1, '', {"from": accounts[0]}) + + with brownie.reverts(): + NFT_contract.mintBatch(accounts[1], mintBatch, minBatchSetOf10, '', {"from": accounts[0]}) + + + # check safetransferfrom and safebatchtransferfrom + with brownie.reverts(): + NFT_contract.safeTransferFrom(accounts[1], accounts[2], 1, 1, '', {"from": accounts[1]}) + + with brownie.reverts(): + NFT_contract.safeBatchTransferFrom(accounts[1], accounts[2], [1,2,3], [1,1,1], '', {"from": accounts[1]}) + + # check ownership functions + with brownie.reverts(): + NFT_contract.transferOwnership(accounts[1]) + + with brownie.reverts(): + NFT_contract.renounceOwnership() + + # check approval functions + with brownie.reverts(): + NFT_contract.setApprovalForAll(accounts[0],accounts[5],True) + + with brownie.reverts(): + NFT_contract.isApprovedForAll(accounts[0],accounts[5]) + + # try and unpause as non-owner + with brownie.reverts(): + NFT_contract.unpause({"from": accounts[1]}) + + NFT_contract.unpause() + assert NFT_contract.paused() == False + + # try un pausing an unpaused contract + with brownie.reverts(): + NFT_contract.unpause() + + +def test_URI(NFT_contract, accounts): + # change contract URI and restore. + assert NFT_contract.uri() == CONTRACT_URI + NFT_contract.setURI(NEW_CONTRACT_URI) + assert NFT_contract.uri() == NEW_CONTRACT_URI + assert NFT_contract.uri() != CONTRACT_URI + NFT_contract.setURI(CONTRACT_URI) + assert NFT_contract.uri() != NEW_CONTRACT_URI + assert NFT_contract.uri() == CONTRACT_URI + + with brownie.reverts(): + NFT_contract.setURI(CONTRACT_URI) + +def test_mint_single_balanceOf(NFT_contract, accounts, test_mint): + # Use the test_mint fixture to mint the tokens. + # this test checks the balances of this test + tx1 = NFT_contract.balanceOf(accounts[1],1) + returnValue1 = tx1.return_value + assert returnValue1 == 1 + + tx2 = NFT_contract.balanceOf(accounts[1],2) + returnValue2 = tx2.return_value + assert returnValue2 == 1 + + tx3 = NFT_contract.balanceOf(accounts[1],3) + returnValue3 = tx3.return_value + assert returnValue3 == 1 + + with brownie.reverts(): + tx4 = NFT_contract.balanceOf(ZERO_ADDRESS,3) + returnValue4 = tx4.return_value + assert returnValue4 == 1 + +def test_mint_batch_balanceOf(NFT_contract, accounts, test_mint_batch): + # Use the test_mint_batch fixture to mint the tokens. + # this test checks the balances of this test + tx1 = NFT_contract.balanceOf(accounts[1],1) + returnValue1 = tx1.return_value + assert returnValue1 == 1 + + tx2 = NFT_contract.balanceOf(accounts[1],2) + returnValue2 = tx2.return_value + assert returnValue2 == 1 + + tx3 = NFT_contract.balanceOf(accounts[1],3) + returnValue3 = tx3.return_value + assert returnValue3 == 1 + + +def test_safeTransferFrom_balanceOf_single(NFT_contract, accounts, test_mint): + # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture + + tx1 = NFT_contract.balanceOf(accounts[1],1, {"from": accounts[1]}) + returnValue1 = tx1.return_value + assert returnValue1 == 1 + + with brownie.reverts(): + # try to transfer item from non item owner account + NFT_contract.safeTransferFrom(accounts[1], accounts[2], 1, 1, '', {"from": accounts[2]}) + + with brownie.reverts(): + # try to transfer item to zero address + NFT_contract.safeTransferFrom(accounts[1], ZERO_ADDRESS, 1, 1, '', {"from": accounts[1]}) + + with brownie.reverts(): + # try to transfer item to self + NFT_contract.safeTransferFrom(accounts[1], accounts[1], 1, 1, '', {"from": accounts[1]}) + + with brownie.reverts(): + # try to transfer more items than we own + NFT_contract.safeTransferFrom(accounts[1], accounts[2], 1, 500, '', {"from": accounts[1]}) + + with brownie.reverts(): + # try to transfer nonexisting item + NFT_contract.safeTransferFrom(accounts[1], accounts[2], 500, 1, '', {"from": accounts[1]}) + + NFT_contract.safeTransferFrom(accounts[1], accounts[2], 1, 1, '', {"from": accounts[1]}) + tx2 = NFT_contract.balanceOf(accounts[2],1, {"from": accounts[0]}) + returnValue2 = tx2.return_value + assert returnValue2 == 1 + + with brownie.reverts(): + # try to transfer item again. to trigger zero balance + NFT_contract.safeTransferFrom(accounts[1], accounts[2], 1, 1, '', {"from": accounts[1]}) + + tx3 = NFT_contract.balanceOf(accounts[1],1, {"from": accounts[0]}) + returnValue3 = tx3.return_value + assert returnValue3 == 0 + + +# TODO: mint 20 NFTs [1:20] and check the balance for each +def test_mintBatch_balanceOf(NFT_contract, accounts, test_mint_batch): + # Use the mint three fixture to mint the tokens. + # this test checks the balances of this test + for i in range (1,10): + tx1 = NFT_contract.balanceOf(accounts[1], i, {"from": accounts[1]}) + returnValue1 = tx1.return_value + assert returnValue1 == 1 + + with brownie.reverts(): + tx2 = NFT_contract.balanceOf(ZERO_ADDRESS, i, {"from": accounts[1]}) + +def test_safeBatchTransferFrom_balanceOf_batch(NFT_contract, accounts, test_mint_batch): + # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture + + tx1 = NFT_contract.balanceOf(accounts[1],1, {"from": accounts[1]}) + returnValue1 = tx1.return_value + assert returnValue1 == 1 + + with brownie.reverts(): + # try to transfer item from non item owner account + NFT_contract.safeBatchTransferFrom(accounts[1], accounts[2], [1,2,3], [1,1,1], '', {"from": accounts[2]}) + + with brownie.reverts(): + # try to transfer item to zero address + NFT_contract.safeBatchTransferFrom(accounts[1], ZERO_ADDRESS, [1,2,3], [1,1,1], '', {"from": accounts[1]}) + + with brownie.reverts(): + # try to transfer item to self + NFT_contract.safeBatchTransferFrom(accounts[1], accounts[1], [1,2,3], [1,1,1], '', {"from": accounts[1]}) + + with brownie.reverts(): + # try to transfer more items than we own + NFT_contract.safeBatchTransferFrom(accounts[1], accounts[2], [1,2,3], [1,125,1], '', {"from": accounts[1]}) + + with brownie.reverts(): + # mismatched item and amounts + NFT_contract.safeBatchTransferFrom(accounts[1], accounts[2], [1,2,3], [1,1], '', {"from": accounts[1]}) + + + with brownie.reverts(): + # try to transfer nonexisting item + NFT_contract.safeBatchTransferFrom(accounts[1], accounts[2], [1,2,500], [1,1,1], '', {"from": accounts[1]}) + + NFT_contract.safeBatchTransferFrom(accounts[1], accounts[2], [1,2,3], [1,1,1], '', {"from": accounts[1]}) + + with brownie.reverts(): + # try to transfer again, our balances are zero now, should fail + NFT_contract.safeBatchTransferFrom(accounts[1], accounts[2], [1,2,3], [1,1,1], '', {"from": accounts[1]}) + + + with brownie.reverts(): + tx2 = NFT_contract.balanceOfBatch([accounts[2],accounts[2],accounts[2]],[1,2], {"from": accounts[0]}) + returnValue2 = tx2.return_value + assert returnValue2 == [1,1,1] + + tx2 = NFT_contract.balanceOfBatch([accounts[2],accounts[2],accounts[2]],[1,2,3], {"from": accounts[0]}) + returnValue2 = tx2.return_value + assert returnValue2 == [1,1,1] + + tx3 = NFT_contract.balanceOf(accounts[1],1, {"from": accounts[0]}) + returnValue3 = tx3.return_value + assert returnValue3 == 0 + + +def test_mint_one_burn_one(NFT_contract, accounts, test_mint): + # check the balance + tx1 = NFT_contract.balanceOf(accounts[1],1, {"from": accounts[1]}) + returnValue1 = tx1.return_value + assert returnValue1 == 1 + + with brownie.reverts(): + # try and burn an item we don't control + NFT_contract.burn(1,1,{"from": accounts[3]}) + + with brownie.reverts(): + # burn an item that contains something we don't own + NFT_contract.burn(595,1,{"from": accounts[1]}) + + with brownie.reverts(): + # burn ah item passing a higher amount than we own + NFT_contract.burn(1,500,{"from": accounts[1]}) + + NFT_contract.burn(1,1,{"from": accounts[1]}) + + tx1 = NFT_contract.balanceOf(accounts[1],1, {"from": accounts[1]}) + returnValue1 = tx1.return_value + assert returnValue1 == 0 + + +def test_mint_batch_burn_batch(NFT_contract, accounts, test_mint_batch): + # check the balance + tx1 = NFT_contract.balanceOfBatch([accounts[1],accounts[1],accounts[1]],[1,2,3], {"from": accounts[1]}) + returnValue1 = tx1.return_value + assert returnValue1 == [1,1,1] + + with brownie.reverts(): + # try and burn a batch we don't control + NFT_contract.burnBatch([1,2],[1,1],{"from": accounts[3]}) + + with brownie.reverts(): + # ids and amounts array length not matching + NFT_contract.burnBatch([1,2,3],[1,1],{"from": accounts[1]}) + + with brownie.reverts(): + # burn a batch that contains something we don't own + NFT_contract.burnBatch([2,3,595],[1,1,1],{"from": accounts[1]}) + + with brownie.reverts(): + # burn a batch passing a higher amount than we own + NFT_contract.burnBatch([1,2,3],[1,500,1],{"from": accounts[1]}) + + # burn existing + NFT_contract.burnBatch([1,2],[1,1],{"from": accounts[1]}) + + tx1 = NFT_contract.balanceOfBatch([accounts[1],accounts[1],accounts[1]],[1,2,3], {"from": accounts[1]}) + returnValue1 = tx1.return_value + assert returnValue1 != [1,1,1] + assert returnValue1 == [0,0,1] + + # burn again, should revert + with brownie.reverts(): + NFT_contract.burnBatch([1,2],[1,1],{"from": accounts[1]}) + + tx1 = NFT_contract.balanceOfBatch([accounts[1],accounts[1],accounts[1]],[1,2,3], {"from": accounts[1]}) + returnValue1 = tx1.return_value + assert returnValue1 != [1,1,1] + assert returnValue1 == [0,0,1] + + +def test_approval_functions(NFT_contract, accounts, test_mint_batch): + + # self-approval by the owner + with brownie.reverts(): + NFT_contract.setApprovalForAll(accounts[5],accounts[5],True, {"from": accounts[5]}) + + # let's approve and operator for somebody else's account + with brownie.reverts(): + NFT_contract.setApprovalForAll(accounts[0],accounts[5],True, {"from": accounts[3]}) + + # set approval correctly + NFT_contract.setApprovalForAll(accounts[0],accounts[5],True) + + # check approval + NFT_contract.isApprovedForAll(accounts[0],accounts[5]) + + # remove approval + NFT_contract.setApprovalForAll(accounts[0],accounts[5],False) + + +def test_max_batch_size_violation(NFT_contract, accounts): + TOTAL_BAD_BATCH = 200 + ids = [] + amounts = [] + for i in range(1,TOTAL_BAD_BATCH): + ids.append(i) + amounts.append(1) + with brownie.reverts(): + NFT_contract.mintBatch(accounts[1], ids, amounts, '', {"from": accounts[0]}) + + + +# Transferring back and forth + + +def test_ownership_functions(NFT_contract): + # change owner from account 0 to account 1 and back + # check all changes by calling isOwner and owner functions + tx1 = NFT_contract.isOwner() + returnValue1 = tx1.return_value + assert returnValue1 == True + assert NFT_contract.owner() == accounts[0] + + tx2 = NFT_contract.isOwner({'from': accounts[1]}) + returnValue2 = tx2.return_value + assert returnValue2 == False + + with brownie.reverts(): + # try to transfer ownership from non-owner account + NFT_contract.transferOwnership(accounts[1], {"from": accounts[2]}) + + with brownie.reverts(): + # try to transfer ownership to current owner + NFT_contract.transferOwnership(accounts[0]) + + with brownie.reverts(): + # try to transfer ownership to current owner + NFT_contract.transferOwnership(ZERO_ADDRESS) + + NFT_contract.transferOwnership(accounts[1]) + + tx1 = NFT_contract.isOwner() + returnValue1 = tx1.return_value + assert returnValue1 == False + + tx2 = NFT_contract.isOwner({'from': accounts[1]}) + returnValue2 = tx2.return_value + assert returnValue2 == True + assert NFT_contract.owner() == accounts[1] + + NFT_contract.transferOwnership(accounts[0],{'from': accounts[1]}) + + tx1 = NFT_contract.isOwner() + returnValue1 = tx1.return_value + assert returnValue1 == True + assert NFT_contract.owner() == accounts[0] + + tx2 = NFT_contract.isOwner({'from': accounts[1]}) + returnValue2 = tx2.return_value + assert returnValue2 == False + +def test_renounce_ownership(NFT_contract): + tx1 = NFT_contract.isOwner() + returnValue1 = tx1.return_value + assert returnValue1 == True + assert NFT_contract.owner() == accounts[0] + + with brownie.reverts(): + # try to transfer ownership from non-owner account + NFT_contract.renounceOwnership({"from": accounts[2]}) + + NFT_contract.renounceOwnership() + + tx1 = NFT_contract.isOwner() + returnValue1 = tx1.return_value + assert returnValue1 == False + assert NFT_contract.owner() == ZERO_ADDRESS \ No newline at end of file From f73abfe858d7b11aa4da6f987eff5a9d58041e7c Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Sat, 16 Apr 2022 23:03:16 -0700 Subject: [PATCH 02/29] Applied most of proposed changes --- examples/tokens/ERC1155ownable.vy | 64 +++++++++++++++++++------------ 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index b4301a83f2..bc120e3da5 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -6,12 +6,20 @@ # @author Dr. Pixel (github: @Doc-Pixel) ############### variables ############### -BATCH_SIZE: constant(uint256) = 128 # maximum items in a batch call. Set to 20, figure out what the practical limits are. -MAX_URI_LENGTH: constant(uint256) = 1024 # initial URI length set to 255. Check internet standards and subtract IDs. Should not be that long, keep eye on IPFS hashes. +# maximum items in a batch call. Set to 20, figure out what the practical limits are. +BATCH_SIZE: constant(uint256) = 128 -owner: public(address) # the contract owner -paused: public(bool) # pause status True / False -uri: public(String[1024]) # keep an eye on the total length +# initial URI length set to 255. Check internet standards and subtract IDs. Should not be that long, keep eye on IPFS hashes. +MAX_URI_LENGTH: constant(uint256) = 1024 + +# the contract owner +owner: public(address) + +# pause status True / False +paused: public(bool) + +# the contracts URI to find the metadata +uri: public(String[MAX_URI_LENGTH]) # NFT marketplace compatibility name: public(String[1024]) @@ -19,8 +27,12 @@ symbol: public(String[1024]) # mappings supportsInterfaces: HashMap[bytes4, bool] -balances: HashMap[uint256,HashMap[address, uint256]] # Mapping from token ID to account balances -operatorApprovals: HashMap[address, HashMap[address, bool]] # Mapping from account to operator approvals + +# Mapping from token ID to account balances +balances: HashMap[uint256,HashMap[address, uint256]] + +# Mapping from account to operator approvals +operatorApprovals: HashMap[address, HashMap[address, bool]] # Interface IDs ERC165_INTERFACE_ID: constant(bytes4) = 0x01ffc9a7 @@ -97,6 +109,22 @@ interface IERC1155MetadataURI: ############### functions ############### +@external +def __init__(name: String[1024], symbol: String[1024], uri: String[1024]): + # @dev contract initialization on deployment + # @dev will set name and symbol, interfaces, owner and URI + # @param name the smart contract name + # @param symbol the smart contract symbol + # @param uri the new uri for the contract + self.name = name + self.symbol = symbol + self.paused = False + self.supportsInterfaces[ERC165_INTERFACE_ID] = True + self.supportsInterfaces[ERC1155_INTERFACE_ID] = True + self.supportsInterfaces[ERC1155_INTERFACE_ID_METADATA] = True + self.owner = msg.sender + self.uri = uri + ## contract status ## @external def pause(): @@ -328,20 +356,8 @@ def setURI(uri: String[MAX_URI_LENGTH]): @external def supportsInterface(interfaceId: bytes4) -> bool: - return self.supportsInterfaces[interfaceId] - -@external -def __init__(name: String[1024], symbol: String[1024], uri: String[1024]): - # @dev contract initialization on deployment - # @dev will set name and symbol, interfaces, owner and URI - # @param name the smart contract name - # @param symbol the smart contract symbol - # @param uri the new uri for the contract - self.name = name - self.symbol = symbol - self.paused = False - self.supportsInterfaces[ERC165_INTERFACE_ID] = True - self.supportsInterfaces[ERC1155_INTERFACE_ID] = True - self.supportsInterfaces[ERC1155_INTERFACE_ID_METADATA] = True - self.owner = msg.sender - self.uri = uri + return interfaceId in [ + ERC165_INTERFACE_ID, + ERC1155_INTERFACE_ID, + ERC1155_INTERFACE_ID_METADATA, + ] From 9d6cb9c852ddcd9813fadbb258bd35c2225861c1 Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Sun, 17 Apr 2022 07:49:20 -0700 Subject: [PATCH 03/29] Applied more of the feedback. --- examples/tokens/ERC1155ownable.vy | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index bc120e3da5..2f3f7cd88c 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -1,15 +1,14 @@ -# @version >=0.3.1 +# @version >=0.3.2 # @dev Implementation of ERC-1155 non-fungible token standard -# @dev depends on Dynarray and bytes4, which will be available with 0.3.2 release # @dev ownable, with approval, OPENSEA compatible (name, symbol) # @author Dr. Pixel (github: @Doc-Pixel) ############### variables ############### -# maximum items in a batch call. Set to 20, figure out what the practical limits are. +# maximum items in a batch call. Set to 128, to be determined what the practical limits are. BATCH_SIZE: constant(uint256) = 128 -# initial URI length set to 255. Check internet standards and subtract IDs. Should not be that long, keep eye on IPFS hashes. +# URI length set to 1024. MAX_URI_LENGTH: constant(uint256) = 1024 # the contract owner @@ -25,8 +24,13 @@ uri: public(String[MAX_URI_LENGTH]) name: public(String[1024]) symbol: public(String[1024]) +# Interface IDs +ERC165_INTERFACE_ID: constant(bytes4) = 0x01ffc9a7 +ERC1155_INTERFACE_ID: constant(bytes4) = 0xd9b67a26 +ERC1155_INTERFACE_ID_METADATA: constant(bytes4) = 0x0e89341c + # mappings -supportsInterfaces: HashMap[bytes4, bool] +supportsInterfaces: constant(bytes4[3]) = [ERC165_INTERFACE_ID, ERC1155_INTERFACE_ID, ERC1155_INTERFACE_ID_METADATA] # Mapping from token ID to account balances balances: HashMap[uint256,HashMap[address, uint256]] @@ -34,10 +38,7 @@ balances: HashMap[uint256,HashMap[address, uint256]] # Mapping from account to operator approvals operatorApprovals: HashMap[address, HashMap[address, bool]] -# Interface IDs -ERC165_INTERFACE_ID: constant(bytes4) = 0x01ffc9a7 -ERC1155_INTERFACE_ID: constant(bytes4) = 0xd9b67a26 -ERC1155_INTERFACE_ID_METADATA: constant(bytes4) = 0x0e89341c + ############### events ############### event Paused: @@ -119,9 +120,6 @@ def __init__(name: String[1024], symbol: String[1024], uri: String[1024]): self.name = name self.symbol = symbol self.paused = False - self.supportsInterfaces[ERC165_INTERFACE_ID] = True - self.supportsInterfaces[ERC1155_INTERFACE_ID] = True - self.supportsInterfaces[ERC1155_INTERFACE_ID_METADATA] = True self.owner = msg.sender self.uri = uri From c4636d1e76a7fbbf17f9b29e49708de900012e99 Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Sun, 17 Apr 2022 07:59:01 -0700 Subject: [PATCH 04/29] ERC165 fix --- examples/tokens/ERC1155ownable.vy | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index 2f3f7cd88c..bd447c7cdd 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -4,6 +4,9 @@ # @dev ownable, with approval, OPENSEA compatible (name, symbol) # @author Dr. Pixel (github: @Doc-Pixel) +############### imports ############### +from vyper.interfaces import ERC165 + ############### variables ############### # maximum items in a batch call. Set to 128, to be determined what the practical limits are. BATCH_SIZE: constant(uint256) = 128 @@ -93,13 +96,7 @@ event ApprovalForAll: approved: bool ############### interfaces ############### - -interface IERC165: - # @dev IERC165 interface definition. - # @param account the account granting the operator approval rights - # @param operator the approved operator - # @param approved the approval status. True of False. - def supportsInterface(_interfaceId: bytes4) -> bool: payable +implements: ERC165 interface IERC1155Receiver: def onERC1155Received(operator: address, fromAddress: address, to: address, id: uint256, _value: uint256, data: bytes32) -> bytes32: payable From f45f150a8c97084d3d595e1e1159de5ca7c6b9a6 Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Mon, 18 Apr 2022 13:01:30 -0700 Subject: [PATCH 05/29] Applied @view/@pure, updated test to accomodate --- examples/tokens/ERC1155ownable.vy | 4 + tests/tokens/test_ERC1155ownable.py | 131 +++++++++------------------- 2 files changed, 46 insertions(+), 89 deletions(-) diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index bd447c7cdd..6620797476 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -170,6 +170,7 @@ def renounceOwnership(): log OwnershipTransferred(oldOwner, ZERO_ADDRESS) ## balance ## +@view @external def balanceOf(account: address, id: uint256) -> uint256: # @dev check the balance for a specific ID and address @@ -181,6 +182,7 @@ def balanceOf(account: address, id: uint256) -> uint256: return self.balances[id][account] @external +@view def balanceOfBatch(accounts: DynArray[address, BATCH_SIZE], ids: DynArray[uint256, BATCH_SIZE]) -> DynArray[uint256,BATCH_SIZE]: #uint256[BATCH_SIZE]: # @dev check the balance for an array of specific IDs and addresses # @dev will return an array of balances @@ -287,6 +289,7 @@ def setApprovalForAll(owner: address, operator: address, approved: bool): log ApprovalForAll(owner, operator, approved) @external +@view def isApprovedForAll(account: address, operator: address) -> bool: # @dev check wether operator is approved as an operator for the account # @param account the NFT owner address @@ -349,6 +352,7 @@ def setURI(uri: String[MAX_URI_LENGTH]): assert self.uri != uri, "new and current URI are identical" self.uri = uri +@pure @external def supportsInterface(interfaceId: bytes4) -> bool: return interfaceId in [ diff --git a/tests/tokens/test_ERC1155ownable.py b/tests/tokens/test_ERC1155ownable.py index 3775360e81..0a8b955e37 100644 --- a/tests/tokens/test_ERC1155ownable.py +++ b/tests/tokens/test_ERC1155ownable.py @@ -1,6 +1,9 @@ + +# brownie test import pytest import brownie from brownie import ZERO_ADDRESS, accounts +from web3.exceptions import ValidationError # ERC1155 ownable, opensea compatible tests # @author Dr. Pixel (github: @Doc-Pixel) @@ -21,7 +24,6 @@ mintConflictBatch = [1,2,3] ##### test fixtures ##### - @pytest.fixture def NFT_contract(ERC1155ownable, accounts, scope="module", autouse=True): yield accounts[0].deploy(ERC1155ownable, CONTRACT_NAME, CONTRACT_SYMBOL, CONTRACT_URI) @@ -39,7 +41,7 @@ def test_mint(NFT_contract): with brownie.reverts(): # mint with non-owner NFT_contract.mint(accounts[1], 4, 1, '', {"from": accounts[3]}) - + # assert_tx_failed(NFT_contract.mint(accounts[1], 4, 1, '', {"from": accounts[3]})) with brownie.reverts(): # mint to zero address NFT_contract.mint(ZERO_ADDRESS, 4, 1, '', {"from": accounts[0]}) @@ -48,7 +50,6 @@ def test_mint(NFT_contract): @pytest.fixture def test_mint_batch(NFT_contract): NFT_contract.mintBatch(accounts[1], mintBatch, minBatchSetOf10, '', {"from": accounts[0]}) - # NFT_contract.mintBatch(accounts[1], mintBatch2, minBatchSetOf10, '', {"from": accounts[0]}) with brownie.reverts(): # mint with non-owner @@ -74,18 +75,15 @@ def test_initial_state(NFT_contract): assert NFT_contract.uri() == CONTRACT_URI # interfaces set up correctly? - tx1 = NFT_contract.supportsInterface(ERC165_INTERFACE_ID) - returnValue1 = tx1.return_value - assert returnValue1 == True + assert NFT_contract.supportsInterface(ERC165_INTERFACE_ID) + # tx1 = NFT_contract.supportsInterface(ERC165_INTERFACE_ID) + # returnValue1 = tx1.return_value + # assert returnValue1 == True + + assert NFT_contract.supportsInterface(ERC1155_INTERFACE_ID) + + assert NFT_contract.supportsInterface(ERC1155_INTERFACE_ID_METADATA) - tx2 = NFT_contract.supportsInterface(ERC1155_INTERFACE_ID) - returnValue2 = tx2.return_value - assert returnValue2 == True - - tx3 = NFT_contract.supportsInterface(ERC1155_INTERFACE_ID_METADATA) - returnValue3 = tx3.return_value - assert returnValue3 == True - def test_pause(NFT_contract): # check the pause status, pause, check, unpause, check, with owner and non-owner accounts @@ -171,46 +169,26 @@ def test_URI(NFT_contract, accounts): def test_mint_single_balanceOf(NFT_contract, accounts, test_mint): # Use the test_mint fixture to mint the tokens. # this test checks the balances of this test - tx1 = NFT_contract.balanceOf(accounts[1],1) - returnValue1 = tx1.return_value - assert returnValue1 == 1 + assert NFT_contract.balanceOf(accounts[1],1) == 1 + assert NFT_contract.balanceOf(accounts[1],2) == 1 + assert NFT_contract.balanceOf(accounts[1],3) == 1 - tx2 = NFT_contract.balanceOf(accounts[1],2) - returnValue2 = tx2.return_value - assert returnValue2 == 1 - - tx3 = NFT_contract.balanceOf(accounts[1],3) - returnValue3 = tx3.return_value - assert returnValue3 == 1 - + # assert_tx_failed with brownie.reverts(): - tx4 = NFT_contract.balanceOf(ZERO_ADDRESS,3) - returnValue4 = tx4.return_value - assert returnValue4 == 1 + assert NFT_contract.balanceOf(ZERO_ADDRESS,3) == 1 def test_mint_batch_balanceOf(NFT_contract, accounts, test_mint_batch): # Use the test_mint_batch fixture to mint the tokens. # this test checks the balances of this test - tx1 = NFT_contract.balanceOf(accounts[1],1) - returnValue1 = tx1.return_value - assert returnValue1 == 1 - - tx2 = NFT_contract.balanceOf(accounts[1],2) - returnValue2 = tx2.return_value - assert returnValue2 == 1 - - tx3 = NFT_contract.balanceOf(accounts[1],3) - returnValue3 = tx3.return_value - assert returnValue3 == 1 - + assert NFT_contract.balanceOf(accounts[1],1) == 1 + assert NFT_contract.balanceOf(accounts[1],2) == 1 + assert NFT_contract.balanceOf(accounts[1],3) == 1 def test_safeTransferFrom_balanceOf_single(NFT_contract, accounts, test_mint): # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture - tx1 = NFT_contract.balanceOf(accounts[1],1, {"from": accounts[1]}) - returnValue1 = tx1.return_value - assert returnValue1 == 1 - + assert NFT_contract.balanceOf(accounts[1],1, {"from": accounts[1]}) == 1 + with brownie.reverts(): # try to transfer item from non item owner account NFT_contract.safeTransferFrom(accounts[1], accounts[2], 1, 1, '', {"from": accounts[2]}) @@ -232,37 +210,31 @@ def test_safeTransferFrom_balanceOf_single(NFT_contract, accounts, test_mint): NFT_contract.safeTransferFrom(accounts[1], accounts[2], 500, 1, '', {"from": accounts[1]}) NFT_contract.safeTransferFrom(accounts[1], accounts[2], 1, 1, '', {"from": accounts[1]}) - tx2 = NFT_contract.balanceOf(accounts[2],1, {"from": accounts[0]}) - returnValue2 = tx2.return_value - assert returnValue2 == 1 - + + assert NFT_contract.balanceOf(accounts[2],1, {"from": accounts[0]}) == 1 + with brownie.reverts(): # try to transfer item again. to trigger zero balance NFT_contract.safeTransferFrom(accounts[1], accounts[2], 1, 1, '', {"from": accounts[1]}) - tx3 = NFT_contract.balanceOf(accounts[1],1, {"from": accounts[0]}) - returnValue3 = tx3.return_value - assert returnValue3 == 0 - + assert NFT_contract.balanceOf(accounts[1],1, {"from": accounts[0]}) == 0 + # TODO: mint 20 NFTs [1:20] and check the balance for each def test_mintBatch_balanceOf(NFT_contract, accounts, test_mint_batch): # Use the mint three fixture to mint the tokens. # this test checks the balances of this test for i in range (1,10): - tx1 = NFT_contract.balanceOf(accounts[1], i, {"from": accounts[1]}) - returnValue1 = tx1.return_value - assert returnValue1 == 1 - + assert NFT_contract.balanceOf(accounts[1], i, {"from": accounts[1]}) == 1 + with brownie.reverts(): - tx2 = NFT_contract.balanceOf(ZERO_ADDRESS, i, {"from": accounts[1]}) + assert NFT_contract.balanceOf(ZERO_ADDRESS, i, {"from": accounts[1]}) == 1 def test_safeBatchTransferFrom_balanceOf_batch(NFT_contract, accounts, test_mint_batch): # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture - tx1 = NFT_contract.balanceOf(accounts[1],1, {"from": accounts[1]}) - returnValue1 = tx1.return_value - assert returnValue1 == 1 + NFT_contract.balanceOf(accounts[1],1, {"from": accounts[1]}) == 1 + with brownie.reverts(): # try to transfer item from non item owner account @@ -297,24 +269,14 @@ def test_safeBatchTransferFrom_balanceOf_batch(NFT_contract, accounts, test_mint with brownie.reverts(): - tx2 = NFT_contract.balanceOfBatch([accounts[2],accounts[2],accounts[2]],[1,2], {"from": accounts[0]}) - returnValue2 = tx2.return_value - assert returnValue2 == [1,1,1] - - tx2 = NFT_contract.balanceOfBatch([accounts[2],accounts[2],accounts[2]],[1,2,3], {"from": accounts[0]}) - returnValue2 = tx2.return_value - assert returnValue2 == [1,1,1] - - tx3 = NFT_contract.balanceOf(accounts[1],1, {"from": accounts[0]}) - returnValue3 = tx3.return_value - assert returnValue3 == 0 - + assert NFT_contract.balanceOfBatch([accounts[2],accounts[2],accounts[2]],[1,2], {"from": accounts[0]}) == [1,1,1] + + assert NFT_contract.balanceOfBatch([accounts[2],accounts[2],accounts[2]],[1,2,3], {"from": accounts[0]}) == [1,1,1] + assert NFT_contract.balanceOf(accounts[1],1, {"from": accounts[0]}) == 0 def test_mint_one_burn_one(NFT_contract, accounts, test_mint): # check the balance - tx1 = NFT_contract.balanceOf(accounts[1],1, {"from": accounts[1]}) - returnValue1 = tx1.return_value - assert returnValue1 == 1 + assert NFT_contract.balanceOf(accounts[1],1, {"from": accounts[1]}) == 1 with brownie.reverts(): # try and burn an item we don't control @@ -330,16 +292,12 @@ def test_mint_one_burn_one(NFT_contract, accounts, test_mint): NFT_contract.burn(1,1,{"from": accounts[1]}) - tx1 = NFT_contract.balanceOf(accounts[1],1, {"from": accounts[1]}) - returnValue1 = tx1.return_value - assert returnValue1 == 0 + assert NFT_contract.balanceOf(accounts[1],1, {"from": accounts[1]}) == 0 def test_mint_batch_burn_batch(NFT_contract, accounts, test_mint_batch): # check the balance - tx1 = NFT_contract.balanceOfBatch([accounts[1],accounts[1],accounts[1]],[1,2,3], {"from": accounts[1]}) - returnValue1 = tx1.return_value - assert returnValue1 == [1,1,1] + assert NFT_contract.balanceOfBatch([accounts[1],accounts[1],accounts[1]],[1,2,3], {"from": accounts[1]}) == [1,1,1] with brownie.reverts(): # try and burn a batch we don't control @@ -360,19 +318,14 @@ def test_mint_batch_burn_batch(NFT_contract, accounts, test_mint_batch): # burn existing NFT_contract.burnBatch([1,2],[1,1],{"from": accounts[1]}) - tx1 = NFT_contract.balanceOfBatch([accounts[1],accounts[1],accounts[1]],[1,2,3], {"from": accounts[1]}) - returnValue1 = tx1.return_value - assert returnValue1 != [1,1,1] - assert returnValue1 == [0,0,1] + assert NFT_contract.balanceOfBatch([accounts[1],accounts[1],accounts[1]],[1,2,3], {"from": accounts[1]}) == [0,0,1] + # burn again, should revert with brownie.reverts(): NFT_contract.burnBatch([1,2],[1,1],{"from": accounts[1]}) - tx1 = NFT_contract.balanceOfBatch([accounts[1],accounts[1],accounts[1]],[1,2,3], {"from": accounts[1]}) - returnValue1 = tx1.return_value - assert returnValue1 != [1,1,1] - assert returnValue1 == [0,0,1] + assert NFT_contract.balanceOfBatch([accounts[1],accounts[1],accounts[1]],[1,2,3], {"from": accounts[1]}) == [0,0,1] def test_approval_functions(NFT_contract, accounts, test_mint_batch): From 435ced83b5e986c481371199cbf50e5ee94eeb85 Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Mon, 18 Apr 2022 13:02:39 -0700 Subject: [PATCH 06/29] Moved tests into the correct folder --- tests/{ => examples}/tokens/test_ERC1155ownable.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{ => examples}/tokens/test_ERC1155ownable.py (100%) diff --git a/tests/tokens/test_ERC1155ownable.py b/tests/examples/tokens/test_ERC1155ownable.py similarity index 100% rename from tests/tokens/test_ERC1155ownable.py rename to tests/examples/tokens/test_ERC1155ownable.py From 76a0db26616ec2019a6587602dde8953f61f7bbf Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Mon, 18 Apr 2022 13:31:42 -0700 Subject: [PATCH 07/29] added interface ERC1155.py --- vyper/builtin_interfaces/ERC1155.py | 107 ++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 vyper/builtin_interfaces/ERC1155.py diff --git a/vyper/builtin_interfaces/ERC1155.py b/vyper/builtin_interfaces/ERC1155.py new file mode 100644 index 0000000000..7f5d566f02 --- /dev/null +++ b/vyper/builtin_interfaces/ERC1155.py @@ -0,0 +1,107 @@ +interface_code = """ +# Events + +event Paused: + account: address + +event unPaused: + account: address + +event OwnershipTransferred: + previouwOwner: address + newOwner: address + +event TransferSingle: + operator: indexed(address) + fromAddress: indexed(address) + to: indexed(address) + id: uint256 + value: uint256 + +event TransferBatch: + operator: indexed(address) # indexed + fromAddress: indexed(address) + to: indexed(address) + ids: DynArray[uint256, BATCH_SIZE] + values: DynArray[uint256, BATCH_SIZE] + +event ApprovalForAll: + account: indexed(address) + operator: indexed(address) + approved: bool + +# Functions + +@external +def pause(): + pass + +@external +def unpause(): + pass + +@external +def isOwner() -> bool: + pass + +@external +def transferOwnership(newOwner: address): + pass + +@external +def renounceOwnership(): + pass + +@view +@external +def balanceOf(account: address, id: uint256) -> uint256: + pass + +@external +@view +def balanceOfBatch(accounts: DynArray[address, BATCH_SIZE], ids: DynArray[uint256, BATCH_SIZE]) -> DynArray[uint256,BATCH_SIZE]: #uint256[BATCH_SIZE]: + pass + +@external +def mint(receiver: address, id: uint256, amount:uint256, data:bytes32): + pass + +@external +def mintBatch(receiver: address, ids: DynArray[uint256, BATCH_SIZE], amounts: DynArray[uint256, BATCH_SIZE], data: bytes32): + pass + +@external +def burn(id: uint256, amount: uint256): + pass + +@external +def burnBatch(ids: DynArray[uint256, BATCH_SIZE], amounts: DynArray[uint256, BATCH_SIZE]): + pass + +@external +def setApprovalForAll(owner: address, operator: address, approved: bool): + pass + +@external +@view +def isApprovedForAll(account: address, operator: address) -> bool: + pass + +@external +def safeTransferFrom(sender: address, receiver: address, id: uint256, amount: uint256, bytes: bytes32): + pass + +@external +def safeBatchTransferFrom(sender: address, receiver: address, ids: DynArray[uint256, BATCH_SIZE], amounts: DynArray[uint256, BATCH_SIZE], _bytes: bytes32): + pass + +@external +def setURI(uri: String[MAX_URI_LENGTH]): + pass + +@pure +@external +def supportsInterface(interfaceId: bytes4) -> bool: + pass + +""" From d2a530501b0033f29a74379ebc71fb93879f66ad Mon Sep 17 00:00:00 2001 From: El De-dog-lo <3859395+fubuloubu@users.noreply.github.com> Date: Mon, 18 Apr 2022 16:57:07 -0400 Subject: [PATCH 08/29] refactor: clean up built-in interface --- vyper/builtin_interfaces/ERC1155.py | 80 ++++++----------------------- 1 file changed, 17 insertions(+), 63 deletions(-) diff --git a/vyper/builtin_interfaces/ERC1155.py b/vyper/builtin_interfaces/ERC1155.py index 7f5d566f02..e6387b3b92 100644 --- a/vyper/builtin_interfaces/ERC1155.py +++ b/vyper/builtin_interfaces/ERC1155.py @@ -1,57 +1,26 @@ interface_code = """ # Events -event Paused: - account: address - -event unPaused: - account: address - -event OwnershipTransferred: - previouwOwner: address - newOwner: address - event TransferSingle: - operator: indexed(address) - fromAddress: indexed(address) - to: indexed(address) + operator: indexed(address) + sender: indexed(address) + receiver: indexed(address) id: uint256 value: uint256 event TransferBatch: operator: indexed(address) # indexed - fromAddress: indexed(address) - to: indexed(address) + sender: indexed(address) + receiver: indexed(address) ids: DynArray[uint256, BATCH_SIZE] values: DynArray[uint256, BATCH_SIZE] event ApprovalForAll: - account: indexed(address) + owner: indexed(address) operator: indexed(address) approved: bool # Functions - -@external -def pause(): - pass - -@external -def unpause(): - pass - -@external -def isOwner() -> bool: - pass - -@external -def transferOwnership(newOwner: address): - pass - -@external -def renounceOwnership(): - pass - @view @external def balanceOf(account: address, id: uint256) -> uint256: @@ -59,23 +28,7 @@ def balanceOf(account: address, id: uint256) -> uint256: @external @view -def balanceOfBatch(accounts: DynArray[address, BATCH_SIZE], ids: DynArray[uint256, BATCH_SIZE]) -> DynArray[uint256,BATCH_SIZE]: #uint256[BATCH_SIZE]: - pass - -@external -def mint(receiver: address, id: uint256, amount:uint256, data:bytes32): - pass - -@external -def mintBatch(receiver: address, ids: DynArray[uint256, BATCH_SIZE], amounts: DynArray[uint256, BATCH_SIZE], data: bytes32): - pass - -@external -def burn(id: uint256, amount: uint256): - pass - -@external -def burnBatch(ids: DynArray[uint256, BATCH_SIZE], amounts: DynArray[uint256, BATCH_SIZE]): +def balanceOfBatch(accounts: DynArray[address, BATCH_SIZE], ids: DynArray[uint256, BATCH_SIZE]) -> DynArray[uint256, BATCH_SIZE]: pass @external @@ -88,20 +41,21 @@ def isApprovedForAll(account: address, operator: address) -> bool: pass @external -def safeTransferFrom(sender: address, receiver: address, id: uint256, amount: uint256, bytes: bytes32): +def safeTransferFrom(sender: address, receiver: address, id: uint256, amount: uint256, data: Bytes[DATA_LENGTH]): pass @external -def safeBatchTransferFrom(sender: address, receiver: address, ids: DynArray[uint256, BATCH_SIZE], amounts: DynArray[uint256, BATCH_SIZE], _bytes: bytes32): +def safeBatchTransferFrom( + sender: address, + receiver: address, + ids: DynArray[uint256, BATCH_SIZE], + amounts: DynArray[uint256, BATCH_SIZE], + data: Bytes[DATA_LENGTH], +): pass +@view @external -def setURI(uri: String[MAX_URI_LENGTH]): - pass - -@pure -@external -def supportsInterface(interfaceId: bytes4) -> bool: +def URI() -> String[MAX_URI_LENGTH]: pass - """ From 4bd7c35018227678542109727d5210868a090d4a Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Sun, 24 Apr 2022 17:43:33 -0700 Subject: [PATCH 09/29] rewrote tests to use eth-tester --- examples/tokens/ERC1155ownable.vy | 12 +- ...able.py => test_ERC1155ownable.py.brownie} | 33 +- .../tokens/test_erc1155ownable_ETHtester.py | 316 ++++++++++++++++++ vyper/builtin_interfaces/ERC1155.py | 61 ---- 4 files changed, 323 insertions(+), 99 deletions(-) rename tests/examples/tokens/{test_ERC1155ownable.py => test_ERC1155ownable.py.brownie} (93%) create mode 100644 tests/examples/tokens/test_erc1155ownable_ETHtester.py delete mode 100644 vyper/builtin_interfaces/ERC1155.py diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index 6620797476..38fc18a186 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -18,6 +18,7 @@ MAX_URI_LENGTH: constant(uint256) = 1024 owner: public(address) # pause status True / False +# @dev not part of the core spec but a common feature for NFT projects paused: public(bool) # the contracts URI to find the metadata @@ -41,8 +42,6 @@ balances: HashMap[uint256,HashMap[address, uint256]] # Mapping from account to operator approvals operatorApprovals: HashMap[address, HashMap[address, bool]] - - ############### events ############### event Paused: # @dev Emits a pause event with the address that paused the contract @@ -103,7 +102,7 @@ interface IERC1155Receiver: def onERC1155BatchReceived(operator: address, fromAddress: address, to: address, _ids: DynArray[uint256, BATCH_SIZE], _amounts: DynArray[uint256, BATCH_SIZE], data: bytes32) -> bytes32: payable interface IERC1155MetadataURI: - def uri(id: uint256) -> String[MAX_URI_LENGTH]: payable + def uri(id: uint256) -> String[MAX_URI_LENGTH]: view ############### functions ############### @@ -125,6 +124,7 @@ def __init__(name: String[1024], symbol: String[1024], uri: String[1024]): def pause(): # @dev Pause the contract, checks if the caller is the owner and if the contract is paused already # @dev emits a pause event + # @dev not part of the core spec but a common feature for NFT projects assert self.owner == msg.sender, "Ownable: caller is not the owner" assert not self.paused, " the contract is already paused" self.paused = True @@ -134,17 +134,13 @@ def pause(): def unpause(): # @dev Unpause the contract, checks if the caller is the owner and if the contract is paused already # @dev emits an unpause event + # @dev not part of the core spec but a common feature for NFT projects assert self.owner == msg.sender, "Ownable: caller is not the owner" assert self.paused, "the contract is not paused" self.paused = False log unPaused(msg.sender) ## ownership ## -@external -def isOwner() -> bool: - # @dev if the calling user it the owner, return true. Otherwise false - return self.owner == msg.sender - @external def transferOwnership(newOwner: address): # @dev Transfer the ownership. Checks for contract pause status, current owner and prevent transferring to diff --git a/tests/examples/tokens/test_ERC1155ownable.py b/tests/examples/tokens/test_ERC1155ownable.py.brownie similarity index 93% rename from tests/examples/tokens/test_ERC1155ownable.py rename to tests/examples/tokens/test_ERC1155ownable.py.brownie index 0a8b955e37..78080dacb2 100644 --- a/tests/examples/tokens/test_ERC1155ownable.py +++ b/tests/examples/tokens/test_ERC1155ownable.py.brownie @@ -365,15 +365,9 @@ def test_max_batch_size_violation(NFT_contract, accounts): def test_ownership_functions(NFT_contract): # change owner from account 0 to account 1 and back - # check all changes by calling isOwner and owner functions - tx1 = NFT_contract.isOwner() - returnValue1 = tx1.return_value - assert returnValue1 == True - assert NFT_contract.owner() == accounts[0] + # check all changes by calling owner function - tx2 = NFT_contract.isOwner({'from': accounts[1]}) - returnValue2 = tx2.return_value - assert returnValue2 == False + assert NFT_contract.owner() == accounts[0] with brownie.reverts(): # try to transfer ownership from non-owner account @@ -388,31 +382,14 @@ def test_ownership_functions(NFT_contract): NFT_contract.transferOwnership(ZERO_ADDRESS) NFT_contract.transferOwnership(accounts[1]) - - tx1 = NFT_contract.isOwner() - returnValue1 = tx1.return_value - assert returnValue1 == False - - tx2 = NFT_contract.isOwner({'from': accounts[1]}) - returnValue2 = tx2.return_value - assert returnValue2 == True assert NFT_contract.owner() == accounts[1] NFT_contract.transferOwnership(accounts[0],{'from': accounts[1]}) - - tx1 = NFT_contract.isOwner() - returnValue1 = tx1.return_value - assert returnValue1 == True assert NFT_contract.owner() == accounts[0] - tx2 = NFT_contract.isOwner({'from': accounts[1]}) - returnValue2 = tx2.return_value - assert returnValue2 == False def test_renounce_ownership(NFT_contract): - tx1 = NFT_contract.isOwner() - returnValue1 = tx1.return_value - assert returnValue1 == True + assert NFT_contract.owner() == accounts[0] with brownie.reverts(): @@ -420,8 +397,4 @@ def test_renounce_ownership(NFT_contract): NFT_contract.renounceOwnership({"from": accounts[2]}) NFT_contract.renounceOwnership() - - tx1 = NFT_contract.isOwner() - returnValue1 = tx1.return_value - assert returnValue1 == False assert NFT_contract.owner() == ZERO_ADDRESS \ No newline at end of file diff --git a/tests/examples/tokens/test_erc1155ownable_ETHtester.py b/tests/examples/tokens/test_erc1155ownable_ETHtester.py new file mode 100644 index 0000000000..58f10f089f --- /dev/null +++ b/tests/examples/tokens/test_erc1155ownable_ETHtester.py @@ -0,0 +1,316 @@ +import pytest +# ERC1155 ownable, opensea compatible tests +# @author Dr. Pixel (github: @Doc-Pixel) + +# constants - contract deployment +CONTRACT_NAME = 'TEST 1155' +CONTRACT_SYMBOL= 'T1155' +CONTRACT_URI = 'https://mydomain.io/NFTdata/{id}' +NEW_CONTRACT_URI = 'https://mynewdomain.io/NFTdata/{id}' +ERC165_INTERFACE_ID = '0x01ffc9a7' +ERC1155_INTERFACE_ID = '0xd9b67a26' +ERC1155_INTERFACE_ID_METADATA = '0x0e89341c' +ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" + +# minting test lists +mintBatch = [1,2,3,4,5,6,7,8,9,10] +mintBatch2 = [11,12,13,14,15,16,17,19,19,20] +minBatchSetOf10 = [1,1,1,1,1,1,1,1,1,1] +mintConflictBatch = [1,2,3] + +@pytest.fixture +def NFT_contract(get_contract, w3): + owner, a1, a2 = w3.eth.accounts[0:3] + with open("examples/tokens/ERC1155ownable.vy") as f: + code = f.read() + c = get_contract(code, *[CONTRACT_NAME, CONTRACT_SYMBOL, CONTRACT_URI]) + return c + +##### test fixtures ##### + +@pytest.fixture +def test_mint(NFT_contract, w3, assert_tx_failed): + NFT_contract.mint(w3.eth.accounts[1], 1, 1, '') + NFT_contract.mint(w3.eth.accounts[1], 2, 1, '') + NFT_contract.mint(w3.eth.accounts[1], 3, 1, '') + + assert_tx_failed(lambda: NFT_contract.mint(w3.eth.accounts[1], 4, 1, '', transact={"from": w3.eth.accounts[3]})) + assert_tx_failed(lambda: NFT_contract.mint(ZERO_ADDRESS, 4, 1, '', transact={"from": w3.eth.accounts[0]})) + + assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],1) == 1) + assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],2) == 1) + assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],3) == 1) + + # check ZERO_ADDRESS balance (should fail) + assert_tx_failed(lambda: NFT_contract.balanceOf(ZERO_ADDRESS,3) == 1) + + +@pytest.fixture +def test_mint_batch(NFT_contract, w3, assert_tx_failed): + NFT_contract.mintBatch(w3.eth.accounts[1], mintBatch, minBatchSetOf10, '') + NFT_contract.mintBatch(w3.eth.accounts[3], mintBatch2, minBatchSetOf10, '') + # assert_tx_failed(lambda: NFT_contract.mintBatch(w3.eth.accounts[1], mintBatch, minBatchSetOf10, '', transact={"from": w3.eth.accounts[2]})) + assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],1) == 1) + assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],2) == 1) + assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],3) == 1) + assert_tx_failed(lambda: NFT_contract.mintBatch(ZERO_ADDRESS, mintBatch, minBatchSetOf10, '')) + assert_tx_failed(lambda: NFT_contract.mintBatch(w3.eth.accounts[1], [1,2,3], [1,1], '')) + + +##### tests ##### + +def test_initial_state(NFT_contract): + # Check if the constructor of the contract is set up properly + # and the contract is deployed with the desired variables + + # variables set correctly? + assert NFT_contract.name() == CONTRACT_NAME + assert NFT_contract.symbol() == CONTRACT_SYMBOL + assert NFT_contract.uri() == CONTRACT_URI + + # interfaces set up correctly? + assert NFT_contract.supportsInterface(ERC165_INTERFACE_ID) + assert NFT_contract.supportsInterface(ERC1155_INTERFACE_ID) + assert NFT_contract.supportsInterface(ERC1155_INTERFACE_ID_METADATA) + + +def test_pause(NFT_contract,w3, assert_tx_failed): + # check the pause status, pause, check, unpause, check, with owner and non-owner w3.eth.accounts + # this test will check all the function that should not work when paused. + assert NFT_contract.paused() == False + + # try to pause the contract from a non owner account + assert_tx_failed(lambda: NFT_contract.pause(transact={"from": w3.eth.accounts[1]})) + + # now pause the contract and check status + NFT_contract.pause(transact={"from": w3.eth.accounts[0]}) + assert NFT_contract.paused() == True + + # try pausing a paused contract + assert_tx_failed(lambda: NFT_contract.pause()) + + # try functions that should not work when paused + assert_tx_failed(lambda: NFT_contract.setURI(NEW_CONTRACT_URI)) + + # test burn and burnbatch + assert_tx_failed(lambda: NFT_contract.burn(1,1)) + assert_tx_failed(lambda: NFT_contract.burnBatch([1,2],[1,1])) + + # check mint and mintbatch + assert_tx_failed(lambda: NFT_contract.mint(w3.eth.accounts[1], 1, 1, '', transact={"from": w3.eth.accounts[0]})) + assert_tx_failed(lambda: NFT_contract.mintBatch(w3.eth.accounts[1], mintBatch, minBatchSetOf10, '', transact={"from": w3.eth.accounts[0]})) + + # check safetransferfrom and safebatchtransferfrom + assert_tx_failed(lambda: NFT_contract.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 1, 1, '', transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) + + # check ownership functions + assert_tx_failed(lambda: NFT_contract.transferOwnership(w3.eth.accounts[1])) + assert_tx_failed(lambda: NFT_contract.renounceOwnership()) + + # check approval functions + assert_tx_failed(lambda: NFT_contract.setApprovalForAll(w3.eth.accounts[0],w3.eth.accounts[5],True)) + assert_tx_failed(lambda: NFT_contract.isApprovedForAll(w3.eth.accounts[0],w3.eth.accounts[5])) + + # try and unpause as non-owner + assert_tx_failed(lambda: NFT_contract.unpause(transact={"from": w3.eth.accounts[1]})) + + NFT_contract.unpause(transact={"from": w3.eth.accounts[0]}) + assert NFT_contract.paused() == False + + # try un pausing an unpaused contract + assert_tx_failed(lambda: NFT_contract.unpause()) + + +def test_URI(NFT_contract, w3,assert_tx_failed): + # change contract URI and restore. + assert NFT_contract.uri() == CONTRACT_URI + NFT_contract.setURI(NEW_CONTRACT_URI, transact={"from": w3.eth.accounts[1]}) + assert NFT_contract.uri() == NEW_CONTRACT_URI + assert NFT_contract.uri() != CONTRACT_URI + NFT_contract.setURI(CONTRACT_URI, transact={"from": w3.eth.accounts[1]}) + assert NFT_contract.uri() != NEW_CONTRACT_URI + assert NFT_contract.uri() == CONTRACT_URI + + assert_tx_failed(lambda: NFT_contract.setURI(CONTRACT_URI)) + +def test_safeTransferFrom_balanceOf_single(NFT_contract, w3, test_mint, assert_tx_failed): + # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture + NFT_contract.mint(w3.eth.accounts[1], 4, 1, '', transact={"from": w3.eth.accounts[0]}) + assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],4, transact={"from": w3.eth.accounts[1]}) == 1) + + # transfer by non-owner + assert_tx_failed(lambda: NFT_contract.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 4, 1, '', transact={"from": w3.eth.accounts[2]})) + + # transfer to zero address + assert_tx_failed(lambda: NFT_contract.safeTransferFrom(w3.eth.accounts[1], ZERO_ADDRESS, 4, 1, '', transact={"from": w3.eth.accounts[1]})) + + # transfer to self + assert_tx_failed(lambda: NFT_contract.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[1], 4, 1, '', transact={"from": w3.eth.accounts[1]})) + + # transfer more than owned + assert_tx_failed(lambda: NFT_contract.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 4, 500, '', transact={"from": w3.eth.accounts[1]})) + + # transfer item not owned / not existing + assert_tx_failed(lambda: NFT_contract.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 500, 1, '', transact={"from": w3.eth.accounts[1]})) + + NFT_contract.mint(w3.eth.accounts[1], 21, 1, '', transact={"from": w3.eth.accounts[0]}) + NFT_contract.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 21, 1, '', transact={"from": w3.eth.accounts[1]}) + + assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[2],1, transact={"from": w3.eth.accounts[0]}) == 1) + + # try to transfer item again + assert_tx_failed(lambda: NFT_contract.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 21, 1, '', transact={"from": w3.eth.accounts[1]})) + assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],1, {"from": w3.eth.w3.eth.accounts[0]}) == 0) + + +# TODO: mint 20 NFTs [1:20] and check the balance for each +def test_mintBatch_balanceOf(NFT_contract, w3, test_mint_batch, assert_tx_failed): + # Use the mint three fixture to mint the tokens. + # this test checks the balances of this test + for i in range (1,10): + assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1], i, transact={"from": w3.eth.accounts[1]}) == 1) + assert_tx_failed(lambda: NFT_contract.balanceOf(ZERO_ADDRESS, i, transact={"from": w3.eth.accounts[1]}) == 1) + +def test_safeBatchTransferFrom_balanceOf_batch(NFT_contract, w3, test_mint_batch, assert_tx_failed): + # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture + + NFT_contract.balanceOf(w3.eth.accounts[1],1, transact={"from": w3.eth.accounts[1]}) == 1 + + + # try to transfer item from non item owner account + assert_tx_failed(lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[2]})) + + # try to transfer item to zero address + assert_tx_failed(lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], ZERO_ADDRESS, [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) + + # try to transfer item to self + assert_tx_failed(lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[1], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) + + # try to transfer more items than we own + assert_tx_failed(lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,125,1], '', transact={"from": w3.eth.accounts[1]})) + + # mismatched item and amounts + assert_tx_failed(lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1], '', transact={"from": w3.eth.accounts[1]})) + + # try to transfer nonexisting item + assert_tx_failed(lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,500], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) + assert (lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) + + # try to transfer again, our balances are zero now, should fail + assert_tx_failed(lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: NFT_contract.balanceOfBatch([w3.eth.accounts[2],w3.eth.accounts[2],w3.eth.accounts[2]],[1,2], transact={"from": w3.eth.accounts[0]}) == [1,1,1]) + + assert (lambda: NFT_contract.balanceOfBatch([w3.eth.accounts[2],w3.eth.accounts[2],w3.eth.accounts[2]],[1,2,3], transact={"from": w3.eth.accounts[0]}) == [1,1,1]) + assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],1, transact={"from": w3.eth.accounts[0]}) == 0) + +def test_mint_one_burn_one(NFT_contract, w3, assert_tx_failed): + # check the balance from an owner and non-owner account + + NFT_contract.mint(w3.eth.accounts[0], 21, 1, '', transact={"from": w3.eth.accounts[0]}) + + assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[0],21, transact={"from": w3.eth.accounts[0]}) == 1) + assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[0],21, transact={"from": w3.eth.accounts[1]}) == 1) + + # try and burn an item we don't control + assert_tx_failed(lambda: NFT_contract.burn(21,1,transact={"from": w3.eth.accounts[3]})) + + # burn an item that contains something we don't own + assert_tx_failed(lambda: NFT_contract.burn(595,1,transact={"from": w3.eth.accounts[1]})) + + # burn ah item passing a higher amount than we own + assert_tx_failed(lambda: NFT_contract.burn(21,500,transact={"from": w3.eth.accounts[1]})) + + NFT_contract.burn(21,1, transact={"from": w3.eth.accounts[0]}) + + assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[0],21, transact={"from": w3.eth.accounts[1]}) == 0) + + +def test_mint_batch_burn_batch(NFT_contract, w3, assert_tx_failed): + # mint NFTs 11-20 + NFT_contract.mintBatch(w3.eth.accounts[3], mintBatch2, minBatchSetOf10, '',transact={"from": w3.eth.accounts[0]}) + + # check the balance + assert (lambda: NFT_contract.balanceOfBatch([w3.eth.accounts[1],w3.eth.accounts[1],w3.eth.accounts[1]],[1,2,3], transact={"from": w3.eth.accounts[1]}) == [1,1,1]) + + # try and burn a batch we don't control + assert_tx_failed(lambda: NFT_contract.burnBatch([11,12],[1,1])) + + # ids and amounts array length not matching + assert_tx_failed(lambda: NFT_contract.burnBatch([1,2,3],[1,1], transact={"from": w3.eth.accounts[1]})) + + # burn a batch that contains something we don't own + assert_tx_failed(lambda: NFT_contract.burnBatch([2,3,595],[1,1,1],transact={"from": w3.eth.accounts[1]})) + + # burn a batch passing a higher amount than we own + assert_tx_failed(lambda: NFT_contract.burnBatch([1,2,3],[1,500,1],transact={"from": w3.eth.accounts[1]})) + + # burn existing + NFT_contract.burnBatch([11,12],[1,1],transact={"from": w3.eth.accounts[3]}) + + assert (lambda: NFT_contract.balanceOfBatch([w3.eth.accounts[1],w3.eth.accounts[1],w3.eth.accounts[1]],[11,12,13], transact={"from": w3.eth.accounts[1]}) == [0,0,1]) + + # burn again, should revert + assert_tx_failed(lambda: NFT_contract.burnBatch([1,2],[1,1],transact={"from": w3.eth.accounts[1]})) + + assert (lambda: NFT_contract.balanceOfBatch([w3.eth.accounts[1],w3.eth.accounts[1],w3.eth.accounts[1]],[1,2,3], transact={"from": w3.eth.accounts[1]}) == [0,0,1]) + + +def test_approval_functions(NFT_contract, w3, test_mint_batch, assert_tx_failed): + + # self-approval by the owner + assert_tx_failed(lambda: NFT_contract.setApprovalForAll(w3.eth.accounts[5],w3.eth.accounts[5],True, transact={"from": w3.eth.accounts[5]})) + + # let's approve and operator for somebody else's account + assert_tx_failed(lambda: NFT_contract.setApprovalForAll(w3.eth.accounts[0],w3.eth.accounts[5],True, transact={"from": w3.eth.accounts[3]})) + + # set approval correctly + NFT_contract.setApprovalForAll(w3.eth.accounts[0],w3.eth.accounts[5],True) + + # check approval + NFT_contract.isApprovedForAll(w3.eth.accounts[0],w3.eth.accounts[5]) + + # remove approval + NFT_contract.setApprovalForAll(w3.eth.accounts[0],w3.eth.accounts[5],False) + + +def test_max_batch_size_violation(NFT_contract, w3, assert_tx_failed): + TOTAL_BAD_BATCH = 200 + ids = [] + amounts = [] + for i in range(1,TOTAL_BAD_BATCH): + ids.append(i) + amounts.append(1) + + assert_tx_failed(lambda: NFT_contract.mintBatch(w3.eth.accounts[1], ids, amounts, '', transact={"from": w3.eth.accounts[0]})) + + +# Transferring back and forth + +def test_ownership_functions(NFT_contract, w3, assert_tx_failed,tester): + owner, a1, a2 = w3.eth.accounts[0:3] + print(owner,a1,a2) + print('___owner___', NFT_contract.owner()) + # change owner from account 0 to account 1 and back + + assert NFT_contract.owner() == owner + assert_tx_failed(lambda: NFT_contract.transferOwnership(w3.eth.accounts[1], transact={"from": a2})) + + # try to transfer ownership to current owner + assert_tx_failed(lambda: NFT_contract.transferOwnership(w3.eth.accounts[0])) + # try to transfer ownership to ZERO ADDRESS + assert_tx_failed(lambda: NFT_contract.transferOwnership("0x0000000000000000000000000000000000000000")) + + # Transfer ownership to account 1 + NFT_contract.transferOwnership(w3.eth.accounts[1]) + assert (lambda: NFT_contract.owner() == w3.eth.accounts[1]) + +def test_renounce_ownership(NFT_contract, w3, assert_tx_failed): + + assert NFT_contract.owner() == w3.eth.accounts[0] + # try to transfer ownership from non-owner account + assert_tx_failed(lambda: NFT_contract.renounceOwnership(transact={"from": w3.eth.accounts[2]})) + + NFT_contract.renounceOwnership(transact={"from": w3.eth.accounts[0]}) + + assert NFT_contract.owner() == None \ No newline at end of file diff --git a/vyper/builtin_interfaces/ERC1155.py b/vyper/builtin_interfaces/ERC1155.py deleted file mode 100644 index e6387b3b92..0000000000 --- a/vyper/builtin_interfaces/ERC1155.py +++ /dev/null @@ -1,61 +0,0 @@ -interface_code = """ -# Events - -event TransferSingle: - operator: indexed(address) - sender: indexed(address) - receiver: indexed(address) - id: uint256 - value: uint256 - -event TransferBatch: - operator: indexed(address) # indexed - sender: indexed(address) - receiver: indexed(address) - ids: DynArray[uint256, BATCH_SIZE] - values: DynArray[uint256, BATCH_SIZE] - -event ApprovalForAll: - owner: indexed(address) - operator: indexed(address) - approved: bool - -# Functions -@view -@external -def balanceOf(account: address, id: uint256) -> uint256: - pass - -@external -@view -def balanceOfBatch(accounts: DynArray[address, BATCH_SIZE], ids: DynArray[uint256, BATCH_SIZE]) -> DynArray[uint256, BATCH_SIZE]: - pass - -@external -def setApprovalForAll(owner: address, operator: address, approved: bool): - pass - -@external -@view -def isApprovedForAll(account: address, operator: address) -> bool: - pass - -@external -def safeTransferFrom(sender: address, receiver: address, id: uint256, amount: uint256, data: Bytes[DATA_LENGTH]): - pass - -@external -def safeBatchTransferFrom( - sender: address, - receiver: address, - ids: DynArray[uint256, BATCH_SIZE], - amounts: DynArray[uint256, BATCH_SIZE], - data: Bytes[DATA_LENGTH], -): - pass - -@view -@external -def URI() -> String[MAX_URI_LENGTH]: - pass -""" From d776fad5b585da6bb0b0b80cc2b9129eae4103e0 Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Tue, 26 Apr 2022 20:45:24 -0700 Subject: [PATCH 10/29] cleaned up brownie tests in favor of eth-tester --- .../tokens/test_ERC1155ownable.py.brownie | 400 ------------------ 1 file changed, 400 deletions(-) delete mode 100644 tests/examples/tokens/test_ERC1155ownable.py.brownie diff --git a/tests/examples/tokens/test_ERC1155ownable.py.brownie b/tests/examples/tokens/test_ERC1155ownable.py.brownie deleted file mode 100644 index 78080dacb2..0000000000 --- a/tests/examples/tokens/test_ERC1155ownable.py.brownie +++ /dev/null @@ -1,400 +0,0 @@ - -# brownie test -import pytest -import brownie -from brownie import ZERO_ADDRESS, accounts -from web3.exceptions import ValidationError - -# ERC1155 ownable, opensea compatible tests -# @author Dr. Pixel (github: @Doc-Pixel) - -# constants - contract deployment -CONTRACT_NAME = 'TEST 1155' -CONTRACT_SYMBOL= 'T1155' -CONTRACT_URI = 'https://mydomain.io/NFTdata/{id}' -NEW_CONTRACT_URI = 'https://mynewdomain.io/NFTdata/{id}' -ERC165_INTERFACE_ID = '0x01ffc9a7' -ERC1155_INTERFACE_ID = '0xd9b67a26' -ERC1155_INTERFACE_ID_METADATA = '0x0e89341c' - -# minting test lists -mintBatch = [1,2,3,4,5,6,7,8,9,10] -mintBatch2 = [11,12,13,14,15,16,17,19,19,20] -minBatchSetOf10 = [1,1,1,1,1,1,1,1,1,1] -mintConflictBatch = [1,2,3] - -##### test fixtures ##### -@pytest.fixture -def NFT_contract(ERC1155ownable, accounts, scope="module", autouse=True): - yield accounts[0].deploy(ERC1155ownable, CONTRACT_NAME, CONTRACT_SYMBOL, CONTRACT_URI) - -@pytest.fixture(autouse=True) -def isolation(fn_isolation): - pass - -@pytest.fixture -def test_mint(NFT_contract): - NFT_contract.mint(accounts[1], 1, 1, '', {"from": accounts[0]}) - NFT_contract.mint(accounts[1], 2, 1, '', {"from": accounts[0]}) - NFT_contract.mint(accounts[1], 3, 1, '', {"from": accounts[0]}) - - with brownie.reverts(): - # mint with non-owner - NFT_contract.mint(accounts[1], 4, 1, '', {"from": accounts[3]}) - # assert_tx_failed(NFT_contract.mint(accounts[1], 4, 1, '', {"from": accounts[3]})) - with brownie.reverts(): - # mint to zero address - NFT_contract.mint(ZERO_ADDRESS, 4, 1, '', {"from": accounts[0]}) - - -@pytest.fixture -def test_mint_batch(NFT_contract): - NFT_contract.mintBatch(accounts[1], mintBatch, minBatchSetOf10, '', {"from": accounts[0]}) - - with brownie.reverts(): - # mint with non-owner - NFT_contract.mintBatch(accounts[1], mintBatch, minBatchSetOf10, '', {"from": accounts[2]}) - - with brownie.reverts(): - # mint to zero addres - NFT_contract.mintBatch(ZERO_ADDRESS, mintBatch, minBatchSetOf10, '', {"from": accounts[0]}) - - with brownie.reverts(): - # ids dont match accounts - NFT_contract.mintBatch(accounts[1], [1,2,3], [1,1], '', {"from": accounts[0]}) - -##### tests ##### - -def test_initial_state(NFT_contract): - # Check if the constructor of the contract is set up properly - # and the contract is deployed with the desired variables - - # variables set correctly? - assert NFT_contract.name() == CONTRACT_NAME - assert NFT_contract.symbol() == CONTRACT_SYMBOL - assert NFT_contract.uri() == CONTRACT_URI - - # interfaces set up correctly? - assert NFT_contract.supportsInterface(ERC165_INTERFACE_ID) - # tx1 = NFT_contract.supportsInterface(ERC165_INTERFACE_ID) - # returnValue1 = tx1.return_value - # assert returnValue1 == True - - assert NFT_contract.supportsInterface(ERC1155_INTERFACE_ID) - - assert NFT_contract.supportsInterface(ERC1155_INTERFACE_ID_METADATA) - - -def test_pause(NFT_contract): - # check the pause status, pause, check, unpause, check, with owner and non-owner accounts - # this test will check all the function that should not work when paused. - assert NFT_contract.paused() == False - - # try and pause as non-owner - with brownie.reverts(): - NFT_contract.pause({"from": accounts[1]}) - - NFT_contract.pause() - assert NFT_contract.paused() == True - - # try pausing a paused contract - with brownie.reverts(): - NFT_contract.pause() - - # try functions that should not work when paused - with brownie.reverts(): - NFT_contract.setURI(NEW_CONTRACT_URI) - - # test burn and burnbatch - with brownie.reverts(): - NFT_contract.burn(1,1,{"from": accounts[1]}) - - with brownie.reverts(): - NFT_contract.burnBatch([1,2],[1,1],{"from": accounts[1]}) - - # check mint and mintbatch - with brownie.reverts(): - NFT_contract.mint(accounts[1], 1, 1, '', {"from": accounts[0]}) - - with brownie.reverts(): - NFT_contract.mintBatch(accounts[1], mintBatch, minBatchSetOf10, '', {"from": accounts[0]}) - - - # check safetransferfrom and safebatchtransferfrom - with brownie.reverts(): - NFT_contract.safeTransferFrom(accounts[1], accounts[2], 1, 1, '', {"from": accounts[1]}) - - with brownie.reverts(): - NFT_contract.safeBatchTransferFrom(accounts[1], accounts[2], [1,2,3], [1,1,1], '', {"from": accounts[1]}) - - # check ownership functions - with brownie.reverts(): - NFT_contract.transferOwnership(accounts[1]) - - with brownie.reverts(): - NFT_contract.renounceOwnership() - - # check approval functions - with brownie.reverts(): - NFT_contract.setApprovalForAll(accounts[0],accounts[5],True) - - with brownie.reverts(): - NFT_contract.isApprovedForAll(accounts[0],accounts[5]) - - # try and unpause as non-owner - with brownie.reverts(): - NFT_contract.unpause({"from": accounts[1]}) - - NFT_contract.unpause() - assert NFT_contract.paused() == False - - # try un pausing an unpaused contract - with brownie.reverts(): - NFT_contract.unpause() - - -def test_URI(NFT_contract, accounts): - # change contract URI and restore. - assert NFT_contract.uri() == CONTRACT_URI - NFT_contract.setURI(NEW_CONTRACT_URI) - assert NFT_contract.uri() == NEW_CONTRACT_URI - assert NFT_contract.uri() != CONTRACT_URI - NFT_contract.setURI(CONTRACT_URI) - assert NFT_contract.uri() != NEW_CONTRACT_URI - assert NFT_contract.uri() == CONTRACT_URI - - with brownie.reverts(): - NFT_contract.setURI(CONTRACT_URI) - -def test_mint_single_balanceOf(NFT_contract, accounts, test_mint): - # Use the test_mint fixture to mint the tokens. - # this test checks the balances of this test - assert NFT_contract.balanceOf(accounts[1],1) == 1 - assert NFT_contract.balanceOf(accounts[1],2) == 1 - assert NFT_contract.balanceOf(accounts[1],3) == 1 - - # assert_tx_failed - with brownie.reverts(): - assert NFT_contract.balanceOf(ZERO_ADDRESS,3) == 1 - -def test_mint_batch_balanceOf(NFT_contract, accounts, test_mint_batch): - # Use the test_mint_batch fixture to mint the tokens. - # this test checks the balances of this test - assert NFT_contract.balanceOf(accounts[1],1) == 1 - assert NFT_contract.balanceOf(accounts[1],2) == 1 - assert NFT_contract.balanceOf(accounts[1],3) == 1 - -def test_safeTransferFrom_balanceOf_single(NFT_contract, accounts, test_mint): - # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture - - assert NFT_contract.balanceOf(accounts[1],1, {"from": accounts[1]}) == 1 - - with brownie.reverts(): - # try to transfer item from non item owner account - NFT_contract.safeTransferFrom(accounts[1], accounts[2], 1, 1, '', {"from": accounts[2]}) - - with brownie.reverts(): - # try to transfer item to zero address - NFT_contract.safeTransferFrom(accounts[1], ZERO_ADDRESS, 1, 1, '', {"from": accounts[1]}) - - with brownie.reverts(): - # try to transfer item to self - NFT_contract.safeTransferFrom(accounts[1], accounts[1], 1, 1, '', {"from": accounts[1]}) - - with brownie.reverts(): - # try to transfer more items than we own - NFT_contract.safeTransferFrom(accounts[1], accounts[2], 1, 500, '', {"from": accounts[1]}) - - with brownie.reverts(): - # try to transfer nonexisting item - NFT_contract.safeTransferFrom(accounts[1], accounts[2], 500, 1, '', {"from": accounts[1]}) - - NFT_contract.safeTransferFrom(accounts[1], accounts[2], 1, 1, '', {"from": accounts[1]}) - - assert NFT_contract.balanceOf(accounts[2],1, {"from": accounts[0]}) == 1 - - with brownie.reverts(): - # try to transfer item again. to trigger zero balance - NFT_contract.safeTransferFrom(accounts[1], accounts[2], 1, 1, '', {"from": accounts[1]}) - - assert NFT_contract.balanceOf(accounts[1],1, {"from": accounts[0]}) == 0 - - -# TODO: mint 20 NFTs [1:20] and check the balance for each -def test_mintBatch_balanceOf(NFT_contract, accounts, test_mint_batch): - # Use the mint three fixture to mint the tokens. - # this test checks the balances of this test - for i in range (1,10): - assert NFT_contract.balanceOf(accounts[1], i, {"from": accounts[1]}) == 1 - - with brownie.reverts(): - assert NFT_contract.balanceOf(ZERO_ADDRESS, i, {"from": accounts[1]}) == 1 - -def test_safeBatchTransferFrom_balanceOf_batch(NFT_contract, accounts, test_mint_batch): - # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture - - NFT_contract.balanceOf(accounts[1],1, {"from": accounts[1]}) == 1 - - - with brownie.reverts(): - # try to transfer item from non item owner account - NFT_contract.safeBatchTransferFrom(accounts[1], accounts[2], [1,2,3], [1,1,1], '', {"from": accounts[2]}) - - with brownie.reverts(): - # try to transfer item to zero address - NFT_contract.safeBatchTransferFrom(accounts[1], ZERO_ADDRESS, [1,2,3], [1,1,1], '', {"from": accounts[1]}) - - with brownie.reverts(): - # try to transfer item to self - NFT_contract.safeBatchTransferFrom(accounts[1], accounts[1], [1,2,3], [1,1,1], '', {"from": accounts[1]}) - - with brownie.reverts(): - # try to transfer more items than we own - NFT_contract.safeBatchTransferFrom(accounts[1], accounts[2], [1,2,3], [1,125,1], '', {"from": accounts[1]}) - - with brownie.reverts(): - # mismatched item and amounts - NFT_contract.safeBatchTransferFrom(accounts[1], accounts[2], [1,2,3], [1,1], '', {"from": accounts[1]}) - - - with brownie.reverts(): - # try to transfer nonexisting item - NFT_contract.safeBatchTransferFrom(accounts[1], accounts[2], [1,2,500], [1,1,1], '', {"from": accounts[1]}) - - NFT_contract.safeBatchTransferFrom(accounts[1], accounts[2], [1,2,3], [1,1,1], '', {"from": accounts[1]}) - - with brownie.reverts(): - # try to transfer again, our balances are zero now, should fail - NFT_contract.safeBatchTransferFrom(accounts[1], accounts[2], [1,2,3], [1,1,1], '', {"from": accounts[1]}) - - - with brownie.reverts(): - assert NFT_contract.balanceOfBatch([accounts[2],accounts[2],accounts[2]],[1,2], {"from": accounts[0]}) == [1,1,1] - - assert NFT_contract.balanceOfBatch([accounts[2],accounts[2],accounts[2]],[1,2,3], {"from": accounts[0]}) == [1,1,1] - assert NFT_contract.balanceOf(accounts[1],1, {"from": accounts[0]}) == 0 - -def test_mint_one_burn_one(NFT_contract, accounts, test_mint): - # check the balance - assert NFT_contract.balanceOf(accounts[1],1, {"from": accounts[1]}) == 1 - - with brownie.reverts(): - # try and burn an item we don't control - NFT_contract.burn(1,1,{"from": accounts[3]}) - - with brownie.reverts(): - # burn an item that contains something we don't own - NFT_contract.burn(595,1,{"from": accounts[1]}) - - with brownie.reverts(): - # burn ah item passing a higher amount than we own - NFT_contract.burn(1,500,{"from": accounts[1]}) - - NFT_contract.burn(1,1,{"from": accounts[1]}) - - assert NFT_contract.balanceOf(accounts[1],1, {"from": accounts[1]}) == 0 - - -def test_mint_batch_burn_batch(NFT_contract, accounts, test_mint_batch): - # check the balance - assert NFT_contract.balanceOfBatch([accounts[1],accounts[1],accounts[1]],[1,2,3], {"from": accounts[1]}) == [1,1,1] - - with brownie.reverts(): - # try and burn a batch we don't control - NFT_contract.burnBatch([1,2],[1,1],{"from": accounts[3]}) - - with brownie.reverts(): - # ids and amounts array length not matching - NFT_contract.burnBatch([1,2,3],[1,1],{"from": accounts[1]}) - - with brownie.reverts(): - # burn a batch that contains something we don't own - NFT_contract.burnBatch([2,3,595],[1,1,1],{"from": accounts[1]}) - - with brownie.reverts(): - # burn a batch passing a higher amount than we own - NFT_contract.burnBatch([1,2,3],[1,500,1],{"from": accounts[1]}) - - # burn existing - NFT_contract.burnBatch([1,2],[1,1],{"from": accounts[1]}) - - assert NFT_contract.balanceOfBatch([accounts[1],accounts[1],accounts[1]],[1,2,3], {"from": accounts[1]}) == [0,0,1] - - - # burn again, should revert - with brownie.reverts(): - NFT_contract.burnBatch([1,2],[1,1],{"from": accounts[1]}) - - assert NFT_contract.balanceOfBatch([accounts[1],accounts[1],accounts[1]],[1,2,3], {"from": accounts[1]}) == [0,0,1] - - -def test_approval_functions(NFT_contract, accounts, test_mint_batch): - - # self-approval by the owner - with brownie.reverts(): - NFT_contract.setApprovalForAll(accounts[5],accounts[5],True, {"from": accounts[5]}) - - # let's approve and operator for somebody else's account - with brownie.reverts(): - NFT_contract.setApprovalForAll(accounts[0],accounts[5],True, {"from": accounts[3]}) - - # set approval correctly - NFT_contract.setApprovalForAll(accounts[0],accounts[5],True) - - # check approval - NFT_contract.isApprovedForAll(accounts[0],accounts[5]) - - # remove approval - NFT_contract.setApprovalForAll(accounts[0],accounts[5],False) - - -def test_max_batch_size_violation(NFT_contract, accounts): - TOTAL_BAD_BATCH = 200 - ids = [] - amounts = [] - for i in range(1,TOTAL_BAD_BATCH): - ids.append(i) - amounts.append(1) - with brownie.reverts(): - NFT_contract.mintBatch(accounts[1], ids, amounts, '', {"from": accounts[0]}) - - - -# Transferring back and forth - - -def test_ownership_functions(NFT_contract): - # change owner from account 0 to account 1 and back - # check all changes by calling owner function - - assert NFT_contract.owner() == accounts[0] - - with brownie.reverts(): - # try to transfer ownership from non-owner account - NFT_contract.transferOwnership(accounts[1], {"from": accounts[2]}) - - with brownie.reverts(): - # try to transfer ownership to current owner - NFT_contract.transferOwnership(accounts[0]) - - with brownie.reverts(): - # try to transfer ownership to current owner - NFT_contract.transferOwnership(ZERO_ADDRESS) - - NFT_contract.transferOwnership(accounts[1]) - assert NFT_contract.owner() == accounts[1] - - NFT_contract.transferOwnership(accounts[0],{'from': accounts[1]}) - assert NFT_contract.owner() == accounts[0] - - -def test_renounce_ownership(NFT_contract): - - assert NFT_contract.owner() == accounts[0] - - with brownie.reverts(): - # try to transfer ownership from non-owner account - NFT_contract.renounceOwnership({"from": accounts[2]}) - - NFT_contract.renounceOwnership() - assert NFT_contract.owner() == ZERO_ADDRESS \ No newline at end of file From e3e0a5148519fde8722541ab8cec9e38e8cbdfa2 Mon Sep 17 00:00:00 2001 From: "DrPixel.eth" <33023023+Doc-Pixel@users.noreply.github.com> Date: Tue, 26 Apr 2022 20:46:25 -0700 Subject: [PATCH 11/29] Update examples/tokens/ERC1155ownable.vy Co-authored-by: El De-dog-lo <3859395+fubuloubu@users.noreply.github.com> --- examples/tokens/ERC1155ownable.vy | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index 38fc18a186..a9ad63c1e5 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -15,6 +15,7 @@ BATCH_SIZE: constant(uint256) = 128 MAX_URI_LENGTH: constant(uint256) = 1024 # the contract owner +# @dev not part of the core spec but a common feature for NFT projects owner: public(address) # pause status True / False From 6be8be408f5388ced57b2bc0bda8427c0835c867 Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Tue, 26 Apr 2022 21:29:13 -0700 Subject: [PATCH 12/29] applied proposed changes in contract and tests --- examples/tokens/ERC1155ownable.vy | 19 +- tests/examples/tokens/test_erc1155.py | 316 ++++++++++++++++++ .../tokens/test_erc1155ownable_ETHtester.py | 316 ------------------ 3 files changed, 330 insertions(+), 321 deletions(-) create mode 100644 tests/examples/tokens/test_erc1155.py delete mode 100644 tests/examples/tokens/test_erc1155ownable_ETHtester.py diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index 38fc18a186..5462bad779 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -25,8 +25,8 @@ paused: public(bool) uri: public(String[MAX_URI_LENGTH]) # NFT marketplace compatibility -name: public(String[1024]) -symbol: public(String[1024]) +name: public(String[128]) +symbol: public(String[16]) # Interface IDs ERC165_INTERFACE_ID: constant(bytes4) = 0x01ffc9a7 @@ -94,12 +94,20 @@ event ApprovalForAll: operator: indexed(address) approved: bool +event URI: + # @dev This emits when the URI gets changed + # @param value the new URI + # @param id the ID + value: String[MAX_URI_LENGTH] + id: uint256 + + ############### interfaces ############### implements: ERC165 interface IERC1155Receiver: - def onERC1155Received(operator: address, fromAddress: address, to: address, id: uint256, _value: uint256, data: bytes32) -> bytes32: payable - def onERC1155BatchReceived(operator: address, fromAddress: address, to: address, _ids: DynArray[uint256, BATCH_SIZE], _amounts: DynArray[uint256, BATCH_SIZE], data: bytes32) -> bytes32: payable + def onERC1155Received(operator: address, sender: address, receiver: address, id: uint256, _value: uint256, data: bytes32) -> bytes32: payable + def onERC1155BatchReceived(operator: address, sender: address, receiver: address, _ids: DynArray[uint256, BATCH_SIZE], _amounts: DynArray[uint256, BATCH_SIZE], data: bytes32) -> bytes32: payable interface IERC1155MetadataURI: def uri(id: uint256) -> String[MAX_URI_LENGTH]: view @@ -107,7 +115,7 @@ interface IERC1155MetadataURI: ############### functions ############### @external -def __init__(name: String[1024], symbol: String[1024], uri: String[1024]): +def __init__(name: String[128], symbol: String[16], uri: String[1024]): # @dev contract initialization on deployment # @dev will set name and symbol, interfaces, owner and URI # @param name the smart contract name @@ -347,6 +355,7 @@ def setURI(uri: String[MAX_URI_LENGTH]): assert not self.paused, "The contract has been paused" assert self.uri != uri, "new and current URI are identical" self.uri = uri + log URI(uri, 0) @pure @external diff --git a/tests/examples/tokens/test_erc1155.py b/tests/examples/tokens/test_erc1155.py new file mode 100644 index 0000000000..54602410e3 --- /dev/null +++ b/tests/examples/tokens/test_erc1155.py @@ -0,0 +1,316 @@ +import pytest +# ERC1155 ownable, opensea compatible tests +# @author Dr. Pixel (github: @Doc-Pixel) + +# constants - contract deployment +CONTRACT_NAME = 'TEST 1155' +CONTRACT_SYMBOL= 'T1155' +CONTRACT_URI = 'https://mydomain.io/NFTdata/{id}' +NEW_CONTRACT_URI = 'https://mynewdomain.io/NFTdata/{id}' +ERC165_INTERFACE_ID = '0x01ffc9a7' +ERC1155_INTERFACE_ID = '0xd9b67a26' +ERC1155_INTERFACE_ID_METADATA = '0x0e89341c' +ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" + +# minting test lists +mintBatch = [1,2,3,4,5,6,7,8,9,10] +mintBatch2 = [11,12,13,14,15,16,17,19,19,20] +minBatchSetOf10 = [1,1,1,1,1,1,1,1,1,1] +mintConflictBatch = [1,2,3] + +@pytest.fixture +def erc1155(get_contract, w3): + owner, a1, a2 = w3.eth.accounts[0:3] + with open("examples/tokens/ERC1155ownable.vy") as f: + code = f.read() + c = get_contract(code, *[CONTRACT_NAME, CONTRACT_SYMBOL, CONTRACT_URI]) + return c + +##### test fixtures ##### + +@pytest.fixture +def test_mint(erc1155, w3, assert_tx_failed): + erc1155.mint(w3.eth.accounts[1], 1, 1, '') + erc1155.mint(w3.eth.accounts[1], 2, 1, '') + erc1155.mint(w3.eth.accounts[1], 3, 1, '') + + assert_tx_failed(lambda: erc1155.mint(w3.eth.accounts[1], 4, 1, '', transact={"from": w3.eth.accounts[3]})) + assert_tx_failed(lambda: erc1155.mint(ZERO_ADDRESS, 4, 1, '', transact={"from": w3.eth.accounts[0]})) + + assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],1) == 1) + assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],2) == 1) + assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],3) == 1) + + # check ZERO_ADDRESS balance (should fail) + assert_tx_failed(lambda: erc1155.balanceOf(ZERO_ADDRESS,3) == 1) + + +@pytest.fixture +def test_mint_batch(erc1155, w3, assert_tx_failed): + erc1155.mintBatch(w3.eth.accounts[1], mintBatch, minBatchSetOf10, '') + erc1155.mintBatch(w3.eth.accounts[3], mintBatch2, minBatchSetOf10, '') + # assert_tx_failed(lambda: erc1155.mintBatch(w3.eth.accounts[1], mintBatch, minBatchSetOf10, '', transact={"from": w3.eth.accounts[2]})) + assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],1) == 1) + assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],2) == 1) + assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],3) == 1) + assert_tx_failed(lambda: erc1155.mintBatch(ZERO_ADDRESS, mintBatch, minBatchSetOf10, '')) + assert_tx_failed(lambda: erc1155.mintBatch(w3.eth.accounts[1], [1,2,3], [1,1], '')) + + +##### tests ##### + +def test_initial_state(erc1155): + # Check if the constructor of the contract is set up properly + # and the contract is deployed with the desired variables + + # variables set correctly? + assert erc1155.name() == CONTRACT_NAME + assert erc1155.symbol() == CONTRACT_SYMBOL + assert erc1155.uri() == CONTRACT_URI + + # interfaces set up correctly? + assert erc1155.supportsInterface(ERC165_INTERFACE_ID) + assert erc1155.supportsInterface(ERC1155_INTERFACE_ID) + assert erc1155.supportsInterface(ERC1155_INTERFACE_ID_METADATA) + + +def test_pause(erc1155,w3, assert_tx_failed): + # check the pause status, pause, check, unpause, check, with owner and non-owner w3.eth.accounts + # this test will check all the function that should not work when paused. + assert erc1155.paused() == False + + # try to pause the contract from a non owner account + assert_tx_failed(lambda: erc1155.pause(transact={"from": w3.eth.accounts[1]})) + + # now pause the contract and check status + erc1155.pause(transact={"from": w3.eth.accounts[0]}) + assert erc1155.paused() == True + + # try pausing a paused contract + assert_tx_failed(lambda: erc1155.pause()) + + # try functions that should not work when paused + assert_tx_failed(lambda: erc1155.setURI(NEW_CONTRACT_URI)) + + # test burn and burnbatch + assert_tx_failed(lambda: erc1155.burn(1,1)) + assert_tx_failed(lambda: erc1155.burnBatch([1,2],[1,1])) + + # check mint and mintbatch + assert_tx_failed(lambda: erc1155.mint(w3.eth.accounts[1], 1, 1, '', transact={"from": w3.eth.accounts[0]})) + assert_tx_failed(lambda: erc1155.mintBatch(w3.eth.accounts[1], mintBatch, minBatchSetOf10, '', transact={"from": w3.eth.accounts[0]})) + + # check safetransferfrom and safebatchtransferfrom + assert_tx_failed(lambda: erc1155.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 1, 1, '', transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) + + # check ownership functions + assert_tx_failed(lambda: erc1155.transferOwnership(w3.eth.accounts[1])) + assert_tx_failed(lambda: erc1155.renounceOwnership()) + + # check approval functions + assert_tx_failed(lambda: erc1155.setApprovalForAll(w3.eth.accounts[0],w3.eth.accounts[5],True)) + assert_tx_failed(lambda: erc1155.isApprovedForAll(w3.eth.accounts[0],w3.eth.accounts[5])) + + # try and unpause as non-owner + assert_tx_failed(lambda: erc1155.unpause(transact={"from": w3.eth.accounts[1]})) + + erc1155.unpause(transact={"from": w3.eth.accounts[0]}) + assert erc1155.paused() == False + + # try un pausing an unpaused contract + assert_tx_failed(lambda: erc1155.unpause()) + + +def test_URI(erc1155, w3,assert_tx_failed): + # change contract URI and restore. + assert erc1155.uri() == CONTRACT_URI + erc1155.setURI(NEW_CONTRACT_URI, transact={"from": w3.eth.accounts[1]}) + assert erc1155.uri() == NEW_CONTRACT_URI + assert erc1155.uri() != CONTRACT_URI + erc1155.setURI(CONTRACT_URI, transact={"from": w3.eth.accounts[1]}) + assert erc1155.uri() != NEW_CONTRACT_URI + assert erc1155.uri() == CONTRACT_URI + + assert_tx_failed(lambda: erc1155.setURI(CONTRACT_URI)) + +def test_safeTransferFrom_balanceOf_single(erc1155, w3, test_mint, assert_tx_failed): + # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture + erc1155.mint(w3.eth.accounts[1], 4, 1, '', transact={"from": w3.eth.accounts[0]}) + assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],4, transact={"from": w3.eth.accounts[1]}) == 1) + + # transfer by non-owner + assert_tx_failed(lambda: erc1155.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 4, 1, '', transact={"from": w3.eth.accounts[2]})) + + # transfer to zero address + assert_tx_failed(lambda: erc1155.safeTransferFrom(w3.eth.accounts[1], ZERO_ADDRESS, 4, 1, '', transact={"from": w3.eth.accounts[1]})) + + # transfer to self + assert_tx_failed(lambda: erc1155.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[1], 4, 1, '', transact={"from": w3.eth.accounts[1]})) + + # transfer more than owned + assert_tx_failed(lambda: erc1155.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 4, 500, '', transact={"from": w3.eth.accounts[1]})) + + # transfer item not owned / not existing + assert_tx_failed(lambda: erc1155.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 500, 1, '', transact={"from": w3.eth.accounts[1]})) + + erc1155.mint(w3.eth.accounts[1], 21, 1, '', transact={"from": w3.eth.accounts[0]}) + erc1155.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 21, 1, '', transact={"from": w3.eth.accounts[1]}) + + assert (lambda: erc1155.balanceOf(w3.eth.accounts[2],1, transact={"from": w3.eth.accounts[0]}) == 1) + + # try to transfer item again + assert_tx_failed(lambda: erc1155.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 21, 1, '', transact={"from": w3.eth.accounts[1]})) + assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],1, {"from": w3.eth.w3.eth.accounts[0]}) == 0) + + +# TODO: mint 20 NFTs [1:20] and check the balance for each +def test_mintBatch_balanceOf(erc1155, w3, test_mint_batch, assert_tx_failed): + # Use the mint three fixture to mint the tokens. + # this test checks the balances of this test + for i in range (1,10): + assert (lambda: erc1155.balanceOf(w3.eth.accounts[1], i, transact={"from": w3.eth.accounts[1]}) == 1) + assert_tx_failed(lambda: erc1155.balanceOf(ZERO_ADDRESS, i, transact={"from": w3.eth.accounts[1]}) == 1) + +def test_safeBatchTransferFrom_balanceOf_batch(erc1155, w3, test_mint_batch, assert_tx_failed): + # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture + + erc1155.balanceOf(w3.eth.accounts[1],1, transact={"from": w3.eth.accounts[1]}) == 1 + + + # try to transfer item from non item owner account + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[2]})) + + # try to transfer item to zero address + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], ZERO_ADDRESS, [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) + + # try to transfer item to self + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[1], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) + + # try to transfer more items than we own + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,125,1], '', transact={"from": w3.eth.accounts[1]})) + + # mismatched item and amounts + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1], '', transact={"from": w3.eth.accounts[1]})) + + # try to transfer nonexisting item + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,500], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) + assert (lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) + + # try to transfer again, our balances are zero now, should fail + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.balanceOfBatch([w3.eth.accounts[2],w3.eth.accounts[2],w3.eth.accounts[2]],[1,2], transact={"from": w3.eth.accounts[0]}) == [1,1,1]) + + assert (lambda: erc1155.balanceOfBatch([w3.eth.accounts[2],w3.eth.accounts[2],w3.eth.accounts[2]],[1,2,3], transact={"from": w3.eth.accounts[0]}) == [1,1,1]) + assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],1, transact={"from": w3.eth.accounts[0]}) == 0) + +def test_mint_one_burn_one(erc1155, w3, assert_tx_failed): + # check the balance from an owner and non-owner account + + erc1155.mint(w3.eth.accounts[0], 21, 1, '', transact={"from": w3.eth.accounts[0]}) + + assert (lambda: erc1155.balanceOf(w3.eth.accounts[0],21, transact={"from": w3.eth.accounts[0]}) == 1) + assert (lambda: erc1155.balanceOf(w3.eth.accounts[0],21, transact={"from": w3.eth.accounts[1]}) == 1) + + # try and burn an item we don't control + assert_tx_failed(lambda: erc1155.burn(21,1,transact={"from": w3.eth.accounts[3]})) + + # burn an item that contains something we don't own + assert_tx_failed(lambda: erc1155.burn(595,1,transact={"from": w3.eth.accounts[1]})) + + # burn ah item passing a higher amount than we own + assert_tx_failed(lambda: erc1155.burn(21,500,transact={"from": w3.eth.accounts[1]})) + + erc1155.burn(21,1, transact={"from": w3.eth.accounts[0]}) + + assert (lambda: erc1155.balanceOf(w3.eth.accounts[0],21, transact={"from": w3.eth.accounts[1]}) == 0) + + +def test_mint_batch_burn_batch(erc1155, w3, assert_tx_failed): + # mint NFTs 11-20 + erc1155.mintBatch(w3.eth.accounts[3], mintBatch2, minBatchSetOf10, '',transact={"from": w3.eth.accounts[0]}) + + # check the balance + assert (lambda: erc1155.balanceOfBatch([w3.eth.accounts[1],w3.eth.accounts[1],w3.eth.accounts[1]],[1,2,3], transact={"from": w3.eth.accounts[1]}) == [1,1,1]) + + # try and burn a batch we don't control + assert_tx_failed(lambda: erc1155.burnBatch([11,12],[1,1])) + + # ids and amounts array length not matching + assert_tx_failed(lambda: erc1155.burnBatch([1,2,3],[1,1], transact={"from": w3.eth.accounts[1]})) + + # burn a batch that contains something we don't own + assert_tx_failed(lambda: erc1155.burnBatch([2,3,595],[1,1,1],transact={"from": w3.eth.accounts[1]})) + + # burn a batch passing a higher amount than we own + assert_tx_failed(lambda: erc1155.burnBatch([1,2,3],[1,500,1],transact={"from": w3.eth.accounts[1]})) + + # burn existing + erc1155.burnBatch([11,12],[1,1],transact={"from": w3.eth.accounts[3]}) + + assert (lambda: erc1155.balanceOfBatch([w3.eth.accounts[1],w3.eth.accounts[1],w3.eth.accounts[1]],[11,12,13], transact={"from": w3.eth.accounts[1]}) == [0,0,1]) + + # burn again, should revert + assert_tx_failed(lambda: erc1155.burnBatch([1,2],[1,1],transact={"from": w3.eth.accounts[1]})) + + assert (lambda: erc1155.balanceOfBatch([w3.eth.accounts[1],w3.eth.accounts[1],w3.eth.accounts[1]],[1,2,3], transact={"from": w3.eth.accounts[1]}) == [0,0,1]) + + +def test_approval_functions(erc1155, w3, test_mint_batch, assert_tx_failed): + + # self-approval by the owner + assert_tx_failed(lambda: erc1155.setApprovalForAll(w3.eth.accounts[5],w3.eth.accounts[5],True, transact={"from": w3.eth.accounts[5]})) + + # let's approve and operator for somebody else's account + assert_tx_failed(lambda: erc1155.setApprovalForAll(w3.eth.accounts[0],w3.eth.accounts[5],True, transact={"from": w3.eth.accounts[3]})) + + # set approval correctly + erc1155.setApprovalForAll(w3.eth.accounts[0],w3.eth.accounts[5],True) + + # check approval + erc1155.isApprovedForAll(w3.eth.accounts[0],w3.eth.accounts[5]) + + # remove approval + erc1155.setApprovalForAll(w3.eth.accounts[0],w3.eth.accounts[5],False) + + +def test_max_batch_size_violation(erc1155, w3, assert_tx_failed): + TOTAL_BAD_BATCH = 200 + ids = [] + amounts = [] + for i in range(1,TOTAL_BAD_BATCH): + ids.append(i) + amounts.append(1) + + assert_tx_failed(lambda: erc1155.mintBatch(w3.eth.accounts[1], ids, amounts, '', transact={"from": w3.eth.accounts[0]})) + + +# Transferring back and forth + +def test_ownership_functions(erc1155, w3, assert_tx_failed,tester): + owner, a1, a2 = w3.eth.accounts[0:3] + print(owner,a1,a2) + print('___owner___', erc1155.owner()) + # change owner from account 0 to account 1 and back + + assert erc1155.owner() == owner + assert_tx_failed(lambda: erc1155.transferOwnership(w3.eth.accounts[1], transact={"from": a2})) + + # try to transfer ownership to current owner + assert_tx_failed(lambda: erc1155.transferOwnership(w3.eth.accounts[0])) + # try to transfer ownership to ZERO ADDRESS + assert_tx_failed(lambda: erc1155.transferOwnership("0x0000000000000000000000000000000000000000")) + + # Transfer ownership to account 1 + erc1155.transferOwnership(w3.eth.accounts[1]) + assert (lambda: erc1155.owner() == w3.eth.accounts[1]) + +def test_renounce_ownership(erc1155, w3, assert_tx_failed): + + assert erc1155.owner() == w3.eth.accounts[0] + # try to transfer ownership from non-owner account + assert_tx_failed(lambda: erc1155.renounceOwnership(transact={"from": w3.eth.accounts[2]})) + + erc1155.renounceOwnership(transact={"from": w3.eth.accounts[0]}) + + assert erc1155.owner() == None \ No newline at end of file diff --git a/tests/examples/tokens/test_erc1155ownable_ETHtester.py b/tests/examples/tokens/test_erc1155ownable_ETHtester.py deleted file mode 100644 index 58f10f089f..0000000000 --- a/tests/examples/tokens/test_erc1155ownable_ETHtester.py +++ /dev/null @@ -1,316 +0,0 @@ -import pytest -# ERC1155 ownable, opensea compatible tests -# @author Dr. Pixel (github: @Doc-Pixel) - -# constants - contract deployment -CONTRACT_NAME = 'TEST 1155' -CONTRACT_SYMBOL= 'T1155' -CONTRACT_URI = 'https://mydomain.io/NFTdata/{id}' -NEW_CONTRACT_URI = 'https://mynewdomain.io/NFTdata/{id}' -ERC165_INTERFACE_ID = '0x01ffc9a7' -ERC1155_INTERFACE_ID = '0xd9b67a26' -ERC1155_INTERFACE_ID_METADATA = '0x0e89341c' -ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" - -# minting test lists -mintBatch = [1,2,3,4,5,6,7,8,9,10] -mintBatch2 = [11,12,13,14,15,16,17,19,19,20] -minBatchSetOf10 = [1,1,1,1,1,1,1,1,1,1] -mintConflictBatch = [1,2,3] - -@pytest.fixture -def NFT_contract(get_contract, w3): - owner, a1, a2 = w3.eth.accounts[0:3] - with open("examples/tokens/ERC1155ownable.vy") as f: - code = f.read() - c = get_contract(code, *[CONTRACT_NAME, CONTRACT_SYMBOL, CONTRACT_URI]) - return c - -##### test fixtures ##### - -@pytest.fixture -def test_mint(NFT_contract, w3, assert_tx_failed): - NFT_contract.mint(w3.eth.accounts[1], 1, 1, '') - NFT_contract.mint(w3.eth.accounts[1], 2, 1, '') - NFT_contract.mint(w3.eth.accounts[1], 3, 1, '') - - assert_tx_failed(lambda: NFT_contract.mint(w3.eth.accounts[1], 4, 1, '', transact={"from": w3.eth.accounts[3]})) - assert_tx_failed(lambda: NFT_contract.mint(ZERO_ADDRESS, 4, 1, '', transact={"from": w3.eth.accounts[0]})) - - assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],1) == 1) - assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],2) == 1) - assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],3) == 1) - - # check ZERO_ADDRESS balance (should fail) - assert_tx_failed(lambda: NFT_contract.balanceOf(ZERO_ADDRESS,3) == 1) - - -@pytest.fixture -def test_mint_batch(NFT_contract, w3, assert_tx_failed): - NFT_contract.mintBatch(w3.eth.accounts[1], mintBatch, minBatchSetOf10, '') - NFT_contract.mintBatch(w3.eth.accounts[3], mintBatch2, minBatchSetOf10, '') - # assert_tx_failed(lambda: NFT_contract.mintBatch(w3.eth.accounts[1], mintBatch, minBatchSetOf10, '', transact={"from": w3.eth.accounts[2]})) - assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],1) == 1) - assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],2) == 1) - assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],3) == 1) - assert_tx_failed(lambda: NFT_contract.mintBatch(ZERO_ADDRESS, mintBatch, minBatchSetOf10, '')) - assert_tx_failed(lambda: NFT_contract.mintBatch(w3.eth.accounts[1], [1,2,3], [1,1], '')) - - -##### tests ##### - -def test_initial_state(NFT_contract): - # Check if the constructor of the contract is set up properly - # and the contract is deployed with the desired variables - - # variables set correctly? - assert NFT_contract.name() == CONTRACT_NAME - assert NFT_contract.symbol() == CONTRACT_SYMBOL - assert NFT_contract.uri() == CONTRACT_URI - - # interfaces set up correctly? - assert NFT_contract.supportsInterface(ERC165_INTERFACE_ID) - assert NFT_contract.supportsInterface(ERC1155_INTERFACE_ID) - assert NFT_contract.supportsInterface(ERC1155_INTERFACE_ID_METADATA) - - -def test_pause(NFT_contract,w3, assert_tx_failed): - # check the pause status, pause, check, unpause, check, with owner and non-owner w3.eth.accounts - # this test will check all the function that should not work when paused. - assert NFT_contract.paused() == False - - # try to pause the contract from a non owner account - assert_tx_failed(lambda: NFT_contract.pause(transact={"from": w3.eth.accounts[1]})) - - # now pause the contract and check status - NFT_contract.pause(transact={"from": w3.eth.accounts[0]}) - assert NFT_contract.paused() == True - - # try pausing a paused contract - assert_tx_failed(lambda: NFT_contract.pause()) - - # try functions that should not work when paused - assert_tx_failed(lambda: NFT_contract.setURI(NEW_CONTRACT_URI)) - - # test burn and burnbatch - assert_tx_failed(lambda: NFT_contract.burn(1,1)) - assert_tx_failed(lambda: NFT_contract.burnBatch([1,2],[1,1])) - - # check mint and mintbatch - assert_tx_failed(lambda: NFT_contract.mint(w3.eth.accounts[1], 1, 1, '', transact={"from": w3.eth.accounts[0]})) - assert_tx_failed(lambda: NFT_contract.mintBatch(w3.eth.accounts[1], mintBatch, minBatchSetOf10, '', transact={"from": w3.eth.accounts[0]})) - - # check safetransferfrom and safebatchtransferfrom - assert_tx_failed(lambda: NFT_contract.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 1, 1, '', transact={"from": w3.eth.accounts[1]})) - assert_tx_failed(lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) - - # check ownership functions - assert_tx_failed(lambda: NFT_contract.transferOwnership(w3.eth.accounts[1])) - assert_tx_failed(lambda: NFT_contract.renounceOwnership()) - - # check approval functions - assert_tx_failed(lambda: NFT_contract.setApprovalForAll(w3.eth.accounts[0],w3.eth.accounts[5],True)) - assert_tx_failed(lambda: NFT_contract.isApprovedForAll(w3.eth.accounts[0],w3.eth.accounts[5])) - - # try and unpause as non-owner - assert_tx_failed(lambda: NFT_contract.unpause(transact={"from": w3.eth.accounts[1]})) - - NFT_contract.unpause(transact={"from": w3.eth.accounts[0]}) - assert NFT_contract.paused() == False - - # try un pausing an unpaused contract - assert_tx_failed(lambda: NFT_contract.unpause()) - - -def test_URI(NFT_contract, w3,assert_tx_failed): - # change contract URI and restore. - assert NFT_contract.uri() == CONTRACT_URI - NFT_contract.setURI(NEW_CONTRACT_URI, transact={"from": w3.eth.accounts[1]}) - assert NFT_contract.uri() == NEW_CONTRACT_URI - assert NFT_contract.uri() != CONTRACT_URI - NFT_contract.setURI(CONTRACT_URI, transact={"from": w3.eth.accounts[1]}) - assert NFT_contract.uri() != NEW_CONTRACT_URI - assert NFT_contract.uri() == CONTRACT_URI - - assert_tx_failed(lambda: NFT_contract.setURI(CONTRACT_URI)) - -def test_safeTransferFrom_balanceOf_single(NFT_contract, w3, test_mint, assert_tx_failed): - # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture - NFT_contract.mint(w3.eth.accounts[1], 4, 1, '', transact={"from": w3.eth.accounts[0]}) - assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],4, transact={"from": w3.eth.accounts[1]}) == 1) - - # transfer by non-owner - assert_tx_failed(lambda: NFT_contract.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 4, 1, '', transact={"from": w3.eth.accounts[2]})) - - # transfer to zero address - assert_tx_failed(lambda: NFT_contract.safeTransferFrom(w3.eth.accounts[1], ZERO_ADDRESS, 4, 1, '', transact={"from": w3.eth.accounts[1]})) - - # transfer to self - assert_tx_failed(lambda: NFT_contract.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[1], 4, 1, '', transact={"from": w3.eth.accounts[1]})) - - # transfer more than owned - assert_tx_failed(lambda: NFT_contract.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 4, 500, '', transact={"from": w3.eth.accounts[1]})) - - # transfer item not owned / not existing - assert_tx_failed(lambda: NFT_contract.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 500, 1, '', transact={"from": w3.eth.accounts[1]})) - - NFT_contract.mint(w3.eth.accounts[1], 21, 1, '', transact={"from": w3.eth.accounts[0]}) - NFT_contract.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 21, 1, '', transact={"from": w3.eth.accounts[1]}) - - assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[2],1, transact={"from": w3.eth.accounts[0]}) == 1) - - # try to transfer item again - assert_tx_failed(lambda: NFT_contract.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 21, 1, '', transact={"from": w3.eth.accounts[1]})) - assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],1, {"from": w3.eth.w3.eth.accounts[0]}) == 0) - - -# TODO: mint 20 NFTs [1:20] and check the balance for each -def test_mintBatch_balanceOf(NFT_contract, w3, test_mint_batch, assert_tx_failed): - # Use the mint three fixture to mint the tokens. - # this test checks the balances of this test - for i in range (1,10): - assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1], i, transact={"from": w3.eth.accounts[1]}) == 1) - assert_tx_failed(lambda: NFT_contract.balanceOf(ZERO_ADDRESS, i, transact={"from": w3.eth.accounts[1]}) == 1) - -def test_safeBatchTransferFrom_balanceOf_batch(NFT_contract, w3, test_mint_batch, assert_tx_failed): - # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture - - NFT_contract.balanceOf(w3.eth.accounts[1],1, transact={"from": w3.eth.accounts[1]}) == 1 - - - # try to transfer item from non item owner account - assert_tx_failed(lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[2]})) - - # try to transfer item to zero address - assert_tx_failed(lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], ZERO_ADDRESS, [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) - - # try to transfer item to self - assert_tx_failed(lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[1], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) - - # try to transfer more items than we own - assert_tx_failed(lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,125,1], '', transact={"from": w3.eth.accounts[1]})) - - # mismatched item and amounts - assert_tx_failed(lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1], '', transact={"from": w3.eth.accounts[1]})) - - # try to transfer nonexisting item - assert_tx_failed(lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,500], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) - assert (lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) - - # try to transfer again, our balances are zero now, should fail - assert_tx_failed(lambda: NFT_contract.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) - assert_tx_failed(lambda: NFT_contract.balanceOfBatch([w3.eth.accounts[2],w3.eth.accounts[2],w3.eth.accounts[2]],[1,2], transact={"from": w3.eth.accounts[0]}) == [1,1,1]) - - assert (lambda: NFT_contract.balanceOfBatch([w3.eth.accounts[2],w3.eth.accounts[2],w3.eth.accounts[2]],[1,2,3], transact={"from": w3.eth.accounts[0]}) == [1,1,1]) - assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[1],1, transact={"from": w3.eth.accounts[0]}) == 0) - -def test_mint_one_burn_one(NFT_contract, w3, assert_tx_failed): - # check the balance from an owner and non-owner account - - NFT_contract.mint(w3.eth.accounts[0], 21, 1, '', transact={"from": w3.eth.accounts[0]}) - - assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[0],21, transact={"from": w3.eth.accounts[0]}) == 1) - assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[0],21, transact={"from": w3.eth.accounts[1]}) == 1) - - # try and burn an item we don't control - assert_tx_failed(lambda: NFT_contract.burn(21,1,transact={"from": w3.eth.accounts[3]})) - - # burn an item that contains something we don't own - assert_tx_failed(lambda: NFT_contract.burn(595,1,transact={"from": w3.eth.accounts[1]})) - - # burn ah item passing a higher amount than we own - assert_tx_failed(lambda: NFT_contract.burn(21,500,transact={"from": w3.eth.accounts[1]})) - - NFT_contract.burn(21,1, transact={"from": w3.eth.accounts[0]}) - - assert (lambda: NFT_contract.balanceOf(w3.eth.accounts[0],21, transact={"from": w3.eth.accounts[1]}) == 0) - - -def test_mint_batch_burn_batch(NFT_contract, w3, assert_tx_failed): - # mint NFTs 11-20 - NFT_contract.mintBatch(w3.eth.accounts[3], mintBatch2, minBatchSetOf10, '',transact={"from": w3.eth.accounts[0]}) - - # check the balance - assert (lambda: NFT_contract.balanceOfBatch([w3.eth.accounts[1],w3.eth.accounts[1],w3.eth.accounts[1]],[1,2,3], transact={"from": w3.eth.accounts[1]}) == [1,1,1]) - - # try and burn a batch we don't control - assert_tx_failed(lambda: NFT_contract.burnBatch([11,12],[1,1])) - - # ids and amounts array length not matching - assert_tx_failed(lambda: NFT_contract.burnBatch([1,2,3],[1,1], transact={"from": w3.eth.accounts[1]})) - - # burn a batch that contains something we don't own - assert_tx_failed(lambda: NFT_contract.burnBatch([2,3,595],[1,1,1],transact={"from": w3.eth.accounts[1]})) - - # burn a batch passing a higher amount than we own - assert_tx_failed(lambda: NFT_contract.burnBatch([1,2,3],[1,500,1],transact={"from": w3.eth.accounts[1]})) - - # burn existing - NFT_contract.burnBatch([11,12],[1,1],transact={"from": w3.eth.accounts[3]}) - - assert (lambda: NFT_contract.balanceOfBatch([w3.eth.accounts[1],w3.eth.accounts[1],w3.eth.accounts[1]],[11,12,13], transact={"from": w3.eth.accounts[1]}) == [0,0,1]) - - # burn again, should revert - assert_tx_failed(lambda: NFT_contract.burnBatch([1,2],[1,1],transact={"from": w3.eth.accounts[1]})) - - assert (lambda: NFT_contract.balanceOfBatch([w3.eth.accounts[1],w3.eth.accounts[1],w3.eth.accounts[1]],[1,2,3], transact={"from": w3.eth.accounts[1]}) == [0,0,1]) - - -def test_approval_functions(NFT_contract, w3, test_mint_batch, assert_tx_failed): - - # self-approval by the owner - assert_tx_failed(lambda: NFT_contract.setApprovalForAll(w3.eth.accounts[5],w3.eth.accounts[5],True, transact={"from": w3.eth.accounts[5]})) - - # let's approve and operator for somebody else's account - assert_tx_failed(lambda: NFT_contract.setApprovalForAll(w3.eth.accounts[0],w3.eth.accounts[5],True, transact={"from": w3.eth.accounts[3]})) - - # set approval correctly - NFT_contract.setApprovalForAll(w3.eth.accounts[0],w3.eth.accounts[5],True) - - # check approval - NFT_contract.isApprovedForAll(w3.eth.accounts[0],w3.eth.accounts[5]) - - # remove approval - NFT_contract.setApprovalForAll(w3.eth.accounts[0],w3.eth.accounts[5],False) - - -def test_max_batch_size_violation(NFT_contract, w3, assert_tx_failed): - TOTAL_BAD_BATCH = 200 - ids = [] - amounts = [] - for i in range(1,TOTAL_BAD_BATCH): - ids.append(i) - amounts.append(1) - - assert_tx_failed(lambda: NFT_contract.mintBatch(w3.eth.accounts[1], ids, amounts, '', transact={"from": w3.eth.accounts[0]})) - - -# Transferring back and forth - -def test_ownership_functions(NFT_contract, w3, assert_tx_failed,tester): - owner, a1, a2 = w3.eth.accounts[0:3] - print(owner,a1,a2) - print('___owner___', NFT_contract.owner()) - # change owner from account 0 to account 1 and back - - assert NFT_contract.owner() == owner - assert_tx_failed(lambda: NFT_contract.transferOwnership(w3.eth.accounts[1], transact={"from": a2})) - - # try to transfer ownership to current owner - assert_tx_failed(lambda: NFT_contract.transferOwnership(w3.eth.accounts[0])) - # try to transfer ownership to ZERO ADDRESS - assert_tx_failed(lambda: NFT_contract.transferOwnership("0x0000000000000000000000000000000000000000")) - - # Transfer ownership to account 1 - NFT_contract.transferOwnership(w3.eth.accounts[1]) - assert (lambda: NFT_contract.owner() == w3.eth.accounts[1]) - -def test_renounce_ownership(NFT_contract, w3, assert_tx_failed): - - assert NFT_contract.owner() == w3.eth.accounts[0] - # try to transfer ownership from non-owner account - assert_tx_failed(lambda: NFT_contract.renounceOwnership(transact={"from": w3.eth.accounts[2]})) - - NFT_contract.renounceOwnership(transact={"from": w3.eth.accounts[0]}) - - assert NFT_contract.owner() == None \ No newline at end of file From 9ff63bbb25b59b852165a52a364cdd42480b76e9 Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Wed, 27 Apr 2022 15:42:43 -0700 Subject: [PATCH 13/29] interface fix / callback bytes constant --- examples/tokens/ERC1155ownable.vy | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index 80c082e811..0bea7b46bc 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -11,6 +11,9 @@ from vyper.interfaces import ERC165 # maximum items in a batch call. Set to 128, to be determined what the practical limits are. BATCH_SIZE: constant(uint256) = 128 +# callback number of bytes +CALLBACK_NUMBYTES: constant(uint256) = 4096 + # URI length set to 1024. MAX_URI_LENGTH: constant(uint256) = 1024 @@ -107,8 +110,8 @@ event URI: implements: ERC165 interface IERC1155Receiver: - def onERC1155Received(operator: address, sender: address, receiver: address, id: uint256, _value: uint256, data: bytes32) -> bytes32: payable - def onERC1155BatchReceived(operator: address, sender: address, receiver: address, _ids: DynArray[uint256, BATCH_SIZE], _amounts: DynArray[uint256, BATCH_SIZE], data: bytes32) -> bytes32: payable + def onERC1155Received(operator: address, sender: address, id: uint256, _value: uint256, data: bytes32) -> bytes32: payable + def onERC1155BatchReceived(operator: address, sender: address, _ids: DynArray[uint256, CALLBACK_NUMBYTES], _amounts: DynArray[uint256, BATCH_SIZE], data: bytes32) -> bytes32: payable interface IERC1155MetadataURI: def uri(id: uint256) -> String[MAX_URI_LENGTH]: view From 241b0c375eab45b4294e03b780f7920ff6f02fa0 Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Thu, 28 Apr 2022 08:47:45 -0700 Subject: [PATCH 14/29] Ownership test assertion to ZERO_ADDRESS --- tests/examples/tokens/test_erc1155.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/examples/tokens/test_erc1155.py b/tests/examples/tokens/test_erc1155.py index 54602410e3..1f0c83a91b 100644 --- a/tests/examples/tokens/test_erc1155.py +++ b/tests/examples/tokens/test_erc1155.py @@ -313,4 +313,4 @@ def test_renounce_ownership(erc1155, w3, assert_tx_failed): erc1155.renounceOwnership(transact={"from": w3.eth.accounts[0]}) - assert erc1155.owner() == None \ No newline at end of file + assert (lambda: erc1155.owner() == ZERO_ADDRESS) \ No newline at end of file From 72f9bff4cce281c96836236cc6ebdbc1ec230b4f Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Fri, 29 Apr 2022 12:31:42 -0700 Subject: [PATCH 15/29] reworked uri part, simplified tests --- examples/tokens/ERC1155ownable.vy | 16 +- tests/examples/tokens/test_erc1155.py | 202 ++++++++++++++------------ 2 files changed, 117 insertions(+), 101 deletions(-) diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index 0bea7b46bc..ef39446019 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -26,7 +26,7 @@ owner: public(address) paused: public(bool) # the contracts URI to find the metadata -uri: public(String[MAX_URI_LENGTH]) +_uri: String[MAX_URI_LENGTH] # NFT marketplace compatibility name: public(String[128]) @@ -129,7 +129,7 @@ def __init__(name: String[128], symbol: String[16], uri: String[1024]): self.symbol = symbol self.paused = False self.owner = msg.sender - self.uri = uri + self._uri = uri ## contract status ## @external @@ -351,16 +351,22 @@ def safeBatchTransferFrom(sender: address, receiver: address, ids: DynArray[uint log TransferBatch(operator, sender, receiver, ids, amounts) -# misc # +# URI # @external def setURI(uri: String[MAX_URI_LENGTH]): # @dev set the URI for the contract # @param uri the new uri for the contract assert not self.paused, "The contract has been paused" - assert self.uri != uri, "new and current URI are identical" - self.uri = uri + assert self._uri != uri, "new and current URI are identical" + self._uri = uri log URI(uri, 0) +@external +def uri(id: uint256) -> String[MAX_URI_LENGTH]: + # @dev retrieve the uri, this function can optionally be extended to return dynamic uris. out of scope. + # @param id NFT ID to retrieve the uri for. + return self._uri + @pure @external def supportsInterface(interfaceId: bytes4) -> bool: diff --git a/tests/examples/tokens/test_erc1155.py b/tests/examples/tokens/test_erc1155.py index 1f0c83a91b..0919a0a258 100644 --- a/tests/examples/tokens/test_erc1155.py +++ b/tests/examples/tokens/test_erc1155.py @@ -20,7 +20,7 @@ @pytest.fixture def erc1155(get_contract, w3): - owner, a1, a2 = w3.eth.accounts[0:3] + owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] with open("examples/tokens/ERC1155ownable.vy") as f: code = f.read() c = get_contract(code, *[CONTRACT_NAME, CONTRACT_SYMBOL, CONTRACT_URI]) @@ -30,16 +30,17 @@ def erc1155(get_contract, w3): @pytest.fixture def test_mint(erc1155, w3, assert_tx_failed): - erc1155.mint(w3.eth.accounts[1], 1, 1, '') - erc1155.mint(w3.eth.accounts[1], 2, 1, '') - erc1155.mint(w3.eth.accounts[1], 3, 1, '') + owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] + erc1155.mint(a1, 1, 1, '') + erc1155.mint(a1, 2, 1, '') + erc1155.mint(a1, 3, 1, '') - assert_tx_failed(lambda: erc1155.mint(w3.eth.accounts[1], 4, 1, '', transact={"from": w3.eth.accounts[3]})) - assert_tx_failed(lambda: erc1155.mint(ZERO_ADDRESS, 4, 1, '', transact={"from": w3.eth.accounts[0]})) + assert_tx_failed(lambda: erc1155.mint(a1, 4, 1, '', transact={"from": a3})) + assert_tx_failed(lambda: erc1155.mint(ZERO_ADDRESS, 4, 1, '', transact={"from": owner})) - assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],1) == 1) - assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],2) == 1) - assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],3) == 1) + assert (lambda: erc1155.balanceOf(a1,1) == 1) + assert (lambda: erc1155.balanceOf(a1,2) == 1) + assert (lambda: erc1155.balanceOf(a1,3) == 1) # check ZERO_ADDRESS balance (should fail) assert_tx_failed(lambda: erc1155.balanceOf(ZERO_ADDRESS,3) == 1) @@ -47,14 +48,15 @@ def test_mint(erc1155, w3, assert_tx_failed): @pytest.fixture def test_mint_batch(erc1155, w3, assert_tx_failed): - erc1155.mintBatch(w3.eth.accounts[1], mintBatch, minBatchSetOf10, '') - erc1155.mintBatch(w3.eth.accounts[3], mintBatch2, minBatchSetOf10, '') - # assert_tx_failed(lambda: erc1155.mintBatch(w3.eth.accounts[1], mintBatch, minBatchSetOf10, '', transact={"from": w3.eth.accounts[2]})) - assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],1) == 1) - assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],2) == 1) - assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],3) == 1) + owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] + erc1155.mintBatch(a1, mintBatch, minBatchSetOf10, '') + erc1155.mintBatch(a3, mintBatch2, minBatchSetOf10, '') + # assert_tx_failed(lambda: erc1155.mintBatch(a1, mintBatch, minBatchSetOf10, '', transact={"from": a2})) + assert (lambda: erc1155.balanceOf(a1,1) == 1) + assert (lambda: erc1155.balanceOf(a1,2) == 1) + assert (lambda: erc1155.balanceOf(a1,3) == 1) assert_tx_failed(lambda: erc1155.mintBatch(ZERO_ADDRESS, mintBatch, minBatchSetOf10, '')) - assert_tx_failed(lambda: erc1155.mintBatch(w3.eth.accounts[1], [1,2,3], [1,1], '')) + assert_tx_failed(lambda: erc1155.mintBatch(a1, [1,2,3], [1,1], '')) ##### tests ##### @@ -66,7 +68,7 @@ def test_initial_state(erc1155): # variables set correctly? assert erc1155.name() == CONTRACT_NAME assert erc1155.symbol() == CONTRACT_SYMBOL - assert erc1155.uri() == CONTRACT_URI + assert erc1155.uri(0) == CONTRACT_URI # interfaces set up correctly? assert erc1155.supportsInterface(ERC165_INTERFACE_ID) @@ -75,15 +77,16 @@ def test_initial_state(erc1155): def test_pause(erc1155,w3, assert_tx_failed): + owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # check the pause status, pause, check, unpause, check, with owner and non-owner w3.eth.accounts # this test will check all the function that should not work when paused. assert erc1155.paused() == False # try to pause the contract from a non owner account - assert_tx_failed(lambda: erc1155.pause(transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.pause(transact={"from": a1})) # now pause the contract and check status - erc1155.pause(transact={"from": w3.eth.accounts[0]}) + erc1155.pause(transact={"from": owner}) assert erc1155.paused() == True # try pausing a paused contract @@ -97,25 +100,25 @@ def test_pause(erc1155,w3, assert_tx_failed): assert_tx_failed(lambda: erc1155.burnBatch([1,2],[1,1])) # check mint and mintbatch - assert_tx_failed(lambda: erc1155.mint(w3.eth.accounts[1], 1, 1, '', transact={"from": w3.eth.accounts[0]})) - assert_tx_failed(lambda: erc1155.mintBatch(w3.eth.accounts[1], mintBatch, minBatchSetOf10, '', transact={"from": w3.eth.accounts[0]})) + assert_tx_failed(lambda: erc1155.mint(a1, 1, 1, '', transact={"from": owner})) + assert_tx_failed(lambda: erc1155.mintBatch(a1, mintBatch, minBatchSetOf10, '', transact={"from": owner})) # check safetransferfrom and safebatchtransferfrom - assert_tx_failed(lambda: erc1155.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 1, 1, '', transact={"from": w3.eth.accounts[1]})) - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 1, 1, '', transact={"from": a1})) + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [1,2,3], [1,1,1], '', transact={"from": a1})) # check ownership functions - assert_tx_failed(lambda: erc1155.transferOwnership(w3.eth.accounts[1])) + assert_tx_failed(lambda: erc1155.transferOwnership(a1)) assert_tx_failed(lambda: erc1155.renounceOwnership()) # check approval functions - assert_tx_failed(lambda: erc1155.setApprovalForAll(w3.eth.accounts[0],w3.eth.accounts[5],True)) - assert_tx_failed(lambda: erc1155.isApprovedForAll(w3.eth.accounts[0],w3.eth.accounts[5])) + assert_tx_failed(lambda: erc1155.setApprovalForAll(owner,a5,True)) + assert_tx_failed(lambda: erc1155.isApprovedForAll(owner,a5)) # try and unpause as non-owner - assert_tx_failed(lambda: erc1155.unpause(transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.unpause(transact={"from": a1})) - erc1155.unpause(transact={"from": w3.eth.accounts[0]}) + erc1155.unpause(transact={"from": owner}) assert erc1155.paused() == False # try un pausing an unpaused contract @@ -123,158 +126,165 @@ def test_pause(erc1155,w3, assert_tx_failed): def test_URI(erc1155, w3,assert_tx_failed): + owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # change contract URI and restore. - assert erc1155.uri() == CONTRACT_URI - erc1155.setURI(NEW_CONTRACT_URI, transact={"from": w3.eth.accounts[1]}) - assert erc1155.uri() == NEW_CONTRACT_URI - assert erc1155.uri() != CONTRACT_URI - erc1155.setURI(CONTRACT_URI, transact={"from": w3.eth.accounts[1]}) - assert erc1155.uri() != NEW_CONTRACT_URI - assert erc1155.uri() == CONTRACT_URI + assert erc1155.uri(0) == CONTRACT_URI + erc1155.setURI(NEW_CONTRACT_URI, transact={"from": a1}) + assert erc1155.uri(0) == NEW_CONTRACT_URI + assert erc1155.uri(0) != CONTRACT_URI + erc1155.setURI(CONTRACT_URI, transact={"from": a1}) + assert erc1155.uri(0) != NEW_CONTRACT_URI + assert erc1155.uri(0) == CONTRACT_URI assert_tx_failed(lambda: erc1155.setURI(CONTRACT_URI)) def test_safeTransferFrom_balanceOf_single(erc1155, w3, test_mint, assert_tx_failed): + owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture - erc1155.mint(w3.eth.accounts[1], 4, 1, '', transact={"from": w3.eth.accounts[0]}) - assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],4, transact={"from": w3.eth.accounts[1]}) == 1) + erc1155.mint(a1, 4, 1, '', transact={"from": owner}) + assert (lambda: erc1155.balanceOf(a1,4, transact={"from": a1}) == 1) # transfer by non-owner - assert_tx_failed(lambda: erc1155.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 4, 1, '', transact={"from": w3.eth.accounts[2]})) + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 4, 1, '', transact={"from": a2})) # transfer to zero address - assert_tx_failed(lambda: erc1155.safeTransferFrom(w3.eth.accounts[1], ZERO_ADDRESS, 4, 1, '', transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, ZERO_ADDRESS, 4, 1, '', transact={"from": a1})) # transfer to self - assert_tx_failed(lambda: erc1155.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[1], 4, 1, '', transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a1, 4, 1, '', transact={"from": a1})) # transfer more than owned - assert_tx_failed(lambda: erc1155.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 4, 500, '', transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 4, 500, '', transact={"from": a1})) # transfer item not owned / not existing - assert_tx_failed(lambda: erc1155.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 500, 1, '', transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 500, 1, '', transact={"from": a1})) - erc1155.mint(w3.eth.accounts[1], 21, 1, '', transact={"from": w3.eth.accounts[0]}) - erc1155.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 21, 1, '', transact={"from": w3.eth.accounts[1]}) + erc1155.mint(a1, 21, 1, '', transact={"from": owner}) + erc1155.safeTransferFrom(a1, a2, 21, 1, '', transact={"from": a1}) - assert (lambda: erc1155.balanceOf(w3.eth.accounts[2],1, transact={"from": w3.eth.accounts[0]}) == 1) + assert (lambda: erc1155.balanceOf(a2,1, transact={"from": owner}) == 1) # try to transfer item again - assert_tx_failed(lambda: erc1155.safeTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], 21, 1, '', transact={"from": w3.eth.accounts[1]})) - assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],1, {"from": w3.eth.w3.eth.accounts[0]}) == 0) + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 21, 1, '', transact={"from": a1})) + assert (lambda: erc1155.balanceOf(a1,1, {"from": w3.eth.owner}) == 0) # TODO: mint 20 NFTs [1:20] and check the balance for each def test_mintBatch_balanceOf(erc1155, w3, test_mint_batch, assert_tx_failed): + owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # Use the mint three fixture to mint the tokens. # this test checks the balances of this test for i in range (1,10): - assert (lambda: erc1155.balanceOf(w3.eth.accounts[1], i, transact={"from": w3.eth.accounts[1]}) == 1) - assert_tx_failed(lambda: erc1155.balanceOf(ZERO_ADDRESS, i, transact={"from": w3.eth.accounts[1]}) == 1) + assert (lambda: erc1155.balanceOf(a1, i, transact={"from": a1}) == 1) + assert_tx_failed(lambda: erc1155.balanceOf(ZERO_ADDRESS, i, transact={"from": a1}) == 1) def test_safeBatchTransferFrom_balanceOf_batch(erc1155, w3, test_mint_batch, assert_tx_failed): - # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture + owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] - erc1155.balanceOf(w3.eth.accounts[1],1, transact={"from": w3.eth.accounts[1]}) == 1 + # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture + erc1155.balanceOf(a1,1, transact={"from": a1}) == 1 # try to transfer item from non item owner account - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[2]})) + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [1,2,3], [1,1,1], '', transact={"from": a2})) # try to transfer item to zero address - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], ZERO_ADDRESS, [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, ZERO_ADDRESS, [1,2,3], [1,1,1], '', transact={"from": a1})) # try to transfer item to self - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[1], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a1, [1,2,3], [1,1,1], '', transact={"from": a1})) # try to transfer more items than we own - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,125,1], '', transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [1,2,3], [1,125,1], '', transact={"from": a1})) # mismatched item and amounts - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1], '', transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [1,2,3], [1,1], '', transact={"from": a1})) # try to transfer nonexisting item - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,500], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) - assert (lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [1,2,500], [1,1,1], '', transact={"from": a1})) + assert (lambda: erc1155.safeBatchTransferFrom(a1, a2, [1,2,3], [1,1,1], '', transact={"from": a1})) # try to transfer again, our balances are zero now, should fail - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(w3.eth.accounts[1], w3.eth.accounts[2], [1,2,3], [1,1,1], '', transact={"from": w3.eth.accounts[1]})) - assert_tx_failed(lambda: erc1155.balanceOfBatch([w3.eth.accounts[2],w3.eth.accounts[2],w3.eth.accounts[2]],[1,2], transact={"from": w3.eth.accounts[0]}) == [1,1,1]) + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [1,2,3], [1,1,1], '', transact={"from": a1})) + assert_tx_failed(lambda: erc1155.balanceOfBatch([a2,a2,a2],[1,2], transact={"from": owner}) == [1,1,1]) - assert (lambda: erc1155.balanceOfBatch([w3.eth.accounts[2],w3.eth.accounts[2],w3.eth.accounts[2]],[1,2,3], transact={"from": w3.eth.accounts[0]}) == [1,1,1]) - assert (lambda: erc1155.balanceOf(w3.eth.accounts[1],1, transact={"from": w3.eth.accounts[0]}) == 0) + assert (lambda: erc1155.balanceOfBatch([a2,a2,a2],[1,2,3], transact={"from": owner}) == [1,1,1]) + assert (lambda: erc1155.balanceOf(a1,1, transact={"from": owner}) == 0) def test_mint_one_burn_one(erc1155, w3, assert_tx_failed): - # check the balance from an owner and non-owner account + owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] - erc1155.mint(w3.eth.accounts[0], 21, 1, '', transact={"from": w3.eth.accounts[0]}) + # check the balance from an owner and non-owner account + erc1155.mint(owner, 21, 1, '', transact={"from": owner}) - assert (lambda: erc1155.balanceOf(w3.eth.accounts[0],21, transact={"from": w3.eth.accounts[0]}) == 1) - assert (lambda: erc1155.balanceOf(w3.eth.accounts[0],21, transact={"from": w3.eth.accounts[1]}) == 1) + assert (lambda: erc1155.balanceOf(owner,21, transact={"from": owner}) == 1) + assert (lambda: erc1155.balanceOf(owner,21, transact={"from": a1}) == 1) # try and burn an item we don't control - assert_tx_failed(lambda: erc1155.burn(21,1,transact={"from": w3.eth.accounts[3]})) + assert_tx_failed(lambda: erc1155.burn(21,1,transact={"from": a3})) # burn an item that contains something we don't own - assert_tx_failed(lambda: erc1155.burn(595,1,transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.burn(595,1,transact={"from": a1})) # burn ah item passing a higher amount than we own - assert_tx_failed(lambda: erc1155.burn(21,500,transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.burn(21,500,transact={"from": a1})) - erc1155.burn(21,1, transact={"from": w3.eth.accounts[0]}) + erc1155.burn(21,1, transact={"from": owner}) - assert (lambda: erc1155.balanceOf(w3.eth.accounts[0],21, transact={"from": w3.eth.accounts[1]}) == 0) + assert (lambda: erc1155.balanceOf(owner,21, transact={"from": a1}) == 0) def test_mint_batch_burn_batch(erc1155, w3, assert_tx_failed): + owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # mint NFTs 11-20 - erc1155.mintBatch(w3.eth.accounts[3], mintBatch2, minBatchSetOf10, '',transact={"from": w3.eth.accounts[0]}) + erc1155.mintBatch(a3, mintBatch2, minBatchSetOf10, '',transact={"from":owner}) # check the balance - assert (lambda: erc1155.balanceOfBatch([w3.eth.accounts[1],w3.eth.accounts[1],w3.eth.accounts[1]],[1,2,3], transact={"from": w3.eth.accounts[1]}) == [1,1,1]) + assert (lambda: erc1155.balanceOfBatch([a1, a1, a1],[1,2,3], transact={"from": a1}) == [1,1,1]) # try and burn a batch we don't control assert_tx_failed(lambda: erc1155.burnBatch([11,12],[1,1])) # ids and amounts array length not matching - assert_tx_failed(lambda: erc1155.burnBatch([1,2,3],[1,1], transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.burnBatch([1,2,3],[1,1], transact={"from": a1})) # burn a batch that contains something we don't own - assert_tx_failed(lambda: erc1155.burnBatch([2,3,595],[1,1,1],transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.burnBatch([2,3,595],[1,1,1],transact={"from": a1})) # burn a batch passing a higher amount than we own - assert_tx_failed(lambda: erc1155.burnBatch([1,2,3],[1,500,1],transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.burnBatch([1,2,3],[1,500,1],transact={"from": a1})) # burn existing - erc1155.burnBatch([11,12],[1,1],transact={"from": w3.eth.accounts[3]}) + erc1155.burnBatch([11,12],[1,1],transact={"from": a3}) - assert (lambda: erc1155.balanceOfBatch([w3.eth.accounts[1],w3.eth.accounts[1],w3.eth.accounts[1]],[11,12,13], transact={"from": w3.eth.accounts[1]}) == [0,0,1]) + assert (lambda: erc1155.balanceOfBatch([a1,a1,a1],[11,12,13], transact={"from": a1}) == [0,0,1]) # burn again, should revert - assert_tx_failed(lambda: erc1155.burnBatch([1,2],[1,1],transact={"from": w3.eth.accounts[1]})) + assert_tx_failed(lambda: erc1155.burnBatch([1,2],[1,1],transact={"from": a1})) - assert (lambda: erc1155.balanceOfBatch([w3.eth.accounts[1],w3.eth.accounts[1],w3.eth.accounts[1]],[1,2,3], transact={"from": w3.eth.accounts[1]}) == [0,0,1]) + assert (lambda: erc1155.balanceOfBatch([a1,a1,a1],[1,2,3], transact={"from": a1}) == [0,0,1]) def test_approval_functions(erc1155, w3, test_mint_batch, assert_tx_failed): - + owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # self-approval by the owner - assert_tx_failed(lambda: erc1155.setApprovalForAll(w3.eth.accounts[5],w3.eth.accounts[5],True, transact={"from": w3.eth.accounts[5]})) + assert_tx_failed(lambda: erc1155.setApprovalForAll(a5, a5,True, transact={"from": a5})) # let's approve and operator for somebody else's account - assert_tx_failed(lambda: erc1155.setApprovalForAll(w3.eth.accounts[0],w3.eth.accounts[5],True, transact={"from": w3.eth.accounts[3]})) + assert_tx_failed(lambda: erc1155.setApprovalForAll(owner, a5,True, transact={"from": a3})) # set approval correctly - erc1155.setApprovalForAll(w3.eth.accounts[0],w3.eth.accounts[5],True) + erc1155.setApprovalForAll(owner, a5,True) # check approval - erc1155.isApprovedForAll(w3.eth.accounts[0],w3.eth.accounts[5]) + erc1155.isApprovedForAll(owner, a5) # remove approval - erc1155.setApprovalForAll(w3.eth.accounts[0],w3.eth.accounts[5],False) + erc1155.setApprovalForAll(owner,a5,False) def test_max_batch_size_violation(erc1155, w3, assert_tx_failed): + owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] TOTAL_BAD_BATCH = 200 ids = [] amounts = [] @@ -282,35 +292,35 @@ def test_max_batch_size_violation(erc1155, w3, assert_tx_failed): ids.append(i) amounts.append(1) - assert_tx_failed(lambda: erc1155.mintBatch(w3.eth.accounts[1], ids, amounts, '', transact={"from": w3.eth.accounts[0]})) + assert_tx_failed(lambda: erc1155.mintBatch(a1, ids, amounts, '', transact={"from": owner})) # Transferring back and forth def test_ownership_functions(erc1155, w3, assert_tx_failed,tester): - owner, a1, a2 = w3.eth.accounts[0:3] + owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] print(owner,a1,a2) print('___owner___', erc1155.owner()) # change owner from account 0 to account 1 and back assert erc1155.owner() == owner - assert_tx_failed(lambda: erc1155.transferOwnership(w3.eth.accounts[1], transact={"from": a2})) + assert_tx_failed(lambda: erc1155.transferOwnership(a1, transact={"from": a2})) # try to transfer ownership to current owner - assert_tx_failed(lambda: erc1155.transferOwnership(w3.eth.accounts[0])) + assert_tx_failed(lambda: erc1155.transferOwnership(owner)) # try to transfer ownership to ZERO ADDRESS assert_tx_failed(lambda: erc1155.transferOwnership("0x0000000000000000000000000000000000000000")) # Transfer ownership to account 1 - erc1155.transferOwnership(w3.eth.accounts[1]) - assert (lambda: erc1155.owner() == w3.eth.accounts[1]) + erc1155.transferOwnership(a1) + assert (lambda: erc1155.owner() == a1) def test_renounce_ownership(erc1155, w3, assert_tx_failed): - - assert erc1155.owner() == w3.eth.accounts[0] + owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] + assert erc1155.owner() == owner # try to transfer ownership from non-owner account - assert_tx_failed(lambda: erc1155.renounceOwnership(transact={"from": w3.eth.accounts[2]})) + assert_tx_failed(lambda: erc1155.renounceOwnership(transact={"from": a2})) - erc1155.renounceOwnership(transact={"from": w3.eth.accounts[0]}) + erc1155.renounceOwnership(transact={"from": owner}) assert (lambda: erc1155.owner() == ZERO_ADDRESS) \ No newline at end of file From 24b21f862adefa67c3474c92fc9940f8c7169a33 Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Fri, 29 Apr 2022 14:15:19 -0700 Subject: [PATCH 16/29] Fixed all testscript issues --- examples/tokens/ERC1155ownable.vy | 11 ++- tests/examples/tokens/test_erc1155.py | 97 +++++++++++++-------------- 2 files changed, 53 insertions(+), 55 deletions(-) diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index ef39446019..dfb08cbc55 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -1,4 +1,4 @@ -# @version >=0.3.2 +# @version >=0.3.3 # @dev Implementation of ERC-1155 non-fungible token standard # @dev ownable, with approval, OPENSEA compatible (name, symbol) @@ -178,7 +178,7 @@ def renounceOwnership(): log OwnershipTransferred(oldOwner, ZERO_ADDRESS) ## balance ## -@view +# @view @external def balanceOf(account: address, id: uint256) -> uint256: # @dev check the balance for a specific ID and address @@ -191,7 +191,7 @@ def balanceOf(account: address, id: uint256) -> uint256: @external @view -def balanceOfBatch(accounts: DynArray[address, BATCH_SIZE], ids: DynArray[uint256, BATCH_SIZE]) -> DynArray[uint256,BATCH_SIZE]: #uint256[BATCH_SIZE]: +def balanceOfBatch(accounts: DynArray[address, BATCH_SIZE], ids: DynArray[uint256, BATCH_SIZE]) -> DynArray[uint256,BATCH_SIZE]: # uint256[BATCH_SIZE]: # @dev check the balance for an array of specific IDs and addresses # @dev will return an array of balances # @dev Can also be used to check ownership of an ID @@ -367,6 +367,11 @@ def uri(id: uint256) -> String[MAX_URI_LENGTH]: # @param id NFT ID to retrieve the uri for. return self._uri +# @external +# @view +# def owner() -> address: +# return self.owner + @pure @external def supportsInterface(interfaceId: bytes4) -> bool: diff --git a/tests/examples/tokens/test_erc1155.py b/tests/examples/tokens/test_erc1155.py index 0919a0a258..10074a05bf 100644 --- a/tests/examples/tokens/test_erc1155.py +++ b/tests/examples/tokens/test_erc1155.py @@ -19,45 +19,38 @@ mintConflictBatch = [1,2,3] @pytest.fixture -def erc1155(get_contract, w3): +def erc1155(get_contract, w3, assert_tx_failed): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] with open("examples/tokens/ERC1155ownable.vy") as f: code = f.read() c = get_contract(code, *[CONTRACT_NAME, CONTRACT_SYMBOL, CONTRACT_URI]) - return c - -##### test fixtures ##### -@pytest.fixture -def test_mint(erc1155, w3, assert_tx_failed): - owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] - erc1155.mint(a1, 1, 1, '') - erc1155.mint(a1, 2, 1, '') - erc1155.mint(a1, 3, 1, '') + c.mint(a1, 1, 1, '', transact={"from": owner}) + c.mint(a1, 2, 1, '', transact={"from": owner}) + c.mint(a1, 3, 1, '', transact={"from": owner}) + c.mint(a1, 4, 1, '', transact={"from": owner}) - assert_tx_failed(lambda: erc1155.mint(a1, 4, 1, '', transact={"from": a3})) - assert_tx_failed(lambda: erc1155.mint(ZERO_ADDRESS, 4, 1, '', transact={"from": owner})) + assert_tx_failed(lambda: c.mint(a1, 4, 1, '', transact={"from": a3})) + assert_tx_failed(lambda: c.mint(ZERO_ADDRESS, 4, 1, '', transact={"from": owner})) - assert (lambda: erc1155.balanceOf(a1,1) == 1) - assert (lambda: erc1155.balanceOf(a1,2) == 1) - assert (lambda: erc1155.balanceOf(a1,3) == 1) + assert c.balanceOf(a1,1) == 1 + assert c.balanceOf(a1,2) == 1 + assert c.balanceOf(a1,3) == 1 + assert c.balanceOf(a1,4) == 1 # check ZERO_ADDRESS balance (should fail) - assert_tx_failed(lambda: erc1155.balanceOf(ZERO_ADDRESS,3) == 1) - - -@pytest.fixture -def test_mint_batch(erc1155, w3, assert_tx_failed): + assert_tx_failed(lambda: c.balanceOf(ZERO_ADDRESS,3, transact={"from": owner}) == 1) owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] - erc1155.mintBatch(a1, mintBatch, minBatchSetOf10, '') - erc1155.mintBatch(a3, mintBatch2, minBatchSetOf10, '') - # assert_tx_failed(lambda: erc1155.mintBatch(a1, mintBatch, minBatchSetOf10, '', transact={"from": a2})) - assert (lambda: erc1155.balanceOf(a1,1) == 1) - assert (lambda: erc1155.balanceOf(a1,2) == 1) - assert (lambda: erc1155.balanceOf(a1,3) == 1) - assert_tx_failed(lambda: erc1155.mintBatch(ZERO_ADDRESS, mintBatch, minBatchSetOf10, '')) - assert_tx_failed(lambda: erc1155.mintBatch(a1, [1,2,3], [1,1], '')) + c.mintBatch(a1, mintBatch, minBatchSetOf10, '', transact={"from": owner}) + c.mintBatch(a3, mintBatch2, minBatchSetOf10, '', transact={"from": owner}) + # assert_tx_failed(lambda: c.mintBatch(a1, mintBatch, minBatchSetOf10, '', transact={"from": a2})) + assert c.balanceOf(a1,1) == 1 + assert c.balanceOf(a1,2) == 1 + assert c.balanceOf(a1,3) == 1 + assert_tx_failed(lambda: c.mintBatch(ZERO_ADDRESS, mintBatch, minBatchSetOf10, '', transact={"from": owner})) + assert_tx_failed(lambda: c.mintBatch(a1, [1,2,3], [1,1], '', transact={"from": owner})) + return c ##### tests ##### @@ -138,12 +131,10 @@ def test_URI(erc1155, w3,assert_tx_failed): assert_tx_failed(lambda: erc1155.setURI(CONTRACT_URI)) -def test_safeTransferFrom_balanceOf_single(erc1155, w3, test_mint, assert_tx_failed): +def test_safeTransferFrom_balanceOf_single(erc1155, w3, assert_tx_failed): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] - # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture - erc1155.mint(a1, 4, 1, '', transact={"from": owner}) - assert (lambda: erc1155.balanceOf(a1,4, transact={"from": a1}) == 1) + # transfer by non-owner assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 4, 1, '', transact={"from": a2})) @@ -162,23 +153,23 @@ def test_safeTransferFrom_balanceOf_single(erc1155, w3, test_mint, assert_tx_fai erc1155.mint(a1, 21, 1, '', transact={"from": owner}) erc1155.safeTransferFrom(a1, a2, 21, 1, '', transact={"from": a1}) - assert (lambda: erc1155.balanceOf(a2,1, transact={"from": owner}) == 1) + assert erc1155.balanceOf(a2,21) == 1 # try to transfer item again assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 21, 1, '', transact={"from": a1})) - assert (lambda: erc1155.balanceOf(a1,1, {"from": w3.eth.owner}) == 0) + assert erc1155.balanceOf(a1,21) == 0 # TODO: mint 20 NFTs [1:20] and check the balance for each -def test_mintBatch_balanceOf(erc1155, w3, test_mint_batch, assert_tx_failed): +def test_mintBatch_balanceOf(erc1155, w3, assert_tx_failed): # test_mint_batch owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # Use the mint three fixture to mint the tokens. # this test checks the balances of this test for i in range (1,10): - assert (lambda: erc1155.balanceOf(a1, i, transact={"from": a1}) == 1) + assert erc1155.balanceOf(a1, i) == 1 assert_tx_failed(lambda: erc1155.balanceOf(ZERO_ADDRESS, i, transact={"from": a1}) == 1) -def test_safeBatchTransferFrom_balanceOf_batch(erc1155, w3, test_mint_batch, assert_tx_failed): +def test_safeBatchTransferFrom_balanceOf_batch(erc1155, w3, assert_tx_failed): # test_mint_batch owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture @@ -202,14 +193,14 @@ def test_safeBatchTransferFrom_balanceOf_batch(erc1155, w3, test_mint_batch, ass # try to transfer nonexisting item assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [1,2,500], [1,1,1], '', transact={"from": a1})) - assert (lambda: erc1155.safeBatchTransferFrom(a1, a2, [1,2,3], [1,1,1], '', transact={"from": a1})) + assert erc1155.safeBatchTransferFrom(a1, a2, [1,2,3], [1,1,1], '', transact={"from": a1}) # try to transfer again, our balances are zero now, should fail assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [1,2,3], [1,1,1], '', transact={"from": a1})) assert_tx_failed(lambda: erc1155.balanceOfBatch([a2,a2,a2],[1,2], transact={"from": owner}) == [1,1,1]) - assert (lambda: erc1155.balanceOfBatch([a2,a2,a2],[1,2,3], transact={"from": owner}) == [1,1,1]) - assert (lambda: erc1155.balanceOf(a1,1, transact={"from": owner}) == 0) + assert erc1155.balanceOfBatch([a2,a2,a2],[1,2,3]) == [1,1,1] + assert erc1155.balanceOf(a1,1) == 0 def test_mint_one_burn_one(erc1155, w3, assert_tx_failed): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] @@ -217,8 +208,8 @@ def test_mint_one_burn_one(erc1155, w3, assert_tx_failed): # check the balance from an owner and non-owner account erc1155.mint(owner, 21, 1, '', transact={"from": owner}) - assert (lambda: erc1155.balanceOf(owner,21, transact={"from": owner}) == 1) - assert (lambda: erc1155.balanceOf(owner,21, transact={"from": a1}) == 1) + assert erc1155.balanceOf(owner,21) == 1 + assert erc1155.balanceOf(owner,21) == 1 # try and burn an item we don't control assert_tx_failed(lambda: erc1155.burn(21,1,transact={"from": a3})) @@ -231,16 +222,16 @@ def test_mint_one_burn_one(erc1155, w3, assert_tx_failed): erc1155.burn(21,1, transact={"from": owner}) - assert (lambda: erc1155.balanceOf(owner,21, transact={"from": a1}) == 0) + assert erc1155.balanceOf(owner,21) == 0 def test_mint_batch_burn_batch(erc1155, w3, assert_tx_failed): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # mint NFTs 11-20 - erc1155.mintBatch(a3, mintBatch2, minBatchSetOf10, '',transact={"from":owner}) + # check the balance - assert (lambda: erc1155.balanceOfBatch([a1, a1, a1],[1,2,3], transact={"from": a1}) == [1,1,1]) + assert erc1155.balanceOfBatch([a3, a3, a3],[11,12,13]) == [1,1,1] # try and burn a batch we don't control assert_tx_failed(lambda: erc1155.burnBatch([11,12],[1,1])) @@ -257,15 +248,15 @@ def test_mint_batch_burn_batch(erc1155, w3, assert_tx_failed): # burn existing erc1155.burnBatch([11,12],[1,1],transact={"from": a3}) - assert (lambda: erc1155.balanceOfBatch([a1,a1,a1],[11,12,13], transact={"from": a1}) == [0,0,1]) + assert erc1155.balanceOfBatch([a3,a3,a3],[11,12,13]) == [0,0,1] # burn again, should revert - assert_tx_failed(lambda: erc1155.burnBatch([1,2],[1,1],transact={"from": a1})) + assert_tx_failed(lambda: erc1155.burnBatch([11,12],[1,1],transact={"from": a3})) - assert (lambda: erc1155.balanceOfBatch([a1,a1,a1],[1,2,3], transact={"from": a1}) == [0,0,1]) + assert (lambda: erc1155.balanceOfBatch([a3,a3,a3],[1,2,3]) == [0,0,1]) -def test_approval_functions(erc1155, w3, test_mint_batch, assert_tx_failed): +def test_approval_functions(erc1155, w3, assert_tx_failed): # test_mint_batch owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # self-approval by the owner assert_tx_failed(lambda: erc1155.setApprovalForAll(a5, a5,True, transact={"from": a5})) @@ -312,8 +303,9 @@ def test_ownership_functions(erc1155, w3, assert_tx_failed,tester): assert_tx_failed(lambda: erc1155.transferOwnership("0x0000000000000000000000000000000000000000")) # Transfer ownership to account 1 - erc1155.transferOwnership(a1) - assert (lambda: erc1155.owner() == a1) + erc1155.transferOwnership(a1,transact={"from": owner}) + # assert erc1155.owner() == a1 + assert erc1155.owner() == a1 def test_renounce_ownership(erc1155, w3, assert_tx_failed): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] @@ -323,4 +315,5 @@ def test_renounce_ownership(erc1155, w3, assert_tx_failed): erc1155.renounceOwnership(transact={"from": owner}) - assert (lambda: erc1155.owner() == ZERO_ADDRESS) \ No newline at end of file + # assert erc1155.owner() == ZERO_ADDRESS + assert erc1155.owner() == None From b3d2be8869aa15bc427a08095d6f4c87d8b18c9b Mon Sep 17 00:00:00 2001 From: El De-dog-lo <3859395+fubuloubu@users.noreply.github.com> Date: Fri, 29 Apr 2022 17:40:21 -0400 Subject: [PATCH 17/29] refactor: apply suggestions from code review --- examples/tokens/ERC1155ownable.vy | 46 +++++++++---------------------- 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index dfb08cbc55..bd15a3c92c 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -38,7 +38,6 @@ ERC1155_INTERFACE_ID: constant(bytes4) = 0xd9b67a26 ERC1155_INTERFACE_ID_METADATA: constant(bytes4) = 0x0e89341c # mappings -supportsInterfaces: constant(bytes4[3]) = [ERC165_INTERFACE_ID, ERC1155_INTERFACE_ID, ERC1155_INTERFACE_ID_METADATA] # Mapping from token ID to account balances balances: HashMap[uint256,HashMap[address, uint256]] @@ -138,7 +137,7 @@ def pause(): # @dev emits a pause event # @dev not part of the core spec but a common feature for NFT projects assert self.owner == msg.sender, "Ownable: caller is not the owner" - assert not self.paused, " the contract is already paused" + assert not self.paused, "the contract is already paused" self.paused = True log Paused(msg.sender) @@ -198,11 +197,10 @@ def balanceOfBatch(accounts: DynArray[address, BATCH_SIZE], ids: DynArray[uint25 # @param accounts a dynamic array of the addresses to check the balance for # @param ids a dynamic array of the token IDs to check the balance assert len(accounts) == len(ids), "ERC1155: accounts and ids length mismatch" - batchBalances: DynArray[uint256, BATCH_SIZE] = empty(DynArray[uint256,BATCH_SIZE]) + batchBalances: DynArray[uint256, BATCH_SIZE] = [] j: uint256 = 0 for i in ids: - tempBalance: uint256 = self.balances[i][accounts[j]] - batchBalances.append(tempBalance) + batchBalances.append(self.balances[i][accounts[j]]) j += 1 return batchBalances @@ -218,7 +216,7 @@ def mint(receiver: address, id: uint256, amount:uint256, data:bytes32): assert not self.paused, "The contract has been paused" assert self.owner == msg.sender, "Only the contract owner can mint" assert receiver != ZERO_ADDRESS, "Can not mint to ZERO ADDRESS" - operator:address = msg.sender + operator: address = msg.sender self.balances[id][receiver] += amount log TransferSingle(operator, ZERO_ADDRESS, receiver, id, amount) @@ -240,7 +238,7 @@ def mintBatch(receiver: address, ids: DynArray[uint256, BATCH_SIZE], amounts: Dy for i in range(BATCH_SIZE): if i >= len(ids): break - self.balances[ids[i]][receiver] = amounts[i] + self.balances[ids[i]][receiver] += amounts[i] log TransferBatch(operator, ZERO_ADDRESS, receiver, ids, amounts) @@ -254,12 +252,8 @@ def burn(id: uint256, amount: uint256): # @param amount of tokens to burnfor this ID assert not self.paused, "The contract has been paused" assert self.balances[id][msg.sender] > 0 , "caller does not own this ID" - operator: address = msg.sender - fromBalance: uint256 = self.balances[id][msg.sender] - assert fromBalance >= amount, "ERC1155: burn amount exceeds balance" - self.balances[id][msg.sender] = fromBalance - amount - - log TransferSingle(operator, msg.sender, ZERO_ADDRESS, id, amount) + self.balances[id][msg.sender] -= amount + log TransferSingle(msg.sender, msg.sender, ZERO_ADDRESS, id, amount) @external def burnBatch(ids: DynArray[uint256, BATCH_SIZE], amounts: DynArray[uint256, BATCH_SIZE]): @@ -275,14 +269,9 @@ def burnBatch(ids: DynArray[uint256, BATCH_SIZE], amounts: DynArray[uint256, BAT for i in range(BATCH_SIZE): if i >= len(ids): break - assert self.balances[ids[i]][msg.sender] > 0 , "Caller does not own this ID or ZERO balance" - id: uint256 = ids[i] - amount: uint256 = amounts[i] - fromBalance: uint256 = self.balances[id][msg.sender] - assert fromBalance >= amount, "ERC1155: burn amount exceeds balance" - self.balances[id][msg.sender] = fromBalance - amount + self.balances[ids[i]][msg.sender] -= amounts[i] - log TransferBatch(operator, msg.sender, ZERO_ADDRESS, ids, amounts) + log TransferBatch(msg.sender, msg.sender, ZERO_ADDRESS, ids, amounts) ## approval ## @external @@ -302,7 +291,6 @@ def isApprovedForAll(account: address, operator: address) -> bool: # @dev check wether operator is approved as an operator for the account # @param account the NFT owner address # @param operator the operator address - assert self.paused == False, "The contract has been paused" return self.operatorApprovals[account][operator] @external @@ -314,13 +302,10 @@ def safeTransferFrom(sender: address, receiver: address, id: uint256, amount: ui # @param amount the amount of tokens for the specified id assert not self.paused, "The contract has been paused" assert receiver != ZERO_ADDRESS, "ERC1155: transfer to the zero address" - assert receiver != sender, "ERC1155: transfer to self" - assert (sender == msg.sender) or (self.operatorApprovals[sender][msg.sender] == True), "Caller is neither owner nor approved operator for this ID" + assert sender == msg.sender or self.operatorApprovals[sender][msg.sender], "Caller is neither owner nor approved operator for this ID" assert self.balances[id][sender] > 0 , "caller does not own this ID or ZERO balance" operator: address = msg.sender - fromBalance: uint256 = self.balances[id][sender] - assert fromBalance >= amount, "ERC1155: insufficient balance for transfer" - self.balances[id][sender] = fromBalance - amount + self.balances[id][sender] -= amount self.balances[id][receiver] += amount log TransferSingle(operator, sender, receiver, id, amount) @@ -333,20 +318,15 @@ def safeBatchTransferFrom(sender: address, receiver: address, ids: DynArray[uint # @param amounts a dynamic array of the amounts for the specified list of ids. assert not self.paused, "The contract has been paused" assert receiver != ZERO_ADDRESS, "ERC1155: transfer to the zero address" - assert (sender == msg.sender) or (self.operatorApprovals[sender][msg.sender] == True), "Caller is neither owner nor approved operator for this ID" + assert sender == msg.sender or self.operatorApprovals[sender][msg.sender], "Caller is neither owner nor approved operator for this ID" assert len(ids) == len(amounts), "ERC1155: ids and amounts length mismatch" - assert sender != receiver, "sending to self" operator: address = msg.sender for i in range(BATCH_SIZE): if i >= len(ids): break - assert self.balances[ids[i]][sender] > 0 , "caller does not own this ID or ZERO balance" id: uint256 = ids[i] amount: uint256 = amounts[i] - fromBalance: uint256 = self.balances[id][sender] - assert fromBalance >= amount, "ERC1155: transfer amount exceeds balance" - # self.balances[id][msg.sender] = fromBalance - amount - self.balances[id][sender] = fromBalance - amount + self.balances[id][sender] -= amount self.balances[id][receiver] += amount log TransferBatch(operator, sender, receiver, ids, amounts) From d374eed973f409a63842c224865b5116efa877b8 Mon Sep 17 00:00:00 2001 From: "DrPixel.eth" <33023023+Doc-Pixel@users.noreply.github.com> Date: Sun, 1 May 2022 16:56:56 -0700 Subject: [PATCH 18/29] Update examples/tokens/ERC1155ownable.vy Co-authored-by: El De-dog-lo <3859395+fubuloubu@users.noreply.github.com> --- examples/tokens/ERC1155ownable.vy | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index bd15a3c92c..d4b51954cc 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -110,7 +110,13 @@ implements: ERC165 interface IERC1155Receiver: def onERC1155Received(operator: address, sender: address, id: uint256, _value: uint256, data: bytes32) -> bytes32: payable - def onERC1155BatchReceived(operator: address, sender: address, _ids: DynArray[uint256, CALLBACK_NUMBYTES], _amounts: DynArray[uint256, BATCH_SIZE], data: bytes32) -> bytes32: payable + def onERC1155BatchReceived( + operator: address, + sender: address, + ids: DynArray[uint256, BATCH_SIZE], + amounts: DynArray[uint256, BATCH_SIZE], + data: Bytes[CALLBACK_NUMBYTES], + ) -> bytes4: payable interface IERC1155MetadataURI: def uri(id: uint256) -> String[MAX_URI_LENGTH]: view From cff1c64dae7bf55e2d2888508bf312a4c03e8912 Mon Sep 17 00:00:00 2001 From: "DrPixel.eth" <33023023+Doc-Pixel@users.noreply.github.com> Date: Sun, 1 May 2022 16:57:12 -0700 Subject: [PATCH 19/29] Update examples/tokens/ERC1155ownable.vy Co-authored-by: El De-dog-lo <3859395+fubuloubu@users.noreply.github.com> --- examples/tokens/ERC1155ownable.vy | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index d4b51954cc..92a7c67e2b 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -109,7 +109,13 @@ event URI: implements: ERC165 interface IERC1155Receiver: - def onERC1155Received(operator: address, sender: address, id: uint256, _value: uint256, data: bytes32) -> bytes32: payable + def onERC1155Received( + operator: address, + sender: address, + id: uint256, + amount: uint256, + data: Bytes[CALLBACK_NUMBYTES], + ) -> bytes32: payable def onERC1155BatchReceived( operator: address, sender: address, From 08e4cc7ef55ea9dd5a2b88032da9229b072847d3 Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Sun, 1 May 2022 17:45:23 -0700 Subject: [PATCH 20/29] applied codebase shrink tips, adjusted tests --- examples/tokens/ERC1155ownable.vy | 70 +++++++++-------- tests/examples/tokens/test_erc1155.py | 108 +++++++++++++------------- 2 files changed, 88 insertions(+), 90 deletions(-) diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index 92a7c67e2b..a37b712b04 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -40,10 +40,10 @@ ERC1155_INTERFACE_ID_METADATA: constant(bytes4) = 0x0e89341c # mappings # Mapping from token ID to account balances -balances: HashMap[uint256,HashMap[address, uint256]] +balanceOf: public(HashMap[uint256,HashMap[address, uint256]]) # Mapping from account to operator approvals -operatorApprovals: HashMap[address, HashMap[address, bool]] +isApprovedForAll: public( HashMap[address, HashMap[address, bool]]) ############### events ############### event Paused: @@ -188,17 +188,17 @@ def renounceOwnership(): self.owner = ZERO_ADDRESS log OwnershipTransferred(oldOwner, ZERO_ADDRESS) -## balance ## -# @view -@external -def balanceOf(account: address, id: uint256) -> uint256: - # @dev check the balance for a specific ID and address - # @dev will return the balance if the id is owned by the address - # @dev Can also be used to check ownership of an ID - # @param account the address to check the balance for - # @param id the token ID to check the balance - assert account != ZERO_ADDRESS, "Please enter a valid address" - return self.balances[id][account] +# ## balance ## +# # @view +# @external +# def balanceOf(account: address, id: uint256) -> uint256: +# # @dev check the balance for a specific ID and address +# # @dev will return the balance if the id is owned by the address +# # @dev Can also be used to check ownership of an ID +# # @param account the address to check the balance for +# # @param id the token ID to check the balance +# assert account != ZERO_ADDRESS, "Please enter a valid address" +# return self.balances[id][account] @external @view @@ -212,7 +212,7 @@ def balanceOfBatch(accounts: DynArray[address, BATCH_SIZE], ids: DynArray[uint25 batchBalances: DynArray[uint256, BATCH_SIZE] = [] j: uint256 = 0 for i in ids: - batchBalances.append(self.balances[i][accounts[j]]) + batchBalances.append(self.balanceOf[i][accounts[j]]) j += 1 return batchBalances @@ -229,7 +229,7 @@ def mint(receiver: address, id: uint256, amount:uint256, data:bytes32): assert self.owner == msg.sender, "Only the contract owner can mint" assert receiver != ZERO_ADDRESS, "Can not mint to ZERO ADDRESS" operator: address = msg.sender - self.balances[id][receiver] += amount + self.balanceOf[id][receiver] += amount log TransferSingle(operator, ZERO_ADDRESS, receiver, id, amount) @@ -250,7 +250,7 @@ def mintBatch(receiver: address, ids: DynArray[uint256, BATCH_SIZE], amounts: Dy for i in range(BATCH_SIZE): if i >= len(ids): break - self.balances[ids[i]][receiver] += amounts[i] + self.balanceOf[ids[i]][receiver] += amounts[i] log TransferBatch(operator, ZERO_ADDRESS, receiver, ids, amounts) @@ -263,8 +263,8 @@ def burn(id: uint256, amount: uint256): # @param id the ID of the token to burn # @param amount of tokens to burnfor this ID assert not self.paused, "The contract has been paused" - assert self.balances[id][msg.sender] > 0 , "caller does not own this ID" - self.balances[id][msg.sender] -= amount + assert self.balanceOf[id][msg.sender] > 0 , "caller does not own this ID" + self.balanceOf[id][msg.sender] -= amount log TransferSingle(msg.sender, msg.sender, ZERO_ADDRESS, id, amount) @external @@ -281,7 +281,7 @@ def burnBatch(ids: DynArray[uint256, BATCH_SIZE], amounts: DynArray[uint256, BAT for i in range(BATCH_SIZE): if i >= len(ids): break - self.balances[ids[i]][msg.sender] -= amounts[i] + self.balanceOf[ids[i]][msg.sender] -= amounts[i] log TransferBatch(msg.sender, msg.sender, ZERO_ADDRESS, ids, amounts) @@ -294,16 +294,16 @@ def setApprovalForAll(owner: address, operator: address, approved: bool): assert owner == msg.sender, "You can only set operators for your own account" assert not self.paused, "The contract has been paused" assert owner != operator, "ERC1155: setting approval status for self" - self.operatorApprovals[owner][operator] = approved + self.isApprovedForAll[owner][operator] = approved log ApprovalForAll(owner, operator, approved) -@external -@view -def isApprovedForAll(account: address, operator: address) -> bool: - # @dev check wether operator is approved as an operator for the account - # @param account the NFT owner address - # @param operator the operator address - return self.operatorApprovals[account][operator] +# @external +# @view +# def isApprovedForAll(account: address, operator: address) -> bool: +# # @dev check wether operator is approved as an operator for the account +# # @param account the NFT owner address +# # @param operator the operator address +# return self.operatorApprovals[account][operator] @external def safeTransferFrom(sender: address, receiver: address, id: uint256, amount: uint256, bytes: bytes32): @@ -314,11 +314,12 @@ def safeTransferFrom(sender: address, receiver: address, id: uint256, amount: ui # @param amount the amount of tokens for the specified id assert not self.paused, "The contract has been paused" assert receiver != ZERO_ADDRESS, "ERC1155: transfer to the zero address" - assert sender == msg.sender or self.operatorApprovals[sender][msg.sender], "Caller is neither owner nor approved operator for this ID" - assert self.balances[id][sender] > 0 , "caller does not own this ID or ZERO balance" + assert sender != receiver + assert sender == msg.sender or self.isApprovedForAll[sender][msg.sender], "Caller is neither owner nor approved operator for this ID" + assert self.balanceOf[id][sender] > 0 , "caller does not own this ID or ZERO balance" operator: address = msg.sender - self.balances[id][sender] -= amount - self.balances[id][receiver] += amount + self.balanceOf[id][sender] -= amount + self.balanceOf[id][receiver] += amount log TransferSingle(operator, sender, receiver, id, amount) @external @@ -330,7 +331,8 @@ def safeBatchTransferFrom(sender: address, receiver: address, ids: DynArray[uint # @param amounts a dynamic array of the amounts for the specified list of ids. assert not self.paused, "The contract has been paused" assert receiver != ZERO_ADDRESS, "ERC1155: transfer to the zero address" - assert sender == msg.sender or self.operatorApprovals[sender][msg.sender], "Caller is neither owner nor approved operator for this ID" + assert sender != receiver + assert sender == msg.sender or self.isApprovedForAll[sender][msg.sender], "Caller is neither owner nor approved operator for this ID" assert len(ids) == len(amounts), "ERC1155: ids and amounts length mismatch" operator: address = msg.sender for i in range(BATCH_SIZE): @@ -338,8 +340,8 @@ def safeBatchTransferFrom(sender: address, receiver: address, ids: DynArray[uint break id: uint256 = ids[i] amount: uint256 = amounts[i] - self.balances[id][sender] -= amount - self.balances[id][receiver] += amount + self.balanceOf[id][sender] -= amount + self.balanceOf[id][receiver] += amount log TransferBatch(operator, sender, receiver, ids, amounts) diff --git a/tests/examples/tokens/test_erc1155.py b/tests/examples/tokens/test_erc1155.py index 10074a05bf..c904f724d3 100644 --- a/tests/examples/tokens/test_erc1155.py +++ b/tests/examples/tokens/test_erc1155.py @@ -25,31 +25,29 @@ def erc1155(get_contract, w3, assert_tx_failed): code = f.read() c = get_contract(code, *[CONTRACT_NAME, CONTRACT_SYMBOL, CONTRACT_URI]) - c.mint(a1, 1, 1, '', transact={"from": owner}) - c.mint(a1, 2, 1, '', transact={"from": owner}) - c.mint(a1, 3, 1, '', transact={"from": owner}) - c.mint(a1, 4, 1, '', transact={"from": owner}) - - assert_tx_failed(lambda: c.mint(a1, 4, 1, '', transact={"from": a3})) - assert_tx_failed(lambda: c.mint(ZERO_ADDRESS, 4, 1, '', transact={"from": owner})) - - assert c.balanceOf(a1,1) == 1 - assert c.balanceOf(a1,2) == 1 - assert c.balanceOf(a1,3) == 1 - assert c.balanceOf(a1,4) == 1 - - # check ZERO_ADDRESS balance (should fail) - assert_tx_failed(lambda: c.balanceOf(ZERO_ADDRESS,3, transact={"from": owner}) == 1) - owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] c.mintBatch(a1, mintBatch, minBatchSetOf10, '', transact={"from": owner}) c.mintBatch(a3, mintBatch2, minBatchSetOf10, '', transact={"from": owner}) # assert_tx_failed(lambda: c.mintBatch(a1, mintBatch, minBatchSetOf10, '', transact={"from": a2})) - assert c.balanceOf(a1,1) == 1 - assert c.balanceOf(a1,2) == 1 - assert c.balanceOf(a1,3) == 1 + assert c.balanceOf(1, a1) == 1 + assert c.balanceOf(2, a1) == 1 + assert c.balanceOf(3, a1) == 1 assert_tx_failed(lambda: c.mintBatch(ZERO_ADDRESS, mintBatch, minBatchSetOf10, '', transact={"from": owner})) assert_tx_failed(lambda: c.mintBatch(a1, [1,2,3], [1,1], '', transact={"from": owner})) + + c.mint(a1, 21, 1, '', transact={"from": owner}) + c.mint(a1, 22, 1, '', transact={"from": owner}) + c.mint(a1, 23, 1, '', transact={"from": owner}) + c.mint(a1, 24, 1, '', transact={"from": owner}) + + assert_tx_failed(lambda: c.mint(a1, 24, 1, '', transact={"from": a3})) + assert_tx_failed(lambda: c.mint(ZERO_ADDRESS, 24, 1, '', transact={"from": owner})) + + assert c.balanceOf(21, a1) == 1 + assert c.balanceOf(22, a1) == 1 + assert c.balanceOf(23, a1) == 1 + assert c.balanceOf(24, a1) == 1 + return c ##### tests ##### @@ -89,16 +87,16 @@ def test_pause(erc1155,w3, assert_tx_failed): assert_tx_failed(lambda: erc1155.setURI(NEW_CONTRACT_URI)) # test burn and burnbatch - assert_tx_failed(lambda: erc1155.burn(1,1)) - assert_tx_failed(lambda: erc1155.burnBatch([1,2],[1,1])) + assert_tx_failed(lambda: erc1155.burn(21,1)) + assert_tx_failed(lambda: erc1155.burnBatch([21,22],[1,1])) # check mint and mintbatch - assert_tx_failed(lambda: erc1155.mint(a1, 1, 1, '', transact={"from": owner})) + assert_tx_failed(lambda: erc1155.mint(a1, 21, 1, '', transact={"from": owner})) assert_tx_failed(lambda: erc1155.mintBatch(a1, mintBatch, minBatchSetOf10, '', transact={"from": owner})) # check safetransferfrom and safebatchtransferfrom - assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 1, 1, '', transact={"from": a1})) - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [1,2,3], [1,1,1], '', transact={"from": a1})) + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 21, 1, '', transact={"from": a1})) + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [21,22,23], [1,1,1], '', transact={"from": a1})) # check ownership functions assert_tx_failed(lambda: erc1155.transferOwnership(a1)) @@ -106,7 +104,6 @@ def test_pause(erc1155,w3, assert_tx_failed): # check approval functions assert_tx_failed(lambda: erc1155.setApprovalForAll(owner,a5,True)) - assert_tx_failed(lambda: erc1155.isApprovedForAll(owner,a5)) # try and unpause as non-owner assert_tx_failed(lambda: erc1155.unpause(transact={"from": a1})) @@ -134,30 +131,28 @@ def test_URI(erc1155, w3,assert_tx_failed): def test_safeTransferFrom_balanceOf_single(erc1155, w3, assert_tx_failed): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] - # transfer by non-owner - assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 4, 1, '', transact={"from": a2})) + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 24, 1, '', transact={"from": a2})) # transfer to zero address - assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, ZERO_ADDRESS, 4, 1, '', transact={"from": a1})) + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, ZERO_ADDRESS, 24, 1, '', transact={"from": a1})) # transfer to self - assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a1, 4, 1, '', transact={"from": a1})) + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a1, 24, 1, '', transact={"from": a1})) # transfer more than owned - assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 4, 500, '', transact={"from": a1})) + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 24, 500, '', transact={"from": a1})) # transfer item not owned / not existing assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 500, 1, '', transact={"from": a1})) - erc1155.mint(a1, 21, 1, '', transact={"from": owner}) erc1155.safeTransferFrom(a1, a2, 21, 1, '', transact={"from": a1}) - assert erc1155.balanceOf(a2,21) == 1 + assert erc1155.balanceOf(21, a2) == 1 # try to transfer item again assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 21, 1, '', transact={"from": a1})) - assert erc1155.balanceOf(a1,21) == 0 + assert erc1155.balanceOf(21, a1) == 0 # TODO: mint 20 NFTs [1:20] and check the balance for each @@ -166,63 +161,64 @@ def test_mintBatch_balanceOf(erc1155, w3, assert_tx_failed): # test_mint_batch # Use the mint three fixture to mint the tokens. # this test checks the balances of this test for i in range (1,10): - assert erc1155.balanceOf(a1, i) == 1 - assert_tx_failed(lambda: erc1155.balanceOf(ZERO_ADDRESS, i, transact={"from": a1}) == 1) + assert erc1155.balanceOf(i, a1) == 1 def test_safeBatchTransferFrom_balanceOf_batch(erc1155, w3, assert_tx_failed): # test_mint_batch owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] - # transfer NFT 1 from account 1 to account 2 use test_mint_single fixture - erc1155.balanceOf(a1,1, transact={"from": a1}) == 1 - + # check a1 balances for NFTs 21-24 + assert erc1155.balanceOf(21, a1) == 1 + assert erc1155.balanceOf(22, a1) == 1 + assert erc1155.balanceOf(23, a1) == 1 + assert erc1155.balanceOf(23, a1) == 1 # try to transfer item from non item owner account - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [1,2,3], [1,1,1], '', transact={"from": a2})) + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [21,22,23], [1,1,1], '', transact={"from": a2})) # try to transfer item to zero address - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, ZERO_ADDRESS, [1,2,3], [1,1,1], '', transact={"from": a1})) + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, ZERO_ADDRESS, [21,22,23], [1,1,1], '', transact={"from": a1})) # try to transfer item to self - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a1, [1,2,3], [1,1,1], '', transact={"from": a1})) + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a1, [21,22,23], [1,1,1], '', transact={"from": a1})) # try to transfer more items than we own - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [1,2,3], [1,125,1], '', transact={"from": a1})) + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [21,22,23], [1,125,1], '', transact={"from": a1})) # mismatched item and amounts - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [1,2,3], [1,1], '', transact={"from": a1})) + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [21,22,23], [1,1], '', transact={"from": a1})) # try to transfer nonexisting item - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [1,2,500], [1,1,1], '', transact={"from": a1})) - assert erc1155.safeBatchTransferFrom(a1, a2, [1,2,3], [1,1,1], '', transact={"from": a1}) + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [21,22,500], [1,1,1], '', transact={"from": a1})) + assert erc1155.safeBatchTransferFrom(a1, a2, [21,22,23], [1,1,1], '', transact={"from": a1}) # try to transfer again, our balances are zero now, should fail - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [1,2,3], [1,1,1], '', transact={"from": a1})) - assert_tx_failed(lambda: erc1155.balanceOfBatch([a2,a2,a2],[1,2], transact={"from": owner}) == [1,1,1]) + assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [21,22,23], [1,1,1], '', transact={"from": a1})) + assert_tx_failed(lambda: erc1155.balanceOfBatch([a2,a2,a2],[21,22], transact={"from": owner}) == [1,1,1]) - assert erc1155.balanceOfBatch([a2,a2,a2],[1,2,3]) == [1,1,1] - assert erc1155.balanceOf(a1,1) == 0 + assert erc1155.balanceOfBatch([a2,a2,a2],[21,22,23]) == [1,1,1] + assert erc1155.balanceOf(21,a1) == 0 def test_mint_one_burn_one(erc1155, w3, assert_tx_failed): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # check the balance from an owner and non-owner account - erc1155.mint(owner, 21, 1, '', transact={"from": owner}) + erc1155.mint(owner, 25, 1, '', transact={"from": owner}) - assert erc1155.balanceOf(owner,21) == 1 - assert erc1155.balanceOf(owner,21) == 1 + assert erc1155.balanceOf(25, owner) == 1 + assert erc1155.balanceOf(25, owner) == 1 # try and burn an item we don't control - assert_tx_failed(lambda: erc1155.burn(21,1,transact={"from": a3})) + assert_tx_failed(lambda: erc1155.burn(25,1,transact={"from": a3})) # burn an item that contains something we don't own assert_tx_failed(lambda: erc1155.burn(595,1,transact={"from": a1})) # burn ah item passing a higher amount than we own - assert_tx_failed(lambda: erc1155.burn(21,500,transact={"from": a1})) + assert_tx_failed(lambda: erc1155.burn(25,500,transact={"from": a1})) - erc1155.burn(21,1, transact={"from": owner}) + erc1155.burn(25,1, transact={"from": owner}) - assert erc1155.balanceOf(owner,21) == 0 + assert erc1155.balanceOf(25, owner) == 0 def test_mint_batch_burn_batch(erc1155, w3, assert_tx_failed): From f1ec2e613e6dc1281791bbe74aeebbbbb73a0ccf Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Sun, 1 May 2022 17:57:14 -0700 Subject: [PATCH 21/29] cleaning up commented out code --- examples/tokens/ERC1155ownable.vy | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index a37b712b04..1a8358157d 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -133,12 +133,12 @@ interface IERC1155MetadataURI: def __init__(name: String[128], symbol: String[16], uri: String[1024]): # @dev contract initialization on deployment # @dev will set name and symbol, interfaces, owner and URI + # @dev self.paused will default to false # @param name the smart contract name # @param symbol the smart contract symbol # @param uri the new uri for the contract self.name = name self.symbol = symbol - self.paused = False self.owner = msg.sender self._uri = uri @@ -188,18 +188,6 @@ def renounceOwnership(): self.owner = ZERO_ADDRESS log OwnershipTransferred(oldOwner, ZERO_ADDRESS) -# ## balance ## -# # @view -# @external -# def balanceOf(account: address, id: uint256) -> uint256: -# # @dev check the balance for a specific ID and address -# # @dev will return the balance if the id is owned by the address -# # @dev Can also be used to check ownership of an ID -# # @param account the address to check the balance for -# # @param id the token ID to check the balance -# assert account != ZERO_ADDRESS, "Please enter a valid address" -# return self.balances[id][account] - @external @view def balanceOfBatch(accounts: DynArray[address, BATCH_SIZE], ids: DynArray[uint256, BATCH_SIZE]) -> DynArray[uint256,BATCH_SIZE]: # uint256[BATCH_SIZE]: @@ -297,14 +285,6 @@ def setApprovalForAll(owner: address, operator: address, approved: bool): self.isApprovedForAll[owner][operator] = approved log ApprovalForAll(owner, operator, approved) -# @external -# @view -# def isApprovedForAll(account: address, operator: address) -> bool: -# # @dev check wether operator is approved as an operator for the account -# # @param account the NFT owner address -# # @param operator the operator address -# return self.operatorApprovals[account][operator] - @external def safeTransferFrom(sender: address, receiver: address, id: uint256, amount: uint256, bytes: bytes32): # @dev transfer token from one address to another. From 0297391d9854762189ef90ee960567b61285e290 Mon Sep 17 00:00:00 2001 From: El De-dog-lo <3859395+fubuloubu@users.noreply.github.com> Date: Sun, 1 May 2022 22:42:37 -0400 Subject: [PATCH 22/29] refactor: flip orientation of `balanceOf` --- examples/tokens/ERC1155ownable.vy | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index 1a8358157d..d37b91695d 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -40,7 +40,7 @@ ERC1155_INTERFACE_ID_METADATA: constant(bytes4) = 0x0e89341c # mappings # Mapping from token ID to account balances -balanceOf: public(HashMap[uint256,HashMap[address, uint256]]) +balanceOf: public(HashMap[address, HashMap[uint256, uint256]]) # Mapping from account to operator approvals isApprovedForAll: public( HashMap[address, HashMap[address, bool]]) @@ -200,7 +200,7 @@ def balanceOfBatch(accounts: DynArray[address, BATCH_SIZE], ids: DynArray[uint25 batchBalances: DynArray[uint256, BATCH_SIZE] = [] j: uint256 = 0 for i in ids: - batchBalances.append(self.balanceOf[i][accounts[j]]) + batchBalances.append(self.balanceOf[accounts[j]][i]) j += 1 return batchBalances @@ -217,7 +217,7 @@ def mint(receiver: address, id: uint256, amount:uint256, data:bytes32): assert self.owner == msg.sender, "Only the contract owner can mint" assert receiver != ZERO_ADDRESS, "Can not mint to ZERO ADDRESS" operator: address = msg.sender - self.balanceOf[id][receiver] += amount + self.balanceOf[receiver][id] += amount log TransferSingle(operator, ZERO_ADDRESS, receiver, id, amount) @@ -238,7 +238,7 @@ def mintBatch(receiver: address, ids: DynArray[uint256, BATCH_SIZE], amounts: Dy for i in range(BATCH_SIZE): if i >= len(ids): break - self.balanceOf[ids[i]][receiver] += amounts[i] + self.balanceOf[receiver][ids[i]] += amounts[i] log TransferBatch(operator, ZERO_ADDRESS, receiver, ids, amounts) @@ -251,8 +251,8 @@ def burn(id: uint256, amount: uint256): # @param id the ID of the token to burn # @param amount of tokens to burnfor this ID assert not self.paused, "The contract has been paused" - assert self.balanceOf[id][msg.sender] > 0 , "caller does not own this ID" - self.balanceOf[id][msg.sender] -= amount + assert self.balanceOf[msg.sender][id] > 0 , "caller does not own this ID" + self.balanceOf[msg.sender][id] -= amount log TransferSingle(msg.sender, msg.sender, ZERO_ADDRESS, id, amount) @external @@ -269,7 +269,7 @@ def burnBatch(ids: DynArray[uint256, BATCH_SIZE], amounts: DynArray[uint256, BAT for i in range(BATCH_SIZE): if i >= len(ids): break - self.balanceOf[ids[i]][msg.sender] -= amounts[i] + self.balanceOf[msg.sender][ids[i]] -= amounts[i] log TransferBatch(msg.sender, msg.sender, ZERO_ADDRESS, ids, amounts) @@ -295,11 +295,10 @@ def safeTransferFrom(sender: address, receiver: address, id: uint256, amount: ui assert not self.paused, "The contract has been paused" assert receiver != ZERO_ADDRESS, "ERC1155: transfer to the zero address" assert sender != receiver - assert sender == msg.sender or self.isApprovedForAll[sender][msg.sender], "Caller is neither owner nor approved operator for this ID" - assert self.balanceOf[id][sender] > 0 , "caller does not own this ID or ZERO balance" + assert self.balanceOf[sender][id] > 0 , "caller does not own this ID or ZERO balance" operator: address = msg.sender - self.balanceOf[id][sender] -= amount - self.balanceOf[id][receiver] += amount + self.balanceOf[sender][id] -= amount + self.balanceOf[receiver][id] += amount log TransferSingle(operator, sender, receiver, id, amount) @external @@ -320,8 +319,8 @@ def safeBatchTransferFrom(sender: address, receiver: address, ids: DynArray[uint break id: uint256 = ids[i] amount: uint256 = amounts[i] - self.balanceOf[id][sender] -= amount - self.balanceOf[id][receiver] += amount + self.balanceOf[sender][id] -= amount + self.balanceOf[receiver][id] += amount log TransferBatch(operator, sender, receiver, ids, amounts) From 375f624cdb25f7a3affbe01d097f324a6292a45f Mon Sep 17 00:00:00 2001 From: El De-dog-lo <3859395+fubuloubu@users.noreply.github.com> Date: Sun, 1 May 2022 22:47:52 -0400 Subject: [PATCH 23/29] test: update tests for switch of args to `balanceOf` --- tests/examples/tokens/test_erc1155.py | 36 +++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/examples/tokens/test_erc1155.py b/tests/examples/tokens/test_erc1155.py index c904f724d3..662fb8ba58 100644 --- a/tests/examples/tokens/test_erc1155.py +++ b/tests/examples/tokens/test_erc1155.py @@ -28,9 +28,9 @@ def erc1155(get_contract, w3, assert_tx_failed): c.mintBatch(a1, mintBatch, minBatchSetOf10, '', transact={"from": owner}) c.mintBatch(a3, mintBatch2, minBatchSetOf10, '', transact={"from": owner}) # assert_tx_failed(lambda: c.mintBatch(a1, mintBatch, minBatchSetOf10, '', transact={"from": a2})) - assert c.balanceOf(1, a1) == 1 - assert c.balanceOf(2, a1) == 1 - assert c.balanceOf(3, a1) == 1 + assert c.balanceOf(a1, 1) == 1 + assert c.balanceOf(a1, 2) == 1 + assert c.balanceOf(a1, 3) == 1 assert_tx_failed(lambda: c.mintBatch(ZERO_ADDRESS, mintBatch, minBatchSetOf10, '', transact={"from": owner})) assert_tx_failed(lambda: c.mintBatch(a1, [1,2,3], [1,1], '', transact={"from": owner})) @@ -43,10 +43,10 @@ def erc1155(get_contract, w3, assert_tx_failed): assert_tx_failed(lambda: c.mint(a1, 24, 1, '', transact={"from": a3})) assert_tx_failed(lambda: c.mint(ZERO_ADDRESS, 24, 1, '', transact={"from": owner})) - assert c.balanceOf(21, a1) == 1 - assert c.balanceOf(22, a1) == 1 - assert c.balanceOf(23, a1) == 1 - assert c.balanceOf(24, a1) == 1 + assert c.balanceOf(a1, 21) == 1 + assert c.balanceOf(a1, 22) == 1 + assert c.balanceOf(a1, 23) == 1 + assert c.balanceOf(a1, 24) == 1 return c @@ -148,11 +148,11 @@ def test_safeTransferFrom_balanceOf_single(erc1155, w3, assert_tx_failed): erc1155.safeTransferFrom(a1, a2, 21, 1, '', transact={"from": a1}) - assert erc1155.balanceOf(21, a2) == 1 + assert erc1155.balanceOf(a2, 21) == 1 # try to transfer item again assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 21, 1, '', transact={"from": a1})) - assert erc1155.balanceOf(21, a1) == 0 + assert erc1155.balanceOf(a1, 21) == 0 # TODO: mint 20 NFTs [1:20] and check the balance for each @@ -161,16 +161,16 @@ def test_mintBatch_balanceOf(erc1155, w3, assert_tx_failed): # test_mint_batch # Use the mint three fixture to mint the tokens. # this test checks the balances of this test for i in range (1,10): - assert erc1155.balanceOf(i, a1) == 1 + assert erc1155.balanceOf(a1, i) == 1 def test_safeBatchTransferFrom_balanceOf_batch(erc1155, w3, assert_tx_failed): # test_mint_batch owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # check a1 balances for NFTs 21-24 - assert erc1155.balanceOf(21, a1) == 1 - assert erc1155.balanceOf(22, a1) == 1 - assert erc1155.balanceOf(23, a1) == 1 - assert erc1155.balanceOf(23, a1) == 1 + assert erc1155.balanceOf(a1, 21) == 1 + assert erc1155.balanceOf(a1, 22) == 1 + assert erc1155.balanceOf(a1, 23) == 1 + assert erc1155.balanceOf(a1, 23) == 1 # try to transfer item from non item owner account assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [21,22,23], [1,1,1], '', transact={"from": a2})) @@ -196,7 +196,7 @@ def test_safeBatchTransferFrom_balanceOf_batch(erc1155, w3, assert_tx_failed): assert_tx_failed(lambda: erc1155.balanceOfBatch([a2,a2,a2],[21,22], transact={"from": owner}) == [1,1,1]) assert erc1155.balanceOfBatch([a2,a2,a2],[21,22,23]) == [1,1,1] - assert erc1155.balanceOf(21,a1) == 0 + assert erc1155.balanceOf(a1, 21) == 0 def test_mint_one_burn_one(erc1155, w3, assert_tx_failed): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] @@ -204,8 +204,8 @@ def test_mint_one_burn_one(erc1155, w3, assert_tx_failed): # check the balance from an owner and non-owner account erc1155.mint(owner, 25, 1, '', transact={"from": owner}) - assert erc1155.balanceOf(25, owner) == 1 - assert erc1155.balanceOf(25, owner) == 1 + assert erc1155.balanceOf(owner, 25) == 1 + assert erc1155.balanceOf(owner, 25) == 1 # try and burn an item we don't control assert_tx_failed(lambda: erc1155.burn(25,1,transact={"from": a3})) @@ -218,7 +218,7 @@ def test_mint_one_burn_one(erc1155, w3, assert_tx_failed): erc1155.burn(25,1, transact={"from": owner}) - assert erc1155.balanceOf(25, owner) == 0 + assert erc1155.balanceOf(owner, 25) == 0 def test_mint_batch_burn_batch(erc1155, w3, assert_tx_failed): From d87c3210acfc8f8ce2e9043b552e5bfaa00633c9 Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Sun, 1 May 2022 19:56:13 -0700 Subject: [PATCH 24/29] pull, isort, black, push --- tests/examples/tokens/test_erc1155.py | 256 +++++++++++++++----------- 1 file changed, 153 insertions(+), 103 deletions(-) diff --git a/tests/examples/tokens/test_erc1155.py b/tests/examples/tokens/test_erc1155.py index 662fb8ba58..ccddb774b9 100644 --- a/tests/examples/tokens/test_erc1155.py +++ b/tests/examples/tokens/test_erc1155.py @@ -1,22 +1,24 @@ import pytest + # ERC1155 ownable, opensea compatible tests # @author Dr. Pixel (github: @Doc-Pixel) # constants - contract deployment -CONTRACT_NAME = 'TEST 1155' -CONTRACT_SYMBOL= 'T1155' -CONTRACT_URI = 'https://mydomain.io/NFTdata/{id}' -NEW_CONTRACT_URI = 'https://mynewdomain.io/NFTdata/{id}' -ERC165_INTERFACE_ID = '0x01ffc9a7' -ERC1155_INTERFACE_ID = '0xd9b67a26' -ERC1155_INTERFACE_ID_METADATA = '0x0e89341c' +CONTRACT_NAME = "TEST 1155" +CONTRACT_SYMBOL = "T1155" +CONTRACT_URI = "https://mydomain.io/NFTdata/{id}" +NEW_CONTRACT_URI = "https://mynewdomain.io/NFTdata/{id}" +ERC165_INTERFACE_ID = "0x01ffc9a7" +ERC1155_INTERFACE_ID = "0xd9b67a26" +ERC1155_INTERFACE_ID_METADATA = "0x0e89341c" ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" # minting test lists -mintBatch = [1,2,3,4,5,6,7,8,9,10] -mintBatch2 = [11,12,13,14,15,16,17,19,19,20] -minBatchSetOf10 = [1,1,1,1,1,1,1,1,1,1] -mintConflictBatch = [1,2,3] +mintBatch = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +mintBatch2 = [11, 12, 13, 14, 15, 16, 17, 19, 19, 20] +minBatchSetOf10 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] +mintConflictBatch = [1, 2, 3] + @pytest.fixture def erc1155(get_contract, w3, assert_tx_failed): @@ -25,23 +27,24 @@ def erc1155(get_contract, w3, assert_tx_failed): code = f.read() c = get_contract(code, *[CONTRACT_NAME, CONTRACT_SYMBOL, CONTRACT_URI]) - c.mintBatch(a1, mintBatch, minBatchSetOf10, '', transact={"from": owner}) - c.mintBatch(a3, mintBatch2, minBatchSetOf10, '', transact={"from": owner}) + c.mintBatch(a1, mintBatch, minBatchSetOf10, "", transact={"from": owner}) + c.mintBatch(a3, mintBatch2, minBatchSetOf10, "", transact={"from": owner}) # assert_tx_failed(lambda: c.mintBatch(a1, mintBatch, minBatchSetOf10, '', transact={"from": a2})) assert c.balanceOf(a1, 1) == 1 assert c.balanceOf(a1, 2) == 1 assert c.balanceOf(a1, 3) == 1 - assert_tx_failed(lambda: c.mintBatch(ZERO_ADDRESS, mintBatch, minBatchSetOf10, '', transact={"from": owner})) - assert_tx_failed(lambda: c.mintBatch(a1, [1,2,3], [1,1], '', transact={"from": owner})) + assert_tx_failed( + lambda: c.mintBatch(ZERO_ADDRESS, mintBatch, minBatchSetOf10, "", transact={"from": owner}) + ) + assert_tx_failed(lambda: c.mintBatch(a1, [1, 2, 3], [1, 1], "", transact={"from": owner})) + c.mint(a1, 21, 1, "", transact={"from": owner}) + c.mint(a1, 22, 1, "", transact={"from": owner}) + c.mint(a1, 23, 1, "", transact={"from": owner}) + c.mint(a1, 24, 1, "", transact={"from": owner}) - c.mint(a1, 21, 1, '', transact={"from": owner}) - c.mint(a1, 22, 1, '', transact={"from": owner}) - c.mint(a1, 23, 1, '', transact={"from": owner}) - c.mint(a1, 24, 1, '', transact={"from": owner}) - - assert_tx_failed(lambda: c.mint(a1, 24, 1, '', transact={"from": a3})) - assert_tx_failed(lambda: c.mint(ZERO_ADDRESS, 24, 1, '', transact={"from": owner})) + assert_tx_failed(lambda: c.mint(a1, 24, 1, "", transact={"from": a3})) + assert_tx_failed(lambda: c.mint(ZERO_ADDRESS, 24, 1, "", transact={"from": owner})) assert c.balanceOf(a1, 21) == 1 assert c.balanceOf(a1, 22) == 1 @@ -50,8 +53,10 @@ def erc1155(get_contract, w3, assert_tx_failed): return c + ##### tests ##### + def test_initial_state(erc1155): # Check if the constructor of the contract is set up properly # and the contract is deployed with the desired variables @@ -62,48 +67,54 @@ def test_initial_state(erc1155): assert erc1155.uri(0) == CONTRACT_URI # interfaces set up correctly? - assert erc1155.supportsInterface(ERC165_INTERFACE_ID) - assert erc1155.supportsInterface(ERC1155_INTERFACE_ID) - assert erc1155.supportsInterface(ERC1155_INTERFACE_ID_METADATA) - + assert erc1155.supportsInterface(ERC165_INTERFACE_ID) + assert erc1155.supportsInterface(ERC1155_INTERFACE_ID) + assert erc1155.supportsInterface(ERC1155_INTERFACE_ID_METADATA) -def test_pause(erc1155,w3, assert_tx_failed): + +def test_pause(erc1155, w3, assert_tx_failed): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # check the pause status, pause, check, unpause, check, with owner and non-owner w3.eth.accounts # this test will check all the function that should not work when paused. assert erc1155.paused() == False - + # try to pause the contract from a non owner account assert_tx_failed(lambda: erc1155.pause(transact={"from": a1})) - + # now pause the contract and check status erc1155.pause(transact={"from": owner}) assert erc1155.paused() == True - + # try pausing a paused contract assert_tx_failed(lambda: erc1155.pause()) - + # try functions that should not work when paused assert_tx_failed(lambda: erc1155.setURI(NEW_CONTRACT_URI)) - # test burn and burnbatch - assert_tx_failed(lambda: erc1155.burn(21,1)) - assert_tx_failed(lambda: erc1155.burnBatch([21,22],[1,1])) + # test burn and burnbatch + assert_tx_failed(lambda: erc1155.burn(21, 1)) + assert_tx_failed(lambda: erc1155.burnBatch([21, 22], [1, 1])) # check mint and mintbatch - assert_tx_failed(lambda: erc1155.mint(a1, 21, 1, '', transact={"from": owner})) - assert_tx_failed(lambda: erc1155.mintBatch(a1, mintBatch, minBatchSetOf10, '', transact={"from": owner})) + assert_tx_failed(lambda: erc1155.mint(a1, 21, 1, "", transact={"from": owner})) + assert_tx_failed( + lambda: erc1155.mintBatch(a1, mintBatch, minBatchSetOf10, "", transact={"from": owner}) + ) # check safetransferfrom and safebatchtransferfrom - assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 21, 1, '', transact={"from": a1})) - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [21,22,23], [1,1,1], '', transact={"from": a1})) + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 21, 1, "", transact={"from": a1})) + assert_tx_failed( + lambda: erc1155.safeBatchTransferFrom( + a1, a2, [21, 22, 23], [1, 1, 1], "", transact={"from": a1} + ) + ) # check ownership functions assert_tx_failed(lambda: erc1155.transferOwnership(a1)) assert_tx_failed(lambda: erc1155.renounceOwnership()) # check approval functions - assert_tx_failed(lambda: erc1155.setApprovalForAll(owner,a5,True)) + assert_tx_failed(lambda: erc1155.setApprovalForAll(owner, a5, True)) # try and unpause as non-owner assert_tx_failed(lambda: erc1155.unpause(transact={"from": a1})) @@ -115,7 +126,7 @@ def test_pause(erc1155,w3, assert_tx_failed): assert_tx_failed(lambda: erc1155.unpause()) -def test_URI(erc1155, w3,assert_tx_failed): +def test_URI(erc1155, w3, assert_tx_failed): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # change contract URI and restore. assert erc1155.uri(0) == CONTRACT_URI @@ -128,41 +139,45 @@ def test_URI(erc1155, w3,assert_tx_failed): assert_tx_failed(lambda: erc1155.setURI(CONTRACT_URI)) + def test_safeTransferFrom_balanceOf_single(erc1155, w3, assert_tx_failed): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] - + # transfer by non-owner - assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 24, 1, '', transact={"from": a2})) - + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 24, 1, "", transact={"from": a2})) + # transfer to zero address - assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, ZERO_ADDRESS, 24, 1, '', transact={"from": a1})) - + assert_tx_failed( + lambda: erc1155.safeTransferFrom(a1, ZERO_ADDRESS, 24, 1, "", transact={"from": a1}) + ) + # transfer to self - assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a1, 24, 1, '', transact={"from": a1})) - + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a1, 24, 1, "", transact={"from": a1})) + # transfer more than owned - assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 24, 500, '', transact={"from": a1})) - + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 24, 500, "", transact={"from": a1})) + # transfer item not owned / not existing - assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 500, 1, '', transact={"from": a1})) - - erc1155.safeTransferFrom(a1, a2, 21, 1, '', transact={"from": a1}) - + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 500, 1, "", transact={"from": a1})) + + erc1155.safeTransferFrom(a1, a2, 21, 1, "", transact={"from": a1}) + assert erc1155.balanceOf(a2, 21) == 1 - + # try to transfer item again - assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 21, 1, '', transact={"from": a1})) + assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 21, 1, "", transact={"from": a1})) assert erc1155.balanceOf(a1, 21) == 0 - + # TODO: mint 20 NFTs [1:20] and check the balance for each def test_mintBatch_balanceOf(erc1155, w3, assert_tx_failed): # test_mint_batch owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] - # Use the mint three fixture to mint the tokens. + # Use the mint three fixture to mint the tokens. # this test checks the balances of this test - for i in range (1,10): + for i in range(1, 10): assert erc1155.balanceOf(a1, i) == 1 - + + def test_safeBatchTransferFrom_balanceOf_batch(erc1155, w3, assert_tx_failed): # test_mint_batch owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] @@ -173,50 +188,82 @@ def test_safeBatchTransferFrom_balanceOf_batch(erc1155, w3, assert_tx_failed): assert erc1155.balanceOf(a1, 23) == 1 # try to transfer item from non item owner account - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [21,22,23], [1,1,1], '', transact={"from": a2})) + assert_tx_failed( + lambda: erc1155.safeBatchTransferFrom( + a1, a2, [21, 22, 23], [1, 1, 1], "", transact={"from": a2} + ) + ) # try to transfer item to zero address - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, ZERO_ADDRESS, [21,22,23], [1,1,1], '', transact={"from": a1})) + assert_tx_failed( + lambda: erc1155.safeBatchTransferFrom( + a1, ZERO_ADDRESS, [21, 22, 23], [1, 1, 1], "", transact={"from": a1} + ) + ) # try to transfer item to self - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a1, [21,22,23], [1,1,1], '', transact={"from": a1})) - + assert_tx_failed( + lambda: erc1155.safeBatchTransferFrom( + a1, a1, [21, 22, 23], [1, 1, 1], "", transact={"from": a1} + ) + ) + # try to transfer more items than we own - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [21,22,23], [1,125,1], '', transact={"from": a1})) + assert_tx_failed( + lambda: erc1155.safeBatchTransferFrom( + a1, a2, [21, 22, 23], [1, 125, 1], "", transact={"from": a1} + ) + ) # mismatched item and amounts - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [21,22,23], [1,1], '', transact={"from": a1})) + assert_tx_failed( + lambda: erc1155.safeBatchTransferFrom( + a1, a2, [21, 22, 23], [1, 1], "", transact={"from": a1} + ) + ) # try to transfer nonexisting item - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [21,22,500], [1,1,1], '', transact={"from": a1})) - assert erc1155.safeBatchTransferFrom(a1, a2, [21,22,23], [1,1,1], '', transact={"from": a1}) - + assert_tx_failed( + lambda: erc1155.safeBatchTransferFrom( + a1, a2, [21, 22, 500], [1, 1, 1], "", transact={"from": a1} + ) + ) + assert erc1155.safeBatchTransferFrom(a1, a2, [21, 22, 23], [1, 1, 1], "", transact={"from": a1}) + # try to transfer again, our balances are zero now, should fail - assert_tx_failed(lambda: erc1155.safeBatchTransferFrom(a1, a2, [21,22,23], [1,1,1], '', transact={"from": a1})) - assert_tx_failed(lambda: erc1155.balanceOfBatch([a2,a2,a2],[21,22], transact={"from": owner}) == [1,1,1]) - - assert erc1155.balanceOfBatch([a2,a2,a2],[21,22,23]) == [1,1,1] + assert_tx_failed( + lambda: erc1155.safeBatchTransferFrom( + a1, a2, [21, 22, 23], [1, 1, 1], "", transact={"from": a1} + ) + ) + assert_tx_failed( + lambda: erc1155.balanceOfBatch([a2, a2, a2], [21, 22], transact={"from": owner}) + == [1, 1, 1] + ) + + assert erc1155.balanceOfBatch([a2, a2, a2], [21, 22, 23]) == [1, 1, 1] assert erc1155.balanceOf(a1, 21) == 0 + def test_mint_one_burn_one(erc1155, w3, assert_tx_failed): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] - - # check the balance from an owner and non-owner account - erc1155.mint(owner, 25, 1, '', transact={"from": owner}) + + # check the balance from an owner and non-owner account + erc1155.mint(owner, 25, 1, "", transact={"from": owner}) assert erc1155.balanceOf(owner, 25) == 1 assert erc1155.balanceOf(owner, 25) == 1 # try and burn an item we don't control - assert_tx_failed(lambda: erc1155.burn(25,1,transact={"from": a3})) + assert_tx_failed(lambda: erc1155.burn(25, 1, transact={"from": a3})) # burn an item that contains something we don't own - assert_tx_failed(lambda: erc1155.burn(595,1,transact={"from": a1})) + assert_tx_failed(lambda: erc1155.burn(595, 1, transact={"from": a1})) # burn ah item passing a higher amount than we own - assert_tx_failed(lambda: erc1155.burn(25,500,transact={"from": a1})) + assert_tx_failed(lambda: erc1155.burn(25, 500, transact={"from": a1})) - erc1155.burn(25,1, transact={"from": owner}) + erc1155.burn(25, 1, transact={"from": owner}) assert erc1155.balanceOf(owner, 25) == 0 @@ -224,50 +271,49 @@ def test_mint_one_burn_one(erc1155, w3, assert_tx_failed): def test_mint_batch_burn_batch(erc1155, w3, assert_tx_failed): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # mint NFTs 11-20 - # check the balance - assert erc1155.balanceOfBatch([a3, a3, a3],[11,12,13]) == [1,1,1] + assert erc1155.balanceOfBatch([a3, a3, a3], [11, 12, 13]) == [1, 1, 1] # try and burn a batch we don't control - assert_tx_failed(lambda: erc1155.burnBatch([11,12],[1,1])) + assert_tx_failed(lambda: erc1155.burnBatch([11, 12], [1, 1])) # ids and amounts array length not matching - assert_tx_failed(lambda: erc1155.burnBatch([1,2,3],[1,1], transact={"from": a1})) + assert_tx_failed(lambda: erc1155.burnBatch([1, 2, 3], [1, 1], transact={"from": a1})) # burn a batch that contains something we don't own - assert_tx_failed(lambda: erc1155.burnBatch([2,3,595],[1,1,1],transact={"from": a1})) + assert_tx_failed(lambda: erc1155.burnBatch([2, 3, 595], [1, 1, 1], transact={"from": a1})) # burn a batch passing a higher amount than we own - assert_tx_failed(lambda: erc1155.burnBatch([1,2,3],[1,500,1],transact={"from": a1})) + assert_tx_failed(lambda: erc1155.burnBatch([1, 2, 3], [1, 500, 1], transact={"from": a1})) # burn existing - erc1155.burnBatch([11,12],[1,1],transact={"from": a3}) + erc1155.burnBatch([11, 12], [1, 1], transact={"from": a3}) - assert erc1155.balanceOfBatch([a3,a3,a3],[11,12,13]) == [0,0,1] + assert erc1155.balanceOfBatch([a3, a3, a3], [11, 12, 13]) == [0, 0, 1] # burn again, should revert - assert_tx_failed(lambda: erc1155.burnBatch([11,12],[1,1],transact={"from": a3})) + assert_tx_failed(lambda: erc1155.burnBatch([11, 12], [1, 1], transact={"from": a3})) - assert (lambda: erc1155.balanceOfBatch([a3,a3,a3],[1,2,3]) == [0,0,1]) + assert lambda: erc1155.balanceOfBatch([a3, a3, a3], [1, 2, 3]) == [0, 0, 1] def test_approval_functions(erc1155, w3, assert_tx_failed): # test_mint_batch owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # self-approval by the owner - assert_tx_failed(lambda: erc1155.setApprovalForAll(a5, a5,True, transact={"from": a5})) + assert_tx_failed(lambda: erc1155.setApprovalForAll(a5, a5, True, transact={"from": a5})) # let's approve and operator for somebody else's account - assert_tx_failed(lambda: erc1155.setApprovalForAll(owner, a5,True, transact={"from": a3})) + assert_tx_failed(lambda: erc1155.setApprovalForAll(owner, a5, True, transact={"from": a3})) # set approval correctly - erc1155.setApprovalForAll(owner, a5,True) + erc1155.setApprovalForAll(owner, a5, True) # check approval erc1155.isApprovedForAll(owner, a5) # remove approval - erc1155.setApprovalForAll(owner,a5,False) + erc1155.setApprovalForAll(owner, a5, False) def test_max_batch_size_violation(erc1155, w3, assert_tx_failed): @@ -275,34 +321,38 @@ def test_max_batch_size_violation(erc1155, w3, assert_tx_failed): TOTAL_BAD_BATCH = 200 ids = [] amounts = [] - for i in range(1,TOTAL_BAD_BATCH): + for i in range(1, TOTAL_BAD_BATCH): ids.append(i) amounts.append(1) - assert_tx_failed(lambda: erc1155.mintBatch(a1, ids, amounts, '', transact={"from": owner})) + assert_tx_failed(lambda: erc1155.mintBatch(a1, ids, amounts, "", transact={"from": owner})) # Transferring back and forth -def test_ownership_functions(erc1155, w3, assert_tx_failed,tester): + +def test_ownership_functions(erc1155, w3, assert_tx_failed, tester): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] - print(owner,a1,a2) - print('___owner___', erc1155.owner()) + print(owner, a1, a2) + print("___owner___", erc1155.owner()) # change owner from account 0 to account 1 and back - + assert erc1155.owner() == owner assert_tx_failed(lambda: erc1155.transferOwnership(a1, transact={"from": a2})) - + # try to transfer ownership to current owner assert_tx_failed(lambda: erc1155.transferOwnership(owner)) # try to transfer ownership to ZERO ADDRESS - assert_tx_failed(lambda: erc1155.transferOwnership("0x0000000000000000000000000000000000000000")) + assert_tx_failed( + lambda: erc1155.transferOwnership("0x0000000000000000000000000000000000000000") + ) - # Transfer ownership to account 1 - erc1155.transferOwnership(a1,transact={"from": owner}) + # Transfer ownership to account 1 + erc1155.transferOwnership(a1, transact={"from": owner}) # assert erc1155.owner() == a1 assert erc1155.owner() == a1 + def test_renounce_ownership(erc1155, w3, assert_tx_failed): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] assert erc1155.owner() == owner From a98de5414464bc841b319322cc6d6619f2d12c9d Mon Sep 17 00:00:00 2001 From: "DrPixel.eth" <33023023+Doc-Pixel@users.noreply.github.com> Date: Tue, 3 May 2022 14:47:14 -0700 Subject: [PATCH 25/29] Resolved linter issues --- tests/examples/tokens/test_erc1155.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/examples/tokens/test_erc1155.py b/tests/examples/tokens/test_erc1155.py index ccddb774b9..6863ebdf83 100644 --- a/tests/examples/tokens/test_erc1155.py +++ b/tests/examples/tokens/test_erc1155.py @@ -29,7 +29,7 @@ def erc1155(get_contract, w3, assert_tx_failed): c.mintBatch(a1, mintBatch, minBatchSetOf10, "", transact={"from": owner}) c.mintBatch(a3, mintBatch2, minBatchSetOf10, "", transact={"from": owner}) - # assert_tx_failed(lambda: c.mintBatch(a1, mintBatch, minBatchSetOf10, '', transact={"from": a2})) + assert c.balanceOf(a1, 1) == 1 assert c.balanceOf(a1, 2) == 1 assert c.balanceOf(a1, 3) == 1 @@ -54,7 +54,7 @@ def erc1155(get_contract, w3, assert_tx_failed): return c -##### tests ##### +# tests def test_initial_state(erc1155): @@ -76,14 +76,14 @@ def test_pause(erc1155, w3, assert_tx_failed): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # check the pause status, pause, check, unpause, check, with owner and non-owner w3.eth.accounts # this test will check all the function that should not work when paused. - assert erc1155.paused() == False + assert not erc1155.paused() # try to pause the contract from a non owner account assert_tx_failed(lambda: erc1155.pause(transact={"from": a1})) # now pause the contract and check status erc1155.pause(transact={"from": owner}) - assert erc1155.paused() == True + assert erc1155.paused() # try pausing a paused contract assert_tx_failed(lambda: erc1155.pause()) @@ -120,7 +120,7 @@ def test_pause(erc1155, w3, assert_tx_failed): assert_tx_failed(lambda: erc1155.unpause(transact={"from": a1})) erc1155.unpause(transact={"from": owner}) - assert erc1155.paused() == False + assert not erc1155.paused() # try un pausing an unpaused contract assert_tx_failed(lambda: erc1155.unpause()) @@ -362,4 +362,4 @@ def test_renounce_ownership(erc1155, w3, assert_tx_failed): erc1155.renounceOwnership(transact={"from": owner}) # assert erc1155.owner() == ZERO_ADDRESS - assert erc1155.owner() == None + From 8f2eb3131c5b6842a811a9db462b786c6ce895f0 Mon Sep 17 00:00:00 2001 From: "DrPixel.eth" <33023023+Doc-Pixel@users.noreply.github.com> Date: Tue, 3 May 2022 14:54:15 -0700 Subject: [PATCH 26/29] Linter fixes for ERC1155 test script --- tests/examples/tokens/test_erc1155.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/examples/tokens/test_erc1155.py b/tests/examples/tokens/test_erc1155.py index 6863ebdf83..9ef7bf4dc1 100644 --- a/tests/examples/tokens/test_erc1155.py +++ b/tests/examples/tokens/test_erc1155.py @@ -29,7 +29,7 @@ def erc1155(get_contract, w3, assert_tx_failed): c.mintBatch(a1, mintBatch, minBatchSetOf10, "", transact={"from": owner}) c.mintBatch(a3, mintBatch2, minBatchSetOf10, "", transact={"from": owner}) - + assert c.balanceOf(a1, 1) == 1 assert c.balanceOf(a1, 2) == 1 assert c.balanceOf(a1, 3) == 1 @@ -362,4 +362,3 @@ def test_renounce_ownership(erc1155, w3, assert_tx_failed): erc1155.renounceOwnership(transact={"from": owner}) # assert erc1155.owner() == ZERO_ADDRESS - From 904ba2a4798ee1773ad9d1e722d5e9aa51841bd1 Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Wed, 4 May 2022 08:48:11 -0700 Subject: [PATCH 27/29] Fixed ownership check in safeTransferFrom --- examples/tokens/ERC1155ownable.vy | 1 + tests/examples/tokens/test_erc1155.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index d37b91695d..4a88fad3f8 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -295,6 +295,7 @@ def safeTransferFrom(sender: address, receiver: address, id: uint256, amount: ui assert not self.paused, "The contract has been paused" assert receiver != ZERO_ADDRESS, "ERC1155: transfer to the zero address" assert sender != receiver + assert sender == msg.sender or self.isApprovedForAll[sender][msg.sender], "Caller is neither owner nor approved operator for this ID" assert self.balanceOf[sender][id] > 0 , "caller does not own this ID or ZERO balance" operator: address = msg.sender self.balanceOf[sender][id] -= amount diff --git a/tests/examples/tokens/test_erc1155.py b/tests/examples/tokens/test_erc1155.py index 9ef7bf4dc1..429cf67c2b 100644 --- a/tests/examples/tokens/test_erc1155.py +++ b/tests/examples/tokens/test_erc1155.py @@ -142,7 +142,7 @@ def test_URI(erc1155, w3, assert_tx_failed): def test_safeTransferFrom_balanceOf_single(erc1155, w3, assert_tx_failed): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] - + assert erc1155.balanceOf(a1, 24) == 1 # transfer by non-owner assert_tx_failed(lambda: erc1155.safeTransferFrom(a1, a2, 24, 1, "", transact={"from": a2})) From d9040635780163abb4cf4e9baf18951b735af5b1 Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Wed, 4 May 2022 14:51:50 -0700 Subject: [PATCH 28/29] Fixed setURI permissions, updated to docstrings --- examples/tokens/ERC1155ownable.vy | 209 ++++++++++++++++-------------- 1 file changed, 110 insertions(+), 99 deletions(-) diff --git a/examples/tokens/ERC1155ownable.vy b/examples/tokens/ERC1155ownable.vy index 4a88fad3f8..f8e46176d6 100644 --- a/examples/tokens/ERC1155ownable.vy +++ b/examples/tokens/ERC1155ownable.vy @@ -1,9 +1,8 @@ # @version >=0.3.3 - -# @dev Implementation of ERC-1155 non-fungible token standard -# @dev ownable, with approval, OPENSEA compatible (name, symbol) -# @author Dr. Pixel (github: @Doc-Pixel) - +""" +@dev Implementation of ERC-1155 non-fungible token standard ownable, with approval, OPENSEA compatible (name, symbol) +@author Dr. Pixel (github: @Doc-Pixel) +""" ############### imports ############### from vyper.interfaces import ERC165 @@ -18,11 +17,11 @@ CALLBACK_NUMBYTES: constant(uint256) = 4096 MAX_URI_LENGTH: constant(uint256) = 1024 # the contract owner -# @dev not part of the core spec but a common feature for NFT projects +# not part of the core spec but a common feature for NFT projects owner: public(address) # pause status True / False -# @dev not part of the core spec but a common feature for NFT projects +# not part of the core spec but a common feature for NFT projects paused: public(bool) # the contracts URI to find the metadata @@ -47,27 +46,20 @@ isApprovedForAll: public( HashMap[address, HashMap[address, bool]]) ############### events ############### event Paused: - # @dev Emits a pause event with the address that paused the contract + # Emits a pause event with the address that paused the contract account: address event unPaused: - # @dev Emits an unpause event with the address that paused the contract + # Emits an unpause event with the address that paused the contract account: address event OwnershipTransferred: - # @dev Emits smart contract ownership transfer - # @param previousOwner The current, soon to be previous owner of the contract - # @param newOwner The new owner of the contract + # Emits smart contract ownership transfer from current to new owner previouwOwner: address newOwner: address event TransferSingle: - # @dev Emits on transfer of a single token - # @param operator the address initiating the transfer. owner or authorized operator - # @param fromAddress the address sending the token - # @param to the address receiving the token - # @param id the token ID - # @param value the amount of tokens + # Emits on transfer of a single token operator: indexed(address) fromAddress: indexed(address) to: indexed(address) @@ -75,12 +67,7 @@ event TransferSingle: value: uint256 event TransferBatch: - # @dev Emits on batch transfer of tokens. the ids array correspond with the values array by their position - # @param operator the address initiating the transfer. owner or authorized operator - # @param fromAddress the address sending the token - # @param to the address receiving the token - # @param ids list of token ids - # @param values list of amounts for each token + # Emits on batch transfer of tokens. the ids array correspond with the values array by their position operator: indexed(address) # indexed fromAddress: indexed(address) to: indexed(address) @@ -88,19 +75,13 @@ event TransferBatch: values: DynArray[uint256, BATCH_SIZE] event ApprovalForAll: - # @dev This emits when an operator is enabled or disabled for an owner. The operator can manage - # @dev all NFTs of the owner. - # @param account Owner of NFT. - # @param operator Address to which we are setting operator rights. - # @param approved Status of operator rights(true if operator rights are given and false if revoked). + # This emits when an operator is enabled or disabled for an owner. The operator manages all tokens for an owner account: indexed(address) operator: indexed(address) approved: bool event URI: - # @dev This emits when the URI gets changed - # @param value the new URI - # @param id the ID + # This emits when the URI gets changed value: String[MAX_URI_LENGTH] id: uint256 @@ -131,12 +112,14 @@ interface IERC1155MetadataURI: @external def __init__(name: String[128], symbol: String[16], uri: String[1024]): - # @dev contract initialization on deployment - # @dev will set name and symbol, interfaces, owner and URI - # @dev self.paused will default to false - # @param name the smart contract name - # @param symbol the smart contract symbol - # @param uri the new uri for the contract + """ + @dev contract initialization on deployment + @dev will set name and symbol, interfaces, owner and URI + @dev self.paused will default to false + @param name the smart contract name + @param symbol the smart contract symbol + @param uri the new uri for the contract + """ self.name = name self.symbol = symbol self.owner = msg.sender @@ -145,9 +128,11 @@ def __init__(name: String[128], symbol: String[16], uri: String[1024]): ## contract status ## @external def pause(): - # @dev Pause the contract, checks if the caller is the owner and if the contract is paused already - # @dev emits a pause event - # @dev not part of the core spec but a common feature for NFT projects + """ + @dev Pause the contract, checks if the caller is the owner and if the contract is paused already + @dev emits a pause event + @dev not part of the core spec but a common feature for NFT projects + """ assert self.owner == msg.sender, "Ownable: caller is not the owner" assert not self.paused, "the contract is already paused" self.paused = True @@ -155,9 +140,11 @@ def pause(): @external def unpause(): - # @dev Unpause the contract, checks if the caller is the owner and if the contract is paused already - # @dev emits an unpause event - # @dev not part of the core spec but a common feature for NFT projects + """ + @dev Unpause the contract, checks if the caller is the owner and if the contract is paused already + @dev emits an unpause event + @dev not part of the core spec but a common feature for NFT projects + """ assert self.owner == msg.sender, "Ownable: caller is not the owner" assert self.paused, "the contract is not paused" self.paused = False @@ -166,10 +153,12 @@ def unpause(): ## ownership ## @external def transferOwnership(newOwner: address): - # @dev Transfer the ownership. Checks for contract pause status, current owner and prevent transferring to - # @dev zero address - # @dev emits an OwnershipTransferred event with the old and new owner addresses - # @param newOwner The address of the new owner. + """ + @dev Transfer the ownership. Checks for contract pause status, current owner and prevent transferring to + @dev zero address + @dev emits an OwnershipTransferred event with the old and new owner addresses + @param newOwner The address of the new owner. + """ assert not self.paused, "The contract has been paused" assert self.owner == msg.sender, "Ownable: caller is not the owner" assert newOwner != self.owner, "This account already owns the contract" @@ -180,8 +169,10 @@ def transferOwnership(newOwner: address): @external def renounceOwnership(): - # @dev Transfer the ownership to ZERO_ADDRESS, this will lock the contract - # @dev emits an OwnershipTransferred event with the old and new ZERO_ADDRESS owner addresses + """ + @dev Transfer the ownership to ZERO_ADDRESS, this will lock the contract + @dev emits an OwnershipTransferred event with the old and new ZERO_ADDRESS owner addresses + """ assert not self.paused, "The contract has been paused" assert self.owner == msg.sender, "Ownable: caller is not the owner" oldOwner: address = self.owner @@ -191,11 +182,13 @@ def renounceOwnership(): @external @view def balanceOfBatch(accounts: DynArray[address, BATCH_SIZE], ids: DynArray[uint256, BATCH_SIZE]) -> DynArray[uint256,BATCH_SIZE]: # uint256[BATCH_SIZE]: - # @dev check the balance for an array of specific IDs and addresses - # @dev will return an array of balances - # @dev Can also be used to check ownership of an ID - # @param accounts a dynamic array of the addresses to check the balance for - # @param ids a dynamic array of the token IDs to check the balance + """ + @dev check the balance for an array of specific IDs and addresses + @dev will return an array of balances + @dev Can also be used to check ownership of an ID + @param accounts a dynamic array of the addresses to check the balance for + @param ids a dynamic array of the token IDs to check the balance + """ assert len(accounts) == len(ids), "ERC1155: accounts and ids length mismatch" batchBalances: DynArray[uint256, BATCH_SIZE] = [] j: uint256 = 0 @@ -207,12 +200,14 @@ def balanceOfBatch(accounts: DynArray[address, BATCH_SIZE], ids: DynArray[uint25 ## mint ## @external def mint(receiver: address, id: uint256, amount:uint256, data:bytes32): - # @dev mint one new token with a certain ID - # @dev this can be a new token or "topping up" the balance of a non-fungible token ID - # @param receiver the account that will receive the minted token - # @param id the ID of the token - # @param amount of tokens for this ID - # @param data the data associated with this mint. Usually stays empty + """ + @dev mint one new token with a certain ID + @dev this can be a new token or "topping up" the balance of a non-fungible token ID + @param receiver the account that will receive the minted token + @param id the ID of the token + @param amount of tokens for this ID + @param data the data associated with this mint. Usually stays empty + """ assert not self.paused, "The contract has been paused" assert self.owner == msg.sender, "Only the contract owner can mint" assert receiver != ZERO_ADDRESS, "Can not mint to ZERO ADDRESS" @@ -223,12 +218,14 @@ def mint(receiver: address, id: uint256, amount:uint256, data:bytes32): @external def mintBatch(receiver: address, ids: DynArray[uint256, BATCH_SIZE], amounts: DynArray[uint256, BATCH_SIZE], data: bytes32): - # @dev mint a batch of new tokens with the passed IDs - # @dev this can be new tokens or "topping up" the balance of existing non-fungible token IDs in the contract - # @param receiver the account that will receive the minted token - # @param ids array of ids for the tokens - # @param amounts amounts of tokens for each ID in the ids array - # @param data the data associated with this mint. Usually stays empty + """ + @dev mint a batch of new tokens with the passed IDs + @dev this can be new tokens or "topping up" the balance of existing non-fungible token IDs in the contract + @param receiver the account that will receive the minted token + @param ids array of ids for the tokens + @param amounts amounts of tokens for each ID in the ids array + @param data the data associated with this mint. Usually stays empty + """ assert not self.paused, "The contract has been paused" assert self.owner == msg.sender, "Only the contract owner can mint" assert receiver != ZERO_ADDRESS, "Can not mint to ZERO ADDRESS" @@ -245,11 +242,13 @@ def mintBatch(receiver: address, ids: DynArray[uint256, BATCH_SIZE], amounts: Dy ## burn ## @external def burn(id: uint256, amount: uint256): - # @dev burn one or more token with a certain ID - # @dev the amount of tokens will be deducted from the holder's balance - # @param receiver the account that will receive the minted token - # @param id the ID of the token to burn - # @param amount of tokens to burnfor this ID + """ + @dev burn one or more token with a certain ID + @dev the amount of tokens will be deducted from the holder's balance + @param receiver the account that will receive the minted token + @param id the ID of the token to burn + @param amount of tokens to burnfor this ID + """ assert not self.paused, "The contract has been paused" assert self.balanceOf[msg.sender][id] > 0 , "caller does not own this ID" self.balanceOf[msg.sender][id] -= amount @@ -257,11 +256,13 @@ def burn(id: uint256, amount: uint256): @external def burnBatch(ids: DynArray[uint256, BATCH_SIZE], amounts: DynArray[uint256, BATCH_SIZE]): - # @dev burn a batch of tokens with the passed IDs - # @dev this can be burning non fungible tokens or reducing the balance of existing non-fungible token IDs in the contract - # @dev inside the loop ownership will be checked for each token. We can not burn tokens we do not own - # @param ids array of ids for the tokens to burn - # @param amounts array of amounts of tokens for each ID in the ids array + """ + @dev burn a batch of tokens with the passed IDs + @dev this can be burning non fungible tokens or reducing the balance of existing non-fungible token IDs in the contract + @dev inside the loop ownership will be checked for each token. We can not burn tokens we do not own + @param ids array of ids for the tokens to burn + @param amounts array of amounts of tokens for each ID in the ids array + """ assert not self.paused, "The contract has been paused" assert len(ids) == len(amounts), "ERC1155: ids and amounts length mismatch" operator: address = msg.sender @@ -276,9 +277,11 @@ def burnBatch(ids: DynArray[uint256, BATCH_SIZE], amounts: DynArray[uint256, BAT ## approval ## @external def setApprovalForAll(owner: address, operator: address, approved: bool): - # @dev set an operator for a certain NFT owner address - # @param account the NFT owner address - # @param operator the operator address + """ + @dev set an operator for a certain NFT owner address + @param account the NFT owner address + @param operator the operator address + """ assert owner == msg.sender, "You can only set operators for your own account" assert not self.paused, "The contract has been paused" assert owner != operator, "ERC1155: setting approval status for self" @@ -287,11 +290,13 @@ def setApprovalForAll(owner: address, operator: address, approved: bool): @external def safeTransferFrom(sender: address, receiver: address, id: uint256, amount: uint256, bytes: bytes32): - # @dev transfer token from one address to another. - # @param sender the sending account (current owner) - # @param receiver the receiving account - # @param id the token id that will be sent - # @param amount the amount of tokens for the specified id + """ + @dev transfer token from one address to another. + @param sender the sending account (current owner) + @param receiver the receiving account + @param id the token id that will be sent + @param amount the amount of tokens for the specified id + """ assert not self.paused, "The contract has been paused" assert receiver != ZERO_ADDRESS, "ERC1155: transfer to the zero address" assert sender != receiver @@ -304,11 +309,13 @@ def safeTransferFrom(sender: address, receiver: address, id: uint256, amount: ui @external def safeBatchTransferFrom(sender: address, receiver: address, ids: DynArray[uint256, BATCH_SIZE], amounts: DynArray[uint256, BATCH_SIZE], _bytes: bytes32): - # @dev transfer tokens from one address to another. - # @param sender the sending account - # @param receiver the receiving account - # @param ids a dynamic array of the token ids that will be sent - # @param amounts a dynamic array of the amounts for the specified list of ids. + """ + @dev transfer tokens from one address to another. + @param sender the sending account + @param receiver the receiving account + @param ids a dynamic array of the token ids that will be sent + @param amounts a dynamic array of the amounts for the specified list of ids. + """ assert not self.paused, "The contract has been paused" assert receiver != ZERO_ADDRESS, "ERC1155: transfer to the zero address" assert sender != receiver @@ -328,27 +335,31 @@ def safeBatchTransferFrom(sender: address, receiver: address, ids: DynArray[uint # URI # @external def setURI(uri: String[MAX_URI_LENGTH]): - # @dev set the URI for the contract - # @param uri the new uri for the contract + """ + @dev set the URI for the contract + @param uri the new uri for the contract + """ assert not self.paused, "The contract has been paused" assert self._uri != uri, "new and current URI are identical" + assert msg.sender == self.owner, "Only the contract owner can update the URI" self._uri = uri log URI(uri, 0) @external def uri(id: uint256) -> String[MAX_URI_LENGTH]: - # @dev retrieve the uri, this function can optionally be extended to return dynamic uris. out of scope. - # @param id NFT ID to retrieve the uri for. + """ + @dev retrieve the uri, this function can optionally be extended to return dynamic uris. out of scope. + @param id NFT ID to retrieve the uri for. + """ return self._uri -# @external -# @view -# def owner() -> address: -# return self.owner - @pure @external def supportsInterface(interfaceId: bytes4) -> bool: + """ + @dev Returns True if the interface is supported + @param interfaceID bytes4 interface identifier + """ return interfaceId in [ ERC165_INTERFACE_ID, ERC1155_INTERFACE_ID, From 4d97475b8086bd7bdeb8f1a9ea6020a83b513e24 Mon Sep 17 00:00:00 2001 From: DataBeast-IT Date: Wed, 4 May 2022 14:53:32 -0700 Subject: [PATCH 29/29] Minor test update --- tests/examples/tokens/test_erc1155.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/examples/tokens/test_erc1155.py b/tests/examples/tokens/test_erc1155.py index 429cf67c2b..4bca205bff 100644 --- a/tests/examples/tokens/test_erc1155.py +++ b/tests/examples/tokens/test_erc1155.py @@ -130,10 +130,10 @@ def test_URI(erc1155, w3, assert_tx_failed): owner, a1, a2, a3, a4, a5 = w3.eth.accounts[0:6] # change contract URI and restore. assert erc1155.uri(0) == CONTRACT_URI - erc1155.setURI(NEW_CONTRACT_URI, transact={"from": a1}) + erc1155.setURI(NEW_CONTRACT_URI, transact={"from": owner}) assert erc1155.uri(0) == NEW_CONTRACT_URI assert erc1155.uri(0) != CONTRACT_URI - erc1155.setURI(CONTRACT_URI, transact={"from": a1}) + erc1155.setURI(CONTRACT_URI, transact={"from": owner}) assert erc1155.uri(0) != NEW_CONTRACT_URI assert erc1155.uri(0) == CONTRACT_URI