From 75f01f6a766d0ee43db06a49214179c518cc0edb Mon Sep 17 00:00:00 2001 From: liana Date: Fri, 23 Jan 2015 17:36:12 +0100 Subject: [PATCH 1/6] - added conversion for string/hash of equal sizes - added tests --- libsolidity/ExpressionCompiler.cpp | 30 +++++++++++++- libsolidity/Types.cpp | 16 ++++++++ libsolidity/Types.h | 3 +- test/SolidityEndToEndTest.cpp | 66 ++++++++++++++++++++++++++++++ 4 files changed, 112 insertions(+), 3 deletions(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 60c5c4ded..66ca2ec14 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -628,7 +628,33 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con return; Type::Category stackTypeCategory = _typeOnStack.getCategory(); Type::Category targetTypeCategory = _targetType.getCategory(); - if (stackTypeCategory == Type::Category::INTEGER || stackTypeCategory == Type::Category::CONTRACT || + + if (stackTypeCategory == Type::Category::STRING && targetTypeCategory == Type::Category::INTEGER) + { + // conversion from string to hash. no need to clean the high bit + // only to shift right because of opposite alignment + IntegerType const& targetIntegerType = dynamic_cast(_targetType); + StaticStringType const& sourceStringType = dynamic_cast(_typeOnStack); + if (targetIntegerType.isHash()) + { + solAssert(targetIntegerType.getNumBits() == sourceStringType.getNumBytes() * 8, "The size should be the same."); + m_context << u256(std::pow(2, 256 - sourceStringType.getNumBytes() * 8)) << + eth::Instruction::SWAP1 << eth::Instruction::DIV; + } + } + else if (targetTypeCategory == Type::Category::STRING && stackTypeCategory == Type::Category::INTEGER) + { + // conversion from hash to string. no need to clean the high bit + // only to shift left because of opposite alignment + StaticStringType const& targetStringType = dynamic_cast(_targetType); + IntegerType const& sourceIntegerType = dynamic_cast(_typeOnStack); + if (sourceIntegerType.isHash()) + { + solAssert(sourceIntegerType.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same."); + m_context << u256(std::pow(2, 256 - sourceIntegerType.getNumBits())) << eth::Instruction::MUL; + } + } + else if (stackTypeCategory == Type::Category::INTEGER || stackTypeCategory == Type::Category::CONTRACT || stackTypeCategory == Type::Category::INTEGER_CONSTANT) { solAssert(targetTypeCategory == Type::Category::INTEGER || targetTypeCategory == Type::Category::CONTRACT, ""); @@ -657,7 +683,7 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con } else if (stackTypeCategory == Type::Category::STRING) { - solAssert(targetTypeCategory == Type::Category::STRING, ""); + solAssert(targetTypeCategory == Type::Category::STRING || targetTypeCategory == Type::Category::INTEGER, "Invalid type conversion requested."); // nothing to do, strings are high-order-bit-aligned //@todo clear lower-order bytes if we allow explicit conversion to shorter strings } diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 2446c513c..28f516218 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -140,6 +140,11 @@ bool IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const bool IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const { + if (_convertTo.getCategory() == Category::STRING) + { + StaticStringType const& convertTo = dynamic_cast(_convertTo); + return isHash() && (m_bits == convertTo.getNumBytes() * 8); + } return _convertTo.getCategory() == getCategory() || _convertTo.getCategory() == Category::CONTRACT; } @@ -367,6 +372,17 @@ bool StaticStringType::isImplicitlyConvertibleTo(Type const& _convertTo) const return convertTo.m_bytes >= m_bytes; } +bool StaticStringType::isExplicitlyConvertibleTo(Type const& _convertTo) const +{ + if (_convertTo.getCategory() == Category::INTEGER) + { + IntegerType const& convertTo = dynamic_cast(_convertTo); + if (convertTo.isHash() && (m_bytes * 8 == convertTo.getNumBits())) + return true; + } + return isImplicitlyConvertibleTo(_convertTo); +} + bool StaticStringType::operator==(Type const& _other) const { if (_other.getCategory() != getCategory()) diff --git a/libsolidity/Types.h b/libsolidity/Types.h index e6c99fe3b..e4742966f 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -233,9 +233,10 @@ public: /// if no type fits. static std::shared_ptr smallestTypeForLiteral(std::string const& _literal); - StaticStringType(int _bytes); + explicit StaticStringType(int _bytes); virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; + virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; virtual bool operator==(Type const& _other) const override; virtual unsigned getCalldataEncodedSize() const override { return m_bytes; } diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index cf04edaad..b0b450738 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -940,6 +940,72 @@ BOOST_AUTO_TEST_CASE(type_conversions_cleanup) 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22})); } +BOOST_AUTO_TEST_CASE(convert_string_to_string) +{ + char const* sourceCode = R"( + contract Test { + function pipeTrough(string3 input) returns (string3 ret) { + return string3(input); + } + })"; + compileAndRun(sourceCode); + string s = "abc"; + auto res = callContractFunction("pipeTrough(string3)", "abc"); + auto goldenRes = encodeArgs(s); + BOOST_CHECK(callContractFunction("pipeTrough(string3)", "abc") == encodeArgs("abc")); +} + +BOOST_AUTO_TEST_CASE(convert_hash_to_string_same_size) +{ + char const* sourceCode = R"( + contract Test { + function hashToString(hash h) returns (string32 s) { + return string32(h); + } + })"; + compileAndRun(sourceCode); + u256 a("0x6162630000000000000000000000000000000000000000000000000000000000"); + BOOST_CHECK(callContractFunction("hashToString(hash256)", a) == encodeArgs(a)); +} + +BOOST_AUTO_TEST_CASE(convert_hash_to_string_different_size) +{ + char const* sourceCode = R"( + contract Test { + function hashToString(hash160 h) returns (string20 s) { + return string20(h); + } + })"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("hashToString(hash160)", u160("0x00000000000000616263")) == + encodeArgs(u256("0x0000000000000000000000000000000000616263000000000000000000000000"))); +} + +BOOST_AUTO_TEST_CASE(convert_string_to_hash_same_size) +{ + char const* sourceCode = R"( + contract Test { + function stringToHash(string32 s) returns (hash h) { + return hash(s); + } + })"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("stringToHash(string32)", string("abc2")) == + encodeArgs(u256("0x6162633200000000000000000000000000000000000000000000000000000000"))); +} + +BOOST_AUTO_TEST_CASE(convert_string_to_hash_different_size) +{ + char const* sourceCode = R"( + contract Test { + function stringToHash(string20 s) returns (hash160 h) { + return hash160(s); + } + })"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("stringToHash(string20)", u256("0x0000000000000000000000000000000000616263000000000000000000000000")) == + encodeArgs(u160("0x00000000000000616263"))); +} BOOST_AUTO_TEST_CASE(send_ether) { From 20421bbfc1cdfa96f73e6e5a8956894ec91e483c Mon Sep 17 00:00:00 2001 From: liana Date: Fri, 23 Jan 2015 18:09:46 +0100 Subject: [PATCH 2/6] - corrected assert --- libsolidity/ExpressionCompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 66ca2ec14..9d282c1cb 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -683,7 +683,7 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con } else if (stackTypeCategory == Type::Category::STRING) { - solAssert(targetTypeCategory == Type::Category::STRING || targetTypeCategory == Type::Category::INTEGER, "Invalid type conversion requested."); + solAssert(targetTypeCategory == Type::Category::STRING, "Invalid type conversion requested."); // nothing to do, strings are high-order-bit-aligned //@todo clear lower-order bytes if we allow explicit conversion to shorter strings } From 54ade2fd44ffc4cc839b1ebe654fa716ccdc3978 Mon Sep 17 00:00:00 2001 From: liana Date: Mon, 26 Jan 2015 13:24:16 +0100 Subject: [PATCH 3/6] - modifications according to PR review --- libsolidity/ExpressionCompiler.cpp | 34 ++++++++++++++++-------------- test/SolidityEndToEndTest.cpp | 25 ++++++++++++++++------ 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 9d282c1cb..2c3b4078e 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -629,17 +629,25 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con Type::Category stackTypeCategory = _typeOnStack.getCategory(); Type::Category targetTypeCategory = _targetType.getCategory(); - if (stackTypeCategory == Type::Category::STRING && targetTypeCategory == Type::Category::INTEGER) + if (stackTypeCategory == Type::Category::STRING) { - // conversion from string to hash. no need to clean the high bit - // only to shift right because of opposite alignment - IntegerType const& targetIntegerType = dynamic_cast(_targetType); - StaticStringType const& sourceStringType = dynamic_cast(_typeOnStack); - if (targetIntegerType.isHash()) + if (targetTypeCategory == Type::Category::INTEGER) { - solAssert(targetIntegerType.getNumBits() == sourceStringType.getNumBytes() * 8, "The size should be the same."); - m_context << u256(std::pow(2, 256 - sourceStringType.getNumBytes() * 8)) << - eth::Instruction::SWAP1 << eth::Instruction::DIV; + // conversion from string to hash. no need to clean the high bit + // only to shift right because of opposite alignment + IntegerType const& targetIntegerType = dynamic_cast(_targetType); + StaticStringType const& sourceStringType = dynamic_cast(_typeOnStack); + if (targetIntegerType.isHash()) + { + solAssert(targetIntegerType.getNumBits() == sourceStringType.getNumBytes() * 8, "The size should be the same."); + m_context << (u256(1) << 256 - sourceStringType.getNumBytes() * 8) << + eth::Instruction::SWAP1 << eth::Instruction::DIV; + } + } + else { + solAssert(targetTypeCategory == Type::Category::STRING, "Invalid type conversion requested."); + // nothing to do, strings are high-order-bit-aligned + //@todo clear lower-order bytes if we allow explicit conversion to shorter strings } } else if (targetTypeCategory == Type::Category::STRING && stackTypeCategory == Type::Category::INTEGER) @@ -651,7 +659,7 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con if (sourceIntegerType.isHash()) { solAssert(sourceIntegerType.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same."); - m_context << u256(std::pow(2, 256 - sourceIntegerType.getNumBits())) << eth::Instruction::MUL; + m_context << (u256(1) << 256 - sourceIntegerType.getNumBits()) << eth::Instruction::MUL; } } else if (stackTypeCategory == Type::Category::INTEGER || stackTypeCategory == Type::Category::CONTRACT || @@ -681,12 +689,6 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con appendHighBitsCleanup(targetType); } } - else if (stackTypeCategory == Type::Category::STRING) - { - solAssert(targetTypeCategory == Type::Category::STRING, "Invalid type conversion requested."); - // nothing to do, strings are high-order-bit-aligned - //@todo clear lower-order bytes if we allow explicit conversion to shorter strings - } else if (_typeOnStack != _targetType) // All other types should not be convertible to non-equal types. BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid type conversion requested.")); diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index b0b450738..1d4839635 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -949,9 +949,6 @@ BOOST_AUTO_TEST_CASE(convert_string_to_string) } })"; compileAndRun(sourceCode); - string s = "abc"; - auto res = callContractFunction("pipeTrough(string3)", "abc"); - auto goldenRes = encodeArgs(s); BOOST_CHECK(callContractFunction("pipeTrough(string3)", "abc") == encodeArgs("abc")); } @@ -977,8 +974,8 @@ BOOST_AUTO_TEST_CASE(convert_hash_to_string_different_size) } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("hashToString(hash160)", u160("0x00000000000000616263")) == - encodeArgs(u256("0x0000000000000000000000000000000000616263000000000000000000000000"))); + BOOST_CHECK(callContractFunction("hashToString(hash160)", u160("0x6161626361626361626361616263616263616263")) == + encodeArgs(string("aabcabcabcaabcabcabc"))); } BOOST_AUTO_TEST_CASE(convert_string_to_hash_same_size) @@ -1003,8 +1000,22 @@ BOOST_AUTO_TEST_CASE(convert_string_to_hash_different_size) } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("stringToHash(string20)", u256("0x0000000000000000000000000000000000616263000000000000000000000000")) == - encodeArgs(u160("0x00000000000000616263"))); + BOOST_CHECK(callContractFunction("stringToHash(string20)", string("aabcabcabcaabcabcabc")) == + encodeArgs(u160("0x6161626361626361626361616263616263616263"))); +} + + +BOOST_AUTO_TEST_CASE(convert_string_to_hash_different_min_size) +{ + char const* sourceCode = R"( + contract Test { + function stringToHash(string1 s) returns (hash8 h) { + return hash8(s); + } + })"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("stringToHash(string1)", string("a")) == + encodeArgs(u128("0x00000000000000000000000000000061"))); } BOOST_AUTO_TEST_CASE(send_ether) From 5bd4a1df100e31b3cd63afb3f282f40a2142c505 Mon Sep 17 00:00:00 2001 From: liana Date: Tue, 27 Jan 2015 10:48:10 +0100 Subject: [PATCH 4/6] -added test case for hash8 to string1 conversion --- test/SolidityEndToEndTest.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 1d4839635..4f4347bff 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -1015,7 +1015,21 @@ BOOST_AUTO_TEST_CASE(convert_string_to_hash_different_min_size) })"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("stringToHash(string1)", string("a")) == - encodeArgs(u128("0x00000000000000000000000000000061"))); + encodeArgs(u256("0x61"))); +} + + +BOOST_AUTO_TEST_CASE(convert_hash_to_string_different_min_size) +{ + char const* sourceCode = R"( + contract Test { + function HashToString(hash8 h) returns (string1 s) { + return string1(h); + } + })"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("HashToString(hash8)", u256("0x61")) == + encodeArgs(string("a"))); } BOOST_AUTO_TEST_CASE(send_ether) From 16ef4eb9a7d72992632c6ba4bd01b6b5b9ddc2b5 Mon Sep 17 00:00:00 2001 From: liana Date: Tue, 27 Jan 2015 12:55:40 +0100 Subject: [PATCH 5/6] -redesigned appendTypeConversion function --- libsolidity/ExpressionCompiler.cpp | 72 +++++++++++++++--------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 2c3b4078e..630a5e911 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -636,11 +636,11 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con // conversion from string to hash. no need to clean the high bit // only to shift right because of opposite alignment IntegerType const& targetIntegerType = dynamic_cast(_targetType); - StaticStringType const& sourceStringType = dynamic_cast(_typeOnStack); + StaticStringType const& typeOnStack = dynamic_cast(_typeOnStack); if (targetIntegerType.isHash()) { - solAssert(targetIntegerType.getNumBits() == sourceStringType.getNumBytes() * 8, "The size should be the same."); - m_context << (u256(1) << 256 - sourceStringType.getNumBytes() * 8) << + solAssert(targetIntegerType.getNumBits() == typeOnStack.getNumBytes() * 8, "The size should be the same."); + m_context << (u256(1) << 256 - typeOnStack.getNumBytes() * 8) << eth::Instruction::SWAP1 << eth::Instruction::DIV; } } @@ -650,43 +650,45 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con //@todo clear lower-order bytes if we allow explicit conversion to shorter strings } } - else if (targetTypeCategory == Type::Category::STRING && stackTypeCategory == Type::Category::INTEGER) - { - // conversion from hash to string. no need to clean the high bit - // only to shift left because of opposite alignment - StaticStringType const& targetStringType = dynamic_cast(_targetType); - IntegerType const& sourceIntegerType = dynamic_cast(_typeOnStack); - if (sourceIntegerType.isHash()) - { - solAssert(sourceIntegerType.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same."); - m_context << (u256(1) << 256 - sourceIntegerType.getNumBits()) << eth::Instruction::MUL; - } - } else if (stackTypeCategory == Type::Category::INTEGER || stackTypeCategory == Type::Category::CONTRACT || stackTypeCategory == Type::Category::INTEGER_CONSTANT) { - solAssert(targetTypeCategory == Type::Category::INTEGER || targetTypeCategory == Type::Category::CONTRACT, ""); - IntegerType addressType(0, IntegerType::Modifier::ADDRESS); - IntegerType const& targetType = targetTypeCategory == Type::Category::INTEGER - ? dynamic_cast(_targetType) : addressType; - if (stackTypeCategory == Type::Category::INTEGER_CONSTANT) + if (targetTypeCategory == Type::Category::STRING && stackTypeCategory == Type::Category::INTEGER) { - IntegerConstantType const& constType = dynamic_cast(_typeOnStack); - // We know that the stack is clean, we only have to clean for a narrowing conversion - // where cleanup is forced. - if (targetType.getNumBits() < constType.getIntegerType()->getNumBits() && _cleanupNeeded) - appendHighBitsCleanup(targetType); - } - else + // conversion from hash to string. no need to clean the high bit + // only to shift left because of opposite alignment + StaticStringType const& targetStringType = dynamic_cast(_targetType); + IntegerType const& typeOnStack = dynamic_cast(_typeOnStack); + if (typeOnStack.isHash()) + { + solAssert(typeOnStack.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same."); + m_context << (u256(1) << 256 - typeOnStack.getNumBits()) << eth::Instruction::MUL; + } + } else { - IntegerType const& typeOnStack = stackTypeCategory == Type::Category::INTEGER - ? dynamic_cast(_typeOnStack) : addressType; - // Widening: clean up according to source type width - // Non-widening and force: clean up according to target type bits - if (targetType.getNumBits() > typeOnStack.getNumBits()) - appendHighBitsCleanup(typeOnStack); - else if (_cleanupNeeded) - appendHighBitsCleanup(targetType); + solAssert(targetTypeCategory == Type::Category::INTEGER || targetTypeCategory == Type::Category::CONTRACT, ""); + IntegerType addressType(0, IntegerType::Modifier::ADDRESS); + IntegerType const& targetType = targetTypeCategory == Type::Category::INTEGER + ? dynamic_cast(_targetType) : addressType; + if (stackTypeCategory == Type::Category::INTEGER_CONSTANT) + { + IntegerConstantType const& constType = dynamic_cast(_typeOnStack); + // We know that the stack is clean, we only have to clean for a narrowing conversion + // where cleanup is forced. + if (targetType.getNumBits() < constType.getIntegerType()->getNumBits() && _cleanupNeeded) + appendHighBitsCleanup(targetType); + } + else + { + IntegerType const& typeOnStack = stackTypeCategory == Type::Category::INTEGER + ? dynamic_cast(_typeOnStack) : addressType; + // Widening: clean up according to source type width + // Non-widening and force: clean up according to target type bits + if (targetType.getNumBits() > typeOnStack.getNumBits()) + appendHighBitsCleanup(typeOnStack); + else if (_cleanupNeeded) + appendHighBitsCleanup(targetType); + } } } else if (_typeOnStack != _targetType) From 1b5098cd04f18670f214730c34aaa8c823811fd1 Mon Sep 17 00:00:00 2001 From: liana Date: Tue, 27 Jan 2015 13:21:20 +0100 Subject: [PATCH 6/6] - cosmetic changes --- libsolidity/ExpressionCompiler.cpp | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 630a5e911..bd8c86531 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -637,14 +637,12 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con // only to shift right because of opposite alignment IntegerType const& targetIntegerType = dynamic_cast(_targetType); StaticStringType const& typeOnStack = dynamic_cast(_typeOnStack); - if (targetIntegerType.isHash()) - { - solAssert(targetIntegerType.getNumBits() == typeOnStack.getNumBytes() * 8, "The size should be the same."); - m_context << (u256(1) << 256 - typeOnStack.getNumBytes() * 8) << - eth::Instruction::SWAP1 << eth::Instruction::DIV; - } + solAssert(targetIntegerType.isHash(), "Only conversion between String and Hash is allowed."); + solAssert(targetIntegerType.getNumBits() == typeOnStack.getNumBytes() * 8, "The size should be the same."); + m_context << (u256(1) << (256 - typeOnStack.getNumBytes() * 8)) << eth::Instruction::SWAP1 << eth::Instruction::DIV; } - else { + else + { solAssert(targetTypeCategory == Type::Category::STRING, "Invalid type conversion requested."); // nothing to do, strings are high-order-bit-aligned //@todo clear lower-order bytes if we allow explicit conversion to shorter strings @@ -659,17 +657,16 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con // only to shift left because of opposite alignment StaticStringType const& targetStringType = dynamic_cast(_targetType); IntegerType const& typeOnStack = dynamic_cast(_typeOnStack); - if (typeOnStack.isHash()) - { - solAssert(typeOnStack.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same."); - m_context << (u256(1) << 256 - typeOnStack.getNumBits()) << eth::Instruction::MUL; - } - } else + solAssert(typeOnStack.isHash(), "Only conversion between String and Hash is allowed."); + solAssert(typeOnStack.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same."); + m_context << (u256(1) << (256 - typeOnStack.getNumBits())) << eth::Instruction::MUL; + } + else { solAssert(targetTypeCategory == Type::Category::INTEGER || targetTypeCategory == Type::Category::CONTRACT, ""); IntegerType addressType(0, IntegerType::Modifier::ADDRESS); IntegerType const& targetType = targetTypeCategory == Type::Category::INTEGER - ? dynamic_cast(_targetType) : addressType; + ? dynamic_cast(_targetType) : addressType; if (stackTypeCategory == Type::Category::INTEGER_CONSTANT) { IntegerConstantType const& constType = dynamic_cast(_typeOnStack); @@ -681,7 +678,7 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con else { IntegerType const& typeOnStack = stackTypeCategory == Type::Category::INTEGER - ? dynamic_cast(_typeOnStack) : addressType; + ? dynamic_cast(_typeOnStack) : addressType; // Widening: clean up according to source type width // Non-widening and force: clean up according to target type bits if (targetType.getNumBits() > typeOnStack.getNumBits())