Merge remote-tracking branch 'origin/develop' into breaking

This commit is contained in:
chriseth
2020-06-30 18:56:51 +02:00
50 changed files with 701 additions and 40 deletions
+1
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;
@@ -0,0 +1 @@
--strict-assembly --optimize-yul
@@ -0,0 +1 @@
The following options are invalid in assembly mode: --optimize-yul. Optimization is disabled by default and can be enabled with --optimize.
@@ -0,0 +1 @@
1
@@ -0,0 +1,3 @@
{
sstore(0, 1)
}
@@ -1 +1 @@
The following options are invalid in assembly mode: --output-dir, --gas, --combined-json, --optimize-yul, --no-optimize-yul. Optimization is disabled by default and can be enabled with --optimize.
The following options are invalid in assembly mode: --output-dir.
@@ -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"(
+304 -1
View File
@@ -355,6 +355,52 @@ BOOST_AUTO_TEST_CASE(private_state_variable)
checkNatspec(sourceCode, "test", userDoc, true);
}
BOOST_AUTO_TEST_CASE(event)
{
char const* sourceCode = R"(
contract ERC20 {
/// @notice This event is emitted when a transfer occurs.
/// @param from The source account.
/// @param to The destination account.
/// @param amount The amount.
/// @dev A test case!
event Transfer(address indexed from, address indexed to, uint amount);
}
)";
char const* devDoc = R"ABCDEF(
{
"events":
{
"Transfer(address,address,uint256)":
{
"details": "A test case!",
"params":
{
"amount": "The amount.", "from": "The source account.", "to": "The destination account."
}
}
},
"methods": {}
}
)ABCDEF";
checkNatspec(sourceCode, "ERC20", devDoc, false);
char const* userDoc = R"ABCDEF(
{
"events":
{
"Transfer(address,address,uint256)":
{
"notice": "This event is emitted when a transfer occurs."
}
},
"methods": {}
}
)ABCDEF";
checkNatspec(sourceCode, "ERC20", userDoc, true);
}
BOOST_AUTO_TEST_CASE(dev_desc_after_nl)
{
char const* sourceCode = R"(
@@ -1218,6 +1264,263 @@ BOOST_AUTO_TEST_CASE(slash3_slash4)
checkNatspec(sourceCode, "test", natspec, true);
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(dev_default_inherit_variable)
{
char const *sourceCode = R"(
contract C {
/// @notice Hello world
/// @dev test
function x() virtual external returns (uint) {
return 1;
}
}
contract D is C {
uint public override x;
}
)";
char const *natspec = R"ABCDEF({
"methods":
{
"x()":
{
"details": "test"
}
}
})ABCDEF";
char const *natspec1 = R"ABCDEF({
"methods" : {},
"stateVariables" :
{
"x" :
{
"details" : "test"
}
}
})ABCDEF";
checkNatspec(sourceCode, "C", natspec, false);
checkNatspec(sourceCode, "D", natspec1, false);
}
BOOST_AUTO_TEST_CASE(user_default_inherit_variable)
{
char const *sourceCode = R"(
contract C {
/// @notice Hello world
/// @dev test
function x() virtual external returns (uint) {
return 1;
}
}
contract D is C {
uint public override x;
}
)";
char const *natspec = R"ABCDEF({
"methods":
{
"x()":
{
"notice": "Hello world"
}
}
})ABCDEF";
checkNatspec(sourceCode, "C", natspec, true);
checkNatspec(sourceCode, "D", natspec, true);
}
BOOST_AUTO_TEST_CASE(dev_default_inherit)
{
char const *sourceCode = R"(
interface ERC20 {
/// Transfer ``amount`` from ``msg.sender`` to ``to``.
/// Second line.
/// @author Programmer
/// @dev test
/// @param to address to transfer to
/// @param amount amount to transfer
function transfer(address to, uint amount) external returns (bool);
}
contract Middle is ERC20 {
function transfer(address to, uint amount) virtual override external returns (bool)
{
return false;
}
}
contract Token is Middle {
function transfer(address to, uint amount) override external returns (bool)
{
return false;
}
}
)";
char const *natspec = R"ABCDEF({
"methods":
{
"transfer(address,uint256)":
{
"author": "Programmer",
"details": "test",
"params":
{
"amount": "amount to transfer",
"to": "address to transfer to"
}
}
}
})ABCDEF";
checkNatspec(sourceCode, "ERC20", natspec, false);
checkNatspec(sourceCode, "Middle", natspec, false);
checkNatspec(sourceCode, "Token", natspec, false);
}
BOOST_AUTO_TEST_CASE(user_default_inherit)
{
char const *sourceCode = R"(
interface ERC20 {
/// Transfer ``amount`` from ``msg.sender`` to ``to``.
/// Second line.
/// @author Programmer
/// @dev test
/// @param to address to transfer to
/// @param amount amount to transfer
function transfer(address to, uint amount) external returns (bool);
}
contract Middle is ERC20 {
function transfer(address to, uint amount) virtual override external returns (bool)
{
return false;
}
}
contract Token is Middle {
function transfer(address to, uint amount) override external returns (bool)
{
return false;
}
}
)";
char const *natspec = R"ABCDEF({
"methods":
{
"transfer(address,uint256)":
{
"notice": "Transfer ``amount`` from ``msg.sender`` to ``to``. Second line."
}
}
})ABCDEF";
checkNatspec(sourceCode, "ERC20", natspec, true);
checkNatspec(sourceCode, "Middle", natspec, true);
checkNatspec(sourceCode, "Token", natspec, true);
}
BOOST_AUTO_TEST_CASE(dev_inherit_parameter_mismatch)
{
char const *sourceCode = R"(
interface ERC20 {
/// Transfer ``amount`` from ``msg.sender`` to ``to``.
/// @author Programmer
/// @dev test
/// @param to address to transfer to
/// @param amount amount to transfer
function transfer(address to, uint amount) external returns (bool);
}
contract Middle is ERC20 {
function transfer(address to, uint amount) override virtual external returns (bool) {
return false;
}
}
contract Token is Middle {
function transfer(address too, uint amount) override external returns (bool) {
return false;
}
}
)";
char const *natspec = R"ABCDEF({
"methods":
{
"transfer(address,uint256)":
{
"author": "Programmer",
"details": "test",
"params":
{
"amount": "amount to transfer",
"to": "address to transfer to"
}
}
}
})ABCDEF";
char const *natspec2 = R"ABCDEF({
"methods": { }
})ABCDEF";
checkNatspec(sourceCode, "ERC20", natspec, false);
checkNatspec(sourceCode, "Middle", natspec, false);
checkNatspec(sourceCode, "Token", natspec2, false);
}
BOOST_AUTO_TEST_CASE(user_inherit_parameter_mismatch)
{
char const *sourceCode = R"(
interface ERC20 {
/// Transfer ``amount`` from ``msg.sender`` to ``to``.
/// @author Programmer
/// @dev test
/// @param to address to transfer to
/// @param amount amount to transfer
function transfer(address to, uint amount) external returns (bool);
}
contract Middle is ERC20 {
function transfer(address to, uint amount) override virtual external returns (bool) {
return false;
}
}
contract Token is Middle {
function transfer(address too, uint amount) override external returns (bool) {
return false;
}
}
)";
char const *natspec = R"ABCDEF({
"methods":
{
"transfer(address,uint256)":
{
"notice": "Transfer ``amount`` from ``msg.sender`` to ``to``."
}
}
})ABCDEF";
char const *natspec2 = R"ABCDEF({
"methods": { }
})ABCDEF";
checkNatspec(sourceCode, "ERC20", natspec, true);
checkNatspec(sourceCode, "Middle", natspec, true);
checkNatspec(sourceCode, "Token", natspec2, true);
}
}
BOOST_AUTO_TEST_SUITE_END()
+2 -1
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);
@@ -0,0 +1,10 @@
contract C {
uint constant gwei = 1 gwei;
function f() public view returns(uint) { return gwei; }
}
// ====
// compileViaYul: also
// ----
// f() -> 1000000000
@@ -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;
}
// ----
@@ -0,0 +1,3 @@
contract C {
uint constant gwei = 1 gwei;
}
@@ -0,0 +1,4 @@
contract C {
uint immutable long___name___that___definitely___exceeds___the___thirty___two___byte___limit = 0;
}
// ----
@@ -0,0 +1,6 @@
contract C {
/// @author author
function iHaveAuthor() public pure {}
}
// ----
// Warning 9843: (17-35): Documentation tag @author is only allowed on contract definitions. It will be disallowed in 0.7.0.
@@ -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.
@@ -0,0 +1,17 @@
object "a" {
code {
setimmutable(
"long___name___that___definitely___exceeds___the___thirty___two___byte___limit",
0x1234567890123456789012345678901234567890
)
}
}
// ----
// Assembly:
// /* "source":152:194 */
// 0x1234567890123456789012345678901234567890
// /* "source":32:204 */
// assignImmutable("0x85a5b1db611c82c46f5fa18e39ae218397536256c451e5de155a86de843a9ad6")
// Bytecode: 73123456789012345678901234567890123456789050
// Opcodes: PUSH20 0x1234567890123456789012345678901234567890 POP
// SourceMappings: 152:42:0:-:0;32:172
@@ -0,0 +1,42 @@
object "a" {
code {
let addr := linkersymbol("contract/test.sol:L")
mstore(128, shl(227, 0x18530aaf))
let success := call(gas(), addr, 0, 128, 4, 128, 0)
}
}
// ----
// Assembly:
// linkerSymbol("f919ba91ac99f96129544b80b9516b27a80e376b9dc693819d0b18b7e0395612")
// /* "source":109:119 */
// 0x18530aaf
// /* "source":104:107 */
// 0xe3
// /* "source":100:120 */
// shl
// /* "source":95:98 */
// 0x80
// /* "source":88:121 */
// mstore
// /* "source":179:180 */
// 0x00
// /* "source":174:177 */
// 0x80
// /* "source":171:172 */
// 0x04
// /* "source":166:169 */
// 0x80
// /* "source":163:164 */
// 0x00
// /* "source":157:161 */
// dup6
// /* "source":150:155 */
// gas
// /* "source":145:181 */
// call
// /* "source":22:187 */
// pop
// pop
// Bytecode: 7300000000000000000000000000000000000000006318530aaf60e31b60805260006080600460806000855af15050
// Opcodes: PUSH20 0x0 PUSH4 0x18530AAF PUSH1 0xE3 SHL PUSH1 0x80 MSTORE PUSH1 0x0 PUSH1 0x80 PUSH1 0x4 PUSH1 0x80 PUSH1 0x0 DUP6 GAS CALL POP POP
// SourceMappings: :::-:0;109:10:0;104:3;100:20;95:3;88:33;179:1;174:3;171:1;166:3;163:1;157:4;150:5;145:36;22:165;
@@ -0,0 +1,16 @@
{
mstore(0, balance(address()))
mstore(0x20, selfbalance())
mstore(0x40, balance(div(mul(address(), 2), 2)))
mstore(0x60, balance(add(address(), 1)))
}
// ====
// EVMVersion: >=istanbul
// ----
// Trace:
// Memory dump:
// 0: 0000000000000000000000000000000000000000000000000000000022223333
// 20: 0000000000000000000000000000000000000000000000000000000022223333
// 40: 0000000000000000000000000000000000000000000000000000000022223333
// 60: 0000000000000000000000000000000000000000000000000000000022222222
// Storage dump:
@@ -0,0 +1,6 @@
{
let x := byte(31, "11112222333344445555666677778888")
}
// ====
// dialect: evm
// ----
@@ -0,0 +1,6 @@
{
let addr := linkersymbol("contract/library.sol:L")
}
// ====
// dialect: evm
// ----
@@ -0,0 +1,6 @@
{
let addr:u256 := linkersymbol("contract/library.sol:L")
}
// ====
// dialect: evmTyped
// ----
@@ -0,0 +1,7 @@
{
linkersymbol("contract/library.sol:L")
}
// ====
// dialect: ewasm
// ----
// DeclarationError 4619: (6-18): Function not found.
@@ -0,0 +1,8 @@
{
let library_name := "contract/library.sol:L"
let addr := linkersymbol(library_name)
}
// ====
// dialect: evm
// ----
// TypeError 9114: (67-79): Function expects direct literals as arguments.
@@ -0,0 +1,6 @@
{
let addr := loadimmutable("address")
}
// ====
// dialect: evm
// ----
@@ -0,0 +1,7 @@
{
setimmutable(loadimmutable("abc"), "abc")
}
// ====
// dialect: evm
// ----
// TypeError 9114: (6-18): Function expects direct literals as arguments.
@@ -0,0 +1,6 @@
{
setimmutable("address", 0x1234567890123456789012345678901234567890)
}
// ====
// dialect: evm
// ----
@@ -0,0 +1,7 @@
{
let name := "long___name___that___definitely___exceeds___the___thirty___two___byte___limit"
}
// ====
// dialect: evm
// ----
// TypeError 3069: (18-97): String literal too long (77 > 32)
@@ -0,0 +1,7 @@
{
let x := byte(40, "long___value__that___definitely___exceeds___the___thirty___two___byte___limit")
}
// ====
// dialect: evm
// ----
// TypeError 3069: (24-103): String literal too long (77 > 32)
@@ -0,0 +1,9 @@
{
setimmutable(
"long___name___that___definitely___exceeds___the___thirty___two___byte___limit",
0x1234567890123456789012345678901234567890
)
}
// ====
// dialect: evm
// ----
@@ -0,0 +1,6 @@
{
let addr := linkersymbol("contract/long___name___that___definitely___exceeds___the___thirty___two___byte___limit.sol:L")
}
// ====
// dialect: evm
// ----
+1
View File
@@ -8,6 +8,7 @@
" ether "
" finney "
" gasleft() "
" gwei "
" hours "
" minutes "
" msg.data "
@@ -182,7 +182,10 @@ u256 EVMInstructionInterpreter::eval(
case Instruction::ADDRESS:
return m_state.address;
case Instruction::BALANCE:
return m_state.balance;
if (arg[0] == m_state.address)
return m_state.selfbalance;
else
return m_state.balance;
case Instruction::SELFBALANCE:
return m_state.selfbalance;
case Instruction::ORIGIN: