Catch panic.

This commit is contained in:
chriseth
2020-12-22 11:08:44 +01:00
parent b78443ac75
commit b965446182
21 changed files with 619 additions and 80 deletions
@@ -0,0 +1,89 @@
contract C {
function f(uint size) public pure {
assembly {
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
mstore(4, 0x20)
mstore(0x24, 7)
mstore(0x44, "abcdefg")
revert(0, size)
}
}
function a() public returns (uint) {
try this.f(3) {
assert(false);
} catch Panic(uint) {
assert(false);
} catch Error(string memory) {
assert(false);
} catch {
assert(true);
}
}
function b() public returns (uint) {
try this.f(6) {
assert(false);
} catch Panic(uint) {
assert(false);
} catch Error(string memory) {
assert(false);
} catch {
assert(true);
}
}
function b2() public returns (uint) {
try this.f(0x43) {
assert(false);
} catch Panic(uint) {
assert(false);
} catch Error(string memory) {
assert(false);
} catch {
assert(true);
}
}
function b3() public returns (string memory) {
try this.f(0x4a) {
assert(false);
} catch Panic(uint) {
assert(false);
} catch Error(string memory) {
assert(false);
} catch {
assert(true);
}
}
function c() public returns (string memory) {
try this.f(0x4b) {
assert(false);
} catch Panic(uint) {
assert(false);
} catch Error(string memory er) {
assert(true);
return er;
} catch {
assert(false);
}
}
function d() public returns (string memory) {
try this.f(0x100) {
assert(false);
} catch Panic(uint) {
assert(false);
} catch Error(string memory er) {
assert(true);
return er;
} catch {
assert(false);
}
}
}
// ====
// EVMVersion: >=byzantium
// compileViaYul: also
// ----
// a() -> 0x00
// b() -> 0x00
// b2() -> 0x00
// b3() -> 0x20, 0x00
// c() -> 0x20, 7, "abcdefg"
// d() -> 0x20, 7, "abcdefg"
@@ -0,0 +1,55 @@
contract C {
function f(uint size) public pure {
assembly {
mstore(0, 0x4e487b7100000000000000000000000000000000000000000000000000000000)
mstore(4, 0x43)
revert(0, size)
}
}
function a() public returns (uint) {
try this.f(3) {
assert(false);
} catch Panic(uint) {
assert(false);
} catch {
assert(true);
}
}
function b() public returns (uint) {
try this.f(6) {
assert(false);
} catch Panic(uint) {
assert(false);
} catch {
assert(true);
}
}
function c() public returns (uint) {
try this.f(0x24) {
assert(false);
} catch Panic(uint c) {
assert(true);
return c;
} catch {
assert(false);
}
}
function d() public returns (uint) {
try this.f(0x100) {
assert(false);
} catch Panic(uint c) {
assert(true);
return c;
} catch {
assert(false);
}
}
}
// ====
// EVMVersion: >=byzantium
// compileViaYul: also
// ----
// a() -> 0x00
// b() -> 0x00
// c() -> 0x43
// d() -> 0x43
@@ -0,0 +1,53 @@
contract C {
function f(uint size) public pure {
assembly {
mstore(0, 0x4e487b7100000000000000000000000000000000000000000000000000000000)
mstore(4, 0x43)
revert(0, size)
}
}
function a() public returns (uint) {
try this.f(3) {
assert(false);
} catch Panic(uint) {
assert(false);
}
// Error will be re-thrown, since there is no low-level catch clause
assert(false);
}
function b() public returns (uint) {
try this.f(6) {
assert(false);
} catch Panic(uint) {
assert(false);
}
// Error will be re-thrown, since there is no low-level catch clause
assert(false);
}
function c() public returns (uint) {
try this.f(0x24) {
assert(false);
} catch Panic(uint c) {
assert(true);
return c;
}
assert(false);
}
function d() public returns (uint) {
try this.f(0x100) {
assert(false);
} catch Panic(uint c) {
assert(true);
return c;
}
assert(false);
}
}
// ====
// EVMVersion: >=byzantium
// compileViaYul: also
// ----
// a() -> FAILURE, hex"4e487b"
// b() -> FAILURE, hex"4e487b710000"
// c() -> 0x43
// d() -> 0x43
@@ -0,0 +1,59 @@
contract C {
function f(uint size) public pure {
assembly {
mstore(0, 0x4e487b7100000000000000000000000000000000000000000000000000000000)
mstore(4, 0x43)
revert(0, size)
}
}
function a() public returns (uint) {
try this.f(3) {
assert(false);
} catch Panic(uint) {
assert(false);
} catch Error(string memory) {
assert(false);
}
// Error will be re-thrown, since there is no low-level catch clause
assert(false);
}
function b() public returns (uint) {
try this.f(6) {
assert(false);
} catch Panic(uint) {
assert(false);
} catch Error(string memory) {
assert(false);
}
// Error will be re-thrown, since there is no low-level catch clause
assert(false);
}
function c() public returns (uint) {
try this.f(0x24) {
assert(false);
} catch Panic(uint c) {
assert(true);
return c;
} catch Error(string memory) {
assert(false);
}
}
function d() public returns (uint) {
try this.f(0x100) {
assert(false);
} catch Panic(uint c) {
assert(true);
return c;
} catch Error(string memory) {
assert(false);
}
}
}
// ====
// EVMVersion: >=byzantium
// compileViaYul: also
// ----
// a() -> FAILURE, hex"4e487b"
// b() -> FAILURE, hex"4e487b710000"
// c() -> 0x43
// d() -> 0x43
@@ -0,0 +1,62 @@
contract C {
function f(uint size) public pure {
assembly {
mstore(0, 0x4e487b7100000000000000000000000000000000000000000000000000000000)
mstore(4, 0x43)
revert(0, size)
}
}
function a() public returns (uint) {
try this.f(3) {
assert(false);
} catch Panic(uint) {
assert(false);
} catch Error(string memory) {
assert(false);
} catch {
assert(true);
}
}
function b() public returns (uint) {
try this.f(6) {
assert(false);
} catch Panic(uint) {
assert(false);
} catch Error(string memory) {
assert(false);
} catch {
assert(true);
}
}
function c() public returns (uint) {
try this.f(0x24) {
assert(false);
} catch Panic(uint c) {
assert(true);
return c;
} catch Error(string memory) {
assert(false);
} catch {
assert(false);
}
}
function d() public returns (uint) {
try this.f(0x100) {
assert(false);
} catch Panic(uint c) {
assert(true);
return c;
} catch Error(string memory) {
assert(false);
} catch {
assert(false);
}
}
}
// ====
// EVMVersion: >=byzantium
// compileViaYul: also
// ----
// a() -> 0x00
// b() -> 0x00
// c() -> 0x43
@@ -0,0 +1,34 @@
contract C {
function uf(bool b, uint x, uint y) public pure returns (uint) {
require(b, "failure");
return x - y;
}
function onlyPanic(bool b, uint x, uint y) public returns (uint r, uint code) {
try this.uf(b, x, y) returns (uint b) {
r = b;
} catch Panic(uint c) {
code = c;
}
}
function panicAndError(bool b, uint x, uint y) public returns (uint r, uint code, string memory msg_) {
try this.uf(b, x, y) returns (uint b) {
r = b;
} catch Panic(uint c) {
code = c;
} catch Error(string memory _errmsg) {
msg_ = _errmsg;
}
}
}
// ====
// EVMVersion: >=byzantium
// compileViaYul: also
// ----
// onlyPanic(bool,uint256,uint256): true, 7, 6 -> 1, 0x00
// onlyPanic(bool,uint256,uint256): true, 6, 7 -> 0x00, 0x11
// onlyPanic(bool,uint256,uint256): false, 7, 6 -> FAILURE, hex"08c379a0", 0x20, 7, "failure"
// onlyPanic(bool,uint256,uint256): false, 6, 7 -> FAILURE, hex"08c379a0", 0x20, 7, "failure"
// panicAndError(bool,uint256,uint256): true, 7, 6 -> 1, 0x00, 0x60, 0x00
// panicAndError(bool,uint256,uint256): true, 6, 7 -> 0x00, 0x11, 0x60, 0x00
// panicAndError(bool,uint256,uint256): false, 7, 6 -> 0x00, 0x00, 0x60, 7, "failure"
// panicAndError(bool,uint256,uint256): false, 6, 7 -> 0x00, 0x00, 0x60, 7, "failure"
@@ -0,0 +1,13 @@
contract C {
function f() public {
try this.f() {
} catch Panic(bytes memory) {
} catch Panic(uint) {
}
}
}
// ====
// EVMVersion: >=byzantium
// ----
// TypeError 1271: (72-109): Expected `catch Panic(uint ...) { ... }`.
// TypeError 6732: (110-139): This try statement already has a "Panic" catch clause.
@@ -0,0 +1,12 @@
contract C {
function f() public {
try this.f() {
} catch Panic(uint) {
} catch Panic(uint) {
}
}
}
// ====
// EVMVersion: >=byzantium
// ----
// TypeError 6732: (102-131): This try statement already has a "Panic" catch clause.
@@ -0,0 +1,11 @@
contract C {
function f() public {
try this.f() {
} catch Error(string memory) {
} catch Panic(uint) {
}
}
}
// ====
// EVMVersion: >=byzantium
// ----
@@ -7,5 +7,5 @@ contract C {
}
}
// ----
// TypeError 3542: (93-119): Invalid catch clause name. Expected either `catch (...)` or `catch Error(...)`.
// TypeError 3542: (120-143): Invalid catch clause name. Expected either `catch (...)` or `catch Error(...)`.
// TypeError 3542: (93-119): Invalid catch clause name. Expected either `catch (...)`, `catch Error(...)`, or `catch Panic(...)`.
// TypeError 3542: (120-143): Invalid catch clause name. Expected either `catch (...)`, `catch Error(...)`, or `catch Panic(...)`.
@@ -0,0 +1,11 @@
contract C {
function f() public {
try this.f() {
} catch Panic() {
}
}
}
// ====
// EVMVersion: >=byzantium
// ----
// TypeError 1271: (72-97): Expected `catch Panic(uint ...) { ... }`.
@@ -0,0 +1,11 @@
contract C {
function f() public {
try this.f() {
} catch Panic(bytes memory) {
}
}
}
// ====
// EVMVersion: >=byzantium
// ----
// TypeError 1271: (72-109): Expected `catch Panic(uint ...) { ... }`.