Add unit denomination `gwei`

This commit is contained in:
Mathias Baumann 2020-06-18 17:09:24 +02:00
parent 062a999e85
commit 02328f3bbb
16 changed files with 58 additions and 9 deletions

View File

@ -1,6 +1,7 @@
### 0.6.11 (unreleased) ### 0.6.11 (unreleased)
Language Features: Language Features:
* General: Add unit denomination ``gwei``
Compiler Features: Compiler Features:

View File

@ -359,10 +359,10 @@ subAssembly
: 'assembly' identifier assemblyBlock ; : 'assembly' identifier assemblyBlock ;
numberLiteral numberLiteral
: (DecimalNumber | HexNumber) NumberUnit? ; : (DecimalNumber | HexNumber) (NumberUnit | Gwei)?;
identifier identifier
: ('from' | 'calldata' | 'address' | Identifier) ; : (Gwei | 'from' | 'calldata' | 'address' | Identifier) ;
BooleanLiteral BooleanLiteral
: 'true' | 'false' ; : 'true' | 'false' ;
@ -385,6 +385,8 @@ NumberUnit
: 'wei' | 'szabo' | 'finney' | 'ether' : 'wei' | 'szabo' | 'finney' | 'ether'
| 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'years' ; | 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'years' ;
Gwei: 'gwei' ;
HexLiteralFragment HexLiteralFragment
: 'hex' (('"' HexDigits? '"') | ('\'' HexDigits? '\'')) ; : 'hex' (('"' HexDigits? '"') | ('\'' HexDigits? '\'')) ;

View File

@ -7,11 +7,12 @@ Units and Globally Available Variables
Ether Units 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 wei == 1);
assert(1 gwei == 1e9);
assert(1 szabo == 1e12); assert(1 szabo == 1e12);
assert(1 finney == 1e15); assert(1 finney == 1e15);
assert(1 ether == 1e18); assert(1 ether == 1e18);

View File

@ -232,6 +232,7 @@ namespace solidity::langutil
\ \
/* Identifiers (not keywords or future reserved words). */ \ /* Identifiers (not keywords or future reserved words). */ \
T(Identifier, nullptr, 0) \ T(Identifier, nullptr, 0) \
T(SubGwei, "gwei", 0) \
\ \
/* Keywords reserved for future use. */ \ /* Keywords reserved for future use. */ \
K(After, "after", 0) \ K(After, "after", 0) \

View File

@ -2084,6 +2084,7 @@ public:
{ {
None = static_cast<int>(Token::Illegal), None = static_cast<int>(Token::Illegal),
Wei = static_cast<int>(Token::SubWei), Wei = static_cast<int>(Token::SubWei),
Gwei = static_cast<int>(Token::SubGwei),
Szabo = static_cast<int>(Token::SubSzabo), Szabo = static_cast<int>(Token::SubSzabo),
Finney = static_cast<int>(Token::SubFinney), Finney = static_cast<int>(Token::SubFinney),
Ether = static_cast<int>(Token::SubEther), Ether = static_cast<int>(Token::SubEther),

View File

@ -1001,6 +1001,8 @@ Literal::SubDenomination ASTJsonImporter::subdenomination(Json::Value const& _no
if (subDenStr == "wei") if (subDenStr == "wei")
return Literal::SubDenomination::Wei; return Literal::SubDenomination::Wei;
else if (subDenStr == "gwei")
return Literal::SubDenomination::Gwei;
else if (subDenStr == "szabo") else if (subDenStr == "szabo")
return Literal::SubDenomination::Szabo; return Literal::SubDenomination::Szabo;
else if (subDenStr == "finney") else if (subDenStr == "finney")

View File

@ -889,6 +889,9 @@ tuple<bool, rational> RationalNumberType::isValidLiteral(Literal const& _literal
case Literal::SubDenomination::Wei: case Literal::SubDenomination::Wei:
case Literal::SubDenomination::Second: case Literal::SubDenomination::Second:
break; break;
case Literal::SubDenomination::Gwei:
value *= bigint("1000000000");
break;
case Literal::SubDenomination::Szabo: case Literal::SubDenomination::Szabo:
value *= bigint("1000000000000"); value *= bigint("1000000000000");
break; break;

View File

@ -1825,11 +1825,16 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance()); expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance());
break; break;
case Token::Number: 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<ASTString> literal = getLiteralAndAdvance(); ASTPointer<ASTString> literal = getLiteralAndAdvance();
nodeFactory.markEndPosition(); nodeFactory.markEndPosition();
Literal::SubDenomination subdenomination = static_cast<Literal::SubDenomination>(m_scanner->currentToken()); Token actualToken = m_scanner->currentToken() == Token::Identifier ? Token::SubGwei : m_scanner->currentToken();
Literal::SubDenomination subdenomination = static_cast<Literal::SubDenomination>(actualToken);
m_scanner->next(); m_scanner->next();
expression = nodeFactory.createNode<Literal>(token, literal, subdenomination); expression = nodeFactory.createNode<Literal>(token, literal, subdenomination);
} }

View File

@ -48,6 +48,7 @@ using Address = util::h160;
// The various denominations; here for ease of use where needed within code. // The various denominations; here for ease of use where needed within code.
static const u256 wei = 1; static const u256 wei = 1;
static const u256 shannon = u256("1000000000"); static const u256 shannon = u256("1000000000");
static const u256 gwei = shannon;
static const u256 szabo = shannon * 1000; static const u256 szabo = shannon * 1000;
static const u256 finney = szabo * 1000; static const u256 finney = szabo * 1000;
static const u256 ether = finney * 1000; static const u256 ether = finney * 1000;

View File

@ -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_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) BOOST_AUTO_TEST_CASE(int_with_szabo_ether_subdenomination)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(

View File

@ -428,8 +428,9 @@ BOOST_AUTO_TEST_CASE(comments_mixed_in_sequence)
BOOST_AUTO_TEST_CASE(ether_subdenominations) 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.currentToken(), Token::SubWei);
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::SubSzabo); BOOST_CHECK_EQUAL(scanner.next(), Token::SubSzabo);
BOOST_CHECK_EQUAL(scanner.next(), Token::SubFinney); BOOST_CHECK_EQUAL(scanner.next(), Token::SubFinney);
BOOST_CHECK_EQUAL(scanner.next(), Token::SubEther); BOOST_CHECK_EQUAL(scanner.next(), Token::SubEther);

View File

@ -0,0 +1,10 @@
contract C {
uint constant gwei = 1 gwei;
function f() public view returns(uint) { return gwei; }
}
// ====
// compileViaYul: also
// ----
// f() -> 1000000000

View File

@ -2,5 +2,6 @@ contract C {
uint constant a = 1 wei + 2 szabo + 3 finney + 4 ether; 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 b = 1 seconds + 2 minutes + 3 hours + 4 days + 5 weeks;
uint constant c = 2 szabo / 1 seconds + 3 finney * 3 hours; uint constant c = 2 szabo / 1 seconds + 3 finney * 3 hours;
uint constant d = 2 gwei / 1 seconds + 3 finney * 3 hours;
} }
// ---- // ----

View File

@ -0,0 +1,3 @@
contract C {
uint constant gwei = 1 gwei;
}

View File

@ -1,15 +1,16 @@
contract c { contract C {
function f() public function f() public
{ {
a = 1 wei; a = 1 wei;
b = 2 szabo; b = 2 szabo;
c = 3 finney; c = 3 finney;
b = 4 ether; d = 4 ether;
e = 5 gwei;
} }
uint256 a; uint256 a;
uint256 b; uint256 b;
uint256 c; uint256 c;
uint256 d; uint256 d;
uint256 e;
} }
// ---- // ----
// Warning 2519: (170-179): This declaration shadows an existing declaration.

View File

@ -8,6 +8,7 @@
" ether " " ether "
" finney " " finney "
" gasleft() " " gasleft() "
" gwei "
" hours " " hours "
" minutes " " minutes "
" msg.data " " msg.data "