Hardforks, such as Istanbul, have illustrated the best practice that smart contracts should not make any assumptions about gas.
Gas costs have, can, and will change, for example: Is transfer() still safe after the Istanbul update?
There are UNGAS proposals and discussions:
Disable opcode GAS. For CALL, CALLCODE and DELEGATECALL, remove the gas parameter, and instead, always set the parameter to be the current available gas left.
If a call frame returns out of gas, revert all changes in current transaction and exit execution.
https://github.com/corepaper/ep/issues/1
https://ethereum.corepaper.org/compatibility/forward/
https://ethereum.corepaper.org/compatibility/legacy-repricing/
The UNGAS specification is short and simple, but its ramifications may be brilliantly deep.
History question for the core devs who designed Ethereum, why was GAS opcode and parameters in the EVM? It seemed to cause many subtleties; some got exposed for simple transfers.
Was UNGAS considered in the design phase? If so, what were the reasons for not adopting it?