msg.value
is a member of the msg (message) object when sending (state transitioning) transactions on the Ethereum network.
msg.value
contains the amount of wei (ether / 1e18) sent in the transaction.
msg.data (bytes): complete calldata
msg.gas (uint): remaining gas - deprecated in version 0.4.21 and to be replaced by gasleft()
msg.sender (address): sender of the message (current call)
msg.sig (bytes4): first four bytes of the calldata (i.e. function identifier)
msg.value (uint): number of wei sent with the message
I often find I want a software client to be able to check but I also want a modifier for readability, so it often ends up like this:
modifier onlyIfAllowed() {
require(isAllowed(args));
_;
}
function isAllowed() public view returns(bool allowed) {
allowed = ...
}
function safer() public onlyIfAllowed ...
Of course, it would also be fine to do that in-line.
function inline() public {
require(isAllowed());
// carry on
Ultimately, it is a matter of personal preference. I find it more readable to go like this:
function tricky() public onlyOwner onlyIfAllowed onlySomethingElse { ...
... so the actual purpose of the function doesn't get mixed up with repetitive steps. It's more DRY, in my opinion. Not everyone agrees. The Vyper team, for example, consider modifiers an anti-feature that obscures important logic that they feel should be in-line.
Hope it helps.
Best Answer
Modifiers are compile-time source code roll-ups. Functions can be "modified" by including the named modifier in the function declaration.
The
_;
line is mandatory. It's a merge wildcard that indicates where "the rest" of the function should go. For example, as @oktapdia suggested,merges the function source with the
modifier
code at the_;
It is possible to place the
_;
at the beginning, in the middle or at the end of themodifier
code. In practice, especially until you understand it really well, I would suggest the safest usage pattern is to use modifiers for consistent validation checks and only use the pattern with_;
at the end. In other words, use modifiers to check some things up front and then carry on.You can use modifiers in conjunction with getter functions. Here is a contrived example to show how you might use them together to keep code organized while you make the state discoverable to clients and ensure potentially complex logic is consistently applied.
return true
are just placeholders for more meaningful results.The idea is clients, other contracts, and other internal functions can use the getter functions to fetch/check the individual concerns (if they want to). Functions that should be guarded by a certain combination of concerns can use the modifier so the logic of it all (and your intent) remains very clear to reviewers.
So, you can have several functions like above, and they may have some tricky steps. Hopefully, they can be understood as individual concerns. Then, when used in combination, you can reduce repetition and improve readability with a modifier.
In case it isn't clear, you could accomplish something quite similar if instead of a modifier you made a third function to work with the combination and then included a
require()
in each function that needs it.A function like:
Then use it like:
The security/validation concern is part of the function, and although this will work, it is arguably less readable than a modifier and the intent may be less clear.
Hope it helps.