My tests seem to indicate that it is trivailly easy to spoof an "only owner" modifier on a view or pure.
For example, this contract:
pragma solidity 0.8.6;
contract Test {
address private owner;
string private secret;
modifier onlyOwner() {
require(msg.sender==owner,"onlyOwner");
_;
}
constructor() {
owner = msg.sender;
secret="Abracadabra";
}
function setSecret(string memory newSecret) public onlyOwner {
secret = newSecret;
}
function getSecret() public view **onlyOwner** returns(string memory) {
return secret;
}
}
So if the design intention was that you could only get or set a secret (and I understand that "there are no secrets on the blockchain") if called by the "owner" address et int he contsructor, it doesn't appear that you can actually enforce that, because using ether.contract.connect(). can call a view function with a string of the account address instead of with a signer.
So if, in hardhat you execute something like this:
[signer0, signer1]= await ethers.getSigners();
let testFactory = await ethers.getContractFactory("Test");
let test = await testFactory.connect(signer1).deploy();
let signer1Address = signer1.address; //get string version of address
--> let secret1 = await test.connect(signer1Address).getSecret();
console.log(secret1); //"Abracadabra"
You get the expected secret even if all you have available is the account owner address, even you don't have the account in your wallet and dont have the keys.
So if that is the case, is there any way to really enforce any kind of require msg.sender==
condition reliably in a view or pure function?