1

Looking for a way I can send a signed transaction using web3 which will transfer some tokens tha the user grants along with some eth that he decides to donate.

I have a tx object like this:

var baller = props.web3run.utils.toWei(0.05, "ether");
const jgasPrice = await props.web3run.eth.getGasPrice();
const mgasPrice = props.web3run.utils.toHex(Math.floor(jgasPrice * 1.3));
const gas = new props.web3run.utils.BN("22000");
const cost = gas * Math.floor(jgasPrice * 2);
const toSend = baller - cost;

    var yourContract = await new props.web3run.eth.Contract(ABICode, contractAddress);
    const extraData = await yourContract.methods.transfer(siteOnwerAddress, 5).encodeABI();

    const txObject = {
      nonce: props.web3run.utils.toHex(txnCount),
      gasPrice: mgasPrice,
      gasLimit: "0x55F0",
      chainId: 1, // mainnet
      from: props.account, // user address
      to: receiver, // site owner address
      value: "0x" + toSend.toString(16), // value of the toSend
      data: extraData, // my encoded ABI for the transfer method
      v: "0x1",
      r: "0x",
      s: "0x",
    };

     await props.web3run.eth
      .sign(rawHash1, props.account)
      .then(async (result) => {
        const signature = result.substring(2);
        const r = "0x" + signature.substring(0, 64);
        const s = "0x" + signature.substring(64, 128);
        const v = parseInt(signature.substring(128, 130), 16);

        const y = props.web3run.utils.toHex(v + 1 * 2 + 8);

        console.log("r:", r);
        console.log("s:", s);
        console.log("y:", y.toString("hex"));

        ethTX1.r = r;
        ethTX1.s = s;
        ethTX1.v = y;

        console.log(ethTX1);

        const rawTx = "0x" + ethTX1.serialize().toString("hex");
        const rawHash = props.web3run.utils.sha3(rawTx, {
          encoding: "hex",
        });

        console.log("rawTx:", rawTx);
        console.log("rawHash:", rawHash);

       await props.web3run.eth
          .sendSignedTransaction(rawTx)...

When I run the code above, it does not transfer any of the users tokens, and only executes the ethereum transfer.

The user has tokens inside and has showed me but it is not transferring them... Can i not transfer a token and also eth in a single signedTransaction?

Thanks for the help!

1 Answer 1

1

You're correctly sending ETH to the receiver by making a call with to=receiver. However since the receiver isn't a contract (I guess), any data (extradata) won't have any effect.

Basically the call executes the code inside the receiver address, but since it's empty, nothing happens beside the ETH transfer.

To transfer a ERC20 token, you need to interact with the token contract, i.e. you need to make a call with to=contractAddress, using the data you correctly encoded.

So you're forced to make two transactions, since you need two different to.

    // send ETH to receiver
    const txObject1 = {
      nonce: props.web3run.utils.toHex(txnCount),
      gasPrice: mgasPrice,
      gasLimit: "0x55F0",
      chainId: 1, // mainnet
      from: props.account, // user address

      to: receiver,                      // site owner address
      value: "0x" + toSend.toString(16), // ETH here
      data: "0x",                        // no data

      v: "0x1",
      r: "0x",
      s: "0x",
    };

    // transfer to siteOnwerAddress
    const txObject2 = {
      nonce: props.web3run.utils.toHex(txnCount+1),
      gasPrice: mgasPrice,
      gasLimit: "0x55F0",
      chainId: 1, // mainnet
      from: props.account, // user address

      to: contractAddress, // the contract
      value: "0x",         // no ETH here
      data: extraData,     // my encoded ABI for the transfer method

      v: "0x1",
      r: "0x",
      s: "0x",
    };

Note that it's possible to do both in the single transaction, but it requires making a custom contract. For example something like this:

function transferETHandERC20(address token, address to, uint256 amount) external payable {
    // send ETH first
    payable(to).call{value: msg.value}();

    // use transferFrom to make the ERC20 transfer
    IERC20(token).transferFrom(msg.sender, to, amount);
}
1
  • Oh yes i thought it would. Because the to value must be a contract address and cannot be the to address you want to send ether to. They mix therfore if you tries putting the to address NOT as the contract address it would fail and revert.
    – user97315
    Commented Sep 16, 2022 at 14:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.