def buy(acct, url, price): """ buy a domain a price :param acct: :param url: :param price: :return: """ owner = Get(ctx, url) if owner != selfAddr: Notify("url not in sale!") return False prevBuyer = Get(ctx, concat('TP_', url)) currentPrice = Get(ctx, concat('Price_', url)) #no buyer before case if not prevBuyer: if price >= currentPrice: if transferONT(acct, selfAddr, price): Put(ctx, concat('TP_', url), acct) if price > currentPrice: Put(ctx, concat('Price_', url), price) Notify('buy succeed!') return True else: Notify('Transfer Failed') return False Notify('Price is lower than current price') return False # has buyer before case if price <= currentPrice: Notify('Price is lower than current price') return False if transferONT(selfAddr, acct, currentPrice): Put(ctx, concat('TP_', url), acct) Put(ctx, concat('Price_', url), price) Notify('refund succeed!') return True else: Notify('refund failed') return False
def do_transfer_from(ctx, Caller, args): """Transfers the approved token at the specified id from the t_from address to the t_to address Only the approved spender OR a whitelisted DEX can invoke this function and a whitelisted DEX will still need to pass the authentication of the spender :param StorageContext ctx: current store context :param list args: 0: bytearray t_spender: approved spender address 1: bytearray t_from: transfer from address (token owner) 2: bytearray t_to: transfer to address (token receiver) 3: int t_id: token id :return: transferFrom success :rtype: bool """ t_spender = args[0] t_from = args[1] t_to = args[2] t_id = args[3] if Caller != GetEntryScriptHash() and not is_whitelisted_dex(ctx, Caller): # non-whitelisted contracts can only approve their own funds for transfer, # even if they have the signature of the owner on the invocation t_from = Caller assert len(t_spender) == 20, INVALID_ADDRESS_ERROR assert len(t_from) == 20, INVALID_ADDRESS_ERROR assert len(t_to) == 20, INVALID_ADDRESS_ERROR assert authenticate(t_spender, Caller), PERMISSION_ERROR if t_from == t_to: print('transfer to self') return True ownership = safe_deserialize(Get(ctx, concat('ownership/', t_id))) assert ownership, TOKEN_DNE_ERROR assert has_key(ownership, 'owner'), TOKEN_DNE_ERROR assert has_key(ownership, 'approved'), 'no approval exists for this token' assert len(ownership['owner']) == 20, TOKEN_DNE_ERROR t_owner = ownership['owner'] assert t_from == t_owner, 'from address is not the owner of this token' assert len( ownership['approved']) == 40, 'malformed approval key for this token' # Finally check to see if the owner approved this spender assert ownership['approved'] == concat(t_from, t_spender), PERMISSION_ERROR res = remove_token_from_owners_list(ctx, t_from, t_id) assert res, 'unable to remove token from owner list' ownership['owner'] = t_to ownership.remove('approved') # remove previous approval Put(ctx, concat('ownership/', t_id), Serialize(ownership)) res = add_token_to_owners_list(ctx, t_to, t_id) # log this transfer event OnTransfer(t_from, t_to, 1) OnNFTTransfer(t_from, t_to, t_id) return True
def getNumberKey(script_hash): return concat("review.neo.number.", script_hash)
def get_kyc_status(ctx, address): print("checking kyc status") kyc_storage_key = concat(KYC_KEY, address) return Get(ctx, kyc_storage_key)
def get_status_address(ctx, address): storage_key = concat(KYC_KEY, address) return Get(ctx, storage_key)
def concatKey(str1, str2): return concat(concat(str1, '_'), str2)
def Main(operation, args): context = GetContext() if operation == 'add': # Try to get a value for this key from storage item_key = args[0] item_value = Get(context, item_key) msg = ["Value read from storage:", item_value] Notify(msg) if len(item_value) == 0: Notify("Storage key not yet set. Setting to 1") item_value = 1 # Store the new value Put(context, item_key, item_value) # Store token list temp = Get(context, 'token_list') if not temp == False: #tokens = Deserialize(temp) name = concat(',', item_key) tokens = concat(temp, name) #a_save_s = Serialize(tokens) Put(context, 'token_list', tokens) msg = ["New value written into list:", tokens] Notify(msg) else: #a_save_s = Serialize(item_key) Put(context, 'token_list', item_key) else: Notify("Storage key already set. Incrementing by 1") item_value += 1 # Store the new value Put(context, item_key, item_value) msg = ["New value written into storage:", item_value] Notify(msg) return item_value elif operation == 'balance': item_key = args[0] item_value = Get(context, item_key) msg = ["Value read from storage:", item_value] Notify(msg) if len(item_value) == 0: Notify("Storage key not yet set. Setting to 0") item_value = 0 else: Notify("Storage key already set.") return item_value elif operation == 'deleteAll': Delete(context, 'token_list') msg = ["Delete the token list:", item_key] Notify(msg) return item_value
def print_info(adr): """ Prints the information stored in the blockchain for the given address :return: indication success execution of the command :rtype: bool """ termsba = Get(ctx, adr) if not termsba: Notify("Partnership for address is not yet created") return False serterms = deserialize_bytearray(termsba) currency = serterms[0] flatfees_struc = serterms[1] partnership_struc = serterms[2] webpage = serterms[3] msg = concat("Partnership Information:", " ") a = concat("Address : ", adr) msg = concat(msg, a) c = concat(", Currency : ", currency) msg = concat(msg, c) d = concat(", Flatfee Structure : ", flatfees_struc) msg = concat(msg, d) e = concat(", Partnership Structure: ", partnership_struc) msg = concat(msg, e) f = concat(", Webpage: ", webpage) msg = concat(msg, f) Notify(msg) json_like_string = concat('["', currency) json_like_string = concat(json_like_string, '","') json_like_string = concat(json_like_string, flatfees_struc) json_like_string = concat(json_like_string, '","') json_like_string = concat(json_like_string, partnership_struc) json_like_string = concat(json_like_string, '", "') json_like_string = concat(json_like_string, webpage) json_like_string = concat(json_like_string, '"]') return json_like_string
def CreatePublication(args): sender = args[0] name = args[1] url = args[2] category = args[3] if not CheckWitness(sender): print('Account owner must be sender') return [False, 'Account owner must be sender'] # Add char limit to prevent big storage costs if (len(name) > 255 or len(url) > 255 or len(category) > 255): print('Args must be less than 255 chars') return [False, 'Arguments must be less than 255 chars'] context = GetContext() publications_key = concat('publications', sender) # Publications by user publication_key = concat( publications_key, sha1(name)) # Publication details - sha1 to prevent malicious input new_publications_key = 'new_publications' # List of new publications for front page view publications = Get(context, publications_key) publication = Get(context, publication_key) new_publications = Get(context, new_publications_key) # If publication already exists check if it is active/deleted if publication: publication = Deserialize(publication) if publication[5]: print('Publication name currently active') return [False, 'Active publication name'] # Check if user has publications already if publications: publications = Deserialize(publications) else: publications = [] # Check if there are publications in the all_publications view if new_publications: new_publications = Deserialize(new_publications) else: new_publications = [] first_date = getWarpedTime(context) + ( SECONDS_IN_DAY - getWarpedTime(context) % SECONDS_IN_DAY) + SECONDS_IN_HOUR * -TIMEZONE is_active = True new_publication = [sender, name, url, category, first_date, is_active] publications.append(name) new_publications.append([sender, name]) # Shift new publication list to the left if len(new_publications) > 5: new_publications = [ new_publications[1], new_publications[2], new_publications[3], new_publications[4], new_publications[5] ] Put(context, publication_key, Serialize(new_publication)) Put(context, publications_key, Serialize(publications)) Put(context, new_publications_key, Serialize(new_publications)) return [True, '']
def do_transfer_from(ctx, t_from, t_to, amount): """ Method to transfer NEP5 tokens of a specified amount from one account to another :param t_from: the address to transfer from :type t_from: bytearray :param t_to: the address to transfer to :type t_to: bytearray :param amount: the amount of NEP5 tokens to transfer :type amount: int :return: whether the transfer was successful :rtype: bool """ if amount <= 0: return False if len(t_from) != 20: return False if len(t_to) != 20: return False available_key = concat(t_from, t_to) available_to_to_addr = Get(ctx, available_key) if available_to_to_addr < amount: print("Insufficient funds approved") return False from_balance = Get(ctx, t_from) if from_balance < amount: print("Insufficient tokens in from balance") return False to_balance = Get(ctx, t_to) new_from_balance = from_balance - amount new_to_balance = to_balance + amount Put(ctx, t_to, new_to_balance) Put(ctx, t_from, new_from_balance) print("transfer complete") new_allowance = available_to_to_addr - amount if new_allowance == 0: print("removing all balance") Delete(ctx, available_key) else: print("updating allowance to new allowance") Put(ctx, available_key, new_allowance) OnTransfer(t_from, t_to, amount) return True
def Main(operation, args): nargs = len(args) if nargs == 0: print("No details entered") return 0 # create a registry to address association for a small fee # can only be called by owner of address being registered ## Concatination point to the reffered registry elif operation == 'RegisterFarmContract': if nargs < 6: print("required arguments: [FarmContract] [owner]") return 0 FarmContract_name = args[0] OwnerNeoAddress = args[1] Farmer_id = args[2] Buyer_id = args[3] Project_id = args[4] Contract_id = args[5] Balance = args[6] Status = args[7] print("Register Farm Contract ") print( "Entered Arguments: [FarmContract_name][OwnerNeoAddress][Farmer_id][Buyer_id][Project_id][Contract_id][Balance][Status]" ) return RegisterFarmContract(FarmContract_name, OwnerNeoAddress, Farmer_id, Buyer_id, Project_id, Contract_id, Balance, Status) ## Registrations that access different features of the agriculture smartcontracts ## Retreive the address/name associated with a given name ## Anyone can call ## Concatination point to the reffered registry elif operation == 'QueryFarmContract': FarmContract_name = args[0] OwnerNeoAddress = args[1] print("Query Farm Contract") print("Entered Arguments: [FarmContract_name] [OwnerNeoAddress]") return QueryFarmContract(FarmContract_name, OwnerNeoAddress) # create Transfer of ownership of registry to new address association for a small fee # can only be called by owner of address being registered ## Concatination point to the reffered registry elif operation == 'TransferFarmContract': if nargs < 2: print( "required arguments: [FarmContract_name] [OwnerNeoAddress] [to_address]" ) return 0 FarmContract_name = args[0] OwnerNeoAddress = args[1] to_address = args[2] print("Transfer Farm Contract ") print( "Entered Arguments: [FarmContract_name][OwnerNeoAddress][to_address]" ) return TransferFarmContract(FarmContract_name, OwnerNeoAddress, to_address) # remove a link between a given registry and it's address # can only be called by registry owner ## Concatination point to the reffered registry elif operation == 'UnregisterFarmContract': FarmContract_name = args[0] OwnerNeoAddress = args[1] print("Unregister Farm Contract ") print("Entered Arguments: [FarmContract_name] [OwnerNeoAddress]") return UnregisterFarmContract(FarmContract_name, OwnerNeoAddress) ## ~~~~~~~~~~~~~~~~~~~~~Digital Coupon and contract progress updates~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## This will be used to update contract balance and contract status ## A service from an oracle will be posting updates to elif operation == 'UpdateFarmContract': if nargs < 6: print("required arguments: [FarmContract] [owner]") return 0 FarmContract_name = args[0] OwnerNeoAddress = args[1] Farmer_id = args[2] Buyer_id = args[3] Project_id = args[4] Contract_id = args[5] Balance = args[6] Status = args[7] print("Update Farm Contract Status") print( "Entered Arguments: [FarmContract_name][OwnerNeoAddress][Farmer_id][Buyer_id][Project_id][Contract_id][Balance][Status]" ) storage_key = concat(FarmContract_name, OwnerNeoAddress) context = GetContext() if not CheckWitness(OwnerNeoAddress): Notify( "Owner argument is not the same as the person who registered") return False raw_data = [ Farmer_id, Buyer_id, Project_id, Contract_id, Balance, Status ] farm_contract_info_serialised = serialize_array(raw_data) putRegistry(context, storage_key, farm_contract_info_serialised) return True
def prefixStorageKey(key): return concat(BTM_STORAGE_PREFIX, key)
def is_whitelisted_dex(ctx, scripthash): return Get(ctx, concat('exchange/', scripthash))
def do_whitelist_dex(ctx, args): return do_set_config(ctx, concat('exchange/', args[0]), args[1])
def Main(operation, args): """Entry point to the program :param str operation: The name of the operation to perform :param list args: A list of arguments along with the operation :return: The result of the operation :rtype: bytearray Token operations: - allowance(token_id): returns approved third-party spender of a token - approve(token_receiver, token_id, revoke): approve third party to spend a token - balanceOf(owner): returns owner's current total tokens owned - name(): returns name of token - decimals(): returns token decimal precision - ownerOf(token_id): returns the owner of the specified token. - properties(token_id): returns a token's read-only data - rwProperties(token_id): returns a token's read/write data - supportedStandards(): returns a list of supported standards {"NEP-10"} - symbol(): returns token symbol - token(token_id): returns a dictionary where token, property, and uri keys map to the corresponding data for the given `token_id` - tokensOfOwner(owner, starting_index): returns a dictionary that contains less than or equal to ten of the tokens owned by the specified address starting at the `starting_index`. - totalSupply(): Returns the total token supply deployed in the system. - transfer(to, token_id, extra_arg): transfers a token - transferFrom(spender, from, to, token_id): allows a third party to execute a pre-approved transfer - uri(token_id): Returns a distinct Uniform Resource Identifier (URI) for a given asset. The URI data of a token supplies a reference to get more information about a specific token or its data. TOKEN_CONTRACT_OWNER operations: - mintToken(owner, properties, URI, extra_arg): create a new NFT token with the specified properties and URI and send it to the specified owner - modifyURI(token_id, token_data): modify specified token's URI data setters: - setName(name): sets the name of the token - setSymbol(symbol): sets the token's symbol - setSupportedStandards(supported_standards): sets the supported standards, 'NEP-10' is always the first element in the array """ # The trigger determines whether this smart contract is being run # in 'verification' mode or 'application' trigger = GetTrigger() # 'Verification' mode is used when trying to spend assets # (eg NEO, Gas) on behalf of this contract's address if trigger == Verification(): # if the script that sent this is the owner, we allow the spend if CheckWitness(TOKEN_CONTRACT_OWNER): return True elif trigger == Application(): # Need to get this at the top level caller = GetCallingScriptHash() ctx = GetContext() if operation == 'name': name = Get(ctx, 'name') if name: return name else: return TOKEN_NAME elif operation == 'symbol': symbol = Get(ctx, 'symbol') if symbol: return symbol else: return TOKEN_SYMBOL elif operation == 'supportedStandards': supported_standards = Get(ctx, 'supportedStandards') if supported_standards: return supported_standards else: return Serialize(['NEP-10']) elif operation == 'totalSupply': return Get(ctx, TOKEN_CIRC_KEY) elif operation == 'allowance': assert len(args) == 1, ARG_ERROR ownership = safe_deserialize( Get(ctx, concat('ownership/', args[0]))) assert ownership, TOKEN_DNE_ERROR # don't fault here in case a calling contract is just checking allowance value if not has_key(ownership, 'approved'): return False if len(ownership['approved']) != 40: return False return ownership['approved'] elif operation == 'balanceOf': assert len(args) == 1, ARG_ERROR assert len(args[0]) == 20, INVALID_ADDRESS_ERROR token_iter = Find(ctx, args[0]) count = 0 while token_iter.next(): count += 1 return count elif operation == 'ownerOf': assert len(args) == 1, ARG_ERROR ownership = safe_deserialize( Get(ctx, concat('ownership/', args[0]))) assert ownership, TOKEN_DNE_ERROR assert has_key(ownership, 'owner'), TOKEN_DNE_ERROR assert len(ownership['owner']) == 20, TOKEN_DNE_ERROR return ownership['owner'] elif operation == 'properties': assert len(args) == 1, ARG_ERROR return get_properties(ctx, args[0]) elif operation == 'rwProperties': assert len(args) == 1, ARG_ERROR return get_rw_properties(ctx, args[0]) elif operation == 'token': assert len(args) == 1, ARG_ERROR token = Get(ctx, concat('token/', args[0])) assert token, TOKEN_DNE_ERROR return token elif operation == 'tokensOfOwner': assert len(args) == 2, ARG_ERROR tokens_of_owner = do_tokens_of_owner(ctx, args[0], args[1]) assert tokens_of_owner, 'address has no tokens' return Serialize(tokens_of_owner) elif operation == 'uri': assert len(args) == 1, ARG_ERROR token = safe_deserialize(Get(ctx, concat('token/', args[0]))) assert token, TOKEN_DNE_ERROR assert has_key(token, 'uri'), TOKEN_DNE_ERROR return token['uri'] elif operation == 'decimals': return TOKEN_DECIMALS # # User RW operations # if operation == 'approve': # args: from, spender, id, revoke # (NFT needs a fourth argument to revoke approval) assert len(args) > 2, ARG_ERROR assert args[2], TOKEN_DNE_ERROR return do_approve(ctx, caller, args) elif operation == 'transfer': assert len(args) > 1, ARG_ERROR return do_transfer(ctx, caller, args) elif operation == 'transferFrom': assert len(args) > 2, ARG_ERROR if len(args) == 3: # Nash-style (from, to, amount/id) transferFrom that can # be invoked only by whitelisted DEX to initiate a # pre-approved transfer return nash_do_transfer_from(ctx, caller, args) else: # Moonlight-style (spender, from, to, amount/id) # transfer where an authenticated spender/originator is # the only one who can initiate a transfer but can send # to an arbitrary third party (or themselves) return do_transfer_from(ctx, caller, args) # # dApp operations # if operation == 'setRWProperties': # args: token id, rwdata assert CheckWitness(DAPP_ADMIN), PERMISSION_ERROR assert len(args) == 2, ARG_ERROR return set_rw_properties(ctx, args[0], args[1]) # Administrative operations if CheckWitness(TOKEN_CONTRACT_OWNER): if operation == 'mintToken': assert len(args) > 3, ARG_ERROR return do_mint_token(ctx, args) elif operation == 'modifyURI': assert len(args) == 2, ARG_ERROR return do_modify_uri(ctx, args) elif operation == 'setName': assert len(args) == 1, ARG_ERROR return do_set_config(ctx, 'name', args[0]) elif operation == 'setSymbol': assert len(args) == 1, ARG_ERROR return do_set_config(ctx, 'symbol', args[0]) elif operation == 'setSupportedStandards': assert len(args) >= 1, ARG_ERROR supported_standards = ['NEP-10'] for arg in args: supported_standards.append(arg) return do_set_config(ctx, 'supportedStandards', Serialize(supported_standards)) AssertionError('unknown operation') return False
def do_transfer_from(ctx, args): """Transfers the approved token at the specified id from the t_from address to the t_to address :param StorageContext ctx: current store context :param list args: 0: byte[] t_from: transfer from address (token owner) 1: byte[] t_to: transfer to address (token receiver) 2: bytes t_id: token id 3: extra_arg: optional argument that can be passed (for use only with smart contracts) :return: transferFrom success :rtype: bool """ t_from = args[0] t_to = args[1] t_id = args[2] if len(t_from) != 20 or len(t_to) != 20: Notify(INVALID_ADDRESS_ERROR) return False if t_from == t_to: Notify('transfer to self') return True t_owner = Get(ctx, t_id) if len(t_owner) != 20: Notify(TOKEN_DNE_ERROR) return False if t_from != t_owner: Notify('from address is not the owner of this token') return False approval_key = concat('approved/', t_id) # authorized spend should be concat(t_owner, t_receiver) authorized_spend = Get(ctx, approval_key) # len(t_owner) == 20 and len(t_receiver) == 20, thus the length of # authorized_spender should be 40 if len(authorized_spend) != 40: Notify('no approval exists for this token') return False # if the input transfer from and transfer to addresses match the # authorized spend if authorized_spend == concat(t_from, t_to): # 1. Is t_to a smart contract? # If True, invoke the transfer_to_smart_contract method. # if transfer_to_smart_contract() returns False, then # reject the transfer if GetContract(t_to): args.remove(0) success = transfer_to_smart_contract(ctx, t_from, args, False) if success is False: return False else: # if t_to is not a contract, there shouldn't be any # extra args to transfer(), this could be a phishing # attempt so reject the transfer if len(args) > 3: Notify(ARG_ERROR) return False res = remove_token_from_owners_list(ctx, t_from, t_id) if res is False: Notify('unable to transfer token') return False Put(ctx, t_id, t_to) # record token's new owner Delete(ctx, approval_key) # remove previous approval add_token_to_owners_list(ctx, t_to, t_id) # log this transfer event OnTransfer(t_from, t_to, 1) OnNFTTransfer(t_from, t_to, t_id) return True Notify(PERMISSION_ERROR) return False
def create_partnership(adr, currency, flatfees_struc, partnership_struc, webpage): """ address, currency, flatfees_struc, partnership_struc, webpage Creates the partnership structure for the given address format for flatfee_struc = addr:fees,addr:fees... format for partnership_struc = addr:fees,addr:fees... :return: indication success execution of the command :rtype: bool """ terms = [currency, flatfees_struc, partnership_struc, webpage] serterms = serialize_array(terms) Put(ctx, adr, serterms) msg = concat("New Partnership Created:", " ") a = concat("Address : ", adr) msg = concat(msg, a) c = concat(", Currency : ", currency) msg = concat(msg, c) d = concat(", Flatfee Structure : ", flatfees_struc) msg = concat(msg, d) e = concat(", Partnership Structure: ", partnership_struc) msg = concat(msg, e) f = concat(", Webpage: ", webpage) msg = concat(msg, f) Notify(msg) return True
def PlaceNewBid(args): owner = args[0] name = args[1] date = args[2] ad_url = args[3] image_urls = args[4] context = GetContext() time = GetTime(context) attachments = get_asset_attachments() user = attachments[1] bid_amount = attachments[3] publication_key = validatePublicationAuction(context, args) if not publication_key: return [False, 'Invalid auction params'] if time >= date: print('Auction has finished') return [False, 'Auction finished'] if bid_amount <= 0: print('No NeoGAS has been attached') return [False, 'No GAS attached'] has_claimed = False new_bid = [user, bid_amount, ad_url, image_urls, time] new_auction = [user, bid_amount, has_claimed] auction_key = concat(publication_key, sha1(date)) bids_key = concat(auction_key, 'bids') auction = Get(context, auction_key) # If no previous bids automatically accept and store current bid if not auction: Put(context, auction_key, Serialize(new_auction)) Put(context, bids_key, Serialize([new_bid])) return [True, ''] auction = Deserialize(auction) previous_user = auction[0] previous_bid = auction[1] if previous_bid >= bid_amount: print('Must bid more than the current best bid') OnRefund(user, bid_amount) return [False, 'Must bid more than current best bid'] bids = Get(context, bids_key) bids = Deserialize(bids) bids.append(new_bid) Put(context, auction_key, Serialize(new_auction)) Put(context, bids_key, Serialize(bids)) # Re-credit funds to previous bidder AddFunds(context, previous_user, previous_bid) return [True, '']
def set_webpage(adr, webpage): msg = concat("Change webpage for: ", adr) Notify(msg) termsba = Get(ctx, adr) if not termsba: Notify("Partnership for address is not yet created") return False serterms = deserialize_bytearray(termsba) currency = serterms[0] flatfees_struc = serterms[1] partnership_struc = serterms[2] terms = [currency, flatfees_struc, partnership_struc, webpage] serterms = serialize_array(terms) Put(ctx, adr, serterms) msg = concat("Webpage updated:", " ") a = concat("Address : ", adr) msg = concat(msg, a) c = concat(", Currency : ", currency) msg = concat(msg, c) d = concat(", Flatfee Structure : ", flatfees_struc) msg = concat(msg, d) e = concat(", Partnership Structure: ", partnership_struc) msg = concat(msg, e) f = concat(", Webpage: ", webpage) msg = concat(msg, f) Notify(msg) return True
def GetUserPubKey(usr_adr): usrpk_key = concat(USR_ADR_PUBKEY_PREFIX, usr_adr) context = GetContext() pub_key = Get(context, usrpk_key) return pub_key
def generate_business_key(address): return concat(b'Business:', address)
def DeleteRecord(record_id): record = GetRecord(record_id) if not record: Log("Record doesn't exist") return False usr_adr = record[0] if not check_permission(usr_adr): Log("Must be owner to delete a record") return False records_id = GetRecordIdList(usr_adr) found = False i = 0 while i < len(records_id): if records_id[i] == record_id: found = True records_id.remove(i) # pop by index i = len(records_id) + 1 # break i += 1 if found: records_serialized = serialize_array(records_id) record_id_list_key = concat(RECORD_ID_LIST_PREFIX, usr_adr) context = GetContext() Put(context, record_id_list_key, records_serialized) record_key = concat(RECORD_ID_META_PREFIX, record_id) Delete(context, record_key) return True else: Log("Record doesn't exist") return False def GetOrderList(): orders_id = GetOrderIdList() orders = [] collection_len = len(orders_id) for i in range(0, collection_len): id = orders_id[i] single_order = GetOrder(id) orders.append(single_order) return orders def GetOrderIdList(): context = GetContext() orders_serialized = Get(context, ORDER_ID_LIST_PREFIX) if not orders_serialized: return [] orders_id = deserialize_bytearray(orders_serialized) return orders_id def InsertOrder(usr_adr, record_id_list_str, price): if not check_permission(usr_adr): Log("Must be owner to create an order") return False if len(record_id_list_str) <= 0: Log("Empty record_id_list") return False # record_incorrect = False # for record_id in record_id_list: # record = GetRecord(record_id) # if (not record) or (record[0] != usr_adr): # record_incorrect = True # if record_incorrect: # Log("Incorrect record_id_list") # return False if price <= 0: Log("Price should be positive") return False context = GetContext() order_data = [usr_adr, record_id_list_str, price, ''] order_data_serialized = serialize_array(order_data) order_id = next_id(NEXT_ORDER_ID_KEY) order_key = concat(ORDER_ID_PREFIX, order_id) Put(context, order_key, order_data_serialized) orders_id = GetOrderIdList() orders_id.append(order_id) orders_serialized = serialize_array(orders_id) Put(context, ORDER_ID_LIST_PREFIX, orders_serialized) msg = concat("New order: ", order_id) Notify(msg) return order_id def GetOrder(order_id): context = GetContext() order_key = concat(ORDER_ID_PREFIX, order_id) order_serialized = Get(context, order_key) if not order_serialized: Log("Order doesn't exist") return False order = deserialize_bytearray(order_serialized) return order def DeleteOrder(order_id): order = GetOrder(order_id) if not order: Log("Order doesn't exist") return False usr_adr = order[0] if not check_permission(usr_adr): Log("Must be owner to delete an order") return False orders_id = GetOrderIdList() found = False i = 0 while i < len(orders_id): if orders_id[i] == order_id: found = True orders_id.remove(i) # pop by index i = len(orders_id) + 1 # break i += 1 if found: orders_serialized = serialize_array(orders_id) context = GetContext() Put(context, ORDER_ID_LIST_PREFIX, orders_serialized) order_key = concat(ORDER_ID_PREFIX, order_id) Delete(context, order_key) return True else: Log("Order doesn't exist") return False # <<< AUXILIARY METHODS >>> def next_id(key): context = GetContext() id = Get(context, key) if not id: Log("Next id doesn't exist yet.") id = INITIAL_ID next_value = id + 1 Put(context, key, next_value) return id def check_permission(usr_adr): if CheckWitness(OWNER): return True if CheckWitness(usr_adr): return True return False # <<< UTILS >>> # def str_to_list(record_id_list_raw): # # TODO implement: "1:2:3" -> [1,2,3] # return record_id_list_raw def deserialize_bytearray(data): # ok this is weird. if you remove this print statement, it stops working :/ # get length of length collection_length_length = data[0:1] # get length of collection collection_len = data[1:collection_length_length + 1] # create a new collection new_collection = list(length=collection_len) # trim the length data offset = 1 + collection_length_length for i in range(0, collection_len): # get the data length length itemlen_len = data[offset:offset + 1] # get the length of the data item_len = data[offset + 1:offset + 1 + itemlen_len] # get the data item = data[offset + 1 + itemlen_len: offset + 1 + itemlen_len + item_len] # store it in collection new_collection[i] = item offset = offset + item_len + itemlen_len + 1 return new_collection def serialize_array(items): # serialize the length of the list itemlength = serialize_var_length_item(items) output = itemlength # now go through and append all your stuff for item in items: # get the variable length of the item # to be serialized itemlen = serialize_var_length_item(item) # add that indicator output = concat(output, itemlen) # now add the item output = concat(output, item) # return the stuff return output def serialize_var_length_item(item): # get the length of your stuff stuff_len = len(item) # now we need to know how many bytes the length of the array # will take to store # this is one byte if stuff_len <= 255: byte_len = b'\x01' # two byte elif stuff_len <= 65535: byte_len = b'\x02' # hopefully 4 byte else: byte_len = b'\x04' out = concat(byte_len, stuff_len) return out
def is_private_placement(ctx, address): storage_key = concat(PP_KEY, address) if Get(ctx, storage_key): return True return False
def DeleteOrder(order_id): order = GetOrder(order_id) if not order: Log("Order doesn't exist") return False usr_adr = order[0] if not check_permission(usr_adr): Log("Must be owner to delete an order") return False orders_id = GetOrderIdList() found = False i = 0 while i < len(orders_id): if orders_id[i] == order_id: found = True orders_id.remove(i) # pop by index i = len(orders_id) + 1 # break i += 1 if found: orders_serialized = serialize_array(orders_id) context = GetContext() Put(context, ORDER_ID_LIST_PREFIX, orders_serialized) order_key = concat(ORDER_ID_PREFIX, order_id) Delete(context, order_key) return True else: Log("Order doesn't exist") return False # <<< AUXILIARY METHODS >>> def next_id(key): context = GetContext() id = Get(context, key) if not id: Log("Next id doesn't exist yet.") id = INITIAL_ID next_value = id + 1 Put(context, key, next_value) return id def check_permission(usr_adr): if CheckWitness(OWNER): return True if CheckWitness(usr_adr): return True return False # <<< UTILS >>> # def str_to_list(record_id_list_raw): # # TODO implement: "1:2:3" -> [1,2,3] # return record_id_list_raw def deserialize_bytearray(data): # ok this is weird. if you remove this print statement, it stops working :/ # get length of length collection_length_length = data[0:1] # get length of collection collection_len = data[1:collection_length_length + 1] # create a new collection new_collection = list(length=collection_len) # trim the length data offset = 1 + collection_length_length for i in range(0, collection_len): # get the data length length itemlen_len = data[offset:offset + 1] # get the length of the data item_len = data[offset + 1:offset + 1 + itemlen_len] # get the data item = data[offset + 1 + itemlen_len: offset + 1 + itemlen_len + item_len] # store it in collection new_collection[i] = item offset = offset + item_len + itemlen_len + 1 return new_collection def serialize_array(items): # serialize the length of the list itemlength = serialize_var_length_item(items) output = itemlength # now go through and append all your stuff for item in items: # get the variable length of the item # to be serialized itemlen = serialize_var_length_item(item) # add that indicator output = concat(output, itemlen) # now add the item output = concat(output, item) # return the stuff return output def serialize_var_length_item(item): # get the length of your stuff stuff_len = len(item) # now we need to know how many bytes the length of the array # will take to store # this is one byte if stuff_len <= 255: byte_len = b'\x01' # two byte elif stuff_len <= 65535: byte_len = b'\x02' # hopefully 4 byte else: byte_len = b'\x04' out = concat(byte_len, stuff_len) return out
def kyc_register(ctx, address): kyc_storage_key = concat(KYC_KEY, address) Put(ctx, kyc_storage_key, True) OnKYCRegister(address) return True
def do_tokens_data_of_owner(ctx, t_owner, start_index): """This method returns five of the owner's token's id and data starting at the given index. See `do_tokens_of_owner` for more detailed information behind rationale. :param StorageContext ctx: current store context :param byte[] t_owner: token owner :param bytes start_index: the index to start searching through the owner's tokens :return: dictionary of id, properties, and uri keys mapped to their corresponding token's data :rtype: bool or dict """ if len(t_owner) != 20: Notify(INVALID_ADDRESS_ERROR) return False if len(start_index) == b'\x00': start_index = b'\x01' # token id's cannot go below 1 start_key = concat(t_owner, start_index) count = 0 token_dict = {} token_iter = Find(ctx, t_owner) # while loop explained: keep looping through the owner's list # of tokens until 5 have been found beginning at the starting # index. # if statement explained: once a key has been found matching # my search key (or of greater value), # update the dictionary, increment the counter, # and disregard trying to find a matching key thereafter. # (once a key has been found matching my search key # (or greater), just get everything afterward while count < 5) # properties propsString = b'properties/[' print("Iteration before") while token_iter.next() and (count < 5): print("iteration") if (token_iter.Key >= start_key) or (count > 0): print("yessss") token_data = do_token_data(ctx, token_iter.Value) # simplify this if/when neo-boa implements something # like token_dict.update(token_data) # keys token_key = concat('token/', token_iter.Value) prop_key = concat('properties/', token_iter.Value) uri_key = concat('uri/', token_iter.Value) # update dictionary p3 = concat(token_data[prop_key], ',') propsString = concat(propsString, p3) count += 1 #if len(token_dict) >= 1: propsString = concat(propsString, ']') print(propsString) return propsString Notify(TOKEN_DNE_ERROR) return False
def getReviewKey(address, script_hash): return concat("review.neo.review.", concat(address, script_hash))
def Main(operation, args): """Entry point to the program :param str operation: The name of the operation to perform :param list args: A list of arguments along with the operation :return: The result of the operation :rtype: bytearray Token operations: - name(): returns name of token - symbol(): returns token symbol - totalSupply(): Returns the total token supply deployed in the system. - decimals(): Return decimalS - tokens(): Return enumerator with all tokens FEHLT - transfer(to, token_id, extra_arg): transfers a token - ownerOf(token_id): returns the owner of the specified token. - tokenURI(token_id): Returns a distinct Uniform Resource Identifier (URI) for a given asset. The URI data of a token supplies a reference to get more information about a specific token or its data. - balanceOf(owner): returns owner's current total tokens owned - tokensOfOwner(owner, starting_index): returns a dictionary that contains less than or equal to ten of the tokens owned by the specified address starting at the `starting_index`. - allowance(token_id): returns approved third-party spender of a token - approve(token_receiver, token_id, revoke): approve third party to spend a token - properties(token_id): returns a token's read-only data - supportedStandards(): returns a list of supported standards {"NEP-10"} - tokenData(token_id): returns a dictionary where token, property, and uri keys map to the corresponding data for the given `token_id` - tokensDataOfOwner(owner, starting_index): returns a dictionary that contains less than or equal to five of the tokens (where token, properties, and uri keys map to their corresponding data for each token id) owned by the specified address starting at the `starting_index`. - transferFrom(from, to, token_id, extra_arg): allows a third party to execute an approved transfer TOKEN_CONTRACT_OWNER operations: - mintToken(owner, properties, URI, extra_arg): create a new NFT token with the specified properties and URI and send it to the specified owner - modifyURI(token_id, token_data): modify specified token's URI data setters: - setName(name): sets the name of the token - setSymbol(symbol): sets the token's symbol - setSupportedStandards(supported_standards): sets the supported standards, 'NEP-10' is always the first element in the array """ # The trigger determines whether this smart contract is being run # in 'verification' mode or 'application' trigger = GetTrigger() # 'Verification' mode is used when trying to spend assets # (eg NEO, Gas) on behalf of this contract's address if trigger == Verification(): # if the script that sent this is the owner, we allow the spend if CheckWitness(TOKEN_CONTRACT_OWNER): return True elif trigger == Application(): ctx = GetContext() if operation == 'name': name = Get(ctx, 'name') if name: return name else: return TOKEN_NAME elif operation == 'symbol': symbol = Get(ctx, 'symbol') if symbol: return symbol else: return TOKEN_SYMBOL elif operation == 'decimals': return TOKEN_DECIMALS elif operation == 'totalSupply': return Get(ctx, TOKEN_CIRC_KEY) if operation == 'allowance': if len(args) == 1: return Get(ctx, concat('approved/', args[0])) Notify(ARG_ERROR) return False elif operation == 'approve': if len(args) == 3: # GetCallingScriptHash() can't be done within the # function because the calling script hash changes # depending on where the function is called return do_approve(ctx, GetCallingScriptHash(), args[0], args[1], args[2]) Notify(ARG_ERROR) return False elif operation == 'balanceOf': if len(args) == 1: if len(args[0]) == 20: return Get(ctx, args[0]) Notify(INVALID_ADDRESS_ERROR) return False Notify(ARG_ERROR) return False elif operation == 'ownerOf': if len(args) == 1: t_owner = Get(ctx, args[0]) if len(t_owner) == 20: return t_owner Notify(TOKEN_DNE_ERROR) return False Notify(ARG_ERROR) return False elif operation == 'properties': if len(args) == 1: token_properties = Get(ctx, concat('properties/', args[0])) if token_properties: return token_properties Notify(TOKEN_DNE_ERROR) return False Notify(ARG_ERROR) return False elif operation == 'tokenData': if len(args) == 1: # check to make sure the token exists if len(Get(ctx, args[0])) == 20: return Serialize(do_token_data(ctx, args[0])) Notify(TOKEN_DNE_ERROR) return False Notify(ARG_ERROR) return False elif operation == 'tokensDataOfOwner': if len(args) == 2: tokens_data_of_owner = do_tokens_data_of_owner( ctx, args[0], args[1]) if tokens_data_of_owner: return Serialize(tokens_data_of_owner) return False Notify(ARG_ERROR) return False elif operation == 'tokensOfOwner': if len(args) == 2: tokens_of_owner = do_tokens_of_owner(ctx, args[0], args[1]) if tokens_of_owner: return Serialize(tokens_of_owner) return False Notify(ARG_ERROR) return False elif operation == 'transfer': if len(args) >= 2: # GetCallingScriptHash() can't be done within the # function because the calling script hash changes # depending on where the function is called return do_transfer(ctx, GetCallingScriptHash(), args) Notify(ARG_ERROR) return False elif operation == 'transferFrom': if len(args) >= 3: return do_transfer_from(ctx, args) Notify(ARG_ERROR) return False elif operation == 'uri': if len(args) == 1: token_uri = Get(ctx, concat('uri/', args[0])) if token_uri: return token_uri Notify(TOKEN_DNE_ERROR) return False Notify(ARG_ERROR) return False # Administrative operations if CheckWitness(TOKEN_CONTRACT_OWNER): if operation == 'mintToken': if len(args) >= 3: return do_mint_token(ctx, args) Notify(ARG_ERROR) return False elif operation == 'modifyURI': if len(args) == 2: return do_modify_uri(ctx, args[0], args[1]) Notify(ARG_ERROR) return False elif operation == 'setName': if len(args) == 1: return do_set_config(ctx, 'name', args[0]) Notify(ARG_ERROR) return False elif operation == 'setSymbol': if len(args) == 1: return do_set_config(ctx, 'symbol', args[0]) Notify(ARG_ERROR) return False elif operation == 'setSupportedStandards': if len(args) >= 1: supported_standards = ['NEP-10'] for arg in args: supported_standards.append(arg) return do_set_config(ctx, 'supportedStandards', Serialize(supported_standards)) Notify(ARG_ERROR) return False else: Notify(PERMISSION_ERROR) return False Notify('unknown operation') return False
def getScriptKey(script_hash, index): return concat("review.neo.script.", concat(script_hash, index))
def do_transfer(ctx, caller, args): """Transfers a token at the specified id from the t_owner address to the t_to address :param StorageContext ctx: current store context :param bytes caller: calling script hash :param list args: 0: byte[] t_to: transfer to address 1: bytes t_id: token id 2: extra_arg: optional argument that can be passed (for use only with smart contracts) :return: transfer success :rtype: bool """ t_to = args[0] t_id = args[1] if len(t_to) != 20: Notify(INVALID_ADDRESS_ERROR) return False t_owner = Get(ctx, t_id) if len(t_owner) != 20: Notify(TOKEN_DNE_ERROR) return False if t_owner == t_to: Notify('transfer to self') return True # Verifies that the calling contract has verified the required # script hashes of the transaction/block is_token_owner = CheckWitness(t_owner) if is_token_owner and GetEntryScriptHash() != caller: Notify('third party script is bouncing the signature to us') return False # if token owner is a smart contract and is the calling # script hash, continue elif GetContract(t_owner) and t_owner == caller: is_token_owner = True if is_token_owner: # 1. Is t_to a smart contract? # If True, invoke the transfer_to_smart_contract # method, if transfer_to_smart_contract() returns False, # then reject the transfer if GetContract(t_to): success = transfer_to_smart_contract(ctx, t_owner, args, False) if success is False: return False else: if len(args) > 2: Notify(ARG_ERROR) return False res = remove_token_from_owners_list(ctx, t_owner, t_id) if res is False: Notify('unable to transfer token') return False Put(ctx, t_id, t_to) # update token's owner # remove any existing approvals for this token Delete(ctx, concat('approved/', t_id)) add_token_to_owners_list(ctx, t_to, t_id) # log this transfer event OnTransfer(t_owner, t_to, 1) OnNFTTransfer(t_owner, t_to, t_id) return True Notify(PERMISSION_ERROR) return False