1

I'm in the process of learning how to write smart contracts and make transactions using the Ethereum blockchain.

I'm following this tutorial and it looks like making a transaction and then adding a record of it in the blockchain are two separate actions.

I'm confused as to the gas fee that needs to be paid for making the transaction. And whether another fee needs to then be paid for adding a record of that transaction to the blockchain.

In the code I'm looking at as a tutorial, the transaction itself takes place here:

        await ethereum.request({
          method: "eth_sendTransaction",
          params: [{
            from: currentAccount,
            to: addressTo,
            gas: "0x5208",
            value: parsedAmount._hex,
          }],
        });
  1. the developer seems to have hardcoded a value for the gas fee: 0x5208. But isn't the value constantly changing? When the above method is called, the Metamask extension opens up and asks the user to confirm the transaction, so I guess maybe it is at that point that the user learns how much they will be paying in gas fees and the 0x5208 I'm looking at above is not what I think it is ?
  2. What if I, the developer, want to know the fee the user will be paying at that moment as well ? Is there a ethereum.getCurrentGasFeeFor(value) ?

Once the above transaction is confirmed, then a record of that transaction is added to the blockchain here:

const transactionHash = await transactionsContract.addToBlockchain(addressTo, parsedAmount, message, keyword);

But in the above code there is no indication about the app itself (not the user) having to also pay a fee for adding a record of the transaction to the blockchain.

  1. I thought that (a) there is a limit on how big the record/block can be and (b) depending on the size of the record/block, the app itself would also have to pay a fee. What if in the above scenario keyword is a 10byte String or a 800Kb string. What will happen in either case?

I would have expected something like:

// pseudocode:

let block = { addressTo, parsedAmount, message, keyword }
let fee = ethereum.computeFeeFor(block)
if (imOkWith(fee)) {
  const transactionHash = await transactionsContract.addToBlockchain(
    block,
    // so that the app is charged for adding this block to the blockchain
    appWalletAddress: '....'
  )
  .....
  ...
} else {
  dealWithTheProblemSomehow() ?
}

Thank you in advance for your help

1 Answer 1

1

These are awesome questions! I'll try to answer each with some additional context. The first paragraph of each section is a rough summary, the rest is additional context.

Why can the gas amount be hardcoded? Isn't it always changing?

The price of each unit of gas is always changing, but the amount of gas a transaction takes is determined solely by the transaction and the gas cost of any "instructions" that the transaction executes.

To understand what this really means, you need to know a bit about how the EVM works. But to oversimplify, every "action" you can take on the state of the Ethereum chain (like sending Ether, storing some data in contract storage, adding two numbers, etc...) costs a predefined amount of gas. Every transaction that manipulates the state of the chain pays gas for those actions, plus some baseline gas attached to every transaction.

So if I know what my smart contract does exactly (i.e. the instructions it runs) I can calculate the amount of gas that calling a function in my smart contract will take. Solidity IDEs like Remix will often expose this information to you, but it's also the basic idea behind how MetaMask and other wallets "guess" how much gas is required for each transaction.

In this case, the gas amount is 0x5208 which is a nice round 21000 in decimal. 21000 happens to be the gas "Paid for every transaction" according to page 27 of the Ethereum Yellow Paper. This lines up with what is in code, since the eth_sendTransaction RPC call doesn't have any data that would invoke any additional instructions.

The price of each unit of gas changes according to some rules set out in the Ethereum specification, though. That's probably what you're seeing when you see the cost of your transaction changing, since MetaMask and other wallets often show the transaction cost in units of Ether or fiat, not in gas units.

Once you figure out how much gas a transaction will cost, you can then use a gas API to figure out the current price of each unit of gas. (You could also just derive it from the state of the chain, but that's a different and more complicated story. It's how the API providers get the price of gas.)

This should answer your questions 1 and 2.

Are there separate fees for executing the transaction and adding it to the chain?

Yes and no. Yes in that this code would cause two transactions to happen and so two fees. No in that the gas cost of each transaction includes its commitment to the chain. So the real answer here is "no".

The example you're showing is doing something a bit weird.

  • First it's calling eth_sendTransaction to send an empty transaction that just transfers parsedAmount Ether (which is basically what a regular Ether transfer is) from currentAddress to toAddress.
  • Then it's calling a custom smart contract's custom-written addToBlockchain function (I found the smart contract address here). This simply stores a record of the transaction for some reason (I assume for some logic down the line in the tutorial). This has nothing to do with the security of Ethereum or anything "official", this is all custom logic.

This should answer half of your question 3.

Is there a maximum size to my transactions?

Not directly, but yes. This answer does a good job of describing this behaviour.

The summary is that there is no limit on transaction sizes, but there is a limit on the maximum amount of gas in each block. Since each transaction must be contained in a single block, and sending "calldata" (basically function call data like function parameters) costs gas, there is a maximum size to the transaction one way or another.

This should answer the other half of your question 3.

3
  • In the example the developer wants to store some data for each transaction ("keyword", "message") and later to be able to retrieve them. Instead of using a DB they're using the Ethereum blockchain. That is what I understand. I could be wrong. Are you implying they could've done both (make transaction + attach data to it) in one single action? May 8 at 17:59
  • As in (pseudoode) : let transacrionId = await ethereum.request({ method: "eth_sendTransaction", params: [{ from, to, gas, value, randomData }] }) let { randomData } = await getTransactionById(transactionId); ? May 8 at 18:00
  • Yep, you could attach data to the transaction. But that might make it a bit difficult to keep track of which transactions are just "regular" transfers that happen to have data, and which of them are your special "recorded" transfers. This behaviour might make sense in the grand scheme of things, since it's often not trivial to keep a running list of data on chain without relying on contract storage. May 8 at 21:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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