Use evmone for testing.

This commit is contained in:
chriseth 2019-06-26 18:42:24 +02:00
parent 7401fbabd9
commit 3dec3af638
16 changed files with 462 additions and 950 deletions

View File

@ -33,6 +33,7 @@
#include <string>
#include <set>
#include <functional>
#include <utility>
/// Operators need to stay in the global namespace.

View File

@ -95,19 +95,19 @@ void CommonOptions::validate() const
"Invalid test path specified."
);
if (!disableIPC)
{
assertThrow(
!ipcPath.empty(),
ConfigException,
"No ipc path specified. The --ipcpath argument must not be empty when given."
);
assertThrow(
fs::exists(ipcPath),
ConfigException,
"Invalid ipc path specified."
);
}
// if (!disableIPC)
// {
// assertThrow(
// !ipcPath.empty(),
// ConfigException,
// "No ipc path specified. The --ipcpath argument must not be empty when given."
// );
// assertThrow(
// fs::exists(ipcPath),
// ConfigException,
// "Invalid ipc path specified."
// );
// }
}
bool CommonOptions::parse(int argc, char const* const* argv)

View File

@ -33,9 +33,52 @@ using namespace std;
using namespace dev;
using namespace dev::test;
EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::vm& _vmInstance):
m_vm(_vmInstance)
namespace
{
evmc::vm& getVM()
{
static unique_ptr<evmc::vm> theVM;
if (!theVM)
{
// TODO make this an option
for (auto path: {
"deps/lib/libevmone.so",
"../deps/lib/libevmone.so",
"/usr/lib/libevmone.so",
"/usr/local/lib/libevmone.so",
// TODO the circleci docker image somehow only has the .a file
"/usr/lib/libevmone.a"
})
{
evmc_loader_error_code errorCode = {};
evmc_instance* vm = evmc_load_and_create(path, &errorCode);
if (!vm || errorCode != EVMC_LOADER_SUCCESS)
continue;
theVM = make_unique<evmc::vm>(vm);
break;
}
if (!theVM)
{
cerr << "Unable to find library libevmone.so" << endl;
assertThrow(false, Exception, "");
}
}
return *theVM;
}
}
EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::vm* _vm):
m_vm(_vm)
{
if (!m_vm)
{
cerr << "Unable to find library libevmone.so" << endl;
assertThrow(false, Exception, "");
}
if (_evmVersion == langutil::EVMVersion::homestead())
m_evmVersion = EVMC_HOMESTEAD;
else if (_evmVersion == langutil::EVMVersion::tangerineWhistle())
@ -123,7 +166,7 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
evmc_address currentAddress = m_currentAddress;
m_currentAddress = message.destination;
evmc::result result = m_vm.execute(*this, m_evmVersion, message, code.data(), code.size());
evmc::result result = m_vm->execute(*this, m_evmVersion, message, code.data(), code.size());
m_currentAddress = currentAddress;
if (result.status_code != EVMC_SUCCESS)

View File

@ -38,7 +38,7 @@ using Address = h160;
class EVMHost: public evmc::Host
{
public:
explicit EVMHost(langutil::EVMVersion _evmVersion, evmc::vm& _vmInstance);
explicit EVMHost(langutil::EVMVersion _evmVersion, evmc::vm* _vm = getVM());
struct Account
{
@ -147,11 +147,6 @@ public:
size_t _topicsCount
) noexcept;
evmc_revision getRevision()
{
return m_evmVersion;
}
static Address convertFromEVMC(evmc_address const& _addr);
static evmc_address convertToEVMC(Address const& _addr);
static h256 convertFromEVMC(evmc_bytes32 const& _data);
@ -165,7 +160,7 @@ public:
private:
evmc::result precompileSha256(evmc_message const& _message) noexcept;
evmc::vm& m_vm;
evmc::vm* m_vm = nullptr;
evmc_revision m_evmVersion;
};

View File

@ -22,57 +22,44 @@
#include <test/ExecutionFramework.h>
#include <libdevcore/CommonIO.h>
#include <boost/test/framework.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <test/EVMHost.h>
#include <test/evmc/evmc.hpp>
#include <test/evmc/loader.h>
#include <test/evmc/helpers.hpp>
#include <cstdlib>
#include <libdevcore/CommonIO.h>
#include <chrono>
#include <thread>
#include <boost/test/framework.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <cstdlib>
using namespace std;
using namespace dev;
using namespace dev::test;
namespace // anonymous
{
h256 const EmptyTrie("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421");
string getIPCSocketPath()
{
string ipcPath = dev::test::Options::get().ipcPath.string();
if (ipcPath.empty())
BOOST_FAIL("ERROR: ipcPath not set! (use --ipcpath <path> or the environment variable ETH_TEST_IPC)");
return ipcPath;
}
}
ExecutionFramework::ExecutionFramework():
ExecutionFramework(getIPCSocketPath(), dev::test::Options::get().evmVersion())
ExecutionFramework(dev::test::Options::get().evmVersion())
{
}
ExecutionFramework::ExecutionFramework(string const& _ipcPath, langutil::EVMVersion _evmVersion):
m_rpc(RPCSession::instance(_ipcPath)),
ExecutionFramework::ExecutionFramework(langutil::EVMVersion _evmVersion):
m_evmVersion(_evmVersion),
m_optimiserSettings(solidity::OptimiserSettings::minimal()),
m_showMessages(dev::test::Options::get().showMessages),
m_sender(m_rpc.account(0))
m_evmHost(make_shared<EVMHost>(m_evmVersion))
{
if (dev::test::Options::get().optimizeYul)
m_optimiserSettings = solidity::OptimiserSettings::full();
else if (dev::test::Options::get().optimize)
m_optimiserSettings = solidity::OptimiserSettings::standard();
m_rpc.test_rewindToBlock(0);
m_evmHost->reset();
for (size_t i = 0; i < 10; i++)
m_evmHost->m_state.accounts[EVMHost::convertToEVMC(account(i))].balance =
EVMHost::convertToEVMC(u256(1) << 100);
}
std::pair<bool, string> ExecutionFramework::compareAndCreateMessage(
@ -103,22 +90,28 @@ std::pair<bool, string> ExecutionFramework::compareAndCreateMessage(
u256 ExecutionFramework::gasLimit() const
{
auto latestBlock = m_rpc.eth_getBlockByNumber("latest", false);
return u256(latestBlock["gasLimit"].asString());
return {m_evmHost->get_tx_context().block_gas_limit};
}
u256 ExecutionFramework::gasPrice() const
{
return u256(m_rpc.eth_gasPrice());
return {EVMHost::convertFromEVMC(m_evmHost->get_tx_context().tx_gas_price)};
}
u256 ExecutionFramework::blockHash(u256 const& _blockNumber) const
u256 ExecutionFramework::blockHash(u256 const& _number) const
{
return u256(m_rpc.eth_getBlockByNumber(toHex(_blockNumber, HexPrefix::Add), false)["hash"].asString());
return {EVMHost::convertFromEVMC(m_evmHost->get_block_hash(uint64_t(_number & numeric_limits<uint64_t>::max())))};
}
u256 ExecutionFramework::blockNumber() const
{
return m_evmHost->m_state.blockNumber;
}
void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 const& _value)
{
m_evmHost->newBlock();
if (m_showMessages)
{
if (_isCreation)
@ -129,104 +122,121 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256
cout << " value: " << _value << endl;
cout << " in: " << toHex(_data) << endl;
}
RPCSession::TransactionData d;
d.data = "0x" + toHex(_data);
d.from = "0x" + toString(m_sender);
d.gas = toHex(m_gas, HexPrefix::Add);
d.gasPrice = toHex(m_gasPrice, HexPrefix::Add);
d.value = toHex(_value, HexPrefix::Add);
if (!_isCreation)
{
d.to = dev::toString(m_contractAddress);
BOOST_REQUIRE(m_rpc.eth_getCode(d.to, "pending").size() > 2);
// Use eth_call to get the output
m_output = fromHex(m_rpc.eth_call(d, "pending"), WhenError::Throw);
}
string txHash = m_rpc.eth_sendTransaction(d);
m_rpc.rpcCall("eth_flush");
m_rpc.test_mineBlocks(1);
RPCSession::TransactionReceipt receipt(m_rpc.eth_getTransactionReceipt(txHash));
m_blockNumber = u256(receipt.blockNumber);
evmc_message message = {};
message.input_data = _data.data();
message.input_size = _data.size();
message.sender = EVMHost::convertToEVMC(m_sender);
message.value = EVMHost::convertToEVMC(_value);
if (_isCreation)
{
m_contractAddress = Address(receipt.contractAddress);
BOOST_REQUIRE(m_contractAddress);
string code = m_rpc.eth_getCode(receipt.contractAddress, "latest");
m_output = fromHex(code, WhenError::Throw);
message.kind = EVMC_CREATE;
message.destination = EVMHost::convertToEVMC(Address{});
}
else
{
message.kind = EVMC_CALL;
message.destination = EVMHost::convertToEVMC(m_contractAddress);
}
message.gas = m_gas.convert_to<int64_t>();
evmc::result result = m_evmHost->call(message);
m_output = bytes(result.output_data, result.output_data + result.output_size);
if (_isCreation)
m_contractAddress = EVMHost::convertFromEVMC(result.create_address);
m_gasUsed = m_gas - result.gas_left;
m_transactionSuccessful = (result.status_code == EVMC_SUCCESS);
if (m_showMessages)
{
cout << " out: " << toHex(m_output) << endl;
cout << " tx hash: " << txHash << endl;
cout << " result: " << size_t(result.status_code) << endl;
cout << " gas used: " << m_gasUsed.str() << endl;
}
m_gasUsed = u256(receipt.gasUsed);
m_logs.clear();
for (auto const& log: receipt.logEntries)
{
LogEntry entry;
entry.address = Address(log.address);
for (auto const& topic: log.topics)
entry.topics.push_back(h256(topic));
entry.data = fromHex(log.data, WhenError::Throw);
m_logs.push_back(entry);
}
if (!receipt.status.empty())
m_transactionSuccessful = (receipt.status == "1");
else
m_transactionSuccessful = (m_gas != m_gasUsed);
}
void ExecutionFramework::sendEther(Address const& _to, u256 const& _value)
void ExecutionFramework::sendEther(Address const& _addr, u256 const& _amount)
{
RPCSession::TransactionData d;
d.data = "0x";
d.from = "0x" + toString(m_sender);
d.gas = toHex(m_gas, HexPrefix::Add);
d.gasPrice = toHex(m_gasPrice, HexPrefix::Add);
d.value = toHex(_value, HexPrefix::Add);
d.to = dev::toString(_to);
m_evmHost->newBlock();
string txHash = m_rpc.eth_sendTransaction(d);
m_rpc.test_mineBlocks(1);
if (m_showMessages)
{
cout << "SEND_ETHER " << m_sender.hex() << " -> " << _addr.hex() << ":" << endl;
if (_amount > 0)
cout << " value: " << _amount << endl;
}
evmc_message message = {};
message.sender = EVMHost::convertToEVMC(m_sender);
message.value = EVMHost::convertToEVMC(_amount);
message.kind = EVMC_CALL;
message.destination = EVMHost::convertToEVMC(_addr);
message.gas = m_gas.convert_to<int64_t>();
m_evmHost->call(message);
}
size_t ExecutionFramework::currentTimestamp()
{
auto latestBlock = m_rpc.eth_getBlockByNumber("latest", false);
return size_t(u256(latestBlock.get("timestamp", "invalid").asString()));
return m_evmHost->get_tx_context().block_timestamp;
}
size_t ExecutionFramework::blockTimestamp(u256 _number)
size_t ExecutionFramework::blockTimestamp(u256 _block)
{
auto latestBlock = m_rpc.eth_getBlockByNumber(toString(_number), false);
return size_t(u256(latestBlock.get("timestamp", "invalid").asString()));
if (_block > blockNumber())
return 0;
else
return size_t((currentTimestamp() / blockNumber()) * _block);
}
Address ExecutionFramework::account(size_t _i)
Address ExecutionFramework::account(size_t _idx)
{
return Address(m_rpc.accountCreateIfNotExists(_i));
return Address(h256(u256{"0x1212121212121212121212121212120000000012"} + _idx * 0x1000), Address::AlignRight);
}
bool ExecutionFramework::addressHasCode(Address const& _addr)
{
string code = m_rpc.eth_getCode(toString(_addr), "latest");
return !code.empty() && code != "0x";
return m_evmHost->get_code_size(EVMHost::convertToEVMC(_addr)) != 0;
}
size_t ExecutionFramework::numLogs() const
{
return m_evmHost->m_state.logs.size();
}
size_t ExecutionFramework::numLogTopics(size_t _logIdx) const
{
return m_evmHost->m_state.logs.at(_logIdx).topics.size();
}
h256 ExecutionFramework::logTopic(size_t _logIdx, size_t _topicIdx) const
{
return m_evmHost->m_state.logs.at(_logIdx).topics.at(_topicIdx);
}
Address ExecutionFramework::logAddress(size_t _logIdx) const
{
return m_evmHost->m_state.logs.at(_logIdx).address;
}
bytes const& ExecutionFramework::logData(size_t _logIdx) const
{
return m_evmHost->m_state.logs.at(_logIdx).data;
}
u256 ExecutionFramework::balanceAt(Address const& _addr)
{
return u256(m_rpc.eth_getBalance(toString(_addr), "latest"));
return u256(EVMHost::convertFromEVMC(m_evmHost->get_balance(EVMHost::convertToEVMC(_addr))));
}
bool ExecutionFramework::storageEmpty(Address const& _addr)
{
h256 root(m_rpc.eth_getStorageRoot(toString(_addr), "latest"));
BOOST_CHECK(root);
return root == EmptyTrie;
if (EVMHost::Account const* acc = m_evmHost->account(EVMHost::convertToEVMC(_addr)))
{
for (auto const& entry: acc->storage)
if (!(entry.second == evmc_bytes32{}))
return false;
}
return true;
}

View File

@ -23,7 +23,6 @@
#pragma once
#include <test/Options.h>
#include <test/RPCSession.h>
#include <libsolidity/interface/OptimiserSettings.h>
@ -38,24 +37,26 @@ namespace dev
{
namespace test
{
using rational = boost::rational<dev::bigint>;
/// An Ethereum address: 20 bytes.
/// @NOTE This is not endian-specific; it's just a bunch of bytes.
using Address = h160;
class EVMHost;
// 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 szabo = shannon * 1000;
static const u256 finney = szabo * 1000;
static const u256 ether = finney * 1000;
using rational = boost::rational<dev::bigint>;
/// An Ethereum address: 20 bytes.
/// @NOTE This is not endian-specific; it's just a bunch of bytes.
using Address = 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 szabo = shannon * 1000;
static const u256 finney = szabo * 1000;
static const u256 ether = finney * 1000;
class ExecutionFramework
{
public:
ExecutionFramework();
explicit ExecutionFramework(std::string const& _ipcPath, langutil::EVMVersion _evmVersion);
explicit ExecutionFramework(langutil::EVMVersion _evmVersion);
virtual ~ExecutionFramework() = default;
virtual bytes const& compileAndRunWithoutCheck(
@ -200,9 +201,7 @@ public:
u256 gasLimit() const;
u256 gasPrice() const;
u256 blockHash(u256 const& _blockNumber) const;
u256 const& blockNumber() const {
return m_blockNumber;
}
u256 blockNumber() const;
template<typename Range>
static bytes encodeArray(bool _dynamicallySized, bool _dynamicallyEncoded, Range const& _elements)
@ -257,26 +256,23 @@ protected:
bool storageEmpty(Address const& _addr);
bool addressHasCode(Address const& _addr);
RPCSession& m_rpc;
struct LogEntry
{
Address address;
std::vector<h256> topics;
bytes data;
};
size_t numLogs() const;
size_t numLogTopics(size_t _logIdx) const;
h256 logTopic(size_t _logIdx, size_t _topicIdx) const;
Address logAddress(size_t _logIdx) const;
bytes const& logData(size_t _logIdx) const;
langutil::EVMVersion m_evmVersion;
solidity::OptimiserSettings m_optimiserSettings = solidity::OptimiserSettings::minimal();
bool m_showMessages = false;
std::shared_ptr<EVMHost> m_evmHost;
bool m_transactionSuccessful = true;
Address m_sender;
Address m_sender = account(0);
Address m_contractAddress;
u256 m_blockNumber;
u256 const m_gasPrice = 100 * szabo;
u256 const m_gas = 100000000;
bytes m_output;
std::vector<LogEntry> m_logs;
u256 m_gasUsed;
};

View File

@ -1,396 +0,0 @@
/*
This file is part of solidity.
solidity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
solidity is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with solidity. If not, see <http://www.gnu.org/licenses/>.
The Implementation originally from https://msdn.microsoft.com/en-us/library/windows/desktop/aa365592(v=vs.85).aspx
*/
/// @file RPCSession.cpp
/// Low-level IPC communication between the test framework and the Ethereum node.
#include <test/RPCSession.h>
#include <test/Options.h>
#include <liblangutil/EVMVersion.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/JSON.h>
#include <string>
#include <stdio.h>
#include <thread>
#include <chrono>
using namespace std;
using namespace dev;
IPCSocket::IPCSocket(string const& _path): m_path(_path)
{
#if defined(_WIN32)
m_socket = CreateFile(
m_path.c_str(), // pipe name
GENERIC_READ | // read and write access
GENERIC_WRITE,
0, // no sharing
NULL, // default security attribute
OPEN_EXISTING, // opens existing pipe
0, // default attributes
NULL); // no template file
if (m_socket == INVALID_HANDLE_VALUE)
BOOST_FAIL("Error creating IPC socket object!");
#else
if (_path.length() >= sizeof(sockaddr_un::sun_path))
BOOST_FAIL("Error opening IPC: socket path is too long!");
struct sockaddr_un saun;
memset(&saun, 0, sizeof(sockaddr_un));
saun.sun_family = AF_UNIX;
strcpy(saun.sun_path, _path.c_str());
// http://idletechnology.blogspot.ca/2011/12/unix-domain-sockets-on-osx.html
//
// SUN_LEN() might be optimal, but it seemingly affects the portability,
// with at least Android missing this macro. Just using the sizeof() for
// structure seemingly works, and would only have the side-effect of
// sending larger-than-required packets over the socket. Given that this
// code is only used for unit-tests, that approach seems simpler.
#if defined(__APPLE__)
saun.sun_len = sizeof(struct sockaddr_un);
#endif // defined(__APPLE__)
if ((m_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
BOOST_FAIL("Error creating IPC socket object");
if (connect(m_socket, reinterpret_cast<struct sockaddr const*>(&saun), sizeof(struct sockaddr_un)) < 0)
{
close(m_socket);
BOOST_FAIL("Error connecting to IPC socket: " << _path);
}
#endif
}
string IPCSocket::sendRequest(string const& _req)
{
#if defined(_WIN32)
// Write to the pipe.
DWORD cbWritten;
BOOL fSuccess = WriteFile(
m_socket, // pipe handle
_req.c_str(), // message
_req.size(), // message length
&cbWritten, // bytes written
NULL); // not overlapped
if (!fSuccess || (_req.size() != cbWritten))
BOOST_FAIL("WriteFile to pipe failed");
// Read from the pipe.
DWORD cbRead;
fSuccess = ReadFile(
m_socket, // pipe handle
m_readBuf, // buffer to receive reply
sizeof(m_readBuf), // size of buffer
&cbRead, // number of bytes read
NULL); // not overlapped
if (!fSuccess)
BOOST_FAIL("ReadFile from pipe failed");
return string(m_readBuf, m_readBuf + cbRead);
#else
if (send(m_socket, _req.c_str(), _req.length(), 0) != (ssize_t)_req.length())
BOOST_FAIL("Writing on IPC failed.");
auto start = chrono::steady_clock::now();
ssize_t ret;
do
{
ret = recv(m_socket, m_readBuf, sizeof(m_readBuf), 0);
// Also consider closed socket an error.
if (ret < 0)
BOOST_FAIL("Reading on IPC failed.");
}
while (
ret == 0 &&
chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count() < m_readTimeOutMS
);
if (ret == 0)
BOOST_FAIL("Timeout reading on IPC.");
return string(m_readBuf, m_readBuf + ret);
#endif
}
RPCSession& RPCSession::instance(string const& _path)
{
try
{
static RPCSession session(_path);
BOOST_REQUIRE_EQUAL(session.m_ipcSocket.path(), _path);
return session;
}
catch (std::exception const&)
{
BOOST_THROW_EXCEPTION(std::runtime_error("Error creating RPC session for socket: " + _path));
}
}
string RPCSession::eth_getCode(string const& _address, string const& _blockNumber)
{
return rpcCall("eth_getCode", { quote(_address), quote(_blockNumber) }).asString();
}
Json::Value RPCSession::eth_getBlockByNumber(string const& _blockNumber, bool _fullObjects)
{
// NOTE: to_string() converts bool to 0 or 1
return rpcCall("eth_getBlockByNumber", { quote(_blockNumber), _fullObjects ? "true" : "false" });
}
RPCSession::TransactionReceipt RPCSession::eth_getTransactionReceipt(string const& _transactionHash)
{
TransactionReceipt receipt;
Json::Value const result = rpcCall("eth_getTransactionReceipt", { quote(_transactionHash) });
receipt.gasUsed = result["gasUsed"].asString();
receipt.contractAddress = result["contractAddress"].asString();
receipt.blockNumber = result["blockNumber"].asString();
if (m_receiptHasStatusField)
{
BOOST_REQUIRE(!result["status"].isNull());
receipt.status = result["status"].asString();
}
for (auto const& log: result["logs"])
{
LogEntry entry;
entry.address = log["address"].asString();
entry.data = log["data"].asString();
for (auto const& topic: log["topics"])
entry.topics.push_back(topic.asString());
receipt.logEntries.push_back(entry);
}
return receipt;
}
string RPCSession::eth_sendTransaction(TransactionData const& _td)
{
return rpcCall("eth_sendTransaction", { _td.toJson() }).asString();
}
string RPCSession::eth_call(TransactionData const& _td, string const& _blockNumber)
{
return rpcCall("eth_call", { _td.toJson(), quote(_blockNumber) }).asString();
}
string RPCSession::eth_sendTransaction(string const& _transaction)
{
return rpcCall("eth_sendTransaction", { _transaction }).asString();
}
string RPCSession::eth_getBalance(string const& _address, string const& _blockNumber)
{
string address = (_address.length() == 20) ? "0x" + _address : _address;
return rpcCall("eth_getBalance", { quote(address), quote(_blockNumber) }).asString();
}
string RPCSession::eth_getStorageRoot(string const& _address, string const& _blockNumber)
{
string address = (_address.length() == 20) ? "0x" + _address : _address;
return rpcCall("eth_getStorageRoot", { quote(address), quote(_blockNumber) }).asString();
}
string RPCSession::eth_gasPrice()
{
return rpcCall("eth_gasPrice").asString();
}
void RPCSession::personal_unlockAccount(string const& _address, string const& _password, int _duration)
{
BOOST_REQUIRE_MESSAGE(
rpcCall("personal_unlockAccount", { quote(_address), quote(_password), to_string(_duration) }),
"Error unlocking account " + _address
);
}
string RPCSession::personal_newAccount(string const& _password)
{
string addr = rpcCall("personal_newAccount", { quote(_password) }).asString();
BOOST_TEST_MESSAGE("Created account " + addr);
return addr;
}
void RPCSession::test_setChainParams(vector<string> const& _accounts)
{
string forks;
if (test::Options::get().evmVersion() >= langutil::EVMVersion::tangerineWhistle())
forks += "\"EIP150ForkBlock\": \"0x00\",\n";
if (test::Options::get().evmVersion() >= langutil::EVMVersion::spuriousDragon())
forks += "\"EIP158ForkBlock\": \"0x00\",\n";
if (test::Options::get().evmVersion() >= langutil::EVMVersion::byzantium())
{
forks += "\"byzantiumForkBlock\": \"0x00\",\n";
m_receiptHasStatusField = true;
}
if (test::Options::get().evmVersion() >= langutil::EVMVersion::constantinople())
forks += "\"constantinopleForkBlock\": \"0x00\",\n";
if (test::Options::get().evmVersion() >= langutil::EVMVersion::petersburg())
forks += "\"constantinopleFixForkBlock\": \"0x00\",\n";
static string const c_configString = R"(
{
"sealEngine": "NoProof",
"params": {
"accountStartNonce": "0x00",
"maximumExtraDataSize": "0x1000000",
"blockReward": "0x",
"allowFutureBlocks": true,
)" + forks + R"(
"homesteadForkBlock": "0x00"
},
"genesis": {
"author": "0000000000000010000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x",
"gasLimit": "0x1000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000042",
"difficulty": "131072"
},
"accounts": {
"0000000000000000000000000000000000000001": { "wei": "1", "precompiled": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } },
"0000000000000000000000000000000000000002": { "wei": "1", "precompiled": { "name": "sha256", "linear": { "base": 60, "word": 12 } } },
"0000000000000000000000000000000000000003": { "wei": "1", "precompiled": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } },
"0000000000000000000000000000000000000004": { "wei": "1", "precompiled": { "name": "identity", "linear": { "base": 15, "word": 3 } } },
"0000000000000000000000000000000000000005": { "wei": "1", "precompiled": { "name": "modexp" } },
"0000000000000000000000000000000000000006": { "wei": "1", "precompiled": { "name": "alt_bn128_G1_add", "linear": { "base": 500, "word": 0 } } },
"0000000000000000000000000000000000000007": { "wei": "1", "precompiled": { "name": "alt_bn128_G1_mul", "linear": { "base": 40000, "word": 0 } } },
"0000000000000000000000000000000000000008": { "wei": "1", "precompiled": { "name": "alt_bn128_pairing_product" } }
}
}
)";
Json::Value config;
BOOST_REQUIRE(jsonParseStrict(c_configString, config));
for (auto const& account: _accounts)
config["accounts"][account]["wei"] = "0x100000000000000000000000000000000000000000";
test_setChainParams(jsonCompactPrint(config));
}
void RPCSession::test_setChainParams(string const& _config)
{
BOOST_REQUIRE(rpcCall("test_setChainParams", { _config }) == true);
}
void RPCSession::test_rewindToBlock(size_t _blockNr)
{
BOOST_REQUIRE(rpcCall("test_rewindToBlock", { to_string(_blockNr) }) == true);
}
void RPCSession::test_mineBlocks(int _number)
{
u256 startBlock = fromBigEndian<u256>(fromHex(rpcCall("eth_blockNumber").asString()));
BOOST_REQUIRE(rpcCall("test_mineBlocks", { to_string(_number) }, true) == true);
BOOST_REQUIRE(fromBigEndian<u256>(fromHex(rpcCall("eth_blockNumber").asString())) == startBlock + _number);
}
void RPCSession::test_modifyTimestamp(size_t _timestamp)
{
BOOST_REQUIRE(rpcCall("test_modifyTimestamp", { to_string(_timestamp) }) == true);
}
Json::Value RPCSession::rpcCall(string const& _methodName, vector<string> const& _args, bool _canFail)
{
string request = "{\"jsonrpc\":\"2.0\",\"method\":\"" + _methodName + "\",\"params\":[";
for (size_t i = 0; i < _args.size(); ++i)
{
request += _args[i];
if (i + 1 != _args.size())
request += ", ";
}
request += "],\"id\":" + to_string(m_rpcSequence) + "}";
++m_rpcSequence;
BOOST_TEST_MESSAGE("Request: " + request);
string reply = m_ipcSocket.sendRequest(request);
BOOST_TEST_MESSAGE("Reply: " + reply);
Json::Value result;
string errorMsg;
if (!jsonParseStrict(reply, result, &errorMsg))
BOOST_FAIL("Failed to parse JSON-RPC response: " + errorMsg);
if (!result.isMember("id") || !result["id"].isUInt())
BOOST_FAIL("Badly formatted JSON-RPC response (missing or non-integer \"id\")");
if (result["id"].asUInt() != (m_rpcSequence - 1))
BOOST_FAIL(
"Response identifier mismatch. "
"Expected " + to_string(m_rpcSequence - 1) + " but got " + to_string(result["id"].asUInt()) + "."
);
if (result.isMember("error"))
{
if (_canFail)
return Json::Value();
BOOST_FAIL("Error on JSON-RPC call: " + result["error"]["message"].asString());
}
if (!result.isMember("result") || result["result"].isNull())
BOOST_FAIL(
"Missing result for JSON-RPC call: " +
result.toStyledString() +
"\nRequest was " +
request
);
return result["result"];
}
string const& RPCSession::accountCreate()
{
m_accounts.push_back(personal_newAccount(""));
personal_unlockAccount(m_accounts.back(), "", 100000);
return m_accounts.back();
}
string const& RPCSession::accountCreateIfNotExists(size_t _id)
{
while ((_id + 1) > m_accounts.size())
accountCreate();
return m_accounts[_id];
}
RPCSession::RPCSession(string const& _path):
m_ipcSocket(_path)
{
accountCreate();
// This will pre-fund the accounts create prior.
test_setChainParams(m_accounts);
}
string RPCSession::TransactionData::toJson() const
{
Json::Value json;
json["from"] = (from.length() == 20) ? "0x" + from : from;
json["to"] = (to.length() == 20 || to == "") ? "0x" + to : to;
json["gas"] = gas;
json["gasprice"] = gasPrice;
json["value"] = value;
json["data"] = data;
return jsonCompactPrint(json);
}

View File

@ -1,146 +0,0 @@
/*
This file is part of solidity.
solidity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
solidity is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file RPCSession.h
* @author Dimtiry Khokhlov <dimitry@ethdev.com>
* @date 2016
*/
#if defined(_WIN32)
#include <windows.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#endif
#include <json/value.h>
#include <boost/noncopyable.hpp>
#include <boost/test/unit_test.hpp>
#include <string>
#include <stdio.h>
#include <map>
#if defined(_WIN32)
class IPCSocket : public boost::noncopyable
{
public:
explicit IPCSocket(std::string const& _path);
std::string sendRequest(std::string const& _req);
~IPCSocket() { CloseHandle(m_socket); }
std::string const& path() const { return m_path; }
private:
std::string m_path;
HANDLE m_socket;
TCHAR m_readBuf[512000];
};
#else
class IPCSocket: public boost::noncopyable
{
public:
explicit IPCSocket(std::string const& _path);
std::string sendRequest(std::string const& _req);
~IPCSocket() {
shutdown(m_socket, SHUT_RDWR);
close(m_socket);
}
std::string const& path() const { return m_path; }
private:
std::string m_path;
int m_socket;
/// Socket read timeout in milliseconds. Needs to be large because the key generation routine
/// might take long.
unsigned static constexpr m_readTimeOutMS = 300000;
char m_readBuf[512000];
};
#endif
class RPCSession: public boost::noncopyable
{
public:
struct TransactionData
{
std::string from;
std::string to;
std::string gas;
std::string gasPrice;
std::string value;
std::string data;
std::string toJson() const;
};
struct LogEntry {
std::string address;
std::vector<std::string> topics;
std::string data;
};
struct TransactionReceipt
{
std::string gasUsed;
std::string contractAddress;
std::vector<LogEntry> logEntries;
std::string blockNumber;
/// note: pre-byzantium the status field will be empty
std::string status;
};
static RPCSession& instance(std::string const& _path);
std::string eth_getCode(std::string const& _address, std::string const& _blockNumber);
Json::Value eth_getBlockByNumber(std::string const& _blockNumber, bool _fullObjects);
std::string eth_call(TransactionData const& _td, std::string const& _blockNumber);
TransactionReceipt eth_getTransactionReceipt(std::string const& _transactionHash);
std::string eth_sendTransaction(TransactionData const& _td);
std::string eth_sendTransaction(std::string const& _transaction);
std::string eth_getBalance(std::string const& _address, std::string const& _blockNumber);
std::string eth_getStorageRoot(std::string const& _address, std::string const& _blockNumber);
std::string eth_gasPrice();
std::string personal_newAccount(std::string const& _password);
void personal_unlockAccount(std::string const& _address, std::string const& _password, int _duration);
void test_setChainParams(std::vector<std::string> const& _accounts);
void test_setChainParams(std::string const& _config);
void test_rewindToBlock(size_t _blockNr);
void test_modifyTimestamp(size_t _timestamp);
void test_mineBlocks(int _number);
Json::Value rpcCall(std::string const& _methodName, std::vector<std::string> const& _args = std::vector<std::string>(), bool _canFail = false);
std::string const& account(size_t _id) const { return m_accounts.at(_id); }
std::string const& accountCreate();
std::string const& accountCreateIfNotExists(size_t _id);
private:
explicit RPCSession(std::string const& _path);
inline std::string quote(std::string const& _arg) { return "\"" + _arg + "\""; }
/// Parse std::string replacing keywords to values
void parseString(std::string& _string, std::map<std::string, std::string> const& _varMap);
IPCSocket m_ipcSocket;
size_t m_rpcSequence = 1;
bool m_receiptHasStatusField = false;
std::vector<std::string> m_accounts;
};

View File

@ -20,11 +20,14 @@
* Tests for a fixed fee registrar contract.
*/
#include <string>
#include <tuple>
#include <boost/test/unit_test.hpp>
#include <test/libsolidity/SolidityExecutionFramework.h>
#include <test/contracts/ContractInterface.h>
#include <test/EVMHost.h>
#include <boost/test/unit_test.hpp>
#include <string>
#include <tuple>
using namespace std;
using namespace dev::test;
@ -413,7 +416,8 @@ BOOST_AUTO_TEST_CASE(auction_simple)
registrar.reserve(name);
BOOST_CHECK_EQUAL(registrar.owner(name), 0);
// "wait" until auction end
m_rpc.test_modifyTimestamp(currentTimestamp() + m_biddingTime + 10);
m_evmHost->m_state.timestamp += m_biddingTime + 10;
// trigger auction again
registrar.reserve(name);
BOOST_CHECK_EQUAL(registrar.owner(name), m_sender);
@ -425,7 +429,7 @@ BOOST_AUTO_TEST_CASE(auction_bidding)
string name = "x";
unsigned startTime = 0x776347e2;
m_rpc.test_modifyTimestamp(startTime);
m_evmHost->m_state.timestamp = startTime;
RegistrarInterface registrar(*this);
// initiate auction
@ -433,19 +437,19 @@ BOOST_AUTO_TEST_CASE(auction_bidding)
registrar.reserve(name);
BOOST_CHECK_EQUAL(registrar.owner(name), 0);
// overbid self
m_rpc.test_modifyTimestamp(startTime + m_biddingTime - 10);
m_evmHost->m_state.timestamp = startTime + m_biddingTime - 10;
registrar.setNextValue(12);
registrar.reserve(name);
// another bid by someone else
sendEther(account(1), 10 * ether);
m_sender = account(1);
m_rpc.test_modifyTimestamp(startTime + 2 * m_biddingTime - 50);
m_evmHost->m_state.timestamp = startTime + 2 * m_biddingTime - 50;
registrar.setNextValue(13);
registrar.reserve(name);
BOOST_CHECK_EQUAL(registrar.owner(name), 0);
// end auction by first bidder (which is not highest) trying to overbid again (too late)
m_sender = account(0);
m_rpc.test_modifyTimestamp(startTime + 4 * m_biddingTime);
m_evmHost->m_state.timestamp = startTime + 4 * m_biddingTime;
registrar.setNextValue(20);
registrar.reserve(name);
BOOST_CHECK_EQUAL(registrar.owner(name), account(1));
@ -461,17 +465,17 @@ BOOST_AUTO_TEST_CASE(auction_renewal)
// register name by auction
registrar.setNextValue(8);
registrar.reserve(name);
m_rpc.test_modifyTimestamp(startTime + 4 * m_biddingTime);
m_evmHost->m_state.timestamp = startTime + 4 * m_biddingTime;
registrar.reserve(name);
BOOST_CHECK_EQUAL(registrar.owner(name), m_sender);
// try to re-register before interval end
sendEther(account(1), 10 * ether);
m_sender = account(1);
m_rpc.test_modifyTimestamp(currentTimestamp() + m_renewalInterval - 1);
m_evmHost->m_state.timestamp = currentTimestamp() + m_renewalInterval - 1;
registrar.setNextValue(80);
registrar.reserve(name);
m_rpc.test_modifyTimestamp(currentTimestamp() + m_biddingTime);
m_evmHost->m_state.timestamp = currentTimestamp() + m_biddingTime;
// if there is a bug in the renewal logic, this would transfer the ownership to account(1),
// but if there is no bug, this will initiate the auction, albeit with a zero bid
registrar.reserve(name);

View File

@ -377,11 +377,11 @@ BOOST_AUTO_TEST_CASE(transfer_ownership)
BOOST_REQUIRE(callContractFunction("setOwner(bytes32,address)", 0x00, ACCOUNT(1)) == encodeArgs());
// Check that an event was raised and contents are correct.
BOOST_REQUIRE(m_logs.size() == 1);
BOOST_CHECK(m_logs[0].data == encodeArgs(ACCOUNT(1)));
BOOST_REQUIRE(m_logs[0].topics.size() == 2);
BOOST_CHECK(m_logs[0].topics[0] == keccak256(string("Transfer(bytes32,address)")));
BOOST_CHECK(m_logs[0].topics[1] == u256(0x00));
BOOST_REQUIRE(numLogs() == 1);
BOOST_CHECK(logData(0) == encodeArgs(ACCOUNT(1)));
BOOST_REQUIRE(numLogTopics(0) == 2);
BOOST_CHECK(logTopic(0, 0) == keccak256(string("Transfer(bytes32,address)")));
BOOST_CHECK(logTopic(0, 1) == u256(0x00));
// Verify that owner of 0x00 is now account(1).
BOOST_CHECK(callContractFunction("owner(bytes32)", 0x00) == encodeArgs(ACCOUNT(1)));
@ -406,11 +406,11 @@ BOOST_AUTO_TEST_CASE(set_resolver)
BOOST_REQUIRE(callContractFunction("setResolver(bytes32,address)", 0x00, ACCOUNT(1)) == encodeArgs());
// Check that an event was raised and contents are correct.
BOOST_REQUIRE(m_logs.size() == 1);
BOOST_CHECK(m_logs[0].data == encodeArgs(ACCOUNT(1)));
BOOST_REQUIRE(m_logs[0].topics.size() == 2);
BOOST_CHECK(m_logs[0].topics[0] == keccak256(string("NewResolver(bytes32,address)")));
BOOST_CHECK(m_logs[0].topics[1] == u256(0x00));
BOOST_REQUIRE(numLogs() == 1);
BOOST_CHECK(logData(0) == encodeArgs(ACCOUNT(1)));
BOOST_REQUIRE(numLogTopics(0) == 2);
BOOST_CHECK(logTopic(0, 0) == keccak256(string("NewResolver(bytes32,address)")));
BOOST_CHECK(logTopic(0, 1) == u256(0x00));
// Verify that the resolver is changed to account(1).
BOOST_CHECK(callContractFunction("resolver(bytes32)", 0x00) == encodeArgs(ACCOUNT(1)));
@ -435,11 +435,11 @@ BOOST_AUTO_TEST_CASE(set_ttl)
BOOST_REQUIRE(callContractFunction("setTTL(bytes32,uint64)", 0x00, 3600) == encodeArgs());
// Check that an event was raised and contents are correct.
BOOST_REQUIRE(m_logs.size() == 1);
BOOST_CHECK(m_logs[0].data == encodeArgs(3600));
BOOST_REQUIRE(m_logs[0].topics.size() == 2);
BOOST_CHECK(m_logs[0].topics[0] == keccak256(string("NewTTL(bytes32,uint64)")));
BOOST_CHECK(m_logs[0].topics[1] == u256(0x00));
BOOST_REQUIRE(numLogs() == 1);
BOOST_CHECK(logData(0) == encodeArgs(3600));
BOOST_REQUIRE(numLogTopics(0) == 2);
BOOST_CHECK(logTopic(0, 0) == keccak256(string("NewTTL(bytes32,uint64)")));
BOOST_CHECK(logTopic(0, 1) == u256(0x00));
// Verify that the TTL has been set.
BOOST_CHECK(callContractFunction("ttl(bytes32)", 0x00) == encodeArgs(3600));
@ -464,12 +464,12 @@ BOOST_AUTO_TEST_CASE(create_subnode)
BOOST_REQUIRE(callContractFunction("setSubnodeOwner(bytes32,bytes32,address)", 0x00, keccak256(string("eth")), ACCOUNT(1)) == encodeArgs());
// Check that an event was raised and contents are correct.
BOOST_REQUIRE(m_logs.size() == 1);
BOOST_CHECK(m_logs[0].data == encodeArgs(ACCOUNT(1)));
BOOST_REQUIRE(m_logs[0].topics.size() == 3);
BOOST_CHECK(m_logs[0].topics[0] == keccak256(string("NewOwner(bytes32,bytes32,address)")));
BOOST_CHECK(m_logs[0].topics[1] == u256(0x00));
BOOST_CHECK(m_logs[0].topics[2] == keccak256(string("eth")));
BOOST_REQUIRE(numLogs() == 1);
BOOST_CHECK(logData(0) == encodeArgs(ACCOUNT(1)));
BOOST_REQUIRE(numLogTopics(0) == 3);
BOOST_CHECK(logTopic(0, 0) == keccak256(string("NewOwner(bytes32,bytes32,address)")));
BOOST_CHECK(logTopic(0, 1) == u256(0x00));
BOOST_CHECK(logTopic(0, 2) == keccak256(string("eth")));
// Verify that the sub-node owner is now account(1).
u256 namehash = keccak256(h256(0x00).asBytes() + keccak256("eth").asBytes());

View File

@ -494,12 +494,12 @@ BOOST_AUTO_TEST_CASE(transfer_event)
BOOST_REQUIRE(callContractFunction("transfer(address,uint256)", ACCOUNT(1), u256(transfer)) == SUCCESS);
// Check that a Transfer event was recorded and contents are correct.
BOOST_REQUIRE(m_logs.size() == 1);
BOOST_CHECK(m_logs[0].data == encodeArgs(transfer));
BOOST_REQUIRE(m_logs[0].topics.size() == 3);
BOOST_CHECK(m_logs[0].topics[0] == keccak256(string("Transfer(address,address,uint256)")));
BOOST_CHECK(m_logs[0].topics[1] == ACCOUNT(0));
BOOST_CHECK(m_logs[0].topics[2] == ACCOUNT(1));
BOOST_REQUIRE(numLogs() == 1);
BOOST_CHECK(logData(0) == encodeArgs(transfer));
BOOST_REQUIRE(numLogTopics(0) == 3);
BOOST_CHECK(logTopic(0, 0) == keccak256(string("Transfer(address,address,uint256)")));
BOOST_CHECK(logTopic(0, 1) == ACCOUNT(0));
BOOST_CHECK(logTopic(0, 2) == ACCOUNT(1));
}
BOOST_AUTO_TEST_CASE(transfer_zero_no_event)
@ -512,7 +512,7 @@ BOOST_AUTO_TEST_CASE(transfer_zero_no_event)
BOOST_REQUIRE(callContractFunction("transfer(address,uint256)", ACCOUNT(1), u256(transfer)) == SUCCESS);
// Check that no Event was recorded.
BOOST_CHECK(m_logs.size() == 0);
BOOST_CHECK(numLogs() == 0);
// Check that balances have not changed.
BOOST_CHECK(callContractFunction("balanceOf(address)", ACCOUNT(0)) == encodeArgs(TOKENSUPPLY - transfer));
@ -529,12 +529,12 @@ BOOST_AUTO_TEST_CASE(approval_and_transfer_events)
BOOST_REQUIRE(callContractFunction("approve(address,uint256)", ACCOUNT(1), u256(allow)) == SUCCESS);
// Check that an Approval event was recorded and contents are correct.
BOOST_REQUIRE(m_logs.size() == 1);
BOOST_CHECK(m_logs[0].data == encodeArgs(allow));
BOOST_REQUIRE(m_logs[0].topics.size() == 3);
BOOST_CHECK(m_logs[0].topics[0] == keccak256(string("Approval(address,address,uint256)")));
BOOST_CHECK(m_logs[0].topics[1] == ACCOUNT(0));
BOOST_CHECK(m_logs[0].topics[2] == ACCOUNT(1));
BOOST_REQUIRE(numLogs() == 1);
BOOST_CHECK(logData(0) == encodeArgs(allow));
BOOST_REQUIRE(numLogTopics(0) == 3);
BOOST_CHECK(logTopic(0, 0) == keccak256(string("Approval(address,address,uint256)")));
BOOST_CHECK(logTopic(0, 1) == ACCOUNT(0));
BOOST_CHECK(logTopic(0, 2) == ACCOUNT(1));
// Send account(1) some ether for gas.
sendEther(account(1), 1000 * ether);
@ -546,12 +546,12 @@ BOOST_AUTO_TEST_CASE(approval_and_transfer_events)
BOOST_REQUIRE(callContractFunction("transferFrom(address,address,uint256)", ACCOUNT(0), ACCOUNT(2), u256(transfer)) == SUCCESS);
// Check that a Transfer event was recorded and contents are correct.
BOOST_REQUIRE(m_logs.size() == 1);
BOOST_CHECK(m_logs[0].data == encodeArgs(transfer));
BOOST_REQUIRE(m_logs[0].topics.size() == 3);
BOOST_CHECK(m_logs[0].topics[0] == keccak256(string("Transfer(address,address,uint256)")));
BOOST_CHECK(m_logs[0].topics[1] == ACCOUNT(0));
BOOST_CHECK(m_logs[0].topics[2] == ACCOUNT(2));
BOOST_REQUIRE(numLogs() == 1);
BOOST_CHECK(logData(0) == encodeArgs(transfer));
BOOST_REQUIRE(numLogTopics(0) == 3);
BOOST_CHECK(logTopic(0, 0) == keccak256(string("Transfer(address,address,uint256)")));
BOOST_CHECK(logTopic(0, 1) == ACCOUNT(0));
BOOST_CHECK(logTopic(0, 2) == ACCOUNT(2));
}
BOOST_AUTO_TEST_CASE(invalid_transfer_1)

View File

@ -43,9 +43,9 @@ namespace test
{
#define REQUIRE_LOG_DATA(DATA) do { \
BOOST_REQUIRE_EQUAL(m_logs.size(), 1); \
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); \
ABI_CHECK(m_logs[0].data, DATA); \
BOOST_REQUIRE_EQUAL(numLogs(), 1); \
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); \
ABI_CHECK(logData(0), DATA); \
} while (false)
BOOST_FIXTURE_TEST_SUITE(ABIEncoderTest, SolidityExecutionFramework)
@ -451,7 +451,7 @@ BOOST_AUTO_TEST_CASE(structs)
);
BOOST_CHECK(callContractFunction("f()") == encoded);
REQUIRE_LOG_DATA(encoded);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("e(uint16,(uint16,uint16,(uint64[2])[],uint16))")));
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("e(uint16,(uint16,uint16,(uint64[2])[],uint16))")));
)
}

View File

@ -24,6 +24,7 @@
#include <test/libsolidity/SolidityExecutionFramework.h>
#include <test/Options.h>
#include <test/EVMHost.h>
#include <liblangutil/Exceptions.h>
#include <liblangutil/EVMVersion.h>
@ -1133,8 +1134,12 @@ BOOST_AUTO_TEST_CASE(blockchain)
}
}
)";
BOOST_CHECK(m_rpc.rpcCall("miner_setEtherbase", {"\"0x1212121212121212121212121212121212121212\""}).asBool() == true);
m_rpc.test_mineBlocks(5);
m_evmHost->m_coinbase = EVMHost::convertToEVMC(Address("0x1212121212121212121212121212121212121212"));
m_evmHost->newBlock();
m_evmHost->newBlock();
m_evmHost->newBlock();
m_evmHost->newBlock();
m_evmHost->newBlock();
compileAndRun(sourceCode, 27);
ABI_CHECK(callContractFunctionWithValue("someInfo()", 28), encodeArgs(28, u256("0x1212121212121212121212121212121212121212"), 7));
}
@ -1184,10 +1189,10 @@ BOOST_AUTO_TEST_CASE(now)
)";
ALSO_VIA_YUL(
compileAndRun(sourceCode);
u256 startBlock = m_blockNumber;
u256 startBlock = blockNumber();
size_t startTime = blockTimestamp(startBlock);
auto ret = callContractFunction("someInfo()");
u256 endBlock = m_blockNumber;
u256 endBlock = blockNumber();
size_t endTime = blockTimestamp(endBlock);
BOOST_CHECK(startBlock != endBlock);
BOOST_CHECK(startTime != endTime);
@ -1276,10 +1281,10 @@ BOOST_AUTO_TEST_CASE(log0)
)";
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1)));
BOOST_CHECK_EQUAL(m_logs[0].topics.size(), 0);
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)
@ -1293,11 +1298,11 @@ BOOST_AUTO_TEST_CASE(log1)
)";
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1)));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], h256(u256(2)));
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)
@ -1311,12 +1316,12 @@ BOOST_AUTO_TEST_CASE(log2)
)";
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1)));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
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(m_logs[0].topics[i], h256(u256(i + 2)));
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2)));
}
BOOST_AUTO_TEST_CASE(log3)
@ -1330,12 +1335,12 @@ BOOST_AUTO_TEST_CASE(log3)
)";
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1)));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 3);
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(m_logs[0].topics[i], h256(u256(i + 2)));
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2)));
}
BOOST_AUTO_TEST_CASE(log4)
@ -1349,12 +1354,12 @@ BOOST_AUTO_TEST_CASE(log4)
)";
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1)));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 4);
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(m_logs[0].topics[i], h256(u256(i + 2)));
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2)));
}
BOOST_AUTO_TEST_CASE(log_in_constructor)
@ -1367,11 +1372,11 @@ BOOST_AUTO_TEST_CASE(log_in_constructor)
}
)";
compileAndRun(sourceCode);
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1)));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], h256(u256(2)));
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)
@ -2615,13 +2620,13 @@ BOOST_AUTO_TEST_CASE(event)
for (bool manually: {true, false})
{
callContractFunctionWithValue("deposit(bytes32,bool)", value, id, manually);
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(value)));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 3);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,bytes32,uint256)")));
BOOST_CHECK_EQUAL(m_logs[0].topics[1], h256(m_sender, h256::AlignRight));
BOOST_CHECK_EQUAL(m_logs[0].topics[2], h256(id));
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), dev::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));
}
}
@ -2640,13 +2645,13 @@ BOOST_AUTO_TEST_CASE(event_emit)
u256 value(18);
u256 id(0x1234);
callContractFunctionWithValue("deposit(bytes32)", value, id);
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(value)));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 3);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,bytes32,uint256)")));
BOOST_CHECK_EQUAL(m_logs[0].topics[1], h256(m_sender, h256::AlignRight));
BOOST_CHECK_EQUAL(m_logs[0].topics[2], h256(id));
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), dev::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));
)
}
@ -2664,11 +2669,11 @@ BOOST_AUTO_TEST_CASE(event_no_arguments)
ALSO_VIA_YUL(
compileAndRun(sourceCode);
callContractFunction("deposit()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data.empty());
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit()")));
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), dev::keccak256(string("Deposit()")));
)
}
@ -2687,11 +2692,11 @@ BOOST_AUTO_TEST_CASE(event_access_through_base_name_emit)
)";
compileAndRun(sourceCode);
callContractFunction("f()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data.empty());
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("x()")));
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), dev::keccak256(string("x()")));
}
BOOST_AUTO_TEST_CASE(events_with_same_name)
@ -2725,32 +2730,32 @@ BOOST_AUTO_TEST_CASE(events_with_same_name)
ALSO_VIA_YUL(
compileAndRun(sourceCode);
ABI_CHECK(callContractFunction("deposit()"), encodeArgs(u256(1)));
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data.empty());
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit()")));
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), dev::keccak256(string("Deposit()")));
ABI_CHECK(callContractFunction("deposit(address)", c_loggedAddress), encodeArgs(u256(2)));
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
ABI_CHECK(m_logs[0].data, encodeArgs(c_loggedAddress));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address)")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
ABI_CHECK(logData(0), encodeArgs(c_loggedAddress));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(address)")));
ABI_CHECK(callContractFunction("deposit(address,uint256)", c_loggedAddress, u256(100)), encodeArgs(u256(3)));
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
ABI_CHECK(m_logs[0].data, encodeArgs(c_loggedAddress, 100));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,uint256)")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
ABI_CHECK(logData(0), encodeArgs(c_loggedAddress, 100));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(address,uint256)")));
ABI_CHECK(callContractFunction("deposit(address,bool)", c_loggedAddress, false), encodeArgs(u256(4)));
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
ABI_CHECK(m_logs[0].data, encodeArgs(c_loggedAddress, false));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,bool)")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
ABI_CHECK(logData(0), encodeArgs(c_loggedAddress, false));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(address,bool)")));
)
}
@ -2786,25 +2791,25 @@ BOOST_AUTO_TEST_CASE(events_with_same_name_inherited_emit)
ALSO_VIA_YUL(
compileAndRun(sourceCode);
ABI_CHECK(callContractFunction("deposit()"), encodeArgs(u256(1)));
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data.empty());
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit()")));
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), dev::keccak256(string("Deposit()")));
ABI_CHECK(callContractFunction("deposit(address)", c_loggedAddress), encodeArgs(u256(1)));
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data == encodeArgs(c_loggedAddress));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address)")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK(logData(0) == encodeArgs(c_loggedAddress));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(address)")));
ABI_CHECK(callContractFunction("deposit(address,uint256)", c_loggedAddress, u256(100)), encodeArgs(u256(1)));
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
ABI_CHECK(m_logs[0].data, encodeArgs(c_loggedAddress, 100));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,uint256)")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
ABI_CHECK(logData(0), encodeArgs(c_loggedAddress, 100));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(address,uint256)")));
)
}
@ -2821,7 +2826,7 @@ BOOST_AUTO_TEST_CASE(event_anonymous)
ALSO_VIA_YUL(
compileAndRun(sourceCode);
callContractFunction("deposit()");
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 0);
BOOST_REQUIRE_EQUAL(numLogTopics(0), 0);
)
}
@ -2840,14 +2845,14 @@ BOOST_AUTO_TEST_CASE(event_anonymous_with_topics)
u256 value(18);
u256 id(0x1234);
callContractFunctionWithValue("deposit(bytes32)", value, id);
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data == encodeArgs("abc"));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 4);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], h256(m_sender, h256::AlignRight));
BOOST_CHECK_EQUAL(m_logs[0].topics[1], h256(id));
BOOST_CHECK_EQUAL(m_logs[0].topics[2], h256(value));
BOOST_CHECK_EQUAL(m_logs[0].topics[3], h256(2));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK(logData(0) == encodeArgs("abc"));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 4);
BOOST_CHECK_EQUAL(logTopic(0, 0), h256(m_sender, h256::AlignRight));
BOOST_CHECK_EQUAL(logTopic(0, 1), h256(id));
BOOST_CHECK_EQUAL(logTopic(0, 2), h256(value));
BOOST_CHECK_EQUAL(logTopic(0, 3), h256(2));
)
}
@ -2866,11 +2871,11 @@ BOOST_AUTO_TEST_CASE(event_lots_of_data)
u256 value(18);
u256 id(0x1234);
callContractFunctionWithValue("deposit(bytes32)", value, id);
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data == encodeArgs((u160)m_sender, id, value, true));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,bytes32,uint256,bool)")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK(logData(0) == encodeArgs((u160)m_sender, id, value, true));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(address,bytes32,uint256,bool)")));
)
}
@ -2886,11 +2891,11 @@ BOOST_AUTO_TEST_CASE(event_really_lots_of_data)
)";
compileAndRun(sourceCode);
callContractFunction("deposit()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK_EQUAL(toHex(m_logs[0].data), toHex(encodeArgs(10, 0x60, 15, 4, asString(FixedHash<4>(dev::keccak256("deposit()")).asBytes()))));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK_EQUAL(toHex(logData(0)), toHex(encodeArgs(10, 0x60, 15, 4, asString(FixedHash<4>(dev::keccak256("deposit()")).asBytes()))));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
}
BOOST_AUTO_TEST_CASE(event_really_lots_of_data_from_storage)
@ -2910,11 +2915,11 @@ BOOST_AUTO_TEST_CASE(event_really_lots_of_data_from_storage)
)";
compileAndRun(sourceCode);
callContractFunction("deposit()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK_EQUAL(toHex(m_logs[0].data), toHex(encodeArgs(10, 0x60, 15, 3, string("ABC"))));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK_EQUAL(toHex(logData(0)), toHex(encodeArgs(10, 0x60, 15, 3, string("ABC"))));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
}
BOOST_AUTO_TEST_CASE(event_really_really_lots_of_data_from_storage)
@ -2935,11 +2940,11 @@ BOOST_AUTO_TEST_CASE(event_really_really_lots_of_data_from_storage)
)";
compileAndRun(sourceCode);
callContractFunction("deposit()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data == encodeArgs(10, 0x60, 15, 31, string("ABC") + string(27, 0) + "Z"));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK(logData(0) == encodeArgs(10, 0x60, 15, 31, string("ABC") + string(27, 0) + "Z"));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
}
BOOST_AUTO_TEST_CASE(event_struct_memory_v2)
@ -2957,11 +2962,11 @@ BOOST_AUTO_TEST_CASE(event_struct_memory_v2)
compileAndRun(sourceCode);
u256 x(42);
callContractFunction("createEvent(uint256)", x);
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data == encodeArgs(x));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint256))")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK(logData(0) == encodeArgs(x));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E((uint256))")));
}
BOOST_AUTO_TEST_CASE(event_struct_storage_v2)
@ -2981,11 +2986,11 @@ BOOST_AUTO_TEST_CASE(event_struct_storage_v2)
compileAndRun(sourceCode);
u256 x(42);
callContractFunction("createEvent(uint256)", x);
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data == encodeArgs(x));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint256))")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK(logData(0) == encodeArgs(x));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E((uint256))")));
}
BOOST_AUTO_TEST_CASE(event_dynamic_array_memory)
@ -3005,11 +3010,11 @@ BOOST_AUTO_TEST_CASE(event_dynamic_array_memory)
compileAndRun(sourceCode);
u256 x(42);
callContractFunction("createEvent(uint256)", x);
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK(logData(0) == encodeArgs(0x20, 3, x, x + 1, x + 2));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(uint256[])")));
}
BOOST_AUTO_TEST_CASE(event_dynamic_array_memory_v2)
@ -3030,11 +3035,11 @@ BOOST_AUTO_TEST_CASE(event_dynamic_array_memory_v2)
compileAndRun(sourceCode);
u256 x(42);
callContractFunction("createEvent(uint256)", x);
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK(logData(0) == encodeArgs(0x20, 3, x, x + 1, x + 2));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(uint256[])")));
}
BOOST_AUTO_TEST_CASE(event_dynamic_nested_array_memory_v2)
@ -3058,11 +3063,11 @@ BOOST_AUTO_TEST_CASE(event_dynamic_nested_array_memory_v2)
compileAndRun(sourceCode);
u256 x(42);
callContractFunction("createEvent(uint256)", x);
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 2, 0x40, 0xa0, 2, x, x + 1, 2, x + 2, x + 3));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[][])")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK(logData(0) == encodeArgs(0x20, 2, 0x40, 0xa0, 2, x, x + 1, 2, x + 2, x + 3));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(uint256[][])")));
}
BOOST_AUTO_TEST_CASE(event_dynamic_array_storage)
@ -3084,11 +3089,11 @@ BOOST_AUTO_TEST_CASE(event_dynamic_array_storage)
compileAndRun(sourceCode);
u256 x(42);
callContractFunction("createEvent(uint256)", x);
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK(logData(0) == encodeArgs(0x20, 3, x, x + 1, x + 2));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(uint256[])")));
)
}
@ -3112,11 +3117,11 @@ BOOST_AUTO_TEST_CASE(event_dynamic_array_storage_v2)
compileAndRun(sourceCode);
u256 x(42);
callContractFunction("createEvent(uint256)", x);
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK(logData(0) == encodeArgs(0x20, 3, x, x + 1, x + 2));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(uint256[])")));
)
}
@ -3143,11 +3148,11 @@ BOOST_AUTO_TEST_CASE(event_dynamic_nested_array_storage_v2)
compileAndRun(sourceCode);
u256 x(42);
callContractFunction("createEvent(uint256)", x);
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 2, 0x40, 0xa0, 2, x, x + 1, 2, x + 2, x + 3));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[][])")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK(logData(0) == encodeArgs(0x20, 2, 0x40, 0xa0, 2, x, x + 1, 2, x + 2, x + 3));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(uint256[][])")));
);
}
@ -3172,18 +3177,18 @@ BOOST_AUTO_TEST_CASE(event_indexed_string)
)";
compileAndRun(sourceCode);
callContractFunction("deposit()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
string dynx(90, 0);
for (size_t i = 0; i < dynx.size(); ++i)
dynx[i] = i;
BOOST_CHECK(m_logs[0].data == bytes());
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 3);
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(dynx));
BOOST_CHECK_EQUAL(m_logs[0].topics[2], dev::keccak256(
BOOST_CHECK(logData(0) == bytes());
BOOST_REQUIRE_EQUAL(numLogTopics(0), 3);
BOOST_CHECK_EQUAL(logTopic(0, 1), dev::keccak256(dynx));
BOOST_CHECK_EQUAL(logTopic(0, 2), dev::keccak256(
encodeArgs(u256(4), u256(5), u256(6), u256(7))
));
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(string,uint256[4])")));
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(string,uint256[4])")));
}
BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one)
@ -3981,11 +3986,11 @@ BOOST_AUTO_TEST_CASE(storing_invalid_boolean)
ABI_CHECK(callContractFunction("perm()"), encodeArgs(1));
ABI_CHECK(callContractFunction("ret()"), encodeArgs(1));
ABI_CHECK(callContractFunction("ev()"), encodeArgs(1));
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_CHECK(m_logs[0].data == encodeArgs(1));
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Ev(bool)")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK(logData(0) == encodeArgs(1));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Ev(bool)")));
}
@ -5907,11 +5912,11 @@ BOOST_AUTO_TEST_CASE(invalid_enum_logged)
)";
compileAndRun(sourceCode, 0, "C");
ABI_CHECK(callContractFunction("test_log_ok()"), encodeArgs(u256(1)));
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
BOOST_REQUIRE_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Log(uint8)")));
BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(0)));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_REQUIRE_EQUAL(logTopic(0, 0), dev::keccak256(string("Log(uint8)")));
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(0)));
// should throw
ABI_CHECK(callContractFunction("test_log()"), encodeArgs());
@ -13554,13 +13559,13 @@ BOOST_AUTO_TEST_CASE(abi_encodePackedV2_structs)
compileAndRun(sourceCode, 0, "C");
bytes structEnc = encodeArgs(int(0x12), u256(-7), int(2), int(3), u256(-7), u256(-8));
ABI_CHECK(callContractFunction("testStorage()"), encodeArgs());
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint8,int16,uint8[2],int16[]))")));
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(structEnc)));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E((uint8,int16,uint8[2],int16[]))")));
BOOST_CHECK_EQUAL(logTopic(0, 1), dev::keccak256(asString(structEnc)));
ABI_CHECK(callContractFunction("testMemory()"), encodeArgs());
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint8,int16,uint8[2],int16[]))")));
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(structEnc)));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E((uint8,int16,uint8[2],int16[]))")));
BOOST_CHECK_EQUAL(logTopic(0, 1), dev::keccak256(asString(structEnc)));
}
BOOST_AUTO_TEST_CASE(abi_encodePackedV2_nestedArray)
@ -13587,9 +13592,9 @@ BOOST_AUTO_TEST_CASE(abi_encodePackedV2_nestedArray)
compileAndRun(sourceCode, 0, "C");
bytes structEnc = encodeArgs(1, 2, 3, 0, 0, 0, 0, 4);
ABI_CHECK(callContractFunction("testNestedArrays()"), encodeArgs());
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint8,int16)[2][][3])")));
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(structEnc)));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E((uint8,int16)[2][][3])")));
BOOST_CHECK_EQUAL(logTopic(0, 1), dev::keccak256(asString(structEnc)));
}
BOOST_AUTO_TEST_CASE(abi_encodePackedV2_arrayOfStrings)
@ -13616,13 +13621,13 @@ BOOST_AUTO_TEST_CASE(abi_encodePackedV2_arrayOfStrings)
compileAndRun(sourceCode, 0, "C");
bytes arrayEncoding = encodeArgs("abc", "0123456789012345678901234567890123456789");
ABI_CHECK(callContractFunction("testStorage()"), encodeArgs());
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(string[])")));
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(arrayEncoding)));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(string[])")));
BOOST_CHECK_EQUAL(logTopic(0, 1), dev::keccak256(asString(arrayEncoding)));
ABI_CHECK(callContractFunction("testMemory()"), encodeArgs());
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(string[])")));
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(arrayEncoding)));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E(string[])")));
BOOST_CHECK_EQUAL(logTopic(0, 1), dev::keccak256(asString(arrayEncoding)));
}
BOOST_AUTO_TEST_CASE(event_signature_in_library)
@ -13649,8 +13654,8 @@ BOOST_AUTO_TEST_CASE(event_signature_in_library)
}
)";
compileAndRun(sourceCode, 0, "C");
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint8,int16),(uint8,int16))")));
BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("E((uint8,int16),(uint8,int16))")));
}
@ -14730,10 +14735,10 @@ BOOST_AUTO_TEST_CASE(event_wrong_abi_name)
u256 id(0x1234);
callContractFunction("f()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 3);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,bytes32,uint256)")));
BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_REQUIRE_EQUAL(numLogTopics(0), 3);
BOOST_CHECK_EQUAL(logTopic(0, 0), dev::keccak256(string("Deposit(address,bytes32,uint256)")));
}
BOOST_AUTO_TEST_CASE(uninitialized_internal_storage_function)
@ -14801,10 +14806,10 @@ BOOST_AUTO_TEST_CASE(dirty_scratch_space_prior_to_constant_optimiser)
}
)";
compileAndRun(sourceCode, 0, "C");
BOOST_REQUIRE_EQUAL(m_logs.size(), 2);
BOOST_CHECK_EQUAL(m_logs[1].address, m_contractAddress);
BOOST_REQUIRE_EQUAL(numLogs(), 2);
BOOST_CHECK_EQUAL(logAddress(1), m_contractAddress);
ABI_CHECK(
m_logs[1].data,
logData(1),
encodeArgs(u256("0x0000000000001234123412431234123412412342112341234124312341234124"))
);
}

View File

@ -35,8 +35,8 @@ SolidityExecutionFramework::SolidityExecutionFramework():
{
}
SolidityExecutionFramework::SolidityExecutionFramework(std::string const& _ipcPath, langutil::EVMVersion _evmVersion):
ExecutionFramework(_ipcPath, _evmVersion)
SolidityExecutionFramework::SolidityExecutionFramework(std::string const&, langutil::EVMVersion _evmVersion):
ExecutionFramework(_evmVersion)
{
}

View File

@ -15,6 +15,7 @@ add_executable(isoltest
IsolTestOptions.cpp
../Options.cpp
../Common.cpp
../EVMHost.cpp
../TestCase.cpp
../libsolidity/util/BytesUtils.cpp
../libsolidity/util/ContractABIUtils.cpp
@ -26,7 +27,6 @@ add_executable(isoltest
../libsolidity/AnalysisFramework.cpp
../libsolidity/SolidityExecutionFramework.cpp
../ExecutionFramework.cpp
../RPCSession.cpp
../libsolidity/ABIJsonTest.cpp
../libsolidity/ASTJSONTest.cpp
../libsolidity/SMTCheckerJSONTest.cpp

View File

@ -142,7 +142,7 @@ DEFINE_PROTO_FUZZER(Contract const& _input)
// We target the default EVM which is the latest
langutil::EVMVersion version = {};
EVMHost hostContext(version, evmone);
EVMHost hostContext(version, &evmone);
// Deploy contract and signal failure if deploy failed
evmc::result createResult = deployContract(hostContext, byteCode);