diff options
-rw-r--r-- | test/ExecutionFramework.cpp | 16 | ||||
-rw-r--r-- | test/ExecutionFramework.h | 7 | ||||
-rw-r--r-- | test/RPCSession.cpp | 5 | ||||
-rw-r--r-- | test/RPCSession.h | 1 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 80 |
5 files changed, 109 insertions, 0 deletions
diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index 00f5e697..ea624735 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -85,6 +85,22 @@ std::pair<bool, string> ExecutionFramework::compareAndCreateMessage( return make_pair(false, message); } +u256 ExecutionFramework::gasLimit() const +{ + auto latestBlock = m_rpc.eth_getBlockByNumber("latest", false); + return u256(latestBlock["gasLimit"].asString()); +} + +u256 ExecutionFramework::gasPrice() const +{ + return u256(m_rpc.eth_gasPrice()); +} + +u256 ExecutionFramework::blockHash(u256 const& _blockNumber) const +{ + return u256(m_rpc.eth_getBlockByNumber(toHex(_blockNumber, HexPrefix::Add), false)["hash"].asString()); +} + void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 const& _value) { if (m_showMessages) diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index cdbec81d..0b42f9d0 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -194,6 +194,13 @@ public: return encodeArgs(u256(0x20), u256(_arg.size()), _arg); } + u256 gasLimit() const; + u256 gasPrice() const; + u256 blockHash(u256 const& _blockNumber) const; + u256 const& blockNumber() const { + return m_blockNumber; + } + private: template <class CppFunction, class... Args> auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments) diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp index b9b19b2f..9ac24972 100644 --- a/test/RPCSession.cpp +++ b/test/RPCSession.cpp @@ -207,6 +207,11 @@ string RPCSession::eth_getStorageRoot(string const& _address, string const& _blo 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( diff --git a/test/RPCSession.h b/test/RPCSession.h index 5af2e26a..6e1391b4 100644 --- a/test/RPCSession.h +++ b/test/RPCSession.h @@ -113,6 +113,7 @@ public: 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); diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 5ffdf6af..15cd3f1d 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -2988,6 +2988,86 @@ BOOST_AUTO_TEST_CASE(gas_and_value_basic) BOOST_REQUIRE(callContractFunction("checkState()") == encodeArgs(false, 20 - 5)); } +BOOST_AUTO_TEST_CASE(gasleft_decrease) +{ + char const* sourceCode = R"( + contract C { + uint v; + function f() public returns (bool) { + uint startGas = gasleft(); + v++; + assert(startGas > gasleft()); + return true; + } + function g() public returns (bool) { + uint startGas = gasleft(); + assert(startGas > gasleft()); + return true; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(true)); +} + +BOOST_AUTO_TEST_CASE(gaslimit) +{ + char const* sourceCode = R"( + contract C { + function f() public returns (uint) { + return block.gaslimit; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), encodeArgs(gasLimit())); +} + +BOOST_AUTO_TEST_CASE(gasprice) +{ + char const* sourceCode = R"( + contract C { + function f() public returns (uint) { + return tx.gasprice; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), encodeArgs(gasPrice())); +} + +BOOST_AUTO_TEST_CASE(blockhash) +{ + char const* sourceCode = R"( + contract C { + uint256 counter; + function g() public returns (bool) { counter++; return true; } + function f() public returns (bytes32[] memory r) { + r = new bytes32[](259); + for (uint i = 0; i < 259; i++) + r[i] = blockhash(block.number - 257 + i); + } + } + )"; + compileAndRun(sourceCode); + // generate a sufficient amount of blocks + while (blockNumber() < u256(255)) + ABI_CHECK(callContractFunction("g()"), encodeArgs(true)); + + vector<u256> hashes; + hashes.reserve(259); + // ``blockhash()`` is only valid for the last 256 blocks, otherwise zero + hashes.emplace_back(0); + for (u256 i = blockNumber() - u256(255); i <= blockNumber(); i++) + hashes.emplace_back(blockHash(i)); + // the current block hash is not yet known at execution time and therefore zero + hashes.emplace_back(0); + // future block hashes are zero + hashes.emplace_back(0); + ABI_CHECK(callContractFunction("f()"), encodeDyn(hashes)); +} + BOOST_AUTO_TEST_CASE(value_complex) { char const* sourceCode = R"( |