def test_send_same_function_call_twice_without_nonce_tracking( each_identity, test_contract, delegate): """Test that we can send two similar transactions to a contract by selecting a random nonce > 2**255""" to = test_contract.address argument = 10 function_call = test_contract.functions.testFunction(argument) max_nonce = 2**255 random_gap = 123456 meta_transaction = MetaTransaction.from_function_call(function_call, to=to, nonce=max_nonce) meta_transaction = each_identity.filled_and_signed_meta_transaction( meta_transaction) delegate.send_signed_meta_transaction(meta_transaction) meta_transaction = MetaTransaction.from_function_call(function_call, to=to, nonce=max_nonce + random_gap) meta_transaction = each_identity.filled_and_signed_meta_transaction( meta_transaction) delegate.send_signed_meta_transaction(meta_transaction) events = test_contract.events.TestEvent.createFilter( fromBlock=0).get_all_entries() for event in events: assert event["args"]["from"] == each_identity.address assert event["args"]["value"] == 0 assert event["args"]["argument"] == argument
def test_tracking_delegation_fee_in_different_network( currency_network_contract, second_currency_network_contract, each_identity, delegate, delegate_address, accounts, ): A = each_identity.address B = accounts[3] to = currency_network_contract.address base_fee = 123 function_call = currency_network_contract.functions.updateCreditlimits( B, 100, 100) meta_transaction = each_identity.filled_and_signed_meta_transaction( MetaTransaction.from_function_call( function_call, to=to, base_fee=base_fee, currency_network_of_fees=second_currency_network_contract.address, )) delegate.send_signed_meta_transaction(meta_transaction) assert currency_network_contract.functions.getDebt( A, delegate_address).call() == 0 assert (second_currency_network_contract.functions.getDebt( A, delegate_address).call() == base_fee)
def test_own_identity_meta_tx_overhead(web3, table, test_contract, identity, owner, delegate): """Tests the overhead of using an owned meta-tx compared to a regular tx""" to = test_contract.address argument = 10 function_call = test_contract.functions.testFunction(argument) meta_transaction = MetaTransaction.from_function_call(function_call, to=to) owner_tx_id = identity.contract.functions.execute( to, 0, meta_transaction.data, 0, 0).transact({"from": owner}) regular_tx_id = test_contract.functions.testFunction(argument).transact() gas_cost_owner_meta_tx = get_gas_costs(web3, owner_tx_id) gas_cost_regular_tx = get_gas_costs(web3, regular_tx_id) overhead = gas_cost_owner_meta_tx - gas_cost_regular_tx report_gas_costs( table, "Overhead of owned unproxied meta-tx over regular transaction", overhead, limit=5000, )
def test_meta_transaction_delegate_call(each_identity, delegate, delegate_address, web3, test_contract): to = test_contract.address argument = 123 function_call = test_contract.functions.testFunction(argument) meta_transaction = MetaTransaction.from_function_call(function_call, to=to) meta_transaction = attr.evolve( meta_transaction, operation_type=MetaTransaction.OperationType.DELEGATE_CALL) meta_transaction = each_identity.filled_and_signed_meta_transaction( meta_transaction) tx_id = delegate.send_signed_meta_transaction(meta_transaction) execution_event = each_identity.contract.events.TransactionExecution.createFilter( fromBlock=0).get_all_entries()[0]["args"] # assert that the delegate call was successful assert get_transaction_status(web3, tx_id) assert execution_event["hash"] == meta_transaction.hash assert execution_event["status"] is True proxied_test_contract = web3.eth.contract(each_identity.contract.address, abi=test_contract.abi) test_event = proxied_test_contract.events.TestEvent.createFilter( fromBlock=0).get_all_entries()[0]["args"] # assert that the successful operation was indeed a delegate call # by checking that `from` is delegate_address and not identity_address assert test_event["from"] == delegate_address assert test_event["value"] == 0 assert test_event["argument"] == argument
def test_delegated_transaction_hash(each_identity_contract, test_contract, accounts): to = accounts[3] from_ = each_identity_contract.address argument = 10 function_call = test_contract.functions.testFunction(argument) meta_transaction = MetaTransaction.from_function_call(function_call, from_=from_, to=to, nonce=0) hash_by_contract = each_identity_contract.functions.transactionHash( meta_transaction.to, meta_transaction.value, meta_transaction.data, meta_transaction.base_fee, meta_transaction.gas_price, meta_transaction.gas_limit, meta_transaction.fee_recipient, meta_transaction.currency_network_of_fees, meta_transaction.nonce, meta_transaction.time_limit, meta_transaction.operation_type.value, ).call() hash = meta_transaction.hash assert hash == HexBytes(hash_by_contract)
def test_meta_tx_over_own_identity_tx_overhead(web3, table, test_contract, identity, owner, delegate): """Tests the overhead of using a meta-tx compared to an owned identity tx""" # The test sends two meta-tx as the first meta-tx of an identity is more expensive than all the next ones # due to storage allocation to = test_contract.address argument = 10 function_call = test_contract.functions.testFunction(argument) # first meta-tx meta_transaction = MetaTransaction.from_function_call(function_call, to=to) filled_meta_tx = identity.filled_and_signed_meta_transaction( meta_transaction) delegate.send_signed_meta_transaction(filled_meta_tx) # second meta-tx we meter second_filled_meta_transaction = identity.filled_and_signed_meta_transaction( meta_transaction) meta_tx_id = delegate.send_signed_meta_transaction( second_filled_meta_transaction) owner_tx_id = identity.contract.functions.execute( to, 0, meta_transaction.data, 0, 0).transact({"from": owner}) gas_cost_meta_tx = get_gas_costs(web3, meta_tx_id) gas_cost_owner_tx = get_gas_costs(web3, owner_tx_id) overhead = gas_cost_meta_tx - gas_cost_owner_tx report_gas_costs( table, "Overhead of unproxied meta-tx over owned transaction", overhead, limit=22000, )
def test_meta_tx_over_regular_tx_overhead(web3, table, test_contract, identity, delegate): """Tests the overhead of using a meta-tx compared to a regular tx""" # The test sends two meta-tx as the first meta-tx of an identity is more expensive than all the next ones # due to storage allocation to = test_contract.address argument = 10 function_call = test_contract.functions.testFunction(argument) # first meta-tx meta_transaction = MetaTransaction.from_function_call(function_call, to=to) filled_meta_tx = identity.filled_and_signed_meta_transaction( meta_transaction) delegate.send_signed_meta_transaction(filled_meta_tx) # second meta-tx we meter second_filled_meta_transaction = identity.filled_and_signed_meta_transaction( meta_transaction) meta_tx_id = delegate.send_signed_meta_transaction( second_filled_meta_transaction) regular_tx_id = test_contract.functions.testFunction(argument).transact() gas_cost_meta_tx = get_gas_costs(web3, meta_tx_id) gas_cost_regular_tx = get_gas_costs(web3, regular_tx_id) overhead = gas_cost_meta_tx - gas_cost_regular_tx report_gas_costs(table, "Overhead of unproxied meta-tx over regular tx", overhead, limit=26750)
def test_meta_transaction_fee_recipient(currency_network_contract, each_identity, delegate, delegate_address, accounts): A = each_identity.address B = accounts[3] to = currency_network_contract.address base_fee = 123 function_call = currency_network_contract.functions.updateCreditlimits( B, 100, 100) meta_transaction = MetaTransaction.from_function_call(function_call, to=to, base_fee=base_fee) meta_transaction = attr.evolve(meta_transaction, fee_recipient=B) meta_transaction = each_identity.filled_and_signed_meta_transaction( meta_transaction) delegate.send_signed_meta_transaction(meta_transaction) debt_A_B = currency_network_contract.functions.getDebt(A, B).call() debt_A_delegate = currency_network_contract.functions.getDebt( A, delegate_address).call() assert debt_A_B == base_fee assert debt_A_delegate == 0 fee_payment_event = each_identity.contract.events.FeePayment().getLogs( )[-1] assert fee_payment_event["args"]["value"] == base_fee assert fee_payment_event["args"]["recipient"] == B
def test_proxy_overhead( web3, gas_values_snapshot, test_contract, proxied_identity, identity, delegate ): """Tests the overhead of using an identity proxy compared to a regular identity""" to = test_contract.address argument = 10 function_call = test_contract.functions.testFunction(argument) meta_transaction = MetaTransaction.from_function_call(function_call, to=to) proxied_meta_transaction = proxied_identity.filled_and_signed_meta_transaction( meta_transaction ) not_proxied_meta_transaction = identity.filled_and_signed_meta_transaction( meta_transaction ) proxied_meta_tx_id = delegate.send_signed_meta_transaction(proxied_meta_transaction) not_proxied_meta_tx_id = delegate.send_signed_meta_transaction( not_proxied_meta_transaction ) gas_cost_proxied_meta_tx = get_gas_costs(web3, proxied_meta_tx_id) gas_cost_not_proxied_tx = get_gas_costs(web3, not_proxied_meta_tx_id) overhead = gas_cost_proxied_meta_tx - gas_cost_not_proxied_tx gas_values_snapshot.assert_gas_costs_match( "PROXIED_META_TRANSACTION_OVERHEAD_OVER_NONPROXY_METATRANSACTION", overhead )
def test_meta_tx_over_regular_tx_overhead( web3, gas_values_snapshot, test_contract, identity, delegate ): """Tests the overhead of using a meta-tx compared to a regular tx""" # The test sends two meta-tx as the first meta-tx of an identity is more expensive than all the next ones # due to storage allocation to = test_contract.address argument = 10 function_call = test_contract.functions.testFunction(argument) # first meta-tx meta_transaction = MetaTransaction.from_function_call(function_call, to=to) filled_meta_tx = identity.filled_and_signed_meta_transaction(meta_transaction) delegate.send_signed_meta_transaction(filled_meta_tx) # second meta-tx we meter second_filled_meta_transaction = identity.filled_and_signed_meta_transaction( meta_transaction ) meta_tx_id = delegate.send_signed_meta_transaction(second_filled_meta_transaction) regular_tx_id = test_contract.functions.testFunction(argument).transact() gas_cost_meta_tx = get_gas_costs(web3, meta_tx_id) gas_cost_regular_tx = get_gas_costs(web3, regular_tx_id) overhead = gas_cost_meta_tx - gas_cost_regular_tx gas_values_snapshot.assert_gas_costs_match( "UNPROXIED_META_TRANSACTION_OVERHEAD", overhead )
def test_proxy_overhead(web3, table, test_contract, proxied_identity, identity, delegate): """Tests the overhead of using an identity proxy compared to a regular identity""" to = test_contract.address argument = 10 function_call = test_contract.functions.testFunction(argument) meta_transaction = MetaTransaction.from_function_call(function_call, to=to) proxied_meta_transaction = proxied_identity.filled_and_signed_meta_transaction( meta_transaction) not_proxied_meta_transaction = identity.filled_and_signed_meta_transaction( meta_transaction) proxied_meta_tx_id = delegate.send_signed_meta_transaction( proxied_meta_transaction) not_proxied_meta_tx_id = delegate.send_signed_meta_transaction( not_proxied_meta_transaction) gas_cost_proxied_meta_tx = get_gas_costs(web3, proxied_meta_tx_id) gas_cost_not_proxied_tx = get_gas_costs(web3, not_proxied_meta_tx_id) overhead = gas_cost_proxied_meta_tx - gas_cost_not_proxied_tx report_gas_costs(table, "Overhead of a proxy over non-proxy meta-tx", overhead, limit=1500)
def transfer_meta_transaction(self, value, max_fee, path, extra_data=b""): function_call = self._proxy.functions.transfer(value, max_fee, path, extra_data) meta_transaction = MetaTransaction.from_function_call( function_call, to=self.address ) return meta_transaction
def test_cannot_revoke_executed_transaction(each_identity, delegate, test_contract): """Test that we can not revoke a meta-tx that was already executed""" to = test_contract.address argument = 10 function_call = test_contract.functions.testFunction(argument) meta_transaction = each_identity.filled_and_signed_meta_transaction( MetaTransaction.from_function_call(function_call, to=to, nonce=0)) delegate.send_signed_meta_transaction(meta_transaction) revoke_function_call = each_identity.contract.functions.cancelTransaction( meta_transaction.hash) revoke_meta_transaction = each_identity.filled_and_signed_meta_transaction( MetaTransaction.from_function_call(revoke_function_call, to=each_identity.address)) delegate.send_signed_meta_transaction(revoke_meta_transaction) events = each_identity.contract.events.TransactionCancellation().getLogs() assert len(events) == 0
def test_reveoke_meta_transaction_nonce_via_hash(each_identity, delegate, test_contract): """Test that we can revoke a meta-tx that uses nonce anti-replay mechanism via canceling the hash""" to = test_contract.address argument = 10 function_call = test_contract.functions.testFunction(argument) meta_transaction = each_identity.filled_and_signed_meta_transaction( MetaTransaction.from_function_call(function_call, to=to)) revoke_function_call = each_identity.contract.functions.cancelTransaction( meta_transaction.hash) revoke_meta_transaction = each_identity.filled_and_signed_meta_transaction( MetaTransaction.from_function_call(revoke_function_call, to=each_identity.address)) delegate.send_signed_meta_transaction(revoke_meta_transaction) assert not delegate.validate_meta_transaction(meta_transaction) with pytest.raises(TransactionFailed): delegate.send_signed_meta_transaction(meta_transaction)
def test_revoke_meta_transaction_hash(each_identity, delegate, test_contract): """Test that we can revoke a meta-tx that uses hash anti-replay mechanism via canceling the hash""" to = test_contract.address argument = 10 function_call = test_contract.functions.testFunction(argument) meta_transaction = each_identity.filled_and_signed_meta_transaction( MetaTransaction.from_function_call(function_call, to=to, nonce=0)) revoke_function_call = each_identity.contract.functions.cancelTransaction( meta_transaction.hash) revoke_meta_transaction = each_identity.filled_and_signed_meta_transaction( MetaTransaction.from_function_call(revoke_function_call, to=each_identity.address)) delegate.send_signed_meta_transaction(revoke_meta_transaction) events = each_identity.contract.events.TransactionCancellation().getLogs() assert len(events) == 1 assert events[0]["args"]["hash"] == meta_transaction.hash assert not delegate.validate_meta_transaction(meta_transaction) with pytest.raises(TransactionFailed): delegate.send_signed_meta_transaction(meta_transaction)
def test_get_failed_meta_transaction_status(each_identity, delegate, test_contract): meta_transaction = MetaTransaction.from_function_call( test_contract.functions.fails(), to=test_contract.address) meta_transaction = each_identity.filled_and_signed_meta_transaction( meta_transaction) delegate.send_signed_meta_transaction(meta_transaction) meta_tx_status = delegate.get_meta_transaction_status( each_identity.address, meta_transaction.hash) assert meta_tx_status == MetaTransactionStatus.FAILURE
def test_delegated_transaction_fail_event(each_identity, delegate, test_contract): to = test_contract.address function_call = test_contract.functions.fails() meta_transaction = each_identity.filled_and_signed_meta_transaction( MetaTransaction.from_function_call(function_call, to=to)) delegate.send_signed_meta_transaction(meta_transaction) event = each_identity.contract.events.TransactionExecution.createFilter( fromBlock=0).get_all_entries()[0]["args"] assert event["hash"] == meta_transaction.hash assert event["status"] is False
def test_delegated_transaction_trustlines_flow(currency_network_contract, each_identity, delegate, accounts): A = each_identity.address B = accounts[3] to = currency_network_contract.address function_call = currency_network_contract.functions.updateCreditlimits( B, 100, 100) meta_transaction = each_identity.filled_and_signed_meta_transaction( MetaTransaction.from_function_call(function_call, to=to)) delegate.send_signed_meta_transaction(meta_transaction) currency_network_contract.functions.updateCreditlimits( A, 100, 100).transact({"from": B}) function_call = currency_network_contract.functions.transfer( 100, 0, [A, B], EXTRA_DATA) meta_transaction = MetaTransaction.from_function_call(function_call, to=to) meta_transaction = each_identity.filled_and_signed_meta_transaction( meta_transaction) delegate.send_signed_meta_transaction(meta_transaction) assert currency_network_contract.functions.balance(A, B).call() == -100
def test_deploy_identity(web3, delegate, owner, owner_key, test_contract): each_identity_contract = deploy_identity(web3, owner) to = test_contract.address argument = 10 function_call = test_contract.functions.testFunction(argument) meta_transaction = MetaTransaction.from_function_call( function_call, to=to, from_=each_identity_contract.address, nonce=0).signed(owner_key) delegate.send_signed_meta_transaction(meta_transaction) assert (len( test_contract.events.TestEvent.createFilter( fromBlock=0).get_all_entries()) > 0)
def test_revoke_meta_transaction_nonce(each_identity, delegate, test_contract): """Test that we can revoke a meta-tx that uses nonce anti-replay mechanism via using the nonce""" to = test_contract.address argument = 10 function_call = test_contract.functions.testFunction(argument) meta_transaction = each_identity.filled_and_signed_meta_transaction( MetaTransaction.from_function_call(function_call, to=to)) revoke_meta_transaction = each_identity.filled_and_signed_meta_transaction( MetaTransaction(to=each_identity.address, nonce=meta_transaction.nonce)) delegate.send_signed_meta_transaction(revoke_meta_transaction) assert not delegate.validate_meta_transaction(meta_transaction) with pytest.raises(SolidityError): delegate.send_signed_meta_transaction(meta_transaction)
def test_delegated_transaction_function_call(each_identity, delegate, test_contract, web3): to = test_contract.address argument = 10 function_call = test_contract.functions.testFunction(argument) meta_transaction = MetaTransaction.from_function_call(function_call, to=to) meta_transaction = each_identity.filled_and_signed_meta_transaction( meta_transaction) tx_id = delegate.send_signed_meta_transaction(meta_transaction) event = test_contract.events.TestEvent.createFilter( fromBlock=0).get_all_entries()[0]["args"] assert get_transaction_status(web3, tx_id) assert event["from"] == each_identity.address assert event["value"] == 0 assert event["argument"] == argument
def test_meta_transaction_with_fees_increases_debt(currency_network_contract, each_identity, delegate, delegate_address, accounts): A = each_identity.address B = accounts[3] to = currency_network_contract.address base_fee = 123 function_call = currency_network_contract.functions.updateCreditlimits( B, 100, 100) meta_transaction = each_identity.filled_and_signed_meta_transaction( MetaTransaction.from_function_call(function_call, to=to, base_fee=base_fee)) delegate.send_signed_meta_transaction(meta_transaction) assert (currency_network_contract.functions.getDebt( A, delegate_address).call() == base_fee)
def test_failing_meta_transaction_with_fees_does_not_increases_debt( currency_network_contract, each_identity, delegate, delegate_address, accounts): A = each_identity.address B = accounts[3] to = currency_network_contract.address base_fee = 123 function_call = currency_network_contract.functions.transfer( 100, 100, [A, B], b"") meta_transaction = each_identity.filled_and_signed_meta_transaction( MetaTransaction.from_function_call(function_call, to=to, base_fee=base_fee)) delegate.send_signed_meta_transaction(meta_transaction) assert currency_network_contract.functions.getDebt( A, delegate_address).call() == 0
def test_meta_transaction_delegate_call_fail(each_identity, delegate, web3, test_contract): to = test_contract.address function_call = test_contract.functions.fails() meta_transaction = MetaTransaction.from_function_call(function_call, to=to) meta_transaction = attr.evolve( meta_transaction, operation_type=MetaTransaction.OperationType.DELEGATE_CALL) meta_transaction = each_identity.filled_and_signed_meta_transaction( meta_transaction) tx_id = delegate.send_signed_meta_transaction(meta_transaction) execution_event = each_identity.contract.events.TransactionExecution.createFilter( fromBlock=0).get_all_entries()[0]["args"] assert get_transaction_status(web3, tx_id) assert execution_event["hash"] == meta_transaction.hash assert execution_event["status"] is False
def test_change_identity_implementation( proxy_contract_with_owner, identity_implementation, identity_implementation_different_address, proxied_identity, delegate, ): assert (proxy_contract_with_owner.functions.implementation().call() == identity_implementation.address) to = proxy_contract_with_owner.address function_call = proxied_identity.contract.functions.changeImplementation( identity_implementation_different_address.address) meta_transaction = MetaTransaction.from_function_call(function_call, to=to) meta_transaction = proxied_identity.filled_and_signed_meta_transaction( meta_transaction) delegate.send_signed_meta_transaction(meta_transaction) assert (proxy_contract_with_owner.functions.implementation().call() == identity_implementation_different_address.address)
def test_own_identity_meta_tx_overhead( web3, gas_values_snapshot, test_contract, identity, owner ): """Tests the overhead of using an owned meta-tx compared to a regular tx""" to = test_contract.address argument = 10 function_call = test_contract.functions.testFunction(argument) meta_transaction = MetaTransaction.from_function_call(function_call, to=to) owner_tx_id = identity.contract.functions.execute( to, 0, meta_transaction.data, 0, 0 ).transact({"from": owner}) regular_tx_id = test_contract.functions.testFunction(argument).transact() gas_cost_owner_meta_tx = get_gas_costs(web3, owner_tx_id) gas_cost_regular_tx = get_gas_costs(web3, regular_tx_id) overhead = gas_cost_owner_meta_tx - gas_cost_regular_tx gas_values_snapshot.assert_gas_costs_match( "UNPROXIED_OWNED_TRANSACTION_OVERHEAD_OVER_REGULAR_TRANSACTION", overhead )
def trustline_update_meta_transaction( self, to, creditline_given, creditline_received, interest_rate_given, interest_rate_received, is_frozen, transfer, ): function_call = self.update_trustline_function_call( to, creditline_given, creditline_received, interest_rate_given, interest_rate_received, is_frozen, transfer, ) meta_transaction = MetaTransaction.from_function_call(function_call, to=self.address) return meta_transaction
def test_meta_transaction_gas_fee(currency_network_contract, each_identity, delegate, delegate_address, accounts): A = each_identity.address B = accounts[3] to = currency_network_contract.address base_fee = 123 effective_gas_price = 1000 contract_gas_price_divisor = 10**6 gas_price = effective_gas_price * contract_gas_price_divisor function_call = currency_network_contract.functions.updateCreditlimits( B, 100, 100) meta_transaction = each_identity.filled_and_signed_meta_transaction( MetaTransaction.from_function_call(function_call, to=to, base_fee=base_fee, gas_price=gas_price)) delegate.send_signed_meta_transaction(meta_transaction) effective_fee = currency_network_contract.functions.getDebt( A, delegate_address).call() assert (effective_fee - base_fee) % effective_gas_price == 0 assert effective_fee - base_fee != 0