Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

{Ethereum / Web3.js} TransactionRevertInstructionError: Transaction has been reverted by the EVM #7122

Closed
Smart-Yanmeng opened this issue Jun 22, 2024 · 5 comments
Labels
4.x 4.0 related

Comments

@Smart-Yanmeng
Copy link

I met the error when I learned to use the API of Web3.eth.sendSignedTransaction() , here is my code and errors.

<script setup>

import {ref} from "vue";
import {Web3} from "web3";

var web3 = new Web3(Web3.givenProvider ||
    "wss:[sepolia web]");

const address = ref("[The right sender address]")
const priKey = ref('[The right sender privateKey]')
const balance = ref(0)
web3.eth.getBalance(address.value).then((res) => {
  balance.value = web3.utils.fromWei(res, 'ether');
})

const send = async () => {

  const nonce = await web3.eth.getTransactionCount(address.value);

  const txParams = {
    nonce: web3.utils.toHex(nonce),
    gasPrice: web3.utils.toHex(web3.utils.toWei('20', 'gwei')),
    gasLimit: web3.utils.toHex(21000),
    to: '[The right receiver address]',
    value: web3.utils.toHex(web3.utils.toWei('0.01', 'ether')),
  };

  const signedTx = await web3.eth.accounts.signTransaction(txParams, priKey.value);

  const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
  console.log('Transaction receipt:', receipt);
}

</script>

In the [] is the right infomations, and when I use the function send and then get the errors:

get_transaction_error.js:67 Uncaught (in promise) TransactionRevertInstructionError: Transaction has been reverted by the EVM
    at eval (get_transaction_error.js:67:15)
    at Generator.next (<anonymous>)
    at eval (get_transaction_error.js:47:67)
    at new Promise (<anonymous>)
    at __awaiter (get_transaction_error.js:29:10)
    at getTransactionError (get_transaction_error.js:54:10)
    at SendTxHelper.eval (send_tx_helper.js:116:101)
    at Generator.next (<anonymous>)
    at fulfilled (send_tx_helper.js:25:24)

My environment is over here:

Node.js -> 20.15.0
npm -> 10.7.0
vue/cli -> 5.0.0
vue -> 3.2.13
Web3.js -> 4.10.0
vant -> 4.9.1

Please help me to find out the error, I am a rookie in web3 :(

I used ethereum-tx to make the Transactions, but I failed.

Then I used the newest version @ethereumjs/tx, but failed either....

I would be glad if you could tell me the usage of the @ethereumjs/tx !

@SantiagoDevRel
Copy link
Member

Hey @Smart-Yanmeng ! I'd say the easiest way is just to use the method sendTransaction() instead of signing and then sending, since web3.js will fillout any missing fields:

SendTransaction()

const privateKey = "private_key";

// Create a wallet to sign
const wallet = web3.eth.accounts.wallet.add(privateKey);

// Construct Tx
const txParams = {
    from: wallet[0].address,
    to: receiverAddress,
  };

// Send tx(and sign under the hood by web3.js)
const receipt = await web3.eth.sendTransaction(txParams)

// Print receipt
console.log(receipt)

or to send a rawTx(sign first and then send):
SendSignedTransaction()

 const txParams = {
    from: senderAddress,
    to: receiverAddress,
    // the following two properties must be included in raw transactions
    maxFeePerGas: block.baseFeePerGas * 2n,
    maxPriorityFeePerGas: 100000,
  };

// Sign
const rawTx = await web3.eth.accounts.signTransaction(txParams, privateKey);

// Send
const receipt = await web3.eth.sendSignedTransaction(rawTx.rawTransaction);

// Print receipt  
console.log('Transaction receipt:', receipt);

Pls let me know if it helps!!🫶

@mconnelly8 mconnelly8 added the 4.x 4.0 related label Jun 25, 2024
@mconnelly8
Copy link

Hey @Smart-Yanmeng, does the above information help you? Please let us know if not and you are still getting an error?

@Smart-Yanmeng
Copy link
Author

Smart-Yanmeng commented Jul 18, 2024

Hey @Smart-Yanmeng ! I'd say the easiest way is just to use the method sendTransaction() instead of signing and then sending, since web3.js will fillout any missing fields:

SendTransaction()

const privateKey = "private_key";

// Create a wallet to sign
const wallet = web3.eth.accounts.wallet.add(privateKey);

// Construct Tx
const txParams = {
    from: wallet[0].address,
    to: receiverAddress,
  };

// Send tx(and sign under the hood by web3.js)
const receipt = await web3.eth.sendTransaction(txParams)

// Print receipt
console.log(receipt)

or to send a rawTx(sign first and then send): SendSignedTransaction()

 const txParams = {
    from: senderAddress,
    to: receiverAddress,
    // the following two properties must be included in raw transactions
    maxFeePerGas: block.baseFeePerGas * 2n,
    maxPriorityFeePerGas: 100000,
  };

// Sign
const rawTx = await web3.eth.accounts.signTransaction(txParams, privateKey);

// Send
const receipt = await web3.eth.sendSignedTransaction(rawTx.rawTransaction);

// Print receipt  
console.log('Transaction receipt:', receipt);

Pls let me know if it helps!!🫶

Hello @SantiagoDevRel, thanks for your reply, but sorry, it doesn't work...
My new code here:

<script setup>
import { ref } from "vue";
import Web3 from "web3";

const web3 = new Web3(Web3.givenProvider || "wss://sepolia.infura.io/ws/v3/b9302a3d12ea44e7b23b5d00a2fc1b2f");

const address = ref("[The right sender address]");
const priKey = ref('[The right sender privateKey]');

const sendTransaction = async (receiverAddress) => {
  const privateKey = priKey.value;
  const wallet = web3.eth.accounts.wallet.add(privateKey);
  const nonce = await web3.eth.getTransactionCount(address.value);

  const txParams = {
    nonce: web3.utils.toHex(nonce),
    gasPrice: web3.utils.toHex(web3.utils.toWei('20', 'gwei')),
    gasLimit: web3.utils.toHex(21000),
    from: wallet[0].address,
    to: receiverAddress,
    value: web3.utils.toHex(web3.utils.toWei('0.000001', 'ether')),
  };

  const receipt = await web3.eth.sendTransaction(txParams);

  console.log('Transaction receipt:', receipt);
};
</script>

And get the error here:

Transaction has been reverted by the EVM
TransactionRevertInstructionError: Transaction has been reverted by the EVM
    at eval (webpack-internal:///./node_modules/web3-eth/lib/esm/utils/get_transaction_error.js:67:15)
    at Generator.next (<anonymous>)
    at eval (webpack-internal:///./node_modules/web3-eth/lib/esm/utils/get_transaction_error.js:47:67)
    at new Promise (<anonymous>)
    at __awaiter (webpack-internal:///./node_modules/web3-eth/lib/esm/utils/get_transaction_error.js:29:10)
    at getTransactionError (webpack-internal:///./node_modules/web3-eth/lib/esm/utils/get_transaction_error.js:54:10)
    at SendTxHelper.eval (webpack-internal:///./node_modules/web3-eth/lib/esm/utils/send_tx_helper.js:116:101)
    at Generator.next (<anonymous>)
    at fulfilled (webpack-internal:///./node_modules/web3-eth/lib/esm/utils/send_tx_helper.js:25:24)

My account has 0.3 SepoliaETH, I have no idea where did the fault...
Or could you run my code in your environment? Thank you so much.

@SantiagoDevRel
Copy link
Member

Hey @Smart-Yanmeng thanks for sharing the code, it helped me to find the errors and even helped me to be aware of some interesting things:

  1. Value field
// when you are using the function `toWei()` for the `value` field, it is converting the 0.000001 to 1000000000000
// BUT the issue is that this returns a string, not a number

// so basically after the `toWei()`, you are doing:
toHex("1000000000000") 
// string, resulting in --> 0x31303030303030303030303030 which is 3897093499672225829160085368880 ❌

//BUT it should be: 
toHex(1000000000000) 
// number, resulting in --> 0xe8d4a51000 which is 1000000000000 ✅

// Solution #1, parse to Number first
value: web3.utils.toHex(Number(web3.utils.toWei("0.000001", "ether")))

// Solution #2, just send the value as string(number) - so remove the toHex()
value: web3.utils.toWei("0.000001", "ether"),
  1. gas issues
// You are sending the wrong value for `gasPrice` which is higher than your gasLimit

// Solution #1, just leave the gasPrice up to web3.js - so remove the gas price
  const txParams = {
    nonce: web3.utils.toHex(nonce),
    //gasPrice: web3.utils.toHex(web3.utils.toWei("20", "gwei")), // 20000000000 
    gasLimit: web3.utils.toHex(21000), // 21000
    from: wallet[0].address,
    to: receiverAddress,
    value: web3.utils.toWei("0.000001", "ether"),
  };

// Solution #2, fetch the current `gasPrice` using web3.js
const txParams = {
    nonce: web3.utils.toHex(nonce),
    //gasPrice: await web3.eth.getGasPrice(), // 3731976n as of now
    gasLimit: web3.utils.toHex(21000),
    from: wallet[0].address,
    to: receiverAddress,
    value: web3.utils.toWei("0.000001", "ether"),
  };

// Solution #3, just put a lower gasPrice lower than your gasLimit but higher than the current gasPrice so it doesnt take years to execute

So here is my final code
(heads up with the key of the infura node, u should reset it):

import { Web3 } from "web3";

const web3 = new Web3("wss://sepolia.infura.io/ws/v3/b9302a3d12ea44e7b23b5d00a2fc1b2f"); 

const from = "...";
const priKey = "...";
const to = "...";

const sendTransaction = async (receiverAddress) => {
  const privateKey = priKey;
  const wallet = web3.eth.accounts.wallet.add(privateKey);
  const nonce = await web3.eth.getTransactionCount(from);
  console.log(await web3.eth.getGasPrice());

  const txParams = {
    nonce: web3.utils.toHex(nonce),
    gasPrice: await web3.eth.getGasPrice(),
    gasLimit: web3.utils.toHex(21000),
    from: wallet[0].address,
    to: receiverAddress,
    value: web3.utils.toWei("0.000001", "ether"),
  };

  const receipt = await web3.eth.sendTransaction(txParams);

  console.log("Transaction receipt:", receipt);
};

sendTransaction(to);

Pls let me know if it helps!!
Here you can see like the 10tx I did to test this hahah
Etherscan

@Smart-Yanmeng
Copy link
Author

Hey @Smart-Yanmeng thanks for sharing the code, it helped me to find the errors and even helped me to be aware of some interesting things:

  1. Value field
// when you are using the function `toWei()` for the `value` field, it is converting the 0.000001 to 1000000000000
// BUT the issue is that this returns a string, not a number

// so basically after the `toWei()`, you are doing:
toHex("1000000000000") 
// string, resulting in --> 0x31303030303030303030303030 which is 3897093499672225829160085368880 ❌

//BUT it should be: 
toHex(1000000000000) 
// number, resulting in --> 0xe8d4a51000 which is 1000000000000 ✅

// Solution #1, parse to Number first
value: web3.utils.toHex(Number(web3.utils.toWei("0.000001", "ether")))

// Solution #2, just send the value as string(number) - so remove the toHex()
value: web3.utils.toWei("0.000001", "ether"),
  1. gas issues
// You are sending the wrong value for `gasPrice` which is higher than your gasLimit

// Solution #1, just leave the gasPrice up to web3.js - so remove the gas price
  const txParams = {
    nonce: web3.utils.toHex(nonce),
    //gasPrice: web3.utils.toHex(web3.utils.toWei("20", "gwei")), // 20000000000 
    gasLimit: web3.utils.toHex(21000), // 21000
    from: wallet[0].address,
    to: receiverAddress,
    value: web3.utils.toWei("0.000001", "ether"),
  };

// Solution #2, fetch the current `gasPrice` using web3.js
const txParams = {
    nonce: web3.utils.toHex(nonce),
    //gasPrice: await web3.eth.getGasPrice(), // 3731976n as of now
    gasLimit: web3.utils.toHex(21000),
    from: wallet[0].address,
    to: receiverAddress,
    value: web3.utils.toWei("0.000001", "ether"),
  };

// Solution #3, just put a lower gasPrice lower than your gasLimit but higher than the current gasPrice so it doesnt take years to execute

So here is my final code (heads up with the key of the infura node, u should reset it):

import { Web3 } from "web3";

const web3 = new Web3("wss://sepolia.infura.io/ws/v3/b9302a3d12ea44e7b23b5d00a2fc1b2f"); 

const from = "...";
const priKey = "...";
const to = "...";

const sendTransaction = async (receiverAddress) => {
  const privateKey = priKey;
  const wallet = web3.eth.accounts.wallet.add(privateKey);
  const nonce = await web3.eth.getTransactionCount(from);
  console.log(await web3.eth.getGasPrice());

  const txParams = {
    nonce: web3.utils.toHex(nonce),
    gasPrice: await web3.eth.getGasPrice(),
    gasLimit: web3.utils.toHex(21000),
    from: wallet[0].address,
    to: receiverAddress,
    value: web3.utils.toWei("0.000001", "ether"),
  };

  const receipt = await web3.eth.sendTransaction(txParams);

  console.log("Transaction receipt:", receipt);
};

sendTransaction(to);

Pls let me know if it helps!! Here you can see like the 10tx I did to test this hahah Etherscan

Ohhhhhhhh! @SantiagoDevRel, it works successfully! Thank you soooooo much !!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4.x 4.0 related
Projects
None yet
Development

No branches or pull requests

3 participants