Merge pull request #7886 from ethereum/develop

Merge develop into develop_060
This commit is contained in:
chriseth 2019-12-03 21:41:49 +01:00 committed by GitHub
commit f2790cc5e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 100 additions and 230 deletions

View File

@ -9,7 +9,7 @@ version: 2.1
parameters: parameters:
docker-image-rev: docker-image-rev:
type: string type: string
default: "2" default: "3"
defaults: defaults:

View File

@ -62,7 +62,7 @@ RUN git clone --recursive -b boost-1.69.0 https://github.com/boostorg/boost.git
rm -rf /usr/src/boost rm -rf /usr/src/boost
# Z3 # Z3
RUN git clone --depth 1 -b z3-4.8.6 https://github.com/Z3Prover/z3.git \ RUN git clone --depth 1 -b z3-4.8.7 https://github.com/Z3Prover/z3.git \
/usr/src/z3; \ /usr/src/z3; \
cd /usr/src/z3; \ cd /usr/src/z3; \
python scripts/mk_make.py --prefix=/usr ; \ python scripts/mk_make.py --prefix=/usr ; \

View File

@ -43,13 +43,13 @@ then
./scripts/install_obsolete_jsoncpp_1_7_4.sh ./scripts/install_obsolete_jsoncpp_1_7_4.sh
# z3 # z3
wget https://github.com/Z3Prover/z3/releases/download/z3-4.8.6/z3-4.8.6-x64-osx-10.14.6.zip wget https://github.com/Z3Prover/z3/releases/download/z3-4.8.7/z3-4.8.7-x64-osx-10.14.6.zip
unzip z3-4.8.6-x64-osx-10.14.6.zip unzip z3-4.8.7-x64-osx-10.14.6.zip
rm -f z3-4.8.6-x64-osx-10.14.6.zip rm -f z3-4.8.7-x64-osx-10.14.6.zip
cp z3-4.8.6-x64-osx-10.14.6/bin/libz3.a /usr/local/lib cp z3-4.8.7-x64-osx-10.14.6/bin/libz3.a /usr/local/lib
cp z3-4.8.6-x64-osx-10.14.6/bin/z3 /usr/local/bin cp z3-4.8.7-x64-osx-10.14.6/bin/z3 /usr/local/bin
cp z3-4.8.6-x64-osx-10.14.6/include/* /usr/local/include cp z3-4.8.7-x64-osx-10.14.6/include/* /usr/local/include
rm -rf z3-4.8.6-x64-osx-10.14.6 rm -rf z3-4.8.7-x64-osx-10.14.6
# evmone # evmone
wget https://github.com/ethereum/evmone/releases/download/v0.3.0/evmone-0.3.0-darwin-x86_64.tar.gz wget https://github.com/ethereum/evmone/releases/download/v0.3.0/evmone-0.3.0-darwin-x86_64.tar.gz

View File

@ -98,33 +98,25 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm):
evmc::address address{}; evmc::address address{};
address.bytes[19] = precompiledAddress; address.bytes[19] = precompiledAddress;
// 1wei // 1wei
m_state.accounts[address].balance.bytes[31] = 1; accounts[address].balance.bytes[31] = 1;
} }
}
evmc_storage_status EVMHost::set_storage(const evmc::address& _addr, const evmc::bytes32& _key, const evmc::bytes32& _value) noexcept
{
evmc::bytes32 previousValue = m_state.accounts[_addr].storage[_key];
m_state.accounts[_addr].storage[_key] = _value;
// TODO EVMC_STORAGE_MODIFIED_AGAIN should be also used
if (previousValue == _value)
return EVMC_STORAGE_UNCHANGED;
else if (previousValue == evmc::bytes32{})
return EVMC_STORAGE_ADDED;
else if (_value == evmc::bytes32{})
return EVMC_STORAGE_DELETED;
else
return EVMC_STORAGE_MODIFIED;
// TODO: support short literals in EVMC and use them here
tx_context.block_difficulty = convertToEVMC(u256("200000000"));
tx_context.block_gas_limit = 20000000;
tx_context.block_coinbase = 0x7878787878787878787878787878787878787878_address;
tx_context.tx_gas_price = convertToEVMC(u256("3000000000"));
tx_context.tx_origin = 0x9292929292929292929292929292929292929292_address;
// Mainnet according to EIP-155
tx_context.chain_id = convertToEVMC(u256(1));
} }
void EVMHost::selfdestruct(const evmc::address& _addr, const evmc::address& _beneficiary) noexcept void EVMHost::selfdestruct(const evmc::address& _addr, const evmc::address& _beneficiary) noexcept
{ {
// TODO actual selfdestruct is even more complicated. // TODO actual selfdestruct is even more complicated.
evmc::uint256be balance = m_state.accounts[_addr].balance; evmc::uint256be balance = accounts[_addr].balance;
m_state.accounts.erase(_addr); accounts.erase(_addr);
m_state.accounts[_beneficiary].balance = balance; accounts[_beneficiary].balance = balance;
} }
evmc::result EVMHost::call(evmc_message const& _message) noexcept evmc::result EVMHost::call(evmc_message const& _message) noexcept
@ -146,12 +138,12 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
else if (_message.destination == 0x0000000000000000000000000000000000000008_address && m_evmVersion >= langutil::EVMVersion::byzantium()) else if (_message.destination == 0x0000000000000000000000000000000000000008_address && m_evmVersion >= langutil::EVMVersion::byzantium())
return precompileALTBN128PairingProduct(_message); return precompileALTBN128PairingProduct(_message);
State stateBackup = m_state; auto const stateBackup = accounts;
u256 value{convertFromEVMC(_message.value)}; u256 value{convertFromEVMC(_message.value)};
Account& sender = m_state.accounts[_message.sender]; auto& sender = accounts[_message.sender];
bytes code; evmc::bytes code;
evmc_message message = _message; evmc_message message = _message;
if (message.depth == 0) if (message.depth == 0)
@ -163,7 +155,7 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
{ {
evmc::result result({}); evmc::result result({});
result.status_code = EVMC_OUT_OF_GAS; result.status_code = EVMC_OUT_OF_GAS;
m_state = stateBackup; accounts = stateBackup;
return result; return result;
} }
} }
@ -177,23 +169,23 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
asBytes(to_string(sender.nonce++)) asBytes(to_string(sender.nonce++))
)); ));
message.destination = convertToEVMC(createAddress); message.destination = convertToEVMC(createAddress);
code = bytes(message.input_data, message.input_data + message.input_size); code = evmc::bytes(message.input_data, message.input_data + message.input_size);
} }
else if (message.kind == EVMC_DELEGATECALL) else if (message.kind == EVMC_DELEGATECALL)
{ {
code = m_state.accounts[message.destination].code; code = accounts[message.destination].code;
message.destination = m_currentAddress; message.destination = m_currentAddress;
} }
else if (message.kind == EVMC_CALLCODE) else if (message.kind == EVMC_CALLCODE)
{ {
code = m_state.accounts[message.destination].code; code = accounts[message.destination].code;
message.destination = m_currentAddress; message.destination = m_currentAddress;
} }
else else
code = m_state.accounts[message.destination].code; code = accounts[message.destination].code;
//TODO CREATE2 //TODO CREATE2
Account& destination = m_state.accounts[message.destination]; auto& destination = accounts[message.destination];
if (value != 0 && message.kind != EVMC_DELEGATECALL && message.kind != EVMC_CALLCODE) if (value != 0 && message.kind != EVMC_DELEGATECALL && message.kind != EVMC_CALLCODE)
{ {
@ -218,55 +210,22 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
else else
{ {
result.create_address = message.destination; result.create_address = message.destination;
destination.code = bytes(result.output_data, result.output_data + result.output_size); destination.code = evmc::bytes(result.output_data, result.output_data + result.output_size);
destination.codeHash = convertToEVMC(keccak256(destination.code)); destination.codehash = convertToEVMC(keccak256({result.output_data, result.output_size}));
} }
} }
if (result.status_code != EVMC_SUCCESS) if (result.status_code != EVMC_SUCCESS)
m_state = stateBackup; accounts = stateBackup;
return result; return result;
} }
evmc_tx_context EVMHost::get_tx_context() const noexcept
{
evmc_tx_context ctx = {};
ctx.block_timestamp = m_state.timestamp;
ctx.block_number = m_state.blockNumber;
ctx.block_coinbase = m_coinbase;
// TODO: support short literals in EVMC and use them here
ctx.block_difficulty = convertToEVMC(u256("200000000"));
ctx.block_gas_limit = 20000000;
ctx.tx_gas_price = convertToEVMC(u256("3000000000"));
ctx.tx_origin = 0x9292929292929292929292929292929292929292_address;
// Mainnet according to EIP-155
ctx.chain_id = convertToEVMC(u256(1));
return ctx;
}
evmc::bytes32 EVMHost::get_block_hash(int64_t _number) const noexcept evmc::bytes32 EVMHost::get_block_hash(int64_t _number) const noexcept
{ {
return convertToEVMC(u256("0x3737373737373737373737373737373737373737373737373737373737373737") + _number); return convertToEVMC(u256("0x3737373737373737373737373737373737373737373737373737373737373737") + _number);
} }
void EVMHost::emit_log(
evmc::address const& _addr,
uint8_t const* _data,
size_t _dataSize,
evmc::bytes32 const _topics[],
size_t _topicsCount
) noexcept
{
LogEntry entry;
entry.address = convertFromEVMC(_addr);
for (size_t i = 0; i < _topicsCount; ++i)
entry.topics.emplace_back(convertFromEVMC(_topics[i]));
entry.data = bytes(_data, _data + _dataSize);
m_state.logs.emplace_back(std::move(entry));
}
Address EVMHost::convertFromEVMC(evmc::address const& _addr) Address EVMHost::convertFromEVMC(evmc::address const& _addr)
{ {
return Address(bytes(begin(_addr.bytes), end(_addr.bytes))); return Address(bytes(begin(_addr.bytes), end(_addr.bytes)));

View File

@ -21,6 +21,7 @@
#pragma once #pragma once
#include <test/evmc/mocked_host.hpp>
#include <test/evmc/evmc.hpp> #include <test/evmc/evmc.hpp>
#include <test/evmc/evmc.h> #include <test/evmc/evmc.h>
@ -34,9 +35,12 @@ namespace test
{ {
using Address = h160; using Address = h160;
class EVMHost: public evmc::Host class EVMHost: public evmc::MockedHost
{ {
public: public:
using MockedHost::get_code_size;
using MockedHost::get_balance;
/// Tries to dynamically load libevmone. @returns nullptr on failure. /// Tries to dynamically load libevmone. @returns nullptr on failure.
/// The path has to be provided for the first successful run and will be ignored /// The path has to be provided for the first successful run and will be ignored
/// afterwards. /// afterwards.
@ -44,134 +48,33 @@ public:
explicit EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm = getVM()); explicit EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm = getVM());
struct Account void reset() { accounts.clear(); m_currentAddress = {}; }
{
evmc::uint256be balance = {};
size_t nonce = 0;
bytes code;
evmc::bytes32 codeHash = {};
std::map<evmc::bytes32, evmc::bytes32> storage;
};
struct LogEntry
{
Address address;
std::vector<h256> topics;
bytes data;
};
struct State
{
size_t blockNumber;
uint64_t timestamp;
std::map<evmc::address, Account> accounts;
std::vector<LogEntry> logs;
};
Account const* account(evmc::address const& _address) const
{
auto it = m_state.accounts.find(_address);
return it == m_state.accounts.end() ? nullptr : &it->second;
}
Account* account(evmc::address const& _address)
{
auto it = m_state.accounts.find(_address);
return it == m_state.accounts.end() ? nullptr : &it->second;
}
void reset() { m_state = State{}; m_currentAddress = {}; }
void newBlock() void newBlock()
{ {
m_state.blockNumber++; tx_context.block_number++;
m_state.timestamp += 15; tx_context.block_timestamp += 15;
m_state.logs.clear(); recorded_logs.clear();
} }
bool account_exists(evmc::address const& _addr) const noexcept final bool account_exists(evmc::address const& _addr) const noexcept final
{ {
return account(_addr) != nullptr; return evmc::MockedHost::account_exists(_addr);
} }
evmc::bytes32 get_storage(evmc::address const& _addr, evmc::bytes32 const& _key) const noexcept final void selfdestruct(evmc::address const& _addr, evmc::address const& _beneficiary) noexcept final;
{
if (auto* acc = account(_addr))
{
auto it = acc->storage.find(_key);
if (it != acc->storage.end())
return it->second;
}
return {};
}
evmc_storage_status set_storage( evmc::result call(evmc_message const& _message) noexcept final;
evmc::address const& _addr,
evmc::bytes32 const& _key,
evmc::bytes32 const& _value
) noexcept;
evmc::uint256be get_balance(evmc::address const& _addr) const noexcept final evmc::bytes32 get_block_hash(int64_t number) const noexcept final;
{
if (Account const* acc = account(_addr))
return acc->balance;
return {};
}
size_t get_code_size(evmc::address const& _addr) const noexcept final
{
if (Account const* acc = account(_addr))
return acc->code.size();
return 0;
}
evmc::bytes32 get_code_hash(evmc::address const& _addr) const noexcept final
{
if (Account const* acc = account(_addr))
return acc->codeHash;
return {};
}
size_t copy_code(
evmc::address const& _addr,
size_t _codeOffset,
uint8_t* _bufferData,
size_t _bufferSize
) const noexcept final
{
size_t i = 0;
if (Account const* acc = account(_addr))
for (; i < _bufferSize && _codeOffset + i < acc->code.size(); i++)
_bufferData[i] = acc->code[_codeOffset + i];
return i;
}
void selfdestruct(evmc::address const& _addr, evmc::address const& _beneficiary) noexcept;
evmc::result call(evmc_message const& _message) noexcept;
evmc_tx_context get_tx_context() const noexcept;
evmc::bytes32 get_block_hash(int64_t number) const noexcept;
void emit_log(
evmc::address const& _addr,
uint8_t const* _data,
size_t _dataSize,
evmc::bytes32 const _topics[],
size_t _topicsCount
) noexcept;
static Address convertFromEVMC(evmc::address const& _addr); static Address convertFromEVMC(evmc::address const& _addr);
static evmc::address convertToEVMC(Address const& _addr); static evmc::address convertToEVMC(Address const& _addr);
static h256 convertFromEVMC(evmc::bytes32 const& _data); static h256 convertFromEVMC(evmc::bytes32 const& _data);
static evmc::bytes32 convertToEVMC(h256 const& _data); static evmc::bytes32 convertToEVMC(h256 const& _data);
State m_state;
evmc::address m_currentAddress = {};
evmc::address m_coinbase = convertToEVMC(Address("0x7878787878787878787878787878787878787878"));
private: private:
evmc::address m_currentAddress = {};
static evmc::result precompileECRecover(evmc_message const& _message) noexcept; static evmc::result precompileECRecover(evmc_message const& _message) noexcept;
static evmc::result precompileSha256(evmc_message const& _message) noexcept; static evmc::result precompileSha256(evmc_message const& _message) noexcept;
static evmc::result precompileRipeMD160(evmc_message const& _message) noexcept; static evmc::result precompileRipeMD160(evmc_message const& _message) noexcept;

View File

@ -25,7 +25,6 @@
#include <test/EVMHost.h> #include <test/EVMHost.h>
#include <test/evmc/evmc.hpp> #include <test/evmc/evmc.hpp>
#include <test/evmc/loader.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
@ -56,7 +55,7 @@ ExecutionFramework::ExecutionFramework(langutil::EVMVersion _evmVersion):
m_evmHost->reset(); m_evmHost->reset();
for (size_t i = 0; i < 10; i++) for (size_t i = 0; i < 10; i++)
m_evmHost->m_state.accounts[EVMHost::convertToEVMC(account(i))].balance = m_evmHost->accounts[EVMHost::convertToEVMC(account(i))].balance =
EVMHost::convertToEVMC(u256(1) << 100); EVMHost::convertToEVMC(u256(1) << 100);
} }
@ -89,12 +88,12 @@ std::pair<bool, string> ExecutionFramework::compareAndCreateMessage(
u256 ExecutionFramework::gasLimit() const u256 ExecutionFramework::gasLimit() const
{ {
return {m_evmHost->get_tx_context().block_gas_limit}; return {m_evmHost->tx_context.block_gas_limit};
} }
u256 ExecutionFramework::gasPrice() const u256 ExecutionFramework::gasPrice() const
{ {
return {EVMHost::convertFromEVMC(m_evmHost->get_tx_context().tx_gas_price)}; return {EVMHost::convertFromEVMC(m_evmHost->tx_context.tx_gas_price)};
} }
u256 ExecutionFramework::blockHash(u256 const& _number) const u256 ExecutionFramework::blockHash(u256 const& _number) const
@ -104,7 +103,7 @@ u256 ExecutionFramework::blockHash(u256 const& _number) const
u256 ExecutionFramework::blockNumber() const u256 ExecutionFramework::blockNumber() const
{ {
return m_evmHost->m_state.blockNumber; return m_evmHost->tx_context.block_number;
} }
void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 const& _value) void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 const& _value)
@ -178,7 +177,7 @@ void ExecutionFramework::sendEther(Address const& _addr, u256 const& _amount)
size_t ExecutionFramework::currentTimestamp() size_t ExecutionFramework::currentTimestamp()
{ {
return m_evmHost->get_tx_context().block_timestamp; return m_evmHost->tx_context.block_timestamp;
} }
size_t ExecutionFramework::blockTimestamp(u256 _block) size_t ExecutionFramework::blockTimestamp(u256 _block)
@ -201,27 +200,30 @@ bool ExecutionFramework::addressHasCode(Address const& _addr)
size_t ExecutionFramework::numLogs() const size_t ExecutionFramework::numLogs() const
{ {
return m_evmHost->m_state.logs.size(); return m_evmHost->recorded_logs.size();
} }
size_t ExecutionFramework::numLogTopics(size_t _logIdx) const size_t ExecutionFramework::numLogTopics(size_t _logIdx) const
{ {
return m_evmHost->m_state.logs.at(_logIdx).topics.size(); return m_evmHost->recorded_logs.at(_logIdx).topics.size();
} }
h256 ExecutionFramework::logTopic(size_t _logIdx, size_t _topicIdx) const h256 ExecutionFramework::logTopic(size_t _logIdx, size_t _topicIdx) const
{ {
return m_evmHost->m_state.logs.at(_logIdx).topics.at(_topicIdx); return EVMHost::convertFromEVMC(m_evmHost->recorded_logs.at(_logIdx).topics.at(_topicIdx));
} }
Address ExecutionFramework::logAddress(size_t _logIdx) const Address ExecutionFramework::logAddress(size_t _logIdx) const
{ {
return m_evmHost->m_state.logs.at(_logIdx).address; return EVMHost::convertFromEVMC(m_evmHost->recorded_logs.at(_logIdx).creator);
} }
bytes const& ExecutionFramework::logData(size_t _logIdx) const bytes ExecutionFramework::logData(size_t _logIdx) const
{ {
return m_evmHost->m_state.logs.at(_logIdx).data; const auto& data = m_evmHost->recorded_logs.at(_logIdx).data;
// TODO: Return a copy of log data, because this is expected from REQUIRE_LOG_DATA(),
// but reference type like string_view would be preferable.
return {data.begin(), data.end()};
} }
u256 ExecutionFramework::balanceAt(Address const& _addr) u256 ExecutionFramework::balanceAt(Address const& _addr)
@ -231,10 +233,11 @@ u256 ExecutionFramework::balanceAt(Address const& _addr)
bool ExecutionFramework::storageEmpty(Address const& _addr) bool ExecutionFramework::storageEmpty(Address const& _addr)
{ {
if (EVMHost::Account const* acc = m_evmHost->account(EVMHost::convertToEVMC(_addr))) const auto it = m_evmHost->accounts.find(EVMHost::convertToEVMC(_addr));
if (it != m_evmHost->accounts.end())
{ {
for (auto const& entry: acc->storage) for (auto const& entry: it->second.storage)
if (!(entry.second == evmc::bytes32{})) if (!(entry.second.value == evmc::bytes32{}))
return false; return false;
} }
return true; return true;

View File

@ -267,7 +267,7 @@ protected:
size_t numLogTopics(size_t _logIdx) const; size_t numLogTopics(size_t _logIdx) const;
h256 logTopic(size_t _logIdx, size_t _topicIdx) const; h256 logTopic(size_t _logIdx, size_t _topicIdx) const;
Address logAddress(size_t _logIdx) const; Address logAddress(size_t _logIdx) const;
bytes const& logData(size_t _logIdx) const; bytes logData(size_t _logIdx) const;
langutil::EVMVersion m_evmVersion; langutil::EVMVersion m_evmVersion;
solidity::RevertStrings m_revertStrings = solidity::RevertStrings::Default; solidity::RevertStrings m_revertStrings = solidity::RevertStrings::Default;

View File

@ -27,7 +27,6 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <string> #include <string>
#include <tuple>
using namespace std; using namespace std;
using namespace dev::test; using namespace dev::test;
@ -280,8 +279,7 @@ protected:
} }
}; };
size_t const m_biddingTime = size_t(7 * 24 * 3600); int64_t const m_biddingTime = 7 * 24 * 3600;
size_t const m_renewalInterval = size_t(365 * 24 * 3600);
}; };
} }
@ -417,7 +415,7 @@ BOOST_AUTO_TEST_CASE(auction_simple)
BOOST_CHECK_EQUAL(registrar.owner(name), 0); BOOST_CHECK_EQUAL(registrar.owner(name), 0);
// "wait" until auction end // "wait" until auction end
m_evmHost->m_state.timestamp += m_biddingTime + 10; m_evmHost->tx_context.block_timestamp += m_biddingTime + 10;
// trigger auction again // trigger auction again
registrar.reserve(name); registrar.reserve(name);
BOOST_CHECK_EQUAL(registrar.owner(name), m_sender); BOOST_CHECK_EQUAL(registrar.owner(name), m_sender);
@ -429,7 +427,7 @@ BOOST_AUTO_TEST_CASE(auction_bidding)
string name = "x"; string name = "x";
unsigned startTime = 0x776347e2; unsigned startTime = 0x776347e2;
m_evmHost->m_state.timestamp = startTime; m_evmHost->tx_context.block_timestamp = startTime;
RegistrarInterface registrar(*this); RegistrarInterface registrar(*this);
// initiate auction // initiate auction
@ -437,19 +435,19 @@ BOOST_AUTO_TEST_CASE(auction_bidding)
registrar.reserve(name); registrar.reserve(name);
BOOST_CHECK_EQUAL(registrar.owner(name), 0); BOOST_CHECK_EQUAL(registrar.owner(name), 0);
// overbid self // overbid self
m_evmHost->m_state.timestamp = startTime + m_biddingTime - 10; m_evmHost->tx_context.block_timestamp = startTime + m_biddingTime - 10;
registrar.setNextValue(12); registrar.setNextValue(12);
registrar.reserve(name); registrar.reserve(name);
// another bid by someone else // another bid by someone else
sendEther(account(1), 10 * ether); sendEther(account(1), 10 * ether);
m_sender = account(1); m_sender = account(1);
m_evmHost->m_state.timestamp = startTime + 2 * m_biddingTime - 50; m_evmHost->tx_context.block_timestamp = startTime + 2 * m_biddingTime - 50;
registrar.setNextValue(13); registrar.setNextValue(13);
registrar.reserve(name); registrar.reserve(name);
BOOST_CHECK_EQUAL(registrar.owner(name), 0); BOOST_CHECK_EQUAL(registrar.owner(name), 0);
// end auction by first bidder (which is not highest) trying to overbid again (too late) // end auction by first bidder (which is not highest) trying to overbid again (too late)
m_sender = account(0); m_sender = account(0);
m_evmHost->m_state.timestamp = startTime + 4 * m_biddingTime; m_evmHost->tx_context.block_timestamp = startTime + 4 * m_biddingTime;
registrar.setNextValue(20); registrar.setNextValue(20);
registrar.reserve(name); registrar.reserve(name);
BOOST_CHECK_EQUAL(registrar.owner(name), account(1)); BOOST_CHECK_EQUAL(registrar.owner(name), account(1));

View File

@ -1115,7 +1115,7 @@ BOOST_AUTO_TEST_CASE(blockchain)
} }
} }
)"; )";
m_evmHost->m_coinbase = EVMHost::convertToEVMC(Address("0x1212121212121212121212121212121212121212")); m_evmHost->tx_context.block_coinbase = EVMHost::convertToEVMC(Address("0x1212121212121212121212121212121212121212"));
m_evmHost->newBlock(); m_evmHost->newBlock();
m_evmHost->newBlock(); m_evmHost->newBlock();
m_evmHost->newBlock(); m_evmHost->newBlock();

View File

@ -1,19 +0,0 @@
pragma experimental SMTChecker;
contract Simple {
uint[] a;
function f(uint n) public {
uint i;
while (i < n)
{
a[i] = i;
++i;
}
require(n > 1);
// Assertion is safe but current solver version cannot solve it.
// Keep test for next solver release.
assert(a[n-1] > a[n-2]);
}
}
// ----
// Warning: (273-296): Assertion violation happens here

View File

@ -0,0 +1,26 @@
pragma experimental SMTChecker;
contract LoopFor2 {
uint[] b;
uint[] c;
function testUnboundedForLoop(uint n) public {
b[0] = 900;
uint[] storage a = b;
require(n > 0 && n < 100);
uint i;
while (i < n) {
b[i] = i + 1;
c[i] = b[i];
++i;
}
// Fails as false positive.
assert(b[0] == c[0]);
assert(a[0] == 900);
assert(b[0] == 900);
}
}
// ----
// Warning: (296-316): Assertion violation happens here
// Warning: (320-339): Assertion violation happens here
// Warning: (343-362): Assertion violation happens here