def post_transaction_to_relay_service(self, safe_tx: SafeTx) -> bool: safe_tx.gas_token = self.gas_token estimation = self.safe_relay_service.get_estimation( self.address, safe_tx) safe_tx.base_gas = estimation["baseGas"] safe_tx.safe_tx_gas = estimation["safeTxGas"] safe_tx.gas_price = estimation["gasPrice"] last_used_nonce: Optional[int] = estimation["lastUsedNonce"] safe_tx.safe_nonce = 0 if last_used_nonce is None else last_used_nonce + 1 safe_tx.refund_receiver = estimation["refundReceiver"] or NULL_ADDRESS safe_tx.signatures = b"" # Sign transaction again self.sign_transaction(safe_tx) if yes_or_no_question("Do you want to execute tx " + str(safe_tx)): try: call_result = safe_tx.call(self.default_sender.address) print_formatted_text( HTML(f"Result: <ansigreen>{call_result}</ansigreen>")) transaction_data = self.safe_relay_service.send_transaction( self.address, safe_tx) tx_hash = transaction_data["txHash"] print_formatted_text( HTML( f"<ansigreen>Gnosis Safe Relay has queued transaction with " f"transaction-hash <b>{tx_hash}</b></ansigreen>")) return True except InvalidInternalTx as invalid_internal_tx: print_formatted_text( HTML( f"Result: <ansired>InvalidTx - {invalid_internal_tx}</ansired>" )) return False
def test_decode_execute_transaction(self): owners = [Account.create() for _ in range(2)] owner_addresses = [owner.address for owner in owners] threshold = 1 safe_creation = self.deploy_test_safe(owners=owner_addresses, threshold=threshold, initial_funding_wei=self.w3.toWei(0.1, 'ether')) safe_address = safe_creation.safe_address to = Account().create().address value = self.w3.toWei(0.01, 'ether') safe_tx_gas = 200000 data_gas = 100000 safe_tx = SafeTx(self.ethereum_client, safe_address, to, value, b'', 0, safe_tx_gas, data_gas, self.gas_price, None, None, safe_nonce=0) safe_tx.sign(owners[0].privateKey) self.assertEqual(safe_tx.call(tx_sender_address=self.ethereum_test_account.address), 1) tx_hash, _ = safe_tx.execute(tx_sender_private_key=self.ethereum_test_account.privateKey) self.ethereum_client.get_transaction_receipt(tx_hash, timeout=60) self.assertEqual(self.ethereum_client.get_balance(to), value) tx_decoder = TxDecoder() function_name, arguments = tx_decoder.decode_transaction(safe_tx.tx['data']) self.assertEqual(function_name, 'execTransaction') self.assertIn('baseGas', arguments)
def execute_safe_transaction(self, safe_tx: SafeTx): try: call_result = safe_tx.call(self.default_sender.address) print_formatted_text( HTML(f"Result: <ansigreen>{call_result}</ansigreen>")) if yes_or_no_question("Do you want to execute tx " + str(safe_tx)): tx_hash, tx = safe_tx.execute(self.default_sender.key, eip1559_speed=TxSpeed.NORMAL) self.executed_transactions.append(tx_hash.hex()) print_formatted_text( HTML( f"<ansigreen>Sent tx with tx-hash {tx_hash.hex()} " f"and safe-nonce {safe_tx.safe_nonce}, waiting for receipt</ansigreen>" )) tx_receipt = self.ethereum_client.get_transaction_receipt( tx_hash, timeout=120) if tx_receipt: fees = self.ethereum_client.w3.fromWei( tx_receipt["gasUsed"] * tx_receipt.get( "effectiveGasPrice", tx.get("gasPrice", 0)), "ether", ) print_formatted_text( HTML( f"<ansigreen>Tx was executed on block-number={tx_receipt['blockNumber']}, fees " f"deducted={fees}</ansigreen>")) self.safe_cli_info.nonce += 1 return True else: print_formatted_text( HTML( f"<ansired>Tx with tx-hash {tx_hash.hex()} still not mined</ansired>" )) except InvalidInternalTx as invalid_internal_tx: print_formatted_text( HTML( f"Result: <ansired>InvalidTx - {invalid_internal_tx}</ansired>" )) return False