3
 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{}

}

when I execute the attack() it will be sucessful. And attack2() will fail. the error message:

transact to test.attack2 errored:

VM error: revert. revert The transaction has been reverted to the initial state. Note: The constructor should be payable if you send value. Debug the transaction to get more information.

1
  • 3
    One calls a function called good and the other calls a function called enter... I'm not sure why they would do the same thing at all.
    – user19510
    Sep 19, 2018 at 18:55

1 Answer 1

3

As already said by smarx you are calling two different functions, therefore they behave differently.

About the question in the title:

You can get insight into the difference between <address>.call and <address>.<function> from the documentation of Solidity, in Section 4.4.4 (page 68) and in Section 4.4.5 (pages 70-71), respectively.

<address>.call

<address>.call(bytes memory) returns (bool): issue low-level CALL with the given payload, returns false on failure, forwards all available gas, adjustable

<address>.function

Function calls cause exceptions if the called contract does not exist (in the sense that the account does not contain code) or if the called contract itself throws an exception or goes out of gas

Conclusion

So the former is low-level in the sense that you have to check the return value manually, while the second let the exception bubble up (is more high-level).

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.