Adds support for the EVM version "Paris".

Deprecates `block.difficulty` and disallow `difficulty()` in inline assembly for EVM versions >= paris.
The change is due to the renaming introduced by EIP-4399 (see: https://eips.ethereum.org/EIPS/eip-4399).
Introduces `block.prevrandao` in Solidity and `prevrandao()` in inline assembly for EVM versions >= paris.

Co-authored-by: Alex Beregszaszi <alex@rtfs.hu>
Co-authored-by: Daniel <daniel@ekpyron.org>
Co-authored-by: matheusaaguiar <95899911+matheusaaguiar@users.noreply.github.com>
Co-authored-by: Nikola Matić <nikola.matic@ethereum.org>
This commit is contained in:
Rodrigo Q. Saramago
2023-01-23 18:50:36 +00:00
co-authored by Alex Beregszaszi Daniel matheusaaguiar Nikola Matić
parent d70d79af4a
commit ef6ff2f055
114 changed files with 842 additions and 221 deletions
+3 -3
View File
@@ -109,7 +109,7 @@ public:
bytes realCode = bytecodeSansMetadata(_bytecode);
BOOST_REQUIRE_MESSAGE(!realCode.empty(), "Invalid or missing metadata in bytecode.");
size_t instructions = 0;
evmasm::eachInstruction(realCode, [&](Instruction _instr, u256 const&) {
evmasm::eachInstruction(realCode, m_evmVersion, [&](Instruction _instr, u256 const&) {
if (!_which || *_which == _instr)
instructions++;
});
@@ -287,7 +287,7 @@ BOOST_AUTO_TEST_CASE(retain_information_in_branches)
bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "c", true);
size_t numSHA3s = 0;
eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) {
eachInstruction(optimizedBytecode, m_evmVersion, [&](Instruction _instr, u256 const&) {
if (_instr == Instruction::KECCAK256)
numSHA3s++;
});
@@ -330,7 +330,7 @@ BOOST_AUTO_TEST_CASE(store_tags_as_unions)
bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "test", true);
size_t numSHA3s = 0;
eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) {
eachInstruction(optimizedBytecode, m_evmVersion, [&](Instruction _instr, u256 const&) {
if (_instr == Instruction::KECCAK256)
numSHA3s++;
});
@@ -1860,6 +1860,7 @@ BOOST_AUTO_TEST_CASE(builtins)
block.chainid;
block.coinbase;
block.difficulty;
block.prevrandao;
block.gaslimit;
block.number;
block.timestamp;
@@ -0,0 +1,12 @@
contract C {
function f() public view returns (uint ret) {
assembly {
ret := difficulty()
}
}
}
// ====
// compileToEwasm: also
// EVMVersion: <paris
// ----
// f() -> 200000000
@@ -0,0 +1,12 @@
contract C {
function f() public view returns (uint ret) {
assembly {
ret := prevrandao()
}
}
}
// ====
// compileToEwasm: also
// EVMVersion: >=paris
// ----
// f() -> 0xa86c2e601b6c44eb4848f7d23d9df3113fbcac42041c49cbed5000cb4f118777
@@ -0,0 +1,10 @@
contract C {
function f() public view returns (uint) {
return block.prevrandao;
}
}
// ====
// compileToEwasm: also
// EVMVersion: >=paris
// ----
// f() -> 0xa86c2e601b6c44eb4848f7d23d9df3113fbcac42041c49cbed5000cb4f118777
@@ -0,0 +1,10 @@
contract C {
function f() public view returns (uint) {
return block.prevrandao;
}
}
// ====
// compileToEwasm: also
// EVMVersion: <paris
// ----
// f() -> 200000000
@@ -0,0 +1,14 @@
contract C {
function f() public view returns (uint256) {
return block.difficulty;
}
function g() public view returns (uint256 ret) {
assembly {
ret := difficulty()
}
}
}
// ====
// EVMVersion: <paris
// ----
@@ -0,0 +1,21 @@
contract C {
function f() public view returns (uint256 ret) {
assembly {
let difficulty := sload(0)
ret := difficulty
}
}
function g() public pure returns (uint256 ret) {
assembly {
function difficulty() -> r {
r := 1000
}
ret := difficulty()
}
}
}
// ====
// EVMVersion: <paris
// ----
// ParserError 5568: (101-111): Cannot use builtin function name "difficulty" as identifier name.
@@ -0,0 +1,9 @@
contract C {
function f() public view returns (uint256) {
return block.difficulty;
}
}
// ====
// EVMVersion: >=paris
// ----
// Warning 8417: (77-93): Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain.
@@ -0,0 +1,12 @@
contract C {
function f() public {
assembly {
pop(difficulty())
}
}
}
// ====
// EVMVersion: >=paris
// ----
// DeclarationError 4619: (74-84): Function "difficulty" not found.
// TypeError 3950: (74-86): Expected expression to evaluate to one value, but got 0 values instead.
@@ -0,0 +1,22 @@
contract C {
function f() public view returns (uint256 ret) {
assembly {
let difficulty := sload(0)
ret := difficulty
}
}
function g() public pure returns (uint256 ret) {
assembly {
function difficulty() -> r {
r := 1000
}
ret := difficulty()
}
}
}
// ====
// EVMVersion: >=paris
// ----
// DeclarationError 5017: (101-111): The identifier "difficulty" is reserved and can not be used.
// DeclarationError 5017: (255-323): The identifier "difficulty" is reserved and can not be used.
@@ -0,0 +1,20 @@
contract C {
function f() public view returns (uint256 ret) {
assembly {
let prevrandao := sload(0)
ret := prevrandao
}
}
function g() public pure returns (uint256 ret) {
assembly {
function prevrandao() -> r {
r := 1000
}
ret := prevrandao()
}
}
}
// ====
// EVMVersion: <paris
// ----
@@ -0,0 +1,14 @@
contract C {
function f() public view returns (uint256) {
return block.prevrandao;
}
function g() public view returns (uint256 ret) {
assembly {
ret := prevrandao()
}
}
}
// ====
// EVMVersion: >=paris
// ----
@@ -0,0 +1,21 @@
contract C {
function f() public view returns (uint256 ret) {
assembly {
let prevrandao := sload(0)
ret := prevrandao
}
}
function g() public pure returns (uint256 ret) {
assembly {
function prevrandao() -> r {
r := 1000
}
ret := prevrandao()
}
}
}
// ====
// EVMVersion: >=paris
// ----
// ParserError 5568: (101-111): Cannot use builtin function name "prevrandao" as identifier name.
@@ -0,0 +1,9 @@
contract C {
function f() public view returns (uint256) {
return block.prevrandao;
}
}
// ====
// EVMVersion: <paris
// ----
// Warning 9432: (77-93): "prevrandao" is not supported by the VM version and will be treated as "difficulty".
@@ -0,0 +1,12 @@
contract C {
function f() public {
assembly {
pop(prevrandao())
}
}
}
// ====
// EVMVersion: <paris
// ----
// DeclarationError 4619: (74-84): Function "prevrandao" not found.
// TypeError 3950: (74-86): Expected expression to evaluate to one value, but got 0 values instead.
@@ -8,6 +8,6 @@ contract C {
}
}
// ====
// EVMVersion: <byzantium
// EVMVersion: =homestead
// ----
// TypeError 9908: (73-106): This catch clause type cannot be used on the selected EVM version (homestead). You need at least a Byzantium-compatible EVM or use `catch { ... }`.
@@ -0,0 +1,13 @@
contract C {
function f() public {
try this.f() {
} catch (bytes memory) {
}
}
}
// ====
// EVMVersion: =spuriousDragon
// ----
// TypeError 9908: (73-106): This catch clause type cannot be used on the selected EVM version (spuriousDragon). You need at least a Byzantium-compatible EVM or use `catch { ... }`.
@@ -0,0 +1,13 @@
contract C {
function f() public {
try this.f() {
} catch (bytes memory) {
}
}
}
// ====
// EVMVersion: =tangerineWhistle
// ----
// TypeError 9908: (73-106): This catch clause type cannot be used on the selected EVM version (tangerineWhistle). You need at least a Byzantium-compatible EVM or use `catch { ... }`.
@@ -8,6 +8,6 @@ contract C {
}
}
// ====
// EVMVersion: <byzantium
// EVMVersion: =homestead
// ----
// TypeError 1812: (73-112): This catch clause type cannot be used on the selected EVM version (homestead). You need at least a Byzantium-compatible EVM or use `catch { ... }`.
@@ -0,0 +1,13 @@
contract C {
function f() public {
try this.f() {
} catch Error(string memory) {
}
}
}
// ====
// EVMVersion: =spuriousDragon
// ----
// TypeError 1812: (73-112): This catch clause type cannot be used on the selected EVM version (spuriousDragon). You need at least a Byzantium-compatible EVM or use `catch { ... }`.
@@ -0,0 +1,13 @@
contract C {
function f() public {
try this.f() {
} catch Error(string memory) {
}
}
}
// ====
// EVMVersion: =tangerineWhistle
// ----
// TypeError 1812: (73-112): This catch clause type cannot be used on the selected EVM version (tangerineWhistle). You need at least a Byzantium-compatible EVM or use `catch { ... }`.
@@ -3,15 +3,12 @@ contract C {
return block.coinbase;
}
function g() public view returns (uint) {
return block.difficulty;
}
function h() public view returns (uint) {
return block.gaslimit;
}
function i() public view returns (uint) {
function h() public view returns (uint) {
return block.timestamp;
}
function j() public view returns (uint) {
function i() public view returns (uint) {
return block.chainid;
}
}
@@ -0,0 +1,13 @@
contract C {
function f() public view returns (uint) {
return block.prevrandao;
}
function g() public view returns (uint ret) {
assembly {
ret := prevrandao()
}
}
}
// ====
// EVMVersion: >=paris
// ----
@@ -73,7 +73,7 @@ contract C {
pop(coinbase())
pop(timestamp())
pop(number())
pop(difficulty())
pop(prevrandao())
pop(gaslimit())
// NOTE: msize() is allowed only with optimizer disabled
@@ -83,7 +83,7 @@ contract C {
}
}
// ====
// EVMVersion: >=london
// EVMVersion: >=paris
// ----
// Warning 5740: (89-1716): Unreachable code.
// Warning 5740: (1729-1741): Unreachable code.
@@ -0,0 +1,11 @@
contract C {
function f() public {
assembly {
pop(difficulty())
}
}
}
// ====
// EVMVersion: <=london
// ----
// Warning 2018: (17-103): Function state mutability can be restricted to view
@@ -73,7 +73,6 @@ contract C {
//pop(coinbase())
//pop(timestamp())
//pop(number())
//pop(difficulty())
//pop(gaslimit())
// NOTE: msize() is allowed only with optimizer disabled
@@ -73,7 +73,7 @@ contract C {
pop(coinbase())
pop(timestamp())
pop(number())
pop(difficulty())
pop(prevrandao())
pop(gaslimit())
// NOTE: msize() is allowed only with optimizer disabled
@@ -83,7 +83,7 @@ contract C {
}
}
// ====
// EVMVersion: >=london
// EVMVersion: >=paris
// ----
// Warning 5740: (94-1733): Unreachable code.
// Warning 5740: (1746-1758): Unreachable code.
@@ -0,0 +1,10 @@
contract C {
function f() public view {
assembly {
pop(difficulty())
}
}
}
// ====
// EVMVersion: <=london
// ----
@@ -6,33 +6,26 @@ contract C {
pop(gas())
pop(address())
pop(balance(0))
pop(selfbalance())
pop(caller())
pop(callvalue())
pop(extcodesize(0))
extcodecopy(0, 1, 2, 3)
pop(extcodehash(0))
pop(create(0, 1, 2))
pop(create2(0, 1, 2, 3))
pop(call(0, 1, 2, 3, 4, 5, 6))
pop(callcode(0, 1, 2, 3, 4, 5, 6))
pop(delegatecall(0, 1, 2, 3, 4, 5))
pop(staticcall(0, 1, 2, 3, 4, 5))
selfdestruct(0)
log0(0, 1)
log1(0, 1, 2)
log2(0, 1, 2, 3)
log3(0, 1, 2, 3, 4)
log4(0, 1, 2, 3, 4, 5)
pop(chainid())
pop(basefee())
pop(origin())
pop(gasprice())
pop(blockhash(0))
pop(coinbase())
pop(timestamp())
pop(number())
pop(difficulty())
pop(gaslimit())
// These two are disallowed too but the error suppresses other errors.
@@ -41,40 +34,31 @@ contract C {
}
}
}
// ====
// EVMVersion: >=london
// ----
// Warning 5740: (672-1083): Unreachable code.
// Warning 5740: (526-853): Unreachable code.
// TypeError 2527: (79-87): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 8961: (101-113): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 2527: (130-135): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (153-162): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (180-190): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (208-221): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (239-247): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (265-276): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (294-308): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (322-345): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (362-376): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 8961: (394-409): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (427-446): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (464-489): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (507-536): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (554-584): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 2527: (602-630): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 8961: (644-659): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (672-682): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (695-708): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (721-737): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (750-769): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (782-804): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 2527: (821-830): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (848-857): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (875-883): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (901-911): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (929-941): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (959-969): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (987-998): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (1016-1024): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (1042-1054): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (1072-1082): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (208-216): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (234-245): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (263-277): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (291-314): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 8961: (331-346): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (364-389): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (407-436): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (454-484): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (498-513): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (526-536): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (549-562): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (575-591): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (604-623): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (636-658): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 2527: (675-683): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (701-711): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (729-741): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (759-769): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (787-798): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (816-824): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (842-852): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
@@ -0,0 +1,11 @@
contract C {
function f() public pure {
assembly {
pop(staticcall(0, 1, 2, 3, 4, 5))
}
}
}
// ====
// EVMVersion: >=byzantium
// ----
// TypeError 2527: (79-107): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
@@ -0,0 +1,13 @@
contract C {
function f() public pure {
assembly {
pop(extcodehash(0))
pop(create2(0, 1, 2, 3))
}
}
}
// ====
// EVMVersion: >=constantinople
// ----
// TypeError 2527: (79-93): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 8961: (111-130): Function cannot be declared as pure because this expression (potentially) modifies the state.
@@ -0,0 +1,13 @@
contract C {
function f() public pure {
assembly {
pop(selfbalance())
pop(chainid())
}
}
}
// ====
// EVMVersion: >=istanbul
// ----
// TypeError 2527: (79-92): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (110-119): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
@@ -0,0 +1,11 @@
contract C {
function f() public pure {
assembly {
pop(basefee())
}
}
}
// ====
// EVMVersion: >=london
// ----
// TypeError 2527: (79-88): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
@@ -0,0 +1,11 @@
contract C {
function f() public pure {
assembly {
pop(prevrandao())
}
}
}
// ====
// EVMVersion: >=paris
// ----
// TypeError 2527: (79-91): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
@@ -0,0 +1,11 @@
contract C {
function f() public pure {
assembly {
pop(difficulty())
}
}
}
// ====
// EVMVersion: <=london
// ----
// TypeError 2527: (79-91): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".