mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
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:
co-authored by
Alex Beregszaszi
Daniel
matheusaaguiar
Nikola Matić
parent
d70d79af4a
commit
ef6ff2f055
@@ -0,0 +1 @@
|
||||
--no-cbor-metadata --via-ir --optimize --opcodes --asm --debug-info none --evm-version paris
|
||||
@@ -0,0 +1,5 @@
|
||||
Warning: Since the VM version paris, "difficulty" was replaced by "prevrandao", which now returns a random number based on the beacon chain.
|
||||
--> evmasm_difficulty_post_paris/input.sol:6:21:
|
||||
|
|
||||
6 | uint256 x = block.difficulty;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@@ -0,0 +1,18 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
pragma solidity >=0.0.0;
|
||||
|
||||
contract C {
|
||||
constructor() payable {
|
||||
uint256 x = block.difficulty;
|
||||
assembly {
|
||||
sstore(0, x)
|
||||
stop()
|
||||
}
|
||||
}
|
||||
|
||||
fallback() external payable {
|
||||
assembly {
|
||||
stop()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
======= evmasm_difficulty_post_paris/input.sol:C =======
|
||||
EVM assembly:
|
||||
sstore(0x00, prevrandao)
|
||||
stop
|
||||
stop
|
||||
|
||||
sub_0: assembly {
|
||||
stop
|
||||
}
|
||||
|
||||
Opcodes:
|
||||
PREVRANDAO PUSH1 0x0 SSTORE STOP INVALID
|
||||
@@ -0,0 +1 @@
|
||||
--no-cbor-metadata --via-ir --optimize --opcodes --asm --debug-info none --evm-version london
|
||||
@@ -0,0 +1,18 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
pragma solidity >=0.0.0;
|
||||
|
||||
contract C {
|
||||
constructor() payable {
|
||||
uint256 x = block.difficulty;
|
||||
assembly {
|
||||
sstore(0, x)
|
||||
stop()
|
||||
}
|
||||
}
|
||||
|
||||
fallback() external payable {
|
||||
assembly {
|
||||
stop()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
======= evmasm_difficulty_pre_paris/input.sol:C =======
|
||||
EVM assembly:
|
||||
sstore(0x00, difficulty)
|
||||
stop
|
||||
stop
|
||||
|
||||
sub_0: assembly {
|
||||
stop
|
||||
}
|
||||
|
||||
Opcodes:
|
||||
DIFFICULTY PUSH1 0x0 SSTORE STOP INVALID
|
||||
@@ -0,0 +1 @@
|
||||
--no-cbor-metadata --via-ir --optimize --opcodes --asm --debug-info none --evm-version paris
|
||||
@@ -0,0 +1,18 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
pragma solidity >=0.0.0;
|
||||
|
||||
contract C {
|
||||
constructor() payable {
|
||||
uint256 x = block.prevrandao;
|
||||
assembly {
|
||||
sstore(0, x)
|
||||
stop()
|
||||
}
|
||||
}
|
||||
|
||||
fallback() external payable {
|
||||
assembly {
|
||||
stop()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
======= evmasm_prevrandao_post_paris/input.sol:C =======
|
||||
EVM assembly:
|
||||
sstore(0x00, prevrandao)
|
||||
stop
|
||||
stop
|
||||
|
||||
sub_0: assembly {
|
||||
stop
|
||||
}
|
||||
|
||||
Opcodes:
|
||||
PREVRANDAO PUSH1 0x0 SSTORE STOP INVALID
|
||||
@@ -0,0 +1 @@
|
||||
--no-cbor-metadata --via-ir --optimize --opcodes --asm --debug-info none --evm-version london
|
||||
@@ -0,0 +1,5 @@
|
||||
Warning: "prevrandao" is not supported by the VM version and will be treated as "difficulty".
|
||||
--> evmasm_prevrandao_pre_paris/input.sol:6:21:
|
||||
|
|
||||
6 | uint256 x = block.prevrandao;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@@ -0,0 +1,18 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
pragma solidity >=0.0.0;
|
||||
|
||||
contract C {
|
||||
constructor() payable {
|
||||
uint256 x = block.prevrandao;
|
||||
assembly {
|
||||
sstore(0, x)
|
||||
stop()
|
||||
}
|
||||
}
|
||||
|
||||
fallback() external payable {
|
||||
assembly {
|
||||
stop()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
======= evmasm_prevrandao_pre_paris/input.sol:C =======
|
||||
EVM assembly:
|
||||
sstore(0x00, difficulty)
|
||||
stop
|
||||
stop
|
||||
|
||||
sub_0: assembly {
|
||||
stop
|
||||
}
|
||||
|
||||
Opcodes:
|
||||
DIFFICULTY PUSH1 0x0 SSTORE STOP INVALID
|
||||
@@ -20,6 +20,7 @@
|
||||
* @date 2018
|
||||
* Tests for the assembler.
|
||||
*/
|
||||
#include <test/Common.h>
|
||||
|
||||
#include <libevmasm/Assembly.h>
|
||||
#include <libsolutil/JSON.h>
|
||||
@@ -59,15 +60,16 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
|
||||
{ "sub.asm", 1 },
|
||||
{ "verbatim.asm", 2 }
|
||||
};
|
||||
Assembly _assembly{false, {}};
|
||||
EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion();
|
||||
Assembly _assembly{evmVersion, false, {}};
|
||||
auto root_asm = make_shared<string>("root.asm");
|
||||
_assembly.setSourceLocation({1, 3, root_asm});
|
||||
|
||||
Assembly _subAsm{false, {}};
|
||||
Assembly _subAsm{evmVersion, false, {}};
|
||||
auto sub_asm = make_shared<string>("sub.asm");
|
||||
_subAsm.setSourceLocation({6, 8, sub_asm});
|
||||
|
||||
Assembly _verbatimAsm(true, "");
|
||||
Assembly _verbatimAsm(evmVersion, true, "");
|
||||
auto verbatim_asm = make_shared<string>("verbatim.asm");
|
||||
_verbatimAsm.setSourceLocation({8, 18, verbatim_asm});
|
||||
|
||||
@@ -215,6 +217,7 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps)
|
||||
{
|
||||
EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion();
|
||||
// Tests for 1, 2, 3 number of immutables.
|
||||
for (int numImmutables = 1; numImmutables <= 3; ++numImmutables)
|
||||
{
|
||||
@@ -243,7 +246,7 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps)
|
||||
{ *subName, 1 }
|
||||
};
|
||||
|
||||
auto subAsm = make_shared<Assembly>(false, string{});
|
||||
auto subAsm = make_shared<Assembly>(evmVersion, false, string{});
|
||||
for (char i = 0; i < numImmutables; ++i)
|
||||
{
|
||||
for (int r = 0; r < numActualRefs; ++r)
|
||||
@@ -253,7 +256,7 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps)
|
||||
}
|
||||
}
|
||||
|
||||
Assembly assembly{true, {}};
|
||||
Assembly assembly{evmVersion, true, {}};
|
||||
for (char i = 1; i <= numImmutables; ++i)
|
||||
{
|
||||
assembly.setSourceLocation({10*i, 10*i + 3+i, assemblyName});
|
||||
@@ -270,7 +273,7 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps)
|
||||
auto const numberOfMappings = std::count(sourceMappings.begin(), sourceMappings.end(), ';');
|
||||
|
||||
LinkerObject const& obj = assembly.assemble();
|
||||
string const disassembly = disassemble(obj.bytecode, "\n");
|
||||
string const disassembly = disassemble(obj.bytecode, evmVersion, "\n");
|
||||
auto const numberOfOpcodes = std::count(disassembly.begin(), disassembly.end(), '\n');
|
||||
|
||||
#if 0 // {{{ debug prints
|
||||
@@ -302,11 +305,12 @@ BOOST_AUTO_TEST_CASE(immutable)
|
||||
{ "root.asm", 0 },
|
||||
{ "sub.asm", 1 }
|
||||
};
|
||||
Assembly _assembly{true, {}};
|
||||
EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion();
|
||||
Assembly _assembly{evmVersion, true, {}};
|
||||
auto root_asm = make_shared<string>("root.asm");
|
||||
_assembly.setSourceLocation({1, 3, root_asm});
|
||||
|
||||
Assembly _subAsm{false, {}};
|
||||
Assembly _subAsm{evmVersion, false, {}};
|
||||
auto sub_asm = make_shared<string>("sub.asm");
|
||||
_subAsm.setSourceLocation({6, 8, sub_asm});
|
||||
_subAsm.appendImmutable("someImmutable");
|
||||
@@ -395,10 +399,11 @@ BOOST_AUTO_TEST_CASE(immutable)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(subobject_encode_decode)
|
||||
{
|
||||
Assembly assembly{true, {}};
|
||||
EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion();
|
||||
Assembly assembly{evmVersion, true, {}};
|
||||
|
||||
shared_ptr<Assembly> subAsmPtr = make_shared<Assembly>(false, string{});
|
||||
shared_ptr<Assembly> subSubAsmPtr = make_shared<Assembly>(false, string{});
|
||||
shared_ptr<Assembly> subAsmPtr = make_shared<Assembly>(evmVersion, false, string{});
|
||||
shared_ptr<Assembly> subSubAsmPtr = make_shared<Assembly>(evmVersion, false, string{});
|
||||
|
||||
assembly.appendSubroutine(subAsmPtr);
|
||||
subAsmPtr->appendSubroutine(subSubAsmPtr);
|
||||
|
||||
@@ -1250,8 +1250,18 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies)
|
||||
// tag unifications (due to block deduplication) is also
|
||||
// visible at the super-assembly.
|
||||
|
||||
Assembly main{false, {}};
|
||||
AssemblyPointer sub = make_shared<Assembly>(true, string{});
|
||||
Assembly::OptimiserSettings settings;
|
||||
settings.runInliner = false;
|
||||
settings.runJumpdestRemover = true;
|
||||
settings.runPeephole = true;
|
||||
settings.runDeduplicate = true;
|
||||
settings.runCSE = true;
|
||||
settings.runConstantOptimiser = true;
|
||||
settings.evmVersion = solidity::test::CommonOptions::get().evmVersion();
|
||||
settings.expectedExecutionsPerDeployment = OptimiserSettings{}.expectedExecutionsPerDeployment;
|
||||
|
||||
Assembly main{settings.evmVersion, false, {}};
|
||||
AssemblyPointer sub = make_shared<Assembly>(settings.evmVersion, true, string{});
|
||||
|
||||
sub->append(u256(1));
|
||||
auto t1 = sub->newTag();
|
||||
@@ -1277,16 +1287,6 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies)
|
||||
main.append(t1.toSubAssemblyTag(subId));
|
||||
main.append(u256(8));
|
||||
|
||||
Assembly::OptimiserSettings settings;
|
||||
settings.runInliner = false;
|
||||
settings.runJumpdestRemover = true;
|
||||
settings.runPeephole = true;
|
||||
settings.runDeduplicate = true;
|
||||
settings.runCSE = true;
|
||||
settings.runConstantOptimiser = true;
|
||||
settings.evmVersion = solidity::test::CommonOptions::get().evmVersion();
|
||||
settings.expectedExecutionsPerDeployment = OptimiserSettings{}.expectedExecutionsPerDeployment;
|
||||
|
||||
main.optimise(settings);
|
||||
|
||||
AssemblyItems expectationMain{
|
||||
|
||||
@@ -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
|
||||
// ----
|
||||
+21
@@ -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
|
||||
// ----
|
||||
+21
@@ -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.
|
||||
+1
-1
@@ -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 { ... }`.
|
||||
+1
-1
@@ -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
|
||||
// ----
|
||||
+2
-2
@@ -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.
|
||||
|
||||
+11
@@ -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
|
||||
-1
@@ -73,7 +73,6 @@ contract C {
|
||||
//pop(coinbase())
|
||||
//pop(timestamp())
|
||||
//pop(number())
|
||||
//pop(difficulty())
|
||||
//pop(gaslimit())
|
||||
|
||||
// NOTE: msize() is allowed only with optimizer disabled
|
||||
|
||||
+2
-2
@@ -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.
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
contract C {
|
||||
function f() public view {
|
||||
assembly {
|
||||
pop(difficulty())
|
||||
}
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: <=london
|
||||
// ----
|
||||
+22
-38
@@ -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".
|
||||
|
||||
+11
@@ -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".
|
||||
+13
@@ -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.
|
||||
+13
@@ -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".
|
||||
+11
@@ -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".
|
||||
+11
@@ -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".
|
||||
+11
@@ -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".
|
||||
@@ -19,6 +19,8 @@
|
||||
#include <test/libyul/EVMCodeTransformTest.h>
|
||||
#include <test/libyul/Common.h>
|
||||
|
||||
#include <test/Common.h>
|
||||
|
||||
#include <libyul/YulStack.h>
|
||||
#include <libyul/backends/evm/EthAssemblyAdapter.h>
|
||||
#include <libyul/backends/evm/EVMObjectCompiler.h>
|
||||
@@ -66,7 +68,7 @@ TestCase::TestResult EVMCodeTransformTest::run(ostream& _stream, string const& _
|
||||
return TestResult::FatalError;
|
||||
}
|
||||
|
||||
evmasm::Assembly assembly{false, {}};
|
||||
evmasm::Assembly assembly{solidity::test::CommonOptions::get().evmVersion(), false, {}};
|
||||
EthAssemblyAdapter adapter(assembly);
|
||||
EVMObjectCompiler::compile(
|
||||
*stack.parserResult(),
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
#include <test/libsolidity/util/SoltestErrors.h>
|
||||
|
||||
#include <test/Common.h>
|
||||
|
||||
#include <libsolutil/AnsiColorized.h>
|
||||
|
||||
#include <libyul/YulStack.h>
|
||||
@@ -101,7 +103,7 @@ TestCase::TestResult ObjectCompilerTest::run(ostream& _stream, string const& _li
|
||||
"Bytecode: " +
|
||||
util::toHex(obj.bytecode->bytecode) +
|
||||
"\nOpcodes: " +
|
||||
boost::trim_copy(evmasm::disassemble(obj.bytecode->bytecode)) +
|
||||
boost::trim_copy(evmasm::disassemble(obj.bytecode->bytecode, solidity::test::CommonOptions::get().evmVersion())) +
|
||||
"\nSourceMappings:" +
|
||||
(obj.sourceMappings->empty() ? "" : " " + *obj.sourceMappings) +
|
||||
"\n";
|
||||
|
||||
@@ -98,7 +98,7 @@ string YulInterpreterTest::interpret()
|
||||
{
|
||||
Interpreter::run(
|
||||
state,
|
||||
EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{}),
|
||||
EVMDialect::strictAssemblyForEVMObjects(solidity::test::CommonOptions::get().evmVersion()),
|
||||
*m_ast,
|
||||
/*disableExternalCalls=*/ !m_simulateExternalCallsToSelf,
|
||||
/*disableMemoryTracing=*/ false
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
{
|
||||
sstore(0, difficulty())
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: <paris
|
||||
// ----
|
||||
// Trace:
|
||||
// Memory dump:
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
sstore(0, difficulty())
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: <paris
|
||||
// ----
|
||||
// Trace:
|
||||
// Memory dump:
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000: 0000000000000000000000000000000000000000000000000000000009999999
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
sstore(0, prevrandao())
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=paris
|
||||
// ----
|
||||
// Trace:
|
||||
// Memory dump:
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000: 0000000000000000000000000000000000000000000000010000000000000001
|
||||
@@ -189,7 +189,7 @@ void FuzzerUtil::testConstantOptimizer(string const& _input, bool _quiet)
|
||||
|
||||
for (bool isCreation: {false, true})
|
||||
{
|
||||
Assembly assembly{isCreation, {}};
|
||||
Assembly assembly{langutil::EVMVersion{}, isCreation, {}};
|
||||
for (u256 const& n: numbers)
|
||||
{
|
||||
if (!_quiet)
|
||||
|
||||
@@ -98,7 +98,7 @@ u256 EVMInstructionInterpreter::eval(
|
||||
using namespace solidity::evmasm;
|
||||
using evmasm::Instruction;
|
||||
|
||||
auto info = instructionInfo(_instruction);
|
||||
auto info = instructionInfo(_instruction, m_evmVersion);
|
||||
yulAssert(static_cast<size_t>(info.args) == _arguments.size(), "");
|
||||
|
||||
auto const& arg = _arguments;
|
||||
@@ -268,8 +268,8 @@ u256 EVMInstructionInterpreter::eval(
|
||||
return m_state.timestamp;
|
||||
case Instruction::NUMBER:
|
||||
return m_state.blockNumber;
|
||||
case Instruction::DIFFICULTY:
|
||||
return m_state.difficulty;
|
||||
case Instruction::PREVRANDAO:
|
||||
return (m_evmVersion < langutil::EVMVersion::paris()) ? m_state.difficulty : m_state.prevrandao;
|
||||
case Instruction::GASLIMIT:
|
||||
return m_state.gaslimit;
|
||||
// --------------- memory / storage / logs ---------------
|
||||
@@ -543,7 +543,7 @@ void EVMInstructionInterpreter::logTrace(
|
||||
)
|
||||
{
|
||||
logTrace(
|
||||
evmasm::instructionInfo(_instruction).name,
|
||||
evmasm::instructionInfo(_instruction, m_evmVersion).name,
|
||||
SemanticInformation::memory(_instruction) == SemanticInformation::Effect::Write,
|
||||
_arguments,
|
||||
_data
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <libsolutil/CommonData.h>
|
||||
#include <libsolutil/Numeric.h>
|
||||
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace solidity::evmasm
|
||||
@@ -74,7 +76,8 @@ struct InterpreterState;
|
||||
class EVMInstructionInterpreter
|
||||
{
|
||||
public:
|
||||
explicit EVMInstructionInterpreter(InterpreterState& _state, bool _disableMemWriteTrace):
|
||||
explicit EVMInstructionInterpreter(langutil::EVMVersion _evmVersion, InterpreterState& _state, bool _disableMemWriteTrace):
|
||||
m_evmVersion(_evmVersion),
|
||||
m_state(_state),
|
||||
m_disableMemoryWriteInstructions(_disableMemWriteTrace)
|
||||
{}
|
||||
@@ -128,6 +131,7 @@ private:
|
||||
return m_disableMemoryWriteInstructions;
|
||||
}
|
||||
|
||||
langutil::EVMVersion m_evmVersion;
|
||||
InterpreterState& m_state;
|
||||
/// Flag to disable trace of instructions that write to memory.
|
||||
bool m_disableMemoryWriteInstructions;
|
||||
|
||||
@@ -597,7 +597,7 @@ u256 EwasmBuiltinInterpreter::readU256(uint64_t _offset, size_t _croppedTo)
|
||||
|
||||
void EwasmBuiltinInterpreter::logTrace(evmasm::Instruction _instruction, std::vector<u256> const& _arguments, bytes const& _data)
|
||||
{
|
||||
logTrace(evmasm::instructionInfo(_instruction).name, _arguments, _data);
|
||||
logTrace(evmasm::instructionInfo(_instruction, langutil::EVMVersion()).name, _arguments, _data);
|
||||
}
|
||||
|
||||
void EwasmBuiltinInterpreter::logTrace(std::string const& _pseudoInstruction, std::vector<u256> const& _arguments, bytes const& _data)
|
||||
|
||||
@@ -314,7 +314,7 @@ void ExpressionEvaluator::operator()(FunctionCall const& _funCall)
|
||||
{
|
||||
if (BuiltinFunctionForEVM const* fun = dialect->builtin(_funCall.functionName.name))
|
||||
{
|
||||
EVMInstructionInterpreter interpreter(m_state, m_disableMemoryTrace);
|
||||
EVMInstructionInterpreter interpreter(dialect->evmVersion(), m_state, m_disableMemoryTrace);
|
||||
|
||||
u256 const value = interpreter.evalBuiltin(*fun, _funCall.arguments, values());
|
||||
|
||||
|
||||
@@ -94,6 +94,7 @@ struct InterpreterState
|
||||
u256 timestamp = 0x88888888;
|
||||
u256 blockNumber = 1024;
|
||||
u256 difficulty = 0x9999999;
|
||||
u256 prevrandao = (u256(1) << 64) + 1;
|
||||
u256 gaslimit = 4000000;
|
||||
u256 chainid = 0x01;
|
||||
/// The minimum value of basefee: 7 wei.
|
||||
|
||||
Reference in New Issue
Block a user