def do_approve(self, storage: StorageAPI, t_owner, t_spender, amount): if not CheckWitness(t_owner): print("Incorrect permission") return False from_balance = storage.get(t_owner) # cannot approve an amount that is # currently greater than the from balance if from_balance >= amount: approval_key = concat(t_owner, t_spender) current_approved_balance = storage.get(approval_key) new_approved_balance = current_approved_balance + amount storage.put(approval_key, new_approved_balance) OnApprove(t_owner, t_spender, amount) return True return False
def do_approve(self, storage: StorageAPI, t_owner, t_spender, amount): if not CheckWitness(t_owner): print("Incorrect permission") return False from_balance = storage.get(t_owner) # Kann keinen Betrag bestätigen der momentan # größer ist als der von "from balance" if from_balance >= amount: approval_key = concat(t_owner, t_spender) current_approved_balance = storage.get(approval_key) new_approved_balance = current_approved_balance + amount storage.put(approval_key, new_approved_balance) OnApprove(t_owner, t_spender, amount) return True return False
def AddOracle(self, args): storage = StorageAPI() isValidOwner = self.ValidateOwner() if isValidOwner == False: return False isValidLength = ValidateArgsLength(args, 1) if isValidLength == False: return False oracleID = args[0] oracleKey = concat(self.oracle_prefix, oracleID) isOracle = storage.get(oracleKey) if isOracle == True: Log("Address is already an oracle") return False oracleCount = storage.get(self.oracle_count_key) newCount = oracleCount + 1 storage.put(oracleKey, True) storage.put(self.oracle_count_key, newCount) OnOracleAdded(oracleID, newCount) return True
def handle_nep51(self, operation, args, token: Token): # these first 3 don't require get ctx if operation == 'name': return token.name elif operation == 'decimals': return token.decimals elif operation == 'symbol': return token.symbol storage = StorageAPI() arg_error = 'Incorrect Arg Length' if operation == 'totalSupply': return storage.get(token.in_circulation_key) elif operation == 'balanceOf': if len(args) == 1: account = args[0] return storage.get(account) return arg_error elif operation == 'transfer': if len(args) == 3: t_from = args[0] t_to = args[1] t_amount = args[2] return self.do_transfer(storage, t_from, t_to, t_amount) return arg_error elif operation == 'transferFrom': if len(args) == 3: t_from = args[0] t_to = args[1] t_amount = args[2] return self.do_transfer_from(storage, t_from, t_to, t_amount) return arg_error elif operation == 'approve': if len(args) == 3: t_owner = args[0] t_spender = args[1] t_amount = args[2] return self.do_approve(storage, t_owner, t_spender, t_amount) return arg_error elif operation == 'allowance': if len(args) == 2: t_owner = args[0] t_spender = args[1] return self.do_allowance(storage, t_owner, t_spender) return arg_error return False
def calculate_can_exchange(self, token: Token, amount: int, address, verify_only: bool): """ Perform custom token exchange calculations here. :param token:Token The token settings for the sale :param amount:int Number of tokens to convert from asset to tokens :param address:bytearray The address to mint the tokens to :return: bool: Whether or not an address can exchange a specified amount """ height = GetHeight() storage = StorageAPI() current_in_circulation = storage.get(token.in_circulation_key) new_amount = current_in_circulation + amount if new_amount > token.total_supply: print("amount greater than total supply") return False print("trying to calculate height????") if height < token.block_sale_start: print("sale not begun yet") return False # if we are in free round, any amount if height > token.limited_round_end: print("Free for all, accept as much as possible") return True # check amount in limited round if amount <= token.max_exchange_limited_round: # check if they have already exchanged in the limited round r1key = concat(address, self.limited_round_key) has_exchanged = storage.get(r1key) # if not, then save the exchange for limited round if not has_exchanged: # note that this method can be invoked during the Verification trigger, so we have the # verify_only param to avoid the Storage.Put during the read-only Verification trigger. # this works around a "method Neo.Storage.Put not found in ->" error in InteropService.py # since Verification is read-only and thus uses a StateReader, not a StateMachine if not verify_only: storage.put(r1key, True) return True print("already exchanged in limited round") return False print("too much for limited round") return False
def calculate_can_exchange(self, token: Token, amount: int, address): """ Perform custom token exchange calculations here. :param token:Token The token settings for the sale :param amount:int Number of tokens to convert from asset to tokens :param address:bytearray The address to mint the tokens to :return: bool: Whether or not an address can exchange a specified amount """ height = GetHeight() storage = StorageAPI() current_in_circulation = storage.get(token.in_circulation_key) new_amount = current_in_circulation + amount if new_amount > token.total_supply: print("amount greater than total supply") return False print("trying to calculate height????") if height < token.block_sale_start: print("sale not begun yet") return False # if we are in free round, any amount if height > token.limited_round_end: print("Free for all, accept as much as possible") return True # check amount in limited round if amount <= token.max_exchange_limited_round: # check if they have already exchanged in the limited round r1key = concat(address, self.limited_round_key) has_exchanged = storage.get(r1key) # if not, then save the exchange for limited round if not has_exchanged: storage.put(r1key, True) return True print("already exchanged in limited round") return False print("too much for limited round") return False
def calculate_can_exchange(self, token: Token, amount: int, address): """ Führt benutzerdefinierte Token exchange Kalkulationen aus. :param token:Token Die Token Einstellungen für den Verkauf :param amount:int Nummer der Tokens die von Asset zu Tokens konvertiert werden :param address:bytearray Die Adresse wo die Tokens erzeugt werden sollen :return: bool: Ob eine Adresse einen bestimmten Betrag tauschen kann oder nicht """ height = GetHeight() storage = StorageAPI() current_in_circulation = storage.get(token.in_circulation_key) new_amount = current_in_circulation + amount if new_amount > token.total_supply: # print("amount greater than total supply") return False if height < token.block_sale_start: # print("sale not begun yet") return False # Ob wir in einer freien Runde sind, jeder Betrag if height > token.limited_round_end: # print("Free for all, accept as much as possible") return True # Überprüfe Betrag in einer limitierten Runde if amount <= token.max_exchange_limited_round: # Überprüfe ob die Adresse bereits in einer limitierten Runde teilgenommen haben r1key = concat(address, self.limited_round_key) has_exchanged = storage.get(r1key) # falls nicht, dann sichere den exchange für die limitierte Runde if not has_exchanged: storage.put(r1key, True) return True print("already exchanged in limited round") return False print("too much for limited round") return False
def do_transfer_from(self, storage: StorageAPI, t_from, t_to, amount): if amount <= 0: return False available_key = concat(t_from, t_to) if len(available_key) != 40: return False if not CheckWitness(t_to): print("to address is not the tx sender") return False available_to_to_addr = storage.get(available_key) if available_to_to_addr < amount: print("Insufficient funds approved") return False from_balance = storage.get(t_from) if from_balance < amount: print("Insufficient tokens in from balance") return False to_balance = storage.get(t_to) new_from_balance = from_balance - amount new_to_balance = to_balance + amount storage.put(t_to, new_to_balance) storage.put(t_from, new_from_balance) print("transfer complete") new_allowance = available_to_to_addr - amount if new_allowance == 0: print("removing all balance") storage.delete(available_key) else: print("updating allowance to new allowance") storage.put(available_key, new_allowance) OnTransfer(t_from, t_to, amount) return True
def crowdfunding_create(args): """ args: 0: crowdfunding address 1..n: member addresses """ print("Create a crowdfunding") storage = StorageAPI() crowdfunding_address = args[0] crowdfunding_meta_key = storage.get_crowdfunding_members_key( crowdfunding_address) print(crowdfunding_meta_key) # Check for minimum number of arguments nargs = len(args) if nargs < 3: print( "Error: need at least 3 arguments: (1) crowdfunding address, (2+3) member addresses" ) return False # Check if this address or crowdfunding_meta already exists balance = storage.get(crowdfunding_address) if len(balance) > 0: print("Error: address is already in use") return False meta = storage.get(crowdfunding_meta_key) if len(meta) > 0: print("Error: crowdfunding is already setup") return False # Build list of addresses to store in meta key print("Build list of addresses") nargs = len(args) member_addresses = args[1] print(member_addresses) i = 2 while i < nargs: member_address = args[i] print(member_address) i += 1 member_addresses = concat(member_addresses, member_address) storage.put(crowdfunding_meta_key, member_addresses) print("Created the crowdfunding with those member addresses") print(member_addresses)
def do_transfer_from(self, storage: StorageAPI, t_from, t_to, amount): if amount <= 0: return False available_key = concat(t_from, t_to) if len(available_key) != 40: return False available_to_to_addr = storage.get(available_key) if available_to_to_addr < amount: print("Insufficient funds approved") return False from_balance = storage.get(t_from) if from_balance < amount: print("Insufficient tokens in from balance") return False # TODO: Check if target is crowdfunding # If no crowdfunding, do normal transfer to_balance = storage.get(t_to) new_from_balance = from_balance - amount new_to_balance = to_balance + amount storage.put(t_to, new_to_balance) storage.put(t_from, new_from_balance) print("transfer complete") new_allowance = available_to_to_addr - amount if new_allowance == 0: print("removing all balance") storage.delete(available_key) else: print("updating allowance to new allowance") storage.put(available_key, new_allowance) OnTransfer(t_from, t_to, amount) return True
def crowdfunding_get_members(crowdfunding_address): storage = StorageAPI() crowdfunding_meta_key = storage.get_crowdfunding_members_key( crowdfunding_address) print(crowdfunding_meta_key) # Check if this address or crowdfunding_meta already exists addresses = storage.get(crowdfunding_meta_key) if len(addresses) == 0: print("Error: address does not belong to a crowdfunding") return False n = len(addresses) num_addresses = n / 20 msg = ["Crowdfunding found. Members:", num_addresses] Notify(msg) address_list = [] i = 0 while i < num_addresses: addr = addresses[0:20] addresses = addresses[20:] address_list.append(addr) i += 1 return address_list
def do_allowance(self, storage: StorageAPI, t_owner, t_spender): allowance_key = concat(t_owner, t_spender) amount = storage.get(allowance_key) return amount
def do_approve(self, storage: StorageAPI, t_owner, t_spender, amount): if not CheckWitness(t_owner): print("Incorrect permission") return False if amount < 0: print("Negative amount") return False from_balance = storage.get(t_owner) # cannot approve an amount that is # currently greater than the from balance if from_balance >= amount: approval_key = concat(t_owner, t_spender) if amount == 0: storage.delete(approval_key) else: storage.put(approval_key, amount) OnApprove(t_owner, t_spender, amount) return True return False
def exchange(self, token: Token): attachments = get_asset_attachments() storage = StorageAPI() can_exchange = self.can_exchange(token, attachments, storage, False) if not can_exchange: print("Cannot exchange value") if attachments.neo_attached > 0: OnRefund(attachments.sender_addr, attachments.neo_attached) return False current_balance = storage.get(attachments.sender_addr) exchanged_tokens = attachments.neo_attached * token.tokens_per_neo / 100000000 new_total = exchanged_tokens + current_balance storage.put(attachments.sender_addr, new_total) token.add_to_circulation(exchanged_tokens, storage) OnTransfer(attachments.receiver_addr, attachments.sender_addr, exchanged_tokens) return True
def level_of(address): """ Return the level of the user who owns the address. """ storage = StorageAPI() level_key = storage.get_level_key(address) stored_level = storage.get(level_key) return stored_level
def InitialiseQueue(storage: StorageAPI, args) -> Queue: queue = Queue() queue = queue.CreateQueueIDs(args) queue.index = storage.get(queue.indexKey) if queue.index == 0: # Indexing starts at 1 queue.index = 1 rawBetID = concat(queue.rawQueueID, queue.index) queue.betID = sha1(rawBetID) betStatusKey = concat("bet/status/", queue.betID) queue.betStatus = storage.get(betStatusKey) return queue
def is_crowdfunding_address(crowdfunding_address): storage = StorageAPI() crowdfunding_meta_key = storage.get_crowdfunding_members_key( crowdfunding_address) addresses = storage.get(crowdfunding_meta_key) if len(addresses) == 0: return False return True
def get_circulation(self, storage:StorageAPI): """ Get the total amount of tokens in circulation :param storage:StorageAPI A StorageAPI object for storage interaction :return: int: Total amount in circulation """ return storage.get(self.in_circulation_key)
def get_circulation(self, storage:StorageAPI): """ Gibt den Gesamtbetrag der Tokens im Umlauf zurück :param storage:StorageAPI Ein StorageAPI Objekt für storage Interaktionen :return: int: Gesamtbetrag im Umlauf """ return storage.get(self.in_circulation_key)
def get_circulation(self, storage: StorageAPI): """ Get the total amount of tokens in circulation :param storage:StorageAPI A StorageAPI object for storage interaction :return: int: Total amount in circulation """ return storage.get(self.in_circulation_key)
def CheckEventConsensus(self, storage: StorageAPI, oracleKey, countKey): oracleStatus = storage.get(oracleKey) if oracleStatus == "participated": Log("Oracle has already participated") return False count = storage.get(countKey) newCount = count + 1 storage.put(countKey, newCount) storage.put(oracleKey, "participated") oracleCount = storage.get(self.oracle_count_key) consensusRequired = storage.get(self.oracle_consensus_key) factoredCount = newCount * 100 required = oracleCount * consensusRequired return factoredCount >= required
def calculate_can_exchange(self, token: Token, amount: int, address, verify_only: bool): height = GetHeight() storage = StorageAPI() current_in_circulation = storage.get(token.in_circulation_key) new_amount = current_in_circulation + amount if new_amount > token.total_supply: print("amount greater than total supply") return False print("trying to calculate height????") if height < token.block_sale_start: print("sale not begun yet") return False if height > token.limited_round_end: print("Free for all, accept as much as possible") return True if amount <= token.max_exchange_limited_round: r1key = concat(address, self.limited_round_key) has_exchanged = storage.get(r1key) if not has_exchanged: if not verify_only: storage.put(r1key, True) return True print("already exchanged in limited round") return False print("too much for limited round") return False
def crowdsale_available_amount(self): """ :return: int Der Betrag der Tokens der für den Crowdsale Verkauf übrig ist """ storage = StorageAPI() in_circ = storage.get(self.in_circulation_key) available = self.total_supply - in_circ return available
def add_to_circulation(self, amount:int, storage:StorageAPI): """ Addiert einen Betrag an Tokens zu den Tokens im Umlauf :param amount: int Der Betrag der zu den Tokens im Umlauf addiert werden soll :param storage:StorageAPI Ein StorageAPI Objekt für storage Interaktionen """ current_supply = storage.get(self.in_circulation_key) current_supply += amount storage.put(self.in_circulation_key, current_supply)
def crowdsale_available_amount(self): """ :return: int The amount of tokens left for sale in the crowdsale """ storage = StorageAPI() in_circ = storage.get(self.in_circulation_key) available = self.total_supply - in_circ return available
def get_kyc_status(self, address, storage:StorageAPI): """ Looks up the KYC status of an address :param address:bytearray The address to lookup :param storage:StorageAPI A StorageAPI object for storage interaction :return: bool: KYC Status of address """ kyc_storage_key = concat(self.kyc_key, address) return storage.get(kyc_storage_key)
def get_kyc_status(self, address, storage:StorageAPI): """ Überprüft den KYC Status einer Adresse :param address:bytearray Die zu durchsuchende Adresse :param storage:StorageAPI Ein StorageAPI Objekt für Storage Interaktionen :return: bool: KYC Status der Adresse """ kyc_storage_key = concat(self.kyc_key, address) return storage.get(kyc_storage_key)
def add_to_circulation(self, amount:int, storage:StorageAPI): """ Adds an amount of token to circlulation :param amount: int the amount to add to circulation :param storage:StorageAPI A StorageAPI object for storage interaction """ current_supply = storage.get(self.in_circulation_key) current_supply += amount storage.put(self.in_circulation_key, current_supply)
def get_kyc_status(self, address, storage: StorageAPI): """ Looks up the KYC status of an address :param address:bytearray The address to lookup :param storage:StorageAPI A StorageAPI object for storage interaction :return: bool: KYC Status of address """ kyc_storage_key = concat(self.kyc_key, address) return storage.get(kyc_storage_key)
def kyc_status(self, args): storage = StorageAPI() if len(args) > 0: addr = args[0] kyc_storage_key = concat(self.kyc_key, addr) return storage.get(kyc_storage_key) return False
def add_to_circulation(self, amount: int, storage: StorageAPI): """ Adds an amount of token to circlulation :param amount: int the amount to add to circulation :param storage:StorageAPI A StorageAPI object for storage interaction """ current_supply = storage.get(self.in_circulation_key) current_supply += amount storage.put(self.in_circulation_key, current_supply)
def do_transfer(self, storage: StorageAPI, t_from, t_to, amount): if amount <= 0: return False if len(t_to) != 20: return False if CheckWitness(t_from): if t_from == t_to: print("transfer to self!") return True from_val = storage.get(t_from) if from_val < amount: print("insufficient funds") return False if from_val == amount: storage.delete(t_from) else: difference = from_val - amount storage.put(t_from, difference) to_value = storage.get(t_to) to_total = to_value + amount storage.put(t_to, to_total) OnTransfer(t_from, t_to, amount) return True else: print("from address is not the tx sender") return False
def InitialiseBet(storage: StorageAPI, args) -> Bet: bet = Bet() bet.eventID = args[0] bet.outcome = args[1] bet.odds = args[2] bet.betType = args[3] bet.betIndex = args[4] bet = bet.CreateBetID() bet.betAmountKey = concat("bet/amount/", bet.betID) bet.unmatchedAmountKey = concat("bet/unmatched/", bet.betID) bet.betMakerKey = concat("bet/maker/", bet.betID) bet.statusKey = concat("bet/status/", bet.betID) bet.betAmount = storage.get(bet.betAmountKey) bet.unmatchedAmount = storage.get(bet.unmatchedAmountKey) bet.betMaker = storage.get(bet.betMakerKey) bet.status = storage.get(bet.statusKey) return bet
def exchange(self, token: Token): """ :param token:Token The token object with NEP5/sale settings :return: bool: Whether the exchange was successful """ attachments = get_asset_attachments() # type: Attachments storage = StorageAPI() # this looks up whether the exchange can proceed can_exchange = self.can_exchange(token, attachments, storage) if not can_exchange: print("Cannot exchange value") # This should only happen in the case that there are a lot of TX on the final # block before the total amount is reached. An amount of TX will get through # the verification phase because the total amount cannot be updated during that phase # because of this, there should be a process in place to manually refund tokens OnRefund(attachments.sender_addr, attachments.neo_attached) return False # lookup the current balance of the address current_balance = storage.get(attachments.sender_addr) # calculate the amount of tokens the attached neo will earn exchanged_tokens = attachments.neo_attached * token.tokens_per_neo / 100000000 # if you want to exchange gas instead of neo, use this # exchanged_tokens += attachments.gas_attached * token.tokens_per_gas / 100000000 # add it to the the exchanged tokens and persist in storage new_total = exchanged_tokens + current_balance storage.put(attachments.sender_addr, new_total) # update the in circulation amount token.add_to_circulation(exchanged_tokens, storage) # dispatch transfer event OnTransfer(attachments.receiver_addr, attachments.sender_addr, exchanged_tokens) return True
def kyc_status(self, args): """ Gets the KYC Status of an address :param args:list a list of arguments :return: bool: Returns the kyc status of an address """ storage = StorageAPI() if len(args) > 0: addr = args[0] kyc_storage_key = concat(self.kyc_key, addr) return storage.get(kyc_storage_key) return False
def deploy(token: Token): """ :param token: Token The token to deploy :return: bool: Whether the operation was successful """ if not CheckWitness(token.owner): print("Must be owner to deploy") return False storage = StorageAPI() if not storage.get('initialized'): # do deploy logic storage.put('initialized', 1) storage.put(token.owner, token.initial_amount) token.add_to_circulation(token.initial_amount, storage) return True return False