From 7cd05bf60361814fe780882f6df629c65f2afa3e Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 22 Sep 2020 18:12:01 +0100 Subject: [PATCH] Introduce block.chainid --- Changelog.md | 1 + docs/cheatsheet.rst | 1 + docs/units-and-global-variables.rst | 1 + libsolidity/analysis/TypeChecker.cpp | 6 ++++++ libsolidity/analysis/ViewPureChecker.cpp | 1 - libsolidity/ast/Types.cpp | 3 ++- libsolidity/codegen/ExpressionCompiler.cpp | 2 ++ libsolidity/codegen/ir/IRGeneratorForStatements.cpp | 2 ++ .../semanticTests/state/block_chainid.sol | 12 ++++++++++++ test/libsolidity/syntaxTests/types/magic_block.sol | 5 +++++ .../syntaxTests/types/magic_block_istanbul.sol | 3 +++ .../viewPureChecker/assembly_chainid_not_pure.sol | 4 ++++ .../viewPureChecker/assembly_istanbul.sol | 3 +++ 13 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 test/libsolidity/semanticTests/state/block_chainid.sol diff --git a/Changelog.md b/Changelog.md index 6abaa1fe6..06d01fdd6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -22,6 +22,7 @@ Breaking Changes: * Type System: Explicit conversions between two types are disallowed if it changes more than one of sign, width or kind at the same time. * Type System: Explicit conversions from literals to enums are only allowed if the value fits in the enum. * Type System: Explicit conversions from literals to integer type is as strict as implicit conversions. + * Type System: Introduce ``block.chainid`` for retrieving the current chain id. * Type System: Support ``address(...).codehash`` to retrieve the codehash of an account. * Type System: Unary negation can only be used on signed integers, not on unsigned integers. * View Pure Checker: Mark ``chainid`` as view. diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst index 8e2a95af5..18d857dbd 100644 --- a/docs/cheatsheet.rst +++ b/docs/cheatsheet.rst @@ -82,6 +82,7 @@ Global Variables the given arguments starting from the second and prepends the given four-byte selector - ``abi.encodeWithSignature(string memory signature, ...) returns (bytes memory)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature)), ...)``` +- ``block.chainid`` (``uint``): current chain id - ``block.coinbase`` (``address payable``): current block miner's address - ``block.difficulty`` (``uint``): current block difficulty - ``block.gaslimit`` (``uint``): current block gaslimit diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index a6152d7f9..c405125b7 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -69,6 +69,7 @@ Block and Transaction Properties -------------------------------- - ``blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent, excluding current, blocks +- ``block.chainid`` (``uint``): current chain id - ``block.coinbase`` (``address payable``): current block miner's address - ``block.difficulty`` (``uint``): current block difficulty - ``block.gaslimit`` (``uint``): current block gaslimit diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 31952f4ff..baaf8035f 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -2922,6 +2922,12 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) (memberName == "min" || memberName == "max") ) annotation.isPure = true; + else if (magicType->kind() == MagicType::Kind::Block && memberName == "chainid" && !m_evmVersion.hasChainID()) + m_errorReporter.typeError( + 3081_error, + _memberAccess.location(), + "\"chainid\" is not supported by the VM version." + ); } if ( diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index 898c33e5f..c7fdc7ee0 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -368,7 +368,6 @@ void ViewPureChecker::endVisit(MemberAccess const& _memberAccess) {MagicType::Kind::ABI, "encodePacked"}, {MagicType::Kind::ABI, "encodeWithSelector"}, {MagicType::Kind::ABI, "encodeWithSignature"}, - {MagicType::Kind::Block, "blockhash"}, {MagicType::Kind::Message, "data"}, {MagicType::Kind::Message, "sig"}, {MagicType::Kind::MetaType, "creationCode"}, diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 4206513fc..50bb438ff 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -3825,7 +3825,8 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const {"blockhash", TypeProvider::function(strings{"uint"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)}, {"difficulty", TypeProvider::uint256()}, {"number", TypeProvider::uint256()}, - {"gaslimit", TypeProvider::uint256()} + {"gaslimit", TypeProvider::uint256()}, + {"chainid", TypeProvider::uint256()} }); case Kind::Message: return MemberList::MemberMap({ diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 2a0e512f5..f9600c22f 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1576,6 +1576,8 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) m_context << Instruction::ORIGIN; else if (member == "gasprice") m_context << Instruction::GASPRICE; + else if (member == "chainid") + m_context << Instruction::CHAINID; else if (member == "data") m_context << u256(0) << Instruction::CALLDATASIZE; else if (member == "sig") diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 00969faf5..fc4231c9e 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -1688,6 +1688,8 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) define(_memberAccess) << "origin()\n"; else if (member == "gasprice") define(_memberAccess) << "gasprice()\n"; + else if (member == "chainid") + define(_memberAccess) << "chainid()\n"; else if (member == "data") { IRVariable var(_memberAccess); diff --git a/test/libsolidity/semanticTests/state/block_chainid.sol b/test/libsolidity/semanticTests/state/block_chainid.sol new file mode 100644 index 000000000..473629d8d --- /dev/null +++ b/test/libsolidity/semanticTests/state/block_chainid.sol @@ -0,0 +1,12 @@ +contract C { + function f() public returns (uint) { + return block.chainid; + } +} +// ==== +// EVMVersion: >=istanbul +// compileViaYul: also +// ---- +// f() -> 1 +// f() -> 1 +// f() -> 1 diff --git a/test/libsolidity/syntaxTests/types/magic_block.sol b/test/libsolidity/syntaxTests/types/magic_block.sol index d0eae923b..e3bf2ab53 100644 --- a/test/libsolidity/syntaxTests/types/magic_block.sol +++ b/test/libsolidity/syntaxTests/types/magic_block.sol @@ -11,6 +11,11 @@ contract C { function i() public view returns (uint) { return block.timestamp; } + function j() public view returns (uint) { + return block.chainid; + } } // ==== // EVMVersion: =istanbul diff --git a/test/libsolidity/syntaxTests/viewPureChecker/assembly_chainid_not_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/assembly_chainid_not_pure.sol index 375fc7940..2f681ed57 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/assembly_chainid_not_pure.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/assembly_chainid_not_pure.sol @@ -2,8 +2,12 @@ contract C { function f() public pure { assembly { pop(chainid()) } } + function g() public pure returns (uint) { + return block.chainid; + } } // ==== // EVMVersion: >=istanbul // ---- // TypeError 2527: (67-76): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (147-160): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". diff --git a/test/libsolidity/syntaxTests/viewPureChecker/assembly_istanbul.sol b/test/libsolidity/syntaxTests/viewPureChecker/assembly_istanbul.sol index 644975ed7..1f4fb4309 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/assembly_istanbul.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/assembly_istanbul.sol @@ -2,6 +2,9 @@ contract C { function f() public view { assembly { pop(chainid()) } } + function g() public view returns (uint) { + return block.chainid; + } } // ==== // EVMVersion: >=istanbul