diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h
index 02d52f495..021f97de8 100644
--- a/libdevcrypto/Common.h
+++ b/libdevcrypto/Common.h
@@ -47,7 +47,7 @@ struct SignatureStruct
{
SignatureStruct() {}
SignatureStruct(Signature const& _s) { *(h520*)this = _s; }
- SignatureStruct(h256 _r, h256 _s, byte _v): r(_r), s(_s), v(_v) {}
+ SignatureStruct(h256 const& _r, h256 const& _s, byte _v): r(_r), s(_s), v(_v) {}
operator Signature() const { return *(h520 const*)this; }
/// @returns true if r,s,v values are valid, otherwise false
diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp
index 1edfe3927..0c1173134 100644
--- a/libethereum/Transaction.cpp
+++ b/libethereum/Transaction.cpp
@@ -43,7 +43,10 @@ Transaction::Transaction(bytesConstRef _rlpData, bool _checkSender)
m_receiveAddress = rlp[field = 3].toHash
();
m_value = rlp[field = 4].toInt();
m_data = rlp[field = 5].toBytes();
- m_vrs = SignatureStruct{ rlp[field = 7].toInt(), rlp[field = 8].toInt(), byte(rlp[field = 6].toInt() - 27) };
+ h256 r = rlp[field = 7].toInt();
+ h256 s = rlp[field = 8].toInt();
+ byte v = rlp[field = 6].toInt() - 27;
+ m_vrs = SignatureStruct{ r, s, v };
if (_checkSender)
m_sender = sender();
}
diff --git a/libevmcore/Assembly.cpp b/libevmcore/Assembly.cpp
index 74bd015a6..5efbb9487 100644
--- a/libevmcore/Assembly.cpp
+++ b/libevmcore/Assembly.cpp
@@ -478,7 +478,6 @@ bytes Assembly::assemble() const
bytes ret;
unsigned totalBytes = bytesRequired();
- ret.reserve(totalBytes);
vector tagPos(m_usedTags);
map tagRef;
multimap dataRef;
@@ -489,6 +488,12 @@ bytes Assembly::assemble() const
for (auto const& i: m_subs)
m_data[i.first] = i.second.assemble();
+ unsigned bytesRequiredIncludingData = bytesRequired();
+ unsigned bytesPerDataRef = dev::bytesRequired(bytesRequiredIncludingData);
+ byte dataRefPush = (byte)Instruction::PUSH1 - 1 + bytesPerDataRef;
+ ret.reserve(bytesRequiredIncludingData);
+ // m_data must not change from here on
+
for (AssemblyItem const& i: m_items)
switch (i.m_type)
{
@@ -526,9 +531,9 @@ bytes Assembly::assemble() const
}
case PushData: case PushSub:
{
- ret.push_back(tagPush);
+ ret.push_back(dataRefPush);
dataRef.insert(make_pair((h256)i.m_data, ret.size()));
- ret.resize(ret.size() + bytesPerTag);
+ ret.resize(ret.size() + bytesPerDataRef);
break;
}
case PushSubSize:
@@ -542,10 +547,12 @@ bytes Assembly::assemble() const
break;
}
case PushProgramSize:
- ret.push_back(tagPush);
+ {
+ ret.push_back(dataRefPush);
sizeRef.push_back(ret.size());
- ret.resize(ret.size() + bytesPerTag);
+ ret.resize(ret.size() + bytesPerDataRef);
break;
+ }
case Tag:
tagPos[(unsigned)i.m_data] = ret.size();
ret.push_back((byte)Instruction::JUMPDEST);
@@ -573,7 +580,7 @@ bytes Assembly::assemble() const
{
for (auto it = its.first; it != its.second; ++it)
{
- bytesRef r(ret.data() + it->second, bytesPerTag);
+ bytesRef r(ret.data() + it->second, bytesPerDataRef);
toBigEndian(ret.size(), r);
}
for (auto b: i.second)
@@ -583,7 +590,7 @@ bytes Assembly::assemble() const
}
for (unsigned pos: sizeRef)
{
- bytesRef r(ret.data() + pos, bytesPerTag);
+ bytesRef r(ret.data() + pos, bytesPerDataRef);
toBigEndian(ret.size(), r);
}
return ret;
diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp
index 1242c0aba..79716fdec 100644
--- a/libsolidity/CompilerStack.cpp
+++ b/libsolidity/CompilerStack.cpp
@@ -36,13 +36,12 @@ namespace dev
namespace solidity
{
-void CompilerStack::addSource(string const& _name, string const& _content)
+bool CompilerStack::addSource(string const& _name, string const& _content)
{
- if (m_sources.count(_name))
- BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Source by given name already exists."));
-
+ bool existed = m_sources.count(_name);
reset(true);
m_sources[_name].scanner = make_shared(CharStream(_content), _name);
+ return existed;
}
void CompilerStack::setSource(string const& _sourceCode)
@@ -181,6 +180,11 @@ SourceUnit const& CompilerStack::getAST(string const& _sourceName) const
return *getSource(_sourceName).ast;
}
+ContractDefinition const& CompilerStack::getContractDefinition(string const& _contractName) const
+{
+ return *getContract(_contractName).contract;
+}
+
bytes CompilerStack::staticCompile(std::string const& _sourceCode, bool _optimize)
{
CompilerStack stack;
@@ -234,9 +238,13 @@ CompilerStack::Contract const& CompilerStack::getContract(string const& _contrac
{
if (m_contracts.empty())
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("No compiled contracts found."));
+ string contractName = _contractName;
if (_contractName.empty())
- return m_contracts.begin()->second;
- auto it = m_contracts.find(_contractName);
+ // try to find the "last contract"
+ for (ASTPointer const& node: m_sourceOrder.back()->ast->getNodes())
+ if (auto contract = dynamic_cast(node.get()))
+ contractName = contract->getName();
+ auto it = m_contracts.find(contractName);
if (it == m_contracts.end())
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Contract " + _contractName + " not found."));
return it->second;
diff --git a/libsolidity/CompilerStack.h b/libsolidity/CompilerStack.h
index 5ad6f0a60..358c8fb77 100644
--- a/libsolidity/CompilerStack.h
+++ b/libsolidity/CompilerStack.h
@@ -57,7 +57,8 @@ public:
CompilerStack(): m_parseSuccessful(false) {}
/// Adds a source object (e.g. file) to the parser. After this, parse has to be called again.
- void addSource(std::string const& _name, std::string const& _content);
+ /// @returns true if a source object by the name already existed and was replaced.
+ bool addSource(std::string const& _name, std::string const& _content);
void setSource(std::string const& _sourceCode);
/// Parses all source units that were added
void parse();
@@ -86,9 +87,13 @@ public:
/// Can be one of 3 types defined at @c DocumentationType
std::string const& getJsonDocumentation(std::string const& _contractName, DocumentationType _type) const;
- /// Returns the previously used scanner, useful for counting lines during error reporting.
+ /// @returns the previously used scanner, useful for counting lines during error reporting.
Scanner const& getScanner(std::string const& _sourceName = "") const;
+ /// @returns the parsed source unit with the supplied name.
SourceUnit const& getAST(std::string const& _sourceName = "") const;
+ /// @returns the parsed contract with the supplied name. Throws an exception if the contract
+ /// does not exist.
+ ContractDefinition const& getContractDefinition(std::string const& _contractName) const;
/// Compile the given @a _sourceCode to bytecode. If a scanner is provided, it is used for
/// scanning the source code - this is useful for printing exception information.
diff --git a/test/stRefundTestFiller.json b/test/stRefundTestFiller.json
new file mode 100644
index 000000000..4060bbb72
--- /dev/null
+++ b/test/stRefundTestFiller.json
@@ -0,0 +1,145 @@
+{
+ "refund_getEtherBack" : {
+ "env" : {
+ "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
+ "currentNumber" : "0",
+ "currentGasLimit" : "1000000",
+ "currentDifficulty" : "256",
+ "currentTimestamp" : 1,
+ "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
+ },
+ "pre" : {
+ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
+ "balance" : "1000000000000000000",
+ "nonce" : 0,
+ "code" : "{ [[ 1 ]] 0 }",
+ "storage" : {
+ "0x01" : "0x01"
+ }
+ },
+ "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
+ "balance" : "1000",
+ "nonce" : 0,
+ "code" : "",
+ "storage": {}
+ }
+ },
+ "transaction" : {
+ "nonce" : "0",
+ "gasPrice" : "1",
+ "gasLimit" : "850",
+ "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
+ "value" : "10",
+ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
+ "data" : ""
+ }
+ },
+
+ "refund_changeNonZeroStorage" : {
+ "env" : {
+ "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
+ "currentNumber" : "0",
+ "currentGasLimit" : "1000000",
+ "currentDifficulty" : "256",
+ "currentTimestamp" : 1,
+ "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
+ },
+ "pre" : {
+ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
+ "balance" : "1000000000000000000",
+ "nonce" : 0,
+ "code" : "{ [[ 1 ]] 23 }",
+ "storage" : {
+ "0x01" : "0x01"
+ }
+ },
+ "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
+ "balance" : "1000",
+ "nonce" : 0,
+ "code" : "",
+ "storage": {}
+ }
+ },
+ "transaction" : {
+ "nonce" : "0",
+ "gasPrice" : "1",
+ "gasLimit" : "850",
+ "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
+ "value" : "10",
+ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
+ "data" : ""
+ }
+ },
+
+ "refund_OOG" : {
+ "env" : {
+ "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
+ "currentNumber" : "0",
+ "currentGasLimit" : "1000000",
+ "currentDifficulty" : "256",
+ "currentTimestamp" : 1,
+ "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
+ },
+ "pre" : {
+ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
+ "balance" : "1000000000000000000",
+ "nonce" : 0,
+ "code" : "{ [[ 1 ]] 0 }",
+ "storage" : {
+ "0x01" : "0x01"
+ }
+ },
+ "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
+ "balance" : "500",
+ "nonce" : 0,
+ "code" : "",
+ "storage": {}
+ }
+ },
+ "transaction" : {
+ "nonce" : "0",
+ "gasPrice" : "1",
+ "gasLimit" : "500",
+ "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
+ "value" : "0",
+ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
+ "data" : ""
+ }
+ },
+
+ "refund_NoOOG_1" : {
+ "env" : {
+ "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
+ "currentNumber" : "0",
+ "currentGasLimit" : "1000000",
+ "currentDifficulty" : "256",
+ "currentTimestamp" : 1,
+ "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
+ },
+ "pre" : {
+ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
+ "balance" : "1000000000000000000",
+ "nonce" : 0,
+ "code" : "{ [[ 1 ]] 0 }",
+ "storage" : {
+ "0x01" : "0x01"
+ }
+ },
+ "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
+ "balance" : "502",
+ "nonce" : 0,
+ "code" : "",
+ "storage": {}
+ }
+ },
+ "transaction" : {
+ "nonce" : "0",
+ "gasPrice" : "1",
+ "gasLimit" : "502",
+ "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
+ "value" : "0",
+ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
+ "data" : ""
+ }
+ }
+}
diff --git a/test/state.cpp b/test/state.cpp
index f183c4813..d8a3dd283 100644
--- a/test/state.cpp
+++ b/test/state.cpp
@@ -140,11 +140,21 @@ BOOST_AUTO_TEST_CASE(stInitCodeTest)
dev::test::executeTests("stInitCodeTest", "/StateTests", dev::test::doStateTests);
}
+BOOST_AUTO_TEST_CASE(stTransactionTest)
+{
+ dev::test::executeTests("stTransactionTest", "/StateTests", dev::test::doStateTests);
+}
+
BOOST_AUTO_TEST_CASE(stSpecialTest)
{
dev::test::executeTests("stSpecialTest", "/StateTests", dev::test::doStateTests);
}
+BOOST_AUTO_TEST_CASE(stRefundTest)
+{
+ dev::test::executeTests("stRefundTest", "/StateTests", dev::test::doStateTests);
+}
+
BOOST_AUTO_TEST_CASE(stCreateTest)
{
for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)