Ping @davesque & @simon-jentzsch with both of you I had a short chat in Osaka and I nearly forgot the details. But we discussed the idea for an EXTSLOAD instruction and corresponding Solidity ABI for the first time. Would be great if you guys could have a look at the first draft here provide and provide suggestions or comments for improvement.
To align with related opcodes, maybe a rename to extsload? (Like extbalance)
I don’t think the same gas price as sload makes sense, because sload assumes you have already paid the cost of loading the account from the state trie (via a call). It probably ought to be something like the sum of the gas cost of extbalance (load the account from the trie) and sload (load the slot from the storage trie).
Yeah, both makes sense. I really like the the name EXTLOAD or EXTSLOAD for this as well. I’m going to add this to the pull request. In fact I think EXTLOAD would be the cleanest. Any thought on keeping or dropping the S?
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.