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{}
}
Wenn ich den Angriff () ausführe , wird es erfolgreich sein. Und attack2() wird fehlschlagen. die Fehlermeldung:
Transaktion zu test.attack2
Fehler:
VM-Fehler: Zurücksetzen. revert Die Transaktion wurde in den Ausgangszustand zurückgesetzt. Hinweis: Der Konstruktor sollte zahlbar sein, wenn Sie einen Wert senden. Debuggen Sie die Transaktion, um weitere Informationen zu erhalten.
Wie bereits von smarx gesagt, rufen Sie zwei verschiedene Funktionen auf, daher verhalten sie sich unterschiedlich.
Zu der Frage im Titel:
Einen Einblick in den Unterschied zwischen <address>.call
und <address>.<function>
aus der Dokumentation von Solidity erhalten Sie in Abschnitt 4.4.4 (Seite 68) bzw. in Abschnitt 4.4.5 (Seiten 70-71).
<address>.call
<address>.call(bytes memory) returns (bool)
: Low-Level-CALL mit der gegebenen Nutzlast ausgeben, bei Fehler falsch zurückgeben, alles verfügbare Gas weiterleiten, einstellbar
<address>.function
Funktionsaufrufe verursachen Ausnahmen, wenn der aufgerufene Vertrag nicht existiert (in dem Sinne, dass das Konto keinen Code enthält) oder wenn der aufgerufene Vertrag selbst eine Ausnahme auslöst oder das Gas ausgeht
Ersteres ist also Low-Level in dem Sinne, dass Sie den Rückgabewert manuell überprüfen müssen, während das Zweite die Ausnahme sprudeln lässt (höher ist).
Benutzer19510
good
und der andere ruft eine Funktion namens aufenter
... Ich bin mir nicht sicher, warum sie überhaupt dasselbe tun würden.