def checker(addr: str, web3: Web3) -> bool: testcases = { "": True, "a": True, "ab": False, "aba": True, "paradigm": False, "tattarrattat": True, } for i in range(10): if i % 2 == 0: if random.random() > 0.5: str = random_string(63) testcases[str + random_string(1) + ''.join(reversed(list(str)))] = True else: str = random_string(64) testcases[str + ''.join(reversed(list(str)))] = True else: testcases[random_string(128)] = False for k, v in testcases.items(): data = web3.sha3(text="test(string)")[:4] + encode_single( 'uint256', 32) + encode_single('string', k) result = web3.eth.call({ "to": addr, "data": data, }) if int(result.hex(), 16) != v: return False return True
def find_transaction_details_in_redeem_event(self, recipient_address: str, secret_hash: str, block_number: int): if not self.filtering_supported: raise NotImplementedError event_signature_hash = self.web3.sha3( text="RedeemSwap(address,bytes20,bytes32)").hex() filter_options = { 'fromBlock': block_number, 'address': self.contract_address, 'topics': [ event_signature_hash, '0x' + encode_single('address', recipient_address).hex(), '0x' + encode_single('bytes20', bytes.fromhex(secret_hash)).hex() ] } event_filter = self.web3.eth.filter(filter_options) for _ in range(ETH_FILTER_MAX_ATTEMPTS): events = event_filter.get_all_entries() if events: return { 'secret': events[0]['data'][2:], 'transaction_hash': events[0]['transactionHash'].hex() }
def hash_reward_proof(channel_identifier, reward_amount, token_network_address, chain_id, nonce): return eth_sign_hash_message( encode_single('uint256', channel_identifier) + encode_single('uint256', reward_amount) + Web3.toBytes(hexstr=token_network_address) + encode_single('uint256', chain_id) + encode_single('uint256', nonce), )
def find_transaction_details_in_redeem_event(self, recipient_address: str, secret_hash: str, block_number: int): # web3.gastracker.io node does not support filtering # etc-geth.0xinfra.com not is not stable so it is used only for filtering filterable_web3 = Web3(HTTPProvider('https://etc-geth.0xinfra.com/')) event_signature_hash = self.web3.sha3( text="RedeemSwap(address,bytes20,bytes32)").hex() filter_options = { 'fromBlock': block_number, 'address': self.contract_address, 'topics': [ event_signature_hash, '0x' + encode_single('address', recipient_address).hex(), '0x' + encode_single('bytes20', bytes.fromhex(secret_hash)).hex() ] } event_filter = filterable_web3.eth.filter(filter_options) for _ in range(ETH_FILTER_MAX_ATTEMPTS): events = event_filter.get_all_entries() if events: return { 'secret': events[0]['data'][2:], 'transaction_hash': events[0]['transactionHash'].hex() }
def packed_data(self) -> bytes: return ( self.sender + self.receiver + encode_single("uint256", self.amount) + encode_single("uint256", self.expiration_block) + self.one_to_n_address + encode_single("uint256", self.chain_id) )
def pack_reward_proof( monitoring_service_contract_address: HexAddress, chain_id: int, non_closing_signature: bytes, reward_amount: int, ) -> bytes: return (Web3.toBytes(hexstr=monitoring_service_contract_address) + encode_single("uint256", chain_id) + encode_single("uint256", MessageTypeId.MSReward) + non_closing_signature + encode_single("uint256", reward_amount))
def packed_data(self) -> bytes: return ( self.one_to_n_address + encode_single("uint256", self.chain_id) + encode_single("uint256", MessageTypeId.IOU) + self.sender + self.receiver + encode_single("uint256", self.amount) + encode_single("uint256", self.claimable_until) )
def is_signature_valid(self): packed_data = (Web3.toBytes(hexstr=self.sender) + Web3.toBytes(hexstr=self.receiver) + encode_single('uint256', self.amount) + encode_single('uint256', self.expiration_block)) try: recovered_address = recover(packed_data, self.signature) except InvalidSignature: return False return is_same_address(recovered_address, self.sender)
def test_getSlot(pipe_graph_interpreter): product_id = 1 wei_value = 100 (inputs, _, _) = prepareGraphProxyInputs( ['uint256', 'uint256'], [product_id, wei_value], ) prodid = pipe_graph_interpreter.functions.getSlot(inputs, 0).call() wei = pipe_graph_interpreter.functions.getSlot(inputs, 32).call() assert prodid == encode_single('uint256', product_id) assert wei == encode_single('uint256', wei_value)
def hash_reward_proof( channel_identifier: int, reward_amount: int, token_network_address: HexAddress, chain_id: int, nonce: int, ) -> bytes: return eth_sign_hash_message( encode_single("uint256", channel_identifier) + encode_single("uint256", reward_amount) + Web3.toBytes(hexstr=token_network_address) + encode_single("uint256", chain_id) + encode_single("uint256", nonce))
def test_contract_signature(self): owner_1 = self.ethereum_test_account safe = self.deploy_test_safe_v1_1_1(owners=[owner_1.address], initial_funding_wei=Web3.toWei( 0.01, "ether")) safe_contract = safe.get_contract() safe_tx_hash = Web3.keccak(text="test") signature_r = HexBytes(safe.address.replace("0x", "").rjust(64, "0")) signature_s = HexBytes( "0" * 62 + "41") # Position of end of signature `0x41 == 65` signature_v = HexBytes("00") contract_signature = encode_single("bytes", b"") signature = signature_r + signature_s + signature_v + contract_signature safe_signature = SafeSignature.parse_signature(signature, safe_tx_hash)[0] self.assertFalse(safe_signature.is_valid(self.ethereum_client, None)) # Check with previously signedMessage tx = safe_contract.functions.signMessage( safe_tx_hash).buildTransaction({"from": safe.address}) safe_tx = safe.build_multisig_tx(safe.address, 0, tx["data"]) safe_tx.sign(owner_1.key) safe_tx.execute(owner_1.key) safe_signature = SafeSignature.parse_signature(signature, safe_tx_hash)[0] self.assertTrue(safe_signature.is_valid(self.ethereum_client, None)) self.assertIsInstance(safe_signature, SafeSignatureContract) # Check with crafted signature safe_tx_hash_2 = Web3.keccak(text="test2") safe_signature = SafeSignature.parse_signature(signature, safe_tx_hash_2)[0] self.assertFalse(safe_signature.is_valid(self.ethereum_client, None)) safe_tx_hash_2_message_hash = safe_contract.functions.getMessageHash( safe_tx_hash_2).call() contract_signature = owner_1.signHash( safe_tx_hash_2_message_hash)["signature"] encoded_contract_signature = encode_single( "bytes", contract_signature) # It will add size of bytes # `32` bytes with the abi encoded size of array. 65 bytes will be padded to next multiple of 32 -> 96 # 96 - 65 = `31` self.assertEqual(len(encoded_contract_signature), len(contract_signature) + 32 + 31) crafted_signature = (signature_r + signature_s + signature_v + encoded_contract_signature) safe_signature = SafeSignature.parse_signature(crafted_signature, safe_tx_hash_2)[0] self.assertEqual(contract_signature, safe_signature.contract_signature) self.assertTrue(safe_signature.is_valid(self.ethereum_client, None))
def test_contract_signature(self): owner_1 = self.ethereum_test_account deployed_safe = self.deploy_test_safe(owners=[owner_1.address], initial_funding_wei=Web3.toWei( 0.01, 'ether')) safe = Safe(deployed_safe.safe_address, self.ethereum_client) safe_contract = safe.get_contract() safe_tx_hash = Web3.keccak(text='test') signature_r = HexBytes(safe.address.replace('0x', '').rjust(64, '0')) signature_s = HexBytes( '0' * 62 + '41') # Position of end of signature `0x41 == 65` signature_v = HexBytes('00') contract_signature = encode_single('bytes', b'') signature = signature_r + signature_s + signature_v + contract_signature safe_signature = SafeSignature.parse_signature(signature, safe_tx_hash)[0] self.assertFalse(safe_signature.is_valid(self.ethereum_client, None)) # Check with previously signedMessage tx = safe_contract.functions.signMessage( safe_tx_hash).buildTransaction({'from': safe.address}) safe_tx = safe.build_multisig_tx(safe.address, 0, tx['data']) safe_tx.sign(owner_1.key) safe_tx.execute(owner_1.key) safe_signature = SafeSignature.parse_signature(signature, safe_tx_hash)[0] self.assertTrue(safe_signature.is_valid(self.ethereum_client, None)) self.assertIsInstance(safe_signature, SafeSignatureContract) # Check with crafted signature safe_tx_hash_2 = Web3.keccak(text='test2') safe_signature = SafeSignature.parse_signature(signature, safe_tx_hash_2)[0] self.assertFalse(safe_signature.is_valid(self.ethereum_client, None)) safe_tx_hash_2_message_hash = safe_contract.functions.getMessageHash( safe_tx_hash_2).call() contract_signature = owner_1.signHash( safe_tx_hash_2_message_hash)['signature'] encoded_contract_signature = encode_single( 'bytes', contract_signature) # It will add size of bytes # `32` bytes with the abi encoded size of array. 65 bytes will be padded to next multiple of 32 -> 96 # 96 - 65 = `31` self.assertEqual(len(encoded_contract_signature), len(contract_signature) + 32 + 31) crafted_signature = signature_r + signature_s + signature_v + encoded_contract_signature safe_signature = SafeSignature.parse_signature(crafted_signature, safe_tx_hash_2)[0] self.assertEqual(contract_signature, safe_signature.contract_signature) self.assertTrue(safe_signature.is_valid(self.ethereum_client, None))
def sign_one_to_n_iou( privatekey, sender, receiver, amount, expiration, v=27, ): iou_hash = eth_sign_hash_message( Web3.toBytes(hexstr=sender) + Web3.toBytes(hexstr=receiver) + encode_single('uint256', amount) + encode_single('uint256', expiration), ) return sign(privkey=privatekey, msg=iou_hash, v=v)
def hash_withdraw_message( token_network_address: HexAddress, chain_identifier: int, channel_identifier: int, participant: HexAddress, amount_to_withdraw: int, ) -> bytes: return eth_sign_hash_message( Web3.toBytes(hexstr=token_network_address) + encode_single("uint256", chain_identifier) + encode_single("uint256", MessageTypeId.WITHDRAW) + encode_single("uint256", channel_identifier) + Web3.toBytes(hexstr=participant) + encode_single("uint256", amount_to_withdraw))
def hash_balance_proof( token_network_address: HexAddress, chain_identifier: int, channel_identifier: int, balance_hash: bytes, nonce: int, additional_hash: bytes, ) -> bytes: return eth_sign_hash_message( Web3.toBytes(hexstr=token_network_address) + encode_single("uint256", chain_identifier) + encode_single("uint256", MessageTypeId.BALANCE_PROOF) + encode_single("uint256", channel_identifier) + balance_hash + encode_single("uint256", nonce) + additional_hash)
def pack_balance_proof( token_network_address: HexAddress, chain_identifier: ChainID, channel_identifier: ChannelID, balance_hash: BalanceHash, nonce: Nonce, additional_hash: AdditionalHash, msg_type: MessageTypeId, ) -> bytes: return (Web3.toBytes(hexstr=token_network_address) + encode_single("uint256", chain_identifier) + encode_single("uint256", msg_type) + encode_single("uint256", channel_identifier) + balance_hash + encode_single("uint256", nonce) + additional_hash)
def pack_reward_proof( monitoring_service_contract_address: HexAddress, chain_id: ChainID, token_network_address: HexAddress, non_closing_participant: HexAddress, non_closing_signature: Signature, reward_amount: TokenAmount, ) -> bytes: return (Web3.toBytes(hexstr=monitoring_service_contract_address) + encode_single("uint256", chain_id) + encode_single("uint256", MessageTypeId.MSReward) + Web3.toBytes(hexstr=token_network_address) + Web3.toBytes(hexstr=non_closing_participant) + non_closing_signature + encode_single("uint256", reward_amount))
def hash_balance_proof( token_network_address, chain_identifier, channel_identifier, balance_hash, nonce, additional_hash, ): return eth_sign_hash_message( Web3.toBytes(hexstr=token_network_address) + encode_single('uint256', chain_identifier) + encode_single('uint256', MessageTypeId.BALANCE_PROOF) + encode_single('uint256', channel_identifier) + balance_hash + encode_single('uint256', nonce) + additional_hash, )
def hash_withdraw_message( token_network_address, chain_identifier, channel_identifier, participant, amount_to_withdraw, ): return eth_sign_hash_message( Web3.toBytes(hexstr=token_network_address) + encode_single('uint256', chain_identifier) + encode_single('uint256', MessageTypeId.WITHDRAW) + encode_single('uint256', channel_identifier) + Web3.toBytes(hexstr=participant) + encode_single('uint256', amount_to_withdraw), )
def test_contract_multiple_signatures(self): """ Test decode of multiple `CONTRACT_SIGNATURE` together """ owner_1 = self.ethereum_test_account deployed_safe = self.deploy_test_safe(owners=[owner_1.address], initial_funding_wei=Web3.toWei(0.01, 'ether')) safe = Safe(deployed_safe.safe_address, self.ethereum_client) safe_contract = safe.get_contract() safe_tx_hash = Web3.keccak(text='test') tx = safe_contract.functions.signMessage( safe_tx_hash ).buildTransaction({'from': safe.address}) safe_tx = safe.build_multisig_tx(safe.address, 0, tx['data']) safe_tx.sign(owner_1.key) safe_tx.execute(owner_1.key) # Check multiple signatures. In this case we reuse signatures for the same owner, it won't make sense # in real life signature_r_1 = HexBytes(safe.address.replace('0x', '').rjust(64, '0')) signature_s_1 = HexBytes('0' * 62 + '82') # Position of end of signature `0x82 == (65 * 2)` signature_v_1 = HexBytes('00') contract_signature_1 = b'' encoded_contract_signature_1 = encode_single('bytes', contract_signature_1) signature_r_2 = HexBytes(safe.address.replace('0x', '').rjust(64, '0')) signature_s_2 = HexBytes('0' * 62 + 'c2') # Position of end of signature `0xc2 == (65 * 2) + 64` signature_v_2 = HexBytes('00') safe_tx_hash_message_hash = safe_contract.functions.getMessageHash(safe_tx_hash).call() contract_signature_2 = owner_1.signHash(safe_tx_hash_message_hash)['signature'] encoded_contract_signature_2 = encode_single('bytes', contract_signature_2) # It will add size of bytes signature = (signature_r_1 + signature_s_1 + signature_v_1 + signature_r_2 + signature_s_2 + signature_v_2 + encoded_contract_signature_1 + encoded_contract_signature_2) count = 0 for safe_signature, contract_signature in zip(SafeSignature.parse_signature(signature, safe_tx_hash), [contract_signature_1, contract_signature_2]): self.assertEqual(safe_signature.contract_signature, contract_signature) self.assertTrue(safe_signature.is_valid(self.ethereum_client, None)) self.assertEqual(safe_signature.signature_type, SafeSignatureType.CONTRACT_SIGNATURE) # Test exported signature exported_signature = SafeSignature.parse_signature(safe_signature.export_signature(), safe_tx_hash)[0] self.assertEqual(exported_signature.contract_signature, safe_signature.contract_signature) self.assertTrue(exported_signature.is_valid(self.ethereum_client, None)) count += 1 self.assertEqual(count, 2)
def pack_withdraw_message( token_network_address: HexAddress, chain_identifier: ChainID, channel_identifier: ChannelID, participant: HexAddress, amount_to_withdraw: TokenAmount, expiration_block: BlockExpiration, ) -> bytes: return (Web3.toBytes(hexstr=token_network_address) + encode_single("uint256", chain_identifier) + encode_single("uint256", MessageTypeId.WITHDRAW) + encode_single("uint256", channel_identifier) + Web3.toBytes(hexstr=participant) + encode_single("uint256", amount_to_withdraw) + encode_single("uint256", expiration_block))
def test_happy_path( chain, gov, vault, strategy, snx, susd, susd_vault, susd_whale, snx_whale, bob, snx_oracle, ): chain.snapshot() # Move stale period to 6 days resolver = Contract(strategy.resolver()) settings = Contract( resolver.getAddress(encode_single("bytes32", b"SystemSettings"))) settings.setRateStalePeriod(24 * 3600 * 6, {"from": settings.owner()}) settings.setDebtSnapshotStaleTime(24 * 3600 * 6, {"from": settings.owner()}) # Do the first deposit snx.transfer(bob, Wei("1000 ether"), {"from": snx_whale}) snx.approve(vault, 2**256 - 1, {"from": bob}) vault.deposit({"from": bob}) # Invest with an SNX price of 20 snx_oracle.updateSnxPrice(Wei("20 ether"), {"from": gov}) strategy.harvest({"from": gov}) assert strategy.balanceOfWant() == Wei("1000 ether") assert strategy.balanceOfSusd() == 0 assert strategy.balanceOfSusdInVault() > 0 # should not allow to withdraw before minimumStakePeriod ends with brownie.reverts(): vault.withdraw({"from": bob}) # We need to wait 24hs to be able to burn synths # Always takeDebtSnapshot after moving time. chain.sleep(86401) chain.mine(1) # This is extremely slow # debtCache.takeDebtSnapshot({"from": debtCache.owner()}) # Donate some sUSD to the susd_vault to mock earnings and harvest profit susd.transfer(susd_vault, Wei("1000 ether"), {"from": susd_whale}) strategy.harvest({"from": gov}) assert vault.strategies(strategy).dict()["totalGain"] > 0 # Sleep 24 hours to allow the minimumStakePeriod to pass chain.sleep(60 * 60 * 24) chain.mine(1) tx = vault.withdraw({"from": bob}) assert snx.balanceOf(bob) > Wei("1000 ether") assert strategy.balanceOfDebt() == 0 chain.revert()
def test_updateReward( monitoring_service_internals: Contract, ms_address: HexAddress, token_network: Contract, monitor_data_internal: Dict, ) -> None: A, B = monitor_data_internal["participants"] reward_identifier = Web3.keccak( encode_single("uint256", monitor_data_internal["channel_identifier"]) + Web3.toBytes(hexstr=token_network.address) ) def update_with_nonce(nonce: int) -> None: monitoring_service_internals.functions.updateRewardPublic( token_network.address, A, B, REWARD_AMOUNT, nonce, ms_address, monitor_data_internal["non_closing_signature"], monitor_data_internal["reward_proof_signature"], ).call_and_transact({"from": ms_address}) # normal first call succeeds update_with_nonce(2) assert monitoring_service_internals.functions.rewardNonce(reward_identifier).call() == 2 # calling again with same nonce fails with pytest.raises(TransactionFailed, match="stale nonce"): update_with_nonce(2) # calling again with higher nonce succeeds update_with_nonce(3) assert monitoring_service_internals.functions.rewardNonce(reward_identifier).call() == 3
def wait_for_event(self, ev, ev_argt, ev_argt_indexed=None, ev_argv_indexed=None, ev_rett=None, ev_callback=None): evsig = ev + self._build_types(ev_argt) sig = "0x" + binascii.hexlify(Web3.sha3(evsig.encode("utf-8"))).decode("utf-8") topics=[sig] if ev_argt_indexed is not None and ev_argv_indexed is not None and len(ev_argv_indexed) == len(ev_argt_indexed): for i in range(0, len(ev_argt_indexed)): topics.append("0x" + binascii.hexlify(eth_abi.encode_single(ev_argt_indexed[i], ev_argv_indexed[i])).decode("utf-8")) event_filter = self.web3.eth.filter({ "address": self.address, "topics": topics }) max_retries = 60 # 2 minutes timeout retries = 0 while retries <= max_retries: for event in event_filter.get_new_entries(): if ev_rett is not None: ret = eth_abi.decode_single(self._build_types(ev_rett), binascii.unhexlify(event["data"][2:])) if ev_callback and ev_callback(ret): return ret else: return True retries += 1 time.sleep(2) raise RuntimeError(f"event timeout: {ev}")
def fill_order(self, order: Order, fill_buy_amount: Wad) -> Transact: """Fills an order. Args: order: The order to be filled. fill_buy_amount: The amount (in terms of `buy_token` of the original order) to be filled. Returns: A :py:class:`pymaker.Transact` instance, which can be used to trigger the transaction. """ assert (isinstance(order, Order)) assert (isinstance(fill_buy_amount, Wad)) method_signature = self.web3.keccak( text=f"fillOrder({self.ORDER_INFO_TYPE},uint256,bytes)")[0:4] method_parameters = encode_single( f"({self.ORDER_INFO_TYPE},uint256,bytes)", [ self._order_tuple(order), fill_buy_amount.value, hexstring_to_bytes(order.signature) ]) request = bytes_to_hexstring(method_signature + method_parameters) return Transact(self, self.web3, self.abi, self.address, self._contract, None, [request])
def construct_event_data_set(event_abi, arguments=None): if arguments is None: arguments = {} if isinstance(arguments, (list, tuple)): if len(arguments) != len(event_abi['inputs']): raise ValueError( "When passing an argument list, the number of arguments must " "match the event constructor.") arguments = { arg['name']: [arg_value] for arg, arg_value in zip(event_abi['inputs'], arguments) } normalized_args = { key: value if is_list_like(value) else [value] for key, value in arguments.items() } non_indexed_args = exclude_indexed_event_inputs(event_abi) zipped_abi_and_args = [(arg, normalized_args.get(arg['name'], [None])) for arg in non_indexed_args] encoded_args = [[ None if option is None else encode_hex( encode_single(arg['type'], option)) for option in arg_options ] for arg, arg_options in zipped_abi_and_args] data = [ list(permutation) if any(value is not None for value in permutation) else [] for permutation in itertools.product(*encoded_args) ] return data
def test_contract_signature(self): safe_account = self.ethereum_test_account safe = self.deploy_test_safe(owners=[safe_account.address], initial_funding_wei=Web3.toWei(0.01, 'ether')) safe_contract = get_safe_contract(self.ethereum_client.w3, safe.safe_address) safe_tx_hash = Web3.keccak(text='test') signature_r = HexBytes(safe.safe_address.replace('0x', '').rjust(64, '0')) signature_s = HexBytes('0' * 62 + '41') # Position of end of signature signature_v = HexBytes('00') contract_signature = HexBytes('0' * 64) signature = signature_r + signature_s + signature_v + contract_signature safe_signature = SafeContractSignature(signature, safe_tx_hash, self.ethereum_client) self.assertFalse(safe_signature.ok) # Approve the hash tx = safe_contract.functions.approveHash( safe_tx_hash ).buildTransaction({'from': safe_account.address}) self.ethereum_client.send_unsigned_transaction(tx, private_key=safe_account.key) safe_signature = SafeContractSignature(signature, safe_tx_hash, self.ethereum_client) self.assertFalse(safe_signature.ok) # Test with an owner signature safe_tx_hash_2 = Web3.keccak(text='test2') safe_tx_hash_2_message_hash = safe_contract.functions.getMessageHash(safe_tx_hash_2).call() safe_signature = SafeContractSignature(signature, safe_tx_hash_2, self.ethereum_client) self.assertFalse(safe_signature.ok) contract_signature = encode_single('bytes', safe_account.signHash(safe_tx_hash_2_message_hash)['signature']) signature = signature_r + signature_s + signature_v + contract_signature safe_signature = SafeContractSignature(signature, safe_tx_hash_2, self.ethereum_client) self.assertTrue(safe_signature.ok)
def construct_event_topic_set(event_abi, arguments=None): if arguments is None: arguments = {} if isinstance(arguments, (list, tuple)): if len(arguments) != len(event_abi['inputs']): raise ValueError( "When passing an argument list, the number of arguments must " "match the event constructor.") arguments = { arg['name']: [arg_value] for arg, arg_value in zip(event_abi['inputs'], arguments) } normalized_args = { key: value if is_list_like(value) else [value] for key, value in arguments.items() } event_topic = encode_hex(event_abi_to_log_topic(event_abi)) indexed_args = get_indexed_event_inputs(event_abi) zipped_abi_and_args = [(arg, normalized_args.get(arg['name'], [None])) for arg in indexed_args] encoded_args = [[ None if option is None else encode_hex( encode_single(arg['type'], option)) for option in arg_options ] for arg, arg_options in zipped_abi_and_args] topics = list(normalize_topic_list([event_topic] + encoded_args)) return topics
def construct_event_topic_set(event_abi, arguments=None): if arguments is None: arguments = {} if isinstance(arguments, (list, tuple)): if len(arguments) != len(event_abi['inputs']): raise ValueError( "When passing an argument list, the number of arguments must " "match the event constructor." ) arguments = { arg['name']: [arg_value] for arg, arg_value in zip(event_abi['inputs'], arguments) } normalized_args = { key: value if is_list_like(value) else [value] for key, value in arguments.items() } event_topic = encode_hex(event_abi_to_log_topic(event_abi)) indexed_args = get_indexed_event_inputs(event_abi) zipped_abi_and_args = [ (arg, normalized_args.get(arg['name'], [None])) for arg in indexed_args ] encoded_args = [ [ None if option is None else encode_hex(encode_single(arg['type'], option)) for option in arg_options] for arg, arg_options in zipped_abi_and_args ] topics = list(normalize_topic_list([event_topic] + encoded_args)) return topics
def to_bytes(self): """ This is how we pass a message through p2p channels """ # Note we don't encode the domain separator, the receiver # must validate that each transaction is signed according # to the domain separator they are using. return encode_single( '(address,uint256,uint256,uint256,uint256,uint256)', self.to_tuple)
def session_id(self) -> bytes: """Session ID as used for OneToN.settled_sessions""" return encode_hex( keccak( Web3.toBytes(hexstr=self.receiver) + Web3.toBytes(hexstr=self.sender) + encode_single('uint256', self.expiration_block)))
def test_single_abi_tuple_reversibility(type_and_value): """ Tests round trip encoding and decoding for tuple types. """ _type, value = type_and_value encoded_value = encode_single(_type, value) decoded_value = decode_single(_type, encoded_value) assert value == decoded_value
def test_always_positive_single(_type, value): """ Tests round trip encoding and decoding for basic types and lists of basic types. """ assert value >= 0 encoded_value = encode_single(_type, value) decoded_value = decode_single(_type, encoded_value) assert decoded_value >= 0
def all_events_filter( self, from_block: typing.BlockSpecification = None, to_block: typing.BlockSpecification = None, ) -> typing.Tuple[Filter, Filter]: channel_topics = [ None, # event topic is any encode_hex(encode_single('bytes32', self.channel_identifier)), # channel_id ] # This will match the events: # ChannelOpened, ChannelNewDeposit, ChannelWithdraw, ChannelClosed, # NonClosingBalanceProofUpdated, ChannelSettled channel_filter = self.token_network.client.new_filter( contract_address=self.token_network.address, topics=channel_topics, from_block=from_block, to_block=to_block, ) # This will match the events: # ChannelUnlocked # # These topics must not be joined with the channel_filter, otherwise # the filter ChannelSettled wont match (observed with geth # 1.8.11-stable-dea1ce05) event_unlock_abi = CONTRACT_MANAGER.get_event_abi( CONTRACT_TOKEN_NETWORK, EVENT_CHANNEL_UNLOCKED, ) event_unlock_topic = encode_hex(event_abi_to_log_topic(event_unlock_abi)) participant1_topic = encode_hex(self.participant1.rjust(32, b'\0')) participant2_topic = encode_hex(self.participant2.rjust(32, b'\0')) unlock_topics = [ event_unlock_topic, [participant1_topic, participant2_topic], # event participant1 is us or them [participant2_topic, participant1_topic], # event participant2 is us or them ] unlock_filter = self.token_network.client.new_filter( contract_address=self.token_network.address, topics=unlock_topics, from_block=from_block, to_block=to_block, ) return channel_filter, unlock_filter
def construct_event_data_set(event_abi, arguments=None): if arguments is None: arguments = {} if isinstance(arguments, (list, tuple)): if len(arguments) != len(event_abi['inputs']): raise ValueError( "When passing an argument list, the number of arguments must " "match the event constructor." ) arguments = { arg['name']: [arg_value] for arg, arg_value in zip(event_abi['inputs'], arguments) } normalized_args = { key: value if is_list_like(value) else [value] for key, value in arguments.items() } non_indexed_args = exclude_indexed_event_inputs(event_abi) zipped_abi_and_args = [ (arg, normalized_args.get(arg['name'], [None])) for arg in non_indexed_args ] encoded_args = [ [ None if option is None else encode_hex(encode_single(arg['type'], option)) for option in arg_options] for arg, arg_options in zipped_abi_and_args ] topics = [ list(permutation) if any(value is not None for value in permutation) else [] for permutation in itertools.product(*encoded_args) ] return topics
def _encode(self, value): if is_dynamic_sized_type(self.arg_type): return to_hex(keccak(encode_single_packed(self.arg_type, value))) else: return to_hex(encode_single(self.arg_type, value))