From what I can see, it seems trivially easy to set message sender in a view function to whatever address you want for external calls through ethers.js via the 'connect' function.
For example, if you have a contract like this:
contract Test {
address public 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;
}
}
Even if you aren't the owner account, you could run
let owner = await con.owner();
let secret = con.connect(owner).getSecret()
And get no complaints from ethers. I know this would fail if you tried to run setSecret
but when there no transaction involved it looks like you don't need a real signer, just a contract address.
Is there some other to check if the msg.sender is actually an account, not just a string of the account address?
Sure it can be, it is not a 'hack', when you call view function you can overwrite msg.sender
And anyway 'secret' variable (even private) can be read by some tools, as any data on blockchain (even if you will not provide read function), it is not a security measure to make variable private..