'Why is a transaction consuming gas for a public view function?
I deployed the following smart contract on Ropsten ethereum test network and afterwards I tried making a transaction using @alch/alchemy-web3 npm package (Yes, I am using Alchemy API) but as you can see I got a fee on the transaction. Why is that? Aren't public view function calls supposed to cost 0 gas?
deployed smart contract
// SPDX-Lincense-Identifier: MIT
pragma solidity ^0.8.11;
contract VendingMachine {
address public owner;
mapping(address => uint256) public donutBalances;
constructor() {
owner = msg.sender;
donutBalances[address(this)] = 100;
}
function getVendingMachineBalance() public view returns (uint256) {
return donutBalances[address(this)];
}
function restock(uint amount) public {
require(msg.sender == owner, "Only the owner can restock this machine.");
donutBalances[address(this)] += amount;
}
function purchase(uint amount) public payable {
require(msg.sender == owner, "Only the owner can restock this machine.");
require(donutBalances[address(this)] >= amount, "Not enough donuts in stock to fulfill purchase request.");
require(msg.value >= amount*2 ether, "You must pay at least 2 ether / donut.");
donutBalances[address(this)] -= amount;
donutBalances[msg.sender] += amount;
}
}
transaction code javascript
const { API_URL, METAMASK_ACCOUNT_PRIVATE_KEY, METAMASK_ACCOUNT_PUBLIC_KEY } = process.env;
const { createAlchemyWeb3 } = require("@alch/alchemy-web3");
const web3 = createAlchemyWeb3(`${API_URL}`);
const contractAddress = '0xc7E286A86e4c5b8F7d52fA3F4Fe7D9DE6601b6F9'
const contractAPI = new web3.eth.Contract(contract.abi, contractAddress)
const nonce = await web3.eth.getTransactionCount(METAMASK_ACCOUNT_PUBLIC_KEY, 'latest');
const transaction = {
to: contractAddress, // faucet address to return eth
gas: 500000,
nonce: nonce,
data: contractAPI.methods.getVendingMachineBalance().encodeABI()
// optional data field to send message or execute smart contract
};
const signedTx = await web3.eth.accounts.signTransaction(transaction, METAMASK_ACCOUNT_PRIVATE_KEY)
web3.eth.sendSignedTransaction(signedTx.rawTransaction, function (error, hash) {
if (!error) {
console.log("🎉 The hash of your transaction is: ", hash, "\n Check Alchemy's Mempool to view the status of your transaction!");
} else {
console.log("❗Something went wrong while submitting your transaction:", error)
}
});
Transaction: https://ropsten.etherscan.io/tx/0x8ce3a288072809a804adac2206dc566dfb3eb3ddba3330bcb52ca6be71963b71
Solution 1:[1]
There are two ways to interact with a smart contract. A transaction (read-write, costs gas fees) and a call (read-only, gas free).
Your JS snippet sends a transaction. If you want to invoke the getVendingMachineBalance()
function using a (gas free) call, you can use the .call() web3js method.
const contractAPI = new web3.eth.Contract(contract.abi, contractAddress);
const response = await contractAPI.methods.getVendingMachineBalance().call();
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Petr Hejda |