contract GatekeeperOne {
address public entrant;
modifier gateOne() {
require(msg.sender != tx.origin);
_;
}
modifier gateTwo() {
require(msg.gas % 8191 == 0);
_;
}
modifier gateThree(bytes8 _gateKey) {
require(uint32(_gateKey) == uint16(_gateKey));
require(uint32(_gateKey) != uint64(_gateKey));
require(uint32(_gateKey) == uint16(tx.origin));
_;
}
function enter(bytes8 _gateKey) public gateOne gateTwo gateThree(_gateKey) returns (bool) {
entrant = tx.origin;
return true;
}
}
contract test{
GatekeeperOne public t;
function test()public payable{
t = GatekeeperOne(0x5c3c1540dfcd795b0aca58a496e3c30fe2405b07);
}
function attack()public payable{
t.call.gas(41171)(bytes4(keccak256("good(bytes8)")), 0x123);
}
function attack2()public payable{
t.enter(0x123);
}
function()public payable{}
}当我执行attack()时,它将是成功的。而attack2()将失败。错误信息:
对test.attack2错误的处理:
VM错误:还原。还原事务已恢复到初始状态。注意:如果您发送值,则应支付构造函数。调试事务以获得更多信息。
发布于 2018-09-19 20:29:39
正如smarx已经说过的,您正在调用两个不同的函数,因此它们的行为不同。
关于标题中的问题:
您可以从.call和.分别在4.4.4节(第68页)和4.4.5节(第70-71页)中深入了解坚实性文献和C2之间的差异。
.call
.call(bytes memory) returns (bool):在给定的有效载荷下发出低级别调用,失败时返回false,转发所有可用的气体,可调。
.function如果被调用的合同不存在(在帐户不包含代码的意义上),或者如果被调用的合同本身抛出异常或退出气体,则函数调用将导致异常。
因此,前者是低级别的,因为您必须手动检查返回值,而第二个级别则让异常泡沫上升(级别更高)。
https://ethereum.stackexchange.com/questions/59103
复制相似问题