Inside _transfer function there is a call goes to _beforeTokenTransfer(sender, recipient, amount);
and that function is written as function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
with no body parts, then is is not useless ? or if it is useful what is purpose of calling a body less inter virtual function ?
3 Answers
Functionally, yes, it is useless since it doesn't do anything. But it does serve a purpose.
OpenZeppelin's architecture is such that you can easily plug in extra functionality. You are never meant to edit their templates, but only extend them. So, if you want to add your custom functionality to function _beforeTokenTransfer
, you can override the function in a sub-contract and add whatever functionality you need. This way there's no need to modify the original OZ contract.
For example a contract:
contract MyToken is ERC20 {
constructor(uint initialSupply, string memory name, string memory symbol)
ERC20(name, symbol) public {
_mint(msg.sender, initialSupply);
}
function _beforeTokenTransfer(address from, address to, uint256 amount)
internal override {
// do something, for example emit an event or check some conditions to make sure the transfer can be allowed. If not allowed, revert the transaction
}
}
-
Can you give an example which demonstrates how extra functionality can be added to it ?– ashwinMar 12, 2021 at 8:24
-
1
-
1@ashwin Example of added functionality: Let's say I have a map of blacklisted accounts that shouldn't receive tokens, I would verify if the receiver address is on that blacklist inside _beforeTokenTransfer()– SkyNov 25, 2022 at 12:24
Sometimes, in order to extend a parent contract you will need to override multiple related functions, which leads to code duplication and increased likelihood of bugs. For example, consider implementing safe ERC20 transfers in the style of IERC721Receiver. You may think overriding transfer and transferFrom would be enough, but what about _transfer and _mint? To prevent you from having to deal with these details, we introduced hooks.
Hooks allow you lots of flexibility in modifying the behaviour of a token by allowing you to execute functionality, in the case of the _beforeTokenTransfer hook, you can execute functionality before the token is transferred.
You will find Hook details Here
You will find some more information Here
Well, burn, mint and transfer are simply transfer functions and this hook can be used for some checking in any kind of transfer. For example maybe you don't want user to send tokens to specific address, because of something, then you can implement that logic in this hook and it will be triggered in any transfer function. For example I don't want user to send their tokens to any other address than address 0. Just because they're useless outside my ecosystem. It's only your fantasy if you want to do some logic before or after token transfer or not. so its upto you , what functionality are you adding there .