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

This commit is contained in:
chriseth
2020-04-28 13:02:06 +02:00
195 changed files with 3903 additions and 1336 deletions
-15
View File
@@ -26,8 +26,6 @@
#include <libsolutil/JSON.h>
#include <libsolutil/AnsiColorized.h>
#include <boost/algorithm/string.hpp>
#include <fstream>
using namespace std;
@@ -85,16 +83,3 @@ void ABIJsonTest::printUpdatedExpectations(ostream& _stream, string const& _line
{
printIndented(_stream, m_obtainedResult, _linePrefix);
}
void ABIJsonTest::printIndented(ostream& _stream, string const& _output, string const& _linePrefix) const
{
stringstream output(_output);
string line;
while (getline(output, line))
if (line.empty())
// Avoid trailing spaces.
_stream << boost::trim_right_copy(_linePrefix) << endl;
else
_stream << _linePrefix << line << endl;
}
-2
View File
@@ -41,8 +41,6 @@ public:
void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const override;
private:
void printIndented(std::ostream& _stream, std::string const& _output, std::string const& _linePrefix = "") const;
std::string m_source;
std::string m_expectation;
std::string m_obtainedResult;
+87 -69
View File
@@ -1126,12 +1126,14 @@ BOOST_AUTO_TEST_CASE(log0)
}
}
)";
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
BOOST_CHECK_EQUAL(numLogTopics(0), 0);
ALSO_VIA_YUL(
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
BOOST_CHECK_EQUAL(numLogTopics(0), 0);
)
}
BOOST_AUTO_TEST_CASE(log1)
@@ -1143,13 +1145,15 @@ BOOST_AUTO_TEST_CASE(log1)
}
}
)";
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), h256(u256(2)));
ALSO_VIA_YUL(
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), h256(u256(2)));
)
}
BOOST_AUTO_TEST_CASE(log2)
@@ -1161,14 +1165,16 @@ BOOST_AUTO_TEST_CASE(log2)
}
}
)";
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
for (unsigned i = 0; i < 2; ++i)
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2)));
ALSO_VIA_YUL(
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
for (unsigned i = 0; i < 2; ++i)
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2)));
)
}
BOOST_AUTO_TEST_CASE(log3)
@@ -1180,14 +1186,16 @@ BOOST_AUTO_TEST_CASE(log3)
}
}
)";
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 3);
for (unsigned i = 0; i < 3; ++i)
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2)));
ALSO_VIA_YUL(
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 3);
for (unsigned i = 0; i < 3; ++i)
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2)));
)
}
BOOST_AUTO_TEST_CASE(log4)
@@ -1199,14 +1207,16 @@ BOOST_AUTO_TEST_CASE(log4)
}
}
)";
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 4);
for (unsigned i = 0; i < 4; ++i)
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2)));
ALSO_VIA_YUL(
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 4);
for (unsigned i = 0; i < 4; ++i)
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2)));
)
}
BOOST_AUTO_TEST_CASE(log_in_constructor)
@@ -1218,12 +1228,14 @@ BOOST_AUTO_TEST_CASE(log_in_constructor)
}
}
)";
compileAndRun(sourceCode);
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), h256(u256(2)));
ALSO_VIA_YUL(
compileAndRun(sourceCode);
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), h256(u256(2)));
)
}
BOOST_AUTO_TEST_CASE(selfdestruct)
@@ -1238,11 +1250,13 @@ BOOST_AUTO_TEST_CASE(selfdestruct)
}
)";
u256 amount(130);
compileAndRun(sourceCode, amount);
u160 address(23);
ABI_CHECK(callContractFunction("a(address)", address), bytes());
BOOST_CHECK(!addressHasCode(m_contractAddress));
BOOST_CHECK_EQUAL(balanceAt(address), amount);
ALSO_VIA_YUL(
compileAndRun(sourceCode, amount);
ABI_CHECK(callContractFunction("a(address)", address), bytes());
BOOST_CHECK(!addressHasCode(m_contractAddress));
BOOST_CHECK_EQUAL(balanceAt(address), amount);
)
}
BOOST_AUTO_TEST_CASE(keccak256)
@@ -1774,20 +1788,22 @@ BOOST_AUTO_TEST_CASE(event)
}
}
)";
compileAndRun(sourceCode);
u256 value(18);
u256 id(0x1234);
for (bool manually: {true, false})
{
callContractFunctionWithValue("deposit(bytes32,bool)", value, id, manually);
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(value)));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 3);
BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("Deposit(address,bytes32,uint256)")));
BOOST_CHECK_EQUAL(logTopic(0, 1), h256(m_sender, h256::AlignRight));
BOOST_CHECK_EQUAL(logTopic(0, 2), h256(id));
}
ALSO_VIA_YUL(
compileAndRun(sourceCode);
u256 value(18);
u256 id(0x1234);
for (bool manually: {true, false})
{
callContractFunctionWithValue("deposit(bytes32,bool)", value, id, manually);
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(value)));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 3);
BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("Deposit(address,bytes32,uint256)")));
BOOST_CHECK_EQUAL(logTopic(0, 1), h256(m_sender, h256::AlignRight));
BOOST_CHECK_EQUAL(logTopic(0, 2), h256(id));
}
)
}
BOOST_AUTO_TEST_CASE(event_emit)
@@ -1801,7 +1817,7 @@ BOOST_AUTO_TEST_CASE(event_emit)
}
)";
ALSO_VIA_YUL(
compileAndRun(sourceCode);
compileAndRun(sourceCode);
u256 value(18);
u256 id(0x1234);
callContractFunctionWithValue("deposit(bytes32)", value, id);
@@ -1850,13 +1866,15 @@ BOOST_AUTO_TEST_CASE(event_access_through_base_name_emit)
}
}
)";
compileAndRun(sourceCode);
callContractFunction("f()");
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK(logData(0).empty());
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("x()")));
ALSO_VIA_YUL(
compileAndRun(sourceCode);
callContractFunction("f()");
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK(logData(0).empty());
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("x()")));
);
}
BOOST_AUTO_TEST_CASE(events_with_same_name)
@@ -52,7 +52,7 @@ BOOST_AUTO_TEST_CASE(function_no_implementation)
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes();
ContractDefinition* contract = dynamic_cast<ContractDefinition*>(nodes[1].get());
BOOST_REQUIRE(contract);
BOOST_CHECK(!contract->annotation().unimplementedFunctions.empty());
BOOST_CHECK(!contract->annotation().unimplementedDeclarations.empty());
BOOST_CHECK(!contract->definedFunctions()[0]->isImplemented());
}
@@ -68,10 +68,10 @@ BOOST_AUTO_TEST_CASE(abstract_contract)
ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[1].get());
ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[2].get());
BOOST_REQUIRE(base);
BOOST_CHECK(!base->annotation().unimplementedFunctions.empty());
BOOST_CHECK(!base->annotation().unimplementedDeclarations.empty());
BOOST_CHECK(!base->definedFunctions()[0]->isImplemented());
BOOST_REQUIRE(derived);
BOOST_CHECK(derived->annotation().unimplementedFunctions.empty());
BOOST_CHECK(derived->annotation().unimplementedDeclarations.empty());
BOOST_CHECK(derived->definedFunctions()[0]->isImplemented());
}
@@ -87,9 +87,9 @@ BOOST_AUTO_TEST_CASE(abstract_contract_with_overload)
ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[1].get());
ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[2].get());
BOOST_REQUIRE(base);
BOOST_CHECK(!base->annotation().unimplementedFunctions.empty());
BOOST_CHECK(!base->annotation().unimplementedDeclarations.empty());
BOOST_REQUIRE(derived);
BOOST_CHECK(!derived->annotation().unimplementedFunctions.empty());
BOOST_CHECK(!derived->annotation().unimplementedDeclarations.empty());
}
BOOST_AUTO_TEST_CASE(implement_abstract_via_constructor)
@@ -104,7 +104,7 @@ BOOST_AUTO_TEST_CASE(implement_abstract_via_constructor)
BOOST_CHECK_EQUAL(nodes.size(), 3);
ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[2].get());
BOOST_REQUIRE(derived);
BOOST_CHECK(!derived->annotation().unimplementedFunctions.empty());
BOOST_CHECK(!derived->annotation().unimplementedDeclarations.empty());
}
BOOST_AUTO_TEST_CASE(function_canonical_signature)
+9 -1
View File
@@ -21,11 +21,15 @@
#include <string>
#include <boost/test/unit_test.hpp>
#include <libsolidity/interface/OptimiserSettings.h>
#include <libsolidity/interface/StandardCompiler.h>
#include <libsolidity/interface/Version.h>
#include <libsolutil/JSON.h>
#include <libsolutil/CommonData.h>
#include <test/Metadata.h>
#include <set>
using namespace std;
using namespace solidity::evmasm;
@@ -1058,8 +1062,12 @@ BOOST_AUTO_TEST_CASE(optimizer_settings_details_different)
BOOST_CHECK(optimizer["details"]["peephole"].asBool() == true);
BOOST_CHECK(optimizer["details"]["yul"].asBool() == true);
BOOST_CHECK(optimizer["details"]["yulDetails"].isObject());
BOOST_CHECK(optimizer["details"]["yulDetails"].getMemberNames() == vector<string>{"stackAllocation"});
BOOST_CHECK(
util::convertContainer<set<string>>(optimizer["details"]["yulDetails"].getMemberNames()) ==
(set<string>{"stackAllocation", "optimizerSteps"})
);
BOOST_CHECK(optimizer["details"]["yulDetails"]["stackAllocation"].asBool() == true);
BOOST_CHECK(optimizer["details"]["yulDetails"]["optimizerSteps"].asString() == OptimiserSettings::DefaultYulOptimiserSteps);
BOOST_CHECK_EQUAL(optimizer["details"].getMemberNames().size(), 8);
BOOST_CHECK(optimizer["runs"].asUInt() == 600);
}
@@ -17,5 +17,7 @@ contract B {
}
}
// ====
// compileViaYul: also
// ----
// f() -> 2, 3, 4, 5, 6, 1000, 1001, 1002, 1003, 1004
@@ -41,5 +41,7 @@ contract C {
}
}
// ====
// compileViaYul: also
// ----
// test() -> 5, 6, 7
@@ -3,6 +3,7 @@ contract C {
return sha256("");
}
}
// ====
// compileViaYul: also
// ----
// f() -> 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
@@ -0,0 +1,14 @@
contract A {
uint x = 42;
function f() public returns(uint256) {
return x;
}
}
contract B is A {
uint public y = f();
}
// ====
// compileViaYul: true
// ----
// constructor() ->
// y() -> 42
@@ -0,0 +1,17 @@
contract A {
uint x;
constructor() public {
x = 42;
}
function f() public returns(uint256) {
return x;
}
}
contract B is A {
uint public y = f();
}
// ====
// compileViaYul: true
// ----
// constructor() ->
// y() -> 42
@@ -0,0 +1,28 @@
contract A {
uint public i;
uint public k;
constructor(uint newI, uint newK) public {
i = newI;
k = newK;
}
}
abstract contract B is A {
uint public j;
constructor(uint newJ) public {
j = newJ;
}
}
contract C is A {
constructor(uint newI, uint newK) A(newI, newK) public {}
}
contract D is B, C {
constructor(uint newI, uint newK) B(newI) C(newI, newK + 1) public {}
}
// ====
// compileViaYul: also
// ----
// constructor(): 2, 0 ->
// i() -> 2
// j() -> 2
// k() -> 1
@@ -0,0 +1,18 @@
contract C {
uint public i;
uint public k;
constructor(uint newI, uint newK) public {
i = newI;
k = newK;
}
}
contract D is C {
constructor(uint newI, uint newK) C(newI, newK + 1) public {}
}
// ====
// compileViaYul: also
// ----
// constructor(): 2, 0 ->
// i() -> 2
// k() -> 1
@@ -0,0 +1,15 @@
contract C {
uint public i;
uint public k;
constructor(uint newI, uint newK) public {
i = newI;
k = newK;
}
}
contract D is C(2, 1) {}
// ====
// compileViaYul: also
// ----
// i() -> 2
// k() -> 1
@@ -34,6 +34,8 @@ contract Child is Base {
BaseBase.init(c, d);
}
}
// ====
// compileViaYul: also
// ----
// x() -> 0
// y() -> 0
@@ -18,6 +18,8 @@ contract Child is Base {
Base.init(c, d);
}
}
// ====
// compileViaYul: also
// ----
// x() -> 0
// y() -> 0
@@ -0,0 +1,19 @@
contract test {
bool public flag = false;
function f0() public {
flag = true;
}
function f() public returns (bool) {
function() internal x = f0;
x();
return flag;
}
}
// ====
// compileViaYul: also
// ----
// f() -> true
// flag() -> true
@@ -0,0 +1,15 @@
contract C {
uint public i;
constructor() public {
i = 2;
}
}
contract D {
function f() public returns (uint r) {
return new C().i();
}
}
// ====
// compileViaYul: also
// ----
// f() -> 2
@@ -0,0 +1,20 @@
contract C {
uint public i;
constructor(uint newI) public {
i = newI;
}
}
contract D {
C c;
constructor(uint v) public {
c = new C(v);
}
function f() public returns (uint r) {
return c.i();
}
}
// ====
// compileViaYul: also
// ----
// constructor(): 2 ->
// f() -> 2
@@ -0,0 +1,21 @@
contract C {
uint public i;
constructor(uint newI) public {
i = newI;
}
}
contract D {
C c;
constructor(uint v) public {
c = new C{salt: "abc"}(v);
}
function f() public returns (uint r) {
return c.i();
}
}
// ====
// EVMVersion: >=constantinople
// compileViaYul: also
// ----
// constructor(): 2 ->
// f() -> 2
@@ -36,8 +36,10 @@ contract test {
}
}
// ====
// compileViaYul: also
// ----
// constructor(), 20 wei ->
// sendAmount(uint256): 5 -> 5
// outOfGas() -> FAILURE # call to helper should not succeed but amount should be transferred anyway #
// checkState() -> false, 15
// checkState() -> false, 15
@@ -0,0 +1,36 @@
interface ERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceID The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
interface Simpson {
function is2D() external returns (bool);
function skinColor() external returns (string memory);
}
contract Homer is ERC165, Simpson {
function supportsInterface(bytes4 interfaceID) external view override returns (bool) {
return
interfaceID == this.supportsInterface.selector || // ERC165
interfaceID == this.is2D.selector ^ this.skinColor.selector; // Simpson
}
function is2D() external override returns (bool) {
return true;
}
function skinColor() external override returns (string memory) {
return "yellow";
}
}
// ----
// supportsInterface(bytes4): left(0x01ffc9a0) -> false
// supportsInterface(bytes4): left(0x01ffc9a7) -> true
// supportsInterface(bytes4): left(0x73b6b492) -> true
// supportsInterface(bytes4): left(0x70b6b492) -> false
@@ -0,0 +1,36 @@
interface ERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceID The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
interface Simpson {
function is2D() external returns (bool);
function skinColor() external returns (string memory);
}
contract Homer is ERC165, Simpson {
function supportsInterface(bytes4 interfaceID) external view override returns (bool) {
return
interfaceID == type(ERC165).interfaceId ||
interfaceID == type(Simpson).interfaceId;
}
function is2D() external override returns (bool) {
return true;
}
function skinColor() external override returns (string memory) {
return "yellow";
}
}
// ----
// supportsInterface(bytes4): left(0x01ffc9a0) -> false
// supportsInterface(bytes4): left(0x01ffc9a7) -> true
// supportsInterface(bytes4): left(0x73b6b492) -> true
// supportsInterface(bytes4): left(0x70b6b492) -> false
@@ -0,0 +1,21 @@
interface HelloWorld {
function hello() external pure;
function world(int) external pure;
}
interface HelloWorldWithEvent {
event Event();
function hello() external pure;
function world(int) external pure;
}
contract Test {
bytes4 public hello_world = type(HelloWorld).interfaceId;
bytes4 public hello_world_with_event = type(HelloWorldWithEvent).interfaceId;
}
// ====
// compileViaYul: also
// ----
// hello_world() -> left(0xc6be8b58)
// hello_world_with_event() -> left(0xc6be8b58)
@@ -0,0 +1,67 @@
interface HelloWorld {
function hello() external pure;
function world(int) external pure;
}
interface HelloWorldDerived is HelloWorld {
function other() external pure;
}
interface ERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceID The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
contract Test {
bytes4 public ghello_world_interfaceId = type(HelloWorld).interfaceId;
bytes4 public ERC165_interfaceId = type(ERC165).interfaceId;
function hello() public pure returns (bytes4 data){
HelloWorld i;
return i.hello.selector;
}
function world() public pure returns (bytes4 data){
HelloWorld i;
return i.world.selector;
}
function hello_world() public pure returns (bytes4 data){
// HelloWorld i;
// return i.hello.selector ^ i.world.selector; // = 0xc6be8b58
return 0xc6be8b58;
}
function hello_world_interfaceId() public pure returns (bytes4 data){
return type(HelloWorld).interfaceId;
}
function other() public pure returns (bytes4 data){
HelloWorldDerived i;
return i.other.selector;
}
function hello_world_derived_interfaceId() public pure returns (bytes4 data){
return type(HelloWorldDerived).interfaceId;
}
}
// ====
// compileViaYul: also
// ----
// hello() -> left(0x19ff1d21)
// world() -> left(0xdf419679)
//
// ERC165_interfaceId() -> left(0x01ffc9a7)
//
// hello_world() -> left(0xc6be8b58)
// hello_world_interfaceId() -> left(0xc6be8b58)
// ghello_world_interfaceId() -> left(0xc6be8b58)
//
// other() -> left(0x85295877)
// hello_world_derived_interfaceId() -> left(0x85295877)
@@ -0,0 +1,47 @@
interface ERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceID The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
contract ERC165MappingImplementation is ERC165 {
/// @dev You must not set element 0xffffffff to true
mapping(bytes4 => bool) internal supportedInterfaces;
constructor() internal {
supportedInterfaces[this.supportsInterface.selector] = true;
}
function supportsInterface(bytes4 interfaceID) external view override returns (bool) {
return supportedInterfaces[interfaceID];
}
}
interface Simpson {
function is2D() external returns (bool);
function skinColor() external returns (string memory);
}
contract Lisa is ERC165MappingImplementation, Simpson {
constructor() public {
supportedInterfaces[this.is2D.selector ^ this.skinColor.selector] = true;
}
function is2D() external override returns (bool) {
return true;
}
function skinColor() external override returns (string memory) {
return "yellow";
}
}
// ----
// supportsInterface(bytes4): left(0x01ffc9a0) -> false
// supportsInterface(bytes4): left(0x01ffc9a7) -> true
// supportsInterface(bytes4): left(0x73b6b492) -> true
// supportsInterface(bytes4): left(0x70b6b492) -> false
@@ -0,0 +1,47 @@
interface ERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceID The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
contract ERC165MappingImplementation is ERC165 {
/// @dev You must not set element 0xffffffff to true
mapping(bytes4 => bool) internal supportedInterfaces;
constructor() internal {
supportedInterfaces[this.supportsInterface.selector] = true;
}
function supportsInterface(bytes4 interfaceID) external view override returns (bool) {
return supportedInterfaces[interfaceID];
}
}
interface Simpson {
function is2D() external returns (bool);
function skinColor() external returns (string memory);
}
contract Lisa is ERC165MappingImplementation, Simpson {
constructor() public {
supportedInterfaces[type(Simpson).interfaceId] = true;
}
function is2D() external override returns (bool) {
return true;
}
function skinColor() external override returns (string memory) {
return "yellow";
}
}
// ----
// supportsInterface(bytes4): left(0x01ffc9a0) -> false
// supportsInterface(bytes4): left(0x01ffc9a7) -> true
// supportsInterface(bytes4): left(0x73b6b492) -> true
// supportsInterface(bytes4): left(0x70b6b492) -> false
@@ -33,6 +33,8 @@ contract C {
}
}
// ====
// compileViaYul: also
// ----
// convertParent() -> 1
// convertSubA() -> 1, 2
@@ -19,6 +19,8 @@ contract D {
}
}
// ====
// compileViaYul: also
// ----
// f() -> 1
// g() -> 5
@@ -21,5 +21,7 @@ contract B {
}
}
// ====
// compileViaYul: also
// ----
// g() -> 42
@@ -21,5 +21,7 @@ contract B {
}
}
// ====
// compileViaYul: also
// ----
// g() -> 42
@@ -15,5 +15,7 @@ contract B {
}
}
// ====
// compileViaYul: also
// ----
// g() -> 1
@@ -17,5 +17,7 @@ contract C {
}
}
// ====
// compileViaYul: also
// ----
// f() -> 2
@@ -22,5 +22,7 @@ contract C {
}
}
// ====
// compileViaYul: also
// ----
// f() -> 2
@@ -6,6 +6,8 @@ contract C {
return L.f(v);
}
}
// ====
// compileViaYul: also
// ----
// g(uint256): 1 -> 1
// g(uint256): 2 -> 4
@@ -0,0 +1,17 @@
abstract contract A {
function f() public mod returns (bool r) {
return true;
}
modifier mod virtual;
}
contract C is A {
modifier mod override {
if (false) _;
}
}
// ----
// f() -> false
@@ -0,0 +1,14 @@
contract A {
uint public x = 0;
uint y = f();
function f() public returns (uint256) {
++x;
return 42;
}
}
contract B is A {
}
// ====
// compileViaYul: also
// ----
// x() -> 1
@@ -0,0 +1,18 @@
contract A {
uint public x = 0;
uint y = f();
function f() public returns (uint256) {
++x;
return 42;
}
}
contract B is A {
uint public z;
constructor() public {
z = x;
}
}
// ====
// compileViaYul: also
// ----
// z() -> 1
@@ -0,0 +1,29 @@
contract A {
uint public a = 42;
uint public b;
uint public c;
constructor(uint x) public {
b = a;
a = x;
}
function f(uint x) public returns (uint256) { c = x * 3; return 23; }
}
contract B is A {
uint public d = f(a);
uint public e = b;
uint public b_a;
uint public b_b;
uint public b_c;
constructor() public A(17) { b_a = a; b_b = b; b_c = c; }
}
// ====
// compileViaYul: true
// ----
// a() -> 17
// b() -> 42
// c() -> 51
// b_a() -> 17
// b_b() -> 42
// b_c() -> 51
// d() -> 23
// e() -> 42
@@ -16,5 +16,7 @@ contract C {
}
}
// ====
// compileViaYul: also
// ----
// constructor() ->
@@ -23,6 +23,8 @@ contract C {
}
}
// ====
// compileViaYul: also
// ----
// test() -> 9, 7
// t2() -> 9
@@ -15,6 +15,8 @@ contract C {
}
}
// ====
// compileViaYul: also
// ----
// f() -> true
// g() -> true
@@ -15,6 +15,8 @@ contract D {
}
}
// ====
// compileViaYul: also
// ----
// constructor(), 27 wei ->
// f() -> 27
@@ -32,6 +32,7 @@ contract D {
}
}
// ====
// compileViaYul: also
// EVMVersion: >=byzantium
// ----
// f() -> 0x1 # This should work, next should throw #
@@ -34,6 +34,8 @@ contract D {
}
}
// ====
// compileViaYul: also
// ----
// f() -> 3
// g() -> 8
@@ -0,0 +1,13 @@
pragma experimental SMTChecker;
contract C {
function f(bytes calldata x) external pure {
x[:18726387213];
x[18726387213:];
x[18726387213:111111111111111111];
}
}
// ----
// Warning: (94-109): Assertion checker does not yet implement this expression.
// Warning: (113-128): Assertion checker does not yet implement this expression.
// Warning: (132-165): Assertion checker does not yet implement this expression.
@@ -0,0 +1,13 @@
pragma experimental SMTChecker;
contract C {
function f(bytes calldata x) external pure {
bytes(x[:18726387213]);
bytes(x[18726387213:]);
bytes(x[18726387213:111111111111111111]);
}
}
// ----
// Warning: (100-115): Assertion checker does not yet implement this expression.
// Warning: (126-141): Assertion checker does not yet implement this expression.
// Warning: (152-185): Assertion checker does not yet implement this expression.
@@ -0,0 +1,14 @@
abstract contract A { modifier mod(uint a) virtual;}
contract B is A { modifier mod(uint a) override { _; } }
abstract contract C {
modifier m virtual;
function f() m public {
}
}
contract D is C {
modifier m override {
_;
}
}
@@ -0,0 +1,10 @@
contract A {modifier m virtual;}
abstract contract B {modifier m virtual;}
contract C is B { }
abstract contract D {modifier m;}
// ----
// TypeError: (0-32): Contract "A" should be marked as abstract.
// TypeError: (76-95): Contract "C" should be marked as abstract.
// TypeError: (118-129): Modifiers without implementation must be marked virtual.
@@ -0,0 +1,31 @@
abstract contract A {
function foo() public virtual;
function foo(uint x) virtual public returns(uint);
modifier mod() virtual;
}
contract B is A {
function foo(uint x) override public returns(uint) {return x;}
modifier mod() override { _; }
}
contract C is A {
function foo() public override {}
modifier mod() override { _; }
}
contract D is A {
function foo() public override {}
function foo(uint x) override public returns(uint) {return x;}
}
/* No errors */
contract E is A {
function foo() public override {}
function foo(uint x) override public returns(uint) {return x;}
modifier mod() override { _;}
}
// ----
// TypeError: (137-254): Contract "B" should be marked as abstract.
// TypeError: (256-344): Contract "C" should be marked as abstract.
// TypeError: (346-466): Contract "D" should be marked as abstract.
@@ -0,0 +1,29 @@
contract C {
function f0() public { (()) = 2; }
function f1() public pure { (()) = (); }
//#8711
function f2() internal pure returns (uint, uint) { return () = f2(); }
//#8277
function f3()public{return()=();}
//#8277
function f4 ( bytes32 hash , uint8 v , bytes32 r , bytes32 s , uint blockExpired , bytes32 salt ) public returns ( address ) {
require ( ( ( ) ) |= keccak256 ( abi . encodePacked ( blockExpired , salt ) ) ) ;
return ecrecover ( hash , v , r , s ) ;
}
}
// ----
// TypeError: (41-43): Empty tuple on the left hand side.
// TypeError: (47-48): Type int_const 2 is not implicitly convertible to expected type tuple().
// TypeError: (86-88): Empty tuple on the left hand side.
// TypeError: (173-175): Empty tuple on the left hand side.
// TypeError: (178-182): Type tuple(uint256,uint256) is not implicitly convertible to expected type tuple().
// TypeError: (166-182): Different number of arguments in return statement than in returns declaration.
// TypeError: (229-231): Empty tuple on the left hand side.
// TypeError: (401-404): Empty tuple on the left hand side.
// TypeError: (399-466): Compound assignment is not allowed for tuple types.
// TypeError: (410-466): Type bytes32 is not implicitly convertible to expected type tuple().
// TypeError: (389-396): No matching declaration found after argument-dependent lookup.