in almost all erc20 contract "_transfer" and "transfer" there are two functions and "transfer" calls internal "_transfer" why? Is there any security benefit of it ? in another words I have seen this approach not only with this particular function but with many functions call is being un necessary forwarded to some internal separate function for example just for checking who is msg.sender like below
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
function isOwner() public view returns (bool) {
return _msgSender() == _owner;
}
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
why this modifier is extended to isOwner() and _msgSender()
why not the same check done inside modifier itself ? Is there any security angle behind it ?
Best Answer
Usually this is because of modular design. So the contract itself is meant to be used as-is without modifications but you should inherit from it and, if needed, modify functionality in that new contract.
So if you want to change the functionality of
_transfer
you override it in the inheriting contract and (probably) also call the inherited contract's_transfer
. In theory the same could be done for thetransfer
function but it's cleaner if there is only one entry point with the nametransfer
.The logic of
_msgSender
refers (at least in the case of OpenZeppelin) to Gas Station Network meta transactions (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/GSN/Context.sol). I'm not sure exactly how it is supposed to be used but I guess you'd simply inherit fromGSN
and implement the required functionality. If you simply usedmsg.sender
in your contracts there would be no way to modify that value based on conditions.