From 02328f3bbbe851701e03413ec0ca852155a142a4 Mon Sep 17 00:00:00 2001 From: Mathias Baumann Date: Thu, 18 Jun 2020 17:09:24 +0200 Subject: [PATCH] Add unit denomination ``gwei`` --- Changelog.md | 1 + docs/Solidity.g4 | 6 ++++-- docs/units-and-global-variables.rst | 3 ++- liblangutil/Token.h | 1 + libsolidity/ast/AST.h | 1 + libsolidity/ast/ASTJsonImporter.cpp | 2 ++ libsolidity/ast/Types.cpp | 3 +++ libsolidity/parsing/Parser.cpp | 9 +++++++-- test/ExecutionFramework.h | 1 + test/libsolidity/SolidityExpressionCompiler.cpp | 15 +++++++++++++++ test/libsolidity/SolidityScanner.cpp | 3 ++- test/libsolidity/semanticTests/literals/gwei.sol | 10 ++++++++++ .../syntaxTests/denominations/denominations.sol | 1 + .../syntaxTests/denominations/gwei.sol | 3 +++ ...eral_constants_with_ether_subdenominations.sol | 7 ++++--- test/tools/ossfuzz/config/solidity.dict | 1 + 16 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 test/libsolidity/semanticTests/literals/gwei.sol create mode 100644 test/libsolidity/syntaxTests/denominations/gwei.sol diff --git a/Changelog.md b/Changelog.md index 9328f2824..052b10158 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.6.11 (unreleased) Language Features: + * General: Add unit denomination ``gwei`` Compiler Features: diff --git a/docs/Solidity.g4 b/docs/Solidity.g4 index 65fee05fa..af351731b 100644 --- a/docs/Solidity.g4 +++ b/docs/Solidity.g4 @@ -359,10 +359,10 @@ subAssembly : 'assembly' identifier assemblyBlock ; numberLiteral - : (DecimalNumber | HexNumber) NumberUnit? ; + : (DecimalNumber | HexNumber) (NumberUnit | Gwei)?; identifier - : ('from' | 'calldata' | 'address' | Identifier) ; + : (Gwei | 'from' | 'calldata' | 'address' | Identifier) ; BooleanLiteral : 'true' | 'false' ; @@ -385,6 +385,8 @@ NumberUnit : 'wei' | 'szabo' | 'finney' | 'ether' | 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'years' ; +Gwei: 'gwei' ; + HexLiteralFragment : 'hex' (('"' HexDigits? '"') | ('\'' HexDigits? '\'')) ; diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index d936ef246..213390be4 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -7,11 +7,12 @@ Units and Globally Available Variables Ether Units =========== -A literal number can take a suffix of ``wei``, ``finney``, ``szabo`` or ``ether`` to specify a subdenomination of Ether, where Ether numbers without a postfix are assumed to be Wei. +A literal number can take a suffix of ``wei``, ``gwei``, ``finney``, ``szabo`` or ``ether`` to specify a subdenomination of Ether, where Ether numbers without a postfix are assumed to be Wei. :: assert(1 wei == 1); + assert(1 gwei == 1e9); assert(1 szabo == 1e12); assert(1 finney == 1e15); assert(1 ether == 1e18); diff --git a/liblangutil/Token.h b/liblangutil/Token.h index d9d4471cb..916f71c75 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -232,6 +232,7 @@ namespace solidity::langutil \ /* Identifiers (not keywords or future reserved words). */ \ T(Identifier, nullptr, 0) \ + T(SubGwei, "gwei", 0) \ \ /* Keywords reserved for future use. */ \ K(After, "after", 0) \ diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index c6c560988..88c3e1beb 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -2084,6 +2084,7 @@ public: { None = static_cast(Token::Illegal), Wei = static_cast(Token::SubWei), + Gwei = static_cast(Token::SubGwei), Szabo = static_cast(Token::SubSzabo), Finney = static_cast(Token::SubFinney), Ether = static_cast(Token::SubEther), diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index 65f9fa718..ccf9af5a7 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -1001,6 +1001,8 @@ Literal::SubDenomination ASTJsonImporter::subdenomination(Json::Value const& _no if (subDenStr == "wei") return Literal::SubDenomination::Wei; + else if (subDenStr == "gwei") + return Literal::SubDenomination::Gwei; else if (subDenStr == "szabo") return Literal::SubDenomination::Szabo; else if (subDenStr == "finney") diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 5ea018107..992f0343d 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -889,6 +889,9 @@ tuple RationalNumberType::isValidLiteral(Literal const& _literal case Literal::SubDenomination::Wei: case Literal::SubDenomination::Second: break; + case Literal::SubDenomination::Gwei: + value *= bigint("1000000000"); + break; case Literal::SubDenomination::Szabo: value *= bigint("1000000000000"); break; diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index c429ba786..4b63cbc58 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1825,11 +1825,16 @@ ASTPointer Parser::parsePrimaryExpression() expression = nodeFactory.createNode(token, getLiteralAndAdvance()); break; case Token::Number: - if (TokenTraits::isEtherSubdenomination(m_scanner->peekNextToken())) + if ( + (m_scanner->peekNextToken() == Token::Identifier && m_scanner->peekLiteral() == "gwei") || + TokenTraits::isEtherSubdenomination(m_scanner->peekNextToken()) + ) { ASTPointer literal = getLiteralAndAdvance(); nodeFactory.markEndPosition(); - Literal::SubDenomination subdenomination = static_cast(m_scanner->currentToken()); + Token actualToken = m_scanner->currentToken() == Token::Identifier ? Token::SubGwei : m_scanner->currentToken(); + + Literal::SubDenomination subdenomination = static_cast(actualToken); m_scanner->next(); expression = nodeFactory.createNode(token, literal, subdenomination); } diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index 72a07ce3e..6fea5310a 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -48,6 +48,7 @@ using Address = util::h160; // The various denominations; here for ease of use where needed within code. static const u256 wei = 1; static const u256 shannon = u256("1000000000"); +static const u256 gwei = shannon; static const u256 szabo = shannon * 1000; static const u256 finney = szabo * 1000; static const u256 ether = finney * 1000; diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 4d1e9e23a..10083b827 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -221,6 +221,21 @@ BOOST_AUTO_TEST_CASE(int_with_wei_ether_subdenomination) BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } +BOOST_AUTO_TEST_CASE(int_with_gwei_ether_subdenomination) +{ + char const* sourceCode = R"( + contract test { + function test () { + uint x = 1 gwei; + } + } + )"; + bytes code = compileFirstExpression(sourceCode); + + bytes expectation({uint8_t(Instruction::PUSH4), 0x3b, 0x9a, 0xca, 0x00}); + BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); +} + BOOST_AUTO_TEST_CASE(int_with_szabo_ether_subdenomination) { char const* sourceCode = R"( diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp index dc628674a..b02a910a5 100644 --- a/test/libsolidity/SolidityScanner.cpp +++ b/test/libsolidity/SolidityScanner.cpp @@ -428,8 +428,9 @@ BOOST_AUTO_TEST_CASE(comments_mixed_in_sequence) BOOST_AUTO_TEST_CASE(ether_subdenominations) { - Scanner scanner(CharStream("wei szabo finney ether", "")); + Scanner scanner(CharStream("wei gwei szabo finney ether", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::SubWei); + BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::SubSzabo); BOOST_CHECK_EQUAL(scanner.next(), Token::SubFinney); BOOST_CHECK_EQUAL(scanner.next(), Token::SubEther); diff --git a/test/libsolidity/semanticTests/literals/gwei.sol b/test/libsolidity/semanticTests/literals/gwei.sol new file mode 100644 index 000000000..7762021dc --- /dev/null +++ b/test/libsolidity/semanticTests/literals/gwei.sol @@ -0,0 +1,10 @@ +contract C { + uint constant gwei = 1 gwei; + + function f() public view returns(uint) { return gwei; } +} +// ==== +// compileViaYul: also +// ---- +// f() -> 1000000000 + diff --git a/test/libsolidity/syntaxTests/denominations/denominations.sol b/test/libsolidity/syntaxTests/denominations/denominations.sol index 43049a144..a34c03de0 100644 --- a/test/libsolidity/syntaxTests/denominations/denominations.sol +++ b/test/libsolidity/syntaxTests/denominations/denominations.sol @@ -2,5 +2,6 @@ contract C { uint constant a = 1 wei + 2 szabo + 3 finney + 4 ether; uint constant b = 1 seconds + 2 minutes + 3 hours + 4 days + 5 weeks; uint constant c = 2 szabo / 1 seconds + 3 finney * 3 hours; + uint constant d = 2 gwei / 1 seconds + 3 finney * 3 hours; } // ---- diff --git a/test/libsolidity/syntaxTests/denominations/gwei.sol b/test/libsolidity/syntaxTests/denominations/gwei.sol new file mode 100644 index 000000000..5bc5edb3d --- /dev/null +++ b/test/libsolidity/syntaxTests/denominations/gwei.sol @@ -0,0 +1,3 @@ +contract C { + uint constant gwei = 1 gwei; +} diff --git a/test/libsolidity/syntaxTests/parsing/literal_constants_with_ether_subdenominations.sol b/test/libsolidity/syntaxTests/parsing/literal_constants_with_ether_subdenominations.sol index 395bacc3e..51ce8b4d5 100644 --- a/test/libsolidity/syntaxTests/parsing/literal_constants_with_ether_subdenominations.sol +++ b/test/libsolidity/syntaxTests/parsing/literal_constants_with_ether_subdenominations.sol @@ -1,15 +1,16 @@ -contract c { +contract C { function f() public { a = 1 wei; b = 2 szabo; c = 3 finney; - b = 4 ether; + d = 4 ether; + e = 5 gwei; } uint256 a; uint256 b; uint256 c; uint256 d; + uint256 e; } // ---- -// Warning 2519: (170-179): This declaration shadows an existing declaration. diff --git a/test/tools/ossfuzz/config/solidity.dict b/test/tools/ossfuzz/config/solidity.dict index 8190e7c55..f788d49c2 100644 --- a/test/tools/ossfuzz/config/solidity.dict +++ b/test/tools/ossfuzz/config/solidity.dict @@ -8,6 +8,7 @@ " ether " " finney " " gasleft() " +" gwei " " hours " " minutes " " msg.data "