The contract has to call one of its own functions and the message has to come from the outside. In that case, the msg.sender
will indeed be itself.
pragma solidity 0.7.6;
interface IRecursive {
function isMe() external view returns(bool);
}
contract Recursive is IRecursive {
function isMe() external view override returns(bool) {
if(msg.sender == address(this)) return true;
return false;
}
function tryThis() external view returns(bool) {
return IRecursive(address(this)).isMe(); // we (this) are msg.sender to the receiver
}
}
When tryThis()
uses the interface to make a call to the instance at its own address the call arrives from the outside and msg.sender
is the address that called isMe()
which just happens to be the same contract.
In some use-cases, it can be handy to elevate the contract itself to an equal footing with other users. However, keep in mind the gas trade-off in using external calls to self from the contract, since it adds close to 1000 gas units (980 in this case) to the call cost.
Hope it helps.