How do I properly build a raw transaction

I am trying to build raw transactions in Java with Web3j.
Our goal that we are trying to achieve is, we want to build raw transactions, send them to another trusted party that does the signing for us, they return the signed transaction and we broadcast it.

I found this so far:

RawTransaction.createContractTransaction(nonce, gasPrice, gasLimit, value, init)

However two things irritate me:

  • There is no destination-field
  • I don’t know how to fill out the init-data

In web3js, something like this would work in order to fill out the init field:

web3.eth.contract(abi)
And then I could call the functions of that contract and assign it to the init field and put it into the raw transaction.

What is the web3j equivalent to this?
An example that includes filling out the init field aswell would be highly appreciated

1 Like

Hello @s1r-mar71n,

Concerning your question, Web3j provides you with all the tools you need to reach what you described.

For the no destination-field: The RawTransaction.createContractTransaction() doesn’t need that because it will be deploying a new contract. If you want to send an EthCall or a regular Ether Transaction, please use : RawTransaction.createTransaction() and RawTransaction.createEtherTransaction() respectively.

The init field in RawTransaction.createContractTransaction() will contain the binary + encoded constructor. The encoded constructor can be generated using FunctionEncoder.encodeConstructor().

For an EthCall, the data field will be the encoded function calls. These latters can be generated using FunctionEncoder.encode(org.web3j.abi.datatypes.Function)).

For signing a raw transaction, please use the RawTransactionManager.sign().

For sending a signed transaction, please use the

  • RawTransactionManager.sendCall: for an eth call where you expect a return value
  • RawTransactionManager.sendTransaction: for other kinds of transactions
  • RawTransactionManager.sendTransactionEIP1559: For EIP1559 gas fees proposal

Let us know if you need any additional information.

1 Like

You can use web3j.ethSendRawTransaction for that.

1 Like

Your replies have been awesome so far, thanks for that!
Only one last thing I struggle with now:

lets say my smart contract expects an array of addresses, how do I pass that to Function?

Because the Constructor of Function is String, List<web3j.abi.datatypes.Type>, List<TypeReference<?>>

You can do something like :

FunctionEncoder.encode(new Function(
      "functionName", 
      Arrays.asList(
           new org.web3j.abi.datatypes.Address("0x123"), 
           new org.web3j.abi.datatypes.Address(BigInteger.valueOf(324)
      ), 
      Collections.singletonList(new org.web3j.abi.datatypes.generated.Uint32(2323)
));
1 Like

Correct me if I’m wrong, but your encoded function is made for a function with this signature, isn’t it?

function functionName(address val1, address val2)public returns(uint32){
}

The function that I’m looking to build a raw transaction for looks more like this:

function distribute(address[ ] memory recipients, uint256 [ ] memory vals)public{
}

Hi, you can easily check how this could be done by creating a simple smart contract with this function and then generating the smart contract wrapper for it.

In that particular function, the generated code would be:

final Function function = new Function(
                "distribute", 
                Arrays.<Type>asList(new org.web3j.abi.datatypes.DynamicArray<org.web3j.abi.datatypes.Address>(
                        org.web3j.abi.datatypes.Address.class,
                        org.web3j.abi.Utils.typeMap(recipients, org.web3j.abi.datatypes.Address.class)), 
                new org.web3j.abi.datatypes.DynamicArray<org.web3j.abi.datatypes.generated.Uint256>(
                        org.web3j.abi.datatypes.generated.Uint256.class,
                        org.web3j.abi.Utils.typeMap(vals, org.web3j.abi.datatypes.generated.Uint256.class))), 
                Collections.<TypeReference<?>>emptyList());

Where recipients is a List<String> and vals a List<BigInteger>.

Then you can encode the result with:

FunctionEncoder.encode(function);

This is the Solidity code I used to generate this function:

pragma solidity ^0.6.0;

contract TestArray {
    function distribute(address[ ] memory recipients, uint256 [ ] memory vals) public{
    }
}

You can find more information on how to generate smart contract wrappers using the Gradle or Maven plugins or the Epirus CLI.

I hope that helps.

1 Like