5

I'm looking forward to get transaction cost for a particular function call in solidity onChain. I found methods using the web3.estimateGasCost(). But i need is, i should be able to calculate this on-chain. Is there anyway that i can calculate this on chain.

My purpose is like, If someone deposit a amount into my contract, the gas price should be less than 1% of the amount he is depositing, otherwise it should skip some steps.

Thank you

3 Answers 3

5

As far as I know - you can't actually estimate the gas from solidity.

Two Related pieces of functionality that might be helpful:

  1. You can potentially use gasLeft(); Global Vars

You can call this function to understand how much gas is left in the transaction execution. You can also call this before and after a function call to understand how much gas that function used.

  1. tx.gasprice is also available as a global variable
1
  • ,Thank you for replying, but This actually doesn't solve my problem, i want to estimate gas price of a particular function before calling it Commented Mar 16, 2021 at 9:57
1
  1. Call gasLeft() at the beginning of the contract, and gasLeft() at the end of the contract call to determine the amount of gas used.
  2. Multiply tx.gasprice with the amount of gas used to get the cost of the that has been spent.
  3. Compare that with the deposit amount.
0

After you successfully load the contract, you call the function, and calling the function will return an object.

  const result = await contract.methods
    .purchase(...args)
    .send({ from: account.data, value });
  console.log("result of calling contract function", result);

result of log will be like this:

        {
// we need this hash to create the transaction    transactionHash:'0x1fef7f56dfa3e29aea427545de0d2b2a170c4a6e6df827a34949d37c9076ad6a', 
    transactionIndex: 0, 
    blockHash:'0x5ea8d44dc43ed4390083a6f7a9288215cf8d825dbe19771547d3c4be6ced5c3c', blockNumber: 423, from: '0xd75536f6b5712f78d444ba0c3b8aae74b7a226ba', …}
        blockHash: "0x5ea8d44dc43ed4390083a6f7a9288215cf8d825dbe19771547d3c4be6ced5c3c"
        blockNumber: 423
        contractAddress: null
        cumulativeGasUsed: 133009
        events: {}
        from: "0xd75536f6b5712f78d444ba0c3b8aae74b7a226ba"
        // ------------WE NEED gasUsed----------------
        gasUsed: 133009
        logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
        status: true
        to: "0xf2654762d9348d332ab707ca51d40cc8f84f9bb3"
        transactionHash: "0x1fef7f56dfa3e29aea427545de0d2b2a170c4a6e6df827a34949d37c9076ad6a"
        transactionIndex: 0
        [[Prototype]]: Object
  • Create the transaction from "transactionHash" you get above

    const tx = await web3.eth.getTransaction(result.transactionHash);
    

From tx we can get the gasPrice

 console.log("transaction",tx)

this is the tx object we need gasPrice

    {
v: '0x0a96', 
r: '0x015550053e18134d342879d0255ba1b4dce9b60339764e7c61538397bf91ddaa', 
s: '0x5d995ff90c19b98fb0b941f4cab7022d140fa7f9a5b2ba74f1eff397e8a61e00', 
to: '0xF2654762d9348D332Ab707CA51d40cc8f84F9BB3', gas: 201726, …} 
accessList: null 
blockHash: null 
blockNumber: null 
from: "0xD75536f6b5712f78D444bA0C3b8Aae74B7A226bA" 
gas: 201726 
// ------- we need gasPrice--------
gasPrice: "20000000000" 
hash: "0xc9665699efc0da2fb3adc23cec11a0e662ca65d1fab4b6a2517de5bade392155" input: "0xd76821cb38343733353500000000000000000000000000000000000000000000000000002bd67188592a17673351fbfbcf90c77bced32546b2528ba30334b36f4a4f9630" nonce: 259 r: "0x015550053e18134d342879d0255ba1b4dce9b60339764e7c61538397bf91ddaa" s: "0x5d995ff90c19b98fb0b941f4cab7022d140fa7f9a5b2ba74f1eff397e8a61e00" to: "0xF2654762d9348D332Ab707CA51d40cc8f84F9BB3" transactionIndex: null type: 0 v: "0x0a96"
 value: "3609000000000000" 
[[Prototype]]: Object
  • so far we got gasUsed and gasPrice, it is easy to calculate the gas price. Before working with numbers in solidity, it is important to convert them to BigNumber objects to work precisely and also BN objects has extra methods to use:

    // define a reusable function const toBN = (value) => web3.utils.toBN(value);

then calculate the gasUsed and gasPrice

  const gasUsed = toBN(result.gasUsed);
  const gasPrice = toBN(tx.gasPrice);

Finally

  // gasUsed is BN object and "mul" is for multiplication
  const gas = gasUsed.mul(gasPrice);

Note that, different packages will end end up different data structure, so make sure you log the result and transaction and get the correct path

1
  • The solution looks great, but in the client context. IMO the question is in the solidity contract context. He wants to estimate gas a function will spent before call it from the contract, at least was what I got =).
    – 0xTheL
    Commented Oct 3, 2022 at 19:23

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.