Ejemplo n.º 1
0
 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
Ejemplo n.º 2
0
    def batch_txs(self, safe_nonce: int,
                  safe_tx_hashes: Sequence[bytes]) -> bool:
        """
        Submit signatures to the tx service. It's recommended to be on Safe v1.3.0 to prevent issues
        with `safeTxGas` and gas estimation.

        :return:
        """

        if not self.ethereum_client.is_contract(
                LAST_MULTISEND_CALL_ONLY_CONTRACT):
            print_formatted_text(
                HTML(
                    f"<ansired>Multisend call only contract {LAST_MULTISEND_CALL_ONLY_CONTRACT} "
                    f"is not deployed on this network and it's required for batching txs</ansired>"
                ))

        multisend_txs = []
        for safe_tx_hash in safe_tx_hashes:
            safe_tx, _ = self.safe_tx_service.get_safe_transaction(
                safe_tx_hash)
            # Check if call is already a Multisend call
            inner_txs = MultiSend.from_transaction_data(safe_tx.data)
            if inner_txs:
                multisend_txs.extend(inner_txs)
            else:
                multisend_txs.append(
                    MultiSendTx(MultiSendOperation.CALL, safe_tx.to,
                                safe_tx.value, safe_tx.data))

        if len(multisend_txs) > 1:
            multisend = MultiSend(LAST_MULTISEND_CALL_ONLY_CONTRACT,
                                  self.ethereum_client)
            safe_tx = SafeTx(
                self.ethereum_client,
                self.address,
                LAST_MULTISEND_CALL_ONLY_CONTRACT,
                0,
                multisend.build_tx_data(multisend_txs),
                SafeOperation.DELEGATE_CALL.value,
                0,
                0,
                0,
                None,
                None,
                safe_nonce=safe_nonce,
            )
        else:
            safe_tx.safe_tx_gas = 0
            safe_tx.base_gas = 0
            safe_tx.gas_price = 0
            safe_tx.signatures = b""
            safe_tx.safe_nonce = safe_nonce  # Resend single transaction
        safe_tx = self.sign_transaction(safe_tx)
        if not safe_tx.signatures:
            print_formatted_text(
                HTML("<ansired>At least one owner must be loaded</ansired>"))
            return False
        else:
            return self.post_transaction_to_tx_service(safe_tx)