[Ethereum] what are the diffrences between
.call and
.

blockchainevmremixsolidity

 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.

Best Answer

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).

Related Topic