Я часто вижу _
в модификаторах
modifier onlyOwner() {
if (msg.sender != owner) throw;
_
}
Выполняет ли он какой-либо код или предназначен для облегчения чтения кода?
Начиная с Solidity версии 0.4.0+, теперь вам нужно добавить точку с запятой после _
. См. Solidity — версия 0.4.0 :
- Изменить
_
на_;
в модификаторах.
Приведенные ниже тесты работают только в Solidity < v 0.4.0.
_
в модификаторе стоит ._
s в код модификатора. А код модифицируемой функции вставляется в каждое место, где _
он находится в модификаторе. См modifier checkThree
. . Это может быть предотвращено более поздними версиями solc
компилятора.checkOne checkTwo checkThree
), а в конце функции они вызываются в обратном порядке. Модификаторы, кажется, применяются как стек. Во всяком случае, в этом примере.Из Solidity Features - Модификаторы функций :
Модификаторы PT можно использовать для простого изменения поведения функций, например, для автоматической проверки условия перед выполнением функции. Они являются наследуемыми свойствами контрактов и могут быть переопределены производными контрактами.
contract owned { function owned() { owner = msg.sender; } address owner; // This contract only defines a modifier but does not use it - it will // be used in derived contracts. // The function body is inserted where the special symbol "_" in the // definition of a modifier appears. modifier onlyowner { if (msg.sender == owner) _ } }
Вот пример с EtherScan.io — The DAO — Source Code .
Модификатор onlyTokenholders
ограничивает выполнение «модифицированных» функций лицами, не являющимися владельцами токенов.
modifier onlyTokenholders {
if (balanceOf(msg.sender) == 0) throw;
_
}
Вот vote(...)
функция с onlyTokenHolders
модификатором:
function vote(
uint _proposalID,
bool _supportsProposal
) onlyTokenholders noEther returns (uint _voteID) {
Proposal p = proposals[_proposalID];
if (p.votedYes[msg.sender]
|| p.votedNo[msg.sender]
|| now >= p.votingDeadline) {
throw;
}
Код внутри vote(...)
функции выполняется только в том случае, если проверка модификатора не выдает ошибку из оператора if (balanceOf(msg.sender) == 0) throw;
. Представляет _
тело vote(...)
функции.
Из Learn X in Y минут — где X=Solidity , вот пример, где _
нет в конце функции модификатора:
// underscore can be included before end of body,
// but explicitly returning will skip, so use carefully
modifier checkValue(uint amount) {
_
if (msg.value > amount) {
msg.sender.send(amount - msg.value);
}
}
Вот код для тестирования _
:
contract TestModifier {
string[] public messages;
uint256 testVariable;
function numberOfMessages() constant returns (uint256) {
return messages.length;
}
modifier checkOne {
messages.push("checkOne - 1");
if (testVariable == 123)
throw;
_
messages.push("checkOne - 2");
if (testVariable == 123)
throw;
}
modifier checkTwo {
messages.push("checkTwo - 1");
if (testVariable == 123)
throw;
_
messages.push("checkTwo - 2");
if (testVariable == 123)
throw;
}
modifier checkThree {
messages.push("checkThree - 1");
if (testVariable == 123)
throw;
_
messages.push("checkThree - 2");
if (testVariable == 123)
throw;
_
messages.push("checkThree - 3");
if (testVariable == 123)
throw;
}
function test() checkOne checkTwo checkThree returns (uint256) {
messages.push("test - 1");
testVariable = 345;
messages.push("test - 2");
return testVariable;
}
}
Сгладил код
> var testModifierSource='contract TestModifier { string[] public messages; uint256 testVariable; function numberOfMessages() constant returns (uint256) { return messages.length; } modifier checkOne { messages.push("checkOne - 1"); if (testVariable == 123) throw; _ messages.push("checkOne - 2"); if (testVariable == 123) throw; } modifier checkTwo { messages.push("checkTwo - 1"); if (testVariable == 123) throw; _ messages.push("checkTwo - 2"); if (testVariable == 123) throw; } modifier checkThree { messages.push("checkThree - 1"); if (testVariable == 123) throw; _ messages.push("checkThree - 2"); if (testVariable == 123) throw; _ messages.push("checkThree - 3"); if (testVariable == 123) throw; } function test() checkOne checkTwo checkThree returns (uint256) { messages.push("test - 1"); testVariable = 345; messages.push("test - 2"); return testVariable; }}'
undefined
Вставил контракт в блокчейн:
> var testModifierCompiled = web3.eth.compile.solidity(testModifierSource);
undefined
> var testModifierContract = web3.eth.contract(testModifierCompiled.TestModifier.info.abiDefinition);
var testModifier = testModifierContract.new({
from:web3.eth.accounts[0],
data: testModifierCompiled.TestModifier.code, gas: 1000000},
function(e, contract) {
if (!e) {
if (!contract.address) {
console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined...");
} else {
console.log("Contract mined! Address: " + contract.address);
console.log(contract);
}
}
})
...
Contract mined! Address: 0xd2ca2d34da6e50d28407f78ded3a07962b56181c
[object Object]
Отправлена транзакция для вызова test()
функции:
> testModifier.test(eth.accounts[0], {
from:web3.eth.accounts[0],
data: testModifierCompiled.TestModifier.code,
gas: 1000000
});
Проверил результаты:
> var i;
> for (i = 0; i < testModifier.numberOfMessages(); i++) {
console.log(testModifier.messages(i));
}
checkOne - 1
checkTwo - 1
checkThree - 1
test - 1
test - 2
test()
:Я удалил оператор возврата, поэтому исходный код test
:
function test() checkOne checkTwo checkThree returns (uint256) {
messages.push("test - 1");
testVariable = 345;
messages.push("test - 2");
// return testVariable;
}
И повторно запустил тест, чтобы получить следующие результаты:
var i;
undefined
> for (i = 0; i < testModifier.numberOfMessages(); i++) {
.. console.log(testModifier.messages(i));
.. }
checkOne - 1
checkTwo - 1
checkThree - 1
test - 1
test - 2
checkThree - 2
test - 1
test - 2
checkThree - 3
checkTwo - 2
checkOne - 2
undefined
дор
Николя Массар
конфиденциальностьisahumanright.eth
@oIG
, некоторые интересные результаты испытаний.@Nicolas Massart
, как модификатор работает в Swift?Телепортирующаяся коза
{action 1; _; action2;}
, при вызове он выполнит действие 1, затем функцию, затем действие 2. Если вы его не укажете, я предполагаю, что подчеркивание неявно помещается в конец модификатора.Телепортирующаяся коза
Джейнти Канани
modifier
какdecorator
в питоне.Дипанкар
ВауБоу
Максарео
Андерсон