def handle_sts(self, operation, args): # project_id always first arg project_id = args[0] sts = sts_get(project_id) storage = StorageManager() arg_error = 'Incorrect Arg Length' if operation == 'decimals': return sts.decimals elif operation == 'symbol': return sts.symbol elif operation == 'totalSupply': return sts.total_supply elif operation == 'balanceOf': if len(args) == 2: account = args[1] return storage.get_double(project_id, account) return arg_error elif operation == 'transfer': if len(args) == 4: t_from = args[1] t_to = args[2] t_amount = args[3] return self.do_transfer(project_id, t_from, t_to, t_amount) return arg_error elif operation == 'transferFrom': if len(args) == 4: t_from = args[1] t_to = args[2] t_amount = args[3] return self.do_transfer_from(project_id, t_from, t_to, t_amount) return arg_error elif operation == 'approve': if len(args) == 4: t_owner = args[1] t_spender = args[2] t_amount = args[3] return self.do_approve(project_id, t_owner, t_spender, t_amount) return arg_error elif operation == 'allowance': if len(args) == 3: t_owner = args[1] t_spender = args[2] return self.do_allowance(project_id, t_owner, t_spender) return arg_error return False
def ms_update_progress(ms: Milestone, updated_progress): """ Args: ms (Milestone): Milestone object containing specific attributes updated_progress (int): New progress of the milestone Return: (int): The avaliable tokens for the Milestone """ storage = StorageManager() # If the updated progress is higher if updated_progress > ms.progress: # Clamp at 100% if updated_progress > 100: updated_progress = 100 # Updates object variable ms.progress = updated_progress # Output milestone info updated_milestone_info = [ ms.title, ms.subtitle, ms.extra_info_hash, updated_progress ] # Saving info to storage updated_milestone_info_serialized = storage.serialize_array( updated_milestone_info) storage.put_triple('MS', ms.project_id, ms.milestone_id, updated_milestone_info_serialized)
def sts_get(project_id) -> SmartTokenShare: """ Get the info list Args: project_id (str): ID for referencing the project Return: (SmartTokenShare): Returns a Smart Token Share object containing attributes """ storage = StorageManager() sts = SmartTokenShare() # Pull STS info sts_info_serialized = storage.get_double('STS', project_id) if sts_info_serialized: sts_info = storage.deserialize_bytearray(sts_info_serialized) # Saves vars to object sts.project_id = project_id sts.symbol = sts_info[0] sts.decimals = sts_info[1] sts.owner = sts_info[2] sts.total_supply = sts_info[3] sts.total_in_circulation = sts_info[4] print('sts_get') print(sts.owner) return sts
def sts_add_to_total_circulation(sts: SmartTokenShare, amount: int): """ Adds an amount of token to circlulation Args: sts (SmartTokenShare): Smart Token Share object containing specific attributes amount (int): amount of tokens added """ storage = StorageManager() # Calculation sts.total_in_circulation = sts.total_in_circulation + amount # output STS info updated_sts_info = [ sts.symbol, sts.decimals, sts.owner, sts.total_supply, sts.total_in_circulation ] # Save STS info updated_sts_info_serialized = storage.serialize_array(updated_sts_info) storage.put_double('STS', sts.project_id, updated_sts_info_serialized)
def test_add_to_total_circulation(self): sts = SmartTokenShare() # Setting default info storage = StorageManager() storage.put_double('STS', self.test_project_id, self.test_sts_info) # Running add_to_total_circulation() sts.add_to_total_circulation(self.test_project_id, self.test_add_amount) sts.add_to_total_circulation(self.test_project_id, self.test_add_amount) sts.add_to_total_circulation(self.test_project_id, self.test_add_amount) in_circ = sts.get_total_circulation(self.test_project_id) test_in_circ = self.test_add_amount * 3 # Check Test if in_circ == test_in_circ: print('test_add_to_total_circulation PASSED') return True print('test_add_to_total_circulation FAILED') return False
def test_add_to_circulation(self): fs = FundingStage() # Setting default info storage = StorageManager() storage.put_triple('FS', self.test_project_id, self.test_funding_stage_id, self.test_fs_info) # # Running add_to_crowdfund_circulation() # fs.add_to_circulation(self.test_project_id, self.test_funding_stage_id, self.test_add_amount) # fs.add_to_circulation(self.test_project_id, self.test_funding_stage_id, self.test_add_amount) # fs.add_to_circulation(self.test_project_id, self.test_funding_stage_id, self.test_add_amount) in_circ = fs.get_circulation(self.test_project_id, self.test_funding_stage_id) test_in_circ = self.test_add_amount * 3 # Check Test if in_circ == test_in_circ: print('test_add_to_circulation PASSED') return True print('test_add_to_circulation FAILED') return False
def ms_get(project_id, milestone_id) -> Milestone: """ Pulls an existing Milestone from storage using the input attributes, and returns a Milestone object Args: project_id (str): ID for referencing the project milestone_id (str): ID for referencing the Milestone Return: (Milestone): Returns a Milestone object containing attributes """ storage = StorageManager() ms = Milestone() # Pull Milestone info milestone_info_serialized = storage.get_triple('MS', project_id, milestone_id) milestone_info = storage.deserialize_bytearray(milestone_info_serialized) if len(milestone_info) == 4: # Saves vars to object ms.project_id = project_id ms.milestone_id = milestone_id ms.title = milestone_info[0] ms.subtitle = milestone_info[1] ms.extra_info_hash = milestone_info[2] ms.progress = milestone_info[3] return ms
def fs_add_to_circulation(fs: FundingStage, amount: int) -> bool: """ Args: fs (FundingStage): Funding Stage object containing specific attributes amount (int): Amount of tokens added """ storage = StorageManager() # Calculation fs.in_circulation = fs.in_circulation + amount # Output STS info updated_fs_info = [ fs.start_block, fs.end_block, fs.supply, fs.tokens_per_gas, fs.in_circulation ] # Serialize array and save to storage updated_fs_info_serialized = storage.serialize_array(updated_fs_info) storage.put_triple('FS', fs.project_id, fs.funding_stage_id, updated_fs_info_serialized) # Update sts ** sts = sts_get(fs.project_id) sts_add_to_total_circulation(sts, amount) return True
def do_allowance(self, project_id, t_owner, t_spender): storage = StorageManager() allowance_key = concat(t_owner, t_spender) amount = storage.get_double(project_id, allowance_key) return amount
def fr_set_active_index(project_id, idx): """ Sets the active index Args: project_id (list): ID for referencing the project idx (int): new active index """ storage = StorageManager() storage.put_double(project_id, 'FR_active_idx', idx)
def claim(): storage = StorageManager() attachments = get_asset_attachments() claim_amount = storage.get_double('CLAIM', attachments.receiver_addr) if claim_amount == attachments.gas_attached: return True return False
def fr_get_active_index(project_id): """ Gets the active index Args: project_id (list): ID for referencing the project Return: (int): Index """ storage = StorageManager() idx = storage.get_double(project_id, 'FR_active_idx') return idx
def fs_create(project_id, funding_stage_id, start_block, end_block, supply, tokens_per_gas) -> FundingStage: """ Creates a new Funding Stage using the input attributes, saves it to storage and returns a FundingStage object Args: project_id (str): ID for referencing the project funding_stage_id (str): ID for referencing the funding stage start_block (int): Block to start fund end_block (int): Block to end fund supply (int): Supply of the token in this fs tokens_per_gas (int): Token to gas ratio Return: (FundingStage): Returns a funding stage object containing these attributes """ # init objects storage = StorageManager() fs = FundingStage() # Saves vars to object fs.project_id = project_id fs.funding_stage_id = funding_stage_id fs.start_block = start_block fs.end_block = end_block fs.supply = supply fs.tokens_per_gas = tokens_per_gas fs.in_circulation = 0 # Info structure fs_info = [start_block, end_block, supply, tokens_per_gas, 0] # Saving info to storage fs_info_serialized = storage.serialize_array(fs_info) storage.put_triple('FS', project_id, funding_stage_id, fs_info_serialized) return fs
def ms_create(project_id, milestone_id, title, subtitle, extra_info_hash) -> Milestone: """ Creates a new Milestone using the input attributes, saves it to storage and returns a Milestone object Args: project_id (str): ID for referencing the project milestone_id (str): ID for referencing the Milestone title (str): Block to start fund subtitle (str): Block to end fund extra_info_hash (str): Supply of the token in this fs Return: (Milestone): Returns a Milestone object containing these attributes """ # init objects storage = StorageManager() ms = Milestone() # Saves vars to object ms.project_id = project_id ms.milestone_id = milestone_id ms.title = title ms.subtitle = subtitle ms.extra_info_hash = extra_info_hash # Sets progress to 0 ms.progress = 0 # Info structure milestone_info = [title, subtitle, extra_info_hash, 0] # Saving info to storage milestone_info_serialized = storage.serialize_array(milestone_info) storage.put_triple('MS', project_id, milestone_id, milestone_info_serialized) return ms
def kyc_status(self, project_id, address): """ Gets the KYC Status of an address Args: args (list): list a list of arguments sts (SmartTokenShare): Smart Token Share reference object Return: (bool): Returns the kyc status of an address """ storage = StorageManager() return storage.get_triple(project_id, 'KYC_address', address)
def fs_claim_system_fee(fs: FundingStage, system_owner_addr): storage = StorageManager() if CheckWitness(system_owner_addr): # If the funding stage complted sucessfully if fs_status(fs) == 1: # Calculating fee fee_calculated = fs_calculate_system_fee(fs) # Sets the claim amount for the address, as 10^8 storage.put_double('CLAIM', system_owner_addr, fee_calculated) return True return False
def kyc_submit(self, project_id, address, phys_address, first_name, last_name, id_type, id_number, id_expiry, file_location, file_hash): """ Submits a KYC information to the smart contract Args: sts (SmartTokenShare): Smart Token Share reference object address (str): Wallet address to whitelist phys_address (str): Physical Address first_name (str): First Name last_name (str): Last Name id_type (str): Id type, eg passport, drivers licence id_number (str): ID Number id_expiry (str): Expiry data file_location (str): web location where file is stored file_hash (str): hash of file """ storage = StorageManager() # Checking its the correct address if CheckWitness(address): if len(address) == 20: # Combines all args into a single list output_kyc_array = list(address, phys_address, first_name, last_name, id_type, id_number, id_expiry, file_location, file_hash) # Serialises list into a single bytearray, and stores that into storeage serialized_kyc = storage.serialize_array(output_kyc_array) storage.put_triple('KYC', project_id, address, serialized_kyc)
def fr_list_append(project_id, key, new_item): """Adds the input list of funding stages to storage (as serialized array) Args: project_id (list): ID for referencing the project new_list (list): list of funding stages to save to storage """ storage = StorageManager() print('new_item') print(new_item) # Gets current stored list current_serialized_list = storage.get_double(project_id, key) # Converts serialized list to normal list current_list = storage.deserialize_bytearray(current_serialized_list) current_list_len = len(current_list) print('current_list_len') print(current_list_len) if current_list_len == 0: output_list = [new_item] else: output_list = current_list output_list.append(new_item) # Serializes list serialized_output_list = storage.serialize_array(output_list) print('serialized_output_list') print(serialized_output_list) # Saves updated serialized list to storage storage.put_double(project_id, key, serialized_output_list)
def test_create(self): sts = SmartTokenShare() # Running create() sts.create(self.test_project_id, self.test_symbol, self.test_decimals, self.test_owner, self.test_total_supply) # Pull output from storage storage = StorageManager() output = storage.get_double('STS', self.test_project_id) # Check Test if output == self.test_sts_info: print('test_create PASSED') return True print('test_create FAILED') return False
def fr_get_list(project_id, key): """ Registers all input addresses Args: project_id (list): ID for referencing the project Return: (list): Output list for key """ storage = StorageManager() # Gets current stored list serialized_list = storage.get_double(project_id, key) # Converts serialized list to normal list output_list = storage.deserialize_bytearray(serialized_list) # output_list = ['sdad','sdads'] return output_list
def test_create(self): fs = FundingStage() # Running start_new_crowdfund() fs.create(self.test_project_id, self.test_funding_stage_id, self.test_start_block, self.test_end_block, self.test_supply, self.test_tokens_per_gas) # Pull output from storage storage = StorageManager() output = storage.get_triple('FS', self.test_project_id, self.test_funding_stage_id) # Check Test if output == self.test_fs_info: print('test_create PASSED') return True print('test_create FAILED') return False
def do_transfer(self, project_id, t_from, t_to, amount): storage = StorageManager() # Pointless if amount <= 0: return False # Validate address if CheckWitness(t_from): # Pointless if t_from == t_to: print("transfer to self!") return True from_val = storage.get_double(project_id, t_from) if from_val < amount: print("insufficient funds") return False if from_val == amount: storage.delete_double(project_id, t_from) else: difference = from_val - amount storage.put_double(project_id, t_from, difference) to_value = storage.get_double(project_id, t_to) to_total = to_value + amount storage.put_double(project_id, t_to, to_total) OnTransfer(project_id, t_from, t_to, amount) return True else: print("from address is not the tx sender") return False
def kyc_register(self, project_id, addresses): """ Registers all input addresses Args: args (list): list a list of arguments sts (SmartTokenShare): Smart Token Share reference object Return: (int): The number of addresses to registered for KYC """ # Gets sts object sts = sts_get(project_id) print('kyc_register') print(sts.owner) ok_count = 0 check_addr = sts.owner check = CheckWitness(check_addr) print('check') print(check) if CheckWitness(check_addr): for address in addresses: if len(address) == 20: storage = StorageManager() storage.put_triple(project_id, 'KYC_address', address, True) OnKYCRegister(project_id, address) ok_count += 1 else: print(sts.owner) print('Only the project owner can register kyc addresses') return 0 return ok_count
def do_approve(self, project_id, t_owner, t_spender, amount): storage = StorageManager() if not CheckWitness(t_owner): print("Incorrect permission") return False from_balance = storage.get_double(project_id, 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_double( project_id, approval_key) new_approved_balance = current_approved_balance + amount storage.put_double(project_id, approval_key, new_approved_balance) OnApprove(project_id, t_owner, t_spender, amount) return True return False
def test_can_exchange(self): fs = FundingStage() attachments = get_asset_attachments() # Registers KYC address storage = StorageManager() storage.put_triple(self.test_project_id, 'KYC_address', self.test_address2, True) fs.create(self.test_project_id, 'test_can_exchange', 1, 999999, 10000, 100) test_result = fs.can_exchange(self.test_project_id, 'test_can_exchange', attachments) # Check Test if test_result: print('test_can_exchange PASSED') return True print('test_can_exchange FAILED') return False
def fs_claim_contributions(fs: FundingStage, owner_addr): """ This is required to prep a claim for a verification transaction Args: fs (FundingStage): Funding Stage object containing specific attributes owner_addr (bytearray): Address of the claim deposit address Return: (bool): Can Claim """ storage = StorageManager() if CheckWitness(owner_addr): # If the funding stage complted sucessfully if fs_status(fs) == 1: # Checks the owner_addr matches the sts project owner sts = sts_get(fs.project_id) if sts_get_attr(sts, 'owner') == owner_addr: # Calculates the gas amount contributed, decimal safe 10^8 gas_contributed = fs.in_circulation / fs.tokens_per_gas * 100000000 # Calculating fee fee_calculated = fs_calculate_system_fee(fs) # Deducting fees gas_to_claim = gas_contributed - fee_calculated # Sets the claim amount for the address, as 10^8 storage.put_double('CLAIM', owner_addr, gas_to_claim) return True return False
def test_available_amount(self): fs = FundingStage() # Running crowdfund_available_amount() # fs.create(self.test_project_id, 'test_available_amount', self.test_start_block, self.test_end_block, self.test_supply, self.test_tokens_per_gas) storage = StorageManager() storage.put_triple('FS', self.test_project_id, 'test_available_amount', self.test_fs_info) available = fs.available_amount(self.test_project_id, 'test_available_amount') print('available') print(available) test_available = self.test_supply - 0 # Check Test if available == test_available: print('test_available_amount PASSED') return True print('test_available_amount FAILED') return False
def fs_get(project_id, funding_stage_id) -> FundingStage: """ Pulls an existing Funding Stage from storage using the input attributes, and returns a FundingStage object Args: project_id (str): ID for referencing the project funding_stage_id (str): ID for referencing the funding stage Return: (FundingStage): Returns a funding stage object containing attributes """ storage = StorageManager() fs = FundingStage() # Pull FundingStage info fs_info_serialized = storage.get_triple('FS', project_id, funding_stage_id) if not fs_info_serialized: print('fs_info_serialized is null') return None fs_info = storage.deserialize_bytearray(fs_info_serialized) # Saves vars to object fs.project_id = project_id fs.funding_stage_id = funding_stage_id fs.start_block = fs_info[0] fs.end_block = fs_info[1] fs.supply = fs_info[2] fs.tokens_per_gas = fs_info[3] fs.in_circulation = fs_info[4] return fs
def get_kyc_submission(self, project_id, address): """ Submits a KYC information to the smart contract Args: sts (SmartTokenShare): Smart Token Share reference object address (str): Wallet address to whitelist Returns: (list): Of KYC submission list (address, phys_address, first_name, last_name, id_type, id_number, id_expiry, file_location, file_hash) """ storage = StorageManager() # Gets sts object sts = sts_get(project_id) # Checking the invoker is the owner/admin if CheckWitness(sts.owner): if len(address) == 20: # Deserialises bytearray back into a list serialized_kyc_sub = storage.get_triple('KYC', project_id, address) return storage.deserialize_bytearray(serialized_kyc_sub)
def fs_refund(fs: FundingStage, refund_addr): """ This is required to prep a refund for for a verification transaction Args: fs (FundingStage): Funding Stage object containing specific attributes refund_addr (bytearray): Address of the refund address in question Return: (bool): Can Refund """ storage = StorageManager() if CheckWitness(refund_addr): # If the funding stage failed if fs_status(fs) != 1: # lookup the current balance of the address current_sts_balance = fs_get_addr_balance(fs, refund_addr) # Calculate gas from current_sts_balance gas_contribution = current_sts_balance / fs.tokens_per_gas * 100000000 # unlocks current_sts_balance to refund_addr, as 10^8 storage.put_double('CLAIM', refund_addr, gas_contribution) # sets refund_addr balance to 0 fs_set_addr_balance(fs, refund_addr, 0) return True return False