aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libsolidity/codegen/ABIFunctions.cpp37
-rw-r--r--libsolidity/codegen/ABIFunctions.h6
-rw-r--r--libsolidity/formal/SMTChecker.cpp10
-rw-r--r--test/libsolidity/ABIEncoderTests.cpp81
-rw-r--r--test/libsolidity/SMTChecker.cpp26
5 files changed, 135 insertions, 25 deletions
diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp
index 756148e7..080be359 100644
--- a/libsolidity/codegen/ABIFunctions.cpp
+++ b/libsolidity/codegen/ABIFunctions.cpp
@@ -87,7 +87,7 @@ string ABIFunctions::tupleEncoder(
);
elementTempl("values", valueNames);
elementTempl("pos", to_string(headPos));
- elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], _encodeAsLibraryTypes, false));
+ elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], _encodeAsLibraryTypes, true));
encodeElements += elementTempl.render();
headPos += dynamic ? 0x20 : _targetTypes[i]->calldataEncodedSize();
}
@@ -371,7 +371,7 @@ string ABIFunctions::abiEncodingFunction(
Type const& _from,
Type const& _to,
bool _encodeAsLibraryTypes,
- bool _compacted
+ bool _fromStack
)
{
solUnimplementedAssert(
@@ -415,7 +415,7 @@ string ABIFunctions::abiEncodingFunction(
dynamic_cast<FunctionType const&>(_from),
to,
_encodeAsLibraryTypes,
- _compacted
+ _fromStack
);
solAssert(_from.sizeOnStack() == 1, "");
@@ -542,7 +542,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray(
mstore(pos, sub(tail, headStart))
tail := <encodeToMemoryFun>(<arrayElementAccess>, tail)
srcPtr := <nextArrayElement>(srcPtr)
- pos := add(pos, <elementEncodedSize>)
+ pos := add(pos, 0x20)
}
pos := tail
<assignEnd>
@@ -580,7 +580,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray(
*_from.baseType(),
*_to.baseType(),
_encodeAsLibraryTypes,
- true
+ false
));
templ("arrayElementAccess", inMemory ? "mload(srcPtr)" : _from.baseType()->isValueType() ? "sload(srcPtr)" : "srcPtr" );
templ("nextArrayElement", nextArrayElementFunction(_from));
@@ -729,7 +729,7 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray(
*_from.baseType(),
*_to.baseType(),
_encodeAsLibraryTypes,
- true
+ false
);
templ("encodeToMemoryFun", encodeToMemoryFun);
std::vector<std::map<std::string, std::string>> items(itemsPerSlot);
@@ -925,7 +925,7 @@ string ABIFunctions::abiEncodingFunctionFunctionType(
FunctionType const& _from,
Type const& _to,
bool _encodeAsLibraryTypes,
- bool _compacted
+ bool _fromStack
)
{
solAssert(_from.kind() == FunctionType::Kind::External, "");
@@ -936,35 +936,31 @@ string ABIFunctions::abiEncodingFunctionFunctionType(
_from.identifier() +
"_to_" +
_to.identifier() +
- (_compacted ? "_compacted" : "") +
+ (_fromStack ? "_fromStack" : "") +
(_encodeAsLibraryTypes ? "_library" : "");
- if (_compacted)
- {
+ if (_fromStack)
return createFunction(functionName, [&]() {
return Whiskers(R"(
- function <functionName>(addr_and_function_id, pos) {
- mstore(pos, <cleanExtFun>(addr_and_function_id))
+ function <functionName>(addr, function_id, pos) {
+ mstore(pos, <combineExtFun>(addr, function_id))
}
)")
("functionName", functionName)
- ("cleanExtFun", cleanupCombinedExternalFunctionIdFunction())
+ ("combineExtFun", combineExternalFunctionIdFunction())
.render();
});
- }
else
- {
return createFunction(functionName, [&]() {
return Whiskers(R"(
- function <functionName>(addr, function_id, pos) {
- mstore(pos, <combineExtFun>(addr, function_id))
+ function <functionName>(addr_and_function_id, pos) {
+ mstore(pos, <cleanExtFun>(addr_and_function_id))
}
)")
("functionName", functionName)
- ("combineExtFun", combineExternalFunctionIdFunction())
+ ("cleanExtFun", cleanupCombinedExternalFunctionIdFunction())
.render();
});
- }
}
string ABIFunctions::copyToMemoryFunction(bool _fromCalldata)
@@ -1212,10 +1208,7 @@ size_t ABIFunctions::headSize(TypePointers const& _targetTypes)
if (t->isDynamicallyEncoded())
headSize += 0x20;
else
- {
- solAssert(t->calldataEncodedSize() > 0, "");
headSize += t->calldataEncodedSize();
- }
}
return headSize;
diff --git a/libsolidity/codegen/ABIFunctions.h b/libsolidity/codegen/ABIFunctions.h
index de2a140a..e61f68bc 100644
--- a/libsolidity/codegen/ABIFunctions.h
+++ b/libsolidity/codegen/ABIFunctions.h
@@ -89,13 +89,13 @@ private:
/// @returns the name of the ABI encoding function with the given type
/// and queues the generation of the function to the requested functions.
- /// @param _compacted if true, the input value was just loaded from storage
+ /// @param _fromStack if false, the input value was just loaded from storage
/// or memory and thus might be compacted into a single slot (depending on the type).
std::string abiEncodingFunction(
Type const& _givenType,
Type const& _targetType,
bool _encodeAsLibraryTypes,
- bool _compacted
+ bool _fromStack
);
/// Part of @a abiEncodingFunction for array target type and given calldata array.
std::string abiEncodingFunctionCalldataArray(
@@ -143,7 +143,7 @@ private:
FunctionType const& _from,
Type const& _to,
bool _encodeAsLibraryTypes,
- bool _compacted
+ bool _fromStack
);
/// @returns a function that copies raw bytes of dynamic length from calldata
diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp
index fd78e578..7c8c089e 100644
--- a/libsolidity/formal/SMTChecker.cpp
+++ b/libsolidity/formal/SMTChecker.cpp
@@ -234,6 +234,16 @@ void SMTChecker::endVisit(BinaryOperation const& _op)
void SMTChecker::endVisit(FunctionCall const& _funCall)
{
+ solAssert(_funCall.annotation().kind != FunctionCallKind::Unset, "");
+ if (_funCall.annotation().kind != FunctionCallKind::FunctionCall)
+ {
+ m_errorReporter.warning(
+ _funCall.location(),
+ "Assertion checker does not yet implement this expression."
+ );
+ return;
+ }
+
FunctionType const& funType = dynamic_cast<FunctionType const&>(*_funCall.expression().annotation().type);
std::vector<ASTPointer<Expression const>> const args = _funCall.arguments();
diff --git a/test/libsolidity/ABIEncoderTests.cpp b/test/libsolidity/ABIEncoderTests.cpp
index 05158601..af51edcc 100644
--- a/test/libsolidity/ABIEncoderTests.cpp
+++ b/test/libsolidity/ABIEncoderTests.cpp
@@ -462,6 +462,87 @@ BOOST_AUTO_TEST_CASE(structs)
)
}
+BOOST_AUTO_TEST_CASE(empty_struct)
+{
+ string sourceCode = R"(
+ contract C {
+ struct S { }
+ S s;
+ event e(uint16, S, uint16);
+ function f() returns (uint, S, uint) {
+ e(7, s, 8);
+ return (7, s, 8);
+ }
+ }
+ )";
+
+ NEW_ENCODER(
+ compileAndRun(sourceCode, 0, "C");
+ bytes encoded = encodeArgs(7, 8);
+ BOOST_CHECK(callContractFunction("f()") == encoded);
+ REQUIRE_LOG_DATA(encoded);
+ )
+}
+
+BOOST_AUTO_TEST_CASE(structs2)
+{
+ string sourceCode = R"(
+ contract C {
+ enum E {A, B, C}
+ struct T { uint x; E e; uint8 y; }
+ struct S { C c; T[] t;}
+ function f() public returns (uint a, S[2] s1, S[] s2, uint b) {
+ a = 7;
+ b = 8;
+ s1[0].c = this;
+ s1[0].t = new T[](1);
+ s1[0].t[0].x = 0x11;
+ s1[0].t[0].e = E.B;
+ s1[0].t[0].y = 0x12;
+ s2 = new S[](2);
+ s2[1].c = C(0x1234);
+ s2[1].t = new T[](3);
+ s2[1].t[1].x = 0x21;
+ s2[1].t[1].e = E.C;
+ s2[1].t[1].y = 0x22;
+ }
+ }
+ )";
+
+ NEW_ENCODER(
+ compileAndRun(sourceCode, 0, "C");
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(
+ 7, 0x80, 0x1e0, 8,
+ // S[2] s1
+ 0x40,
+ 0x100,
+ // S s1[0]
+ u256(u160(m_contractAddress)),
+ 0x40,
+ // T s1[0].t
+ 1, // length
+ // s1[0].t[0]
+ 0x11, 1, 0x12,
+ // S s1[1]
+ 0, 0x40,
+ // T s1[1].t
+ 0,
+ // S[] s2 (0x1e0)
+ 2, // length
+ 0x40, 0xa0,
+ // S s2[0]
+ 0, 0x40, 0,
+ // S s2[1]
+ 0x1234, 0x40,
+ // s2[1].t
+ 3, // length
+ 0, 0, 0,
+ 0x21, 2, 0x22,
+ 0, 0, 0
+ ));
+ )
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp
index d58f296f..8d712a80 100644
--- a/test/libsolidity/SMTChecker.cpp
+++ b/test/libsolidity/SMTChecker.cpp
@@ -79,6 +79,32 @@ BOOST_AUTO_TEST_CASE(simple_overflow)
CHECK_WARNING(text, "Overflow (resulting value larger than");
}
+BOOST_AUTO_TEST_CASE(warn_on_typecast)
+{
+ string text = R"(
+ contract C {
+ function f() public pure returns (uint) {
+ return uint8(1);
+ }
+ }
+ )";
+ CHECK_WARNING(text, "Assertion checker does not yet implement this expression.");
+}
+
+BOOST_AUTO_TEST_CASE(warn_on_struct)
+{
+ string text = R"(
+ contract C {
+ struct A { uint a; uint b; }
+ function f() public pure returns (A) {
+ return A({ a: 1, b: 2 });
+ }
+ }
+ )";
+ /// Multiple warnings, should check for: Assertion checker does not yet implement this expression.
+ CHECK_WARNING_ALLOW_MULTI(text, "");
+}
+
BOOST_AUTO_TEST_SUITE_END()
}