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)
Language Features:
* General: Add unit denomination ``gwei``
Compiler Features:

View File

@ -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? '\'')) ;

View File

@ -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);

View File

@ -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) \

View File

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

View File

@ -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")

View File

@ -889,6 +889,9 @@ tuple<bool, rational> 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;

View File

@ -1825,11 +1825,16 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
expression = nodeFactory.createNode<Literal>(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<ASTString> literal = getLiteralAndAdvance();
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();
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.
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;

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_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"(

View File

@ -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);

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 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;
}
// ----

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
{
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.

View File

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