Thanks, I’ve updated both now in the EIP, higher gas cost (1500) and renamed to EXTSLOAD.
Proposal A new EVM instruction EXTSLOAD (0x5c) that works like SLOAD (0x54) with the gas cost of EXTCODE(700) + SLOAD(800) = 1500 and an additional parameter representing the contract that is to be read from.
This constant misunderstanding is probably the biggest reason for why we definitely should introduce this new opcode. Any developer who currently codes Solidity assuming non-exposed storage variables are in any way private is creating attack surfaces today. The “private” is an artificial attribute that does not actually exist in any meaningful way and just leads to confusion as some people in fact believe that the data would be protected in some way – while it is not. It’s open today, readable by anyone who cares to. If there is an “attack” transaction that can only be created by knowing the internal storage state of a contract then it can be created today already. EXTSLOAD would wipe out this misunderstanding making it clear to every developer that their contract storage data is always in the open. This would clarify documentation and language around this whole topic.
From a software-engineering perspective, giving access to private members of another object is considered bad design, as it by-passes state encapsulation. This is not about data protection, this is about software design.
For example, when using EXTSLOAD on an OpenZeppeling proxy contract, it might work for a while, but then suddenly brake once the proxy contract is upgraded because the calling contract might have made wrong assumption about the internal state of the proxy contract. When calling methods on other people’s contracts, one should use the official API exposed through the according methods.
If you want to save gas, you should propose lower costs for calls to other contracts in general.
External clients can already arbitrarily read contract storage slots.
Further, there is a big difference between “giving access to private members of another object is considered bad design” and “accessing private members of another object is considered bad design”.
In other words, giving software developers more tools/functionality is not bad, just because some might shoot themselves in the foot. However, shooting yourself in the foot is almost always a bad idea.
In the proposal it is mentioned cost of the proposed opcode EXTSLOAD = cost of EXTCODE + cost of SLOAD. Since if self contract knows which slot id it wants to read from which target contract, the bytecode of the target contract does not provide any useful information and I think the target contract address and slot id is enough for the geth node (and others) to fetch the slot value from the SSD, so the cost could be simply a cost of a SLOAD.
Ah I can’t go to that sadly, but this opcode seems intuitively like something that would be very good. I’m having a fleeting thought (without much testing on it) that some current smart contracts might rely on the fact that others can’t read their state right now?
I wonder if we can come up with an example where adding this opcode gives smart contracts the ability to do damage of some kind that you couldn’t already do off-chain with the sensitive data.
I came across a contract that prevents other contracts from directly reading the state on it. I think the benefit comes from charging money for whitelisting an address, probably to fund gas. Allowing EXTSLOAD would harm the oracle business (which is definitely bad). However, looking at the oracle’s business logic the read method loads the slot at location 0x03 which is not recorded in the same block (the read function uses cur feed and not the nxt feed), hence an external untrusted party can provide the oracle feed and proof to a smart contract, which can proceed to utilize the feed for its logic, without paying the oracle maintainer for being whitelisted. But oracles should get funding for gas otherwise it would be a problem. Not sure if it is difficult for open oracles to be economically sustainable through donations or if the whitelist is really worth it.
As a side note, historically an EVM change did hurt businesses e.g. Gas tokens. However, those changes did come with benefits and interest from the community.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface Buyer {
function price() external view returns (uint);
}
contract Shop {
uint public price = 100;
bool private isSold;
function buy() public {
Buyer _buyer = Buyer(msg.sender);
if (_buyer.price() >= price && !isSold) {
isSold = true;
price = _buyer.price();
}
}
}
Here is a modified code from ethernaut.
The catch in this level is that originally the isSold field is public and therefore could be used by the Buyer contract to respond different prices in the two different calls.
Here it is private and still the attack could be possible. The merkle tree can be used to proove a storage but only the initial value of it.
With this instruction many attack vectors will be created.
This contract could query buyer only once, but still many other contracts already in the network would become vulnerable
The last thing we should do is shy away from giving developers options and increasing transparency of contracts because some businesses operating on-chain really on contract-to-contract privacy so they can set up paywalls. Seem antithetical to Ethereum.
Hey Renan but also @deluca-mike I think there is a misunderstanding here how Ethereum state actually works.
The “public” or “private” field markers are only architectural decorators inside Solidity, but in Ethereum all storage is always readable. Please have a look at the documentation and examples of the RPC call getStorageAtJSON-RPC API | ethereum.org
So in your example of price and isSold can be fetched using:
So in fact the keyword private is a false friend as many developers confuse this with meaning it’s not readable from the outside - when in fact anyone can read it using RPC calls - it is just inside Solidity where it’s impossible to access. This is a restriction in Solidity that you don’t have when writing e.g. a python script using RPC calls from the outside. This EIP-2330 is proposing the addition of EXTSLOAD so that this in-equality is fixed and you get the same powers inside Solidity that you have from the outside already.
I think that Renan suggested that making isSold private could prevent attacks during EVM execution. However, this might not be effective. Even if isSold is set to private, it’s possible to manipulate the process. An attacker could record the initial price() call and modify the response.
Hey Neburo, this would fail because the buyer.price function is marked as external, so the Shop contract would make an staticcall and would revert if it tryed to store something in storage