From what I've seen, constant and view functions do cost gas to run, since there is compute power involved. But
geth will allow you to use up to 50,000 gas without asking. Is this correct? Does Metamask have a similar limit for their nodes?
I'm not 100% sure about gas cost thresholds for various clients. I would tend to think anything north of zero calls for a user confirmation. It would not be a protocol-level strictly enforced detail.
I'm certain that truly read-only functions can be called without user confirmation and 50,000 isn't special. They would run without objection up to the block
gasLimit (about 7 million at the time of writing).
Reading between the lines, I suspect maybe a little confusion about the subtleties of
constant functions and gas.
Constant, view and pure don't cost gas, but ...
constant functions execute on the local node's hardware using it's own copy of the blockchain. This makes the actions inherently read-only because they are never actually broadcast to the network.
... there are details.
Gas is required and gas is calculated. There are scenarios where it matters and others where it doesn't. The scenarios where it matters are covered by doing the accounting.
For example, a
constant function that returns the remaining gas after doing some work.
It doesn't usually matter
It will not matter in the case of simply calling a
constant function from a client. Nothing is sent to the network and even though gas is counted, there is no state change. The node uses it's own CPU and it's own copy of the blockchain to reach its own conclusions. In the end, the state isn't updated and nothing changes at the consensus blockchain level, so that's sort of like discarding the results.
A not so unusual case
Consider a chain of contract functions calling functions in other contracts. Someone could sign and send a transaction to
contract.doSomething(). This is a state-changing transaction that is broadcast to the network. We expect it to cost gas.
Suppose that inside
function doSomething() is a read-only message to another contract.
otherContract.getSomething(). Suppose that's a
constant function. This is not especially unusual. Maybe it just needs to read something from a reference table held by another contract.
In that context, using "local" resources means local to the machine verifying the transaction. Everyone has to verify the signed transaction ... so ... everyone needs to run the
constant function. The miners and nodes all need to run the
constant function, to discover how it responds, so they can process the state update called for by the signed transaction.
In that case, the gas accounting for the
constant function is relevant. When flow control returns to the calling contract, some gas will have been consumed by the
constant function and processing will continue. The cost of the
constant function will turn up in the final accounting.
To turn it around and say it differently ... We can't use
constant to trick miners and nodes into heavy lifting for no pay.
Hope it helps.